summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Cooper <J.L.Cooper@lboro.ac.uk>2020-09-17 15:30:10 +0100
committerJason Cooper <J.L.Cooper@lboro.ac.uk>2020-09-17 15:30:10 +0100
commit17d40d073057917794629b8cea934c1ea9198bb0 (patch)
tree5dbf00b20a2deadd779c1724fc740ccb4069ca03
parentea3e7426d986f7d43206e8c2989e74910b444783 (diff)
Added support to result set callbacks to specify the `last_insert_id`
-rw-r--r--Changes1
-rw-r--r--README.md23
-rw-r--r--lib/DBD/Mock.pm24
-rw-r--r--lib/DBD/Mock/StatementTrack.pm4
-rw-r--r--lib/DBD/Mock/st.pm5
-rw-r--r--t/016_mock_add_resultset_test.t51
6 files changed, 107 insertions, 1 deletions
diff --git a/Changes b/Changes
index 7d71d3a..33a6899 100644
--- a/Changes
+++ b/Changes
@@ -2,6 +2,7 @@ Revision history for Perl extension DBD::Mock.
{{$NEXT}}
- The DBD::st module now supports the last_insert_id method
+ - Result sets with callbacks can now specify a last_insert_id
1.55 2019-12-30T14:20:00Z
- Fixed bug rt131264 t/033_table_info.t fails (with older DBI)
diff --git a/README.md b/README.md
index 15acad7..d393816 100644
--- a/README.md
+++ b/README.md
@@ -1202,6 +1202,29 @@ great caution (if at all).
property to be undef in this situation then set the
`$DBD::Mock::DefaultFieldsToUndef` flag to `1`.
+ If you're mocking an INSERT statement with a callback and you want to
+ explicitly set the database's `last_insert_id` value then you can use the
+ `last_insert_id` key in the result set. If you don't specify a
+ `last_insert_id` then the standard `DBD::Mock` logic for generating an value
+ for the last inserted item will be followed. This will allow you to mock
+ MySQL/MariaDB INSERT queries that use `ON DUPLICATE KEY UPDATE` logic to set
+ the `last_insert_id`.
+
+ $dbh->{mock_add_resultset} = {
+ sql => 'INSERT INTO y ( x ) VALUES ( ? ) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID( id )',
+ callback => sub {
+ my @bound_params = @_;
+
+ my %result = (
+ fields => [],
+ rows => [],
+ last_insert_id => 99,
+ );
+
+ return %result;
+ },
+ };
+
# BUGS
- Odd `$dbh` attribute behavior
diff --git a/lib/DBD/Mock.pm b/lib/DBD/Mock.pm
index 3402c1e..91ae8f4 100644
--- a/lib/DBD/Mock.pm
+++ b/lib/DBD/Mock.pm
@@ -1398,6 +1398,30 @@ stays compatible with previous versions. If you need the C<NUM_OF_FIELDS>
property to be undef in this situation then set the
C<$DBD::Mock::DefaultFieldsToUndef> flag to C<1>.
+If you're mocking an INSERT statement with a callback and you want to
+explicitly set the database's C<last_insert_id> value then you can use the
+C<last_insert_id> key in the result set. If you don't specify a
+C<last_insert_id> then the standard C<DBD::Mock> logic for generating an value
+for the last inserted item will be followed. This will allow you to mock
+MySQL/MariaDB INSERT queries that use C<ON DUPLICATE KEY UPDATE> logic to set
+the C<last_insert_id>.
+
+
+ $dbh->{mock_add_resultset} = {
+ sql => 'INSERT INTO y ( x ) VALUES ( ? ) ON DUPLICATE KEY UPDATE id = LAST_INSERT_ID( id )',
+ callback => sub {
+ my @bound_params = @_;
+
+ my %result = (
+ fields => [],
+ rows => [],
+ last_insert_id => 99,
+ );
+
+ return %result;
+ },
+ };
+
=back
diff --git a/lib/DBD/Mock/StatementTrack.pm b/lib/DBD/Mock/StatementTrack.pm
index 31dedda..60fae31 100644
--- a/lib/DBD/Mock/StatementTrack.pm
+++ b/lib/DBD/Mock/StatementTrack.pm
@@ -141,6 +141,10 @@ sub mark_executed {
if (ref $recordSet{rows} eq "ARRAY") {
$self->{return_data} = $recordSet{rows};
}
+
+ if (defined $recordSet{last_insert_id}) {
+ $self->{last_insert_id} = $recordSet{last_insert_id};
+ }
}
}
diff --git a/lib/DBD/Mock/st.pm b/lib/DBD/Mock/st.pm
index bb2b20a..44229d3 100644
--- a/lib/DBD/Mock/st.pm
+++ b/lib/DBD/Mock/st.pm
@@ -131,7 +131,10 @@ sub execute {
#use Data::Dumper;warn Dumper $dbh->{mock_last_insert_ids};
if ( $dbh->{Statement} =~ /^\s*?insert(?:\s+ignore)?\s+into\s+(\S+)/i ) {
- if ( $dbh->{mock_last_insert_ids}
+ if ( $tracker->{last_insert_id} ) {
+ $dbh->{mock_last_insert_id} = $tracker->{last_insert_id};
+
+ } elsif ( $dbh->{mock_last_insert_ids}
&& exists $dbh->{mock_last_insert_ids}{$1} )
{
$dbh->{mock_last_insert_id} = $dbh->{mock_last_insert_ids}{$1}++;
diff --git a/t/016_mock_add_resultset_test.t b/t/016_mock_add_resultset_test.t
index 6743a82..9ddf98a 100644
--- a/t/016_mock_add_resultset_test.t
+++ b/t/016_mock_add_resultset_test.t
@@ -317,4 +317,55 @@ $dbh->{mock_add_resultset} = {
$sth->finish();
}
+$dbh->{mock_start_insert_id} = [ 'y', 4 ];
+
+$dbh->{mock_add_resultset} = {
+ sql => 'INSERT INTO y ( x ) VALUES ( ? )',
+ callback => sub {
+ my @bound_params = @_;
+
+ my %result = (
+ fields => [],
+ rows => []
+ );
+
+ return %result;
+ },
+};
+
+{
+ my $sth = $dbh->prepare( 'INSERT INTO y ( x ) VALUES ( ? )' );
+
+ $sth->execute( 'test' );
+
+ is( $dbh->last_insert_id(), 4, "last_insert_id should return the next Id value after an insert as our callback doesn't override it")
+}
+
+
+$dbh->{mock_add_resultset} = {
+ sql => 'INSERT INTO y ( x ) VALUES ( ? )',
+ callback => sub {
+ my @bound_params = @_;
+
+ my %result = (
+ fields => [],
+ rows => [],
+ last_insert_id => 99,
+ );
+
+ return %result;
+ },
+};
+
+{
+ my $sth = $dbh->prepare( 'INSERT INTO y ( x ) VALUES ( ? )' );
+
+ $sth->execute( 'test' );
+
+ is( $dbh->last_insert_id(), 99, "last_insert_id should return the id the callback has provided");
+
+ is( $dbh->{mock_last_insert_ids}{y}, 5, "If we provide a last_insert_id value then the one stored against the table shouldn't be updated");
+}
+
+
done_testing();