BingoX
view release on metacpan or search on metacpan
lib/BingoX/Carbon.pm view on Meta::CPAN
if (%tmpparams) { # %tmpparams remaining are parameters not in $order list
unshift @$order, '(';
push @$order, (')', 'AND', split (' ', join(' AND ', keys %tmpparams)));
}
} else { # order list empty!
$order = [ split (' ', join(' AND ', keys %$params)) ];
}
} elsif (ref $params eq 'HASH') {
$order = [ split (' ', join(' AND ', keys %$params)) ];
} else { # make sure we have params
return undef;
}
## parse each field and add to SQL statement ##
my ($WHERE, @query, @bindings);
foreach my $field (@$order) {
if (($field eq 'AND') || ($field eq 'OR') || ($field eq '(') || $field eq ')') {
next if (($field =~ /^(?:AND|OR)$/o) && (!@query || ($query[$#query] =~ /^(?:AND|OR)$/o)));
next if (($field =~ /^(?:\(|\))$/o) && ($query[$#query] =~ /^(?:\(|\))$/o));
push @query, $field;
next;
}
## make sure field is in params ##
unless (defined $class->deffields->{$field}) {
pop @query;
next;
}
## enforce precedence ##
my $sql = '('; # ) loathe BBEdit
my @valuelist = $params->{$field};
next unless (defined $valuelist[0]);
## add relation prefix if $r_flag ##
$field = "${alias}.${field}" if $alias;
for (my $x = 0; $x <= $#valuelist; $x++) {
my $value = $valuelist[$x];
if (ref($value) eq 'ARRAY') { # IN, BETWEEN, or multiple comparisons
my ( $type, @values ) = @{ $value };
if (substr(lc($type), -2) eq 'in') { # 'IN' or 'NOT IN'
return $self->error_handler("no bindings passed to format_conditions for type ($type)")
unless (@values);
my (@IN_bindings, @IN_sql);
while (my $value = shift(@values)) {
if (lc(substr($value, 0, 6)) eq 'select') {
push (@IN_sql, $value);
push (@IN_bindings, splice(@values, 0, $#values + 1)); # $/
} else {
push (@IN_sql, '?');
push (@IN_bindings, $value);
}
}
$sql .= "$field " . uc($type) . ' (' . join(', ', @IN_sql) . ')';
push(@bindings, @IN_bindings);
} elsif (substr(lc($type), -7) eq 'between') { # 'BETWEEN' or 'NOT BETWEEN'
return $self->error_handler("no bindings passed to format_conditions for type ($type)")
unless (@values);
$sql .= "$field " . uc($type) . ' ? AND ?';
push(@bindings, @values[0,1]);
} else { # LIST of conditions
splice (@valuelist, $x+1, 0, @$value); # appending will push to next iterations
}
} elsif ($value =~ /^\/(.+?)\/$/) { # regex
$sql .= "$field ~ ?";
push(@bindings, $1);
} elsif ($value =~ /^(\d+?)-(\d+?)$/) { # date or numeric range
$sql .= "($field > ? AND $field < ?)";
push(@bindings, $1, $2);
} elsif ($value eq '&&') { # AND
$sql .= ' AND ';
} elsif ($value eq '||') { # OR
$sql .= ' OR ';
# BEGIN BBEdit loathing
} elsif ($value eq '(') # Open paren ) loathe BBedit
{ # loathe BBedit here, too!
$sql .= '('; # ) loathe BBedit
} # loathe BBedit here, too! # ( loathe BBedit
elsif ($value eq ')') { # Close paren ( loathe BBedit
$sql .= ')'; # END BBEdit loathing
} elsif (lc($value) =~ /^(?:like|not|is)\s|<|>/) { # Allow LIKE,NOT,IS,<,>,<=,>= blindly
if ($value =~ /##/) {
while ($value =~ s/##(.+?)##/?/o) {
push(@bindings, $1);
}
}
$sql .= "$field $value"; # can use with embeded SELECT
### Why do we need this code? Uncomment if you change the else!
# } elsif ($value =~ /^-?(?:\d+?)\.?(?:\d*?)$/) { # exact match number
# $sql .= "$field = ?";
# push(@bindings, $value);
###
} else { # exact match lexical
$sql .= "$field = ?";
push(@bindings, $value);
}
} # END for (multiple values loop)
## enforce precedence ( ##
$sql .= ')';
## add to array to be joined later ##
push(@query, $sql) if ($sql ne '()');
} # END foreach (fields loop)
$WHERE = 'WHERE ' . join(' ', @query) if (@query);
warn "$class->format_conditions:\t\"$WHERE\" [@bindings]\n" if ($debug);
return ($WHERE, @bindings);
} # END sub format_conditions
=head2 AUTOLOAD
=over 4
=item AUTOLOAD
AUTOLOAD method - returns requested field data from object.
If that requested data has not been cached, it is retrieved from the
database, cached, and returned. If data is passed then field value is
modified in the database and instance data, and value is returned.
( run in 0.623 second using v1.01-cache-2.11-cpan-71847e10f99 )