use Scalar::Util qw/blessed weaken reftype/;
use Try::Tiny;
use Data::Compare (); # no imports!!! guard against insane architecture
-
+use Data::Query::Constants;
+use Data::Query::ExprHelpers;
# not importing first() as it will clash with our own method
use List::Util ();
=head3 Resolving conditions and attributes
-When a resultset is chained from another resultset (ie:
-C<my $new_rs = $old_rs->search(\%extra_cond, \%attrs)>), conditions
+When a resultset is chained from another resultset (e.g.:
+C<< my $new_rs = $old_rs->search(\%extra_cond, \%attrs) >>), conditions
and attributes with the same keys need resolving.
If any of L</columns>, L</select>, L</as> are present, they reset the
: 'classic_nonpruning'
;
- # $args and $attrs to _mk_row_parser are seperated to delineate what is
+ # $args and $attrs to _mk_row_parser are separated to delineate what is
# core collapser stuff and what is dbic $rs specific
@{$self->{_row_parser}{$parser_type}}{qw(cref nullcheck)} = $rsrc->_mk_row_parser({
eval => 1,
# can't work without it). Add an explicit check for the *main*
# result, hopefully this will gradually weed out such errors
#
- # FIXME - this is a temporary kludge that reduces perfromance
+ # FIXME - this is a temporary kludge that reduces performance
# It is however necessary for the time being
my ($unrolled_non_null_cols_to_check, $err);
$sql_maker->{name_sep} = '';
}
+ $sql_maker->clear_renderer;
+ $sql_maker->clear_converter;
+
my ($lquote, $rquote, $sep) = map { quotemeta $_ } ($sql_maker->_quote_chars, $sql_maker->name_sep);
- my $having_sql = $sql_maker->_parse_rs_attrs ({ having => $attrs->{having} });
+ my $having_sql = $sql_maker->_render_sqla(where => $attrs->{having});
+
+ $sql_maker->clear_renderer;
+ $sql_maker->clear_converter;
+
my %seen_having;
# search for both a proper quoted qualified string, for a naive unquoted scalarref
# and if all fails for an utterly naive quoted scalar-with-function
while ($having_sql =~ /
- $rquote $sep $lquote (.+?) $rquote
+ (?: $rquote $sep)? $lquote (.+?) $rquote
|
[\s,] \w+ \. (\w+) [\s,]
|
if (! $needs_subq) {
# Most databases do not allow aliasing of tables in UPDATE/DELETE. Thus
# a condition containing 'me' or other table prefixes will not work
- # at all. Tell SQLMaker to dequalify idents via a gross hack.
- $cond = do {
- my $sqla = $rsrc->storage->sql_maker;
- local $sqla->{_dequalify_idents} = 1;
- \[ $sqla->_recurse_where($self->{cond}) ];
- };
+ # at all - so we convert the WHERE to a dq tree now, dequalify all
+ # identifiers found therein via a scan across the tree, and then use
+ # \{} style to pass the result onwards for use in the final query
+ if ($self->{cond}) {
+ $cond = do {
+ my $converter = $rsrc->storage->sql_maker->converter;
+ scan_dq_nodes({
+ DQ_IDENTIFIER ,=> sub { $_ = [ $_->[-1] ] for $_[0]->{elements} }
+ }, my $where_dq = $converter->_where_to_dq($self->{cond}));
+ \$where_dq;
+ };
+ }
}
else {
# we got this far - means it is time to wrap a subquery
elsif ($storage->_use_multicolumn_in) {
# no syntax for calling this properly yet
# !!! EXPERIMENTAL API !!! WILL CHANGE !!!
- $cond = $storage->sql_maker->_where_op_multicolumn_in (
- $idcols, # how do I convey a list of idents...? can binds reside on lhs?
- $subrs->as_query
+ my $left = $storage->sql_maker->_render_sqla(select_select => $idcols);
+ $left =~ s/^SELECT //i;
+ my $right = $storage->sql_maker
+ ->converter
+ ->_literal_to_dq(${$subrs->as_query});
+ $cond = \Operator(
+ { 'SQL.Naive' => 'in' },
+ [ Literal(SQL => "( $left )"), $right ],
),
}
else {
element should be a data value in the earlier specified column order.
For example:
- $Arstist_rs->populate([
+ $schema->resultset("Artist")->populate([
[ qw( artistid name ) ],
[ 100, 'A Formally Unknown Singer' ],
[ 101, 'A singer that jumped the shark two albums ago' ],
}
-# populate() argumnets went over several incarnations
+# populate() arguments went over several incarnations
# What we ultimately support is AoH
sub _normalize_populate_args {
my ($self, $arg) = @_;
);
}
else {
- # precendence must be given to passed values over values inherited from
+ # precedence must be given to passed values over values inherited from
# the cond, so the order here is important.
my $collapsed_cond = $self->_collapse_cond($self->{cond});
my %implied = %{$self->_remove_alias($collapsed_cond, $alias)};
# determines if the resultset defines at least one
# of the attributes supplied
#
-# used to determine if a subquery is neccessary
+# used to determine if a subquery is necessary
#
# supports some virtual attributes:
# -join
}
# run through the resulting joinstructure (starting from our current slot)
- # and unset collapse if proven unnesessary
+ # and unset collapse if proven unnecessary
#
# also while we are at it find out if the current root source has
# been premultiplied by previous related_source chaining
If an L</order_by> is already declared, and orders the resultset in a way that
makes collapsing as described above impossible (e.g. C<< ORDER BY
has_many_rel.column >> or C<ORDER BY RANDOM()>), DBIC will automatically
-switch to "eager" mode and slurp the entire resultset before consturcting the
+switch to "eager" mode and slurp the entire resultset before constructing the
first object returned by L</next>.
Setting this attribute on a resultset that does not join any has_many
=item dbic_colname
Used to fill in missing sqlt_datatype and sqlt_size attributes (if they are
-explicitly specified they are never overriden). Also used by some weird DBDs,
+explicitly specified they are never overridden). Also used by some weird DBDs,
where the column name should be available at bind_param time (e.g. Oracle).
=back