X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI.pm;h=a823f220cbac95ee25e9603ce2cd7df0fff4a3a1;hb=227d836679dd2e91b1cf49c3d9e566be79f49297;hp=74003163c2de0ac7ae9cf063638431d6785f9cb6;hpb=c2ecf953198fc6c43edae1b39de4cc86debcb11b;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index 7400316..a823f22 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -18,7 +18,8 @@ use Sub::Name (); __PACKAGE__->mk_group_accessors('simple' => qw/_connect_info _dbi_connect_info _dbh _sql_maker _sql_maker_opts _conn_pid - _conn_tid transaction_depth _dbh_autocommit _driver_determined savepoints/ + _conn_tid transaction_depth _dbh_autocommit _driver_determined savepoints + __server_info/ ); # the values for these accessors are picked out (and deleted) from @@ -33,7 +34,10 @@ __PACKAGE__->mk_group_accessors('simple' => @storage_options); # default cursor class, overridable in connect_info attributes __PACKAGE__->cursor_class('DBIx::Class::Storage::DBI::Cursor'); -__PACKAGE__->mk_group_accessors('inherited' => qw/sql_maker_class/); +__PACKAGE__->mk_group_accessors('inherited' => qw/ + sql_maker_class + _supports_insert_returning +/); __PACKAGE__->sql_maker_class('DBIx::Class::SQLAHacks'); @@ -89,7 +93,7 @@ DBIx::Class::Storage::DBI - DBI storage handler ); $schema->resultset('Book')->search({ - written_on => $schema->storage->datetime_parser(DateTime->now) + written_on => $schema->storage->datetime_parser->format_datetime(DateTime->now) }); =head1 DESCRIPTION @@ -742,6 +746,7 @@ sub disconnect { $self->_dbh_rollback unless $self->_dbh_autocommit; + %{ $self->_dbh->{CachedKids} } = (); $self->_dbh->disconnect; $self->_dbh(undef); $self->{_dbh_gen}++; @@ -849,7 +854,7 @@ sub ensure_connected { Returns a C<$dbh> - a data base handle of class L. The returned handle is guaranteed to be healthy by implicitly calling L, and if necessary performing a reconnection before returning. Keep in mind that this -is very B on some database engines. Consider using L +is very B on some database engines. Consider using L instead. =cut @@ -915,6 +920,8 @@ sub _populate_dbh { $self->{transaction_depth} = $self->_dbh_autocommit ? 0 : 1; $self->_run_connection_actions unless $self->{_in_determine_driver}; + + $self->_populate_server_info; } sub _run_connection_actions { @@ -927,6 +934,37 @@ sub _run_connection_actions { $self->_do_connection_actions(connect_call_ => $_) for @actions; } +sub _populate_server_info { + my $self = shift; + my %info; + + my $dbms_ver = eval { + local $@; + $self->_get_dbh->get_info(18) + }; + + if (defined $dbms_ver) { + $info{dbms_ver} = $dbms_ver; + + ($dbms_ver) = $dbms_ver =~ /^(\S+)/; + + my @verparts = split /\./, $dbms_ver; + $info{dbms_ver_normalized} = sprintf "%d.%03d%03d", @verparts; + } + + $self->__server_info(\%info); + + return \%info; +} + +sub _server_info { + my $self = shift; + + $self->_get_dbh; + + return $self->__server_info(@_); +} + sub _determine_driver { my ($self) = @_; @@ -1362,29 +1400,56 @@ sub _execute { $self->dbh_do('_dbh_execute', @_); # retry over disconnects } -sub insert { +sub _prefetch_insert_auto_nextvals { my ($self, $source, $to_insert) = @_; - my $ident = $source->from; - my $bind_attributes = $self->source_bind_attributes($source); - - my $updated_cols = {}; + my $upd = {}; foreach my $col ( $source->columns ) { if ( !defined $to_insert->{$col} ) { my $col_info = $source->column_info($col); if ( $col_info->{auto_nextval} ) { - $updated_cols->{$col} = $to_insert->{$col} = $self->_sequence_fetch( + $upd->{$col} = $to_insert->{$col} = $self->_sequence_fetch( 'nextval', - $col_info->{sequence} || - $self->_dbh_get_autoinc_seq($self->_get_dbh, $source) + $col_info->{sequence} ||= + $self->_dbh_get_autoinc_seq($self->_get_dbh, $source, $col) ); } } } - $self->_execute('insert' => [], $source, $bind_attributes, $to_insert); + return $upd; +} + +sub insert { + my $self = shift; + my ($source, $to_insert, $opts) = @_; + + my $updated_cols = $self->_prefetch_insert_auto_nextvals (@_); + + my $bind_attributes = $self->source_bind_attributes($source); + + my ($rv, $sth) = $self->_execute('insert' => [], $source, $bind_attributes, $to_insert, $opts); + + if ($opts->{returning}) { + my @ret_cols = @{$opts->{returning}}; + + my @ret_vals = eval { + local $SIG{__WARN__} = sub {}; + my @r = $sth->fetchrow_array; + $sth->finish; + @r; + }; + + my %ret; + @ret{@ret_cols} = @ret_vals if (@ret_vals); + + $updated_cols = { + %$updated_cols, + %ret, + }; + } return $updated_cols; } @@ -1471,7 +1536,7 @@ sub insert_bulk { # neither _execute_array, nor _execute_inserts_with_no_binds are # atomic (even if _execute _array is a single call). Thus a safety # scope guard - my $guard = $self->txn_scope_guard unless $self->{transaction_depth} != 0; + my $guard = $self->txn_scope_guard; $self->_query_start( $sql, ['__BULK__'] ); my $sth = $self->sth($sql); @@ -1488,8 +1553,7 @@ sub insert_bulk { $self->_query_end( $sql, ['__BULK__'] ); - - $guard->commit if $guard; + $guard->commit; return (wantarray ? ($rv, $sth, @bind) : $rv); } @@ -1518,7 +1582,11 @@ sub _execute_array { my @data = map { $_->[$data_index] } @$data; - $sth->bind_param_array( $placeholder_index, [@data], $attributes ); + $sth->bind_param_array( + $placeholder_index, + [@data], + (%$attributes ? $attributes : ()), + ); $placeholder_index++; }