Skip to content

Commit a6aabb0

Browse files
committed
MDEV-27013: COM_STMT_PREPARE returns 0 columns for INSERT .. RETURNING
If this was a SELECT statement, the columns would be populated by the mysql_test_insert call to send_prep_stmt. So we need to get the column count for returning statements and populate this instead of 0. Note the unit test would return the correct results the server correction changed as it was popluated from the COM_STMT_EXECUTE. However this test useful to run via socat interceptor[1] to examine the results at offset 9 after packet beginning 0c. tests/mariadb-client-test -S /tmp/intercept.sock -u $USER -D test test_mdev_27013 [1] socat -x -v UNIX-LISTEN:/tmp/intercept.sock,fork UNIX-CONNECT:/tmp/mariadb.sock
1 parent 60f046d commit a6aabb0

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

sql/sql_prepare.cc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2434,6 +2434,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
24342434
TABLE_LIST *tables;
24352435
enum enum_sql_command sql_command= lex->sql_command;
24362436
int res= 0;
2437+
bool returning= false;
24372438
DBUG_ENTER("check_prepared_statement");
24382439
DBUG_PRINT("enter",("command: %d param_count: %u",
24392440
sql_command, stmt->param_count));
@@ -2495,6 +2496,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
24952496
lex->many_values,
24962497
lex->update_list, lex->value_list,
24972498
lex->duplicates);
2499+
returning= lex->has_returning();
24982500
break;
24992501

25002502
case SQLCOM_LOAD:
@@ -2516,6 +2518,7 @@ static bool check_prepared_statement(Prepared_statement *stmt)
25162518

25172519
case SQLCOM_DELETE:
25182520
res= mysql_test_delete(stmt, tables);
2521+
returning= lex->has_returning();
25192522
break;
25202523
/* The following allow WHERE clause, so they must be tested like SELECT */
25212524
case SQLCOM_SHOW_DATABASES:
@@ -2655,11 +2658,13 @@ static bool check_prepared_statement(Prepared_statement *stmt)
26552658

26562659
case SQLCOM_DELETE_MULTI:
26572660
res= mysql_test_multidelete(stmt, tables);
2661+
returning= lex->has_returning();
26582662
break;
26592663

26602664
case SQLCOM_INSERT_SELECT:
26612665
case SQLCOM_REPLACE_SELECT:
26622666
res= mysql_test_insert_select(stmt, tables);
2667+
returning= lex->has_returning();
26632668
break;
26642669

26652670
case SQLCOM_HA_READ:
@@ -2725,7 +2730,17 @@ static bool check_prepared_statement(Prepared_statement *stmt)
27252730
Protocol::SEND_EOF);
27262731
}
27272732
else
2728-
res= send_prep_stmt(stmt, 0);
2733+
{
2734+
if (returning)
2735+
{
2736+
select_send result(thd);
2737+
List<Item> &field_list= lex->returning()->item_list;
2738+
res= send_prep_stmt(stmt, field_list.elements) ||
2739+
result.send_result_set_metadata(field_list, Protocol::SEND_EOF);
2740+
}
2741+
else
2742+
res= send_prep_stmt(stmt, 0);
2743+
}
27292744
if (!res)
27302745
thd->protocol->flush();
27312746
}

tests/mysql_client_test.c

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ static void test_prepare_insert_update()
347347
const char **cur_query;
348348

349349
myheader("test_prepare_insert_update");
350-
350+
351351
for (cur_query= testcase; *cur_query; cur_query++)
352352
{
353353
char query[MAX_TEST_QUERY_LENGTH];
@@ -21874,6 +21874,69 @@ static void test_mdev19838()
2187421874
myquery(rc);
2187521875
}
2187621876

21877+
static void test_mdev_27013()
21878+
{
21879+
int rc;
21880+
unsigned paramCount = 1;
21881+
MYSQL_STMT *stmt;
21882+
MYSQL_FIELD *fld;
21883+
const char *commands[] = {
21884+
"SELECT * FROM mdev27013",
21885+
"SELECT c1,c2 FROM mdev27013",
21886+
"INSERT INTO mdev27013 (c1) VALUES('tweet') RETURNING *",
21887+
"REPLACE INTO mdev27013 SET c2='growl' RETURNING c1, c2",
21888+
"DELETE FROM mdev27013 RETURNING *"
21889+
};
21890+
21891+
myheader("test_mdev27013");
21892+
21893+
rc = mysql_query(mysql, "CREATE TABLE mdev27013("
21894+
"c1 char(36), c2 char(36)"
21895+
")");
21896+
myquery(rc);
21897+
21898+
stmt = mysql_stmt_init(mysql);
21899+
check_stmt(stmt);
21900+
21901+
for (int com= 0; com < 5; com++)
21902+
{
21903+
rc = mariadb_stmt_execute_direct(stmt, commands[com], -1);
21904+
21905+
if (rc)
21906+
mct_log("comm: %s err: %s", commands[com], mysql_stmt_error(stmt));
21907+
DIE_UNLESS(rc == 0);
21908+
21909+
paramCount = mysql_stmt_field_count(stmt);
21910+
DIE_UNLESS(paramCount == 2);
21911+
21912+
fld= mariadb_stmt_fetch_fields(stmt);
21913+
DIE_UNLESS(fld != NULL);
21914+
21915+
mct_log("comm: %s\n", commands[com]);
21916+
for (unsigned int i = 0; i < paramCount; ++i)
21917+
{
21918+
mct_log("name: '%s'/'%s'; table: '%s'/'%s'; "
21919+
"db: '%s'; catalog: '%s'; length: %d; max_length: %d; "
21920+
"type: %d; decimals: %d\n",
21921+
(const char *) fld[i].name,
21922+
(const char *) fld[i].org_name,
21923+
(const char *) fld[i].table,
21924+
(const char *) fld[i].org_table,
21925+
(const char *) fld[i].db,
21926+
(const char *) fld[i].catalog,
21927+
(int) fld[i].length,
21928+
(int) fld[i].max_length,
21929+
(int) fld[i].type,
21930+
(int) fld[i].decimals);
21931+
}
21932+
}
21933+
21934+
mysql_stmt_close(stmt);
21935+
21936+
rc = mysql_query(mysql, "drop table mdev27013");
21937+
myquery(rc);
21938+
}
21939+
2187721940
static void test_mdev_24411()
2187821941
{
2187921942
int rc;
@@ -23274,6 +23337,7 @@ static struct my_tests_st my_tests[]= {
2327423337
{ "test_mdev_34718_ad", test_mdev_34718_ad },
2327523338
{ "test_mdev_34958", test_mdev_34958 },
2327623339
{ "test_mdev_32086", test_mdev_32086 },
23340+
{ "test_mdev_27013", test_mdev_27013 },
2327723341
#endif
2327823342
{ 0, 0 }
2327923343
};

0 commit comments

Comments
 (0)