use DBIx::Class::_Util 'fail_on_internal_wantarray';
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 ();
$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
my $subrs = (ref $self)->new($rsrc, $attrs);
if (@$idcols == 1) {
- $cond = { $idcols->[0] => { -in => $subrs->as_query } };
+ $cond = { $idcols->[0] => { -in => \$subrs->_as_select_dq } };
}
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 {
$aq;
}
+sub _as_select_dq {
+ my $self = shift;
+ my $attrs = { %{ $self->_resolved_attrs } };
+ my $storage = $self->result_source->storage;
+ my (undef, $ident, @args) = $storage->_select_args(
+ $attrs->{from}, $attrs->{select}, $attrs->{where}, $attrs
+ );
+ $ident = $ident->from if blessed($ident);
+ $storage->sql_maker->converter->_select_to_dq(
+ $ident, @args
+ );
+}
+
=head2 find_or_new
=over 4