# GLOBALS
#======================================================================
-our $VERSION = '1.84';
+our $VERSION = '1.85';
# This would confuse some packagers
$VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
sub insert {
my $self = shift;
- my $table = $self->_table(shift);
+ my ($table_sql, @all_bind) = $self->_table(shift);
my $data = shift || return;
my $options = shift;
my $method = $self->_METHOD_FOR_refkind("_insert", $data);
- my ($sql, @bind) = $self->$method($data);
- $sql = join " ", $self->_sqlcase('insert into'), $table, $sql;
+ my ($values_sql, @values_bind) = $self->$method($data);
+ my $sql = join " ", $self->_sqlcase('insert into'), $table_sql, $values_sql;
+ push @all_bind, @values_bind;
if ($options->{returning}) {
- my ($s, @b) = $self->_insert_returning($options);
- $sql .= $s;
- push @bind, @b;
+ my ($returning_sql, @returning_bind) = $self->_insert_returning($options);
+ $sql .= $returning_sql;
+ push @all_bind, @returning_bind;
}
- return wantarray ? ($sql, @bind) : $sql;
+ return wantarray ? ($sql, @all_bind) : $sql;
}
# So that subclasses can override INSERT ... RETURNING separately from
sub update {
my $self = shift;
- my $table = $self->_table(shift);
+ my ($table_sql, @all_bind) = $self->_table(shift);
my $data = shift || return;
my $where = shift;
my $options = shift;
# first build the 'SET' part of the sql statement
- my (@set, @all_bind);
puke "Unsupported data type specified to \$sql->update"
unless ref $data eq 'HASH';
+ my ($values_sql, @values_bind) = $self->_update_set_values($data);
+ my $sql = $self->_sqlcase('update ') . $table_sql . $self->_sqlcase(' set ')
+ . $values_sql;
+ push @all_bind, @values_bind;
+
+ if ($where) {
+ my($where_sql, @where_bind) = $self->where($where);
+ $sql .= $where_sql;
+ push @all_bind, @where_bind;
+ }
+
+ if ($options->{returning}) {
+ my ($returning_sql, @returning_bind) = $self->_update_returning($options);
+ $sql .= $returning_sql;
+ push @all_bind, @returning_bind;
+ }
+
+ return wantarray ? ($sql, @all_bind) : $sql;
+}
+
+sub _update_set_values {
+ my ($self, $data) = @_;
+
+ my (@set, @all_bind);
for my $k (sort keys %$data) {
my $v = $data->{$k};
my $r = ref $v;
}
# generate sql
- my $sql = $self->_sqlcase('update') . " $table " . $self->_sqlcase('set ')
- . join ', ', @set;
-
- if ($where) {
- my($where_sql, @where_bind) = $self->where($where);
- $sql .= $where_sql;
- push @all_bind, @where_bind;
- }
-
- if ($options->{returning}) {
- my ($returning_sql, @returning_bind) = $self->_update_returning($options);
- $sql .= $returning_sql;
- push @all_bind, @returning_bind;
- }
+ my $sql = join ', ', @set;
- return wantarray ? ($sql, @all_bind) : $sql;
+ return ($sql, @all_bind);
}
# So that subclasses can override UPDATE ... RETURNING separately from
sub select {
my $self = shift;
- my $table = $self->_table(shift);
+ my ($table_sql, @table_bind) = $self->_table(shift);
my $fields = shift || '*';
my $where = shift;
my $order = shift;
- my($where_sql, @bind) = $self->where($where, $order);
+ my($where_sql, @where_bind) = $self->where($where, $order);
my $f = (ref $fields eq 'ARRAY') ? join ', ', map { $self->_quote($_) } @$fields
: $fields;
my $sql = join(' ', $self->_sqlcase('select'), $f,
- $self->_sqlcase('from'), $table)
+ $self->_sqlcase('from'), $table_sql)
. $where_sql;
- return wantarray ? ($sql, @bind) : $sql;
+ return wantarray ? ($sql, @table_bind, @where_bind) : $sql;
}
#======================================================================
sub delete {
my $self = shift;
- my $table = $self->_table(shift);
+ my ($table_sql, @all_bind) = $self->_table(shift);
my $where = shift;
my $options = shift;
- my($where_sql, @bind) = $self->where($where);
- my $sql = $self->_sqlcase('delete from') . " $table" . $where_sql;
+ my($where_sql, @where_bind) = $self->where($where);
+ my $sql = $self->_sqlcase('delete from ') . $table_sql . $where_sql;
+ push @all_bind, @where_bind;
if ($options->{returning}) {
my ($returning_sql, @returning_bind) = $self->_delete_returning($options);
$sql .= $returning_sql;
- push @bind, @returning_bind;
+ push @all_bind, @returning_bind;
}
- return wantarray ? ($sql, @bind) : $sql;
+ return wantarray ? ($sql, @all_bind) : $sql;
}
# So that subclasses can override DELETE ... RETURNING separately from
my $from = shift;
$self->_SWITCH_refkind($from, {
ARRAYREF => sub {join ', ', map { $self->_quote($_) } @$from;},
+ ARRAYREFREF => sub {
+ my ($sql, @bind) = @$$from;
+ $self->_assert_bindval_matches_bindtype(@bind);
+ return ($sql, @bind);
+ },
SCALAR => sub {$self->_quote($from)},
SCALARREF => sub {$$from},
});
character itself.
When opening-closing-style quoting is used (L</quote_char> is an arrayref)
-this parameter defaults to the B<closing (right)> L</quote_char>. Occurences
+this parameter defaults to the B<closing (right)> L</quote_char>. Occurrences
of the B<opening (left)> L</quote_char> within the identifier are currently left
untouched. The default for opening-closing-style quotes may change in future
versions, thus you are B<strongly encouraged> to specify the escape character
The argument can be either a plain scalar (interpreted as a table
name, will be quoted), or an arrayref (interpreted as a list
of table names, joined by commas, quoted), or a scalarref
-(literal table name, not quoted), or a ref to an arrayref
-(list of literal table names, joined by commas, not quoted).
+(literal SQL, not quoted), or a reference to an arrayref
+(literal SQL and bind values).
=item $fields
=back
-On failure returns C<undef>, on sucess returns a B<scalar> reference
+On failure returns C<undef>, on success returns a B<scalar> reference
to the original supplied argument.
=over
=back
-On failure returns C<undef>, on sucess returns an B<array> reference
+On failure returns C<undef>, on success returns an B<array> reference
containing the unpacked version of the supplied literal SQL and bind values.
=head1 WHERE CLAUSES