summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2020-06-22 18:21:21 +0200
committerOleksandr Byelkin <sanja@mariadb.com>2021-07-15 16:28:13 +0200
commita7d880f0b095939118594ecbeba953959ae8e351 (patch)
tree4bd583a11bf5fc42327bdb8b069fb7673cb54a47 /tests
parent826eab3f9b28dbc370e5d7a2f81dc42d2f09ed40 (diff)
downloadmariadb-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.c174
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 },