diff --git a/go/vt/vttablet/endtoend/main_test.go b/go/vt/vttablet/endtoend/main_test.go index 3eb1d5b9a13..c963486907d 100644 --- a/go/vt/vttablet/endtoend/main_test.go +++ b/go/vt/vttablet/endtoend/main_test.go @@ -118,6 +118,14 @@ insert into vitess_b(eid, id) values(1, 1), (1, 2); insert into vitess_c(eid, name, foo) values(10, 'abcd', '20'), (11, 'bcde', '30'); create table vitess_mixed_case(Col1 int default 0, COL2 int default null, primary key(col1)); +CREATE TABLE vitess_autoinc_seq ( + id bigint(20) unsigned NOT NULL AUTO_INCREMENT, + name varchar(255) NOT NULL, + sequence bigint(20) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (id), + UNIQUE KEY name (name) +); + create table vitess_big(id int default 0, string1 varchar(128) default null, string2 varchar(100) default null, string3 char(1) default null, string4 varchar(50) default null, string5 varchar(50) default null, string6 varchar(16) default null, string7 varchar(120) default null, bigint1 bigint(20) default null, bigint2 bigint(20) default null, integer1 int default null, tinyint1 tinyint(4) default null, primary key(id)); create table vitess_ints(tiny tinyint default 0, tinyu tinyint unsigned default null, small smallint default null, smallu smallint unsigned default null, medium mediumint default null, mediumu mediumint unsigned default null, normal int default null, normalu int unsigned default null, big bigint default null, bigu bigint unsigned default null, y year default null, primary key(tiny)); @@ -170,7 +178,7 @@ var tableACLConfig = `{ }, { "name": "vitess", - "table_names_or_prefixes": ["vitess_a", "vitess_b", "vitess_c", "dual", "vitess_d", "vitess_temp", "vitess_e", "vitess_f", "vitess_mixed_case", "upsert_test", "vitess_strings", "vitess_fracts", "vitess_ints", "vitess_misc", "vitess_big", "vitess_view", "vitess_json", "vitess_bool"], + "table_names_or_prefixes": ["vitess_a", "vitess_b", "vitess_c", "dual", "vitess_d", "vitess_temp", "vitess_e", "vitess_f", "vitess_mixed_case", "upsert_test", "vitess_strings", "vitess_fracts", "vitess_ints", "vitess_misc", "vitess_big", "vitess_view", "vitess_json", "vitess_bool", "vitess_autoinc_seq"], "readers": ["dev"], "writers": ["dev"], "admins": ["dev"] diff --git a/go/vt/vttablet/endtoend/misc_test.go b/go/vt/vttablet/endtoend/misc_test.go index d04f7cc2022..1544c2965bd 100644 --- a/go/vt/vttablet/endtoend/misc_test.go +++ b/go/vt/vttablet/endtoend/misc_test.go @@ -647,6 +647,46 @@ func TestClientFoundRows(t *testing.T) { } } +func TestLastInsertId(t *testing.T) { + client := framework.NewClient() + res, err := client.Execute("insert ignore into vitess_autoinc_seq SET name = 'foo', sequence = 0", nil) + if err != nil { + t.Fatal(err) + } + defer client.Execute("delete from vitess_autoinc_seq where name = 'foo'", nil) + + if err := client.Begin(true); err != nil { + t.Fatal(err) + } + defer client.Rollback() + + res, err = client.Execute("insert ignore into vitess_autoinc_seq SET name = 'foo', sequence = 0", nil) + if err != nil { + t.Fatal(err) + } + + qr, err := client.Execute("update vitess_autoinc_seq set sequence=last_insert_id(sequence + 1) where name='foo'", nil) + if err != nil { + t.Error(err) + } + + insID := res.InsertID + + if want, got := insID+1, qr.InsertID; want != got { + t.Errorf("insertId mismatch; got %v, want %v", got, want) + } + + qr, err = client.Execute("select sequence from vitess_autoinc_seq where name = 'foo'", nil) + if err != nil { + t.Error(err) + } + + wantCol := sqltypes.NewUint64(insID + uint64(1)) + if !reflect.DeepEqual(qr.Rows[0][0], wantCol) { + t.Errorf("Execute: \n%#v, want \n%#v", qr.Rows[0][0], wantCol) + } +} + func TestAppDebugRequest(t *testing.T) { client := framework.NewClient() diff --git a/go/vt/vttablet/tabletserver/query_executor.go b/go/vt/vttablet/tabletserver/query_executor.go index b61dc4078b7..6ad07f2dc70 100644 --- a/go/vt/vttablet/tabletserver/query_executor.go +++ b/go/vt/vttablet/tabletserver/query_executor.go @@ -678,7 +678,12 @@ func (qre *QueryExecutor) execDMLPKRows(conn *TxConnection, query *sqlparser.Par if err != nil { return nil, err } - // DMLs should only return RowsAffected. + + // UPDATEs can return InsertID when LAST_INSERT_ID(expr) is used. In + // this case it should be the same for all rows. + result.InsertID = r.InsertID + + // DMLs should all return RowsAffected. result.RowsAffected += r.RowsAffected } if qre.plan.Table.Type == schema.Message {