diff options
author | Dmitry Shulga <dmitry.shulga@mariadb.com> | 2021-07-18 13:28:12 +0700 |
---|---|---|
committer | Dmitry Shulga <dmitry.shulga@mariadb.com> | 2021-07-18 13:28:12 +0700 |
commit | ddbe57c727fc2fd25d26e52266e0ed2de4ebbb1d (patch) | |
tree | 8ac386587d3c5b0d488f43634930024bf50753b5 | |
parent | 0f6e170c34700a2964556839c676c1b7768f3ffb (diff) | |
download | mariadb-git-bb-10.2-MDEV-26145.tar.gz |
MDEV-26145: Incorrect metadata is sent on running query with union in PS modebb-10.2-MDEV-26145
Test cases like the following one produce different result sets if it's run
with and without th option --ps-protocol.
CREATE TABLE t1(a INT);
--enable_metadata
(SELECT MAX(a) FROM t1) UNION (SELECT MAX(a) FROM t1);
--disable_metadata
DROP TABLE t1;
Result sets differ in metadata for the query
(SELECT MAX(a) FROM t1) UNION (SELECT MAX(a) FROM t1);
The reason for different content of query metadata is that for queries
with union the items being created on JOIN preparing phase is placed into
item_list from SELECT_LEX_UNIT whereas for queries without union item_list
from SELECT_LEX is used instead.
-rw-r--r-- | mysql-test/r/mysql_client_test.result | 5 | ||||
-rw-r--r-- | mysql-test/t/mysql_client_test.test | 4 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 7 | ||||
-rw-r--r-- | tests/mysql_client_test.c | 62 |
4 files changed, 77 insertions, 1 deletions
diff --git a/mysql-test/r/mysql_client_test.result b/mysql-test/r/mysql_client_test.result index 9538475fb86..37a735286da 100644 --- a/mysql-test/r/mysql_client_test.result +++ b/mysql-test/r/mysql_client_test.result @@ -126,6 +126,11 @@ Data: EOF mysql_stmt_next_result(): 0; field_count: 0 # ------------------------------------ +# cat MYSQL_TMP_DIR/test_mdev26145.out.log +# ------------------------------------ +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def MAX(a) MAX(a) 3 11 0 Y 32768 0 63 +# ------------------------------------ SET @@global.general_log= @old_general_log; SET @@global.slow_query_log= @old_slow_query_log; diff --git a/mysql-test/t/mysql_client_test.test b/mysql-test/t/mysql_client_test.test index 8c2f5e2c32b..aa9b1d5a77c 100644 --- a/mysql-test/t/mysql_client_test.test +++ b/mysql-test/t/mysql_client_test.test @@ -35,6 +35,10 @@ echo ok; --echo # ------------------------------------ --cat_file $MYSQL_TMP_DIR/test_wl4435.out.log --echo # ------------------------------------ +--echo # cat MYSQL_TMP_DIR/test_mdev26145.out.log +--echo # ------------------------------------ +--cat_file $MYSQL_TMP_DIR/test_mdev26145.out.log +--echo # ------------------------------------ --echo SET @@global.general_log= @old_general_log; diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 922d7c92796..624bcb90cd5 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -1674,7 +1674,12 @@ static int mysql_test_select(Prepared_statement *stmt, if (!lex->describe && !thd->lex->analyze_stmt && !stmt->is_sql_prepare()) { /* Make copy of item list, as change_columns may change it */ - List<Item> fields(lex->select_lex.item_list); + SELECT_LEX_UNIT* master_unit= unit->first_select()->master_unit(); + bool is_union_op= + master_unit->is_union() || master_unit->fake_select_lex; + + List<Item> fields(is_union_op ? unit->item_list : + lex->select_lex.item_list); /* Change columns if a procedure like analyse() */ if (unit->last_procedure && unit->last_procedure->change_columns(thd, fields)) diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c index 93f23236dbc..7b0d79c4b45 100644 --- a/tests/mysql_client_test.c +++ b/tests/mysql_client_test.c @@ -19896,6 +19896,67 @@ static void test_ps_params_in_ctes() myquery(rc); } +void display_result_metadata(MYSQL_FIELD *field, + uint num_fields) +{ + mct_log("Catalog\tDatabase\tTable\tTable_alias\tColumn\t" + "Column_alias\tType\tLength\tMax length\tIs_null\t" + "Flags\tDecimals\tCharsetnr\n"); + for (MYSQL_FIELD* field_end= field+num_fields; field < field_end; field++) + { + mct_log("%s\t", field->catalog); + mct_log("%s\t", field->db); + mct_log("%s\t", field->org_table); + mct_log("%s\t", field->table); + mct_log("%s\t", field->org_name); + mct_log("%s\t", field->name); + mct_log("%u\t", field->type); + mct_log("%lu\t", field->length); + mct_log("%lu\t", field->max_length); + mct_log("%s\t", (IS_NOT_NULL(field->flags) ? "N" : "Y")); + mct_log("%u\t", field->flags); + mct_log("%u\t", field->decimals); + mct_log("%u\n", field->charsetnr); + } +} + +static void test_mdev_26145() +{ + MYSQL_STMT *stmt; + int rc; + + myheader("test_mdev_26145"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1"); + myquery(rc); + + rc= mysql_query(mysql, "CREATE TABLE t1(a INT)"); + myquery(rc); + + stmt= mysql_simple_prepare( + mysql, "(SELECT MAX(a) FROM t1) UNION (SELECT MAX(a) FROM t1)"); + check_stmt(stmt); + + rc= mysql_stmt_execute(stmt); + check_execute(stmt, rc); + + MYSQL_RES *result= mysql_stmt_result_metadata(stmt); + DIE_UNLESS(result); + + int num_fields= mysql_stmt_field_count(stmt); + MYSQL_FIELD *fields= mysql_fetch_fields(result); + + mct_start_logging("test_mdev26145"); + display_result_metadata(fields, num_fields); + mct_close_log(); + + mysql_free_result(result); + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "DROP TABLE t1"); + + myquery(rc); +} #ifndef EMBEDDED_LIBRARY #define MDEV19838_MAX_PARAM_COUNT 32 @@ -20047,6 +20108,7 @@ static void test_mdev19838() #endif // EMBEDDED_LIBRARY static struct my_tests_st my_tests[]= { + { "test_mdev_26145", test_mdev_26145 }, { "disable_query_logs", disable_query_logs }, { "test_view_sp_list_fields", test_view_sp_list_fields }, { "client_query", client_query }, |