=item * Support of C<...FOR UPDATE> type of select statement modifiers
-=item * The -ident operator
+=item * The L</-ident> operator
-=item * The -value operator
+=item * The L</-value> operator
=back
}
# the "oh noes offset/top without limit" constant
-# limited to 32 bits for sanity (and consistency,
-# since it is ultimately handed to sprintf %u)
+# limited to 31 bits for sanity (and consistency,
+# since it may be handed to the like of sprintf %u)
+#
+# Also *some* builds of SQLite fail the test
+# some_column BETWEEN ? AND ?: 1, 4294967295
+# with the proper integer bind attrs
+#
# Implemented as a method, since ::Storage::DBI also
# refers to it (i.e. for the case of software_limit or
# as the value to abuse with MSSQL ordered subqueries)
-sub __max_int { 0xFFFFFFFF };
+sub __max_int () { 0x7FFFFFFF };
+
+# poor man's de-qualifier
+sub _quote {
+ $_[0]->next::method( ( $_[0]{_dequalify_idents} and ! ref $_[1] )
+ ? $_[1] =~ / ([^\.]+) $ /x
+ : $_[1]
+ );
+}
sub new {
my $self = shift->next::method(@_);
}
;
- $sql = $self->$limiter ($sql, $rs_attrs, $limit, $offset);
+ $sql = $self->$limiter (
+ $sql,
+ { %{$rs_attrs||{}}, _selector_sql => $fields },
+ $limit,
+ $offset
+ );
}
else {
($sql, @bind) = $self->next::method ($table, $fields, $where, $rs_attrs);
sub _assemble_binds {
my $self = shift;
- return map { @{ (delete $self->{"${_}_bind"}) || [] } } (qw/select from where group having order/);
+ return map { @{ (delete $self->{"${_}_bind"}) || [] } } (qw/pre_select select from where group having order limit/);
}
my $for_syntax = {
sub _from_chunk_to_sql {
my ($self, $fromspec) = @_;
- return join (' ', $self->_SWITCH_refkind($fromspec, {
- SCALARREF => sub {
+ return join (' ', do {
+ if (! ref $fromspec) {
+ $self->_quote($fromspec);
+ }
+ elsif (ref $fromspec eq 'SCALAR') {
$$fromspec;
- },
- ARRAYREFREF => sub {
+ }
+ elsif (ref $fromspec eq 'REF' and ref $$fromspec eq 'ARRAY') {
push @{$self->{from_bind}}, @{$$fromspec}[1..$#$$fromspec];
$$fromspec->[0];
- },
- HASHREF => sub {
+ }
+ elsif (ref $fromspec eq 'HASH') {
my ($as, $table, $toomuch) = ( map
{ $_ => $fromspec->{$_} }
( grep { $_ !~ /^\-/ } keys %$fromspec )
if defined $toomuch;
($self->_from_chunk_to_sql($table), $self->_quote($as) );
- },
- SCALAR => sub {
- $self->_quote($fromspec);
- },
- }));
+ }
+ else {
+ $self->throw_exception('Unsupported from refkind: ' . ref $fromspec );
+ }
+ });
}
sub _join_condition {
1;
+=head1 OPERATORS
+
+=head2 -ident
+
+Used to explicitly specify an SQL identifier. Takes a plain string as value
+which is then invariably treated as a column name (and is being properly
+quoted if quoting has been requested). Most useful for comparison of two
+columns:
+
+ my %where = (
+ priority => { '<', 2 },
+ requestor => { -ident => 'submitter' }
+ );
+
+which results in:
+
+ $stmt = 'WHERE "priority" < ? AND "requestor" = "submitter"';
+ @bind = ('2');
+
+=head2 -value
+
+The -value operator signals that the argument to the right is a raw bind value.
+It will be passed straight to DBI, without invoking any of the SQL::Abstract
+condition-parsing logic. This allows you to, for example, pass an array as a
+column value for databases that support array datatypes, e.g.:
+
+ my %where = (
+ array => { -value => [1, 2, 3] }
+ );
+
+which results in:
+
+ $stmt = 'WHERE array = ?';
+ @bind = ([1, 2, 3]);
+
=head1 AUTHORS
See L<DBIx::Class/CONTRIBUTORS>.