X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI.pm;h=c276f38ca3fe8701b51b7d6c975d494c8c2aa06c;hb=9901aad73ff9dc45b426534fe406c102fb9fb77c;hp=a337f51bf287c3a307ff89d0b3082b89f3aa21d5;hpb=c9225efc0cbce68b35a84ca35ca05114768825e0;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index a337f51..c276f38 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -171,6 +171,13 @@ sub _recurse_fields { .'( '.$self->_recurse_fields($fields->{$func}).' )'; } } + # Is the second check absolutely necessary? + elsif ( $ref eq 'REF' and ref($$fields) eq 'ARRAY' ) { + return $self->_bind_to_sql( $fields ); + } + else { + Carp::croak($ref . qq{ unexpected in _recurse_fields()}) + } } sub _order_by { @@ -259,10 +266,20 @@ sub _recurse_from { return join('', @sqlf); } +sub _bind_to_sql { + my $self = shift; + my $arr = shift; + my $sql = shift @$$arr; + $sql =~ s/\?/$self->_quote((shift @$$arr)->[1])/eg; + return $sql +} + sub _make_as { my ($self, $from) = @_; - return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ : $self->_quote($_)) } - reverse each %{$self->_skip_options($from)}); + return join(' ', map { (ref $_ eq 'SCALAR' ? $$_ + : ref $_ eq 'REF' ? $self->_bind_to_sql($_) + : $self->_quote($_)) + } reverse each %{$self->_skip_options($from)}); } sub _skip_options { @@ -1173,11 +1190,15 @@ sub txn_rollback { sub _prep_for_execute { my ($self, $op, $extra_bind, $ident, $args) = @_; + if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) { + $ident = $ident->from(); + } + my ($sql, @bind) = $self->sql_maker->$op($ident, @$args); + unshift(@bind, map { ref $_ eq 'ARRAY' ? $_ : [ '!!dummy', $_ ] } @$extra_bind) if $extra_bind; - return ($sql, \@bind); } @@ -1218,10 +1239,6 @@ sub _query_end { sub _dbh_execute { my ($self, $dbh, $op, $extra_bind, $ident, $bind_attributes, @args) = @_; - - if( blessed($ident) && $ident->isa("DBIx::Class::ResultSource") ) { - $ident = $ident->from(); - } my ($sql, $bind) = $self->_prep_for_execute($op, $extra_bind, $ident, \@args); @@ -1269,20 +1286,22 @@ sub insert { my $ident = $source->from; my $bind_attributes = $self->source_bind_attributes($source); + my $updated_cols = {}; + $self->ensure_connected; foreach my $col ( $source->columns ) { if ( !defined $to_insert->{$col} ) { my $col_info = $source->column_info($col); if ( $col_info->{auto_nextval} ) { - $to_insert->{$col} = $self->_sequence_fetch( 'nextval', $col_info->{sequence} || $self->_dbh_get_autoinc_seq($self->dbh, $source) ); + $updated_cols->{$col} = $to_insert->{$col} = $self->_sequence_fetch( 'nextval', $col_info->{sequence} || $self->_dbh_get_autoinc_seq($self->dbh, $source) ); } } } $self->_execute('insert' => [], $source, $bind_attributes, $to_insert); - return $to_insert; + return $updated_cols; } ## Still not quite perfect, and EXPERIMENTAL @@ -1357,20 +1376,19 @@ sub delete { } sub _select { + my $self = shift; + my $sql_maker = $self->sql_maker; + local $sql_maker->{for}; + return $self->_execute($self->_select_args(@_)); +} + +sub _select_args { my ($self, $ident, $select, $condition, $attrs) = @_; my $order = $attrs->{order_by}; - if (ref $condition eq 'SCALAR') { - my $unwrap = ${$condition}; - if ($unwrap =~ s/ORDER BY (.*)$//i) { - $order = $1; - $condition = \$unwrap; - } - } - my $for = delete $attrs->{for}; my $sql_maker = $self->sql_maker; - local $sql_maker->{for} = $for; + $sql_maker->{for} = $for; if (exists $attrs->{group_by} || $attrs->{having}) { $order = { @@ -1392,8 +1410,7 @@ sub _select { $attrs->{rows} = 2**48 if not defined $attrs->{rows} and defined $attrs->{offset}; push @args, $attrs->{rows}, $attrs->{offset}; } - - return $self->_execute(@args); + return @args; } sub source_bind_attributes { @@ -1542,9 +1559,18 @@ Return the row id of the last insert. =cut sub _dbh_last_insert_id { - my ($self, $dbh, $source, $col) = @_; - # XXX This is a SQLite-ism as a default... is there a DBI-generic way? - $dbh->func('last_insert_rowid'); + # All Storage's need to register their own _dbh_last_insert_id + # the old SQLite-based method was highly inappropriate + + my $self = shift; + my $class = ref $self; + $self->throw_exception (<reset(); - $sqlt = $self->configure_sqlt($sqlt, $db); $sqlt->{schema} = $sqlt_schema; $sqlt->producer($db); @@ -1673,7 +1698,6 @@ sub create_ddl_dir { $t->debug( 0 ); $t->trace( 0 ); $t->parser( $db ) or die $t->error; - $t = $self->configure_sqlt($t, $db); my $out = $t->translate( $prefilename ) or die $t->error; $source_schema = $t->schema; unless ( $source_schema->name ) { @@ -1691,7 +1715,6 @@ sub create_ddl_dir { $t->debug( 0 ); $t->trace( 0 ); $t->parser( $db ) or die $t->error; - $t = $self->configure_sqlt($t, $db); my $out = $t->translate( $filename ) or die $t->error; $dest_schema = $t->schema; $dest_schema->name( $filename ) @@ -1711,17 +1734,6 @@ sub create_ddl_dir { } } -sub configure_sqlt() { - my $self = shift; - my $tr = shift; - my $db = shift || $self->sqlt_type; - if ($db eq 'PostgreSQL') { - $tr->quote_table_names(0); - $tr->quote_field_names(0); - } - return $tr; -} - =head2 deployment_statements =over 4 @@ -1752,7 +1764,7 @@ sub deployment_statements { $type ||= $self->sqlt_type; $version ||= $schema->schema_version || '1.x'; $dir ||= './'; - my $filename = $schema->ddl_filename($type, $dir, $version); + my $filename = $schema->ddl_filename($type, $version, $dir); if(-f $filename) { my $file;