CGI-OptimalQuery
view release on metacpan or search on metacpan
lib/DBIx/OptimalQuery.pm view on Meta::CPAN
die "could not parse sort\n";
}
}
my @deps = grep { $_ } keys %deps;
return { sql => \@sql, binds => \@binds, deps => \@deps, name => \@name };
}
# normalize member variables
sub _normalize {
my $oq = shift;
#$$oq{error_handler}->("DEBUG: \$oq->_normalize()\n") if $$oq{debug};
$oq->{'AutoSetLongReadLen'} = 1 unless exists $oq->{'AutoSetLongReadLen'};
# make sure all option hash refs exist
$oq->{'select'}->{$_}->[3] ||= {} for keys %{ $oq->{'select'} };
$oq->{'joins' }->{$_}->[3] ||= {} for keys %{ $oq->{'joins'} };
# since the sql & deps definitions can optionally be entered as arrays
# turn all into arrays if not already
for ( # key, index
['select', 0], ['select', 1],
['joins', 0], ['joins', 1], ['joins', 2],
['named_filters', 0], ['named_filters', 1],
['named_sorts', 0], ['named_sorts', 1] ) {
my ($key, $i) = @$_;
$oq->{$key} ||= {};
foreach my $alias (keys %{ $oq->{$key} }) {
if (ref($oq->{$key}->{$alias}) eq 'ARRAY' &&
defined $oq->{$key}->{$alias}->[$i] &&
ref($oq->{$key}->{$alias}->[$i]) ne 'ARRAY') {
$oq->{$key}->{$alias}->[$i] = [$oq->{$key}->{$alias}->[$i]];
}
}
}
# make sure the following select options, if they exist are array references
foreach my $col (keys %{ $oq->{'select'} }) {
my $opts = $oq->{'select'}->{$col}->[3];
foreach my $opt (qw( select_sql sort_sql filter_sql )) {
$opts->{$opt} = [$opts->{$opt}]
if exists $opts->{$opt} && ref($opts->{$opt}) ne 'ARRAY';
}
# make sure defined deps exist
foreach my $dep (@{ $$oq{'select'}{$col}[0] }) {
die "dep $dep for select $col does not exist"
if defined $dep && ! exists $$oq{'joins'}{$dep};
}
}
# look for new cursors and define parent child links if not already defined
foreach my $join (keys %{ $oq->{'joins'} }) {
my $opts = $oq->{'joins'}->{$join}->[3];
if (exists $opts->{new_cursor}) {
if (ref($opts->{new_cursor}) ne 'HASH') {
$oq->_formulate_new_cursor($join);
} else {
die "could not find keys, join, and sql for new cursor in $join"
unless exists $opts->{new_cursor}->{'keys'} &&
exists $opts->{new_cursor}->{'join'} &&
exists $opts->{new_cursor}->{'sql'};
}
}
# make sure defined deps exist
foreach my $dep (@{ $$oq{'joins'}{$join}[0] }) {
die "dep $dep for join $join does not exist"
if defined $dep && ! exists $$oq{'joins'}{$dep};
}
}
# make sure deps for named_sorts exist
foreach my $named_sort (keys %{ $$oq{'named_sorts'} }) {
foreach my $dep (@{ $$oq{'named_sorts'}{$named_sort}->[0] }) {
die "dep $dep for named_sort $named_sort does not exist"
if defined $dep && ! exists $$oq{'joins'}{$dep};
}
}
# make sure deps for named_filter exist
foreach my $named_filter (keys %{ $$oq{'named_filters'} }) {
if (ref($$oq{'named_filters'}{$named_filter}) eq 'ARRAY') {
foreach my $dep (@{ $$oq{'named_filters'}{$named_filter}->[0] }) {
die "dep $dep for named_sort $named_filter does not exist"
if defined $dep && ! exists $$oq{'joins'}{$dep};
}
}
}
$oq->{'col_types'} = undef;
return undef;
}
# defines how a child cursor joins to its parent cursor
# by defining keys, join, sql in child cursor
# called from the _normalize method
sub _formulate_new_cursor {
my $oq = shift;
my $joinAlias = shift;
#$$oq{error_handler}->("DEBUG: \$oq->_formulate_new_cursor('$joinAlias')\n") if $$oq{debug};
# vars to define
my (@keys, $join, $sql, @sqlBinds);
# get join definition
my ($fromSql, @fromBinds) = @{ $oq->{joins}->{$joinAlias}->[1] };
my ($whereSql, @whereBinds);
($whereSql, @whereBinds) = @{ $oq->{joins}->{$joinAlias}->[2] }
if defined $oq->{joins}->{$joinAlias}->[2];
# if NOT an SQL-92 type join
if (defined $whereSql) {
$whereSql =~ s/\(\+\)/\ /g; # remove outer join notation
die "BAD_PARAMS - where binds not allowed in 'new_cursor' joins"
if scalar(@whereBinds);
}
# else is SQL-92 so separate out joins from table definition
# do this by making it a pre SQL-92 type join
# by defining $whereSql
# and removing join sql from $fromSql
else {
$_ = $fromSql;
m/\G\s*left\b/sicg;
m/\G\s*join\b/sicg;
# parse inline view
if (m/\G\s*\(/scg) {
$fromSql = '(';
my $p=1;
my $q;
while ($p > 0 && m/\G(.)/scg) {
my $c = $1;
if ($q) { $q = '' if $c eq $q; } # if end of quote
elsif ($c eq "'" || $c eq '"') { $q = $c; } # if start of quote
elsif ($c eq '(') { $p++; } # if left paren
elsif ($c eq ')') { $p--; } # if right paren
$fromSql .= $c;
}
}
# parse table name
elsif (m/\G\s*(\w+)\b/scg) {
$fromSql = $1;
}
else {
die "could not parse tablename";
}
# include alias if it exists
if (m/\G\s*([\d\w\_]+)\s*/scg && lc($1) ne 'on') {
$fromSql .= ' '.$1;
m/\G\s*on\b/cgi;
}
# get the whereSql
if (m/\G\s*\((.*)\)\s*$/cgs) {
$whereSql = $1;
( run in 1.608 second using v1.01-cache-2.11-cpan-df04353d9ac )