From 0e0f7a0423a88363ea5263ffeadde1bbb7ba2820 Mon Sep 17 00:00:00 2001 From: "kroki/tomash@moonlight.intranet" <> Date: Fri, 27 Oct 2006 13:32:41 +0400 Subject: [PATCH] BUG#22584: last_insert_id not updated after inserting a record through a updatable view. When there's a VIEW on a base table that have AUTO_INCREMENT column, and this VIEW doesn't provide an access such column, after INSERT to such VIEW LAST_INSERT_ID() did not return the value just generated. This behaviour is intended and correct, because if the VIEW doesn't list some columns then these columns are effectively hidden from the user, and so any side effects of inserting default values to them. However, there was a bug that such statement inserting into a view would reset LAST_INSERT_ID() instead of leaving it unchanged. This patch restores the original value of LAST_INSERT_ID() instead of resetting it to zero. --- mysql-test/r/view.result | 34 ++++++++++++++++++++++++++++++++++ mysql-test/t/view.test | 38 ++++++++++++++++++++++++++++++++++++++ sql/sql_parse.cc | 19 +++++++++++++++++-- 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 13921dc88d7..198233adf71 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2970,4 +2970,38 @@ UPDATE t1 SET i= f1(); DROP FUNCTION f1; DROP VIEW v1; DROP TABLE t1; +DROP VIEW IF EXISTS v1, v2; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT); +CREATE VIEW v1 AS SELECT j FROM t1; +CREATE VIEW v2 AS SELECT * FROM t1; +INSERT INTO t1 (j) VALUES (1); +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +1 +INSERT INTO v1 (j) VALUES (2); +# LAST_INSERT_ID() should not change. +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +1 +INSERT INTO v2 (j) VALUES (3); +# LAST_INSERT_ID() should be updated. +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +3 +INSERT INTO v1 (j) SELECT j FROM t1; +# LAST_INSERT_ID() should not change. +SELECT LAST_INSERT_ID(); +LAST_INSERT_ID() +3 +SELECT * FROM t1; +i j +1 1 +2 2 +3 3 +4 1 +5 2 +6 3 +DROP VIEW v1, v2; +DROP TABLE t1; End of 5.0 tests. diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index d3dcd857e62..401bda27bb4 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2908,4 +2908,42 @@ DROP VIEW v1; DROP TABLE t1; +# +# BUG#22584: last_insert_id not updated after inserting a record +# through a updatable view +# +# We still do not update LAST_INSERT_ID if AUTO_INCREMENT column is +# not accessible through a view. However, we do not reset the value +# of LAST_INSERT_ID, but keep it unchanged. +# +--disable_warnings +DROP VIEW IF EXISTS v1, v2; +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1 (i INT AUTO_INCREMENT PRIMARY KEY, j INT); +CREATE VIEW v1 AS SELECT j FROM t1; +CREATE VIEW v2 AS SELECT * FROM t1; + +INSERT INTO t1 (j) VALUES (1); +SELECT LAST_INSERT_ID(); + +INSERT INTO v1 (j) VALUES (2); +--echo # LAST_INSERT_ID() should not change. +SELECT LAST_INSERT_ID(); + +INSERT INTO v2 (j) VALUES (3); +--echo # LAST_INSERT_ID() should be updated. +SELECT LAST_INSERT_ID(); + +INSERT INTO v1 (j) SELECT j FROM t1; +--echo # LAST_INSERT_ID() should not change. +SELECT LAST_INSERT_ID(); + +SELECT * FROM t1; + +DROP VIEW v1, v2; +DROP TABLE t1; + + --echo End of 5.0 tests. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7b5387e5e2f..d2cbd5b0008 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3369,8 +3369,16 @@ end_with_restore_list: res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, lex->update_list, lex->value_list, lex->duplicates, lex->ignore); + + /* + If we have inserted into a VIEW, and the base table has + AUTO_INCREMENT column, but this column is not accessible through + a view, then we should restore LAST_INSERT_ID to the value it + had before the statement. + */ if (first_table->view && !first_table->contain_auto_increment) - thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it + thd->last_insert_id= thd->current_insert_id; + break; } case SQLCOM_REPLACE_SELECT: @@ -3431,8 +3439,15 @@ end_with_restore_list: select_lex->table_list.first= (byte*) first_table; } + /* + If we have inserted into a VIEW, and the base table has + AUTO_INCREMENT column, but this column is not accessible through + a view, then we should restore LAST_INSERT_ID to the value it + had before the statement. + */ if (first_table->view && !first_table->contain_auto_increment) - thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it + thd->last_insert_id= thd->current_insert_id; + break; } case SQLCOM_TRUNCATE: