
[Commits] b9e28d4227e: MDEV-15777:Support Early NULLs filtering-like restrictions in the range optimizer
by varunraiko1803ï¼ gmail.com 20 Apr '18
by varunraiko1803ï¼ gmail.com 20 Apr '18
20 Apr '18
revision-id: b9e28d4227ea4b4d9cd147f87354afaf44e14746 (mariadb-10.3.0-765-gb9e28d4227e)
parent(s): 91245909a2f0c89444ecb5af587284f53b7196ee
author: Varun Gupta
committer: Varun Gupta
timestamp: 2018-04-20 22:58:45 +0530
message:
MDEV-15777:Support Early NULLs filtering-like restrictions in the range optimizer
Introduced function make_null_rejecting_conds() that would calcualte the null rejecting conds for the keys of a table and
then we can perform range analysis on these conditions.
TABLE strucuture introduces a null_rejecting_cond field that would hold these null rejecting conditions for a table.
---
mysql-test/main/mdev15777.result | 65 ++++++++++++++++++++
mysql-test/main/mdev15777.test | 34 +++++++++++
sql/opt_range.cc | 124 ++++++++++++++++++++++++++++++++++++++-
sql/opt_range.h | 2 +
sql/sql_select.cc | 22 ++++++-
sql/table.cc | 1 +
sql/table.h | 6 ++
7 files changed, 250 insertions(+), 4 deletions(-)
diff --git a/mysql-test/main/mdev15777.result b/mysql-test/main/mdev15777.result
new file mode 100644
index 00000000000..87167c16f6d
--- /dev/null
+++ b/mysql-test/main/mdev15777.result
@@ -0,0 +1,65 @@
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+create table one_m(a int);
+insert into one_m select A.a + B.a* 1000 from one_k A, one_k B;
+delete from one_m where a=0 limit 1;
+create table t1 (
+id int(10) unsigned NOT NULL AUTO_INCREMENT,
+filler varchar(100),
+subset_id int(11) DEFAULT NULL,
+PRIMARY KEY (id),
+KEY t1_subset_id (subset_id)
+);
+create table t1_subsets (
+id int(10) unsigned NOT NULL AUTO_INCREMENT,
+filler1 varchar(100),
+filler2 varchar(100),
+filler3 varchar(100),
+PRIMARY KEY (id)
+);
+insert into t1 select a,a, NULL from one_m where a < 50*1000;
+insert into t1_subsets select a,a,a,a from one_m where a < 500*1000 limit 499000;
+analyze format=json
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t1_subsets.id FROM t1_subsets);
+ANALYZE
+{
+ "query_block": {
+ "select_id": 1,
+ "r_loops": 1,
+ "r_total_time_ms": 0.0444,
+ "table": {
+ "table_name": "t1",
+ "access_type": "range",
+ "possible_keys": ["t1_subset_id"],
+ "key": "t1_subset_id",
+ "key_length": "5",
+ "used_key_parts": ["subset_id"],
+ "r_loops": 1,
+ "rows": 3,
+ "r_rows": 0,
+ "r_total_time_ms": 0.0146,
+ "filtered": 100,
+ "r_filtered": 100,
+ "index_condition": "t1.subset_id is not null"
+ },
+ "table": {
+ "table_name": "t1_subsets",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["id"],
+ "ref": ["test.t1.subset_id"],
+ "r_loops": 0,
+ "rows": 1,
+ "r_rows": null,
+ "filtered": 100,
+ "r_filtered": null,
+ "attached_condition": "t1.subset_id = t1_subsets.`id`",
+ "using_index": true
+ }
+ }
+}
+drop table t1,t1_subsets,ten,one_k,one_m;
diff --git a/mysql-test/main/mdev15777.test b/mysql-test/main/mdev15777.test
new file mode 100644
index 00000000000..ad5777aeecf
--- /dev/null
+++ b/mysql-test/main/mdev15777.test
@@ -0,0 +1,34 @@
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table one_k(a int);
+insert into one_k select A.a + B.a* 10 + C.a * 100 from ten A, ten B, ten C;
+
+create table one_m(a int);
+insert into one_m select A.a + B.a* 1000 from one_k A, one_k B;
+delete from one_m where a=0 limit 1;
+
+create table t1 (
+ id int(10) unsigned NOT NULL AUTO_INCREMENT,
+ filler varchar(100),
+ subset_id int(11) DEFAULT NULL,
+ PRIMARY KEY (id),
+ KEY t1_subset_id (subset_id)
+);
+
+create table t1_subsets (
+ id int(10) unsigned NOT NULL AUTO_INCREMENT,
+ filler1 varchar(100),
+ filler2 varchar(100),
+ filler3 varchar(100),
+ PRIMARY KEY (id)
+);
+
+insert into t1 select a,a, NULL from one_m where a < 50*1000;
+insert into t1_subsets select a,a,a,a from one_m where a < 500*1000 limit 499000;
+
+analyze format=json
+SELECT * FROM t1 WHERE t1.subset_id IN (SELECT t1_subsets.id FROM t1_subsets);
+drop table t1,t1_subsets,ten,one_k,one_m;
+
+
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 38dbed92a22..9343f97382d 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2399,6 +2399,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
uint idx;
double scan_time;
+ Item *null_rejecting_conds= NULL;
DBUG_ENTER("SQL_SELECT::test_quick_select");
DBUG_PRINT("enter",("keys_to_use: %lu prev_tables: %lu const_tables: %lu",
(ulong) keys_to_use.to_ulonglong(), (ulong) prev_tables,
@@ -2422,6 +2423,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
read_time= (double) records + scan_time + 1; // Force to use index
possible_keys.clear_all();
+ null_rejecting_conds= head->null_rejecting_conds;
DBUG_PRINT("info",("Time to scan table: %g", read_time));
@@ -2430,7 +2432,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
{
uchar buff[STACK_BUFF_ALLOC];
MEM_ROOT alloc;
- SEL_TREE *tree= NULL;
+ SEL_TREE *tree= NULL, *not_null_cond_tree= NULL;
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
@@ -2539,6 +2541,12 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
TRP_GROUP_MIN_MAX *group_trp;
double best_read_time= read_time;
+ if (null_rejecting_conds)
+ {
+ not_null_cond_tree= null_rejecting_conds->get_mm_tree(¶m,
+ &null_rejecting_conds);
+ }
+
if (cond)
{
if ((tree= cond->get_mm_tree(¶m, &cond)))
@@ -2557,6 +2565,13 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
tree= NULL;
}
}
+ if (not_null_cond_tree)
+ {
+ if (!tree)
+ tree= not_null_cond_tree;
+ else
+ tree= tree_and(¶m, tree, not_null_cond_tree);
+ }
/*
Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
@@ -14647,6 +14662,113 @@ void QUICK_GROUP_MIN_MAX_SELECT::add_keys_and_lengths(String *key_names,
add_key_and_length(key_names, used_lengths, &first);
}
+inline void add_cond(THD *thd, Item **e1, Item *e2)
+{
+ if (*e1)
+ {
+ if (!e2)
+ return;
+ Item *res;
+ if ((res= new (thd->mem_root) Item_cond_and(thd, *e1, e2)))
+ {
+ res->fix_fields(thd, 0);
+ res->update_used_tables();
+ *e1= res;
+ }
+ }
+ else
+ *e1= e2;
+}
+
+/*
+ Create null rejecting conditions for a table, for all the equalites
+ present in the WHERE clause of a query.
+
+ SYNOPSIS
+ make_null_rejecting_conds()
+ @param TABLE - Keys of this table will participate in null
+ rejecting conditions
+ @param keyuse_array - array that has all the equalites of the
+ WHERE clasuse
+
+ DESCRIPTION
+ This function creates null rejecting conditions for a table. These
+ conditions are created to do range analysis on them , the conditions
+ are of the form tbl.key.keypart IS NOT NULL.
+
+ IMPLEMENTATION
+ Lookup in the keyuse array to check if it has equalites that belong
+ to the given table. If yes then find out if the conditions are null
+ rejecting and accordingly create all the condition for the keys of a
+ given table and AND them.
+
+
+ RETURN
+ NOT NULL - Found null rejecting conditions for the given table
+ NULL - No null rejecting conditions for the given table
+*/
+
+void make_null_rejecting_conds(THD *thd, TABLE *table,
+ DYNAMIC_ARRAY *keyuse_array, key_map *const_keys)
+{
+ KEY *keyinfo;
+ Item *cond= NULL;
+ KEYUSE* keyuse;
+
+ /*
+ The null rejecting conds added will be on the keypart of a key, so for
+ that we need the table to atleast have a key.
+ */
+ if (!table->s->keys)
+ return ;
+ if (table->null_rejecting_conds)
+ return;
+
+ for(uint i=0; i < keyuse_array->elements; i++)
+ {
+ keyuse= (KEYUSE*)dynamic_array_ptr(keyuse_array, i);
+ if (keyuse->table == table)
+ {
+ /*
+ No null rejecting conds for a hash key
+ */
+ if (keyuse->key == MAX_KEY)
+ continue;
+ keyinfo= keyuse->table->key_info+keyuse->key;
+ Field *field= keyinfo->key_part[keyuse->keypart].field;
+
+ /*
+ No need to add null-rejecting condition if we have a
+ keyuse element as
+ - table.key.keypart= const
+ - (table.key.keypart= tbl.otherfield or table.key.keypart IS NULL)
+ - table.key.keypart IS NOT NULLABLE
+ */
+
+ if (keyuse->val->const_item()
+ || !(keyuse->null_rejecting && field->maybe_null())
+ || keyuse->optimize & KEY_OPTIMIZE_REF_OR_NULL)
+ continue;
+
+ Item_field *field_item= new (thd->mem_root)Item_field(thd, field);
+ Item* not_null_item= new (thd->mem_root)Item_func_isnotnull(thd,
+ field_item);
+
+ /*
+ adding the key to const keys as we have the condition
+ as key.keypart IS NOT NULL
+ */
+
+ const_keys->set_bit(keyuse->key);
+ not_null_item->fix_fields(thd, 0);
+ not_null_item->update_used_tables();
+ add_cond(thd, &cond, not_null_item);
+ }
+ }
+ table->null_rejecting_conds= cond;
+ return;
+}
+
#ifndef DBUG_OFF
diff --git a/sql/opt_range.h b/sql/opt_range.h
index bd85a12d4a1..894d46a892c 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -1728,6 +1728,8 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond);
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
#endif
void store_key_image_to_rec(Field *field, uchar *ptr, uint len);
+void make_null_rejecting_conds(THD *thd, TABLE *table,
+ DYNAMIC_ARRAY *keyuse_array, key_map *const_keys);
extern String null_string;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 796ea569e64..daef79e2f68 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -4783,6 +4783,9 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
add_group_and_distinct_keys(join, s);
s->table->cond_selectivity= 1.0;
+
+ make_null_rejecting_conds(join->thd, s->table,
+ keyuse_array, &s->const_keys);
/*
Perform range analysis if there are keys it could use (1).
@@ -4812,6 +4815,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
1, &error);
if (!select)
goto error;
+
records= get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit);
/* Range analyzer could modify the condition. */
@@ -5330,15 +5334,24 @@ add_key_field(JOIN *join,
If the condition has form "tbl.keypart = othertbl.field" and
othertbl.field can be NULL, there will be no matches if othertbl.field
has NULL value.
+
+ The field KEY_FIELD::null_rejecting is set to TRUE if we have both
+ the left and right hand side of the equality are NULLABLE
+
We use null_rejecting in add_not_null_conds() to add
'othertbl.field IS NOT NULL' to tab->select_cond.
+
+ We use null_rejecting in make_null_rejecting_conds() to add
+ tbl.keypart IS NOT NULL so we can do range analysis on this condition
+
*/
{
Item *real= (*value)->real_item();
if (((cond->functype() == Item_func::EQ_FUNC) ||
(cond->functype() == Item_func::MULT_EQUAL_FUNC)) &&
- (real->type() == Item::FIELD_ITEM) &&
+ (((real->type() == Item::FIELD_ITEM) &&
((Item_field*)real)->field->maybe_null())
+ ||(field->maybe_null())))
(*key_fields)->null_rejecting= true;
else
(*key_fields)->null_rejecting= false;
@@ -9794,7 +9807,10 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
uint maybe_null= MY_TEST(keyinfo->key_part[i].null_bit);
j->ref.items[i]=keyuse->val; // Save for cond removal
j->ref.cond_guards[i]= keyuse->cond_guard;
- if (keyuse->null_rejecting)
+ Item *real= (keyuse->val)->real_item();
+ if (keyuse->null_rejecting &&
+ (real->type() == Item::FIELD_ITEM) &&
+ ((Item_field*)real)->field->maybe_null())
j->ref.null_rejecting|= (key_part_map)1 << i;
keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
/*
@@ -18516,7 +18532,7 @@ free_tmp_table(THD *thd, TABLE *entry)
DBUG_ASSERT(entry->pos_in_table_list->table == entry);
entry->pos_in_table_list->table= NULL;
}
-
+ entry->null_rejecting_conds= NULL;
free_root(&own_root, MYF(0)); /* the table is allocated in its own root */
thd_proc_info(thd, save_proc_info);
diff --git a/sql/table.cc b/sql/table.cc
index 577ed20a87e..c4e7c3aba09 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -4593,6 +4593,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
created= TRUE;
cond_selectivity= 1.0;
cond_selectivity_sampling_explain= NULL;
+ null_rejecting_conds= NULL;
#ifdef HAVE_REPLICATION
/* used in RBR Triggers */
master_had_triggers= 0;
diff --git a/sql/table.h b/sql/table.h
index 32e99db880f..9496aef046d 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1354,6 +1354,12 @@ struct TABLE
SplM_opt_info *spl_opt_info;
key_map keys_usable_for_splitting;
+ /*
+ Null rejecting conds added for all tables so we can do range analysis
+ on these conditions
+ */
+ Item* null_rejecting_conds;
+
void init(THD *thd, TABLE_LIST *tl);
bool fill_item_list(List<Item> *item_list) const;
void reset_item_list(List<Item> *item_list, uint skip) const;
1
0

[Commits] 331034cb6e1: MDEV-11975: SQLCOM_PREPARE of EXPLAIN & ANALYZE statement do not return correct metadata info
by Oleksandr Byelkin 20 Apr '18
by Oleksandr Byelkin 20 Apr '18
20 Apr '18
revision-id: 331034cb6e1552e1ab7c12b6f7341f557f76b807 (mariadb-10.3.6-16-g331034cb6e1)
parent(s): cff60be7fe159fdcb2517ce8441610ad512aa7d0
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-04-20 14:40:14 +0200
message:
MDEV-11975: SQLCOM_PREPARE of EXPLAIN & ANALYZE statement do not return correct metadata info
Added metadate info after prepare EXPLAIN/ANALYZE.
---
mysql-test/main/mysql_client_test.result | 122 ++++++++++++
mysql-test/main/mysql_client_test.test | 7 +
sql/sql_class.cc | 30 ++-
sql/sql_class.h | 2 +
sql/sql_prepare.cc | 24 ++-
tests/mysql_client_test.c | 323 +++++++++++++++++++++++++++++++
6 files changed, 498 insertions(+), 10 deletions(-)
diff --git a/mysql-test/main/mysql_client_test.result b/mysql-test/main/mysql_client_test.result
index 83ef8d442b3..6f65979517b 100644
--- a/mysql-test/main/mysql_client_test.result
+++ b/mysql-test/main/mysql_client_test.result
@@ -122,5 +122,127 @@ EOF
mysql_stmt_next_result(): 0; field_count: 0
# ------------------------------------
+
+# cat MYSQL_TMP_DIR/test_explain_meta.out.log
+# ------------------------------------
+SELECT number of fields: 1
+EXPALIN number of fields: 10
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+EXPALIN JSON number of fields: 1
+ - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+ANALYZE number of fields: 13
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
+ - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+ANALYZE JSON number of fields: 1
+ - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+EXPALIN INSERT number of fields: 10
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+EXPALIN JSON INSERT number of fields: 1
+ - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+ANALYZE INSERT number of fields: 13
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
+ - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+ANALYZE JSON INSERT number of fields: 1
+ - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+EXPALIN UPDATE number of fields: 10
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+EXPALIN JSON UPDATE number of fields: 1
+ - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+ANALYZE UPDATE number of fields: 13
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
+ - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+ANALYZE JSON UPDATE number of fields: 1
+ - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+EXPALIN DELETE number of fields: 10
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+EXPALIN JSON DELETE number of fields: 1
+ - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+ANALYZE DELETE number of fields: 13
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
+ - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+ANALYZE JSON DELETE number of fields: 1
+ - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+# ------------------------------------
+
SET @@global.general_log= @old_general_log;
SET @@global.slow_query_log= @old_slow_query_log;
diff --git a/mysql-test/main/mysql_client_test.test b/mysql-test/main/mysql_client_test.test
index 260473aa0d0..2c6febd8ffa 100644
--- a/mysql-test/main/mysql_client_test.test
+++ b/mysql-test/main/mysql_client_test.test
@@ -29,5 +29,12 @@ echo ok;
--echo # ------------------------------------
--echo
+--echo
+--echo # cat MYSQL_TMP_DIR/test_explain_meta.out.log
+--echo # ------------------------------------
+--cat_file $MYSQL_TMP_DIR/test_explain_meta.out.log
+--echo # ------------------------------------
+--echo
+
SET @@global.general_log= @old_general_log;
SET @@global.slow_query_log= @old_slow_query_log;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 96485ed15ec..0ec95e11829 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2659,18 +2659,32 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, size_t key_length)
}
-int THD::send_explain_fields(select_result *result, uint8 explain_flags, bool is_analyze)
+void THD::prepare_explain_fields(select_result *result,
+ List<Item> *field_list,
+ uint8 explain_flags,
+ bool is_analyze)
{
- List<Item> field_list;
+ ;
if (lex->explain_json)
- make_explain_json_field_list(field_list, is_analyze);
+ make_explain_json_field_list(*field_list, is_analyze);
else
- make_explain_field_list(field_list, explain_flags, is_analyze);
+ make_explain_field_list(*field_list, explain_flags, is_analyze);
+
+ result->prepare(*field_list, NULL);
+}
- result->prepare(field_list, NULL);
- return (result->send_result_set_metadata(field_list,
- Protocol::SEND_NUM_ROWS |
- Protocol::SEND_EOF));
+
+int THD::send_explain_fields(select_result *result,
+ uint8 explain_flags,
+ bool is_analyze)
+{
+ List<Item> field_list;
+ int rc;
+ prepare_explain_fields(result, &field_list, explain_flags, is_analyze);
+ rc= result->send_result_set_metadata(field_list,
+ Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF);
+ return(rc);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a7c33cbc504..67bcb639954 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3738,6 +3738,8 @@ class THD :public Statement,
void add_changed_table(TABLE *table);
void add_changed_table(const char *key, size_t key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, size_t key_length);
+ void prepare_explain_fields(select_result *result, List<Item> *field_list,
+ uint8 explain_flags, bool is_analyze);
int send_explain_fields(select_result *result, uint8 explain_flags,
bool is_analyze);
void make_explain_field_list(List<Item> &field_list, uint8 explain_flags,
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 24f3cc66c6b..e37c2006cc6 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2500,8 +2500,28 @@ static bool check_prepared_statement(Prepared_statement *stmt)
break;
}
if (res == 0)
- DBUG_RETURN(stmt->is_sql_prepare() ?
- FALSE : (send_prep_stmt(stmt, 0) || thd->protocol->flush()));
+ {
+ if (!stmt->is_sql_prepare())
+ {
+ if (lex->describe || lex->analyze_stmt)
+ {
+ if (!lex->result &&
+ !(lex->result= new (stmt->mem_root) select_send(thd)))
+ DBUG_RETURN(TRUE);
+ List<Item> field_list;
+ thd->prepare_explain_fields(lex->result, &field_list,
+ lex->describe, lex->analyze_stmt);
+ res= send_prep_stmt(stmt, lex->result->field_count(field_list)) ||
+ lex->result->send_result_set_metadata(field_list,
+ Protocol::SEND_EOF);
+ }
+ else
+ res= send_prep_stmt(stmt, 0);
+ if (!res)
+ thd->protocol->flush();
+ }
+ DBUG_RETURN(FALSE);
+ }
error:
DBUG_RETURN(TRUE);
}
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index e90453411cb..ae4b2ead99d 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -1056,6 +1056,7 @@ static void test_wl4435_2()
rc= mysql_query(mysql, "DROP PROCEDURE p1");
myquery(rc);
}
+ mct_close_log();
}
@@ -20238,6 +20239,327 @@ static void test_proxy_header()
#endif
+
+static void print_metadata(MYSQL_RES *rs_metadata, int num_fields)
+{
+ MYSQL_FIELD *fields= mysql_fetch_fields(rs_metadata);
+
+ for (int i = 0; i < num_fields; ++i)
+ {
+ mct_log(" - %d: name: '%s'/'%s'; table: '%s'/'%s'; "
+ "db: '%s'; catalog: '%s'; length: %d; max_length: %d; "
+ "type: %d; decimals: %d\n",
+ (int) i,
+ (const char *) fields[i].name,
+ (const char *) fields[i].org_name,
+ (const char *) fields[i].table,
+ (const char *) fields[i].org_table,
+ (const char *) fields[i].db,
+ (const char *) fields[i].catalog,
+ (int) fields[i].length,
+ (int) fields[i].max_length,
+ (int) fields[i].type,
+ (int) fields[i].decimals);
+
+ }
+}
+
+static void test_explain_meta()
+{
+ MYSQL_STMT *stmt;
+ int num_fields;
+ char query[MAX_TEST_QUERY_LENGTH];
+ MYSQL_RES *rs_metadata;
+ int rc;
+
+ myheader("test_explain_meta");
+ mct_start_logging("test_explain_meta");
+
+ strmov(query, "SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("SELECT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN number of fields: %d\n", (int) num_fields);
+ if (num_fields != 10)
+ {
+ mct_close_log();
+ DIE("num_fields != 10");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN format=json SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN JSON number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "ANALYZE SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 13)
+ {
+ mct_close_log();
+ DIE("num_fields != 13");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "ANALYZE format=json SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE JSON number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ myquery(rc);
+
+ strmov(query, "EXPLAIN INSERT INTO t1 values (1)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN INSERT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 10)
+ {
+ mct_close_log();
+ DIE("num_fields != 10");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN format=json INSERT INTO t1 values(1)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN JSON INSERT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "ANALYZE INSERT INTO t1 values(1)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE INSERT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 13)
+ {
+ mct_close_log();
+ DIE("num_fields != 13");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "ANALYZE format=json INSERT INTO t1 values(1)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE JSON INSERT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "EXPLAIN UPDATE t1 set a=2");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN UPDATE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 10)
+ {
+ mct_close_log();
+ DIE("num_fields != 10");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN format=json UPDATE t1 set a=2");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN JSON UPDATE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "ANALYZE UPDATE t1 set a=2");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE UPDATE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 13)
+ {
+ mct_close_log();
+ DIE("num_fields != 13");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "ANALYZE format=json UPDATE t1 set a=2");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE JSON UPDATE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "EXPLAIN DELETE FROM t1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN DELETE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 10)
+ {
+ mct_close_log();
+ DIE("num_fields != 10");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN format=json DELETE FROM t1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN JSON DELETE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "ANALYZE DELETE FROM t1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE DELETE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 13)
+ {
+ mct_close_log();
+ DIE("num_fields != 13");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "ANALYZE format=json DELETE FROM t1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE JSON DELETE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+ mct_close_log();
+}
+
static struct my_tests_st my_tests[]= {
{ "disable_query_logs", disable_query_logs },
{ "test_view_sp_list_fields", test_view_sp_list_fields },
@@ -20524,6 +20846,7 @@ static struct my_tests_st my_tests[]= {
#ifndef EMBEDDED_LIBRARY
{ "test_proxy_header", test_proxy_header},
#endif
+ { "test_explain_meta", test_explain_meta },
{ 0, 0 }
};
1
0

[Commits] 331034cb6e1: MDEV-11975: SQLCOM_PREPARE of EXPLAIN & ANALYZE statement do not return correct metadata info
by Oleksandr Byelkin 20 Apr '18
by Oleksandr Byelkin 20 Apr '18
20 Apr '18
revision-id: 331034cb6e1552e1ab7c12b6f7341f557f76b807 (mariadb-10.3.6-16-g331034cb6e1)
parent(s): cff60be7fe159fdcb2517ce8441610ad512aa7d0
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-04-20 14:40:14 +0200
message:
MDEV-11975: SQLCOM_PREPARE of EXPLAIN & ANALYZE statement do not return correct metadata info
Added metadate info after prepare EXPLAIN/ANALYZE.
---
mysql-test/main/mysql_client_test.result | 122 ++++++++++++
mysql-test/main/mysql_client_test.test | 7 +
sql/sql_class.cc | 30 ++-
sql/sql_class.h | 2 +
sql/sql_prepare.cc | 24 ++-
tests/mysql_client_test.c | 323 +++++++++++++++++++++++++++++++
6 files changed, 498 insertions(+), 10 deletions(-)
diff --git a/mysql-test/main/mysql_client_test.result b/mysql-test/main/mysql_client_test.result
index 83ef8d442b3..6f65979517b 100644
--- a/mysql-test/main/mysql_client_test.result
+++ b/mysql-test/main/mysql_client_test.result
@@ -122,5 +122,127 @@ EOF
mysql_stmt_next_result(): 0; field_count: 0
# ------------------------------------
+
+# cat MYSQL_TMP_DIR/test_explain_meta.out.log
+# ------------------------------------
+SELECT number of fields: 1
+EXPALIN number of fields: 10
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+EXPALIN JSON number of fields: 1
+ - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+ANALYZE number of fields: 13
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
+ - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+ANALYZE JSON number of fields: 1
+ - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+EXPALIN INSERT number of fields: 10
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+EXPALIN JSON INSERT number of fields: 1
+ - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+ANALYZE INSERT number of fields: 13
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
+ - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+ANALYZE JSON INSERT number of fields: 1
+ - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+EXPALIN UPDATE number of fields: 10
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+EXPALIN JSON UPDATE number of fields: 1
+ - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+ANALYZE UPDATE number of fields: 13
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
+ - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+ANALYZE JSON UPDATE number of fields: 1
+ - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+EXPALIN DELETE number of fields: 10
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+EXPALIN JSON DELETE number of fields: 1
+ - 0: name: 'EXPLAIN'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+ANALYZE DELETE number of fields: 13
+ - 0: name: 'id'/''; table: ''/''; db: ''; catalog: 'def'; length: 3; max_length: 0; type: 8; decimals: 0
+ - 1: name: 'select_type'/''; table: ''/''; db: ''; catalog: 'def'; length: 57; max_length: 0; type: 253; decimals: 39
+ - 2: name: 'table'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 3: name: 'type'/''; table: ''/''; db: ''; catalog: 'def'; length: 30; max_length: 0; type: 253; decimals: 39
+ - 4: name: 'possible_keys'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 5: name: 'key'/''; table: ''/''; db: ''; catalog: 'def'; length: 192; max_length: 0; type: 253; decimals: 39
+ - 6: name: 'key_len'/''; table: ''/''; db: ''; catalog: 'def'; length: 12288; max_length: 0; type: 253; decimals: 39
+ - 7: name: 'ref'/''; table: ''/''; db: ''; catalog: 'def'; length: 6144; max_length: 0; type: 253; decimals: 39
+ - 8: name: 'rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 10; max_length: 0; type: 8; decimals: 0
+ - 9: name: 'r_rows'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 10
+ - 10: name: 'filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 11: name: 'r_filtered'/''; table: ''/''; db: ''; catalog: 'def'; length: 4; max_length: 0; type: 5; decimals: 2
+ - 12: name: 'Extra'/''; table: ''/''; db: ''; catalog: 'def'; length: 765; max_length: 0; type: 253; decimals: 39
+ANALYZE JSON DELETE number of fields: 1
+ - 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
+# ------------------------------------
+
SET @@global.general_log= @old_general_log;
SET @@global.slow_query_log= @old_slow_query_log;
diff --git a/mysql-test/main/mysql_client_test.test b/mysql-test/main/mysql_client_test.test
index 260473aa0d0..2c6febd8ffa 100644
--- a/mysql-test/main/mysql_client_test.test
+++ b/mysql-test/main/mysql_client_test.test
@@ -29,5 +29,12 @@ echo ok;
--echo # ------------------------------------
--echo
+--echo
+--echo # cat MYSQL_TMP_DIR/test_explain_meta.out.log
+--echo # ------------------------------------
+--cat_file $MYSQL_TMP_DIR/test_explain_meta.out.log
+--echo # ------------------------------------
+--echo
+
SET @@global.general_log= @old_general_log;
SET @@global.slow_query_log= @old_slow_query_log;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 96485ed15ec..0ec95e11829 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2659,18 +2659,32 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, size_t key_length)
}
-int THD::send_explain_fields(select_result *result, uint8 explain_flags, bool is_analyze)
+void THD::prepare_explain_fields(select_result *result,
+ List<Item> *field_list,
+ uint8 explain_flags,
+ bool is_analyze)
{
- List<Item> field_list;
+ ;
if (lex->explain_json)
- make_explain_json_field_list(field_list, is_analyze);
+ make_explain_json_field_list(*field_list, is_analyze);
else
- make_explain_field_list(field_list, explain_flags, is_analyze);
+ make_explain_field_list(*field_list, explain_flags, is_analyze);
+
+ result->prepare(*field_list, NULL);
+}
- result->prepare(field_list, NULL);
- return (result->send_result_set_metadata(field_list,
- Protocol::SEND_NUM_ROWS |
- Protocol::SEND_EOF));
+
+int THD::send_explain_fields(select_result *result,
+ uint8 explain_flags,
+ bool is_analyze)
+{
+ List<Item> field_list;
+ int rc;
+ prepare_explain_fields(result, &field_list, explain_flags, is_analyze);
+ rc= result->send_result_set_metadata(field_list,
+ Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF);
+ return(rc);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a7c33cbc504..67bcb639954 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3738,6 +3738,8 @@ class THD :public Statement,
void add_changed_table(TABLE *table);
void add_changed_table(const char *key, size_t key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, size_t key_length);
+ void prepare_explain_fields(select_result *result, List<Item> *field_list,
+ uint8 explain_flags, bool is_analyze);
int send_explain_fields(select_result *result, uint8 explain_flags,
bool is_analyze);
void make_explain_field_list(List<Item> &field_list, uint8 explain_flags,
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 24f3cc66c6b..e37c2006cc6 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -2500,8 +2500,28 @@ static bool check_prepared_statement(Prepared_statement *stmt)
break;
}
if (res == 0)
- DBUG_RETURN(stmt->is_sql_prepare() ?
- FALSE : (send_prep_stmt(stmt, 0) || thd->protocol->flush()));
+ {
+ if (!stmt->is_sql_prepare())
+ {
+ if (lex->describe || lex->analyze_stmt)
+ {
+ if (!lex->result &&
+ !(lex->result= new (stmt->mem_root) select_send(thd)))
+ DBUG_RETURN(TRUE);
+ List<Item> field_list;
+ thd->prepare_explain_fields(lex->result, &field_list,
+ lex->describe, lex->analyze_stmt);
+ res= send_prep_stmt(stmt, lex->result->field_count(field_list)) ||
+ lex->result->send_result_set_metadata(field_list,
+ Protocol::SEND_EOF);
+ }
+ else
+ res= send_prep_stmt(stmt, 0);
+ if (!res)
+ thd->protocol->flush();
+ }
+ DBUG_RETURN(FALSE);
+ }
error:
DBUG_RETURN(TRUE);
}
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index e90453411cb..ae4b2ead99d 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -1056,6 +1056,7 @@ static void test_wl4435_2()
rc= mysql_query(mysql, "DROP PROCEDURE p1");
myquery(rc);
}
+ mct_close_log();
}
@@ -20238,6 +20239,327 @@ static void test_proxy_header()
#endif
+
+static void print_metadata(MYSQL_RES *rs_metadata, int num_fields)
+{
+ MYSQL_FIELD *fields= mysql_fetch_fields(rs_metadata);
+
+ for (int i = 0; i < num_fields; ++i)
+ {
+ mct_log(" - %d: name: '%s'/'%s'; table: '%s'/'%s'; "
+ "db: '%s'; catalog: '%s'; length: %d; max_length: %d; "
+ "type: %d; decimals: %d\n",
+ (int) i,
+ (const char *) fields[i].name,
+ (const char *) fields[i].org_name,
+ (const char *) fields[i].table,
+ (const char *) fields[i].org_table,
+ (const char *) fields[i].db,
+ (const char *) fields[i].catalog,
+ (int) fields[i].length,
+ (int) fields[i].max_length,
+ (int) fields[i].type,
+ (int) fields[i].decimals);
+
+ }
+}
+
+static void test_explain_meta()
+{
+ MYSQL_STMT *stmt;
+ int num_fields;
+ char query[MAX_TEST_QUERY_LENGTH];
+ MYSQL_RES *rs_metadata;
+ int rc;
+
+ myheader("test_explain_meta");
+ mct_start_logging("test_explain_meta");
+
+ strmov(query, "SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("SELECT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN number of fields: %d\n", (int) num_fields);
+ if (num_fields != 10)
+ {
+ mct_close_log();
+ DIE("num_fields != 10");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN format=json SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN JSON number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "ANALYZE SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 13)
+ {
+ mct_close_log();
+ DIE("num_fields != 13");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "ANALYZE format=json SELECT 1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE JSON number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "CREATE TABLE t1 (a int)");
+ myquery(rc);
+
+ strmov(query, "EXPLAIN INSERT INTO t1 values (1)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN INSERT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 10)
+ {
+ mct_close_log();
+ DIE("num_fields != 10");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN format=json INSERT INTO t1 values(1)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN JSON INSERT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "ANALYZE INSERT INTO t1 values(1)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE INSERT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 13)
+ {
+ mct_close_log();
+ DIE("num_fields != 13");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "ANALYZE format=json INSERT INTO t1 values(1)");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE JSON INSERT number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "EXPLAIN UPDATE t1 set a=2");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN UPDATE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 10)
+ {
+ mct_close_log();
+ DIE("num_fields != 10");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN format=json UPDATE t1 set a=2");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN JSON UPDATE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "ANALYZE UPDATE t1 set a=2");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE UPDATE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 13)
+ {
+ mct_close_log();
+ DIE("num_fields != 13");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "ANALYZE format=json UPDATE t1 set a=2");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE JSON UPDATE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "EXPLAIN DELETE FROM t1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN DELETE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 10)
+ {
+ mct_close_log();
+ DIE("num_fields != 10");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "EXPLAIN format=json DELETE FROM t1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("EXPALIN JSON DELETE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+
+ strmov(query, "ANALYZE DELETE FROM t1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE DELETE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 13)
+ {
+ mct_close_log();
+ DIE("num_fields != 13");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ strmov(query, "ANALYZE format=json DELETE FROM t1");
+ stmt= mysql_simple_prepare(mysql, query);
+ check_stmt(stmt);
+
+ rs_metadata= mysql_stmt_result_metadata(stmt);
+
+ num_fields= mysql_stmt_field_count(stmt);
+ mct_log("ANALYZE JSON DELETE number of fields: %d\n", (int) num_fields);
+ if (num_fields != 1)
+ {
+ mct_close_log();
+ DIE("num_fields != 1");
+ }
+ print_metadata(rs_metadata, num_fields);
+ mysql_stmt_close(stmt);
+
+ rc= mysql_query(mysql, "DROP TABLE t1");
+ myquery(rc);
+ mct_close_log();
+}
+
static struct my_tests_st my_tests[]= {
{ "disable_query_logs", disable_query_logs },
{ "test_view_sp_list_fields", test_view_sp_list_fields },
@@ -20524,6 +20846,7 @@ static struct my_tests_st my_tests[]= {
#ifndef EMBEDDED_LIBRARY
{ "test_proxy_header", test_proxy_header},
#endif
+ { "test_explain_meta", test_explain_meta },
{ 0, 0 }
};
1
0
revision-id: b810b210d28329354365391135a3c5c465ad5f8b (mariadb-10.3.6-17-gb810b210d28)
parent(s): 346c8ab9533a3de6a4cb348428402ffee2aa8da2
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-04-20 14:39:57 +0200
message:
postreview fix
---
mysql-test/main/mysql_client_test.result | 2 +-
mysql-test/main/mysql_client_test.test | 4 +++-
sql/sql_class.cc | 36 ++++++++++++++++++--------------
sql/sql_class.h | 5 +++--
sql/sql_explain.cc | 3 +--
sql/sql_parse.cc | 5 ++---
sql/sql_prepare.cc | 12 +++++++----
sql/sql_prepare.h | 2 --
tests/mysql_client_test.c | 2 ++
9 files changed, 40 insertions(+), 31 deletions(-)
diff --git a/mysql-test/main/mysql_client_test.result b/mysql-test/main/mysql_client_test.result
index 20385acfa00..6f65979517b 100644
--- a/mysql-test/main/mysql_client_test.result
+++ b/mysql-test/main/mysql_client_test.result
@@ -122,6 +122,7 @@ EOF
mysql_stmt_next_result(): 0; field_count: 0
# ------------------------------------
+
# cat MYSQL_TMP_DIR/test_explain_meta.out.log
# ------------------------------------
SELECT number of fields: 1
@@ -243,6 +244,5 @@ ANALYZE JSON DELETE number of fields: 1
- 0: name: 'ANALYZE'/''; table: ''/''; db: ''; catalog: 'def'; length: 234; max_length: 0; type: 253; decimals: 39
# ------------------------------------
-
SET @@global.general_log= @old_general_log;
SET @@global.slow_query_log= @old_slow_query_log;
diff --git a/mysql-test/main/mysql_client_test.test b/mysql-test/main/mysql_client_test.test
index 79ad9f84477..2c6febd8ffa 100644
--- a/mysql-test/main/mysql_client_test.test
+++ b/mysql-test/main/mysql_client_test.test
@@ -27,12 +27,14 @@ echo ok;
--echo # ------------------------------------
--cat_file $MYSQL_TMP_DIR/test_wl4435.out.log
--echo # ------------------------------------
+--echo
+
--echo
--echo # cat MYSQL_TMP_DIR/test_explain_meta.out.log
--echo # ------------------------------------
--cat_file $MYSQL_TMP_DIR/test_explain_meta.out.log
--echo # ------------------------------------
--echo
---echo
+
SET @@global.general_log= @old_general_log;
SET @@global.slow_query_log= @old_slow_query_log;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 349ec576264..0ec95e11829 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -69,7 +69,6 @@
#include "wsrep_thd.h"
#include "sql_connect.h"
#include "my_atomic.h"
-#include "sql_prepare.h"
#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
@@ -2660,26 +2659,31 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, size_t key_length)
}
+void THD::prepare_explain_fields(select_result *result,
+ List<Item> *field_list,
+ uint8 explain_flags,
+ bool is_analyze)
+{
+ ;
+ if (lex->explain_json)
+ make_explain_json_field_list(*field_list, is_analyze);
+ else
+ make_explain_field_list(*field_list, explain_flags, is_analyze);
+
+ result->prepare(*field_list, NULL);
+}
+
+
int THD::send_explain_fields(select_result *result,
uint8 explain_flags,
- bool is_analyze,
- Prepared_statement *stmt)
+ bool is_analyze)
{
List<Item> field_list;
int rc;
- if (lex->explain_json)
- make_explain_json_field_list(field_list, is_analyze);
- else
- make_explain_field_list(field_list, explain_flags, is_analyze);
-
- result->prepare(field_list, NULL);
- if (stmt)
- rc= send_prep_stmt(stmt, result->field_count(field_list)) ||
- result->send_result_set_metadata(field_list, Protocol::SEND_EOF);
- else
- rc= result->send_result_set_metadata(field_list,
- Protocol::SEND_NUM_ROWS |
- Protocol::SEND_EOF);
+ prepare_explain_fields(result, &field_list, explain_flags, is_analyze);
+ rc= result->send_result_set_metadata(field_list,
+ Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF);
return(rc);
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 706b72d9d06..67bcb639954 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -2174,7 +2174,6 @@ struct QUERY_START_TIME_INFO
extern "C" void my_message_sql(uint error, const char *str, myf MyFlags);
-class Prepared_statement;
/**
@class THD
For each client connection we create a separate thread with THD serving as
@@ -3739,8 +3738,10 @@ class THD :public Statement,
void add_changed_table(TABLE *table);
void add_changed_table(const char *key, size_t key_length);
CHANGED_TABLE_LIST * changed_table_dup(const char *key, size_t key_length);
+ void prepare_explain_fields(select_result *result, List<Item> *field_list,
+ uint8 explain_flags, bool is_analyze);
int send_explain_fields(select_result *result, uint8 explain_flags,
- bool is_analyze, Prepared_statement *stmt);
+ bool is_analyze);
void make_explain_field_list(List<Item> &field_list, uint8 explain_flags,
bool is_analyze);
void make_explain_json_field_list(List<Item> &field_list, bool is_analyze);
diff --git a/sql/sql_explain.cc b/sql/sql_explain.cc
index 96374fc1a33..5d977c6d5c2 100644
--- a/sql/sql_explain.cc
+++ b/sql/sql_explain.cc
@@ -164,8 +164,7 @@ int Explain_query::send_explain(THD *thd)
LEX *lex= thd->lex;
if (!(result= new (thd->mem_root) select_send(thd)) ||
- thd->send_explain_fields(result, lex->describe, lex->analyze_stmt,
- NULL))
+ thd->send_explain_fields(result, lex->describe, lex->analyze_stmt))
return 1;
int res= 0;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index fa8279d9d6f..2593bac7462 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6469,9 +6469,8 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
*/
if (!(result= new (thd->mem_root) select_send(thd)))
return 1; /* purecov: inspected */
- thd->send_explain_fields(result, lex->describe, lex->analyze_stmt,
- NULL);
-
+ thd->send_explain_fields(result, lex->describe, lex->analyze_stmt);
+
/*
This will call optimize() for all parts of query. The query plan is
printed out below.
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index b9016e72410..e37c2006cc6 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -356,7 +356,7 @@ find_prepared_statement(THD *thd, ulong id)
*/
#ifndef EMBEDDED_LIBRARY
-bool send_prep_stmt(Prepared_statement *stmt, uint columns)
+static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
{
NET *net= &stmt->thd->net;
uchar buff[12];
@@ -394,7 +394,7 @@ bool send_prep_stmt(Prepared_statement *stmt, uint columns)
DBUG_RETURN(error);
}
#else
-bool send_prep_stmt(Prepared_statement *stmt,
+static bool send_prep_stmt(Prepared_statement *stmt,
uint columns __attribute__((unused)))
{
THD *thd= stmt->thd;
@@ -2508,8 +2508,12 @@ static bool check_prepared_statement(Prepared_statement *stmt)
if (!lex->result &&
!(lex->result= new (stmt->mem_root) select_send(thd)))
DBUG_RETURN(TRUE);
- res= thd->send_explain_fields(lex->result, lex->describe,
- lex->analyze_stmt, stmt);
+ List<Item> field_list;
+ thd->prepare_explain_fields(lex->result, &field_list,
+ lex->describe, lex->analyze_stmt);
+ res= send_prep_stmt(stmt, lex->result->field_count(field_list)) ||
+ lex->result->send_result_set_metadata(field_list,
+ Protocol::SEND_EOF);
}
else
res= send_prep_stmt(stmt, 0);
diff --git a/sql/sql_prepare.h b/sql/sql_prepare.h
index ce6d9df22d0..ca040da341f 100644
--- a/sql/sql_prepare.h
+++ b/sql/sql_prepare.h
@@ -83,8 +83,6 @@ void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length);
void mysqld_stmt_reset(THD *thd, char *packet);
void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length);
void reinit_stmt_before_use(THD *thd, LEX *lex);
-class Prepared_statement;
-bool send_prep_stmt(Prepared_statement *stmt, uint columns);
my_bool bulk_parameters_iterations(THD *thd);
my_bool bulk_parameters_set(THD *thd);
diff --git a/tests/mysql_client_test.c b/tests/mysql_client_test.c
index b2177c660de..ae4b2ead99d 100644
--- a/tests/mysql_client_test.c
+++ b/tests/mysql_client_test.c
@@ -20236,8 +20236,10 @@ static void test_proxy_header()
test_proxy_header_localhost();
test_proxy_header_ignore();
}
+
#endif
+
static void print_metadata(MYSQL_RES *rs_metadata, int num_fields)
{
MYSQL_FIELD *fields= mysql_fetch_fields(rs_metadata);
1
0

[Commits] c15b617: MDEV-15902 Assertion `n < m_size' failed, sql_array.h:64:
by IgorBabaev 20 Apr '18
by IgorBabaev 20 Apr '18
20 Apr '18
revision-id: c15b6170bbd59d6763ebba085e34c1ce864427f0 (mariadb-10.3.6-16-gc15b617)
parent(s): cff60be7fe159fdcb2517ce8441610ad512aa7d0
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-04-19 18:40:31 -0700
message:
MDEV-15902 Assertion `n < m_size' failed, sql_array.h:64:
Element_type& Bounds_checked_array<Element_type>::operator[]
(size_t) [with Element_type = Item*; size_t = long unsigned int]
In sql_yacc.yy the semantic actions for the MEDIAN window function
lacked a call of st_select_lex::prepare_add_window_spec().
This function saves the head of the thd->lex->order_list into
lex->save_order_list in order this head to be restored in
st_select_lex::add_window_spec after the specification of the
window function has been parsed.
Without a call of prepare_add_window_spec() when add_window_spec()
was called the head of an empty list was copied into
thd->lex->order_list (instead of assumed saved head this list).
This made the list thd->lex->order_list invalid and potentially
could cause many different problems.
Corrected the result set in the test case for MDEV-15899 that
used the MEDIAN window function and could not be correct
without this fix.
---
mysql-test/main/derived_cond_pushdown.result | 44 ++++++++++++++--------------
mysql-test/main/win_percentile.result | 15 ++++++++++
mysql-test/main/win_percentile.test | 15 ++++++++++
sql/sql_yacc.yy | 3 +-
4 files changed, 54 insertions(+), 23 deletions(-)
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 1b7aeda..82f621c 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -15130,31 +15130,31 @@ cte as (select median(f2) over (partition by f1) as k1 from t1 order by f1),
cte1 as (select median(f4) over (partition by f1) as k2 from t1)
select k1,k2 from cte1, cte;
k1 k2
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
+1.0000000000 9.0000000000
+1.0000000000 9.0000000000
1.0000000000 8.0000000000
-1.0000000000 8.0000000000
-1.0000000000 8.0000000000
-1.0000000000 8.0000000000
-1.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
+1.0000000000 0.0000000000
+1.0000000000 9.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
0.0000000000 8.0000000000
+0.0000000000 0.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
0.0000000000 8.0000000000
+0.0000000000 0.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
0.0000000000 8.0000000000
+0.0000000000 0.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
0.0000000000 8.0000000000
+0.0000000000 0.0000000000
+0.0000000000 9.0000000000
explain with
cte as (select median(f2) over (partition by f1) as k1 from t1 order by f1),
cte1 as (select median(f4) over (partition by f1) as k2 from t1)
@@ -15162,6 +15162,6 @@ select k1,k2 from cte1, cte;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 5
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
-3 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
-2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary
+3 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
drop table t1;
diff --git a/mysql-test/main/win_percentile.result b/mysql-test/main/win_percentile.result
index c51e2e6..d1b205e 100644
--- a/mysql-test/main/win_percentile.result
+++ b/mysql-test/main/win_percentile.result
@@ -324,3 +324,18 @@ median(score) over (partition by name) c
4.0000000000 4.0000000000
4.0000000000 4.0000000000
drop table t1;
+#
+# MDEV-13352: MEDIAN window function over a table with virtual column
+# in select with CTE and ORDER BY
+#
+CREATE TABLE t1 (f1 int ,f2 int ,f3 int, f4 int, v1 int AS (-f4) virtual);
+INSERT INTO t1(f1,f2,f3,f4) VALUES
+(1,10,100,10), (7,11,112,15), (3,14,121,12);
+WITH CTE AS (SELECT MIN(f3) OVER () FROM t1)
+SELECT MEDIAN(f3) OVER () FROM t1
+ORDER BY f1, f2, f3, f4, v1;
+MEDIAN(f3) OVER ()
+112.0000000000
+112.0000000000
+112.0000000000
+DROP TABLE t1;
diff --git a/mysql-test/main/win_percentile.test b/mysql-test/main/win_percentile.test
index 468d8cf..233b21d 100644
--- a/mysql-test/main/win_percentile.test
+++ b/mysql-test/main/win_percentile.test
@@ -102,3 +102,18 @@ select median(score) over (partition by name), percentile_cont(0.8) within grou
select median(score) over (partition by name), percentile_cont(0.9) within group(order by score) over (partition by name) as c from t1;
select median(score) over (partition by name), percentile_cont(1) within group(order by score) over (partition by name) as c from t1;
drop table t1;
+
+--echo #
+--echo # MDEV-13352: MEDIAN window function over a table with virtual column
+--echo # in select with CTE and ORDER BY
+--echo #
+
+CREATE TABLE t1 (f1 int ,f2 int ,f3 int, f4 int, v1 int AS (-f4) virtual);
+INSERT INTO t1(f1,f2,f3,f4) VALUES
+ (1,10,100,10), (7,11,112,15), (3,14,121,12);
+
+WITH CTE AS (SELECT MIN(f3) OVER () FROM t1)
+SELECT MEDIAN(f3) OVER () FROM t1
+ORDER BY f1, f2, f3, f4, v1;
+
+DROP TABLE t1;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d69156c..93704cd 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -11257,10 +11257,11 @@ percentile_function:
{
Item *args= new (thd->mem_root) Item_decimal(thd, "0.5", 3,
thd->charset());
- if (($$ == NULL) || (thd->is_error()))
+ if ((args == NULL) || (thd->is_error()))
{
MYSQL_YYABORT;
}
+ Select->prepare_add_window_spec(thd);
if (add_order_to_list(thd, $3,FALSE)) MYSQL_YYABORT;
$$= new (thd->mem_root) Item_sum_percentile_cont(thd, args);
1
0

[Commits] 6373c85: MDEV-15902 Assertion `n < m_size' failed, sql_array.h:64:
by IgorBabaev 20 Apr '18
by IgorBabaev 20 Apr '18
20 Apr '18
revision-id: 6373c8599004e15a6e23816302de9ca310787111 (mariadb-10.3.6-16-g6373c85)
parent(s): cff60be7fe159fdcb2517ce8441610ad512aa7d0
author: Igor Babaev
committer: Igor Babaev
timestamp: 2018-04-19 18:35:03 -0700
message:
MDEV-15902 Assertion `n < m_size' failed, sql_array.h:64:
Element_type& Bounds_checked_array<Element_type>::operator[]
(size_t) [with Element_type = Item*; size_t = long unsigned int]
In sql_yacc.yy the semantic actions for the MEDIAN window function
lacked a call of st_select_lex::prepare_add_window_spec().
This function saves the head of the thd->lex->order_list into
lex->save_order_list in order this head to be restored in
st_select_lex::add_window_spec after the specification of the
window function has been parsed.
Without a call of prepare_add_window_spec() when add_window_spec()
was called the head of an empty list was copied into
thd->lex->order_list (instead of assumed saved head this list).
This made the list thd->lex->order_list invalid and potentially
could cause many different problems.
---
mysql-test/main/derived_cond_pushdown.result | 44 ++++++++++++++--------------
mysql-test/main/win_percentile.result | 15 ++++++++++
mysql-test/main/win_percentile.test | 15 ++++++++++
sql/sql_yacc.yy | 3 +-
4 files changed, 54 insertions(+), 23 deletions(-)
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 1b7aeda..82f621c 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -15130,31 +15130,31 @@ cte as (select median(f2) over (partition by f1) as k1 from t1 order by f1),
cte1 as (select median(f4) over (partition by f1) as k2 from t1)
select k1,k2 from cte1, cte;
k1 k2
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
+1.0000000000 9.0000000000
+1.0000000000 9.0000000000
1.0000000000 8.0000000000
-1.0000000000 8.0000000000
-1.0000000000 8.0000000000
-1.0000000000 8.0000000000
-1.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
-0.0000000000 8.0000000000
+1.0000000000 0.0000000000
+1.0000000000 9.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
0.0000000000 8.0000000000
+0.0000000000 0.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
0.0000000000 8.0000000000
+0.0000000000 0.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
0.0000000000 8.0000000000
+0.0000000000 0.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
+0.0000000000 9.0000000000
0.0000000000 8.0000000000
+0.0000000000 0.0000000000
+0.0000000000 9.0000000000
explain with
cte as (select median(f2) over (partition by f1) as k1 from t1 order by f1),
cte1 as (select median(f4) over (partition by f1) as k2 from t1)
@@ -15162,6 +15162,6 @@ select k1,k2 from cte1, cte;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived3> ALL NULL NULL NULL NULL 5
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 5 Using join buffer (flat, BNL join)
-3 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
-2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary
+3 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
drop table t1;
diff --git a/mysql-test/main/win_percentile.result b/mysql-test/main/win_percentile.result
index c51e2e6..d1b205e 100644
--- a/mysql-test/main/win_percentile.result
+++ b/mysql-test/main/win_percentile.result
@@ -324,3 +324,18 @@ median(score) over (partition by name) c
4.0000000000 4.0000000000
4.0000000000 4.0000000000
drop table t1;
+#
+# MDEV-13352: MEDIAN window function over a table with virtual column
+# in select with CTE and ORDER BY
+#
+CREATE TABLE t1 (f1 int ,f2 int ,f3 int, f4 int, v1 int AS (-f4) virtual);
+INSERT INTO t1(f1,f2,f3,f4) VALUES
+(1,10,100,10), (7,11,112,15), (3,14,121,12);
+WITH CTE AS (SELECT MIN(f3) OVER () FROM t1)
+SELECT MEDIAN(f3) OVER () FROM t1
+ORDER BY f1, f2, f3, f4, v1;
+MEDIAN(f3) OVER ()
+112.0000000000
+112.0000000000
+112.0000000000
+DROP TABLE t1;
diff --git a/mysql-test/main/win_percentile.test b/mysql-test/main/win_percentile.test
index 468d8cf..233b21d 100644
--- a/mysql-test/main/win_percentile.test
+++ b/mysql-test/main/win_percentile.test
@@ -102,3 +102,18 @@ select median(score) over (partition by name), percentile_cont(0.8) within grou
select median(score) over (partition by name), percentile_cont(0.9) within group(order by score) over (partition by name) as c from t1;
select median(score) over (partition by name), percentile_cont(1) within group(order by score) over (partition by name) as c from t1;
drop table t1;
+
+--echo #
+--echo # MDEV-13352: MEDIAN window function over a table with virtual column
+--echo # in select with CTE and ORDER BY
+--echo #
+
+CREATE TABLE t1 (f1 int ,f2 int ,f3 int, f4 int, v1 int AS (-f4) virtual);
+INSERT INTO t1(f1,f2,f3,f4) VALUES
+ (1,10,100,10), (7,11,112,15), (3,14,121,12);
+
+WITH CTE AS (SELECT MIN(f3) OVER () FROM t1)
+SELECT MEDIAN(f3) OVER () FROM t1
+ORDER BY f1, f2, f3, f4, v1;
+
+DROP TABLE t1;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d69156c..93704cd 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -11257,10 +11257,11 @@ percentile_function:
{
Item *args= new (thd->mem_root) Item_decimal(thd, "0.5", 3,
thd->charset());
- if (($$ == NULL) || (thd->is_error()))
+ if ((args == NULL) || (thd->is_error()))
{
MYSQL_YYABORT;
}
+ Select->prepare_add_window_spec(thd);
if (add_order_to_list(thd, $3,FALSE)) MYSQL_YYABORT;
$$= new (thd->mem_root) Item_sum_percentile_cont(thd, args);
1
0

[Commits] 67260fd: MDEV-15130 Assertion `table->s->null_bytes == 0' failed in ...
by sachin 19 Apr '18
by sachin 19 Apr '18
19 Apr '18
revision-id: 67260fd307423b04119bcb4ef1e0bc62fdff4969 (mariadb-10.3.6-22-g67260fd)
parent(s): cd8b8169b6f39450f10f1ba8a16ae68486bc0975
author: Sachin Setiya
committer: Sachin Setiya
timestamp: 2018-04-19 22:57:30 +0530
message:
MDEV-15130 Assertion `table->s->null_bytes == 0' failed in ...
table_setup_timers::read_row_values under 'test_completely_invisible'
Also solves:-
MDEV-15131 Assertion `false' failed in table_setup_actors::read_row_values
upon querying perfschema under 'test_pseudo_invisible'
MDEV-15137 Assertion `f->real_type() == MYSQL_TYPE_VARCHAR' failed in
PFS_engine_table::set_field_varchar_utf8 upon querying perfschema under
'test_completely_invisible'
Performance schema table are created on the fly , when there is query on
perf schema tables, and test_pseudo_invisible debug_dbug flag is on, then
when query calls mysql_prepare_create_table one invisible field is added ,
this crashes the server.
---
mysql-test/main/invisible_field.result | 14 ++++++++++++++
mysql-test/main/invisible_field.test | 21 +++++++++++++++++++++
storage/perfschema/ha_perfschema.cc | 10 ++++++++++
3 files changed, 45 insertions(+)
diff --git a/mysql-test/main/invisible_field.result b/mysql-test/main/invisible_field.result
index 5cea77f..8395789 100644
--- a/mysql-test/main/invisible_field.result
+++ b/mysql-test/main/invisible_field.result
@@ -556,3 +556,17 @@ INSERT INTO t1 (c,t) VALUES ('foo','2000-01-01 00:00:00');
CREATE TRIGGER tr BEFORE INSERT ON t1 FOR EACH ROW SET @a= 1;
INSERT INTO t1 SELECT * FROM t1;
DROP TABLE t1;
+#MDEV-15130
+SET debug_dbug= "+d,test_completely_invisible";
+UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE' WHERE name = 'wait';
+ERROR HY000: Internal error: Don't query performance_schema whentest_completely_invisible is on
+#MDEV-15131
+SET debug_dbug="+d,test_pseudo_invisible";
+SELECT * FROM performance_schema.setup_actors;
+ERROR HY000: Internal error: Don't query performance_schema whentest_pseudo_invisible is on
+#MDEV-15137
+CREATE TABLE t1 (i INT);
+SET debug_dbug= "+d,test_completely_invisible";
+SELECT * FROM performance_schema.events_stages_summary_by_account_by_event_name STRAIGHT_JOIN t1 ON ( i = SUM_TIMER_WAIT );
+ERROR HY000: Internal error: Don't query performance_schema whentest_pseudo_invisible is on
+DROP TABLE t1;
diff --git a/mysql-test/main/invisible_field.test b/mysql-test/main/invisible_field.test
index cfe89d7..53336b8 100644
--- a/mysql-test/main/invisible_field.test
+++ b/mysql-test/main/invisible_field.test
@@ -1,3 +1,5 @@
+--source include/have_perfschema.inc
+
FLUSH STATUS;
create table t1(abc int primary key, xyz int invisible);
SHOW STATUS LIKE 'Feature_invisible_columns';
@@ -246,3 +248,22 @@ CREATE TRIGGER tr BEFORE INSERT ON t1 FOR EACH ROW SET @a= 1;
INSERT INTO t1 SELECT * FROM t1;
# Cleanup
DROP TABLE t1;
+
+--echo #MDEV-15130
+SET debug_dbug= "+d,test_completely_invisible";
+--error ER_INTERNAL_ERROR
+UPDATE performance_schema.setup_timers SET timer_name = 'CYCLE' WHERE name = 'wait';
+
+--echo #MDEV-15131
+SET debug_dbug="+d,test_pseudo_invisible";
+--error ER_INTERNAL_ERROR
+SELECT * FROM performance_schema.setup_actors;
+
+--echo #MDEV-15137
+CREATE TABLE t1 (i INT);
+SET debug_dbug= "+d,test_completely_invisible";
+--error ER_INTERNAL_ERROR
+SELECT * FROM performance_schema.events_stages_summary_by_account_by_event_name STRAIGHT_JOIN t1 ON ( i = SUM_TIMER_WAIT );
+
+# Cleanup
+DROP TABLE t1;
diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc
index e8e9581..d5846f2 100644
--- a/storage/perfschema/ha_perfschema.cc
+++ b/storage/perfschema/ha_perfschema.cc
@@ -64,6 +64,16 @@ static int pfs_discover_table(handlerton *hton, THD *thd, TABLE_SHARE *share)
{
const PFS_engine_table_share *pfs_share;
+ DBUG_EXECUTE_IF("test_pseudo_invisible", {
+ my_error(ER_INTERNAL_ERROR, MYF(0), "Don't query performance_schema when"
+ "test_pseudo_invisible is on");
+ return 1;
+ });
+ DBUG_EXECUTE_IF("test_completely_invisible", {
+ my_error(ER_INTERNAL_ERROR, MYF(0), "Don't query performance_schema when"
+ "test_completely_invisible is on");
+ return 1;
+ });
if ((pfs_share= find_table_share(share->db.str, share->table_name.str)))
return share->init_from_sql_statement_string(thd, false,
pfs_share->sql.str,
1
0

[Commits] d7dae31: MDEV-15167 Server crashes in in bitmap_bits_set upon REPAIR PARTITION...
by sachin 19 Apr '18
by sachin 19 Apr '18
19 Apr '18
revision-id: d7dae3119254776b290dba742d4cb9e2c12ff087 (mariadb-10.3.6-20-gd7dae31)
parent(s): 419385dbf10453b17a370fd9e5bd934d09e0b440
author: Sachin Setiya
committer: Sachin Setiya
timestamp: 2018-04-19 22:11:41 +0530
message:
MDEV-15167 Server crashes in in bitmap_bits_set upon REPAIR PARTITION...
after rebuilding under test_pseudo_invisible
If we are doing alter related to partitioning then simple alter stmt
like adding column(or any alter stmt) can't be combined with partition
alter, this will generate a syntax error.
But IF we add
SET debug_dbug="+d,test_pseudo_invisible";
or test_completely_invisible
this will add a column to table with have an already partitioning related
alter. This execution of wrong stmt will crash the server on later stages.
(like on repair partition).
So we will simply return 1 (and ER_INTERNAL_ERROR) if we any of these
debug_dbug flags turned on.
---
mysql-test/main/invisible_partition.result | 10 ++++++++++
mysql-test/main/invisible_partition.test | 13 +++++++++++++
sql/sql_partition.cc | 11 +++++++++++
3 files changed, 34 insertions(+)
diff --git a/mysql-test/main/invisible_partition.result b/mysql-test/main/invisible_partition.result
new file mode 100644
index 0000000..b2915c8
--- /dev/null
+++ b/mysql-test/main/invisible_partition.result
@@ -0,0 +1,10 @@
+CREATE TABLE t1 (a INT NOT NULL, KEY (a)) ENGINE=MEMORY PARTITION BY KEY(a) PARTITIONS 4;
+INSERT INTO t1 VALUES (1),(2);
+SET debug_dbug="+d,test_pseudo_invisible";
+ALTER TABLE t1 REBUILD PARTITION p2;
+ERROR HY000: Internal error: Don't to it with test_pseudo_invisible
+SET debug_dbug='';
+ALTER TABLE t1 REPAIR PARTITION p1,p2,p3;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+Drop table t1;
diff --git a/mysql-test/main/invisible_partition.test b/mysql-test/main/invisible_partition.test
new file mode 100644
index 0000000..85bd30e
--- /dev/null
+++ b/mysql-test/main/invisible_partition.test
@@ -0,0 +1,13 @@
+--source include/have_partition.inc
+--source include/have_binlog_format_row.inc
+
+CREATE TABLE t1 (a INT NOT NULL, KEY (a)) ENGINE=MEMORY PARTITION BY KEY(a) PARTITIONS 4;
+INSERT INTO t1 VALUES (1),(2);
+SET debug_dbug="+d,test_pseudo_invisible";
+--error ER_INTERNAL_ERROR
+ALTER TABLE t1 REBUILD PARTITION p2;
+SET debug_dbug='';
+ALTER TABLE t1 REPAIR PARTITION p1,p2,p3;
+
+# Cleanup
+Drop table t1;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index c5c39a2..634c120 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -4872,6 +4872,17 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
ALTER_PARTITION_TABLE_REORG |
ALTER_PARTITION_REBUILD))
{
+ /*
+ You can't add column when we are doing alter related to partition
+ */
+ DBUG_EXECUTE_IF("test_pseudo_invisible", {
+ my_error(ER_INTERNAL_ERROR, MYF(0), "Don't to it with test_pseudo_invisible");
+ DBUG_RETURN(1);
+ });
+ DBUG_EXECUTE_IF("test_completely_invisible", {
+ my_error(ER_INTERNAL_ERROR, MYF(0), "Don't to it with test_completely_invisible");
+ DBUG_RETURN(1);
+ });
partition_info *tab_part_info;
ulonglong flags= 0;
bool is_last_partition_reorged= FALSE;
1
0

[Commits] 39fbafb: Post-merge fixes: make rocksdb.allow_to_start_after_corruption pass
by psergeyï¼ askmonty.org 19 Apr '18
by psergeyï¼ askmonty.org 19 Apr '18
19 Apr '18
revision-id: 39fbafbcc22cd51c1cbca8a06320394e94a9cd50
parent(s): 955233256ee26486dc55ce50e759e05ad88546fc
committer: Sergei Petrunia
branch nick: 10.2-r10
timestamp: 2018-04-19 16:28:05 +0300
message:
Post-merge fixes: make rocksdb.allow_to_start_after_corruption pass
---
.../mysql-test/rocksdb/r/allow_to_start_after_corruption.result | 7 +++++--
.../mysql-test/rocksdb/t/allow_to_start_after_corruption.test | 8 ++++----
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/storage/rocksdb/mysql-test/rocksdb/r/allow_to_start_after_corruption.result b/storage/rocksdb/mysql-test/rocksdb/r/allow_to_start_after_corruption.result
index 1a2abbf..9b5a335 100644
--- a/storage/rocksdb/mysql-test/rocksdb/r/allow_to_start_after_corruption.result
+++ b/storage/rocksdb/mysql-test/rocksdb/r/allow_to_start_after_corruption.result
@@ -12,9 +12,10 @@ insert into t1 values (1,1),(2,2),(3,3);
select * from t1 where pk=1;
pk col1
1 1
-set session debug= "+d,rocksdb_return_status_corrupted";
+set session debug_dbug= "+d,rocksdb_return_status_corrupted";
select * from t1 where pk=1;
ERROR HY000: Lost connection to MySQL server during query
+FOUND 1 /data corruption detected/ in allow_to_start_after_corruption_debug.err
#
# The same for scan queries
#
@@ -23,12 +24,14 @@ pk col1
1 1
2 2
3 3
-set session debug= "+d,rocksdb_return_status_corrupted";
+set session debug_dbug= "+d,rocksdb_return_status_corrupted";
select * from t1;
ERROR HY000: Lost connection to MySQL server during query
+FOUND 1 /data corruption detected/ in allow_to_start_after_corruption_debug.err
#
# Test restart failure. The server is shutdown at this point.
#
+FOUND 1 /The server will exit normally and stop restart attempts/ in allow_to_start_after_corruption_debug.err
#
# Remove corruption file and restart cleanly
#
diff --git a/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test b/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test
index 1863c32..67b2d5f 100644
--- a/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test
+++ b/storage/rocksdb/mysql-test/rocksdb/t/allow_to_start_after_corruption.test
@@ -26,7 +26,7 @@ create table t1 (
insert into t1 values (1,1),(2,2),(3,3);
select * from t1 where pk=1;
-set session debug= "+d,rocksdb_return_status_corrupted";
+set session debug_dbug= "+d,rocksdb_return_status_corrupted";
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--error 2013
select * from t1 where pk=1;
@@ -41,7 +41,7 @@ select * from t1 where pk=1;
--source include/start_mysqld_with_option.inc
select * from t1;
-set session debug= "+d,rocksdb_return_status_corrupted";
+set session debug_dbug= "+d,rocksdb_return_status_corrupted";
--exec echo "wait" > $_expect_file_name
--error 2013
select * from t1;
@@ -57,7 +57,7 @@ select * from t1;
# remove flag to ignore corruption
--let $_mysqld_option=--log-error=$LOG
--error 0
---exec $MYSQLD_CMD $_mysqld_option
+--exec $MYSQLD_CMD --plugin_load=$HA_ROCKSDB_SO $_mysqld_option
--let SEARCH_PATTERN=The server will exit normally and stop restart attempts
--source include/search_pattern_in_file.inc
--remove_file $LOG
@@ -66,7 +66,7 @@ select * from t1;
--echo # Remove corruption file and restart cleanly
--echo #
---exec rm $MYSQLTEST_VARDIR/mysqld.$_server_id/data/.rocksdb/ROCKSDB_CORRUPTED
+--exec rm $MYSQLTEST_VARDIR/mysqld.$_server_id/data/#rocksdb/ROCKSDB_CORRUPTED
--source include/start_mysqld_with_option.inc
drop table t1;
1
0

[Commits] 9552332: MyRocks: fix rocksdb.information_schema testcase.
by psergeyï¼ askmonty.org 19 Apr '18
by psergeyï¼ askmonty.org 19 Apr '18
19 Apr '18
revision-id: 955233256ee26486dc55ce50e759e05ad88546fc
parent(s): 6bea5e9e0f37499a9ff5f54e2e8f7665ec1ac317
committer: Sergei Petrunia
branch nick: 10.2-r10
timestamp: 2018-04-19 15:41:13 +0300
message:
MyRocks: fix rocksdb.information_schema testcase.
"The Store binlog position inside RocksDB" feature is only needed for
obtaining binlog position after having restored a MyRocks backup.
This is not yet supported in MariaDB, so properly disable it in both
places where it is done.
---
storage/rocksdb/ha_rocksdb.cc | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc
index 5f19fac..6e9e7ef 100644
--- a/storage/rocksdb/ha_rocksdb.cc
+++ b/storage/rocksdb/ha_rocksdb.cc
@@ -2079,10 +2079,16 @@ class Rdb_transaction {
rollback();
return true;
} else {
+#ifdef MARIAROCKS_NOT_YET
+ /*
+ Storing binlog position inside MyRocks is needed only for restoring
+ MyRocks from backups. This feature is not supported yet.
+ */
mysql_bin_log_commit_pos(m_thd, &m_mysql_log_offset,
&m_mysql_log_file_name);
binlog_manager.update(m_mysql_log_file_name, m_mysql_log_offset,
get_write_batch());
+#endif
return commit_no_binlog();
}
}
@@ -3089,7 +3095,11 @@ static int rocksdb_prepare(handlerton* hton, THD* thd, bool prepare_tx)
/* We were instructed to prepare the whole transaction, or
this is an SQL statement end and autocommit is on */
-#ifdef MARIAROCKS_NOT_YET // Crash-safe slave does not work yet
+#ifdef MARIAROCKS_NOT_YET
+ /*
+ Storing binlog position inside MyRocks is needed only for restoring
+ MyRocks from backups. This feature is not supported yet.
+ */
std::vector<st_slave_gtid_info> slave_gtid_info;
my_core::thd_slave_gtid_info(thd, &slave_gtid_info);
for (const auto &it : slave_gtid_info) {
1
0