From: Rob Kinyon Date: Mon, 14 Mar 2011 03:20:24 +0000 (-0400) Subject: First cut. Need to add control of how many rows are sent at once. X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=64b39761640eb1055d8b5833566613efe941b177;p=dbsrgits%2FDBIx-Class.git First cut. Need to add control of how many rows are sent at once. --- diff --git a/Changes b/Changes index 1306d67..f44d793 100644 --- a/Changes +++ b/Changes @@ -7,6 +7,9 @@ Revision history for DBIx::Class - Both the ::ODBC and ::ADO dispatchers now warn if a rdbms-specific driver is not found for this connection before falling back to plain ::Storage::DBI + - populate() in void context now uses the multi-row INSERT + statement in MySQL. It will send 500 rows at one time. You can + change this behavior by setting ???? * Fixes - Fix exiting via next warnings from ResultSource diff --git a/lib/DBIx/Class/SQLMaker/MySQL.pm b/lib/DBIx/Class/SQLMaker/MySQL.pm index ccb1195..7d86993 100644 --- a/lib/DBIx/Class/SQLMaker/MySQL.pm +++ b/lib/DBIx/Class/SQLMaker/MySQL.pm @@ -21,6 +21,30 @@ sub insert { return $self->SUPER::insert (@_); } +sub insert_bulk { + my ($self, $table, $data, $cols) = @_; + + my $sql = sprintf( + 'INSERT INTO %s ( ', $self->_quote($table), + ); + $sql .= join( ', ', map { $self->_quote($_) } @$cols ); + $sql .= ' ) VALUES '; + + my @bind; + my @sql; + foreach my $datum ( @$data ) { + push @sql, '(' + . join( ', ', ('?') x @$datum ) + . ')'; + push @bind, map { [ dummy => $_ ] } @$datum; + } + + return ( + $sql . join(',', @sql), + @bind + ); +} + # Allow STRAIGHT_JOIN's sub _generate_join_clause { my ($self, $join_type) = @_; diff --git a/lib/DBIx/Class/Storage/DBI.pm b/lib/DBIx/Class/Storage/DBI.pm index 2dc005c..b3cead4 100644 --- a/lib/DBIx/Class/Storage/DBI.pm +++ b/lib/DBIx/Class/Storage/DBI.pm @@ -1830,8 +1830,17 @@ sub insert_bulk { } } + return $self->_insert_bulk( + $source, $cols, \%colvalues, $data, + ); +} + +# Broken out so that it can be overridden in Storage/DBI/mysql.pm +sub _insert_bulk { + my ($self, $source, $cols, $colvalues, $data) = @_; + my ($sql, $bind) = $self->_prep_for_execute ( - 'insert', undef, $source, [\%colvalues] + 'insert', undef, $source, [$colvalues] ); if (! @$bind) { @@ -1841,7 +1850,7 @@ sub insert_bulk { # directly into the SQL. This obviosly can't be good for multi-inserts $self->throw_exception('Cannot insert_bulk without support for placeholders') - if first { ref $_ ne 'SCALAR' } values %colvalues; + if first { ref $_ ne 'SCALAR' } values %$colvalues; } # neither _execute_array, nor _execute_inserts_with_no_binds are diff --git a/lib/DBIx/Class/Storage/DBI/mysql.pm b/lib/DBIx/Class/Storage/DBI/mysql.pm index fcf9fbf..0f4d210 100644 --- a/lib/DBIx/Class/Storage/DBI/mysql.pm +++ b/lib/DBIx/Class/Storage/DBI/mysql.pm @@ -121,6 +121,16 @@ sub _subq_update_delete { return shift->_per_row_update_delete (@_); } +sub _insert_bulk { + my ($self, $source, $cols, $colvalues, $data) = @_; + + my $bind_attrs = $self->source_bind_attributes($source); + + return $self->_execute( + 'insert_bulk' => [], $source, $bind_attrs, $data, $cols, + ); +} + 1; =head1 NAME diff --git a/t/71mysql.t b/t/71mysql.t index 84bebc7..1f45311 100644 --- a/t/71mysql.t +++ b/t/71mysql.t @@ -411,4 +411,32 @@ ZEROINSEARCH: { ok ($rs->find({ name => "Hardcore Forker $pid" }), 'Expected row created'); } +# Verify that populate in void context uses INSERT INTO foo VALUES (), (), () +# instead of 3 distinct SQL statements as other databases may require. +{ + my $rsrc = $schema->resultset('Artist')->result_source; + my ($rv, $sth, @bind) = $schema->storage->insert_bulk( + $rsrc, + [qw/ artistid name rank charfield /], + [ + [ 100, 'John', 200, 'Smith' ], + [ 101, 'Joan', 201, 'Snith' ], + ], + ); + + is_same_sql_bind( + $sth->{Statement}, + \@bind, + q{INSERT INTO artist ( artistid, name, rank, charfield ) VALUES ( ?, ?, ?, ? ), ( ?, ?, ?, ? )}, + [ + map { [ dummy => $_ ] } ( + 100, 'John', 200, 'Smith', + 101, 'Joan', 201, 'Snith', + ), + ], + ); + + is( $schema->resultset('Artist')->find( 100 )->name, 'John' ); +} + done_testing;