summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2019-10-17 14:08:33 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2019-10-17 17:32:14 +0200
commitde2186dd2f5937a56d799f55c33078a7ad8ebddc (patch)
tree7b44a00f8fb8dcbea6145a0ae2fecf0cc764ac72
parent6cdde9ebbf59254a81f04961818577ffd203f9d6 (diff)
downloadmariadb-git-de2186dd2f5937a56d799f55c33078a7ad8ebddc.tar.gz
MDEV-20074: Lost connection on update trigger
Instead of checking lex->sql_command which does not corect in case of triggers mark tables for insert.
-rw-r--r--mysql-test/suite/sql_sequence/other.result91
-rw-r--r--mysql-test/suite/sql_sequence/other.test136
-rw-r--r--sql/sp_head.cc6
-rw-r--r--sql/sql_base.cc27
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc15
-rw-r--r--sql/sql_view.cc13
-rw-r--r--sql/sql_yacc.yy13
-rw-r--r--sql/sql_yacc_ora.yy13
-rw-r--r--sql/table.h6
10 files changed, 305 insertions, 17 deletions
diff --git a/mysql-test/suite/sql_sequence/other.result b/mysql-test/suite/sql_sequence/other.result
index ff58e35772b..abc101b3c00 100644
--- a/mysql-test/suite/sql_sequence/other.result
+++ b/mysql-test/suite/sql_sequence/other.result
@@ -209,4 +209,95 @@ delete s,t1 from t1,s;
ERROR HY000: Storage engine SEQUENCE of the table `test`.`s` doesn't have this option
DROP SEQUENCE s;
DROP TABLE t1;
+#
+# MDEV-20074: Lost connection on update trigger
+#
+# INSERT & table
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+INSERT INTO t2(a_p_name, a_p_first_name) VALUES(old.p_name, old.p_first_name);
+END;
+$$
+update t1 set p_first_name='Yunxi' where p_id=1;
+drop sequence s1;
+drop table t1,t2;
+# INSERT & view
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+create view v2 as select * from t2;
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+INSERT INTO v2(a_p_name, a_p_first_name) VALUES(old.p_name, old.p_first_name);
+END;
+$$
+update t1 set p_first_name='Yunxi' where p_id=1;
+drop view v2;
+drop table t1,t2;
+drop sequence s1;
+# INSERT SELECT & view
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+create view v2 as select * from t2;
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+INSERT INTO v2(a_p_name, a_p_first_name) SELECT old.p_name, old.p_first_name;
+END;
+$$
+update t1 set p_first_name='Yunxi' where p_id=1;
+drop view v2;
+drop table t1,t2;
+drop sequence s1;
+# REPLACE & view
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+create view v2 as select * from t2;
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+REPLACE INTO v2(a_p_name, a_p_first_name) VALUES(old.p_name, old.p_first_name);
+END;
+$$
+update t1 set p_first_name='Yunxi' where p_id=1;
+drop view v2;
+drop table t1,t2;
+drop sequence s1;
+# REPLACE SELECT & view
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+create view v2 as select * from t2;
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+REPLACE INTO v2(a_p_name, a_p_first_name) SELECT old.p_name, old.p_first_name;
+END;
+$$
+update t1 set p_first_name='Yunxi' where p_id=1;
+drop view v2;
+drop table t1,t2;
+drop sequence s1;
# End of 10.3 tests
diff --git a/mysql-test/suite/sql_sequence/other.test b/mysql-test/suite/sql_sequence/other.test
index 5759b195950..70c4efa40e5 100644
--- a/mysql-test/suite/sql_sequence/other.test
+++ b/mysql-test/suite/sql_sequence/other.test
@@ -179,4 +179,140 @@ DROP SEQUENCE s;
DROP TABLE t1;
+--echo #
+--echo # MDEV-20074: Lost connection on update trigger
+--echo #
+
+--echo # INSERT & table
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+
+DELIMITER $$;
+
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+INSERT INTO t2(a_p_name, a_p_first_name) VALUES(old.p_name, old.p_first_name);
+END;
+$$
+DELIMITER ;$$
+
+update t1 set p_first_name='Yunxi' where p_id=1;
+
+drop sequence s1;
+drop table t1,t2;
+
+
+--echo # INSERT & view
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+create view v2 as select * from t2;
+
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+
+DELIMITER $$;
+
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+INSERT INTO v2(a_p_name, a_p_first_name) VALUES(old.p_name, old.p_first_name);
+END;
+$$
+DELIMITER ;$$
+
+update t1 set p_first_name='Yunxi' where p_id=1;
+
+drop view v2;
+drop table t1,t2;
+drop sequence s1;
+
+
+--echo # INSERT SELECT & view
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+create view v2 as select * from t2;
+
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+
+DELIMITER $$;
+
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+INSERT INTO v2(a_p_name, a_p_first_name) SELECT old.p_name, old.p_first_name;
+END;
+$$
+DELIMITER ;$$
+
+update t1 set p_first_name='Yunxi' where p_id=1;
+
+drop view v2;
+drop table t1,t2;
+drop sequence s1;
+
+
+--echo # REPLACE & view
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+create view v2 as select * from t2;
+
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+
+DELIMITER $$;
+
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+REPLACE INTO v2(a_p_name, a_p_first_name) VALUES(old.p_name, old.p_first_name);
+END;
+$$
+DELIMITER ;$$
+
+update t1 set p_first_name='Yunxi' where p_id=1;
+
+drop view v2;
+drop table t1,t2;
+drop sequence s1;
+
+
+--echo # REPLACE SELECT & view
+create sequence s1 increment by 1 start with 1;
+create table t1 (p_id integer, p_name varchar(128), p_first_name varchar(128));
+create table t2 (a_id integer default nextval(s1), a_p_name varchar(128), a_p_first_name varchar(128), t timestamp default current_timestamp);
+create view v2 as select * from t2;
+
+insert into t1 values
+(1, 'Luo','Frank'),(2, 'Xe','Emma'),(3, 'Li','Anna'),(4, 'Lun','Serg'),(5, 'Xu','Nils'),(6, 'Ja','Ute'),(7, 'Jin','Mike'),(8, 'Lio','Carl'),(9, 'Lang','Kevin'),(10, 'Ling','Lisa'),(11, 'Fang','Frank'),(12, 'Feng','Emma'),(13, 'Tuo','Anna'),(14, 'Tua','Serg'),(15, 'Moa','Nils'),(16, 'Hua','Ute'),(17, 'Xufa','Mike'),(18, 'Lulu','Carl'),(19, 'Hoho','Kevin'),(20, 'Tata','Lisa');
+
+DELIMITER $$;
+
+CREATE TRIGGER tr_upd
+BEFORE UPDATE on t1
+FOR EACH ROW
+BEGIN
+REPLACE INTO v2(a_p_name, a_p_first_name) SELECT old.p_name, old.p_first_name;
+END;
+$$
+DELIMITER ;$$
+
+update t1 set p_first_name='Yunxi' where p_id=1;
+
+drop view v2;
+drop table t1,t2;
+drop sequence s1;
+
--echo # End of 10.3 tests
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 458955b2d6b..48166fac4c6 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -4652,6 +4652,7 @@ typedef struct st_sp_table
uint lock_count;
uint query_lock_count;
uint8 trg_event_map;
+ my_bool for_insert_data;
} SP_TABLE;
@@ -4747,6 +4748,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
if (tab->query_lock_count > tab->lock_count)
tab->lock_count++;
tab->trg_event_map|= table->trg_event_map;
+ tab->for_insert_data|= table->for_insert_data;
}
else
{
@@ -4770,6 +4772,7 @@ sp_head::merge_table_list(THD *thd, TABLE_LIST *table, LEX *lex_for_tmp_check)
tab->lock_type= table->lock_type;
tab->lock_count= tab->query_lock_count= 1;
tab->trg_event_map= table->trg_event_map;
+ tab->for_insert_data= table->for_insert_data;
if (my_hash_insert(&m_sptabs, (uchar *)tab))
return FALSE;
}
@@ -4853,7 +4856,8 @@ sp_head::add_used_tables_to_table_list(THD *thd,
TABLE_LIST::PRELOCK_ROUTINE,
belong_to_view,
stab->trg_event_map,
- query_tables_last_ptr);
+ query_tables_last_ptr,
+ stab->for_insert_data);
tab_buff+= ALIGN_SIZE(sizeof(TABLE_LIST));
result= TRUE;
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 4bf894798de..4729612f2b0 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -4420,9 +4420,11 @@ add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *tables)
{
TABLE_LIST *global_table_list= prelocking_ctx->query_tables;
+ DBUG_ENTER("add_internal_tables");
do
{
+ DBUG_PRINT("info", ("table name: %s", tables->table_name.str));
/*
Skip table if already in the list. Can happen with prepared statements
*/
@@ -4432,20 +4434,22 @@ add_internal_tables(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *tl= (TABLE_LIST *) thd->alloc(sizeof(TABLE_LIST));
if (!tl)
- return TRUE;
+ DBUG_RETURN(TRUE);
tl->init_one_table_for_prelocking(&tables->db,
&tables->table_name,
NULL, tables->lock_type,
TABLE_LIST::PRELOCK_NONE,
0, 0,
- &prelocking_ctx->query_tables_last);
+ &prelocking_ctx->query_tables_last,
+ tables->for_insert_data);
/*
Store link to the new table_list that will be used by open so that
Item_func_nextval() can find it
*/
tables->next_local= tl;
+ DBUG_PRINT("info", ("table name: %s added", tables->table_name.str));
} while ((tables= tables->next_global));
- return FALSE;
+ DBUG_RETURN(FALSE);
}
@@ -4476,6 +4480,7 @@ bool DML_prelocking_strategy::
handle_table(THD *thd, Query_tables_list *prelocking_ctx,
TABLE_LIST *table_list, bool *need_prelocking)
{
+ DBUG_ENTER("handle_table");
TABLE *table= table_list->table;
/* We rely on a caller to check that table is going to be changed. */
DBUG_ASSERT(table_list->lock_type >= TL_WRITE_ALLOW_WRITE ||
@@ -4506,7 +4511,7 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
{
if (arena)
thd->restore_active_arena(arena, &backup);
- return TRUE;
+ DBUG_RETURN(TRUE);
}
*need_prelocking= TRUE;
@@ -4534,7 +4539,8 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
NULL, lock_type,
TABLE_LIST::PRELOCK_FK,
table_list->belong_to_view, op,
- &prelocking_ctx->query_tables_last);
+ &prelocking_ctx->query_tables_last,
+ table_list->for_insert_data);
}
if (arena)
thd->restore_active_arena(arena, &backup);
@@ -4542,8 +4548,11 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
}
/* Open any tables used by DEFAULT (like sequence tables) */
+ DBUG_PRINT("info", ("table: %p name: %s db: %s flags: %u",
+ table_list, table_list->table_name.str,
+ table_list->db.str, table_list->for_insert_data));
if (table->internal_tables &&
- ((sql_command_flags[thd->lex->sql_command] & CF_INSERTS_DATA) ||
+ (table_list->for_insert_data ||
thd->lex->default_used))
{
Query_arena *arena, backup;
@@ -4556,10 +4565,10 @@ handle_table(THD *thd, Query_tables_list *prelocking_ctx,
if (unlikely(error))
{
*need_prelocking= TRUE;
- return TRUE;
+ DBUG_RETURN(TRUE);
}
}
- return FALSE;
+ DBUG_RETURN(FALSE);
}
@@ -4576,7 +4585,7 @@ bool open_and_lock_internal_tables(TABLE *table, bool lock_table)
THD *thd= table->in_use;
TABLE_LIST *tl;
MYSQL_LOCK *save_lock,*new_lock;
- DBUG_ENTER("open_internal_tables");
+ DBUG_ENTER("open_and_lock_internal_tables");
/* remove pointer to old select_lex which is already destroyed */
for (tl= table->internal_tables ; tl ; tl= tl->next_global)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 3820ee5923d..8b6b2ca9df0 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -4060,6 +4060,8 @@ public:
}
bool tvc_finalize();
bool tvc_finalize_derived();
+
+ void mark_first_table_as_inserting();
};
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index e55f9aab35d..81eba0da8cb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3282,6 +3282,10 @@ mysql_execute_command(THD *thd)
#endif
DBUG_ENTER("mysql_execute_command");
+ // check that we correctly marked first table for data insertion
+ DBUG_ASSERT(!(sql_command_flags[lex->sql_command] & CF_INSERTS_DATA) ||
+ first_table->for_insert_data);
+
DBUG_ASSERT(thd->transaction.stmt.is_empty() || thd->in_sub_stmt);
/*
Each statement or replication event which might produce deadlock
@@ -10200,3 +10204,14 @@ CHARSET_INFO *find_bin_collation(CHARSET_INFO *cs)
}
return cs;
}
+
+void LEX::mark_first_table_as_inserting()
+{
+ TABLE_LIST *t= select_lex.table_list.first;
+ DBUG_ENTER("Query_tables_list::mark_tables_with_important_flags");
+ DBUG_ASSERT(sql_command_flags[sql_command] & CF_INSERTS_DATA);
+ t->for_insert_data= TRUE;
+ DBUG_PRINT("info", ("table_list: %p name: %s db: %s command: %u",
+ t, t->table_name.str,t->db.str, sql_command));
+ DBUG_VOID_RETURN;
+}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 0bde411a977..98c1e816f31 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1490,6 +1490,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
privileges of top_view
*/
tbl->grant.want_privilege= SELECT_ACL;
+
/*
After unfolding the view we lose the list of tables referenced in it
(we will have only a list of underlying tables in case of MERGE
@@ -1540,6 +1541,18 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
views with subqueries in select list.
*/
view_main_select_tables= lex->select_lex.table_list.first;
+ /*
+ Mergeable view can be used for inserting, so we move the flag down
+ */
+ if (table->for_insert_data)
+ {
+ for (TABLE_LIST *t= view_main_select_tables;
+ t;
+ t= t->next_local)
+ {
+ t->for_insert_data= TRUE;
+ }
+ }
/*
Let us set proper lock type for tables of the view's main
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 00ab03cba26..235be9b0f89 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7888,6 +7888,7 @@ alter:
MYSQL_YYABORT;
Lex->select_lex.db= (Lex->select_lex.table_list.first)->db;
Lex->create_last_non_select_table= Lex->last_table();
+ Lex->mark_first_table_as_inserting();
}
alter_commands
{
@@ -13459,7 +13460,9 @@ insert:
Lex->current_select= &Lex->select_lex;
}
insert_field_spec opt_insert_update
- {}
+ {
+ Lex->mark_first_table_as_inserting();
+ }
;
replace:
@@ -13476,7 +13479,9 @@ replace:
Lex->current_select= &Lex->select_lex;
}
insert_field_spec
- {}
+ {
+ Lex->mark_first_table_as_inserting();
+ }
;
insert_lock_option:
@@ -14859,7 +14864,9 @@ load:
opt_xml_rows_identified_by
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
opt_load_data_set_spec
- {}
+ {
+ Lex->mark_first_table_as_inserting();
+ }
;
data_or_xml:
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index f33ef8cfc68..12ac95dedee 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -7825,6 +7825,7 @@ alter:
MYSQL_YYABORT;
Lex->select_lex.db= (Lex->select_lex.table_list.first)->db;
Lex->create_last_non_select_table= Lex->last_table();
+ Lex->mark_first_table_as_inserting();
}
alter_commands
{
@@ -13420,7 +13421,9 @@ insert:
Lex->current_select= &Lex->select_lex;
}
insert_field_spec opt_insert_update
- {}
+ {
+ Lex->mark_first_table_as_inserting();
+ }
;
replace:
@@ -13437,7 +13440,9 @@ replace:
Lex->current_select= &Lex->select_lex;
}
insert_field_spec
- {}
+ {
+ Lex->mark_first_table_as_inserting();
+ }
;
insert_lock_option:
@@ -14826,7 +14831,9 @@ load:
opt_xml_rows_identified_by
opt_field_term opt_line_term opt_ignore_lines opt_field_or_var_spec
opt_load_data_set_spec
- {}
+ {
+ Lex->mark_first_table_as_inserting();
+ }
;
data_or_xml:
diff --git a/sql/table.h b/sql/table.h
index 494d6628ebe..0a0f0aab77f 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1985,7 +1985,8 @@ struct TABLE_LIST
prelocking_types prelocking_type,
TABLE_LIST *belong_to_view_arg,
uint8 trg_event_map_arg,
- TABLE_LIST ***last_ptr)
+ TABLE_LIST ***last_ptr,
+ my_bool insert_data)
{
init_one_table(db_arg, table_name_arg, alias_arg, lock_type_arg);
@@ -2000,6 +2001,7 @@ struct TABLE_LIST
**last_ptr= this;
prev_global= *last_ptr;
*last_ptr= &next_global;
+ for_insert_data= insert_data;
}
@@ -2411,6 +2413,8 @@ struct TABLE_LIST
/* System Versioning */
vers_select_conds_t vers_conditions;
+ my_bool for_insert_data;
+
/**
@brief
Find the bottom in the chain of embedded table VIEWs.