diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 2792ca8e015..35eec93f540 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1021,10 +1021,19 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, */ restore_record(table,s->default_values); // Get empty record table->reset_default_fields(); + /* + Reset the sentinel thd->bulk_param in order not to consume the next + values of a bound array in case one of statement executed by + the trigger's body is INSERT statement. + */ + void *save_bulk_param= thd->bulk_param; + thd->bulk_param= nullptr; + if (unlikely(fill_record_n_invoke_before_triggers(thd, table, fields, *values, 0, TRG_EVENT_INSERT))) { + thd->bulk_param= save_bulk_param; if (values_list.elements != 1 && ! thd->is_error()) { info.records++; @@ -1038,6 +1047,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, error=1; break; } + thd->bulk_param= save_bulk_param; } else { @@ -1067,12 +1077,22 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, } } table->reset_default_fields(); + + /* + Reset the sentinel thd->bulk_param in order not to consume the next + values of a bound array in case one of statement executed by + the trigger's body is INSERT statement. + */ + void *save_bulk_param= thd->bulk_param; + thd->bulk_param= nullptr; + if (unlikely(fill_record_n_invoke_before_triggers(thd, table, table-> field_to_fill(), *values, 0, TRG_EVENT_INSERT))) { + thd->bulk_param= save_bulk_param; if (values_list.elements != 1 && ! thd->is_error()) { info.records++; @@ -1081,6 +1101,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list, error=1; break; } + thd->bulk_param= save_bulk_param; } /* diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index ebc462bea50..66281641b08 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -21870,6 +21870,103 @@ static void test_mdev19838() rc = mysql_query(mysql, "drop table mdev19838"); myquery(rc); } + +static void test_mdev_24411() +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind; + MYSQL_RES *result; + MYSQL_ROW row; + my_ulonglong row_count; + unsigned int vals[] = { 1, 2, 3}; + unsigned int vals_array_len = 3; + const char *insert_stmt= "INSERT INTO t1 VALUES (?)"; + + myheader("test_mdev_24411"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t2"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t1 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t2 (a INT)"); + myquery(rc); + + rc= mysql_query(mysql, + "CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW " + "BEGIN INSERT INTO t2 (a) VALUES (NEW.a); END;"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + check_stmt(stmt); + + rc= mysql_stmt_prepare(stmt, insert_stmt, strlen(insert_stmt)); + check_execute(stmt, rc); + + memset(&bind, 0, sizeof(bind)); + bind.buffer_type= MYSQL_TYPE_LONG; + bind.buffer= vals; + + rc= mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, &vals_array_len); + check_execute(stmt, rc); + + rc= mysql_stmt_bind_param(stmt, &bind); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + /* + It's expected that the INSERT statement adds three rows into + the table t1 + */ + row_count = mysql_stmt_affected_rows(stmt); + DIE_UNLESS(row_count == 3); + + /* + * Check that the BEFORE INSERT trigger of the table t1 does work correct + * and inserted the rows (1), (2), (3) into the table t2. + */ + rc= mysql_query(mysql, "SELECT 't1' tname, a FROM t1 " + "UNION SELECT 't2' tname, a FROM t2 ORDER BY tname,a"); + myquery(rc); + + result= mysql_store_result(mysql); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 1); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 2); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t1") == 0 && atoi(row[1]) == 3); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 1); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 2); + + row = mysql_fetch_row(result); + DIE_UNLESS(strcmp(row[0], "t2") == 0 && atoi(row[1]) == 3); + + row= mysql_fetch_row(result); + DIE_UNLESS(row == NULL); + + mysql_free_result(result); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE t1, t2"); + myquery(rc); +} + #endif // EMBEDDED_LIBRARY @@ -22307,6 +22404,9 @@ static struct my_tests_st my_tests[]= { { "test_mdev20261", test_mdev20261 }, { "test_mdev_30159", test_mdev_30159 }, { "test_connect_autocommit", test_connect_autocommit}, +#ifndef EMBEDDED_LIBRARY + { "test_mdev_24411", test_mdev_24411}, +#endif { 0, 0 } };