op => '_expand_op',
func => '_expand_func',
values => '_expand_values',
+ list => '_expand_list',
},
expand_op => {
(map +($_ => __PACKAGE__->make_binop_expander('_expand_between')),
}
sub _expand_insert_clause_target {
- +(target => $_[0]->expand_maybe_list_expr($_[2], -ident));
+ +(target => $_[0]->expand_expr($_[2], -ident));
}
sub _expand_insert_clause_fields {
return +{ -row => [
- $_[0]->expand_maybe_list_expr($_[2], -ident)
+ $_[0]->expand_expr({ -list => $_[2] }, -ident)
] } if ref($_[2]) eq 'ARRAY';
return $_[2]; # should maybe still expand somewhat?
}
}
sub _expand_insert_clause_returning {
- +(returning => $_[0]->expand_maybe_list_expr($_[2], -ident));
+ +(returning => $_[0]->expand_expr({ -list => $_[2] }, -ident));
}
sub _expand_insert_values {
my $f = $options->{returning};
my ($sql, @bind) = @{ $self->render_aqt(
- $self->expand_maybe_list_expr($f, -ident)
+ $self->expand_expr({ -list => $f }, -ident)
) };
return ($self->_sqlcase(' returning ').$sql, @bind);
}
sub _expand_update_set_values {
my ($self, undef, $data) = @_;
- $self->expand_maybe_list_expr( [
+ $self->expand_expr({ -list => [
map {
my ($k, $set) = @$_;
$set = { -bind => $_ } unless defined $set;
}
);
} sort keys %$data
- ] );
+ ] });
}
sub _expand_update_clause_target {
my ($self, undef, $target) = @_;
- +(target => $self->expand_maybe_list_expr($target, -ident));
+ +(target => $self->expand_expr({ -list => $target }, -ident));
}
sub _expand_update_clause_set {
}
sub _expand_update_clause_returning {
- +(returning => $_[0]->expand_maybe_list_expr($_[2], -ident));
+ +(returning => $_[0]->expand_expr({ -list => $_[2] }, -ident));
}
# So that subclasses can override UPDATE ... RETURNING separately from
sub _expand_select_clause_select {
my ($self, undef, $select) = @_;
- +(select => $self->expand_maybe_list_expr($select, -ident));
+ +(select => $self->expand_expr({ -list => $select }, -ident));
}
sub _expand_select_clause_from {
my ($self, undef, $from) = @_;
- +(from => $self->expand_maybe_list_expr($from, -ident));
+ +(from => $self->expand_expr({ -list => $from }, -ident));
}
sub _expand_select_clause_where {
my ($self, $fields) = @_;
return $fields unless ref($fields);
return @{ $self->render_aqt(
- $self->expand_maybe_list_expr($fields, '-ident')
+ $self->expand_expr({ -list => $fields }, '-ident')
) };
}
sub _delete_returning { shift->_returning(@_) }
sub _expand_delete_clause_target {
- +(target => $_[0]->expand_maybe_list_expr($_[2], -ident));
+ +(target => $_[0]->expand_expr({ -list => $_[2] }, -ident));
}
sub _expand_delete_clause_where { +(where => $_[0]->expand_expr($_[2])); }
sub _expand_delete_clause_returning {
- +(returning => $_[0]->expand_maybe_list_expr($_[2], -ident));
+ +(returning => $_[0]->expand_expr({ -list => $_[2] }, -ident));
}
sub _render_delete_clause_target {
return $self->_expand_expr({ -ident => $v });
}
+sub _expand_list {
+ my ($self, undef, $expr) = @_;
+ return { -op => [
+ ',', map $self->expand_expr($_),
+ @{$expr->{-op}}[1..$#{$expr->{-op}}]
+ ] } if ref($expr) eq 'HASH' and ($expr->{-op}||[''])->[0] eq ',';
+ return +{ -op => [ ',',
+ map $self->expand_expr($_),
+ ref($expr) eq 'ARRAY' ? @$expr : $expr
+ ] };
+}
+
sub _expand_op_andor {
my ($self, $logop, $v, $k) = @_;
if (defined $k) {
return unless defined($arg) and not (ref($arg) eq 'ARRAY' and !@$arg);
- return $self->expand_maybe_list_expr($arg)
+ return $self->expand_expr({ -list => $arg })
if ref($arg) eq 'HASH' and ($arg->{-op}||[''])->[0] eq ',';
my $expander = sub {
my $self = shift;
my $from = shift;
$self->render_aqt(
- $self->expand_maybe_list_expr($from, -ident)
+ $self->expand_expr({ -list => $from }, -ident)
)->[0];
}
# UTILITY FUNCTIONS
#======================================================================
-sub expand_maybe_list_expr {
- my ($self, $expr, $default) = @_;
- return { -op => [
- ',', map $self->expand_expr($_, $default),
- @{$expr->{-op}}[1..$#{$expr->{-op}}]
- ] } if ref($expr) eq 'HASH' and ($expr->{-op}||[''])->[0] eq ',';
- return +{ -op => [ ',',
- map $self->expand_expr($_, $default),
- ref($expr) eq 'ARRAY' ? @$expr : $expr
- ] };
-}
-
# highly optimized, as it's called way too often
sub _quote {
# my ($self, $label) = @_;
my $aqt = $self->expand_expr($expr);
my $aqt = $self->expand_expr($expr, -ident);
-=head2 expand_maybe_list_expr
-
-expand_expr but with commas if there's more than one entry.
-
- my $aqt = $self->expand_maybe_list_expr([ @exprs ], $default?);
-
=head2 render_aqt
Top level means avoid parens on statement AQT.
VALUES (?, ?), (?, ?)
[ 1, 2, 3, 4 ]
+=head2 list
+
+Expects a value or an arrayref of values, expands them, and returns just
+the expanded aqt for a single entry or a comma operator for multiple:
+
+ # expr
+ { -list => [ { -ident => 'foo' } ] }
+
+ # aqt
+ { -op => [ ',', { -ident => [ 'foo' ] } ] }
+
+ # query
+ foo
+ []
+
+ # expr
+ { -list => [ { -ident => 'foo' }, { -ident => 'bar' } ] }
+
+ # aqt
+ { -op => [ ',', { -ident => [ 'foo' ] }, { -ident => [ 'bar' ] } ] }
+
+ # query
+ foo, bar
+ []
+
=head2 between op
The RHS of between must either be a pair of exprs/plain values, or a single
{ -bind => [ 'baz', 'argh' ] },
] } ] },
returning => { -op => [ ',', { -ident => [ 'id' ] } ] },
- target => { -op => [ ',', { -ident => [ 'foo' ] } ] },
+ target => { -ident => [ 'foo' ] },
} }
# query
[ ',', { -ident => [ 'bar' ] }, { -ident => [ 'baz' ] } ]
} ] },
from => { -select => {
- from => { -from_list => [ { -ident => [ 'other' ] } ] },
+ from => { -ident => [ 'other' ] },
select => { -op =>
[ ',', { -ident => [ 'bar' ] }, { -ident => [ 'baz' ] } ]
},
} },
- target => { -op => [ ',', { -ident => [ 'foo' ] } ] },
+ target => { -ident => [ 'foo' ] },
} }
# query
] },
] },
] },
- target => { -from_list => [ { -ident => [ 'foo' ] } ] },
+ target => { -ident => [ 'foo' ] },
where => { -op => [ 'not', { -ident => [ 'quux' ] } ] },
} }