diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2020-06-22 18:21:21 +0200 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2021-07-15 16:28:13 +0200 |
commit | a7d880f0b095939118594ecbeba953959ae8e351 (patch) | |
tree | 4bd583a11bf5fc42327bdb8b069fb7673cb54a47 /tests | |
parent | 826eab3f9b28dbc370e5d7a2f81dc42d2f09ed40 (diff) | |
download | mariadb-git-a7d880f0b095939118594ecbeba953959ae8e351.tar.gz |
MDEV-21916: COM_STMT_BULK_EXECUTE with RETURNING insert wrong values
The problem is that array binding uses net buffer to read parameters for each
execution while each execiting with RETURNING write in the same buffer.
Solution is to allocate new net buffer to avoid changing buffer we are reading
from.
Diffstat (limited to 'tests')
-rw-r--r-- | tests/mysql_client_test.c | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 4b3e0a5b446..7587e08e727 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -20547,6 +20547,178 @@ static void test_bulk_replace() rc= mysql_query(mysql, "DROP TABLE t1"); myquery(rc); } + + +static void test_bulk_insert_returning() +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind[2], res_bind[2]; + MYSQL_ROW row; + MYSQL_RES *result; + int i, + id[]= {1, 2, 3, 4}, + val[]= {1, 1, 1, 1}, + count= sizeof(id)/sizeof(id[0]); + unsigned long length[2]; + my_bool is_null[2]; + my_bool error[2]; + int32 res[2]; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, + "CREATE TABLE t1 (id int not null primary key, active int)"); + myquery(rc); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, + "insert into t1 values (?, ?) returning id, active", + -1); + check_execute(stmt, rc); + + memset(bind, 0, sizeof(bind)); + bind[0].buffer_type = MYSQL_TYPE_LONG; + bind[0].buffer = (void *)id; + bind[0].buffer_length = 0; + bind[1].buffer_type = MYSQL_TYPE_LONG; + bind[1].buffer = (void *)val; + bind[1].buffer_length = 0; + + mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count); + rc= mysql_stmt_bind_param(stmt, bind); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + myquery(rc); + + memset(res_bind, 0, sizeof(res_bind)); + for (i= 0; i < 2; i++) + { + res_bind[i].buffer_type= MYSQL_TYPE_LONG; + res_bind[i].buffer= (char *)&res[i]; + res_bind[i].is_null= &is_null[i]; + res_bind[i].length= &length[i]; + res_bind[i].error= &error[i]; + } + rc= mysql_stmt_bind_result(stmt, res_bind); + myquery(rc); + rc= mysql_stmt_store_result(stmt); + myquery(rc); + + i= 0; + while (!mysql_stmt_fetch(stmt)) + { + i++; + DIE_IF(is_null[0] || is_null[1]); + DIE_IF(res[0] != i); + DIE_IF(res[1] != 1); + } + DIE_IF(i != 4); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "SELECT id,active FROM t1"); + myquery(rc); + + result= mysql_store_result(mysql); + mytest(result); + + i= 0; + while ((row= mysql_fetch_row(result))) + { + i++; + DIE_IF(atoi(row[0]) != i); + DIE_IF(atoi(row[1]) != 1); + } + DIE_IF(i != 4); + mysql_free_result(result); + + + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); +} + +static void test_bulk_delete_returning() +{ + int rc; + MYSQL_STMT *stmt; + MYSQL_BIND bind[2], res_bind[2]; + MYSQL_ROW row; + MYSQL_RES *result; + int i, + id[]= {1, 2, 3, 4}, + count= sizeof(id)/sizeof(id[0]); + unsigned long length[1]; + my_bool is_null[1]; + my_bool error[1]; + int32 res[1]; + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + rc= mysql_query(mysql, "CREATE TABLE t1 (id int not null primary key)"); + myquery(rc); + rc= mysql_query(mysql, "insert into t1 values (1), (2), (3), (4)"); + myquery(rc); + verify_affected_rows(4); + + stmt= mysql_stmt_init(mysql); + rc= mysql_stmt_prepare(stmt, "DELETE FROM t1 WHERE id=? RETURNING id", -1); + check_execute(stmt, rc); + + memset(bind, 0, sizeof(bind)); + bind[0].buffer_type = MYSQL_TYPE_LONG; + bind[0].buffer = (void *)id; + bind[0].buffer_length = 0; + + mysql_stmt_attr_set(stmt, STMT_ATTR_ARRAY_SIZE, (void*)&count); + rc= mysql_stmt_bind_param(stmt, bind); + check_execute(stmt, rc); + + rc= mysql_stmt_execute(stmt); + myquery(rc); + + memset(res_bind, 0, sizeof(res_bind)); + res_bind[0].buffer_type= MYSQL_TYPE_LONG; + res_bind[0].buffer= (char *)&res[0]; + res_bind[0].is_null= &is_null[0]; + res_bind[0].length= &length[0]; + res_bind[0].error= &error[0]; + rc= mysql_stmt_bind_result(stmt, res_bind); + myquery(rc); + rc= mysql_stmt_store_result(stmt); + myquery(rc); + + i= 0; + while (!mysql_stmt_fetch(stmt)) + { + i++; + DIE_IF(is_null[0]); + DIE_IF(res[0] != i); + } + DIE_IF(i != 4); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "SELECT id FROM t1"); + myquery(rc); + + result= mysql_store_result(mysql); + mytest(result); + + i= 0; + while ((row= mysql_fetch_row(result))) + { + i++; + printf("\nResult (SHOULD NOT BE HERE!!!) %d %s \n", i, row[0]); + } + DIE_IF(i != 0 ); + mysql_free_result(result); + + + rc= mysql_query(mysql, "DROP TABLE t1"); + myquery(rc); +} #endif @@ -21427,6 +21599,8 @@ static struct my_tests_st my_tests[]= { { "test_bulk_autoinc", test_bulk_autoinc}, { "test_bulk_delete", test_bulk_delete }, { "test_bulk_replace", test_bulk_replace }, + { "test_bulk_insert_returning", test_bulk_insert_returning }, + { "test_bulk_delete_returning", test_bulk_delete_returning }, #endif { "test_ps_params_in_ctes", test_ps_params_in_ctes }, { "test_explain_meta", test_explain_meta }, |