28 May '19
revision-id: 678cd7f4ffb86fdac88f85b270edc66c3beb37d0 (mariadb-10.4.4-114-g678cd7f4ffb)
parent(s): 54b81cf6cad395e1bc57c876566454b90a1228f3
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2019-05-28 13:31:08 +0200
message:
Improve inheritance of lex_keeper.
---
sql/sp_head.h | 56 +++++++++++++++++++++++++++++++-------------------------
sql/sql_class.h | 10 +++++-----
2 files changed, 36 insertions(+), 30 deletions(-)
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 3365bf4883f..2b2ba732bb6 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -1242,11 +1242,28 @@ class sp_lex_keeper
TABLE_LIST **lex_query_tables_own_last;
};
+/*
+ Class for basic instructions using LEX (there are some other more complex
+ using LEX)
+*/
+
+class sp_lex_basic_instr : public sp_instr
+{
+ protected:
+
+ sp_lex_keeper m_lex_keeper;
+
+ public:
+
+ sp_lex_basic_instr(uint ip, sp_pcontext *ctx, LEX *lex, bool lex_owner)
+ : sp_instr(ip, ctx), m_lex_keeper(lex, lex_owner)
+ {}
+};
/**
Call out to some prepared SQL statement.
*/
-class sp_instr_stmt : public sp_instr
+class sp_instr_stmt : public sp_lex_basic_instr
{
sp_instr_stmt(const sp_instr_stmt &); /**< Prevent use of these */
void operator=(sp_instr_stmt &);
@@ -1256,7 +1273,7 @@ class sp_instr_stmt : public sp_instr
LEX_STRING m_query; ///< For thd->query
sp_instr_stmt(uint ip, sp_pcontext *ctx, LEX *lex)
- : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE)
+ : sp_lex_basic_instr(ip, ctx, lex, TRUE)
{
m_query.str= 0;
m_query.length= 0;
@@ -1271,14 +1288,10 @@ class sp_instr_stmt : public sp_instr
virtual void print(String *str);
-private:
-
- sp_lex_keeper m_lex_keeper;
-
}; // class sp_instr_stmt : public sp_instr
-class sp_instr_set : public sp_instr
+class sp_instr_set : public sp_lex_basic_instr
{
sp_instr_set(const sp_instr_set &); /**< Prevent use of these */
void operator=(sp_instr_set &);
@@ -1289,9 +1302,8 @@ class sp_instr_set : public sp_instr
const Sp_rcontext_handler *rh,
uint offset, Item *val,
LEX *lex, bool lex_resp)
- : sp_instr(ip, ctx),
- m_rcontext_handler(rh), m_offset(offset), m_value(val),
- m_lex_keeper(lex, lex_resp)
+ : sp_lex_basic_instr(ip, ctx, lex, lex_resp),
+ m_rcontext_handler(rh), m_offset(offset), m_value(val)
{}
virtual ~sp_instr_set()
@@ -1308,7 +1320,6 @@ class sp_instr_set : public sp_instr
const Sp_rcontext_handler *m_rcontext_handler;
uint m_offset; ///< Frame offset
Item *m_value;
- sp_lex_keeper m_lex_keeper;
}; // class sp_instr_set : public sp_instr
@@ -1389,7 +1400,7 @@ class sp_instr_set_row_field_by_name : public sp_instr_set
/**
Set NEW/OLD row field value instruction. Used in triggers.
*/
-class sp_instr_set_trigger_field : public sp_instr
+class sp_instr_set_trigger_field : public sp_lex_basic_instr
{
sp_instr_set_trigger_field(const sp_instr_set_trigger_field &);
void operator=(sp_instr_set_trigger_field &);
@@ -1399,9 +1410,9 @@ class sp_instr_set_trigger_field : public sp_instr
sp_instr_set_trigger_field(uint ip, sp_pcontext *ctx,
Item_trigger_field *trg_fld,
Item *val, LEX *lex)
- : sp_instr(ip, ctx),
+ : sp_lex_basic_instr(ip, ctx, lex, TRUE),
trigger_field(trg_fld),
- value(val), m_lex_keeper(lex, TRUE)
+ value(val)
{}
virtual ~sp_instr_set_trigger_field()
@@ -1416,7 +1427,6 @@ class sp_instr_set_trigger_field : public sp_instr
private:
Item_trigger_field *trigger_field;
Item *value;
- sp_lex_keeper m_lex_keeper;
}; // class sp_instr_trigger_field : public sp_instr
@@ -1592,7 +1602,7 @@ class sp_instr_preturn : public sp_instr
}; // class sp_instr_preturn : public sp_instr
-class sp_instr_freturn : public sp_instr
+class sp_instr_freturn : public sp_lex_basic_instr
{
sp_instr_freturn(const sp_instr_freturn &); /**< Prevent use of these */
void operator=(sp_instr_freturn &);
@@ -1601,8 +1611,7 @@ class sp_instr_freturn : public sp_instr
sp_instr_freturn(uint ip, sp_pcontext *ctx,
Item *val, const Type_handler *handler, LEX *lex)
- : sp_instr(ip, ctx), m_value(val), m_type_handler(handler),
- m_lex_keeper(lex, TRUE)
+ : sp_lex_basic_instr(ip, ctx, lex, TRUE), m_value(val), m_type_handler(handler)
{}
virtual ~sp_instr_freturn()
@@ -1624,7 +1633,6 @@ class sp_instr_freturn : public sp_instr
Item *m_value;
const Type_handler *m_type_handler;
- sp_lex_keeper m_lex_keeper;
}; // class sp_instr_freturn : public sp_instr
@@ -1759,7 +1767,7 @@ class sp_instr_hreturn : public sp_instr_jump
/** This is DECLARE CURSOR */
-class sp_instr_cpush : public sp_instr,
+class sp_instr_cpush : public sp_lex_basic_instr,
public sp_cursor
{
sp_instr_cpush(const sp_instr_cpush &); /**< Prevent use of these */
@@ -1768,7 +1776,7 @@ class sp_instr_cpush : public sp_instr,
public:
sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex, uint offset)
- : sp_instr(ip, ctx), m_lex_keeper(lex, TRUE), m_cursor(offset)
+ : sp_lex_basic_instr(ip, ctx, lex, TRUE), m_cursor(offset)
{}
virtual ~sp_instr_cpush()
@@ -1786,7 +1794,6 @@ class sp_instr_cpush : public sp_instr,
virtual void cleanup_stmt() { /* no op */ }
private:
- sp_lex_keeper m_lex_keeper;
uint m_cursor; /**< Frame offset (for debugging) */
}; // class sp_instr_cpush : public sp_instr
@@ -1853,18 +1860,17 @@ class sp_instr_copen : public sp_instr
Initialize the structure of a cursor%ROWTYPE variable
from the LEX containing the cursor SELECT statement.
*/
-class sp_instr_cursor_copy_struct: public sp_instr
+class sp_instr_cursor_copy_struct: public sp_lex_basic_instr
{
/**< Prevent use of these */
sp_instr_cursor_copy_struct(const sp_instr_cursor_copy_struct &);
void operator=(sp_instr_cursor_copy_struct &);
- sp_lex_keeper m_lex_keeper;
uint m_cursor;
uint m_var;
public:
sp_instr_cursor_copy_struct(uint ip, sp_pcontext *ctx, uint coffs,
sp_lex_cursor *lex, uint voffs)
- : sp_instr(ip, ctx), m_lex_keeper(lex, FALSE),
+ : sp_lex_basic_instr(ip, ctx, lex, FALSE),
m_cursor(coffs),
m_var(voffs)
{}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 9fc0f9f216c..499b3056f7e 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5326,19 +5326,19 @@ class sp_cursor: public sp_cursor_statistics
public:
sp_cursor()
:result(NULL, false),
- m_lex_keeper(NULL),
+ m_lex_keeper_ptr(NULL),
server_side_cursor(NULL)
{ }
sp_cursor(THD *thd_arg, sp_lex_keeper *lex_keeper, bool view_structure_only)
:result(thd_arg, view_structure_only),
- m_lex_keeper(lex_keeper),
+ m_lex_keeper_ptr(lex_keeper),
server_side_cursor(NULL)
{}
virtual ~sp_cursor()
{ destroy(); }
- sp_lex_keeper *get_lex_keeper() { return m_lex_keeper; }
+ sp_lex_keeper *get_lex_keeper() { return m_lex_keeper_ptr; }
int open(THD *thd);
@@ -5355,13 +5355,13 @@ class sp_cursor: public sp_cursor_statistics
{
sp_cursor_statistics::reset();
result.reset(thd_arg);
- m_lex_keeper= lex_keeper;
+ m_lex_keeper_ptr= lex_keeper;
server_side_cursor= NULL;
}
private:
Select_fetch_into_spvars result;
- sp_lex_keeper *m_lex_keeper;
+ sp_lex_keeper *m_lex_keeper_ptr;
Server_side_cursor *server_side_cursor;
void destroy();
};
1
0
[Commits] 72abc68: MDEV-18479 Assertion `join->best_read < double(1.79769313486231570815e+308L)'
by IgorBabaev 28 May '19
by IgorBabaev 28 May '19
28 May '19
revision-id: 72abc68cf4d1c512f1d7befb4c30c0c07f3136cc (mariadb-5.5.64-7-g72abc68)
parent(s): 2c9844a438c5f0bddcb037a1e05978118f48abb6
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-05-27 19:08:00 -0700
message:
MDEV-18479 Assertion `join->best_read < double(1.79769313486231570815e+308L)'
or server crashes in JOIN::fix_all_splittings_in_plan after EXPLAIN
This patch resolves the problem of overflowing when performing
calculations to estimate the cost of an evaluated query execution plan.
The overflowing in a non-debug build could cause different kind of
problems uncluding crashes of the server.
---
mysql-test/r/derived_view.result | 401 +++++++++++++++++++++++++++++++++++++++
mysql-test/t/derived_view.test | 260 +++++++++++++++++++++++++
sql/opt_subselect.cc | 69 ++++---
sql/sql_const.h | 8 +
sql/sql_select.cc | 113 ++++++-----
5 files changed, 772 insertions(+), 79 deletions(-)
diff --git a/mysql-test/r/derived_view.result b/mysql-test/r/derived_view.result
index 12811eb..ab36393 100644
--- a/mysql-test/r/derived_view.result
+++ b/mysql-test/r/derived_view.result
@@ -2640,3 +2640,404 @@ Note 1003 select straight_join `test`.`t1`.`c1` AS `c1` from `test`.`t1` where <
DROP TABLE t1, t2;
set optimizer_switch=@exit_optimizer_switch;
set join_cache_level=@exit_join_cache_level;
+#
+# Bug mdev-12812: EXPLAIN for query with many expensive derived
+#
+CREATE TABLE t1
+(id int auto_increment primary key,
+uid int NOT NULL,
+gp_id int NOT NULL,
+r int NOT NULL
+);
+INSERT INTO t1(uid,gp_id,r) VALUES
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1);
+CREATE TABLE t2 (id int) ;
+INSERT INTO t2 VALUES (1);
+explain SELECT 1 FROM t2 JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_1 ON gp_1.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_2 ON gp_2.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_3 ON gp_3.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_4 ON gp_4.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_5 ON gp_5.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_6 ON gp_6.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+WHERE p1.gp_id=7) gp_7 ON gp_7.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_8 ON gp_8.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_9 ON gp_9.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_14 ON gp_14.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_15 ON gp_15.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+) gp_16 ON gp_16.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+)gp_17 ON gp_17.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+)gp_18 ON gp_18.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+)gp_19 ON gp_19.id=t2.id
+JOIN
+(SELECT t2.id
+FROM t2
+JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+) gp_20 ON gp_20.id=t2.id ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 system NULL NULL NULL NULL 1
+1 SIMPLE t2 system NULL NULL NULL NULL 1
+1 SIMPLE t2 system NULL NULL NULL NULL 1
+1 SIMPLE t2 system NULL NULL NULL NULL 1
+1 SIMPLE t2 system NULL NULL NULL NULL 1
+1 SIMPLE t2 system NULL NULL NULL NULL 1
+1 SIMPLE p4 ALL NULL NULL NULL NULL 550 Using where
+1 SIMPLE p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p4 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p1 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p3 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p4 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p1 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p3 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p4 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p1 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p3 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p4 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived17> ALL NULL NULL NULL NULL 50328437500000 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived14> ALL NULL NULL NULL NULL 27680640625000000 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived7> ALL NULL NULL NULL NULL 7798774269472204288 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived8> ALL NULL NULL NULL NULL 7798774269472204288 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived9> ALL NULL NULL NULL NULL -3222391729959551616 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived10> ALL NULL NULL NULL NULL -3222391729959551616 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived11> ALL NULL NULL NULL NULL -3222391729959551616 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived12> ALL NULL NULL NULL NULL -3222391729959551616 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived13> ALL NULL NULL NULL NULL -3222391729959551616 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived15> ALL NULL NULL NULL NULL -3222391729959551616 Using where; Using join buffer (incremental, BNL join)
+1 SIMPLE <derived16> ALL NULL NULL NULL NULL -3222391729959551616 Using where; Using join buffer (incremental, BNL join)
+17 DERIVED t2 system NULL NULL NULL NULL 1
+17 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+17 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+17 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+17 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+17 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+16 DERIVED t2 system NULL NULL NULL NULL 1
+16 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+16 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+16 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+16 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+16 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+16 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+16 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+15 DERIVED t2 system NULL NULL NULL NULL 1
+15 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+15 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+15 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+15 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+15 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+15 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+15 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+14 DERIVED t2 system NULL NULL NULL NULL 1
+14 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+14 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+14 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+14 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+14 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+14 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+13 DERIVED t2 system NULL NULL NULL NULL 1
+13 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+13 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+13 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+13 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+13 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+13 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+13 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+12 DERIVED t2 system NULL NULL NULL NULL 1
+12 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+12 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+12 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+12 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+12 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+12 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+12 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+11 DERIVED t2 system NULL NULL NULL NULL 1
+11 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+11 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+11 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+11 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+11 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+11 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+11 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+10 DERIVED t2 system NULL NULL NULL NULL 1
+10 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+10 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+10 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+10 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+10 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+10 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+10 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+9 DERIVED t2 system NULL NULL NULL NULL 1
+9 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where
+9 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+9 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+9 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+9 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+9 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+9 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+8 DERIVED t2 system NULL NULL NULL NULL 1
+8 DERIVED p1 ALL NULL NULL NULL NULL 550 Using where
+8 DERIVED p3 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+8 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+8 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+8 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+8 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+8 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+8 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+8 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+7 DERIVED t2 system NULL NULL NULL NULL 1
+7 DERIVED p1 ALL NULL NULL NULL NULL 550 Using where
+7 DERIVED p3 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (flat, BNL join)
+7 DERIVED p4 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+7 DERIVED p5 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+7 DERIVED p6 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+7 DERIVED p7 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+7 DERIVED p8 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+7 DERIVED p9 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+7 DERIVED p10 ALL NULL NULL NULL NULL 550 Using where; Using join buffer (incremental, BNL join)
+DROP TABLE t1, t2;
diff --git a/mysql-test/t/derived_view.test b/mysql-test/t/derived_view.test
index 07fbe49..f6613e2 100644
--- a/mysql-test/t/derived_view.test
+++ b/mysql-test/t/derived_view.test
@@ -1934,3 +1934,263 @@ DROP TABLE t1, t2;
# The following command must be the last one the file
set optimizer_switch=@exit_optimizer_switch;
set join_cache_level=@exit_join_cache_level;
+
+--echo #
+--echo # Bug mdev-12812: EXPLAIN for query with many expensive derived
+--echo #
+
+CREATE TABLE t1
+(id int auto_increment primary key,
+ uid int NOT NULL,
+ gp_id int NOT NULL,
+ r int NOT NULL
+);
+
+INSERT INTO t1(uid,gp_id,r) VALUES
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),(1,1,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),(1,2,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),(1,3,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),(1,4,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),(1,5,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),(1,6,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),(1,7,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),(1,8,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),(1,9,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),
+(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,10,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),(1,11,1),
+(1,11,1);
+
+CREATE TABLE t2 (id int) ;
+INSERT INTO t2 VALUES (1);
+
+explain SELECT 1 FROM t2 JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_1 ON gp_1.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_2 ON gp_2.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+ JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_3 ON gp_3.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+ JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_4 ON gp_4.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+ JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_5 ON gp_5.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+ JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_6 ON gp_6.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p1 ON p1.r=1 AND p1.uid=t2.id
+ JOIN t1 p3 ON p3.r=3 AND p3.uid=t2.id
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ WHERE p1.gp_id=7) gp_7 ON gp_7.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_8 ON gp_8.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_9 ON gp_9.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_14 ON gp_14.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_15 ON gp_15.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ ) gp_16 ON gp_16.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ )gp_17 ON gp_17.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ )gp_18 ON gp_18.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ JOIN t1 p9 ON p9.r=9 AND p9.uid=t2.id
+ JOIN t1 p10 ON p10.r=10 AND p10.uid=t2.id
+ )gp_19 ON gp_19.id=t2.id
+JOIN
+(SELECT t2.id
+ FROM t2
+ JOIN t1 p4 ON p4.r=4 AND p4.uid=t2.id
+ JOIN t1 p5 ON p5.r=5 AND p5.uid=t2.id
+ JOIN t1 p6 ON p6.r=6 AND p6.uid=t2.id
+ JOIN t1 p7 ON p7.r=7 AND p7.uid=t2.id
+ JOIN t1 p8 ON p8.r=8 AND p8.uid=t2.id
+ ) gp_20 ON gp_20.id=t2.id ;
+
+DROP TABLE t1, t2;
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index a0e19af..cb82132 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -27,6 +27,7 @@
#endif
#include "sql_base.h"
+#include "sql_const.h"
#include "sql_select.h"
#include "filesort.h"
#include "opt_subselect.h"
@@ -1380,8 +1381,8 @@ void get_delayed_table_estimates(TABLE *table,
*startup_cost= item->jtbm_read_time;
/* Calculate cost of scanning the temptable */
- double data_size= item->jtbm_record_count *
- hash_sj_engine->tmp_table->s->reclength;
+ double data_size= COST_MULT(item->jtbm_record_count,
+ hash_sj_engine->tmp_table->s->reclength);
/* Do like in handler::read_time */
*scan_time= data_size/IO_SIZE + 2;
}
@@ -2451,7 +2452,8 @@ bool optimize_semijoin_nests(JOIN *join, table_map all_table_map)
int tableno;
double rows= 1.0;
while ((tableno = tm_it.next_bit()) != Table_map_iterator::BITMAP_END)
- rows *= join->map2table[tableno]->table->quick_condition_rows;
+ rows= COST_MULT(rows,
+ join->map2table[tableno]->table->quick_condition_rows);
sjm->rows= min(sjm->rows, rows);
}
memcpy(sjm->positions, join->best_positions + join->const_tables,
@@ -2564,7 +2566,7 @@ static uint get_tmp_table_rec_length(Item **p_items, uint elements)
static double
get_tmp_table_lookup_cost(THD *thd, double row_count, uint row_size)
{
- if (row_count * row_size > thd->variables.max_heap_table_size)
+ if (row_count > thd->variables.max_heap_table_size / (double) row_size)
return (double) DISK_TEMPTABLE_LOOKUP_COST;
else
return (double) HEAP_TEMPTABLE_LOOKUP_COST;
@@ -2970,8 +2972,11 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
}
double mat_read_time= prefix_cost.total_cost();
- mat_read_time += mat_info->materialization_cost.total_cost() +
- prefix_rec_count * mat_info->lookup_cost.total_cost();
+ mat_read_time=
+ COST_ADD(mat_read_time,
+ COST_ADD(mat_info->materialization_cost.total_cost(),
+ COST_MULT(prefix_rec_count,
+ mat_info->lookup_cost.total_cost())));
/*
NOTE: When we pick to use SJM[-Scan] we don't memcpy its POSITION
@@ -3011,9 +3016,12 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
}
/* Add materialization cost */
- prefix_cost += mat_info->materialization_cost.total_cost() +
- prefix_rec_count * mat_info->scan_cost.total_cost();
- prefix_rec_count *= mat_info->rows;
+ prefix_cost=
+ COST_ADD(prefix_cost,
+ COST_ADD(mat_info->materialization_cost.total_cost(),
+ COST_MULT(prefix_rec_count,
+ mat_info->scan_cost.total_cost())));
+ prefix_rec_count= COST_MULT(prefix_rec_count, mat_info->rows);
uint i;
table_map rem_tables= remaining_tables;
@@ -3027,8 +3035,8 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
{
best_access_path(join, join->positions[i].table, rem_tables, i,
disable_jbuf, prefix_rec_count, &curpos, &dummy);
- prefix_rec_count *= curpos.records_read;
- prefix_cost += curpos.read_time;
+ prefix_rec_count= COST_MULT(prefix_rec_count, curpos.records_read);
+ prefix_cost= COST_ADD(prefix_cost, curpos.read_time);
}
*strategy= SJ_OPT_MATERIALIZE_SCAN;
@@ -3335,16 +3343,18 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
for (uint j= first_dupsweedout_table; j <= idx; j++)
{
POSITION *p= join->positions + j;
- current_fanout *= p->records_read;
- dups_cost += p->read_time + current_fanout / TIME_FOR_COMPARE;
+ current_fanout= COST_MULT(current_fanout, p->records_read);
+ dups_cost= COST_ADD(dups_cost,
+ COST_ADD(p->read_time,
+ current_fanout / TIME_FOR_COMPARE));
if (p->table->emb_sj_nest)
{
- sj_inner_fanout *= p->records_read;
+ sj_inner_fanout= COST_MULT(sj_inner_fanout, p->records_read);
dups_removed_fanout |= p->table->table->map;
}
else
{
- sj_outer_fanout *= p->records_read;
+ sj_outer_fanout= COST_MULT(sj_outer_fanout, p->records_read);
temptable_rec_size += p->table->table->file->ref_length;
}
}
@@ -3363,12 +3373,13 @@ bool Duplicate_weedout_picker::check_qep(JOIN *join,
sj_outer_fanout,
temptable_rec_size);
- double write_cost= join->positions[first_tab].prefix_record_count*
- sj_outer_fanout * one_write_cost;
- double full_lookup_cost= join->positions[first_tab].prefix_record_count*
- sj_outer_fanout* sj_inner_fanout *
- one_lookup_cost;
- dups_cost += write_cost + full_lookup_cost;
+ double write_cost= COST_MULT(join->positions[first_tab].prefix_record_count,
+ sj_outer_fanout * one_write_cost);
+ double full_lookup_cost=
+ COST_MULT(join->positions[first_tab].prefix_record_count,
+ COST_MULT(sj_outer_fanout,
+ sj_inner_fanout * one_lookup_cost));
+ dups_cost= COST_ADD(dups_cost, COST_ADD(write_cost, full_lookup_cost));
*read_time= dups_cost;
*record_count= prefix_rec_count * sj_outer_fanout;
@@ -3515,8 +3526,8 @@ static void recalculate_prefix_record_count(JOIN *join, uint start, uint end)
if (j == join->const_tables)
prefix_count= 1.0;
else
- prefix_count= join->best_positions[j-1].prefix_record_count *
- join->best_positions[j-1].records_read;
+ prefix_count= COST_MULT(join->best_positions[j-1].prefix_record_count,
+ join->best_positions[j-1].records_read);
join->best_positions[j].prefix_record_count= prefix_count;
}
@@ -5807,14 +5818,16 @@ bool JOIN::choose_subquery_plan(table_map join_tables)
The cost of executing the subquery and storing its result in an indexed
temporary table.
*/
- double materialization_cost= inner_read_time_1 +
- write_cost * inner_record_count_1;
+ double materialization_cost= COST_ADD(inner_read_time_1,
+ COST_MULT(write_cost,
+ inner_record_count_1));
- materialize_strategy_cost= materialization_cost +
- outer_lookup_keys * lookup_cost;
+ materialize_strategy_cost= COST_ADD(materialization_cost,
+ COST_MULT(outer_lookup_keys,
+ lookup_cost));
/* C.2 Compute the cost of the IN=>EXISTS strategy. */
- in_exists_strategy_cost= outer_lookup_keys * inner_read_time_2;
+ in_exists_strategy_cost= COST_MULT(outer_lookup_keys, inner_read_time_2);
/* C.3 Compare the costs and choose the cheaper strategy. */
if (materialize_strategy_cost >= in_exists_strategy_cost)
diff --git a/sql/sql_const.h b/sql/sql_const.h
index 96b6448..c3b03dd 100644
--- a/sql/sql_const.h
+++ b/sql/sql_const.h
@@ -214,6 +214,14 @@
#define HEAP_TEMPTABLE_LOOKUP_COST 0.05
#define DISK_TEMPTABLE_LOOKUP_COST 1.0
+
+#define COST_MAX (DBL_MAX * (1.0 - DBL_EPSILON))
+
+#define COST_ADD(c,d) (COST_MAX - (d) > (c) ? (c) + (d) : COST_MAX)
+
+#define COST_MULT(c,f) (COST_MAX / (f) > (c) ? (c) * (f) : COST_MAX)
+
+
#define MY_CHARSET_BIN_MB_MAXLEN 1
/** Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used). */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4886e35..961a7da 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5676,7 +5676,7 @@ best_access_path(JOIN *join,
else
tmp= table->file->read_time(key, 1,
(ha_rows) min(tmp,s->worst_seeks));
- tmp*= record_count;
+ tmp= COST_MULT(tmp, record_count);
}
}
else
@@ -5841,18 +5841,18 @@ best_access_path(JOIN *join,
else
tmp= table->file->read_time(key, 1,
(ha_rows) min(tmp,s->worst_seeks));
- tmp*= record_count;
+ tmp= COST_MULT(tmp, record_count);
}
else
- tmp= best_time; // Do nothing
+ tmp= best_time; // Do nothing
}
- tmp += s->startup_cost;
+ tmp= COST_ADD(tmp, s->startup_cost);
loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp);
} /* not ft_key */
if (tmp + 0.0001 < best_time - records/(double) TIME_FOR_COMPARE)
{
- best_time= tmp + records/(double) TIME_FOR_COMPARE;
+ best_time= COST_ADD(tmp, records/(double) TIME_FOR_COMPARE);
best= tmp;
best_records= records;
best_key= start_key;
@@ -5885,14 +5885,18 @@ best_access_path(JOIN *join,
ha_rows rnd_records= matching_candidates_in_table(s, found_constraint);
tmp= s->quick ? s->quick->read_time : s->scan_time();
- tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+ double cmp_time= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+ tmp= COST_ADD(tmp, cmp_time);
/* We read the table as many times as join buffer becomes full. */
- tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
- record_count /
- (double) thd->variables.join_buff_size));
- best_time= tmp +
- (record_count*join_sel) / TIME_FOR_COMPARE * rnd_records;
+
+ double refills= (1.0 + floor((double) cache_record_length(join,idx) *
+ record_count /
+ (double) thd->variables.join_buff_size));
+ tmp= COST_MULT(tmp, refills);
+ best_time= COST_ADD(tmp,
+ COST_MULT((record_count*join_sel) / TIME_FOR_COMPARE,
+ rnd_records));
best= tmp;
records= rows2double(rnd_records);
best_key= hj_start_key;
@@ -5960,9 +5964,9 @@ best_access_path(JOIN *join,
access (see first else-branch below), but we don't take it into
account here for range/index_merge access. Find out why this is so.
*/
- tmp= record_count *
- (s->quick->read_time +
- (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
+ double cmp_time= (s->found_records - rnd_records)/(double) TIME_FOR_COMPARE;
+ tmp= COST_MULT(record_count,
+ COST_ADD(s->quick->read_time, cmp_time));
loose_scan_opt.check_range_access(join, idx, s->quick);
}
@@ -5977,16 +5981,15 @@ best_access_path(JOIN *join,
- read the whole table record
- skip rows which does not satisfy join condition
*/
- tmp= record_count *
- (tmp +
- (s->records - rnd_records)/(double) TIME_FOR_COMPARE);
+ double cmp_time= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+ tmp= COST_MULT(record_count, COST_ADD(tmp,cmp_time));
}
else
{
- /* We read the table as many times as join buffer becomes full. */
- tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
- record_count /
- (double) thd->variables.join_buff_size));
+ double refills= (1.0 + floor((double) cache_record_length(join,idx) *
+ (record_count /
+ (double) thd->variables.join_buff_size)));
+ tmp= COST_MULT(tmp, refills);
/*
We don't make full cartesian product between rows in the scanned
table and existing records because we skip all rows from the
@@ -5994,7 +5997,8 @@ best_access_path(JOIN *join,
we read the table (see flush_cached_records for details). Here we
take into account cost to read and skip these records.
*/
- tmp+= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+ double cmp_time= (s->records - rnd_records)/(double) TIME_FOR_COMPARE;
+ tmp= COST_ADD(tmp, cmp_time);
}
}
@@ -6005,9 +6009,9 @@ best_access_path(JOIN *join,
tmp give us total cost of using TABLE SCAN
*/
if (best == DBL_MAX ||
- (tmp + record_count/(double) TIME_FOR_COMPARE*rnd_records <
+ COST_ADD(tmp, record_count/(double) TIME_FOR_COMPARE*rnd_records) <
(best_key->is_for_hash_join() ? best_time :
- best + record_count/(double) TIME_FOR_COMPARE*records)))
+ COST_ADD(best, record_count/(double) TIME_FOR_COMPARE*records)))
{
/*
If the table has a range (s->quick is set) make_join_select()
@@ -6526,9 +6530,10 @@ optimize_straight_join(JOIN *join, table_map join_tables)
join->positions + idx, &loose_scan_pos);
/* compute the cost of the new plan extended with 's' */
- record_count*= join->positions[idx].records_read;
- read_time+= join->positions[idx].read_time +
- record_count / (double) TIME_FOR_COMPARE;
+ record_count= COST_MULT(record_count, join->positions[idx].records_read);
+ read_time= COST_ADD(read_time,
+ COST_ADD(join->positions[idx].read_time,
+ record_count / (double) TIME_FOR_COMPARE));
advance_sj_state(join, join_tables, idx, &record_count, &read_time,
&loose_scan_pos);
@@ -6710,9 +6715,10 @@ greedy_search(JOIN *join,
swap_variables(JOIN_TAB*, join->best_ref[idx], join->best_ref[best_idx]);
/* compute the cost of the new plan extended with 'best_table' */
- record_count*= join->positions[idx].records_read;
- read_time+= join->positions[idx].read_time +
- record_count / (double) TIME_FOR_COMPARE;
+ record_count= COST_MULT(record_count, join->positions[idx].records_read);
+ read_time= COST_ADD(read_time,
+ COST_ADD(join->positions[idx].read_time,
+ record_count / (double) TIME_FOR_COMPARE));
remaining_tables&= ~(best_table->table->map);
--size_remain;
@@ -6819,11 +6825,13 @@ void JOIN::get_partial_cost_and_fanout(int end_tab_idx,
}
if (tab->records_read && (cur_table_map & filter_map))
{
- record_count *= tab->records_read;
- read_time += tab->read_time + record_count / (double) TIME_FOR_COMPARE;
+ record_count= COST_MULT(record_count, tab->records_read);
+ read_time= COST_ADD(read_time,
+ COST_ADD(tab->read_time,
+ record_count / (double) TIME_FOR_COMPARE));
if (tab->emb_sj_nest)
- sj_inner_fanout *= tab->records_read;
- }
+ sj_inner_fanout= COST_MULT(sj_inner_fanout, tab->records_read);
+ }
if (i == last_sj_table)
{
@@ -6861,8 +6869,8 @@ void JOIN::get_prefix_cost_and_fanout(uint n_tables,
{
if (best_positions[i].records_read)
{
- record_count *= best_positions[i].records_read;
- read_time += best_positions[i].read_time;
+ record_count= COST_MULT(record_count, best_positions[i].records_read);
+ read_time= COST_ADD(read_time, best_positions[i].read_time);
}
}
*read_time_arg= read_time;// + record_count / TIME_FOR_COMPARE;
@@ -7068,10 +7076,11 @@ best_extension_by_limited_search(JOIN *join,
record_count, join->positions + idx, &loose_scan_pos);
/* Compute the cost of extending the plan with 's' */
-
- current_record_count= record_count * position->records_read;
- current_read_time=read_time + position->read_time +
- current_record_count / (double) TIME_FOR_COMPARE;
+ current_record_count= COST_MULT(record_count, position->records_read);
+ current_read_time=COST_ADD(read_time,
+ COST_ADD(position->read_time,
+ current_record_count /
+ (double) TIME_FOR_COMPARE));
advance_sj_state(join, remaining_tables, idx, ¤t_record_count,
¤t_read_time, &loose_scan_pos);
@@ -7145,7 +7154,7 @@ best_extension_by_limited_search(JOIN *join,
join->sort_by_table !=
join->positions[join->const_tables].table->table)
/* We have to make a temp table */
- current_read_time+= current_record_count;
+ current_read_time= COST_ADD(current_read_time, current_record_count);
if (current_read_time < join->best_read)
{
memcpy((uchar*) join->best_positions, (uchar*) join->positions,
@@ -7189,11 +7198,11 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
DBUG_PRINT("best",("read_time: %g record_count: %g",read_time,
record_count));
- read_time+=record_count/(double) TIME_FOR_COMPARE;
+ read_time= COST_ADD(read_time, record_count/(double) TIME_FOR_COMPARE);
if (join->sort_by_table &&
join->sort_by_table !=
join->positions[join->const_tables].table->table)
- read_time+=record_count; // We have to make a temp table
+ read_time= COST_ADD(read_time, record_count); // We have to make a temp table
if (read_time < join->best_read)
{
memcpy((uchar*) join->best_positions,(uchar*) join->positions,
@@ -7202,7 +7211,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
}
DBUG_RETURN(FALSE);
}
- if (read_time+record_count/(double) TIME_FOR_COMPARE >= join->best_read)
+ if (COST_ADD(read_time, record_count/(double) TIME_FOR_COMPARE)
+ >= join->best_read)
DBUG_RETURN(FALSE); /* Found better before */
JOIN_TAB *s;
@@ -7224,8 +7234,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
Go to the next level only if there hasn't been a better key on
this level! This will cut down the search for a lot simple cases!
*/
- double current_record_count=record_count*records;
- double current_read_time=read_time+best;
+ double current_record_count= COST_MULT(record_count, records);
+ double current_read_time= COST_ADD(read_time, best);
advance_sj_state(join, rest_tables, idx, ¤t_record_count,
¤t_read_time, &loose_scan_pos);
@@ -7552,8 +7562,8 @@ prev_record_reads(POSITION *positions, uint idx, table_map found_ref)
#max_nested_outer_joins=64-1) will not make it any more precise.
*/
if (pos->records_read)
- found*= pos->records_read;
- }
+ found= COST_MULT(found, pos->records_read);
+ }
}
return found;
}
@@ -13835,11 +13845,12 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
pos= loose_scan_pos;
reopt_remaining_tables &= ~rs->table->map;
- rec_count *= pos.records_read;
- cost += pos.read_time;
+ rec_count= COST_MULT(rec_count, pos.records_read);
+ cost= COST_ADD(cost, pos.read_time);
+
if (!rs->emb_sj_nest)
- *outer_rec_count *= pos.records_read;
+ *outer_rec_count= COST_MULT(*outer_rec_count, pos.records_read);
}
join->cur_sj_inner_tables= save_cur_sj_inner_tables;
2
1
[Commits] befd5104a9c: MDEV-7409 On RBR, extend the PROCESSLIST info to include at least the name of the recently used table
by sachin.setiyaï¼ mariadb.com 28 May '19
by sachin.setiyaï¼ mariadb.com 28 May '19
28 May '19
revision-id: befd5104a9cd8a8ffba29a417d5c58f369585fb3 (mariadb-10.4.4-55-gbefd5104a9c)
parent(s): 4c995eb16843e56cd07c20e1f97ae495f0614010
author: Sachin
committer: Sachin
timestamp: 2019-05-28 13:42:09 +0530
message:
MDEV-7409 On RBR, extend the PROCESSLIST info to include at least the name of the recently used table
When RBR is used, add the db name to db Field and table name to Status
Field of the "SHOW FULL PROCESSLIST" command for SQL thread.
---
mysql-test/suite/rpl/r/rpl_rbr_monitor.result | 57 +++++++++++++++++
mysql-test/suite/rpl/t/rpl_rbr_monitor.test | 86 +++++++++++++++++++++++++
sql/debug_sync.cc | 3 +-
sql/log_event.cc | 90 +++++++++++++++++++++------
4 files changed, 215 insertions(+), 21 deletions(-)
diff --git a/mysql-test/suite/rpl/r/rpl_rbr_monitor.result b/mysql-test/suite/rpl/r/rpl_rbr_monitor.result
new file mode 100644
index 00000000000..67e98b80de0
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_rbr_monitor.result
@@ -0,0 +1,57 @@
+include/master-slave.inc
+[connection master]
+connection master;
+create table t1(a int primary key);
+connection slave;
+SET GLOBAL debug_dbug="+d,should_wait_for_mdev7409";
+select * from t1;
+a
+connection master;
+insert into t1(a) values(1);
+#monitoring write rows
+connection slave;
+SELECT db , state FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE DB = 'test' AND STATE LIKE "Write_rows_log_event::write_row(%) on table t1";
+db state
+test Write_rows_log_event::write_row(-1) on table t1
+set debug_sync="now signal cont";
+#monitoring update rows
+connection master;
+update t1 set a = a + 4194304 ;
+connection slave;
+SELECT db, state FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::find_row(%) on table t1";
+db state
+test Update_rows_log_event::find_row(-1) on table t1
+set debug_sync="now signal cont1";
+SELECT db, state FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::unpack_current_row(%) on table t1";
+db state
+test Update_rows_log_event::unpack_current_row(-1) on table t1
+set debug_sync="now signal cont2";
+SELECT db, state FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::ha_update_row(%) on table t1";
+db state
+test Update_rows_log_event::ha_update_row(-1) on table t1
+set debug_sync="now signal cont3";
+set debug_sync="RESET";
+#monitoring delete rows
+connection master;
+delete from t1 where a>1;
+connection slave;
+SELECT db , state FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE DB = 'test' AND STATE LIKE "Delete_rows_log_event::find_row(%) on table t1";
+db state
+test Delete_rows_log_event::find_row(-1) on table t1
+set debug_sync="now signal cont1";
+SELECT db, state FROM INFORMATION_SCHEMA.PROCESSLIST
+WHERE DB = 'test' AND STATE LIKE "Delete_rows_log_event::ha_delete_row(%) on table t1";
+db state
+test Delete_rows_log_event::ha_delete_row(-1) on table t1
+set debug_sync="now signal cont2";
+set debug_sync="RESET";
+SET GLOBAL debug_dbug="";
+connection master;
+drop table t1;
+connection slave;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_rbr_monitor.test b/mysql-test/suite/rpl/t/rpl_rbr_monitor.test
new file mode 100644
index 00000000000..e9eca2c0047
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_rbr_monitor.test
@@ -0,0 +1,86 @@
+--source include/have_innodb.inc
+--source include/have_debug.inc
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+--enable_connect_log
+
+--connection master
+create table t1(a int primary key);
+--save_master_pos
+
+--connection slave
+--sync_with_master
+SET GLOBAL debug_dbug="+d,should_wait_for_mdev7409";
+select * from t1;
+
+--connection master
+insert into t1(a) values(1);
+--save_master_pos
+
+--echo #monitoring write rows
+--connection slave
+
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Write_rows_log_event::write_row(%) on table t1";
+--source include/wait_condition.inc
+SELECT db , state FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Write_rows_log_event::write_row(%) on table t1";
+set debug_sync="now signal cont";
+--sync_with_master
+
+--echo #monitoring update rows
+--connection master
+update t1 set a = a + 4194304 ;
+
+--connection slave
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::find_row(%) on table t1";
+--source include/wait_condition.inc
+SELECT db, state FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::find_row(%) on table t1";
+set debug_sync="now signal cont1";
+
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::unpack_current_row(%) on table t1";
+--source include/wait_condition.inc
+SELECT db, state FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::unpack_current_row(%) on table t1";
+set debug_sync="now signal cont2";
+
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::ha_update_row(%) on table t1";
+--source include/wait_condition.inc
+SELECT db, state FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Update_rows_log_event::ha_update_row(%) on table t1";
+set debug_sync="now signal cont3";
+set debug_sync="RESET";
+--sync_with_master
+
+--echo #monitoring delete rows
+--connection master
+delete from t1 where a>1;
+
+--connection slave
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Delete_rows_log_event::find_row(%) on table t1";
+--source include/wait_condition.inc
+SELECT db , state FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Delete_rows_log_event::find_row(%) on table t1";
+set debug_sync="now signal cont1";
+
+let $wait_condition= SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Delete_rows_log_event::ha_delete_row(%) on table t1";
+--source include/wait_condition.inc
+SELECT db, state FROM INFORMATION_SCHEMA.PROCESSLIST
+ WHERE DB = 'test' AND STATE LIKE "Delete_rows_log_event::ha_delete_row(%) on table t1";
+set debug_sync="now signal cont2";
+set debug_sync="RESET";
+--sync_with_master
+SET GLOBAL debug_dbug="";
+
+#CleanUp
+--connection master
+drop table t1;
+--sync_slave_with_master
+
+--source include/rpl_end.inc
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc
index 357d8f4ce60..f7bc817ab13 100644
--- a/sql/debug_sync.cc
+++ b/sql/debug_sync.cc
@@ -1360,7 +1360,8 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
Do this before emitting the signal, so other threads can see it
if they awake before we enter_cond() below.
*/
- if (action->wait_for.length())
+ if (action->wait_for.length() &&
+ DBUG_EVALUATE_IF("should_wait_for_mdev7409", 0, 1))
{
st_debug_sync_control *ds_control= thd->debug_sync_control;
strxnmov(ds_control->ds_proc_info, sizeof(ds_control->ds_proc_info)-1,
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 70f0e6c2623..8b1d7dd4b69 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -53,6 +53,7 @@
#include "rpl_constants.h"
#include "sql_digest.h"
#include "zlib.h"
+#include "debug_sync.h"
#define my_b_write_string(A, B) my_b_write((A), (uchar*)(B), (uint) (sizeof(B) - 1))
@@ -13670,19 +13671,29 @@ Write_rows_log_event::do_exec_row(rpl_group_info *rgi)
{
DBUG_ASSERT(m_table != NULL);
const char *tmp= thd->get_proc_info();
- const char *message= "Write_rows_log_event::write_row()";
+ LEX_CSTRING *tmp_db= &thd->db;
+ char *message, msg[128];
+ my_snprintf(msg, sizeof(msg),"Write_rows_log_event::write_row() on table %s",
+ m_table->s->table_name.str);
+ thd->db= m_table->s->db;
+ message= msg;
int error;
#ifdef WSREP_PROC_INFO
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Write_rows_log_event::write_row(%lld)",
- (long long) wsrep_thd_trx_seqno(thd));
+ "Write_rows_log_event::write_row(%lld) on table %s",
+ (long long) wsrep_thd_trx_seqno(thd), m_table->s->table_name.str);
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
thd_proc_info(thd, message);
+ DBUG_EXECUTE_IF("should_wait_for_mdev7409",{
+ debug_sync_set_action
+ (thd, STRING_WITH_LEN("now WAIT_FOR cont"));
+ };);
error= write_row(rgi, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT);
thd_proc_info(thd, tmp);
+ thd->db= *tmp_db;
if (unlikely(error) && unlikely(!thd->is_error()))
{
@@ -14345,32 +14356,47 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi)
{
int error;
const char *tmp= thd->get_proc_info();
- const char *message= "Delete_rows_log_event::find_row()";
+ LEX_CSTRING *tmp_db= &thd->db;
+ char *message, msg[128];
+ my_snprintf(msg, sizeof(msg),"Delete_rows_log_event::find_row() on table %s",
+ m_table->s->table_name.str);
+ thd->db= m_table->s->db;
+ message= msg;
const bool invoke_triggers=
slave_run_triggers_for_rbr && !master_had_triggers && m_table->triggers;
DBUG_ASSERT(m_table != NULL);
#ifdef WSREP_PROC_INFO
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Delete_rows_log_event::find_row(%lld)",
- (long long) wsrep_thd_trx_seqno(thd));
+ "Delete_rows_log_event::find_row(%lld) on table %s",
+ (long long) wsrep_thd_trx_seqno(thd), m_table->s->table_name.str) ;
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
thd_proc_info(thd, message);
+ DBUG_EXECUTE_IF("should_wait_for_mdev7409",{
+ debug_sync_set_action
+ (thd, STRING_WITH_LEN("now WAIT_FOR cont1"));
+ };);
if (likely(!(error= find_row(rgi))))
{
/*
Delete the record found, located in record[0]
*/
- message= "Delete_rows_log_event::ha_delete_row()";
+ my_snprintf(msg, sizeof(msg),"Delete_rows_log_event::ha_delete_row() on table %s",
+ m_table->s->table_name.str);
+ message= msg;
#ifdef WSREP_PROC_INFO
snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Delete_rows_log_event::ha_delete_row(%lld)",
- (long long) wsrep_thd_trx_seqno(thd));
+ "Delete_rows_log_event::ha_delete_row(%lld) on table %s",
+ (long long) wsrep_thd_trx_seqno(thd), m_table->s->table_name.str) ;
message= thd->wsrep_info;
#endif
thd_proc_info(thd, message);
+ DBUG_EXECUTE_IF("should_wait_for_mdev7409",{
+ debug_sync_set_action
+ (thd, STRING_WITH_LEN("now WAIT_FOR cont2"));
+ };);
if (invoke_triggers &&
unlikely(process_triggers(TRG_EVENT_DELETE, TRG_ACTION_BEFORE, FALSE)))
@@ -14399,6 +14425,7 @@ int Delete_rows_log_event::do_exec_row(rpl_group_info *rgi)
m_table->file->ha_index_or_rnd_end();
}
thd_proc_info(thd, tmp);
+ thd->db= *tmp_db;
return error;
}
@@ -14567,17 +14594,27 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
const bool invoke_triggers=
slave_run_triggers_for_rbr && !master_had_triggers && m_table->triggers;
const char *tmp= thd->get_proc_info();
- const char *message= "Update_rows_log_event::find_row()";
+ LEX_CSTRING *tmp_db= &thd->db;
+ char *message, msg[128];
DBUG_ASSERT(m_table != NULL);
+ my_snprintf(msg, sizeof(msg),"Update_rows_log_event::find_row() on table %s",
+ m_table->s->table_name.str);
+ thd->db= m_table->s->db;
+ message= msg;
#ifdef WSREP_PROC_INFO
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Update_rows_log_event::find_row(%lld)",
- (long long) wsrep_thd_trx_seqno(thd));
+ "Update_rows_log_event::find_row(%lld) on table %s",
+ (long long) wsrep_thd_trx_seqno(thd), m_table->s->table_name.str) ;
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
thd_proc_info(thd, message);
+ DBUG_EXECUTE_IF("should_wait_for_mdev7409",{
+ debug_sync_set_action
+ (thd, STRING_WITH_LEN("now WAIT_FOR cont1"));
+ };);
+
int error= find_row(rgi);
if (unlikely(error))
{
@@ -14588,6 +14625,7 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
if ((m_curr_row= m_curr_row_end))
unpack_current_row(rgi, &m_cols_ai);
thd_proc_info(thd, tmp);
+ thd->db= *tmp_db;
return error;
}
@@ -14605,16 +14643,22 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
store_record(m_table,record[1]);
m_curr_row= m_curr_row_end;
- message= "Update_rows_log_event::unpack_current_row()";
+ my_snprintf(msg, sizeof(msg),"Update_rows_log_event::unpack_current_row() on table %s",
+ m_table->s->table_name.str);
+ message= msg;
#ifdef WSREP_PROC_INFO
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Update_rows_log_event::unpack_current_row(%lld)",
- (long long) wsrep_thd_trx_seqno(thd));
+ "Update_rows_log_event::unpack_current_row(%lld) on table %s",
+ (long long) wsrep_thd_trx_seqno(thd), m_table->s->table_name.str) ;
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
/* this also updates m_curr_row_end */
thd_proc_info(thd, message);
+ DBUG_EXECUTE_IF("should_wait_for_mdev7409",{
+ debug_sync_set_action
+ (thd, STRING_WITH_LEN("now WAIT_FOR cont2"));
+ };);
if (unlikely((error= unpack_current_row(rgi, &m_cols_ai))))
goto err;
@@ -14632,15 +14676,21 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength);
#endif
- message= "Update_rows_log_event::ha_update_row()";
+ my_snprintf(msg, sizeof(msg),"Update_rows_log_event::ha_update_row() on table %s",
+ m_table->s->table_name.str);
+ message= msg;
#ifdef WSREP_PROC_INFO
my_snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1,
- "Update_rows_log_event::ha_update_row(%lld)",
- (long long) wsrep_thd_trx_seqno(thd));
+ "Update_rows_log_event::ha_update_row(%lld) on table %s",
+ (long long) wsrep_thd_trx_seqno(thd), m_table->s->table_name.str) ;
message= thd->wsrep_info;
#endif /* WSREP_PROC_INFO */
thd_proc_info(thd, message);
+ DBUG_EXECUTE_IF("should_wait_for_mdev7409",{
+ debug_sync_set_action
+ (thd, STRING_WITH_LEN("now WAIT_FOR cont3"));
+ };);
if (invoke_triggers &&
unlikely(process_triggers(TRG_EVENT_UPDATE, TRG_ACTION_BEFORE, TRUE)))
{
@@ -14670,9 +14720,9 @@ Update_rows_log_event::do_exec_row(rpl_group_info *rgi)
unlikely(process_triggers(TRG_EVENT_UPDATE, TRG_ACTION_AFTER, TRUE)))
error= HA_ERR_GENERIC; // in case if error is not set yet
- thd_proc_info(thd, tmp);
-
err:
+ thd_proc_info(thd, tmp);
+ thd->db= *tmp_db;
m_table->file->ha_index_or_rnd_end();
return error;
}
1
0
[Commits] 53d0e921794: MDEV-11094: Blackhole table updates on slave fail when row annotation is enabled
by sujatha 27 May '19
by sujatha 27 May '19
27 May '19
revision-id: 53d0e9217943719b806ef9fa1cac0a699df4839c (mariadb-10.1.39-31-g53d0e921794)
parent(s): 47637a3dd13d19e897a7cbfd1499f1bf3b2fdb2a
author: Sujatha
committer: Sujatha
timestamp: 2019-05-17 13:11:49 +0530
message:
MDEV-11094: Blackhole table updates on slave fail when row annotation is enabled
Problem:
=======
rpl_blackhole.test fails when executed with following options
mysqld=--binlog_annotate_row_events=1, mysqld=--replicate_annotate_row_events=1
Test output:
------------
worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 16000..16019
rpl.rpl_blackhole_bug 'mix' [ pass ] 791
rpl.rpl_blackhole_bug 'row' [ fail ]
Replicate_Wild_Ignore_Table
Last_Errno 1032
Last_Error Could not execute Update_rows_v1 event on table test.t1; Can't find
record in 't1', Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event's
master log master-bin.000001, end_log_pos 1510
Analysis:
=========
Enabling "replicate_annotate_row_events" on slave, Tells the slave to write
annotate rows events received from the master to its own binary log. The
received annotate events are applied after the Gtid event as shown below.
thd->query() will be set to the actual query received from the master, through
annotate event. Annotate_rows event should not be deleted after the event is
applied as the thd->query will be used to generate new Annotate_rows event
during applying the subsequent Rows events. After the last Rows event has been
applied, the saved Annotate_rows event (if any) will be deleted.
master-bin.000001 | 457 | Gtid | BEGIN GTID 0-1-2
master-bin.000001 | 495 | Annotate_rows | insert into t values (10)
master-bin.000001 | 539 | Table_map | table_id: 19 (test.t)
master-bin.000001 | 579 | Write_rows_v1 | table_id: 19 flags: STMT_END_F
master-bin.000001 | 613 | Xid | COMMIT /* xid=7 */
In balckhole engine all the DML operations are noops as they donot store any
data. They simply return success without doing any operation. But the existing
strictly expects thd->query() to be 'NULL' to identify that row based
replication is in use. This assumption will fail when row annotations are
enabled as the query is not 'NULL'. Hence various row based operations like
'update', 'delete', 'index lookup' will fail when row annotations are enabled.
Fix:
===
Extend the row based replication check to include row annotations as well.
i.e Either the thd->query() is NULL or thd->query() points to query and row
annotations are in use.
---
mysql-test/suite/rpl/t/rpl_blackhole-master.opt | 1 +
mysql-test/suite/rpl/t/rpl_blackhole-slave.opt | 1 +
storage/blackhole/ha_blackhole.cc | 28 +++++++++++++++++++------
3 files changed, 24 insertions(+), 6 deletions(-)
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole-master.opt b/mysql-test/suite/rpl/t/rpl_blackhole-master.opt
new file mode 100644
index 00000000000..1ad0b884c60
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole-master.opt
@@ -0,0 +1 @@
+--binlog_annotate_row_events
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole-slave.opt b/mysql-test/suite/rpl/t/rpl_blackhole-slave.opt
new file mode 100644
index 00000000000..7ac6a84faa7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole-slave.opt
@@ -0,0 +1 @@
+--binlog_annotate_row_events --replicate_annotate_row_events
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 01aaa9ea15f..43bcdc541a1 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -25,6 +25,16 @@
#include "ha_blackhole.h"
#include "sql_class.h" // THD, SYSTEM_THREAD_SLAVE_SQL
+static bool is_row_based_replication(THD *thd)
+{
+ /*
+ A row event which has its thd->query() == NULL or a row event which has
+ replicate_annotate_row_events enabled. In the later case the thd->query()
+ will be pointing to the query, received through replicated annotate event
+ from master.
+ */
+ return ((thd->query() == NULL) || thd->variables.binlog_annotate_row_events);
+}
/* Static declarations for handlerton */
static handler *blackhole_create_handler(handlerton *hton,
@@ -109,7 +119,8 @@ int ha_blackhole::update_row(const uchar *old_data, uchar *new_data)
{
DBUG_ENTER("ha_blackhole::update_row");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
DBUG_RETURN(0);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -118,7 +129,8 @@ int ha_blackhole::delete_row(const uchar *buf)
{
DBUG_ENTER("ha_blackhole::delete_row");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
DBUG_RETURN(0);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -135,7 +147,8 @@ int ha_blackhole::rnd_next(uchar *buf)
int rc;
DBUG_ENTER("ha_blackhole::rnd_next");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -220,7 +233,8 @@ int ha_blackhole::index_read_map(uchar * buf, const uchar * key,
int rc;
DBUG_ENTER("ha_blackhole::index_read");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -235,7 +249,8 @@ int ha_blackhole::index_read_idx_map(uchar * buf, uint idx, const uchar * key,
int rc;
DBUG_ENTER("ha_blackhole::index_read_idx");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -249,7 +264,8 @@ int ha_blackhole::index_read_last_map(uchar * buf, const uchar * key,
int rc;
DBUG_ENTER("ha_blackhole::index_read_last");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
2
3
[Commits] 42129dae63c: MDEV-18741: Optimizer trace: multi-part key ranges are printed incorrectly
by Varun 27 May '19
by Varun 27 May '19
27 May '19
revision-id: 42129dae63c4331b01f9a504c9f3ef1c0c1f857a (mariadb-10.4.4-126-g42129dae63c)
parent(s): 592fe954ef82be1bc08b29a8e54f7729eb1e1343
author: Varun Gupta
committer: Varun Gupta
timestamp: 2019-05-24 14:43:44 +0530
message:
MDEV-18741: Optimizer trace: multi-part key ranges are printed incorrectly
Changed the function append_range_all_keyparts to use sel_arg_range_seq_init / sel_arg_range_seq_next to produce ranges.
Also adjusted to print format for the ranges, now the ranges are printed as:
(keypart1_min, keypart2_min,..) OP (keypart1_name,keypart2_name, ..) OP (keypart1_max,keypart2_max, ..)
Also added more tests for range and index merge access for optimizer trace
---
mysql-test/main/opt_trace.result | 276 ++++++++++-
mysql-test/main/opt_trace.test | 57 +++
mysql-test/main/opt_trace_index_merge.result | 509 ++++++++++++++++++++-
mysql-test/main/opt_trace_index_merge.test | 112 +++++
.../main/opt_trace_index_merge_innodb.result | 6 +-
sql/opt_range.cc | 351 +++++++-------
sql/opt_range.h | 7 +-
sql/opt_range_mrr.cc | 10 +-
8 files changed, 1122 insertions(+), 206 deletions(-)
diff --git a/mysql-test/main/opt_trace.result b/mysql-test/main/opt_trace.result
index 12d4c713886..3e4b7fe6e8a 100644
--- a/mysql-test/main/opt_trace.result
+++ b/mysql-test/main/opt_trace.result
@@ -1248,7 +1248,7 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
{
"index": "a",
"covering": true,
- "ranges": ["2 <= b <= 2 AND 3 <= c <= 3"],
+ "ranges": ["(2,3) <= (b,c) <= (2,3)"],
"rows": 8,
"cost": 2.2
}
@@ -1264,7 +1264,7 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
"rows": 8,
"cost": 2.2,
"key_parts_used_for_access": ["a", "b", "c"],
- "ranges": ["2 <= b <= 2 AND 3 <= c <= 3"],
+ "ranges": ["(2,3) <= (b,c) <= (2,3)"],
"chosen": false,
"cause": "cost"
},
@@ -1446,7 +1446,7 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
{
"index": "id",
"covering": true,
- "ranges": ["0x24a20f <= a"],
+ "ranges": ["(0x24a20f) <= (a)"],
"rows": 9,
"cost": 2.35
}
@@ -1462,7 +1462,7 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
"rows": 9,
"cost": 2.35,
"key_parts_used_for_access": ["id"],
- "ranges": ["0x24a20f <= a"],
+ "ranges": ["(0x24a20f) <= (a)"],
"chosen": false,
"cause": "cost"
},
@@ -1624,7 +1624,7 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
{
"index": "id",
"covering": true,
- "ranges": ["0x24a20f <= a <= 0x24a20f"],
+ "ranges": ["(0x24a20f) <= (a) <= (0x24a20f)"],
"rows": 9,
"cost": 2.35
}
@@ -1640,7 +1640,7 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
"rows": 9,
"cost": 2.35,
"key_parts_used_for_access": ["id", "a"],
- "ranges": ["0x24a20f <= a <= 0x24a20f"],
+ "ranges": ["(0x24a20f) <= (a) <= (0x24a20f)"],
"chosen": false,
"cause": "cost"
},
@@ -1856,7 +1856,7 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
"range_scan_alternatives": [
{
"index": "a_c",
- "ranges": ["1 <= a <= 1"],
+ "ranges": ["(1) <= (a) <= (1)"],
"rowid_ordered": false,
"using_mrr": false,
"index_only": false,
@@ -1866,7 +1866,7 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
},
{
"index": "a_b",
- "ranges": ["1 <= a <= 1 AND 2 <= b <= 2"],
+ "ranges": ["(1,2) <= (a,b) <= (1,2)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
@@ -1885,7 +1885,7 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
"type": "range_scan",
"index": "a_b",
"rows": 21,
- "ranges": ["1 <= a <= 1 AND 2 <= b <= 2"]
+ "ranges": ["(1,2) <= (a,b) <= (1,2)"]
},
"rows_for_plan": 21,
"cost_for_plan": 27.445,
@@ -2025,7 +2025,7 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
"range_scan_alternatives": [
{
"index": "a_c",
- "ranges": ["1 <= a <= 1"],
+ "ranges": ["(1) <= (a) <= (1)"],
"rowid_ordered": false,
"using_mrr": false,
"index_only": false,
@@ -2044,7 +2044,7 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
"type": "range_scan",
"index": "a_c",
"rows": 180,
- "ranges": ["1 <= a <= 1"]
+ "ranges": ["(1) <= (a) <= (1)"]
},
"rows_for_plan": 180,
"cost_for_plan": 231.72,
@@ -2895,7 +2895,7 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
"range_scan_alternatives": [
{
"index": "pk",
- "ranges": ["2 <= pk <= 2"],
+ "ranges": ["(2) <= (pk) <= (2)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
@@ -2906,7 +2906,7 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
},
{
"index": "pk_a",
- "ranges": ["2 <= pk <= 2 AND 5 <= a <= 5"],
+ "ranges": ["(2,5) <= (pk,a) <= (2,5)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
@@ -2917,7 +2917,7 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
},
{
"index": "pk_a_b",
- "ranges": ["2 <= pk <= 2 AND 5 <= a <= 5 AND 1 <= b <= 1"],
+ "ranges": ["(2,5,1) <= (pk,a,b) <= (2,5,1)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": true,
@@ -2964,7 +2964,7 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
"type": "range_scan",
"index": "pk_a_b",
"rows": 1,
- "ranges": ["2 <= pk <= 2 AND 5 <= a <= 5 AND 1 <= b <= 1"]
+ "ranges": ["(2,5,1) <= (pk,a,b) <= (2,5,1)"]
},
"rows_for_plan": 1,
"cost_for_plan": 1.1793,
@@ -3338,7 +3338,7 @@ explain delete from t0 where t0.a<3 {
"range_scan_alternatives": [
{
"index": "a",
- "ranges": ["NULL < a < 3"],
+ "ranges": ["(NULL) < (a) < (3)"],
"rowid_ordered": false,
"using_mrr": false,
"index_only": false,
@@ -3354,7 +3354,7 @@ explain delete from t0 where t0.a<3 {
"type": "range_scan",
"index": "a",
"rows": 3,
- "ranges": ["NULL < a < 3"]
+ "ranges": ["(NULL) < (a) < (3)"]
},
"rows_for_plan": 3,
"cost_for_plan": 5.007,
@@ -3481,7 +3481,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"range_scan_alternatives": [
{
"index": "a",
- "ranges": ["NULL < a < 3"],
+ "ranges": ["(NULL) < (a) < (3)"],
"rowid_ordered": false,
"using_mrr": false,
"index_only": true,
@@ -3500,7 +3500,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"type": "range_scan",
"index": "a",
"rows": 3,
- "ranges": ["NULL < a < 3"]
+ "ranges": ["(NULL) < (a) < (3)"]
},
"rows_for_plan": 3,
"cost_for_plan": 1.407,
@@ -3546,7 +3546,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"range_scan_alternatives": [
{
"index": "a",
- "ranges": ["NULL < a < 3"],
+ "ranges": ["(NULL) < (a) < (3)"],
"rowid_ordered": false,
"using_mrr": false,
"index_only": true,
@@ -3565,7 +3565,7 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"type": "range_scan",
"index": "a",
"rows": 3,
- "ranges": ["NULL < a < 3"]
+ "ranges": ["(NULL) < (a) < (3)"]
},
"rows_for_plan": 3,
"cost_for_plan": 1.407,
@@ -6034,4 +6034,238 @@ COUNT(*)
1
DROP VIEW v1;
DROP TABLE t1;
+#
+# MDEV-18741: Optimizer trace: multi-part key ranges are printed incorrectly.
+#
+create table t0(a int);
+insert into t0 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 t0 A, t0 B, t0 C;
+create table t1 ( a int, b int, key a_b(a,b));
+insert into t1 select a,a from one_k;
+set optimizer_trace='enabled=on';
+explain select * from t1 force index (a_b) where a=2 and b=4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a_b a_b 10 const,const 1 Using index
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
+[
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "a_b",
+ "ranges":
+ [
+ "(2,4) <= (a,b) <= (2,4)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 1,
+ "cost": 1.1783,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union":
+ [
+ ]
+ }
+]
+explain select * from t1 where a >= 900 and b between 10 and 20;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a_b a_b 10 NULL 107 Using where; Using index
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
+[
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "a_b",
+ "ranges":
+ [
+ "(900,10) <= (a,b)"
+ ],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 107,
+ "cost": 10.955,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union":
+ [
+ ]
+ }
+]
+drop table t0,t1;
+create table t1 (start_date date, end_date date, filler char(100), key(start_date, end_date)) ;
+insert into t1 select date_add(now(), interval a day), date_add(now(), interval (a+7) day), 'data' from one_k;
+explain select * from t1 force index(start_date) where start_date >= '2019-02-10' and end_date <'2019-04-01';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range start_date start_date 8 NULL 1000 Using index condition
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
+[
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "start_date",
+ "ranges":
+ [
+ "(0x4ac60f,NULL) < (start_date,end_date)"
+ ],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 1000,
+ "cost": 1282.2,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union":
+ [
+ ]
+ }
+]
+drop table t1,one_k;
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (
+a int not null,
+b int not null,
+c int not null,
+d int not null,
+key a_b_c(a,b,c)
+);
+insert into t1 select a,a, a,a from ten;
+explain select * from t1 force index(a_b_c) where a between 1 and 4 and b < 50;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a_b_c a_b_c 8 NULL 4 Using index condition
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
+[
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "a_b_c",
+ "ranges":
+ [
+ "(1) <= (a,b) < (4,50)"
+ ],
+ "rowid_ordered": false,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 4,
+ "cost": 6.2648,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union":
+ [
+ ]
+ }
+]
+drop table ten,t1;
+# Ported test from MYSQL for ranges involving Binary column
+CREATE TABLE t1(i INT PRIMARY KEY, b BINARY(16), INDEX i_b(b));
+INSERT INTO t1 VALUES (1, x'D95B94336A9946A39CF5B58CFE772D8C');
+INSERT INTO t1 VALUES (2, NULL);
+EXPLAIN SELECT * FROM t1 WHERE b IN (0xD95B94336A9946A39CF5B58CFE772D8C);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref i_b i_b 17 const 1 Using index condition
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
+[
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "i_b",
+ "ranges":
+ [
+ "(0xd95b94336a9946a39cf5b58cfe772d8c) <= (b) <= (0xd95b94336a9946a39cf5b58cfe772d8c)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 1,
+ "cost": 2.3797,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union":
+ [
+ ]
+ }
+]
+EXPLAIN SELECT * FROM t1 WHERE b IS NULL;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref i_b i_b 17 const 1 Using index condition
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
+[
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "i_b",
+ "ranges":
+ [
+ "(NULL) <= (b) <= (NULL)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 1,
+ "cost": 2.3797,
+ "chosen": true
+ }
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union":
+ [
+ ]
+ }
+]
+drop table t1;
set optimizer_trace='enabled=off';
diff --git a/mysql-test/main/opt_trace.test b/mysql-test/main/opt_trace.test
index 4ec7c338acd..981a53ac1ad 100644
--- a/mysql-test/main/opt_trace.test
+++ b/mysql-test/main/opt_trace.test
@@ -387,4 +387,61 @@ SELECT COUNT(*) FROM v1 WHERE MATCH (f) AGAINST ('fooba');
DROP VIEW v1;
DROP TABLE t1;
+--echo #
+--echo # MDEV-18741: Optimizer trace: multi-part key ranges are printed incorrectly.
+--echo #
+
+create table t0(a int);
+insert into t0 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 t0 A, t0 B, t0 C;
+create table t1 ( a int, b int, key a_b(a,b));
+insert into t1 select a,a from one_k;
+set optimizer_trace='enabled=on';
+
+explain select * from t1 force index (a_b) where a=2 and b=4;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+explain select * from t1 where a >= 900 and b between 10 and 20;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+drop table t0,t1;
+
+create table t1 (start_date date, end_date date, filler char(100), key(start_date, end_date)) ;
+--disable_warnings
+insert into t1 select date_add(now(), interval a day), date_add(now(), interval (a+7) day), 'data' from one_k;
+--enable_warnings
+explain select * from t1 force index(start_date) where start_date >= '2019-02-10' and end_date <'2019-04-01';
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table t1,one_k;
+
+create table ten(a int);
+insert into ten values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (
+ a int not null,
+ b int not null,
+ c int not null,
+ d int not null,
+ key a_b_c(a,b,c)
+);
+
+insert into t1 select a,a, a,a from ten;
+explain select * from t1 force index(a_b_c) where a between 1 and 4 and b < 50;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+drop table ten,t1;
+
+--echo # Ported test from MYSQL for ranges involving Binary column
+
+CREATE TABLE t1(i INT PRIMARY KEY, b BINARY(16), INDEX i_b(b));
+INSERT INTO t1 VALUES (1, x'D95B94336A9946A39CF5B58CFE772D8C');
+INSERT INTO t1 VALUES (2, NULL);
+
+EXPLAIN SELECT * FROM t1 WHERE b IN (0xD95B94336A9946A39CF5B58CFE772D8C);
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+EXPLAIN SELECT * FROM t1 WHERE b IS NULL;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+drop table t1;
+
set optimizer_trace='enabled=off';
diff --git a/mysql-test/main/opt_trace_index_merge.result b/mysql-test/main/opt_trace_index_merge.result
index 50daef815d6..b5e68d04615 100644
--- a/mysql-test/main/opt_trace_index_merge.result
+++ b/mysql-test/main/opt_trace_index_merge.result
@@ -110,7 +110,7 @@ explain select * from t1 where a=1 or b=1 {
"range_scan_alternatives": [
{
"index": "a",
- "ranges": ["1 <= a <= 1"],
+ "ranges": ["(1) <= (a) <= (1)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": true,
@@ -126,7 +126,7 @@ explain select * from t1 where a=1 or b=1 {
"range_scan_alternatives": [
{
"index": "b",
- "ranges": ["1 <= b <= 1"],
+ "ranges": ["(1) <= (b) <= (1)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": true,
@@ -147,7 +147,7 @@ explain select * from t1 where a=1 or b=1 {
"type": "range_scan",
"index": "a",
"rows": 1,
- "ranges": ["1 <= a <= 1"],
+ "ranges": ["(1) <= (a) <= (1)"],
"analyzing_roworder_intersect": {
"cause": "too few roworder scans"
}
@@ -156,7 +156,7 @@ explain select * from t1 where a=1 or b=1 {
"type": "range_scan",
"index": "b",
"rows": 1,
- "ranges": ["1 <= b <= 1"],
+ "ranges": ["(1) <= (b) <= (1)"],
"analyzing_roworder_intersect": {
"cause": "too few roworder scans"
}
@@ -176,13 +176,13 @@ explain select * from t1 where a=1 or b=1 {
"type": "range_scan",
"index": "a",
"rows": 1,
- "ranges": ["1 <= a <= 1"]
+ "ranges": ["(1) <= (a) <= (1)"]
},
{
"type": "range_scan",
"index": "b",
"rows": 1,
- "ranges": ["1 <= b <= 1"]
+ "ranges": ["(1) <= (b) <= (1)"]
}
]
},
@@ -243,3 +243,500 @@ explain select * from t1 where a=1 or b=1 {
drop table t0,t1;
set optimizer_trace="enabled=off";
set @@optimizer_switch= @tmp_opt_switch;
+# More tests added index_merge access
+create table t1
+(
+/* Field names reflect value(rowid) distribution, st=STairs, swt= SaWTooth */
+st_a int not null default 0,
+swt1a int not null default 0,
+swt2a int not null default 0,
+st_b int not null default 0,
+swt1b int not null default 0,
+swt2b int not null default 0,
+/* fields/keys for row retrieval tests */
+key1 int,
+key2 int,
+key3 int,
+key4 int,
+/* make rows much bigger then keys */
+filler1 char (200),
+filler2 char (200),
+filler3 char (200),
+filler4 char (200),
+filler5 char (200),
+filler6 char (200),
+/* order of keys is important */
+key sta_swt12a(st_a,swt1a,swt2a),
+key sta_swt1a(st_a,swt1a),
+key sta_swt2a(st_a,swt2a),
+key sta_swt21a(st_a,swt2a,swt1a),
+key st_a(st_a),
+key stb_swt1a_2b(st_b,swt1b,swt2a),
+key stb_swt1b(st_b,swt1b),
+key st_b(st_b),
+key(key1),
+key(key2),
+key(key3),
+key(key4)
+) ;
+create table t0 as select * from t1;
+# Printing of many insert into t0 values (....) disabled.
+alter table t1 disable keys;
+# Printing of many insert into t1 select .... from t0 disabled.
+# Printing of many insert into t1 (...) values (....) disabled.
+alter table t1 enable keys;
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, -1, -1, 'key1-key2');
+insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 100, 100, 'key4-key3');
+set optimizer_trace='enabled=on';
+# 3-way ROR-intersection
+explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3 key1,key2,key3 5,5,5 NULL 2 Using intersect(key1,key2,key3); Using where; Using index
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
+[
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "key1",
+ "ranges":
+ [
+ "(100) <= (key1) <= (100)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 2243,
+ "cost": 2862.1,
+ "chosen": true
+ },
+
+ {
+ "index": "key2",
+ "ranges":
+ [
+ "(100) <= (key2) <= (100)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 2243,
+ "cost": 2862.1,
+ "chosen": false,
+ "cause": "cost"
+ },
+
+ {
+ "index": "key3",
+ "ranges":
+ [
+ "(100) <= (key3) <= (100)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": false,
+ "rows": 2243,
+ "cost": 2862.1,
+ "chosen": false,
+ "cause": "cost"
+ }
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "intersecting_indexes":
+ [
+
+ {
+ "index": "key1",
+ "index_scan_cost": 58.252,
+ "cumulated_index_scan_cost": 58.252,
+ "disk_sweep_cost": 1923.1,
+ "cumulative_total_cost": 1981.4,
+ "usable": true,
+ "matching_rows_now": 2243,
+ "intersect_covering_with_this_index": false,
+ "chosen": true
+ },
+
+ {
+ "index": "key2",
+ "index_scan_cost": 58.252,
+ "cumulated_index_scan_cost": 116.5,
+ "disk_sweep_cost": 84.518,
+ "cumulative_total_cost": 201.02,
+ "usable": true,
+ "matching_rows_now": 77.636,
+ "intersect_covering_with_this_index": false,
+ "chosen": true
+ },
+
+ {
+ "index": "key3",
+ "index_scan_cost": 58.252,
+ "cumulated_index_scan_cost": 174.76,
+ "disk_sweep_cost": 0,
+ "cumulative_total_cost": 174.76,
+ "usable": true,
+ "matching_rows_now": 2.6872,
+ "intersect_covering_with_this_index": true,
+ "chosen": true
+ }
+ ],
+ "clustered_pk":
+ {
+ "clustered_pk_added_to_intersect": false,
+ "cause": "no clustered pk index"
+ },
+ "rows": 2,
+ "cost": 174.76,
+ "covering": true,
+ "chosen": true
+ },
+ "analyzing_index_merge_union":
+ [
+ ]
+ }
+]
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.chosen_range_access_summary')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.chosen_range_access_summary'))
+[
+
+ {
+ "range_access_plan":
+ {
+ "type": "index_roworder_intersect",
+ "rows": 2,
+ "cost": 174.76,
+ "covering": true,
+ "clustered_pk_scan": false,
+ "intersect_of":
+ [
+
+ {
+ "type": "range_scan",
+ "index": "key1",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key1) <= (100)"
+ ]
+ },
+
+ {
+ "type": "range_scan",
+ "index": "key2",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key2) <= (100)"
+ ]
+ },
+
+ {
+ "type": "range_scan",
+ "index": "key3",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key3) <= (100)"
+ ]
+ }
+ ]
+ },
+ "rows_for_plan": 2,
+ "cost_for_plan": 174.76,
+ "chosen": true
+ }
+]
+# ROR-union(ROR-intersection, ROR-range)
+explain select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index_merge key1,key2,key3,key4 key1,key2,key3,key4 5,5,5,5 NULL 154 Using union(intersect(key1,key2),intersect(key3,key4)); Using where
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives'))
+[
+
+ {
+ "range_scan_alternatives":
+ [
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "cause": "too few roworder scans"
+ },
+ "analyzing_index_merge_union":
+ [
+
+ {
+ "indexes_to_merge":
+ [
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "key1",
+ "ranges":
+ [
+ "(100) <= (key1) <= (100)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 2243,
+ "cost": 170.53,
+ "chosen": true
+ },
+
+ {
+ "index": "key2",
+ "ranges":
+ [
+ "(100) <= (key2) <= (100)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 2243,
+ "cost": 170.53,
+ "chosen": false,
+ "cause": "cost"
+ }
+ ],
+ "index_to_merge": "key1",
+ "cumulated_cost": 170.53
+ },
+
+ {
+ "range_scan_alternatives":
+ [
+
+ {
+ "index": "key3",
+ "ranges":
+ [
+ "(100) <= (key3) <= (100)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 2243,
+ "cost": 170.53,
+ "chosen": true
+ },
+
+ {
+ "index": "key4",
+ "ranges":
+ [
+ "(100) <= (key4) <= (100)"
+ ],
+ "rowid_ordered": true,
+ "using_mrr": false,
+ "index_only": true,
+ "rows": 2243,
+ "cost": 170.53,
+ "chosen": false,
+ "cause": "cost"
+ }
+ ],
+ "index_to_merge": "key3",
+ "cumulated_cost": 341.05
+ }
+ ],
+ "cost_of_reading_ranges": 341.05,
+ "use_roworder_union": true,
+ "cause": "always cheaper than non roworder retrieval",
+ "analyzing_roworder_scans":
+ [
+
+ {
+ "type": "range_scan",
+ "index": "key1",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key1) <= (100)"
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "intersecting_indexes":
+ [
+
+ {
+ "index": "key1",
+ "index_scan_cost": 58.252,
+ "cumulated_index_scan_cost": 58.252,
+ "disk_sweep_cost": 1923.1,
+ "cumulative_total_cost": 1981.4,
+ "usable": true,
+ "matching_rows_now": 2243,
+ "intersect_covering_with_this_index": false,
+ "chosen": true
+ },
+
+ {
+ "index": "key2",
+ "index_scan_cost": 58.252,
+ "cumulated_index_scan_cost": 116.5,
+ "disk_sweep_cost": 84.518,
+ "cumulative_total_cost": 201.02,
+ "usable": true,
+ "matching_rows_now": 77.636,
+ "intersect_covering_with_this_index": false,
+ "chosen": true
+ }
+ ],
+ "clustered_pk":
+ {
+ "clustered_pk_added_to_intersect": false,
+ "cause": "no clustered pk index"
+ },
+ "rows": 77,
+ "cost": 201.02,
+ "covering": false,
+ "chosen": true
+ }
+ },
+
+ {
+ "type": "range_scan",
+ "index": "key3",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key3) <= (100)"
+ ],
+ "analyzing_roworder_intersect":
+ {
+ "intersecting_indexes":
+ [
+
+ {
+ "index": "key3",
+ "index_scan_cost": 58.252,
+ "cumulated_index_scan_cost": 58.252,
+ "disk_sweep_cost": 1923.1,
+ "cumulative_total_cost": 1981.4,
+ "usable": true,
+ "matching_rows_now": 2243,
+ "intersect_covering_with_this_index": false,
+ "chosen": true
+ },
+
+ {
+ "index": "key4",
+ "index_scan_cost": 58.252,
+ "cumulated_index_scan_cost": 116.5,
+ "disk_sweep_cost": 84.518,
+ "cumulative_total_cost": 201.02,
+ "usable": true,
+ "matching_rows_now": 77.636,
+ "intersect_covering_with_this_index": false,
+ "chosen": true
+ }
+ ],
+ "clustered_pk":
+ {
+ "clustered_pk_added_to_intersect": false,
+ "cause": "no clustered pk index"
+ },
+ "rows": 77,
+ "cost": 201.02,
+ "covering": false,
+ "chosen": true
+ }
+ }
+ ],
+ "index_roworder_union_cost": 386.73,
+ "members": 2,
+ "chosen": true
+ }
+ ]
+ }
+]
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.chosen_range_access_summary')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+JSON_DETAILED(JSON_EXTRACT(trace, '$**.chosen_range_access_summary'))
+[
+
+ {
+ "range_access_plan":
+ {
+ "type": "index_roworder_union",
+ "union_of":
+ [
+
+ {
+ "type": "index_roworder_intersect",
+ "rows": 77,
+ "cost": 201.02,
+ "covering": false,
+ "clustered_pk_scan": false,
+ "intersect_of":
+ [
+
+ {
+ "type": "range_scan",
+ "index": "key1",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key1) <= (100)"
+ ]
+ },
+
+ {
+ "type": "range_scan",
+ "index": "key2",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key2) <= (100)"
+ ]
+ }
+ ]
+ },
+
+ {
+ "type": "index_roworder_intersect",
+ "rows": 77,
+ "cost": 201.02,
+ "covering": false,
+ "clustered_pk_scan": false,
+ "intersect_of":
+ [
+
+ {
+ "type": "range_scan",
+ "index": "key3",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key3) <= (100)"
+ ]
+ },
+
+ {
+ "type": "range_scan",
+ "index": "key4",
+ "rows": 2243,
+ "ranges":
+ [
+ "(100) <= (key4) <= (100)"
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ "rows_for_plan": 154,
+ "cost_for_plan": 386.73,
+ "chosen": true
+ }
+]
+drop table t0,t1;
+set optimizer_trace="enabled=off";
diff --git a/mysql-test/main/opt_trace_index_merge.test b/mysql-test/main/opt_trace_index_merge.test
index d5efaf81db5..73240b6a9e2 100644
--- a/mysql-test/main/opt_trace_index_merge.test
+++ b/mysql-test/main/opt_trace_index_merge.test
@@ -19,3 +19,115 @@ select * from information_schema.OPTIMIZER_TRACE;
drop table t0,t1;
set optimizer_trace="enabled=off";
set @@optimizer_switch= @tmp_opt_switch;
+
+--echo # More tests added index_merge access
+
+--enable_warnings
+create table t1
+(
+ /* Field names reflect value(rowid) distribution, st=STairs, swt= SaWTooth */
+ st_a int not null default 0,
+ swt1a int not null default 0,
+ swt2a int not null default 0,
+
+ st_b int not null default 0,
+ swt1b int not null default 0,
+ swt2b int not null default 0,
+
+ /* fields/keys for row retrieval tests */
+ key1 int,
+ key2 int,
+ key3 int,
+ key4 int,
+
+ /* make rows much bigger then keys */
+ filler1 char (200),
+ filler2 char (200),
+ filler3 char (200),
+ filler4 char (200),
+ filler5 char (200),
+ filler6 char (200),
+
+ /* order of keys is important */
+ key sta_swt12a(st_a,swt1a,swt2a),
+ key sta_swt1a(st_a,swt1a),
+ key sta_swt2a(st_a,swt2a),
+ key sta_swt21a(st_a,swt2a,swt1a),
+ key st_a(st_a),
+ key stb_swt1a_2b(st_b,swt1b,swt2a),
+ key stb_swt1b(st_b,swt1b),
+ key st_b(st_b),
+
+ key(key1),
+ key(key2),
+ key(key3),
+ key(key4)
+) ;
+# Fill table
+create table t0 as select * from t1;
+--disable_query_log
+--echo # Printing of many insert into t0 values (....) disabled.
+let $cnt=1000;
+while ($cnt)
+{
+ eval insert into t0 values (1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 'data1', 'data2', 'data3', 'data4', 'data5', 'data6');
+ dec $cnt;
+}
+--enable_query_log
+
+alter table t1 disable keys;
+--disable_query_log
+--echo # Printing of many insert into t1 select .... from t0 disabled.
+let $1=4;
+while ($1)
+{
+ let $2=4;
+ while ($2)
+ {
+ let $3=4;
+ while ($3)
+ {
+ eval insert into t1 select $1, $2, $3, $1 ,$2, $3, key1, key2, key3, key4, filler1, filler2, filler3, filler4, filler5, filler6 from t0;
+ dec $3;
+ }
+ dec $2;
+ }
+ dec $1;
+}
+
+--echo # Printing of many insert into t1 (...) values (....) disabled.
+# Row retrieval tests
+# -1 is used for values 'out of any range we are using'
+# insert enough rows for index intersection to be used for (key1,key2)
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, 100, 100,'key1-key2-key3-key4');
+let $cnt=400;
+while ($cnt)
+{
+ eval insert into t1 (key1, key2, key3, key4, filler1) values (100, -1, 100, -1,'key1-key3');
+ dec $cnt;
+}
+let $cnt=400;
+while ($cnt)
+{
+ eval insert into t1 (key1, key2, key3, key4, filler1) values (-1, 100, -1, 100,'key2-key4');
+ dec $cnt;
+}
+--enable_query_log
+alter table t1 enable keys;
+
+insert into t1 (key1, key2, key3, key4, filler1) values (100, 100, -1, -1, 'key1-key2');
+insert into t1 (key1, key2, key3, key4, filler1) values (-1, -1, 100, 100, 'key4-key3');
+set optimizer_trace='enabled=on';
+
+--echo # 3-way ROR-intersection
+explain select key1,key2,key3 from t1 where key1=100 and key2=100 and key3=100;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.chosen_range_access_summary')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+--echo # ROR-union(ROR-intersection, ROR-range)
+explain select key1,key2,key3,key4 from t1 where key1=100 and key2=100 or key3=100 and key4=100;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.analyzing_range_alternatives')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+select JSON_DETAILED(JSON_EXTRACT(trace, '$**.chosen_range_access_summary')) from INFORMATION_SCHEMA.OPTIMIZER_TRACE;
+
+drop table t0,t1;
+set optimizer_trace="enabled=off";
diff --git a/mysql-test/main/opt_trace_index_merge_innodb.result b/mysql-test/main/opt_trace_index_merge_innodb.result
index 94e9d4f58cc..6a245cc83da 100644
--- a/mysql-test/main/opt_trace_index_merge_innodb.result
+++ b/mysql-test/main/opt_trace_index_merge_innodb.result
@@ -116,7 +116,7 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
"range_scan_alternatives": [
{
"index": "PRIMARY",
- "ranges": ["pk1 < 0", "0 < pk1"],
+ "ranges": ["(pk1) < (0)", "(0) < (pk1)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
@@ -127,7 +127,7 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
},
{
"index": "key1",
- "ranges": ["1 <= key1 <= 1"],
+ "ranges": ["(1) <= (key1) <= (1)"],
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
@@ -164,7 +164,7 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
"type": "range_scan",
"index": "key1",
"rows": 1,
- "ranges": ["1 <= key1 <= 1"]
+ "ranges": ["(1) <= (key1) <= (1)"]
},
"rows_for_plan": 1,
"cost_for_plan": 2.3751,
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 7e432aca42a..bff5bd371b6 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -328,8 +328,6 @@ class PARAM : public RANGE_OPT_PARAM
uint *imerge_cost_buff; /* buffer for index_merge cost estimates */
uint imerge_cost_buff_size; /* size of the buffer */
- /* TRUE if last checked tree->key can be used for ROR-scan */
- bool is_ror_scan;
/* Number of ranges in the last checked tree->key */
uint n_ranges;
uint8 first_null_comp; /* first null component if any, 0 - otherwise */
@@ -351,7 +349,7 @@ static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts);
static ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
SEL_ARG *tree, bool update_tbl_stats,
uint *mrr_flags, uint *bufsize,
- Cost_estimate *cost);
+ Cost_estimate *cost, bool *is_ror_scan);
QUICK_RANGE_SELECT *get_quick_select(PARAM *param,uint index,
SEL_ARG *key_tree, uint mrr_flags,
@@ -431,16 +429,18 @@ static int and_range_trees(RANGE_OPT_PARAM *param,
static bool remove_nonrange_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree);
static void print_key_value(String *out, const KEY_PART_INFO *key_part,
- const uchar *key);
+ const uchar* key, uint length);
+static void print_keyparts_name(String *out, const KEY_PART_INFO *key_part,
+ uint n_keypart, key_part_map keypart_map);
-static void append_range_all_keyparts(Json_writer_array *range_trace,
- String *range_string,
- String *range_so_far, const SEL_ARG *keypart,
- const KEY_PART_INFO *key_parts);
+static void trace_ranges(Json_writer_array *range_trace,
+ PARAM *param, uint idx,
+ SEL_ARG *keypart,
+ const KEY_PART_INFO *key_parts);
static
-void append_range(String *out, const KEY_PART_INFO *key_parts,
- const uchar *min_key, const uchar *max_key, const uint flag);
+void print_range(String *out, const KEY_PART_INFO *key_part,
+ KEY_MULTI_RANGE *range, uint n_key_parts);
/*
@@ -2208,7 +2208,7 @@ class TABLE_READ_PLAN
@param param Parameters for range analysis of this table
@param trace_object The optimizer trace object the info is appended to
*/
- virtual void trace_basic_info(const PARAM *param,
+ virtual void trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const= 0;
};
@@ -2251,11 +2251,11 @@ class TRP_RANGE : public TABLE_READ_PLAN
}
DBUG_RETURN(quick);
}
- void trace_basic_info(const PARAM *param,
+ void trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const;
};
-void TRP_RANGE::trace_basic_info(const PARAM *param,
+void TRP_RANGE::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
DBUG_ASSERT(param->using_real_indexes);
@@ -2273,10 +2273,7 @@ void TRP_RANGE::trace_basic_info(const PARAM *param,
// TRP_RANGE should not be created if there are no range intervals
DBUG_ASSERT(key);
- String range_info;
- range_info.length(0);
- range_info.set_charset(system_charset_info);
- append_range_all_keyparts(&trace_range, NULL, &range_info, key, key_part);
+ trace_ranges(&trace_range, param, key_idx, key, key_part);
}
@@ -2296,7 +2293,7 @@ class TRP_ROR_INTERSECT : public TABLE_READ_PLAN
struct st_ror_scan_info *cpk_scan; /* Clustered PK scan, if there is one */
bool is_covering; /* TRUE if no row retrieval phase is necessary */
double index_scan_costs; /* SUM(cost(index_scan)) */
- void trace_basic_info(const PARAM *param,
+ void trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const;
};
@@ -2317,11 +2314,11 @@ class TRP_ROR_UNION : public TABLE_READ_PLAN
MEM_ROOT *parent_alloc);
TABLE_READ_PLAN **first_ror; /* array of ptrs to plans for merged scans */
TABLE_READ_PLAN **last_ror; /* end of the above array */
- void trace_basic_info(const PARAM *param,
+ void trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const;
};
-void TRP_ROR_UNION::trace_basic_info(const PARAM *param,
+void TRP_ROR_UNION::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
@@ -2351,12 +2348,12 @@ class TRP_INDEX_INTERSECT : public TABLE_READ_PLAN
TRP_RANGE **range_scans_end; /* end of the array */
/* keys whose scans are to be filtered by cpk conditions */
key_map filtered_scans;
- void trace_basic_info(const PARAM *param,
+ void trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const;
};
-void TRP_INDEX_INTERSECT::trace_basic_info(const PARAM *param,
+void TRP_INDEX_INTERSECT::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
@@ -2385,11 +2382,11 @@ class TRP_INDEX_MERGE : public TABLE_READ_PLAN
MEM_ROOT *parent_alloc);
TRP_RANGE **range_scans; /* array of ptrs to plans of merged scans */
TRP_RANGE **range_scans_end; /* end of the array */
- void trace_basic_info(const PARAM *param,
+ void trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const;
};
-void TRP_INDEX_MERGE::trace_basic_info(const PARAM *param,
+void TRP_INDEX_MERGE::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
@@ -2452,12 +2449,12 @@ class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
MEM_ROOT *parent_alloc);
void use_index_scan() { is_index_scan= TRUE; }
- void trace_basic_info(const PARAM *param,
+ void trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const;
};
-void TRP_GROUP_MIN_MAX::trace_basic_info(const PARAM *param,
+void TRP_GROUP_MIN_MAX::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
@@ -2489,10 +2486,8 @@ void TRP_GROUP_MIN_MAX::trace_basic_info(const PARAM *param,
// can have group quick without ranges
if (index_tree)
{
- String range_info;
- range_info.set_charset(system_charset_info);
- append_range_all_keyparts(&trace_range, NULL, &range_info, index_tree,
- key_part);
+ trace_ranges(&trace_range, param, param_idx,
+ index_tree, key_part);
}
}
@@ -3176,6 +3171,7 @@ double records_in_column_ranges(PARAM *param, uint idx,
seq.real_keyno= MAX_KEY;
seq.param= param;
seq.start= tree;
+ seq.is_ror_scan= FALSE;
seq_it= seq_if.init((void *) &seq, 0, flags);
@@ -3395,7 +3391,6 @@ bool calculate_cond_selectivity_for_table(THD *thd, TABLE *table, Item **cond)
param.mem_root= &alloc;
param.old_root= thd->mem_root;
param.table= table;
- param.is_ror_scan= FALSE;
param.remove_false_where_parts= true;
if (create_key_parts_for_pseudo_indexes(¶m, used_fields))
@@ -6374,7 +6369,7 @@ typedef struct st_ror_scan_info : INDEX_SCAN_INFO
{
} ROR_SCAN_INFO;
-void TRP_ROR_INTERSECT::trace_basic_info(const PARAM *param,
+void TRP_ROR_INTERSECT::trace_basic_info(PARAM *param,
Json_writer_object *trace_object) const
{
THD *thd= param->thd;
@@ -6397,20 +6392,9 @@ void TRP_ROR_INTERSECT::trace_basic_info(const PARAM *param,
trace_isect_idx.add("rows", (*cur_scan)->records);
Json_writer_array trace_range(thd, "ranges");
- for (const SEL_ARG *current= (*cur_scan)->sel_arg->first(); current;
- current= current->next)
- {
- String range_info;
- range_info.set_charset(system_charset_info);
- for (const SEL_ARG *part= current; part;
- part= part->next_key_part ? part->next_key_part : nullptr)
- {
- const KEY_PART_INFO *cur_key_part= key_part + part->part;
- append_range(&range_info, cur_key_part, part->min_value,
- part->max_value, part->min_flag | part->max_flag);
- }
- trace_range.add(range_info.ptr(), range_info.length());
- }
+
+ trace_ranges(&trace_range, param, (*cur_scan)->idx,
+ (*cur_scan)->sel_arg, key_part);
}
}
@@ -7363,6 +7347,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
Cost_estimate cost;
double found_read_time;
uint mrr_flags, buf_size;
+ bool is_ror_scan= FALSE;
INDEX_SCAN_INFO *index_scan;
uint keynr= param->real_keynr[idx];
if (key->type == SEL_ARG::MAYBE_KEY ||
@@ -7377,7 +7362,7 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
found_records= check_quick_select(param, idx, read_index_only, key,
update_tbl_stats, &mrr_flags,
- &buf_size, &cost);
+ &buf_size, &cost, &is_ror_scan);
if (found_records != HA_POS_ERROR && tree->index_scans &&
(index_scan= (INDEX_SCAN_INFO *)alloc_root(param->mem_root,
@@ -7388,9 +7373,6 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
const KEY &cur_key= param->table->key_info[keynr];
const KEY_PART_INFO *key_part= cur_key.key_part;
- String range_info;
- range_info.set_charset(system_charset_info);
-
index_scan->idx= idx;
index_scan->keynr= keynr;
index_scan->key_info= ¶m->table->key_info[keynr];
@@ -7401,17 +7383,16 @@ static TRP_RANGE *get_key_scans_params(PARAM *param, SEL_TREE *tree,
*tree->index_scans_end++= index_scan;
if (unlikely(thd->trace_started()))
- append_range_all_keyparts(&trace_range, NULL, &range_info, key,
- key_part);
+ trace_ranges(&trace_range, param, idx, key, key_part);
trace_range.end();
- trace_idx.add("rowid_ordered", param->is_ror_scan)
+ trace_idx.add("rowid_ordered", is_ror_scan)
.add("using_mrr", !(mrr_flags & HA_MRR_USE_DEFAULT_IMPL))
.add("index_only", read_index_only)
.add("rows", found_records)
.add("cost", cost.total_cost());
}
- if ((found_records != HA_POS_ERROR) && param->is_ror_scan)
+ if ((found_records != HA_POS_ERROR) && is_ror_scan)
{
tree->n_ror_scans++;
tree->ror_scans_map.set_bit(idx);
@@ -11026,7 +11007,8 @@ void SEL_ARG::test_use_count(SEL_ARG *root)
static
ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
SEL_ARG *tree, bool update_tbl_stats,
- uint *mrr_flags, uint *bufsize, Cost_estimate *cost)
+ uint *mrr_flags, uint *bufsize, Cost_estimate *cost,
+ bool *is_ror_scan)
{
SEL_ARG_RANGE_SEQ seq;
RANGE_SEQ_IF seq_if = {NULL, sel_arg_range_seq_init, sel_arg_range_seq_next, 0, 0};
@@ -11051,9 +11033,9 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
param->range_count=0;
param->max_key_part=0;
- param->is_ror_scan= TRUE;
+ seq.is_ror_scan= TRUE;
if (file->index_flags(keynr, 0, TRUE) & HA_KEY_SCAN_NOT_ROR)
- param->is_ror_scan= FALSE;
+ seq.is_ror_scan= FALSE;
*mrr_flags= param->force_default_mrr? HA_MRR_USE_DEFAULT_IMPL: 0;
/*
@@ -11106,12 +11088,12 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
TODO: Don't have this logic here, make table engines return
appropriate flags instead.
*/
- param->is_ror_scan= FALSE;
+ seq.is_ror_scan= FALSE;
}
else if (param->table->s->primary_key == keynr && pk_is_clustered)
{
/* Clustered PK scan is always a ROR scan (TODO: same as above) */
- param->is_ror_scan= TRUE;
+ seq.is_ror_scan= TRUE;
}
else if (param->range_count > 1)
{
@@ -11121,8 +11103,9 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
(1,3)" returns ROR order for all records with x=1, then ROR
order for records with x=3
*/
- param->is_ror_scan= FALSE;
+ seq.is_ror_scan= FALSE;
}
+ *is_ror_scan= seq.is_ror_scan;
DBUG_PRINT("exit", ("Records: %lu", (ulong) rows));
DBUG_RETURN(rows); //psergey-merge:todo: maintain first_null_comp.
@@ -13547,21 +13530,19 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
Cost_estimate dummy_cost;
uint mrr_flags= HA_MRR_USE_DEFAULT_IMPL;
uint mrr_bufsize=0;
+ bool is_ror_scan= FALSE;
cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
FALSE /*don't care*/,
cur_index_tree, TRUE,
&mrr_flags, &mrr_bufsize,
- &dummy_cost);
+ &dummy_cost, &is_ror_scan);
if (unlikely(cur_index_tree && thd->trace_started()))
{
Json_writer_array trace_range(thd, "ranges");
const KEY_PART_INFO *key_part= cur_index_info->key_part;
-
- String range_info;
- range_info.set_charset(system_charset_info);
- append_range_all_keyparts(&trace_range, NULL, &range_info,
- cur_index_tree, key_part);
+ trace_ranges(&trace_range, param, cur_param_idx,
+ cur_index_tree, key_part);
}
}
cost_group_min_max(table, cur_index_info, cur_used_key_parts,
@@ -15733,12 +15714,16 @@ void QUICK_GROUP_MIN_MAX_SELECT::dbug_dump(int indent, bool verbose)
}
#endif /* !DBUG_OFF */
+
static
-void append_range(String *out, const KEY_PART_INFO *key_part,
- const uchar *min_key, const uchar *max_key, const uint flag)
+void print_range(String *out, const KEY_PART_INFO *key_part,
+ KEY_MULTI_RANGE *range, uint n_key_parts)
{
- if (out->length() > 0)
- out->append(STRING_WITH_LEN(" AND "));
+ uint flag= range->range_flag;
+ String key_name;
+ key_name.set_charset(system_charset_info);
+ key_part_map keypart_map= range->start_key.keypart_map |
+ range->end_key.keypart_map;
if (flag & GEOM_FLAG)
{
@@ -15747,22 +15732,24 @@ void append_range(String *out, const KEY_PART_INFO *key_part,
range types, so printing "col < some_geom" doesn't make sense.
Just print the column name, not operator.
*/
- out->append(key_part->field->field_name);
+ print_keyparts_name(out, key_part, n_key_parts, keypart_map);
out->append(STRING_WITH_LEN(" "));
- print_key_value(out, key_part, min_key);
+ print_key_value(out, key_part, range->start_key.key,
+ range->start_key.length);
return;
}
if (!(flag & NO_MIN_RANGE))
{
- print_key_value(out, key_part, min_key);
+ print_key_value(out, key_part, range->start_key.key,
+ range->start_key.length);
if (flag & NEAR_MIN)
out->append(STRING_WITH_LEN(" < "));
else
out->append(STRING_WITH_LEN(" <= "));
}
- out->append(key_part->field->field_name);
+ print_keyparts_name(out, key_part, n_key_parts, keypart_map);
if (!(flag & NO_MAX_RANGE))
{
@@ -15770,7 +15757,8 @@ void append_range(String *out, const KEY_PART_INFO *key_part,
out->append(STRING_WITH_LEN(" < "));
else
out->append(STRING_WITH_LEN(" <= "));
- print_key_value(out, key_part, max_key);
+ print_key_value(out, key_part, range->end_key.key,
+ range->end_key.length);
}
}
@@ -15778,60 +15766,43 @@ void append_range(String *out, const KEY_PART_INFO *key_part,
Add ranges to the trace
For ex:
- query: select * from t1 where a=2 ;
- and we have an index on a , so we create a range
- 2 <= a <= 2
+ lets say we have an index a_b(a,b)
+ query: select * from t1 where a=2 and b=4 ;
+ so we create a range:
+ (2,4) <= (a,b) <= (2,4)
this is added to the trace
*/
-static void append_range_all_keyparts(Json_writer_array *range_trace,
- String *range_string,
- String *range_so_far, const SEL_ARG *keypart,
- const KEY_PART_INFO *key_parts)
+static void trace_ranges(Json_writer_array *range_trace,
+ PARAM *param, uint idx,
+ SEL_ARG *keypart,
+ const KEY_PART_INFO *key_parts)
{
-
- DBUG_ASSERT(keypart);
- DBUG_ASSERT(keypart && keypart != &null_element);
-
- // Navigate to first interval in red-black tree
+ SEL_ARG_RANGE_SEQ seq;
+ KEY_MULTI_RANGE range;
+ range_seq_t seq_it;
+ uint flags= 0;
+ RANGE_SEQ_IF seq_if = {NULL, sel_arg_range_seq_init,
+ sel_arg_range_seq_next, 0, 0};
+ KEY *keyinfo= param->table->key_info + param->real_keynr[idx];
+ uint n_key_parts= param->table->actual_n_key_parts(keyinfo);
+ seq.keyno= idx;
+ seq.real_keyno= param->real_keynr[idx];
+ seq.param= param;
+ seq.start= keypart;
+ /*
+ is_ror_scan is set to FALSE here, because we are only interested
+ in iterating over all the ranges and printing them.
+ */
+ seq.is_ror_scan= FALSE;
const KEY_PART_INFO *cur_key_part= key_parts + keypart->part;
- const SEL_ARG *keypart_range= keypart->first();
- const size_t save_range_so_far_length= range_so_far->length();
-
+ seq_it= seq_if.init((void *) &seq, 0, flags);
- while (keypart_range)
+ while (!seq_if.next(seq_it, &range))
{
- // Append the current range predicate to the range String
- switch (keypart->type)
- {
- case SEL_ARG::Type::KEY_RANGE:
- append_range(range_so_far, cur_key_part, keypart_range->min_value,
- keypart_range->max_value,
- keypart_range->min_flag | keypart_range->max_flag);
- break;
- case SEL_ARG::Type::MAYBE_KEY:
- range_so_far->append("MAYBE_KEY");
- break;
- case SEL_ARG::Type::IMPOSSIBLE:
- range_so_far->append("IMPOSSIBLE");
- break;
- default:
- DBUG_ASSERT(false);
- break;
- }
-
- if (keypart_range->next_key_part &&
- keypart_range->next_key_part->part ==
- keypart_range->part + 1 &&
- keypart_range->is_singlepoint())
- {
- append_range_all_keyparts(range_trace, range_string, range_so_far,
- keypart_range->next_key_part, key_parts);
- }
- else
- range_trace->add(range_so_far->c_ptr_safe(), range_so_far->length());
- keypart_range= keypart_range->next;
- range_so_far->length(save_range_so_far_length);
+ StringBuffer<128> range_info(system_charset_info);
+ print_range(&range_info, cur_key_part, &range, n_key_parts);
+ range_trace->add(range_info.c_ptr_safe(), range_info.length());
}
}
@@ -15841,70 +15812,110 @@ static void append_range_all_keyparts(Json_writer_array *range_trace,
@param[out] out String the key is appended to
@param[in] key_part Index components description
@param[in] key Key tuple
+ @param[in] used_length length of the key tuple
*/
+
static void print_key_value(String *out, const KEY_PART_INFO *key_part,
- const uchar *key)
+ const uchar* key, uint used_length)
{
+ out->append(STRING_WITH_LEN("("));
Field *field= key_part->field;
+ StringBuffer<128> tmp(system_charset_info);
+ TABLE *table= field->table;
+ uint store_length;
+ my_bitmap_map *old_sets[2];
+ dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set);
+ const uchar *key_end= key+used_length;
- if (field->flags & BLOB_FLAG)
+ for (; key < key_end; key+=store_length, key_part++)
{
- // Byte 0 of a nullable key is the null-byte. If set, key is NULL.
- if (field->real_maybe_null() && *key)
- out->append(STRING_WITH_LEN("NULL"));
- else
- (field->type() == MYSQL_TYPE_GEOMETRY)
- ? out->append(STRING_WITH_LEN("unprintable_geometry_value"))
- : out->append(STRING_WITH_LEN("unprintable_blob_value"));
- return;
- }
+ field= key_part->field;
+ store_length= key_part->store_length;
+ if (field->flags & BLOB_FLAG)
+ {
+ // Byte 0 of a nullable key is the null-byte. If set, key is NULL.
+ if (field->real_maybe_null() && *key)
+ out->append(STRING_WITH_LEN("NULL"));
+ else
+ (field->type() == MYSQL_TYPE_GEOMETRY)
+ ? out->append(STRING_WITH_LEN("unprintable_geometry_value"))
+ : out->append(STRING_WITH_LEN("unprintable_blob_value"));
+ goto next;
+ }
- uint store_length= key_part->store_length;
+ if (field->real_maybe_null())
+ {
+ /*
+ Byte 0 of key is the null-byte. If set, key is NULL.
+ Otherwise, print the key value starting immediately after the
+ null-byte
+ */
+ if (*key)
+ {
+ out->append(STRING_WITH_LEN("NULL"));
+ goto next;
+ }
+ key++; // Skip null byte
+ store_length--;
+ }
- if (field->real_maybe_null())
- {
/*
- Byte 0 of key is the null-byte. If set, key is NULL.
- Otherwise, print the key value starting immediately after the
- null-byte
+ Binary data cannot be converted to UTF8 which is what the
+ optimizer trace expects. If the column is binary, the hex
+ representation is printed to the trace instead.
*/
- if (*key)
+ if (field->flags & BINARY_FLAG)
{
- out->append(STRING_WITH_LEN("NULL"));
- return;
+ out->append("0x");
+ for (uint i = 0; i < store_length; i++)
+ {
+ out->append(_dig_vec_lower[*(key + i) >> 4]);
+ out->append(_dig_vec_lower[*(key + i) & 0x0F]);
+ }
+ goto next;
}
- key++; // Skip null byte
- store_length--;
+
+ field->set_key_image(key, key_part->length);
+ if (field->type() == MYSQL_TYPE_BIT)
+ (void)field->val_int_as_str(&tmp, 1); // may change tmp's charset
+ else
+ field->val_str(&tmp); // may change tmp's charset
+ out->append(tmp.ptr(), tmp.length(), tmp.charset());
+
+ next:
+ if (key + store_length < key_end)
+ out->append(STRING_WITH_LEN(","));
}
+ dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets);
+ out->append(STRING_WITH_LEN(")"));
+}
- /*
- Binary data cannot be converted to UTF8 which is what the
- optimizer trace expects. If the column is binary, the hex
- representation is printed to the trace instead.
- */
- if (field->flags & BINARY_FLAG)
+/**
+ Print key parts involed in a range
+ @param[out] out String the key is appended to
+ @param[in] key_part Index components description
+ @param[in] n_keypart Number of keyparts in index
+ @param[in] keypart_map map for keyparts involved in the range
+*/
+
+void print_keyparts_name(String *out, const KEY_PART_INFO *key_part,
+ uint n_keypart, key_part_map keypart_map)
+{
+ uint i;
+ out->append(STRING_WITH_LEN("("));
+ bool first_keypart= TRUE;
+ for (i=0; i < n_keypart; key_part++, i++)
{
- out->append("0x");
- for (uint i = 0; i < store_length; i++)
+ if (keypart_map & (1 << i))
{
- out->append(_dig_vec_lower[*(key + i) >> 4]);
- out->append(_dig_vec_lower[*(key + i) & 0x0F]);
+ if (first_keypart)
+ first_keypart= FALSE;
+ else
+ out->append(STRING_WITH_LEN(","));
+ out->append(key_part->field->field_name);
}
- return;
+ else
+ break;
}
-
- StringBuffer<128> tmp(system_charset_info);
- TABLE *table= field->table;
- my_bitmap_map *old_sets[2];
-
- dbug_tmp_use_all_columns(table, old_sets, table->read_set, table->write_set);
-
- field->set_key_image(key, key_part->length);
- if (field->type() == MYSQL_TYPE_BIT)
- (void)field->val_int_as_str(&tmp, 1); // may change tmp's charset
- else
- field->val_str(&tmp); // may change tmp's charset
- out->append(tmp.ptr(), tmp.length(), tmp.charset());
-
- dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets);
+ out->append(STRING_WITH_LEN(")"));
}
diff --git a/sql/opt_range.h b/sql/opt_range.h
index 98f6284da0f..ae0e3822272 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -458,7 +458,9 @@ class SEL_ARG :public Sql_alloc
SEL_ARG *key_tree= first();
uint res= key_tree->store_min(key[key_tree->part].store_length,
range_key, *range_key_flag);
- *range_key_flag|= key_tree->min_flag;
+ // add flags only if a key_part is written to the buffer
+ if (res)
+ *range_key_flag|= key_tree->min_flag;
if (key_tree->next_key_part &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE &&
key_tree->part != last_part &&
@@ -480,7 +482,8 @@ class SEL_ARG :public Sql_alloc
SEL_ARG *key_tree= last();
uint res=key_tree->store_max(key[key_tree->part].store_length,
range_key, *range_key_flag);
- (*range_key_flag)|= key_tree->max_flag;
+ if (res)
+ (*range_key_flag)|= key_tree->max_flag;
if (key_tree->next_key_part &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE &&
key_tree->part != last_part &&
diff --git a/sql/opt_range_mrr.cc b/sql/opt_range_mrr.cc
index 3a25da3edb2..5644e456dd4 100644
--- a/sql/opt_range_mrr.cc
+++ b/sql/opt_range_mrr.cc
@@ -53,6 +53,8 @@ typedef struct st_sel_arg_range_seq
int i; /* Index of last used element in the above array */
bool at_start; /* TRUE <=> The traversal has just started */
+ /* TRUE if last checked tree->key can be used for ROR-scan */
+ bool is_ror_scan;
} SEL_ARG_RANGE_SEQ;
@@ -165,7 +167,7 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
seq->i--;
step_down_to(seq, key_tree->next);
key_tree= key_tree->next;
- seq->param->is_ror_scan= FALSE;
+ seq->is_ror_scan= FALSE;
goto walk_right_n_up;
}
@@ -207,7 +209,7 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
!memcmp(cur[-1].min_key, cur[-1].max_key, len) &&
!key_tree->min_flag && !key_tree->max_flag))
{
- seq->param->is_ror_scan= FALSE;
+ seq->is_ror_scan= FALSE;
if (!key_tree->min_flag)
cur->min_key_parts +=
key_tree->next_key_part->store_min_key(seq->param->key[seq->keyno],
@@ -312,7 +314,7 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
range->range_flag |= UNIQUE_RANGE | (cur->min_key_flag & NULL_RANGE);
}
- if (seq->param->is_ror_scan)
+ if (seq->is_ror_scan)
{
/*
If we get here, the condition on the key was converted to form
@@ -327,7 +329,7 @@ bool sel_arg_range_seq_next(range_seq_t rseq, KEY_MULTI_RANGE *range)
(range->start_key.length == range->end_key.length) &&
!memcmp(range->start_key.key, range->end_key.key, range->start_key.length) &&
is_key_scan_ror(seq->param, seq->real_keyno, key_tree->part + 1)))
- seq->param->is_ror_scan= FALSE;
+ seq->is_ror_scan= FALSE;
}
}
seq->param->range_count++;
2
1
[Commits] dce1387e30b: MDEV-11094: Blackhole table updates on slave fail when row annotation is enabled
by sujatha 27 May '19
by sujatha 27 May '19
27 May '19
revision-id: dce1387e30b3d0784cce542c4b27316f56d5a002 (mariadb-10.1.39-43-gdce1387e30b)
parent(s): aaf53ea0b68efde4a90cabbbcaf9ca41c1fbf62f
author: Sujatha
committer: Sujatha
timestamp: 2019-05-27 17:05:27 +0530
message:
MDEV-11094: Blackhole table updates on slave fail when row annotation is enabled
Problem:
=======
rpl_blackhole.test fails when executed with following options
mysqld=--binlog_annotate_row_events=1, mysqld=--replicate_annotate_row_events=1
Test output:
------------
worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 16000..16019
rpl.rpl_blackhole_bug 'mix' [ pass ] 791
rpl.rpl_blackhole_bug 'row' [ fail ]
Replicate_Wild_Ignore_Table
Last_Errno 1032
Last_Error Could not execute Update_rows_v1 event on table test.t1; Can't find
record in 't1', Error_code: 1032; handler error HA_ERR_END_OF_FILE; the event's
master log master-bin.000001, end_log_pos 1510
Analysis:
=========
Enabling "replicate_annotate_row_events" on slave, Tells the slave to write
annotate rows events received from the master to its own binary log. The
received annotate events are applied after the Gtid event as shown below.
thd->query() will be set to the actual query received from the master, through
annotate event. Annotate_rows event should not be deleted after the event is
applied as the thd->query will be used to generate new Annotate_rows event
during applying the subsequent Rows events. After the last Rows event has been
applied, the saved Annotate_rows event (if any) will be deleted.
In balckhole engine all the DML operations are noops as they donot store any
data. They simply return success without doing any operation. But the existing
strictly expects thd->query() to be 'NULL' to identify that row based
replication is in use. This assumption will fail when row annotations are
enabled as the query is not 'NULL'. Hence various row based operations like
'update', 'delete', 'index lookup' will fail when row annotations are enabled.
Fix:
===
Extend the row based replication check to include row annotations as well.
i.e Either the thd->query() is NULL or thd->query() points to query and row
annotations are in use.
---
.../extra/rpl_tests/rpl_blackhole_basic.test | 94 +++++
.../suite/rpl/r/rpl_blackhole_row_annotate.result | 429 +++++++++++++++++++++
mysql-test/suite/rpl/t/rpl_blackhole.test | 77 +---
.../rpl/t/rpl_blackhole_row_annotate-master.opt | 1 +
.../rpl/t/rpl_blackhole_row_annotate-slave.opt | 1 +
.../suite/rpl/t/rpl_blackhole_row_annotate.test | 48 +++
storage/blackhole/ha_blackhole.cc | 28 +-
7 files changed, 596 insertions(+), 82 deletions(-)
diff --git a/mysql-test/extra/rpl_tests/rpl_blackhole_basic.test b/mysql-test/extra/rpl_tests/rpl_blackhole_basic.test
new file mode 100644
index 00000000000..6b813601982
--- /dev/null
+++ b/mysql-test/extra/rpl_tests/rpl_blackhole_basic.test
@@ -0,0 +1,94 @@
+# PURPOSE. Test that blackhole works with replication in all three
+# modes: STATEMENT, MIXED, and ROW.
+#
+# METHOD. We start by creating a table on the master and then change
+# the engine to use blackhole on the slave.
+#
+# After insert/update/delete of one or more rows, the test the
+# proceeds to check that replication is running after replicating an
+# change, that the blackhole engine does not contain anything (which
+# is just a check that the correct engine is used), and that something
+# is written to the binary log.
+#
+# Whe check INSERT, UPDATE, and DELETE statement for tables with no
+# key (forcing a range search on the slave), primary keys (using a
+# primary key lookup), and index/key with multiple matches (forcing an
+# index search).
+
+# We start with no primary key
+CREATE TABLE t1 (a INT, b INT, c INT);
+CREATE TABLE t2 (a INT, b INT, c INT);
+
+sync_slave_with_master;
+ALTER TABLE t1 ENGINE=BLACKHOLE;
+
+connection master;
+INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4);
+sync_slave_with_master;
+
+# Test insert, no primary key
+let $statement = INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4);
+source extra/rpl_tests/rpl_blackhole.test;
+
+# Test update, no primary key
+let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1;
+source extra/rpl_tests/rpl_blackhole.test;
+
+# Test delete, no primary key
+let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 1;
+source extra/rpl_tests/rpl_blackhole.test;
+
+# Test INSERT-SELECT into Blackhole, no primary key
+let $statement = INSERT INTO t1 SELECT * FROM t2;
+source extra/rpl_tests/rpl_blackhole.test;
+
+#
+# The MASTER has MyISAM as the engine for both tables. The SLAVE has Blackhole
+# on t1 (transactional engine) and MyISAM on t2 (non-transactional engine).
+#
+# In MIXED mode, the command "INSERT INTO t2 SELECT * FROM t1" is logged as
+# statement on the master. On the slave, it is tagged as unsafe because the
+# statement mixes both transactional and non-transactional engines and as such
+# its changes are logged as rows. However, due to the nature of the blackhole
+# engine, no rows are returned and thus any chain replication would make the
+# next master on the chain diverge.
+#
+# Fo this reason, we have disabled the statement.
+#
+# Test INSERT-SELECT from Blackhole, no primary key
+# let $statement = INSERT INTO t2 SELECT * FROM t1;
+# source extra/rpl_tests/rpl_blackhole.test;
+#
+
+connection master;
+ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b);
+
+# Test insert, primary key
+let $statement = INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4);
+source extra/rpl_tests/rpl_blackhole.test;
+
+# Test update, primary key
+let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2;
+source extra/rpl_tests/rpl_blackhole.test;
+
+# Test delete, primary key
+let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 2;
+source extra/rpl_tests/rpl_blackhole.test;
+
+connection master;
+ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a);
+
+# Test insert, key
+let $statement = INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4);
+source extra/rpl_tests/rpl_blackhole.test;
+
+# Test update, key
+let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3;
+source extra/rpl_tests/rpl_blackhole.test;
+
+# Test delete, key
+let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 3;
+source extra/rpl_tests/rpl_blackhole.test;
+
+connection master;
+DROP TABLE t1,t2;
diff --git a/mysql-test/suite/rpl/r/rpl_blackhole_row_annotate.result b/mysql-test/suite/rpl/r/rpl_blackhole_row_annotate.result
new file mode 100644
index 00000000000..eae15cf9f87
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_blackhole_row_annotate.result
@@ -0,0 +1,429 @@
+include/master-slave.inc
+[connection master]
+SET timestamp=1000000000;
+RESET MASTER;
+SET timestamp=1000000000;
+RESET MASTER;
+CREATE TABLE t1 (a INT, b INT, c INT);
+CREATE TABLE t2 (a INT, b INT, c INT);
+ALTER TABLE t1 ENGINE=BLACKHOLE;
+INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4);
+[on master]
+INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4);
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+[on master]
+UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1;
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+[on master]
+DELETE FROM t1 WHERE a % 2 = 0 AND b = 1;
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+[on master]
+INSERT INTO t1 SELECT * FROM t2;
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b);
+[on master]
+INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4);
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+[on master]
+UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2;
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+[on master]
+DELETE FROM t1 WHERE a % 2 = 0 AND b = 2;
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a);
+[on master]
+INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4);
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+[on master]
+UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3;
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+[on master]
+DELETE FROM t1 WHERE a % 2 = 0 AND b = 3;
+[on slave]
+# Expect 0
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+0
+>>> Something was written to binary log <<<
+DROP TABLE t1,t2;
+show binlog events in 'slave-bin.000001' from <start_pos>;
+Log_name Pos Event_type Server_id End_log_pos Info
+slave-bin.000001 # Gtid_list 2 # []
+slave-bin.000001 # Binlog_checkpoint 2 # slave-bin.000001
+slave-bin.000001 # Gtid 1 # GTID 0-1-1
+slave-bin.000001 # Query 1 # use `test`; CREATE TABLE t1 (a INT, b INT, c INT)
+slave-bin.000001 # Gtid 1 # GTID 0-1-2
+slave-bin.000001 # Query 1 # use `test`; CREATE TABLE t2 (a INT, b INT, c INT)
+slave-bin.000001 # Gtid 2 # GTID 0-2-3
+slave-bin.000001 # Query 2 # use `test`; ALTER TABLE t1 ENGINE=BLACKHOLE
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-3
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4)
+slave-bin.000001 # Table_map 1 # table_id: # (test.t2)
+slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-4
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4)
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-5
+slave-bin.000001 # Annotate_rows 1 # UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Update_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-6
+slave-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE a % 2 = 0 AND b = 1
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Delete_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-7
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t1 SELECT * FROM t2
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # GTID 0-1-8
+slave-bin.000001 # Query 1 # use `test`; ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b)
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-9
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4)
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-10
+slave-bin.000001 # Annotate_rows 1 # UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Update_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-11
+slave-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE a % 2 = 0 AND b = 2
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Delete_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # GTID 0-1-12
+slave-bin.000001 # Query 1 # use `test`; ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a)
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-13
+slave-bin.000001 # Annotate_rows 1 # INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4)
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Write_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-14
+slave-bin.000001 # Annotate_rows 1 # UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Update_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+slave-bin.000001 # Gtid 1 # BEGIN GTID 0-1-15
+slave-bin.000001 # Annotate_rows 1 # DELETE FROM t1 WHERE a % 2 = 0 AND b = 3
+slave-bin.000001 # Table_map 1 # table_id: # (test.t1)
+slave-bin.000001 # Delete_rows_v1 1 # table_id: # flags: STMT_END_F
+slave-bin.000001 # Query 1 # COMMIT
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
+DELIMITER /*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # Start: binlog v 4, server v #.##.## created 010909 7:16:40 at startup
+# Warning: this binlog is either in use or was not closed properly.
+ROLLBACK/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # Gtid list []
+# at #
+#010909 7:16:40 server id # end_log_pos # Binlog checkpoint slave-bin.000001
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-1 ddl
+/*!100101 SET @@session.skip_parallel_replication=0*//*!*/;
+/*!100001 SET @@session.gtid_domain_id=0*//*!*/;
+/*!100001 SET @@session.server_id=1*//*!*/;
+/*!100001 SET @@session.gtid_seq_no=1*//*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+use `test`/*!*/;
+SET TIMESTAMP=1000000000/*!*/;
+SET @@session.pseudo_thread_id=#/*!*/;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
+SET @@session.sql_mode=1342177280/*!*/;
+SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
+/*!\C latin1 *//*!*/;
+SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
+SET @@session.lc_time_names=0/*!*/;
+SET @@session.collation_database=DEFAULT/*!*/;
+CREATE TABLE t1 (a INT, b INT, c INT)
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-2 ddl
+/*!100001 SET @@session.gtid_seq_no=2*//*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+CREATE TABLE t2 (a INT, b INT, c INT)
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-2-3 ddl
+/*!100001 SET @@session.server_id=2*//*!*/;
+/*!100001 SET @@session.gtid_seq_no=3*//*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+ALTER TABLE t1 ENGINE=BLACKHOLE
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-3 trans
+/*!100001 SET @@session.server_id=1*//*!*/;
+/*!100001 SET @@session.gtid_seq_no=3*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4)
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t2` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-4 trans
+/*!100001 SET @@session.gtid_seq_no=4*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4)
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-5 trans
+/*!100001 SET @@session.gtid_seq_no=5*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Update_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-6 trans
+/*!100001 SET @@session.gtid_seq_no=6*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE FROM t1 WHERE a % 2 = 0 AND b = 1
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-7 trans
+/*!100001 SET @@session.gtid_seq_no=7*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO t1 SELECT * FROM t2
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-8 ddl
+/*!100001 SET @@session.gtid_seq_no=8*//*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b)
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-9 trans
+/*!100001 SET @@session.gtid_seq_no=9*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4)
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-10 trans
+/*!100001 SET @@session.gtid_seq_no=10*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Update_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-11 trans
+/*!100001 SET @@session.gtid_seq_no=11*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE FROM t1 WHERE a % 2 = 0 AND b = 2
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-12 ddl
+/*!100001 SET @@session.gtid_seq_no=12*//*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a)
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-13 trans
+/*!100001 SET @@session.gtid_seq_no=13*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4)
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Write_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-14 trans
+/*!100001 SET @@session.gtid_seq_no=14*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Update_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-15 trans
+/*!100001 SET @@session.gtid_seq_no=15*//*!*/;
+BEGIN
+/*!*/;
+# at #
+# at #
+#010909 7:16:40 server id # end_log_pos # Annotate_rows:
+#Q> DELETE FROM t1 WHERE a % 2 = 0 AND b = 3
+#010909 7:16:40 server id # end_log_pos # Table_map: `test`.`t1` mapped to number #
+# at #
+#010909 7:16:40 server id # end_log_pos # Delete_rows: table id # flags: STMT_END_F
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+COMMIT
+/*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # GTID 0-1-16 ddl
+/*!100001 SET @@session.gtid_seq_no=16*//*!*/;
+# at #
+#010909 7:16:40 server id # end_log_pos # Query thread_id=# exec_time=# error_code=0
+SET TIMESTAMP=1000000000/*!*/;
+DROP TABLE IF EXISTS `t1`,`t2` /* generated by server */
+/*!*/;
+DELIMITER ;
+# End of log file
+ROLLBACK /* added by mysqlbinlog */;
+/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
+/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole.test b/mysql-test/suite/rpl/t/rpl_blackhole.test
index 76b2e2421c9..9128382d12b 100644
--- a/mysql-test/suite/rpl/t/rpl_blackhole.test
+++ b/mysql-test/suite/rpl/t/rpl_blackhole.test
@@ -20,81 +20,6 @@ source include/master-slave.inc;
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
-# We start with no primary key
-CREATE TABLE t1 (a INT, b INT, c INT);
-CREATE TABLE t2 (a INT, b INT, c INT);
+source extra/rpl_tests/rpl_blackhole_basic.test;
-sync_slave_with_master;
-ALTER TABLE t1 ENGINE=BLACKHOLE;
-
-connection master;
-INSERT INTO t2 VALUES (1,9,1), (2,9,2), (3,9,3), (4,9,4);
-sync_slave_with_master;
-
-# Test insert, no primary key
-let $statement = INSERT INTO t1 VALUES (1,1,1),(2,1,2),(3,1,3),(4,1,4);
-source extra/rpl_tests/rpl_blackhole.test;
-
-# Test update, no primary key
-let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 1;
-source extra/rpl_tests/rpl_blackhole.test;
-
-# Test delete, no primary key
-let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 1;
-source extra/rpl_tests/rpl_blackhole.test;
-
-# Test INSERT-SELECT into Blackhole, no primary key
-let $statement = INSERT INTO t1 SELECT * FROM t2;
-source extra/rpl_tests/rpl_blackhole.test;
-
-#
-# The MASTER has MyISAM as the engine for both tables. The SLAVE has Blackhole
-# on t1 (transactional engine) and MyISAM on t2 (non-transactional engine).
-#
-# In MIXED mode, the command "INSERT INTO t2 SELECT * FROM t1" is logged as
-# statement on the master. On the slave, it is tagged as unsafe because the
-# statement mixes both transactional and non-transactional engines and as such
-# its changes are logged as rows. However, due to the nature of the blackhole
-# engine, no rows are returned and thus any chain replication would make the
-# next master on the chain diverge.
-#
-# Fo this reason, we have disabled the statement.
-#
-# Test INSERT-SELECT from Blackhole, no primary key
-# let $statement = INSERT INTO t2 SELECT * FROM t1;
-# source extra/rpl_tests/rpl_blackhole.test;
-#
-
-connection master;
-ALTER TABLE t1 ADD PRIMARY KEY pk_t1 (a,b);
-
-# Test insert, primary key
-let $statement = INSERT INTO t1 VALUES (1,2,1),(2,2,2),(3,2,3),(4,2,4);
-source extra/rpl_tests/rpl_blackhole.test;
-
-# Test update, primary key
-let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 2;
-source extra/rpl_tests/rpl_blackhole.test;
-
-# Test delete, primary key
-let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 2;
-source extra/rpl_tests/rpl_blackhole.test;
-
-connection master;
-ALTER TABLE t1 DROP PRIMARY KEY, ADD KEY key_t1 (a);
-
-# Test insert, key
-let $statement = INSERT INTO t1 VALUES (1,3,1),(2,3,2),(3,3,3),(4,3,4);
-source extra/rpl_tests/rpl_blackhole.test;
-
-# Test update, key
-let $statement = UPDATE t1 SET c = 2*c WHERE a % 2 = 0 AND b = 3;
-source extra/rpl_tests/rpl_blackhole.test;
-
-# Test delete, key
-let $statement = DELETE FROM t1 WHERE a % 2 = 0 AND b = 3;
-source extra/rpl_tests/rpl_blackhole.test;
-
-connection master;
-DROP TABLE t1,t2;
--source include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt
new file mode 100644
index 00000000000..1ad0b884c60
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-master.opt
@@ -0,0 +1 @@
+--binlog_annotate_row_events
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt
new file mode 100644
index 00000000000..7ac6a84faa7
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate-slave.opt
@@ -0,0 +1 @@
+--binlog_annotate_row_events --replicate_annotate_row_events
diff --git a/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test
new file mode 100644
index 00000000000..67c59731a23
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_blackhole_row_annotate.test
@@ -0,0 +1,48 @@
+# ==== Purpose ====
+#
+# Test verifies that when "replicate_annotate_row_events" are enabled on slave
+# the DML operations on blackhole engine will be successful. It also ensures
+# that Annotate events are logged into slave's binary log.
+#
+# ==== Implementation ====
+#
+# Steps:
+# 0 - Enable "replicate_annotate_row_events" on slave and do DML operations
+# on master.
+# 1 - Slave server will successfully apply the DML operations and it is in
+# sync with master.
+# 2 - Verify that the "show binlog events" prints all annotate events.
+# 3 - Stream the slave's binary log using "mysqlbinlog" tool and verify
+# that the Annotate events are being displayed.
+#
+# ==== References ====
+#
+# MDEV-11094: Blackhole table updates on slave fail when row annotation is
+# enabled
+
+source include/have_blackhole.inc;
+source include/have_binlog_format_row.inc;
+source include/binlog_start_pos.inc;
+source include/master-slave.inc;
+
+SET timestamp=1000000000;
+RESET MASTER;
+connection slave;
+SET timestamp=1000000000;
+RESET MASTER;
+
+connection master;
+source extra/rpl_tests/rpl_blackhole_basic.test;
+
+# Verify on slave.
+connection slave;
+--replace_column 2 # 5 #
+--replace_result $binlog_start_pos <start_pos>
+--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
+--eval show binlog events in 'slave-bin.000001' from $binlog_start_pos
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--replace_regex /server id [0-9]*/server id #/ /server v [^ ]*/server v #.##.##/ /exec_time=[0-9]*/exec_time=#/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/
+--exec $MYSQL_BINLOG --base64-output=decode-rows $MYSQLD_DATADIR/slave-bin.000001
+
+source include/rpl_end.inc;
diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
index 01aaa9ea15f..43bcdc541a1 100644
--- a/storage/blackhole/ha_blackhole.cc
+++ b/storage/blackhole/ha_blackhole.cc
@@ -25,6 +25,16 @@
#include "ha_blackhole.h"
#include "sql_class.h" // THD, SYSTEM_THREAD_SLAVE_SQL
+static bool is_row_based_replication(THD *thd)
+{
+ /*
+ A row event which has its thd->query() == NULL or a row event which has
+ replicate_annotate_row_events enabled. In the later case the thd->query()
+ will be pointing to the query, received through replicated annotate event
+ from master.
+ */
+ return ((thd->query() == NULL) || thd->variables.binlog_annotate_row_events);
+}
/* Static declarations for handlerton */
static handler *blackhole_create_handler(handlerton *hton,
@@ -109,7 +119,8 @@ int ha_blackhole::update_row(const uchar *old_data, uchar *new_data)
{
DBUG_ENTER("ha_blackhole::update_row");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
DBUG_RETURN(0);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -118,7 +129,8 @@ int ha_blackhole::delete_row(const uchar *buf)
{
DBUG_ENTER("ha_blackhole::delete_row");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
DBUG_RETURN(0);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
@@ -135,7 +147,8 @@ int ha_blackhole::rnd_next(uchar *buf)
int rc;
DBUG_ENTER("ha_blackhole::rnd_next");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -220,7 +233,8 @@ int ha_blackhole::index_read_map(uchar * buf, const uchar * key,
int rc;
DBUG_ENTER("ha_blackhole::index_read");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -235,7 +249,8 @@ int ha_blackhole::index_read_idx_map(uchar * buf, uint idx, const uchar * key,
int rc;
DBUG_ENTER("ha_blackhole::index_read_idx");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
@@ -249,7 +264,8 @@ int ha_blackhole::index_read_last_map(uchar * buf, const uchar * key,
int rc;
DBUG_ENTER("ha_blackhole::index_read_last");
THD *thd= ha_thd();
- if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL && thd->query() == NULL)
+ if (thd->system_thread == SYSTEM_THREAD_SLAVE_SQL &&
+ is_row_based_replication(thd))
rc= 0;
else
rc= HA_ERR_END_OF_FILE;
1
0
[Commits] e29f0912557: MDEV-19600: The optimizer should be able to produce rows=1 estimate for unique index with NULLable columns
by Sergei Petrunia 27 May '19
by Sergei Petrunia 27 May '19
27 May '19
revision-id: e29f091255746b7bcc331bea45d4ca2d9b47dfa2 (mariadb-10.3.12-218-ge29f0912557)
parent(s): 592dc59d7a5f9bd80bffdd9d0f003243ff639767
author: Sergei Petrunia
committer: Sergei Petrunia
timestamp: 2019-05-27 10:40:04 +0300
message:
MDEV-19600: The optimizer should be able to produce rows=1 estimate for unique index with NULLable columns
Modify best_access_path() to produce rows=1 estimate for null-rejecting
lookups on unique NULL keys.
---
mysql-test/main/invisible_field.result | 4 +-
mysql-test/main/join.result | 30 +++++++++++
mysql-test/main/join.test | 30 +++++++++++
mysql-test/main/order_by.result | 2 +-
mysql-test/main/subselect_sj.result | 74 +++++++++++++++++++++++----
mysql-test/main/subselect_sj.test | 52 ++++++++++++++++++-
mysql-test/main/subselect_sj_jcl6.result | 58 ++++++++++++++++++++-
mysql-test/main/subselect_sj_nonmerged.result | 12 ++---
mysql-test/main/table_elim.result | 2 +-
sql/sql_select.cc | 47 +++++++++++------
10 files changed, 275 insertions(+), 36 deletions(-)
diff --git a/mysql-test/main/invisible_field.result b/mysql-test/main/invisible_field.result
index 876a80814e5..43a8b9d726b 100644
--- a/mysql-test/main/invisible_field.result
+++ b/mysql-test/main/invisible_field.result
@@ -404,8 +404,8 @@ b int(11) YES NULL
c int(11) YES NULL
explain select * from t1,t2 where t1.b = t2.c and t1.c = t2.b;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL NULL NULL NULL NULL 10
-1 SIMPLE t1 ALL b,c NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
+1 SIMPLE t2 ALL NULL NULL NULL NULL 10 Using where
+1 SIMPLE t1 ref b,c b 5 test.t2.c 1 Using where
select * from t1,t2 where t1.b = t2.c and t1.c = t2.b;
a a b c
1 1 1 1
diff --git a/mysql-test/main/join.result b/mysql-test/main/join.result
index cc8e174c8e6..8ca82002855 100644
--- a/mysql-test/main/join.result
+++ b/mysql-test/main/join.result
@@ -1599,3 +1599,33 @@ SELECT STRAIGHT_JOIN * FROM t1, t2 AS t2_1, t2 AS t2_2
WHERE t2_2.c = t2_1.c AND t2_2.b = t2_1.b AND ( a IS NULL OR t2_1.c = a );
a b c b c
DROP TABLE t1,t2;
+#
+# MDEV-19600: The optimizer should be able to produce rows=1 estimate for unique index with NULLable columns
+#
+create table t0(a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t1 (
+pk int not null primary key auto_increment,
+a int,
+b int,
+unique key(a)
+);
+insert into t1 (a,b) select null, 12345 from t0 A, t0 B, t0 C;
+insert into t1 (a,b) select a,a from t0;
+# Simulate InnoDB's persistent statistics (It always uses nulls_equal)
+set @tmp1= @@myisam_stats_method;
+set myisam_stats_method=nulls_equal;
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+set myisam_stats_method=@tmp1;
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 pk A 1010 NULL NULL BTREE
+t1 0 a 1 a A 10 NULL NULL YES BTREE
+# t1 must use ref(t1.a=t0.a) and rows must be 1 (and not 45):
+explain select * from t0,t1 where t0.a=t1.a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t0 ALL NULL NULL NULL NULL 10 Using where
+1 SIMPLE t1 ref a a 5 test.t0.a 1
+drop table t0,t1;
diff --git a/mysql-test/main/join.test b/mysql-test/main/join.test
index 3d2a02e2346..b90a9cc39eb 100644
--- a/mysql-test/main/join.test
+++ b/mysql-test/main/join.test
@@ -1254,3 +1254,33 @@ SELECT STRAIGHT_JOIN * FROM t1, t2 AS t2_1, t2 AS t2_2
WHERE t2_2.c = t2_1.c AND t2_2.b = t2_1.b AND ( a IS NULL OR t2_1.c = a );
DROP TABLE t1,t2;
+
+--echo #
+--echo # MDEV-19600: The optimizer should be able to produce rows=1 estimate for unique index with NULLable columns
+--echo #
+
+create table t0(a int);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t1 (
+ pk int not null primary key auto_increment,
+ a int,
+ b int,
+ unique key(a)
+);
+
+# 10K of null values
+insert into t1 (a,b) select null, 12345 from t0 A, t0 B, t0 C;
+insert into t1 (a,b) select a,a from t0;
+
+--echo # Simulate InnoDB's persistent statistics (It always uses nulls_equal)
+set @tmp1= @@myisam_stats_method;
+set myisam_stats_method=nulls_equal;
+analyze table t1;
+set myisam_stats_method=@tmp1;
+show keys from t1;
+
+--echo # t1 must use ref(t1.a=t0.a) and rows must be 1 (and not 45):
+explain select * from t0,t1 where t0.a=t1.a;
+
+drop table t0,t1;
diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result
index 8d1e471f618..8692e727c60 100644
--- a/mysql-test/main/order_by.result
+++ b/mysql-test/main/order_by.result
@@ -1515,7 +1515,7 @@ WHERE t2.b=14 AND t2.a=t1.a AND 5.1<t2.c AND t1.b='DE'
ORDER BY t2.c LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 range a,b,c c 5 NULL 420 Using where
-1 SIMPLE t1 ref a a 39 test.t2.a,const 10 Using where; Using index
+1 SIMPLE t1 ref a a 39 test.t2.a,const 1 Using where; Using index
SELECT d FROM t3 AS t1, t2 AS t2
WHERE t2.b=14 AND t2.a=t1.a AND 5.1<t2.c AND t1.b='DE'
ORDER BY t2.c LIMIT 1;
diff --git a/mysql-test/main/subselect_sj.result b/mysql-test/main/subselect_sj.result
index 454a09771f6..77dccf24e69 100644
--- a/mysql-test/main/subselect_sj.result
+++ b/mysql-test/main/subselect_sj.result
@@ -2555,33 +2555,89 @@ CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, KEY(b) );
INSERT INTO t1 VALUES
(1,2),(2,1),(3,3),(4,2),(5,5),
(6,3),(7,1),(8,4),(9,3),(10,2);
-CREATE TABLE t2 ( c INT, d INT, UNIQUE KEY(c) );
+CREATE TABLE t2 ( c INT, d INT, KEY(c) );
INSERT INTO t2 VALUES
(1,2),(2,1),(3,3),(4,2),(5,5),(6,3),(7,1);
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+explain
+SELECT a, b, d FROM t1, t2
+WHERE ( b, d ) IN
+( SELECT b, d FROM t1, t2 WHERE b = c );
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7
+1 PRIMARY t1 index b b 5 NULL 10 Using where; Using index; LooseScan
+1 PRIMARY t2 ref c c 5 test.t1.b 1 Using where; FirstMatch(t1)
+1 PRIMARY t1 ref b b 5 test.t1.b 2
SELECT a, b, d FROM t1, t2
WHERE ( b, d ) IN
( SELECT b, d FROM t1, t2 WHERE b = c );
a b d
2 1 2
7 1 2
-2 1 2
-7 1 2
-1 2 1
-4 2 1
-10 2 1
+8 4 2
1 2 1
4 2 1
10 2 1
3 3 3
6 3 3
9 3 3
+2 1 2
+7 1 2
+8 4 2
+5 5 5
3 3 3
6 3 3
9 3 3
-8 4 2
-8 4 2
-5 5 5
+1 2 1
+4 2 1
+10 2 1
DROP TABLE t1, t2;
+# Another testcase for the above that still uses LooseScan:
+create table t0(a int primary key);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t10(a int primary key);
+insert into t10 select A.a + B.a* 10 + C.a * 100 from t0 A, t0 B, t0 C;
+create table t1 (
+pk int primary key auto_increment,
+kp1 int,
+kp2 int,
+filler char(100),
+key (kp1, kp2)
+);
+insert into t1 (kp1, kp2, filler)
+select
+A.a, B.a, 'filler-data'
+from t0 A, t0 B;
+create table t2 (a int, filler char(100), key(a));
+create table t3 (a int);
+insert into t3 values (1),(2);
+insert into t2
+select (A.a+1000*B.a)/20, 'filler_data' from t10 A, t0 B;
+analyze table t1,t2,t3;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Table is already up to date
+test.t3 analyze status OK
+delete from t1 where kp2 in (1,3);
+# Ref + LooseScan on t1:
+explain select sum(t2.a)
+from t2,t3
+where (t3.a,t2.a) in (select kp1,kp2 from t1,t0 where t0.a=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 const PRIMARY PRIMARY 4 const 1 Using index
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 10 Using where; Using index; LooseScan
+1 PRIMARY t2 ref a a 5 test.t1.kp2 20 Using index
+select sum(t2.a)
+from t2,t3
+where (t3.a,t2.a) in (select kp1,kp2 from t1,t0 where t0.a=2);
+sum(t2.a)
+1640
+drop table t0,t10;
+drop table t1,t2,t3;
#
# BUG#920713: Wrong result (missing rows) with firstmatch+BNL, IN subquery, ...
#
diff --git a/mysql-test/main/subselect_sj.test b/mysql-test/main/subselect_sj.test
index e4e31691843..83be663f642 100644
--- a/mysql-test/main/subselect_sj.test
+++ b/mysql-test/main/subselect_sj.test
@@ -2285,16 +2285,66 @@ INSERT INTO t1 VALUES
(1,2),(2,1),(3,3),(4,2),(5,5),
(6,3),(7,1),(8,4),(9,3),(10,2);
-CREATE TABLE t2 ( c INT, d INT, UNIQUE KEY(c) );
+CREATE TABLE t2 ( c INT, d INT, KEY(c) );
INSERT INTO t2 VALUES
(1,2),(2,1),(3,3),(4,2),(5,5),(6,3),(7,1);
+analyze table t1,t2;
+explain
+SELECT a, b, d FROM t1, t2
+WHERE ( b, d ) IN
+ ( SELECT b, d FROM t1, t2 WHERE b = c );
SELECT a, b, d FROM t1, t2
WHERE ( b, d ) IN
( SELECT b, d FROM t1, t2 WHERE b = c );
DROP TABLE t1, t2;
+--echo # Another testcase for the above that still uses LooseScan:
+
+create table t0(a int primary key);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+
+create table t10(a int primary key);
+insert into t10 select A.a + B.a* 10 + C.a * 100 from t0 A, t0 B, t0 C;
+
+create table t1 (
+ pk int primary key auto_increment,
+ kp1 int,
+ kp2 int,
+ filler char(100),
+ key (kp1, kp2)
+);
+
+# 10 groups, each has 10 elements.
+insert into t1 (kp1, kp2, filler)
+select
+ A.a, B.a, 'filler-data'
+from t0 A, t0 B;
+
+create table t2 (a int, filler char(100), key(a));
+
+create table t3 (a int);
+insert into t3 values (1),(2);
+
+insert into t2
+select (A.a+1000*B.a)/20, 'filler_data' from t10 A, t0 B;
+
+analyze table t1,t2,t3;
+delete from t1 where kp2 in (1,3);
+
+--echo # Ref + LooseScan on t1:
+explain select sum(t2.a)
+from t2,t3
+where (t3.a,t2.a) in (select kp1,kp2 from t1,t0 where t0.a=2);
+
+select sum(t2.a)
+from t2,t3
+where (t3.a,t2.a) in (select kp1,kp2 from t1,t0 where t0.a=2);
+
+drop table t0,t10;
+drop table t1,t2,t3;
+
--echo #
--echo # BUG#920713: Wrong result (missing rows) with firstmatch+BNL, IN subquery, ...
--echo #
diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result
index fc279b05ac2..773984ff0d4 100644
--- a/mysql-test/main/subselect_sj_jcl6.result
+++ b/mysql-test/main/subselect_sj_jcl6.result
@@ -2569,9 +2569,22 @@ CREATE TABLE t1 ( a INT PRIMARY KEY, b INT, KEY(b) );
INSERT INTO t1 VALUES
(1,2),(2,1),(3,3),(4,2),(5,5),
(6,3),(7,1),(8,4),(9,3),(10,2);
-CREATE TABLE t2 ( c INT, d INT, UNIQUE KEY(c) );
+CREATE TABLE t2 ( c INT, d INT, KEY(c) );
INSERT INTO t2 VALUES
(1,2),(2,1),(3,3),(4,2),(5,5),(6,3),(7,1);
+analyze table t1,t2;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+test.t2 analyze status OK
+explain
+SELECT a, b, d FROM t1, t2
+WHERE ( b, d ) IN
+( SELECT b, d FROM t1, t2 WHERE b = c );
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 7
+1 PRIMARY t1 index b b 5 NULL 10 Using where; Using index; LooseScan
+1 PRIMARY t2 ref c c 5 test.t1.b 1 Using where; FirstMatch(t1)
+1 PRIMARY t1 ref b b 5 test.t1.b 2 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
SELECT a, b, d FROM t1, t2
WHERE ( b, d ) IN
( SELECT b, d FROM t1, t2 WHERE b = c );
@@ -2596,6 +2609,49 @@ a b d
10 2 1
10 2 1
DROP TABLE t1, t2;
+# Another testcase for the above that still uses LooseScan:
+create table t0(a int primary key);
+insert into t0 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
+create table t10(a int primary key);
+insert into t10 select A.a + B.a* 10 + C.a * 100 from t0 A, t0 B, t0 C;
+create table t1 (
+pk int primary key auto_increment,
+kp1 int,
+kp2 int,
+filler char(100),
+key (kp1, kp2)
+);
+insert into t1 (kp1, kp2, filler)
+select
+A.a, B.a, 'filler-data'
+from t0 A, t0 B;
+create table t2 (a int, filler char(100), key(a));
+create table t3 (a int);
+insert into t3 values (1),(2);
+insert into t2
+select (A.a+1000*B.a)/20, 'filler_data' from t10 A, t0 B;
+analyze table t1,t2,t3;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+test.t2 analyze status Table is already up to date
+test.t3 analyze status OK
+delete from t1 where kp2 in (1,3);
+# Ref + LooseScan on t1:
+explain select sum(t2.a)
+from t2,t3
+where (t3.a,t2.a) in (select kp1,kp2 from t1,t0 where t0.a=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t0 const PRIMARY PRIMARY 4 const 1 Using index
+1 PRIMARY t3 ALL NULL NULL NULL NULL 2 Using where
+1 PRIMARY t1 ref kp1 kp1 5 test.t3.a 10 Using where; Using index; LooseScan
+1 PRIMARY t2 ref a a 5 test.t1.kp2 20 Using index
+select sum(t2.a)
+from t2,t3
+where (t3.a,t2.a) in (select kp1,kp2 from t1,t0 where t0.a=2);
+sum(t2.a)
+1640
+drop table t0,t10;
+drop table t1,t2,t3;
#
# BUG#920713: Wrong result (missing rows) with firstmatch+BNL, IN subquery, ...
#
diff --git a/mysql-test/main/subselect_sj_nonmerged.result b/mysql-test/main/subselect_sj_nonmerged.result
index 47970668ae5..4d9a70e6bba 100644
--- a/mysql-test/main/subselect_sj_nonmerged.result
+++ b/mysql-test/main/subselect_sj_nonmerged.result
@@ -67,9 +67,9 @@ insert into t4 select A.a + 10*B.a, A.a + 10*B.a, 'filler' from t0 A, t0 B;
explain select * from t0, t4 where
t4.b=t0.a and t4.a in (select max(t2.a) from t1, t2 group by t2.b);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t0 ALL NULL NULL NULL NULL 10
-1 PRIMARY t4 ALL a NULL NULL NULL 100 Using where; Using join buffer (flat, BNL join)
-1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t4.a 1
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 5
+1 PRIMARY t0 ALL NULL NULL NULL NULL 10 Using where; Using join buffer (flat, BNL join)
+1 PRIMARY t4 ref a a 10 <subquery2>.max(t2.a),test.t0.a 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 Using temporary
2 MATERIALIZED t1 ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join)
insert into t4 select 100 + (B.a *100 + A.a), 100 + (B.a*100 + A.a), 'filler' from t4 A, t0 B;
@@ -77,9 +77,9 @@ explain select * from t4 where
t4.a in (select max(t2.a) from t1, t2 group by t2.b) and
t4.b in (select max(t2.a) from t1, t2 group by t2.b);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 5
-1 PRIMARY t4 ref a a 5 <subquery2>.max(t2.a) 12 Using index condition
-1 PRIMARY <subquery3> eq_ref distinct_key distinct_key 4 test.t4.b 1
+1 PRIMARY <subquery3> ALL distinct_key NULL NULL NULL 5
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 5 Using join buffer (flat, BNL join)
+1 PRIMARY t4 ref a a 10 <subquery2>.max(t2.a),<subquery3>.max(t2.a) 1
3 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 Using temporary
3 MATERIALIZED t1 ALL NULL NULL NULL NULL 10 Using join buffer (flat, BNL join)
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 5 Using temporary
diff --git a/mysql-test/main/table_elim.result b/mysql-test/main/table_elim.result
index cf9a4a38779..7780e165451 100644
--- a/mysql-test/main/table_elim.result
+++ b/mysql-test/main/table_elim.result
@@ -279,7 +279,7 @@ insert into t2 values
explain select t1.* from t1 left join t2 on t2.a=t1.a;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 10 NULL 2 Using index
-1 SIMPLE t2 ref a a 3 test.t1.a 2 Using where
+1 SIMPLE t2 ref a a 3 test.t1.a 1 Using where
drop table t1, t2;
#
# check UPDATE/DELETE that look like they could be eliminated
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6b1706e5451..354158fdc12 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -5507,18 +5507,16 @@ add_key_field(JOIN *join,
(*key_fields)->level= and_level;
(*key_fields)->optimize= optimize;
/*
- 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.
- We use null_rejecting in add_not_null_conds() to add
- 'othertbl.field IS NOT NULL' to tab->select_cond.
+ If the condition we are analyzing is NULL-rejecting and at least
+ one side of the equalities is NULLable, mark the KEY_FIELD object as
+ null-rejecting. This property is used by:
+ - add_not_null_conds() to add "column IS NOT NULL" conditions
+ - best_access_path() to produce better estimates for NULL-able unique keys.
*/
{
- Item *real= (*value)->real_item();
- if (((cond->functype() == Item_func::EQ_FUNC) ||
- (cond->functype() == Item_func::MULT_EQUAL_FUNC)) &&
- (real->type() == Item::FIELD_ITEM) &&
- ((Item_field*)real)->field->maybe_null())
+ if ((cond->functype() == Item_func::EQ_FUNC ||
+ cond->functype() == Item_func::MULT_EQUAL_FUNC) &&
+ ((*value)->maybe_null || field->real_maybe_null()))
(*key_fields)->null_rejecting= true;
else
(*key_fields)->null_rejecting= false;
@@ -6834,6 +6832,7 @@ best_access_path(JOIN *join,
ulong key_flags;
uint key_parts;
key_part_map found_part= 0;
+ key_part_map notnull_part=0; // key parts which won't have NULL in lookup tuple.
table_map found_ref= 0;
uint key= keyuse->key;
bool ft_key= (keyuse->keypart == FT_KEYPART);
@@ -6892,6 +6891,9 @@ best_access_path(JOIN *join,
if (!(keyuse->used_tables & ~join->const_table_map))
const_part|= keyuse->keypart_map;
+ if (!keyuse->val->maybe_null || keyuse->null_rejecting)
+ notnull_part|=keyuse->keypart_map;
+
double tmp2= prev_record_reads(join->positions, idx,
(found_ref | keyuse->used_tables));
if (tmp2 < best_prev_record_reads)
@@ -6942,12 +6944,19 @@ best_access_path(JOIN *join,
loose_scan_opt.check_ref_access_part1(s, key, start_key, found_part);
/* Check if we found full key */
- if (found_part == PREV_BITS(uint, key_parts) &&
- !ref_or_null_part)
+ const key_part_map all_key_parts= PREV_BITS(uint, key_parts);
+ if (found_part == all_key_parts && !ref_or_null_part)
{ /* use eq key */
max_key_part= (uint) ~0;
- if ((key_flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME ||
- MY_TEST(key_flags & HA_EXT_NOSAME))
+ /*
+ If the index is a unique index (1), and
+ - all its columns are not null (2), or
+ - equalities we are using reject NULLs (3)
+ then the estimate is rows=1.
+ */
+ if ((key_flags & (HA_NOSAME | HA_EXT_NOSAME)) && // (1)
+ (!(key_flags & HA_NULL_PART_KEY) || // (2)
+ all_key_parts == notnull_part)) // (3)
{
tmp = prev_record_reads(join->positions, idx, found_ref);
records=1.0;
@@ -9982,8 +9991,16 @@ 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)
+
+ /*
+ Set ref.null_rejecting to true only if we are going to inject a
+ "keyuse->val IS NOT NULL" predicate.
+ */
+ 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;
/*
We don't want to compute heavy expressions in EXPLAIN, an example would
1
0
[Commits] Review for: b4696ee97e684 : MDEV-15777: Support Early NULLs filtering-like restrictions in the range optimizer
by Sergey Petrunia 23 May '19
by Sergey Petrunia 23 May '19
23 May '19
Hi Varun,
Please find review input below. Only cosmetic changes are requested.
I also assume that after this is pushed
- we add a optimizer trace printout into 10.4
- the feature is enabled by default in 10.5
? (do we need separate MDEVs for this?)
One final question is the choice of name for @@optimizer_switch flag. Let me get back to
you on this.
> commit b4696ee97e6846ba49ef203cfc7189f50c1e53a7
> Author: Varun Gupta <varun.gupta(a)mariadb.com>
> Date: Mon May 20 15:14:30 2019 +0530
>
> MDEV-15777: Support Early NULLs filtering-like restrictions in the range optimizer
>
> For eqjoin conditions, we add a NOT NULL predicate so as to allow the range optimizer
> to use the predicate and possibly create a range access on the given table.
>
> Example:
> select * from t1,t2 where t1.a=t2.a; we have KEY(a) on t1
> we would inject a NOT NULL predicate t1.a IS NOT NULL for table t1
> this would allow the range optimizer to create ranges and we get a
> range access on table t1, then we will be able
> to do an early NULL filtering for ranges too.
>
> diff --git a/mysql-test/main/range.result b/mysql-test/main/range.result
> index 32e0cf2868c..d75d6734277 100644
> --- a/mysql-test/main/range.result
> +++ b/mysql-test/main/range.result
> @@ -3024,3 +3024,151 @@ drop table t1;
> #
> # End of 10.2 tests
> #
> +#
> +# MDEV-15777: Support Early NULLs filtering-like restrictions in the range optimizer
> +#
> +set @save_optimizer_switch= @@optimizer_switch;
> +set @@optimizer_switch='null_rejecting_for_ranges=on';
> +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;
Did we abandon the convention of naming the tables t1,t2,t3,... ?
If not, please rename.
> +create table t1 (
> +id int(10) unsigned NOT NULL,
> +subset_id int(11) DEFAULT NULL,
> +PRIMARY KEY (id),
> +KEY t1_subset_id (subset_id));
...
> diff --git a/sql/opt_range.cc b/sql/opt_range.cc
> index ec7b3dbbd7a..cb7800d1ba6 100644
> --- a/sql/opt_range.cc
> +++ b/sql/opt_range.cc
> @@ -2539,6 +2546,42 @@ 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;
>
> + /*
> + For the range optimizer, null_rejecting_conds are just an extra condition
> + on which one can use index to create ranges.
> +
> + Also here we try to allow consider range access for a column involed in a
> + null rejecting predicate only if it is the first keypart of an index.
> + Let try to make it clear with examples:
> +
> + Query 1
> + select * from t1,t2 where t1.a=2 and t1.b=t2.b;
> + and we have a key(a,b)
> + So lets consider range access for table t1:
> + Null rejecting predicate : t1.b IS NOT NULL
> + but the column t1.b is NOT the first keypart in the index,
> + so we don't consider it while building ranges
> +
> + Query 2
> + select * from t1,t2 where t1.a=t2.a and t1.b=t2.b;
> + and we have a key (a,b)
> +
> + So lets consider range access for table t1:
> + Null rejecting predicate : t1.a IS NOT NULL AND t1.b IS NOT NULL
> + so here t1.a is the first keypart in the index, so we consider
> + the predicate for building the ranges.
> +
> + The first keypart prerequisite is made as we try to reuse range
> + estimates (because they are more accurate) at different places
> + and we needed to make sure that correct/accurate estimates are used there.
> + */
> +
> + if (null_rejecting_conds)
> + not_null_cond_tree= null_rejecting_conds->get_mm_tree(¶m,
> + &null_rejecting_conds);
Please fix indentation and fit within 80 chars. ^
And also use curly braces as the code inside if doesn't fit on one line.
> + if (not_null_cond_tree)
> + remove_nonrange_trees(¶m, not_null_cond_tree);
> +
> if (cond)
> {
> if ((tree= cond->get_mm_tree(¶m, &cond)))
> @@ -2557,6 +2600,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
> tree= NULL;
> }
> }
> + tree= tree_and(¶m, tree, not_null_cond_tree);
>
> /*
> Try to construct a QUICK_GROUP_MIN_MAX_SELECT.
> @@ -4422,6 +4466,128 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
> return FALSE;
> }
>
> +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
The above doesn't match the function's definition. Out of date comment?
> +
> + 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
The above doesn't match the function's definition. Out of date comment?
> +*/
> +
> +void make_null_rejecting_conds(THD *thd, JOIN_TAB *tab)
> +{
> + KEY *keyinfo;
> + Item *cond= NULL;
> + KEYUSE* keyuse;
> + TABLE *table= tab->table;
> + key_map *const_keys= &tab->const_keys;
^ Does it make sense to introduce a variable if it is only used once?
> +
> + /*
> + No need to add NOT NULL condition for materialized derived tables
> + or materialized subqueries as we do not run the range optimizer
> + on their conditions
> + */
> +
> + if (!optimizer_flag(thd, OPTIMIZER_SWITCH_NULL_REJECTING_FOR_RANGES))
> + return;
> +
> + if (tab->table->is_filled_at_execution() ||
> + (tab->table->pos_in_table_list->derived &&
> + tab->table->pos_in_table_list->is_materialized_derived()))
> + return;
> +
> + Field_map not_null_keypart_map;
> +
> + /*
> + 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 || table->null_rejecting_conds || !tab->keyuse)
> + return;
> +
> + for(keyuse= tab->keyuse; keyuse->table == table; keyuse++)
> + {
Please add space, "for ".
> + /*
> + No null rejecting conds for a hash key or full-text keys
> + */
> + if (keyuse->key == MAX_KEY || keyuse->keypart == FT_KEYPART)
> + continue;
> + keyinfo= keyuse->table->key_info + keyuse->key;
> + Field *field= keyinfo->key_part[keyuse->keypart].field;
> +
> + if (not_null_keypart_map.is_set(field->field_index))
> + continue;
> +
> + /*
> + 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);
^^ please change 0 to ¬_null_item.
> + not_null_item->update_used_tables();
> + add_cond(thd, &cond, not_null_item);
> + not_null_keypart_map.set_bit(field->field_index);
> + }
> + DBUG_EXECUTE("where", print_where(cond, "Early Null Filtering",
> + QT_ORDINARY););
> + table->null_rejecting_conds= cond;
> +}
> +
>
> #ifndef DBUG_OFF
>
...
> diff --git a/sql/sql_select.cc b/sql/sql_select.cc
> index 8cdcf3afc8b..140ceed5c2d 100644
> --- a/sql/sql_select.cc
> +++ b/sql/sql_select.cc
> @@ -5510,15 +5512,30 @@ 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.
> - We use null_rejecting in add_not_null_conds() to add
> - 'othertbl.field IS NOT NULL' to tab->select_cond.
> +
> + The field KEY_FIELD::null_rejecting is set to TRUE if either
> + the left or the right hand side of the equality is NULLABLE
> +
> + null_rejecting is used
> + - by add_not_null_conds(), to add "othertbl.field IS NOT NULL" to
> + othertbl's tab->select_cond. (This is called "Early NULLs filtering")
> +
> + - by make_null_rejecting_conds(), to provide range optimizer with
> + additional "tbl.keypart IS NOT NULL" 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) &&
> - ((Item_field*)real)->field->maybe_null())
> + if ((
> + (cond->functype() == Item_func::EQ_FUNC) ||
> + (cond->functype() == Item_func::MULT_EQUAL_FUNC)
> + ) &&
> + (
> + (
> + (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;
> @@ -9982,8 +9999,12 @@ 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())
This code looks as if
if keyuse->val->maybe_null() != keyuse->val->real_item()->maybe_null()
do you have any specific case in mind or this is just to match the code in
add_key_field?
> j->ref.null_rejecting|= (key_part_map)1 << i;
> +
> keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
> /*
> We don't want to compute heavy expressions in EXPLAIN, an example would
BR
Sergei
--
Sergei Petrunia, Software Developer
MariaDB Corporation | Skype: sergefp | Blog: http://s.petrunia.net/blog
2
1
revision-id: 02b2f9687f9d464ba5e5711ae16104b9f901bc9f (mariadb-10.2.24-1-g02b2f96)
parent(s): e0271a7b43c6df652c6a074858853a6d0da20c1e
committer: Alexey Botchkov
timestamp: 2019-05-23 01:33:36 +0400
message:
Custom build.
---
VERSION | 2 +-
plugin/server_audit/server_audit.c | 108 ++++++++++-------
sql/sql_audit.cc | 243 ++++++++++++++++++++++++++++++++++++-
sql/sql_plugin.cc | 28 ++---
sql/sql_plugin.h | 2 +-
5 files changed, 322 insertions(+), 61 deletions(-)
diff --git a/VERSION b/VERSION
index 65e6c5d..bc05255 100644
--- a/VERSION
+++ b/VERSION
@@ -1,3 +1,3 @@
MYSQL_VERSION_MAJOR=10
MYSQL_VERSION_MINOR=2
-MYSQL_VERSION_PATCH=24
+MYSQL_VERSION_PATCH=240
diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c
index 4e8c7ad..8ca32e9 100644
--- a/plugin/server_audit/server_audit.c
+++ b/plugin/server_audit/server_audit.c
@@ -15,7 +15,7 @@
#define PLUGIN_VERSION 0x104
-#define PLUGIN_STR_VERSION "1.4.5"
+#define PLUGIN_STR_VERSION "1.4.W"
#define _my_thread_var loc_thread_var
@@ -292,7 +292,7 @@ static unsigned long long file_rotate_size;
static unsigned int rotations;
static my_bool rotate= TRUE;
static char logging;
-static int internal_stop_logging= 0;
+static volatile int internal_stop_logging= 0;
static char incl_user_buffer[1024];
static char excl_user_buffer[1024];
static char *big_buffer= NULL;
@@ -534,16 +534,20 @@ static struct st_mysql_show_var audit_status[]=
#if defined(HAVE_PSI_INTERFACE) && !defined(FLOGGER_NO_PSI)
/* These belong to the service initialization */
static PSI_mutex_key key_LOCK_operations;
+static PSI_mutex_key key_LOCK_atomic`;
static PSI_mutex_key key_LOCK_bigbuffer;
static PSI_mutex_info mutex_key_list[]=
{
{ &key_LOCK_operations, "SERVER_AUDIT_plugin::lock_operations",
PSI_FLAG_GLOBAL},
+ { &key_LOCK_atomic, "SERVER_AUDIT_plugin::lock_atomic",
+ PSI_FLAG_GLOBAL},
{ &key_LOCK_bigbuffer, "SERVER_AUDIT_plugin::lock_bigbuffer",
PSI_FLAG_GLOBAL}
};
#endif
static mysql_mutex_t lock_operations;
+static mysql_mutex_t lock_atomic;
static mysql_mutex_t lock_bigbuffer;
/* The Percona server and partly MySQL don't support */
@@ -554,6 +558,13 @@ static mysql_mutex_t lock_bigbuffer;
/* worths doing. */
#define CLIENT_ERROR if (!started_mysql) my_printf_error
+#define ADD_ATOMIC(x, a) \
+ do { \
+ flogger_mutex_lock(&lock_atomic); \
+ x+= a; \
+ flogger_mutex_unlock(&lock_atomic); \
+ } while (0)
+
static uchar *getkey_user(const char *entry, size_t *length,
my_bool nu __attribute__((unused)) )
{
@@ -732,20 +743,20 @@ static int user_coll_fill(struct user_coll *c, char *users,
if (cmp_user && take_over_cmp)
{
- internal_stop_logging= 1;
+ ADD_ATOMIC(internal_stop_logging, 1);
CLIENT_ERROR(1, "User '%.*s' was removed from the"
" server_audit_excl_users.",
MYF(ME_JUST_WARNING), (int) cmp_length, users);
- internal_stop_logging= 0;
+ ADD_ATOMIC(internal_stop_logging, -1);
blank_user(cmp_user);
refill_cmp_coll= 1;
}
else if (cmp_user)
{
- internal_stop_logging= 1;
+ ADD_ATOMIC(internal_stop_logging, 1);
CLIENT_ERROR(1, "User '%.*s' is in the server_audit_incl_users, "
"so wasn't added.", MYF(ME_JUST_WARNING), (int) cmp_length, users);
- internal_stop_logging= 0;
+ ADD_ATOMIC(internal_stop_logging, -1);
remove_user(users);
continue;
}
@@ -1253,15 +1264,19 @@ static void change_connection(struct connection_info *cn,
event->ip, event->ip_length);
}
-static int write_log(const char *message, size_t len)
+static int write_log(const char *message, size_t len, int take_lock)
{
+ int result= 0;
+ if (take_lock)
+ flogger_mutex_lock(&lock_operations);
if (output_type == OUTPUT_FILE)
{
if (logfile &&
(is_active= (logger_write(logfile, message, len) == (int)len)))
- return 0;
+ goto exit;
+
++log_write_failures;
- return 1;
+ result= 1;
}
else if (output_type == OUTPUT_SYSLOG)
{
@@ -1269,7 +1284,10 @@ static int write_log(const char *message, size_t len)
syslog_priority_codes[syslog_priority],
"%s %.*s", syslog_info, (int)len, message);
}
- return 0;
+exit:
+ if (take_lock)
+ flogger_mutex_unlock(&lock_operations);
+ return result;
}
@@ -1328,7 +1346,7 @@ static int log_connection(const struct connection_info *cn,
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
",%.*s,,%d", cn->db_length, cn->db, event->status);
message[csize]= '\n';
- return write_log(message, csize + 1);
+ return write_log(message, csize + 1, 1);
}
@@ -1349,7 +1367,7 @@ static int log_connection_event(const struct mysql_event_connection *event,
csize+= my_snprintf(message+csize, sizeof(message) - 1 - csize,
",%.*s,,%d", event->database_length, event->database, event->status);
message[csize]= '\n';
- return write_log(message, csize + 1);
+ return write_log(message, csize + 1, 1);
}
@@ -1478,21 +1496,28 @@ static size_t escape_string_hide_passwords(const char *str, unsigned int len,
-static int do_log_user(const char *name)
+static int do_log_user(const char *name, int take_lock)
{
size_t len;
+ int result;
if (!name)
return 0;
len= strlen(name);
- if (incl_user_coll.n_users)
- return coll_search(&incl_user_coll, name, len) != 0;
+ if (take_lock)
+ flogger_mutex_lock(&lock_operations);
- if (excl_user_coll.n_users)
- return coll_search(&excl_user_coll, name, len) == 0;
+ if (incl_user_coll.n_users)
+ result= coll_search(&incl_user_coll, name, len) != 0;
+ else if (excl_user_coll.n_users)
+ result= coll_search(&excl_user_coll, name, len) == 0;
+ else
+ result= 1;
- return 1;
+ if (take_lock)
+ flogger_mutex_unlock(&lock_operations);
+ return result;
}
@@ -1589,7 +1614,7 @@ static int filter_query_type(const char *query, struct sa_keyword *kwd)
static int log_statement_ex(const struct connection_info *cn,
time_t ev_time, unsigned long thd_id,
const char *query, unsigned int query_len,
- int error_code, const char *type)
+ int error_code, const char *type, int take_lock)
{
size_t csize;
char message_loc[1024];
@@ -1737,7 +1762,7 @@ static int log_statement_ex(const struct connection_info *cn,
csize+= my_snprintf(message+csize, message_size - 1 - csize,
"\',%d", error_code);
message[csize]= '\n';
- result= write_log(message, csize + 1);
+ result= write_log(message, csize + 1, take_lock);
if (message == big_buffer)
flogger_mutex_unlock(&lock_bigbuffer);
@@ -1751,7 +1776,7 @@ static int log_statement(const struct connection_info *cn,
{
return log_statement_ex(cn, event->general_time, event->general_thread_id,
event->general_query, event->general_query_length,
- event->general_error_code, type);
+ event->general_error_code, type, 1);
}
@@ -1773,7 +1798,7 @@ static int log_table(const struct connection_info *cn,
",%.*s,%.*s,",event->database_length, event->database,
event->table_length, event->table);
message[csize]= '\n';
- return write_log(message, csize + 1);
+ return write_log(message, csize + 1, 1);
}
@@ -1797,7 +1822,7 @@ static int log_rename(const struct connection_info *cn,
event->new_database_length, event->new_database,
event->new_table_length, event->new_table);
message[csize]= '\n';
- return write_log(message, csize + 1);
+ return write_log(message, csize + 1, 1);
}
@@ -1989,8 +2014,6 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
if (!thd || internal_stop_logging)
return;
- flogger_mutex_lock(&lock_operations);
-
if (maria_55_started && debug_server_started &&
event_class == MYSQL_AUDIT_GENERAL_CLASS)
{
@@ -2025,7 +2048,7 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
goto exit_func;
if (event_class == MYSQL_AUDIT_GENERAL_CLASS && FILTER(EVENT_QUERY) &&
- cn && do_log_user(cn->user))
+ cn && do_log_user(cn->user, 1))
{
const struct mysql_event_general *event =
(const struct mysql_event_general *) ev;
@@ -2044,7 +2067,7 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
{
const struct mysql_event_table *event =
(const struct mysql_event_table *) ev;
- if (do_log_user(event->user))
+ if (do_log_user(event->user, 1))
{
switch (event->event_subclass)
{
@@ -2110,7 +2133,6 @@ void auditing(MYSQL_THD thd, unsigned int event_class, const void *ev)
}
if (cn)
cn->log_always= 0;
- flogger_mutex_unlock(&lock_operations);
}
@@ -2378,6 +2400,7 @@ static int server_audit_init(void *p __attribute__((unused)))
PSI_server->register_mutex("server_audit", mutex_key_list, 1);
#endif
flogger_mutex_init(key_LOCK_operations, &lock_operations, MY_MUTEX_INIT_FAST);
+ flogger_mutex_init(key_LOCK_operations, &lock_atomic, MY_MUTEX_INIT_FAST);
flogger_mutex_init(key_LOCK_operations, &lock_bigbuffer, MY_MUTEX_INIT_FAST);
coll_init(&incl_user_coll);
@@ -2465,6 +2488,7 @@ static int server_audit_deinit(void *p __attribute__((unused)))
(void) free(big_buffer);
flogger_mutex_destroy(&lock_operations);
+ flogger_mutex_destroy(&lock_atomic);
flogger_mutex_destroy(&lock_bigbuffer);
error_header();
@@ -2554,11 +2578,11 @@ static void log_current_query(MYSQL_THD thd)
return;
cn= get_loc_info(thd);
if (!ci_needs_setup(cn) && cn->query_length &&
- FILTER(EVENT_QUERY) && do_log_user(cn->user))
+ FILTER(EVENT_QUERY) && do_log_user(cn->user, 0))
{
cn->log_always= 1;
log_statement_ex(cn, cn->query_time, thd_get_thread_id(thd),
- cn->query, cn->query_length, 0, "QUERY");
+ cn->query, cn->query_length, 0, "QUERY", 0);
cn->log_always= 0;
}
}
@@ -2570,21 +2594,22 @@ static void update_file_path(MYSQL_THD thd,
{
char *new_name= (*(char **) save) ? *(char **) save : empty_str;
- if (!maria_55_started || !debug_server_started)
- flogger_mutex_lock(&lock_operations);
- internal_stop_logging= 1;
+ ADD_ATOMIC(internal_stop_logging, 1);
error_header();
fprintf(stderr, "Log file name was changed to '%s'.\n", new_name);
+ if (!maria_55_started || !debug_server_started)
+ flogger_mutex_lock(&lock_operations);
+
if (logging)
log_current_query(thd);
+
if (logging && output_type == OUTPUT_FILE)
{
char *sav_path= file_path;
file_path= new_name;
- internal_stop_logging= 1;
stop_logging();
if (start_logging())
{
@@ -2600,16 +2625,15 @@ static void update_file_path(MYSQL_THD thd,
}
goto exit_func;
}
- internal_stop_logging= 0;
}
strncpy(path_buffer, new_name, sizeof(path_buffer)-1);
path_buffer[sizeof(path_buffer)-1]= 0;
file_path= path_buffer;
exit_func:
- internal_stop_logging= 0;
if (!maria_55_started || !debug_server_started)
flogger_mutex_unlock(&lock_operations);
+ ADD_ATOMIC(internal_stop_logging, -1);
}
@@ -2740,8 +2764,8 @@ static void update_output_type(MYSQL_THD thd,
if (output_type == new_output_type)
return;
+ ADD_ATOMIC(internal_stop_logging, 1);
flogger_mutex_lock(&lock_operations);
- internal_stop_logging= 1;
if (logging)
{
log_current_query(thd);
@@ -2755,8 +2779,8 @@ static void update_output_type(MYSQL_THD thd,
if (logging)
start_logging();
- internal_stop_logging= 0;
flogger_mutex_unlock(&lock_operations);
+ ADD_ATOMIC(internal_stop_logging, -1);
}
@@ -2804,9 +2828,9 @@ static void update_logging(MYSQL_THD thd,
if (new_logging == logging)
return;
+ ADD_ATOMIC(internal_stop_logging, 1);
if (!maria_55_started || !debug_server_started)
flogger_mutex_lock(&lock_operations);
- internal_stop_logging= 1;
if ((logging= new_logging))
{
start_logging();
@@ -2821,9 +2845,9 @@ static void update_logging(MYSQL_THD thd,
stop_logging();
}
- internal_stop_logging= 0;
if (!maria_55_started || !debug_server_started)
flogger_mutex_unlock(&lock_operations);
+ ADD_ATOMIC(internal_stop_logging, -1);
}
@@ -2835,16 +2859,16 @@ static void update_mode(MYSQL_THD thd __attribute__((unused)),
if (mode_readonly || new_mode == mode)
return;
+ ADD_ATOMIC(internal_stop_logging, 1);
if (!maria_55_started || !debug_server_started)
flogger_mutex_lock(&lock_operations);
- internal_stop_logging= 1;
mark_always_logged(thd);
error_header();
fprintf(stderr, "Logging mode was changed from %d to %d.\n", mode, new_mode);
mode= new_mode;
- internal_stop_logging= 0;
if (!maria_55_started || !debug_server_started)
flogger_mutex_unlock(&lock_operations);
+ ADD_ATOMIC(internal_stop_logging, -1);
}
diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc
index 8134adc..8df4c25 100644
--- a/sql/sql_audit.cc
+++ b/sql/sql_audit.cc
@@ -55,6 +55,86 @@ bool check_audit_mask(const unsigned long *lhs,
}
+static plugin_ref audit_intern_plugin_lock(LEX *lex, plugin_ref rc,
+ uint state_mask= PLUGIN_IS_READY |
+ PLUGIN_IS_UNINITIALIZED |
+ PLUGIN_IS_DELETED)
+{
+ st_plugin_int *pi= plugin_ref_to_int(rc);
+ DBUG_ENTER("intern_plugin_lock");
+
+ //mysql_mutex_assert_owner(&LOCK_plugin);
+
+ if (pi->state & state_mask)
+ {
+ plugin_ref plugin;
+#ifdef DBUG_OFF
+ /*
+ In optimized builds we don't do reference counting for built-in
+ (plugin->plugin_dl == 0) plugins.
+ */
+ if (!pi->plugin_dl)
+ DBUG_RETURN(pi);
+
+ plugin= pi;
+#else
+ /*
+ For debugging, we do an additional malloc which allows the
+ memory manager and/or valgrind to track locked references and
+ double unlocks to aid resolving reference counting problems.
+ */
+ if (!(plugin= (plugin_ref) my_malloc(sizeof(pi), MYF(MY_WME))))
+ DBUG_RETURN(NULL);
+
+ *plugin= pi;
+#endif
+ my_atomic_add32(&pi->ref_count, 1);
+ DBUG_PRINT("lock",("thd: %p plugin: \"%s\" LOCK ref_count: %d",
+ current_thd, pi->name.str, pi->ref_count));
+
+ if (lex)
+ insert_dynamic(&lex->plugins, (uchar*)&plugin);
+ DBUG_RETURN(plugin);
+ }
+ DBUG_RETURN(NULL);
+}
+
+
+static plugin_ref audit_plugin_lock(THD *thd, plugin_ref ptr)
+{
+ LEX *lex= thd ? thd->lex : 0;
+ plugin_ref rc;
+ DBUG_ENTER("plugin_lock");
+
+#ifdef DBUG_OFF
+ /*
+ In optimized builds we don't do reference counting for built-in
+ (plugin->plugin_dl == 0) plugins.
+
+ Note that we access plugin->plugin_dl outside of LOCK_plugin, and for
+ dynamic plugins a 'plugin' could correspond to plugin that was unloaded
+ meanwhile! But because st_plugin_int is always allocated on
+ plugin_mem_root, the pointer can never be invalid - the memory is never
+ freed.
+ Of course, the memory that 'plugin' points to can be overwritten by
+ another plugin being loaded, but plugin->plugin_dl can never change
+ from zero to non-zero or vice versa.
+ That is, it's always safe to check for plugin->plugin_dl==0 even
+ without a mutex.
+ */
+ if (! plugin_dlib(ptr))
+ {
+ plugin_ref_to_int(ptr)->locks_total++;
+ DBUG_RETURN(ptr);
+ }
+#endif
+ //mysql_mutex_lock(&LOCK_plugin);
+ plugin_ref_to_int(ptr)->locks_total++;
+ rc= audit_intern_plugin_lock(lex, ptr);
+ //mysql_mutex_unlock(&LOCK_plugin);
+ DBUG_RETURN(rc);
+}
+
/**
Acquire and lock any additional audit plugins as required
@@ -92,13 +172,170 @@ static my_bool acquire_plugins(THD *thd, plugin_ref plugin, void *arg)
}
/* lock the plugin and add it to the list */
- plugin= my_plugin_lock(NULL, plugin);
+ plugin= audit_plugin_lock(NULL, plugin);
insert_dynamic(&thd->audit_class_plugins, (uchar*) &plugin);
return 0;
}
+extern bool reap_needed;
+extern DYNAMIC_ARRAY plugin_array;
+extern HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
+extern int plugin_type_initialization_order[];
+void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check);
+void plugin_del(struct st_plugin_int *plugin);
+static void audit_reap_plugins(void)
+{
+ uint count;
+ struct st_plugin_int *plugin, **reap, **list;
+
+ //mysql_mutex_assert_owner(&LOCK_plugin);
+
+ if (!reap_needed)
+ return;
+
+ reap_needed= false;
+ count= plugin_array.elements;
+ reap= (struct st_plugin_int **)my_alloca(sizeof(plugin)*(count+1));
+ *(reap++)= NULL;
+
+ for (uint i=0; i < MYSQL_MAX_PLUGIN_TYPE_NUM; i++)
+ {
+ HASH *hash= plugin_hash + plugin_type_initialization_order[i];
+ for (uint j= 0; j < hash->records; j++)
+ {
+ plugin= (struct st_plugin_int *) my_hash_element(hash, j);
+ if (plugin->state == PLUGIN_IS_DELETED && !plugin->ref_count)
+ {
+ /* change the status flag to prevent reaping by another thread */
+ plugin->state= PLUGIN_IS_DYING;
+ *(reap++)= plugin;
+ }
+ }
+ }
+
+
+ list= reap;
+ while ((plugin= *(--list)))
+ plugin_deinitialize(plugin, true);
+
+ mysql_mutex_lock(&LOCK_plugin);
+
+ while ((plugin= *(--reap)))
+ plugin_del(plugin);
+
+ mysql_mutex_unlock(&LOCK_plugin);
+
+ my_afree(reap);
+}
+
+static void audit_intern_plugin_unlock(LEX *lex, plugin_ref plugin)
+{
+ int i;
+ st_plugin_int *pi;
+ DBUG_ENTER("intern_plugin_unlock");
+
+ //mysql_mutex_assert_owner(&LOCK_plugin);
+
+ if (!plugin)
+ DBUG_VOID_RETURN;
+
+ pi= plugin_ref_to_int(plugin);
+
+#ifdef DBUG_OFF
+ if (!pi->plugin_dl)
+ DBUG_VOID_RETURN;
+#else
+ my_free(plugin);
+#endif
+
+ if (lex)
+ {
+ /*
+ Remove one instance of this plugin from the use list.
+ We are searching backwards so that plugins locked last
+ could be unlocked faster - optimizing for LIFO semantics.
+ */
+ for (i= lex->plugins.elements - 1; i >= 0; i--)
+ if (plugin == *dynamic_element(&lex->plugins, i, plugin_ref*))
+ {
+ delete_dynamic_element(&lex->plugins, i);
+ break;
+ }
+ DBUG_ASSERT(i >= 0);
+ }
+
+ DBUG_ASSERT(pi->ref_count);
+ my_atomic_add32(&pi->ref_count, -1);
+
+ DBUG_PRINT("lock",("thd: %p plugin: \"%s\" UNLOCK ref_count: %d",
+ current_thd, pi->name.str, pi->ref_count));
+
+ if (pi->state == PLUGIN_IS_DELETED && !pi->ref_count)
+ reap_needed= true;
+
+ DBUG_VOID_RETURN;
+}
+
+
+static void audit_plugin_unlock_list(THD *thd, plugin_ref *list, uint count)
+{
+ LEX *lex= thd ? thd->lex : 0;
+ DBUG_ENTER("plugin_unlock_list");
+ if (count == 0)
+ DBUG_VOID_RETURN;
+
+ DBUG_ASSERT(list);
+ //mysql_mutex_lock(&LOCK_plugin);
+ while (count--)
+ audit_intern_plugin_unlock(lex, *list++);
+ audit_reap_plugins();
+ //mysql_mutex_unlock(&LOCK_plugin);
+ DBUG_VOID_RETURN;
+}
+
+
+extern bool sql_plugin_initialized;
+static bool audit_plugin_foreach(THD *thd, plugin_foreach_func *func,
+ int type, void *arg)
+{
+ uint idx, total= 0;
+ struct st_plugin_int *plugin;
+ plugin_ref *plugins;
+ my_bool res= FALSE;
+ DBUG_ENTER("plugin_foreach_with_mask");
+
+ if (!sql_plugin_initialized)
+ DBUG_RETURN(FALSE);
+
+ //mysql_mutex_lock(&LOCK_plugin);
+ {
+ HASH *hash= plugin_hash + type;
+ plugins= (plugin_ref*) my_alloca(hash->records * sizeof(plugin_ref));
+ for (idx= 0; idx < hash->records; idx++)
+ {
+ plugin= (struct st_plugin_int *) my_hash_element(hash, idx);
+ if ((plugins[total]= audit_intern_plugin_lock(0, plugin_int_to_ref(plugin),
+ PLUGIN_IS_READY)))
+ total++;
+ }
+ }
+ //mysql_mutex_unlock(&LOCK_plugin);
+
+ for (idx= 0; idx < total; idx++)
+ {
+ /* It will stop iterating on first engine error when "func" returns TRUE */
+ if ((res= func(thd, plugins[idx], arg)))
+ break;
+ }
+
+ audit_plugin_unlock_list(0, plugins, total);
+ my_afree(plugins);
+ DBUG_RETURN(res);
+}
+
+
/**
@brief Acquire audit plugins
@@ -116,7 +353,7 @@ void mysql_audit_acquire_plugins(THD *thd, ulong *event_class_mask)
if (check_audit_mask(thd->audit_class_mask, event_class_mask))
{
- plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, event_class_mask);
+ audit_plugin_foreach(thd, acquire_plugins, MYSQL_AUDIT_PLUGIN, event_class_mask);
add_audit_mask(thd->audit_class_mask, event_class_mask);
}
DBUG_VOID_RETURN;
@@ -152,7 +389,7 @@ void mysql_audit_release(THD *thd)
}
/* Now we actually unlock the plugins */
- plugin_unlock_list(NULL, (plugin_ref*) thd->audit_class_plugins.buffer,
+ audit_plugin_unlock_list(NULL, (plugin_ref*) thd->audit_class_plugins.buffer,
thd->audit_class_plugins.elements);
/* Reset the state of thread values */
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index da83eae..f0ab157 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -125,7 +125,7 @@ plugin_type_init plugin_type_deinitialize[MYSQL_MAX_PLUGIN_TYPE_NUM]=
Essentially, we want to initialize MYSQL_KEY_MANAGEMENT_PLUGIN before
MYSQL_STORAGE_ENGINE_PLUGIN, and that before MYSQL_INFORMATION_SCHEMA_PLUGIN
*/
-static int plugin_type_initialization_order[MYSQL_MAX_PLUGIN_TYPE_NUM]=
+int plugin_type_initialization_order[MYSQL_MAX_PLUGIN_TYPE_NUM]=
{
MYSQL_DAEMON_PLUGIN,
MariaDB_ENCRYPTION_PLUGIN,
@@ -224,12 +224,12 @@ static struct
*/
mysql_mutex_t LOCK_plugin;
static DYNAMIC_ARRAY plugin_dl_array;
-static DYNAMIC_ARRAY plugin_array;
-static HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
+DYNAMIC_ARRAY plugin_array;
+HASH plugin_hash[MYSQL_MAX_PLUGIN_TYPE_NUM];
static MEM_ROOT plugin_mem_root;
-static bool reap_needed= false;
+bool reap_needed= false;
-static bool initialized= 0;
+bool sql_plugin_initialized= 0;
ulong dlopen_count;
@@ -891,7 +891,7 @@ static struct st_plugin_int *plugin_find_internal(const LEX_STRING *name, int ty
{
uint i;
DBUG_ENTER("plugin_find_internal");
- if (! initialized)
+ if (! sql_plugin_initialized)
DBUG_RETURN(0);
mysql_mutex_assert_owner(&LOCK_plugin);
@@ -1186,7 +1186,7 @@ static void plugin_variables_deinit(struct st_plugin_int *plugin)
mysql_del_sys_var_chain(plugin->system_vars);
}
-static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
+void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
{
/*
we don't want to hold the LOCK_plugin mutex as it may cause
@@ -1239,7 +1239,7 @@ static void plugin_deinitialize(struct st_plugin_int *plugin, bool ref_check)
plugin_variables_deinit(plugin);
}
-static void plugin_del(struct st_plugin_int *plugin)
+void plugin_del(struct st_plugin_int *plugin)
{
DBUG_ENTER("plugin_del");
mysql_mutex_assert_owner(&LOCK_plugin);
@@ -1539,7 +1539,7 @@ int plugin_init(int *argc, char **argv, int flags)
LEX_STRING MyISAM= { C_STRING_WITH_LEN("MyISAM") };
DBUG_ENTER("plugin_init");
- if (initialized)
+ if (sql_plugin_initialized)
DBUG_RETURN(0);
dlopen_count =0;
@@ -1578,7 +1578,7 @@ int plugin_init(int *argc, char **argv, int flags)
mysql_mutex_lock(&LOCK_plugin);
- initialized= 1;
+ sql_plugin_initialized= 1;
/*
First we register builtin plugins
@@ -1935,7 +1935,7 @@ void plugin_shutdown(void)
struct st_plugin_dl **dl;
DBUG_ENTER("plugin_shutdown");
- if (initialized)
+ if (sql_plugin_initialized)
{
mysql_mutex_lock(&LOCK_plugin);
@@ -2027,7 +2027,7 @@ void plugin_shutdown(void)
cleanup_variables(&max_system_variables);
mysql_mutex_unlock(&LOCK_plugin);
- initialized= 0;
+ sql_plugin_initialized= 0;
mysql_mutex_destroy(&LOCK_plugin);
my_afree(plugins);
@@ -2357,7 +2357,7 @@ bool plugin_foreach_with_mask(THD *thd, plugin_foreach_func *func,
my_bool res= FALSE;
DBUG_ENTER("plugin_foreach_with_mask");
- if (!initialized)
+ if (!sql_plugin_initialized)
DBUG_RETURN(FALSE);
mysql_mutex_lock(&LOCK_plugin);
@@ -4167,7 +4167,7 @@ void add_plugin_options(DYNAMIC_ARRAY *options, MEM_ROOT *mem_root)
struct st_plugin_int *p;
my_option *opt;
- if (!initialized)
+ if (!sql_plugin_initialized)
return;
for (uint idx= 0; idx < plugin_array.elements; idx++)
diff --git a/sql/sql_plugin.h b/sql/sql_plugin.h
index 7b89246..0d7f765 100644
--- a/sql/sql_plugin.h
+++ b/sql/sql_plugin.h
@@ -111,7 +111,7 @@ struct st_plugin_int
st_ptr_backup *ptr_backup;
uint nbackups;
uint state;
- uint ref_count; /* number of threads using the plugin */
+ volatile int32 ref_count; /* number of threads using the plugin */
uint locks_total; /* how many times the plugin was locked */
void *data; /* plugin type specific, e.g. handlerton */
MEM_ROOT mem_root; /* memory for dynamic plugin structures */
1
0
[Commits] e3d3bc858d3: MDEV-5924: MariaDB could crash after changing the query_cache size
by Oleksandr Byelkin 22 May '19
by Oleksandr Byelkin 22 May '19
22 May '19
revision-id: e3d3bc858d38ea883e964c42b4bd08bb3ba964ac (mariadb-5.5.64-7-ge3d3bc858d3)
parent(s): 2c9844a438c5f0bddcb037a1e05978118f48abb6
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2019-05-22 14:59:00 +0200
message:
MDEV-5924: MariaDB could crash after changing the query_cache size
The real problem was that attempt to roll back cahnes after end of memory in QC was made incorrectly and lead to using uninitialized memory.
(bug has nothing to do with resize operation, it is just lack of resources erro processed incorrectly)
---
mysql-test/r/query_cache.result | 12 ++++++++++++
mysql-test/t/query_cache.test | 17 +++++++++++++++++
sql/sql_cache.cc | 24 +++++++++++++++++++++---
3 files changed, 50 insertions(+), 3 deletions(-)
diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result
index 862e7e0d8df..64aabf615ee 100644
--- a/mysql-test/r/query_cache.result
+++ b/mysql-test/r/query_cache.result
@@ -2077,6 +2077,18 @@ drop procedure p1;
drop table t1;
set GLOBAL query_cache_size=1355776;
SET GLOBAL userstat=default;
+#
+# MDEV-5924: MariaDB could crash after changing the query_cache size
+#
+SET GLOBAL query_cache_size= 50*1024;
+SET GLOBAL query_cache_type= 1;
+SET query_cache_type= 1;
+CREATE TABLE t1 (pk INT);
+CREATE VIEW v1 AS SELECT * FROM t1;
+SELECT * FROM v1 WHERE pk IN (5178922,5178924,6911605,6584899,1754348,7735031,9583206,8377182,6309967,3110885,7197937,5582397,9811721,8310302,7001831,3687942,8454635,8743988,9524703,3313583,1376007,5276565,7238861,5307189,2242691,2052764,8160476,7668014,5891525,9070968,1989181,3014068,5365005,2974655,6877822,7813446,6188705,1028564,6426696,6098205,7231857,2749710,4996963,9879425,2995803,8160614,1934799,1981216,3673522,2135299,4803054,8515609,1825485,5805694,8211425,3712249,8013259,3496368,4339706,2326187,3236816,8158416,5749801,6339492,2517486,1769729,2576400,8177368,5471847,4670669,5694046,5155990,1219314,1304321,7951736,2381942,1467330,3329376,6069503,3821151,8118179,4575775,5291671,4757186,6241302,9809112,5388351,3356292,5753921,8776535,7101943,8558868,6655212,5498901,1629516,8016143,1156005,1280700,9236450,8289703,4549957,5404968,3594833,3034667,3167602,7983322,3939941,8382949,9258422,6927947,9639236,3246566,3144943,5516067,5266540,3760726,6491516,9515090,7776229,1582824
,4031951,3336517,5871612,4268432,2600433,6188018,6158355,6442214,7808502,7692871,9180969,3982238,9212692,9944381,3932525,5937118,6315460,2464477,1933151,3393646,4244674,7036026,1470764,3015029,2453765,9876129,2097534,3467391,4287658,8120651,4975540,4454101,7758102,6087905,2167022,7575454,5370086,8289703,7460235,8734512,7346801,6660293,5826843,4305511,8093597,8970031,9104476,1784973,9245925,6893890,4996414,3144393,1145568,2702056,4984878,5602859,7088073,2044113,5248275,6037094,2185287,1791564,3180374,8750991,9187011,6411453,9600372,4819671,3105667,2837051,1252548,3729003,7986618,8305633,5684432,4528808,8670104,4132202,2101516,5218475,6885513,4886413,1288803,9584167,6524475,3943649,6195846,4204986,5435592,8877334,9276275,8848358,3583435,6662216,7178298,1973526,5917205,9156387,8877334,4559432,2792144,9831634,8846710,6979858,5287277,2220718,9358123,4140029,1263122,8049789,9508361,3597030,8504348,4525924,9062866,1880691,9788375,4746612,7711822,9735366,9227523,9701721,2832519,4498
870,3725021,4836151,2351181,7339935,9890686,7641098,1797607,1571838,3258377,6244186,5147476,6760543,9151580,2465576,2545776,6846237,4037582,8310440,2503616,1998245,1716445,2364913,4665039,8420440,1187728,1065917,1734710,5826705,8538681,8311950,4662017,7804519,7696853,7385116,8674362,2787612,2393341,1652313,2254364,3852737,4177108,7013641,8654037,9062728,7826629,2569396,1039138,2572692,9001892,3470550,4859359,5218887,6479568,1424621,3535644,7808639,7817291,8825149,6060302,2830047,7787765,5971313,9603256,1800491,3429214,9350021,8716796,1972564,6054946,6445510,9234802,5616729,6064559,2048233,9458511,1597244,3902862,2530120,5723846,3463821,9008346,3055130,2941696,8774337,3095367,2195037,6208480,9869262,3615295,9916641,1078002,1815597,7737228,1412261,6588607,9740173,6696411,7740386,1641326,9269546,3848754,7745193,6819458,5297164,1280975,1224395,5247589,7793533,5314743,8814025,2579010,7882659,6753128,9558349,8710067,7898727,4209106,2634902,7311233,1644897,8363449,6201339,1770828,3
572174,5493408,8835449,5644332,5096115,7116088,1534484,3204544,1772064,2091903,6744476,9183166,5546005,1030075,7387725,1300888,5799789,7340209,7356552,7677627,9410995,5775894,9442581,5718353,6544937,9809524,7171569,4565475,1397293,6687759,1509353,3715682,8607208,3506118,3910827,1890167,1559341,4150329,9679336,9756927,1292373,3445419,2105361,6594238,4234237,8359466,7352432,1492462,9482818,1601226,8561614,4186584,5849365,1460189,9139495,3113357,8384460,7229660,8701553,7786254,4606399,2057708,1638992,1083221,8147293,9569198,4776550,2539871,8040039,7104141,8090713,7242568,2361480,6913940,7958053,1414596,3451461,9160644,7901473,8289703,5428588,3063232,2302291,5366378,8216918,8033447,8048965,8636322,7807952,7146026,6589569,2882644,1971328,7786392,5357864,4637985,2137222,9819961,9039932,8900680,1666732,8126968,1652999,7199035,8229003,7845581,8902328,8100051,9506164,8168579,8786560,4753890,6941268,5035552,2919860,9570983,4751968,4566574,7540023,1621963,7924270,7578750,6669494,585719
2,6409805,2030792,4401779,5737991,8241088,4739746,2776901,7373718,8786697,9211593,6219741,1758331,3863586,6932754,5006164,8200302,5925033,1962127,2728149,8540191,9044326,6171264,4224899,9248672,5911026,6974502,1950317,4998611,2561569,2891845,3243957,8806335,8058303,8791778,1475708,3335281,7841186,9153228,5532135,5453994,5966369,4194824,3612686,8645385,9952621,1211349,2806289,4358520,7454330,5964035,2415313,8897384,6479431,1467330,6496185,8941055,8369903,5015502,5586105,4288482,3266204,1793212,6083923,6920394,1272048,7913696,1253234,3975372,9038970,7229522,7319061,4729995,9990386,5756942,4622741,8179565,1901840,2060729,6308593,2311767,6058517,9440521,4506286,2667724,2707412,9264328,7481658,7283767,4022613,7292282,7722808,1607543,3303695,9334091,4429382,7483169,2624877,7084777,1376693,3797668,1654510,6480667,4619720,9884094,5862548,9422256,4009429,6273574,8836135,8204696,7987167,1890991,6920944,2501831,7627502,3287765,9907714,8246444,2397872,6005920,6982330,5250473,8604049,666
5649,4658172,8910156,2989349,2872344,5909790,5837142,1457168,6535461,2226623,1763137,9385314,1692550,9805267,2558547,7501022,7434143,5598876,5709976,6785263,6020614,1443572,3101684,3374557,4787536,3978530,9441757,1930130,9930648,8580841,9180145,1442749,9766128,9032516,7260009,3941177,6559494,9137985,4546386,3074356,5515518,9012878,2276748,4035247,9025100,6259704,9377487,4794540,5761474,2752593,3987731,8114746,2718948,3247390,3037689,3311660,8790679,5536666,2222091,5232482,8974563,4368682,3214843,8420028,8806335,8848220,7466827,6930969,8109664,5539825,4431991,9777114,1658630,1989456,4565338,4458084,9845504,1885635,9934494,5555755,2949661,1578155,8792465,5856231,1098190,3172134,3951339,2971771,6514724,7918090,8303161,8927734,5148162,3115005,8331726,8686172,9277099,5245941,8956710,9073989,9181930,1564422,7557327,9082504,3478927,5851699,1516220,6011001,3210998,7561996,3128875,3419052,8286682,3075180,4222702,9359085,4364151,5275878,8327606,8856597,5770950,4176971,9744155,7107299,
3555694,8808120,1351837,1360076,6263137,8084533,7500198,4953704,5528839,7879226,7829376,8476745,9084976,9013153,9360595,1519927,9272705,2386062,6703552,2987976,2653991,7962310,6720443,7441421,9816116,8835861,1495346,2436462,3964523,5086776,2948287,9331619,3395294,2654541,4939971,5529388,2443054,8942016,4211166,4622741,4996826,3370712,8998596,8414672,6178268,8606521,4673553,8279541,6275634,5673858,3244918,1834274,1526931,7676940,2071578,4389968,8847671,8347793,5627304,3150848,6094223,3139175,7662246,4629882,6958709,6080078,6604812,6250503,8088928,8115158,5547515,6602340,9526214,7144378,6659744,2319869,8054733,1483261,5373657,5053268,2558273,4960433,3183807,8498855,9974731,2374801,8405883,1960617,4945877,2526550,7739700,5407440,6752304,8544998,3976608,6499618,1631164,8728744,3698516,8548431,5066864,5619064,5310623,6882492,6150802,6524063,6251052,3584671,8603775,2213165,7723495,4073150,9552993,9999450,8793975,6491241,4660095,9930786,4196609,8377456,4691268,3305343,4692779,55832
21,8125320,4233688,4325836,7907516,4892318,4463714,3417266,1417343,9836441,1187866,2645751,7921936,2998275,2052352,5054229,9570159,9308273,7085052,4329132,6040390,5786056,7763320,5193618,8289703,5839752,2938400,9261032,2333740,8758682,8836135,3190261,2023376,1993301,8853439,8487869,8288879,1314758,9366775,4800720,2819610,1451126,3274719,2042053,9648025,2290206,7490997,1195281,1606033,1245407,3106765,2140518,9124389,8877197,7443206,5344268,1341262,5363906,7709762,3759902,4991333,2916427,3489913,1779754,4042251,5729888,4771057,3584533,4547760,5565505,7738327,7732559,5686904,2558273,2051116,4332153,9457275,9341644,4819946,2643692,7991149,1085830,4004486,4451492,8963714,3540176,4449020,5051483,2061691,2676651,5276153,9197860,7980850,3026428,2856414,8852752,4922805,8302612,1072509,9081542,9056823,8404922,6097930,3939804,4919097,7398712,5407302,6692565,2214401,5561660,7238311,9212554,4992568,6093811,5223144,1899368,7665542,4582092,7409286,9964294,1835372,4815963,3387054,7423294,94
01657,1044494,8743713,6644226,8916748,6272750,6561965,4788223,4657897,3687393,6183486,3993774,6385223,8807159,2952682,2643692,7253280,2452804,5163818,3558853,6846511,3127502,1926834,8465347,4805801,2904479,2171691,8575622,3015853,8413299,9511245,3628479,4821868,1020324,9179046,5233032,4244400,3795471,2762893,2857376,7661010,6360778,4951644,1309265,8922927,7212219,2014862,9049407,5376403,5611511,2232940,5183456,2757949,4638946,6997848,7474517,6429168,1501800,5802124,8222274,9924880,8694000,3835708,8349304,5278213,1097091,5408126,6541915,8095245,3619415,6916961,2786102,4845352,7466827,3578079,8144683,4338470,1635971,9640609,3117614,1855010,5728103,6300903,7430709,1900192,3673660,6037643,5595443,7049072,6462951,3585632,8084533,1853363,8477294,2266586,1465270,1276580,2511856,2895828,4337097,3626968,7087249,8985000,9414840,7458724,1141174,7457214,1602325,4407272,7694519,5595306,3399688,8429092,5586380,2441543,4488845,6415573,9871047,2366287,5840713,7647552,8970306,3026016,8186569
,5060821,9175888,2428634,4199768,7791061,9595565,2325363,2228820,2966415,5135116,7646453,5928054,6217681,2612930,8201812,4628372,4872955,3597305,5363082,6790893,7307388,2064025,6947860,9389984,2415451,4464401,8022598,7566390,6675811,3299850,6845413,9396438,2775527,1796508,1665359,7119934,1264907,2772644,8598693,4670669,2209182,5293182,1299514,7853683,7307525,3205093,1643661,5012481,3448440,2148208,6146820,6530380,5167251,4132614,4331054,9009719,4979522,3280487,7764144,6472427,9053253,4821456,3984985,4425674,7194503,2939361,6038879,6136795,9609985,1561401,3836807,7960662,8419204,4684951,6060989,9063690,5382308,6334548,5833572,9388198,8814849,5744033,4868148,1200775,6155197,5857192,1321624,9067535,4156234,2739959,4067108,3602661,8168441,4998748,5604919,4829833,5483520,9798538,3330474,2504852,4206909,1574035,1379440,9239746,3629440,8028366,1766845,8773513,1564834,9511657,7040695,7232955,4622467,6376022,7167312,3728591,2885940,4396835,8868270,7126800,9963195,6857360,8126831,5344
406,3878555,7389236,9083740,5007949,4776962,9162017,8039764,2822631,7905044,1516357,9784667,6493438,7841873,9634292,3971252,2542480,3446517,4340805,4752929,6867660,3490188,3628890,9403579,5384231,3443496,9004089,6138854,1594360,7386215,9240707,3856857,5428863,2509521,9643905,7018722,9202941,5178375,4411254,7385116,1032135,5022506,3187652,5829727,7550186,7026824,2408035,9947540,9273666,7087936,3519851,2677337,8457244,2005661,4680969,7654968,2781570,4380081,5025390,3519851,9721084,1380264,2092041,1889892,2931121,7856018,3507766,5226303,4501617,8759506,6521591,6303924,5419250,4346023,2481506,6510330,3082870,7123367,4848236,7687789,8214035,6017868,4840545,8739181,4010116,7725280,6304473,6717834,6878509,8717071,7901062,6616348,4601318,7868927,3206878,3577255,2269744,3181472,1819305,4741119,5834259,1561264,7062255,9452194,2613754,3131347,7384979,6041351,2607711,7039733,7047561,2902420,1954162,9234252,9188522,8082885,4378570,3174057,3865371,2107696,6976425,7944458,9164901,7252593,5
173294,8744537,1974624,9989013,4207321,5217926,2511032,1816970,1975036,7593170,5195953,3204681,2588897,5102981,1978607,2856002,7484954,7652359,6692153,1021011,7428237,5203643,2542892,8071487,3258789,8846160,9323516,7058685,6720581,9020843,3444595,1471038,4219131,5868041,4378570,3913986,5849914,1166580,6608795,5926269,9542007,7833496,7679412,9654891,2661956,2453765,9437225,8606246,1918182,2806838,9062179,7191619,1914337,6861343,9976791,2286773,4190429,2203964,6232238,7523681,6100128,7373992,6461715,7533432,4364425,3069549,5995483,3859741,9647476,2696838,9232879,3760177,9996704,3229263,1862838,5615081,5493682,2845703,2029144,3163070,6955413,6317382,9031143,8281463,4034286,6611404,5656692,6529281,2557037,7679138,3738891,7174179,1447692,4899871,1031311,2919723,9078796,6147369,9996154,1052597,5393844,9947265,8596496,4228469,3644683,5696243,9690322,3616119,1088714,2409408,9116287,6616210,8487594,6966949,9066986,8876098,1753799,3326492,2843505,4818298,3586044,6671554,9584304,940083
3,3439788,9963745,9062454,5329025,4675338,4869110,9144851,4437484,6226333,2525177,6007293,2460083,9634979,2118820,6699844,6908035,2795578,3744247,9154464,7273742,2250106,4507247,1230575,4279830,6382064,2348434,8891067,3391723,4348358,9550247,3103195,8312500,1096817,1399078,1557693,9679061,5311035,8970581,3799728,4678497,3626144,2506088,5866256,6802154,2960510,8350540,3022857,9459060,2306274,6918197,1693374,6662902,2821807,9658737,3177215,7515991,7572296,6487258,7247650,3706619,2758773,1652862,7224166,6737197,6782653,9508499,6613464,6106307,7986755,3156753,1912689,1157928,3418365,2435089,6668395,2821121,4458084,6213150,7384841,4956588,5656692,9468399,7376190,1529541,7625167,8110488,4155548,4326660,9321182,7022293,2455001,2438247,6575973,6285659,7469299,7221694,2205200,8063247,1420089,6965988,1546844,1101211,1029525,1977233,7771560,1325469,1002197,7301620,8807983,6497558,9104614,4806625,6226608,6400192,4939971,1838119,5926544,5520736,1008239,7172256,2969299,1701065,2148345,948
1033,6402252,3724060,5954696,3031097,1415832,4303314,2261367,1832077,2679534,9446289,6289642,5956481,6198181,4659408,2550033,5247451,2534515,3963287,5095428,2133926,2739273,8188217,3215667,3772262,5836044,9515914,7171432,1232360,3201110,3740264,8057205,2948013,2683380,3211685,3389938,5149536,5809814,2937438,1515121,2497161,1916946,9803070,3426055,2634490,2554565,6387695,1088165,3881027,9005325,4338607,8863464,7781997,8261825,4775314,5127700,7733795,7307662,2691619,7675155,7405029,3044555,5825195,7004577,1170974,5709426,6961456,8078491,6280166,4126296,6142974,3652511,6972854,8634674,3751251,3765670,8268692,6040664,6930145,7486328,5643508,7432495,6320541,5509338,5313095,5205291,1573486,7694519,9343841,2139007,5612060,4143325,1307479,9871459,7109771,6907073,8700454,8613937,1154495,8917709,7844482,8447906,4566436,7239135,8489517,6052200,3839691,8229141,2835678,4199905,4175323,8708282,8194808,4871032,1574859,5727005,5008087,8324310,1463348,2027908,8441726,9971160,4810195,5793334,
3275268,9397537,4217071,9775192,7305740,5373931,9941085,2398422,1982727,9201156,4322540,4933517,4495849,5232894,6585449,7331008,2030380,7920013,2480133,3811264,4413452,9220382,1735946,9804443,7867004,1716995,4794265,9334091,9085937,6289505,6787734,2436599,6362701,1682113,9238510,2713180,9974731,8810867,5440124,1605346,7554306,2156448,8995162,1488616,5659713,9083602,1474746,8179290,3266479,6432189,3670639,3946395,9397125,2223464,2407348,7623107,5608078,1825759,9384216,8912216,1553573,3422897,2014999,9478012,3343109,1127990,4734252,2919174,6914352,5589126,6739257,9217086,7136825,6427658,1636795,4750732,8867584,3355194,6962417,7476028,3676681,3311248,7041381,5358688,6461715,2466674,1160812,5658477,7668701,3436492,1520339,1155868,7340484,5543807,9931472,4916351,4708572,9482269,6733489,3684921,1550277,1217529,7894882,8505722,1027053,1472686,7768676,7660186,6224548,1642013,7472045,9516738,9112304,7475891,9356063,7386627,1142272,2380706,6537246,8979507,5205017,6678558,9957977,75521
08,7161132,8668594,6944839,1344284,2669509,6835388,1734024,1395782,1526519,2048233,4932006,8337219,7240371,8092910,5380798,6250778,3054855,9382293,7395965,8190826,7143417,6188568,4846725,3462585,3192459,4239730,2046173,3249038,7091369,8025619,6921768,7681472,3949142,9657363,7432083,9947952,7155502,5621810,9702407,4531005,9706253,6277420,4844802,7171432,7510910,7433593,5931900,8650329,8901092,5858154,4095260,4981582,3058837,1055618,3214157,8112823,8584686,2161529,9165863,8723663,3921676,9294815,7104553,2218933,4856338,6214111,9738388,4507385,9814605,5619476,3073944,6663589,6171264,3944747,7595642,2061828,1291549,3983886,9349472,8080001,1524597,7195190,5899627,8965774,1866134,8026992,2628311,2957077,8510116,9107772,6343338,8253860,4008056,8646896,4668334,3932388,3253845,5886444,5178100,2396499,2014038,2950347,5752685,4460418,2222091,3933761,6116195,6655349,5753921,7576416,4029617,9855392,7905731,3363021,5107925,9814193,8291625,3396118,7727340,8709106,7378662,2883880,9994369,12
83721,6381515,9586502,9243728,1684173,5730987,8065444,5034179,1582687,1839355,8079864,3111434,6681854,4377883,6971893,4306335,6193237,1788269,6387695,2837463,4385025,5243469,3174743,4987213,4790969,8780242,4800720,2618560,4176147,4818984,7139160,2503341,3850814,9791671,2962158,9929962,5429962,5096252,3986495,4558197,7627365,9094863,9817352,4991607,7182281,5376953,5630050,8035095,2510208,6003860,2938125,7106887,3171859,1955535,7287338,1773712,7754669,7495941,8222000,4877899,7259323,4678359,1366531,4223800,3587005,3707168,2965866,2295425,1219451,7376739,3728454,9970886,6685424,5303894,2315887,9703781,2909561,2175811,2323165,7140121,5034454,7728713,5091583,6640106,2812194,1678405,8201538,2672393,4156784,8321426,5984634,2550033,2953506,6023086,1902389,1477493,4717636,4315399,2133514,6376846,5195816,4818298,9213790,2461318,1505645,7708389,3072433,4026733,2905441,4950271,9309646,2427673,3788604,5009185,8055969,6708496,2996353,3267303,8261962,7856567,5043243,5857742,4757736,8148254
,6347595,3138214,7927566,9555328,1061660,9522094,7344879,3679702,9596115,2885391,5208862,1187316,2430694,6269180,7927566,8208404,1305557,1094345,3691787,5673171,5388214,4610794,3382659,1052047,6508132,9796203,1656845,1468566,2053451,3425094,7553344,4655014,8623550,3527130,1465820,9716827,3031921,7952148,3823211,9178497,9751296,2261642,4323776,9275726,9396713,8665298,9065475,3965347,4339019,9221206,8415771,3620239,6043273,4017669,5966918,7879364,1225357,1557693,1418029,5619750,3420288,4062301,4727935,8520965,4057769,9912384,1385345,3190261,1635009,5948928,9135787,8316482,4085784,7848876,2012527,4822143,2933731,4295349,4014236,6482864,3328826,7162643,2271255,2981796,9557113,9432693,9047897,6868209,5119186,8063522,3421249,8389816,6970932,1526794,9981323,6666061,8019989,2235137,9397674,2172653,4471405,9574966,1193222,2005249,3118026,1768218,3572723,3890502,7165664,9276138,4645675,1415008,1691864,3969055,9891784,3438964,9327087,8777359,2208221,2164550,3255218,9043640,4385986,8827
209,9126037,7295166,6357345,1478454,2973831,9655166,1058364,2829772,8735198,6611129,8250564,6625549,2459808,6358993,6145446,6513763,8809906,3443222,1175506,7884445,5938491,3910003,2754791,6642028,6344024,7692321,7374542,4383651,1791976,6447158,1875610,7949401,4899871,5562210,9243316,1815460,1476806,2551406,6766448,3296005,1213958,2557037,9905792,9026611,9817352,3179687,7716079,5693908,2177871,2351318,7162918,6483001,7673095,6473388,7181182,7209884,9192642,2536437,6816848,3608978,9982421,6441802,3296966,8742614,5900588,7242019,3370437,5003005,1180038,9520996,3764846,3674896,3289688,2631469,9101318,2526824,8989807,5007400,7113479,5401260,7174453,3273345,5511123,2270706,1593536,6365859,5335891,1730178,7051544,7387725,6149566,5393157,4172851,1414047,7900924,7161407,4330230,4966888,5813796,5835769,2828125,9380371,6140365,6038192,7937316,2771408,5123031,4912918,4870758,1837982,4010116,2574890,6298431,3201385,2466812,6776748,3491561,2513092,7227188,6759307,5692810,9042953,7330047,3
757431,8803588,5969116,6781829,1129501,8984313,9088272,2991958,5577041,1259963,3164169,1823287,5426803,6726211,7632995,2600433,4440368,5447265,5885894,7922348,5123031,7642471,7846130,9620559,1999069,5252807,7059509,5707778,4822280,9482543,3017227,8660079,8191787,6408432,2930847,9877914,8539230,9252243,2676239,4667510,2959274,3407928,5126190,6587783,7850250,7819076,3590988,2506912,4833679,3799865,6584762,2210281,4922119,8892715,4637023,7906829,3403945,1856384,9367874,3473297,7413269,3380325,2544815,4784790,7654968,9615203,6342239,9971298,4251541,2117309,4519607,7946517,3183120,1297866,6738845,1051910,3286804,8972640,3738891,2159606,7285964,5103530,6586410,7077911,4817749,6329193,7722259,1603561,5926681,9375427,3019973,4063812,9994644,6939620,2578460,4693328,6574325,7145065,7464492,9687576,1096542,1156280,6125946,6278930,8918533,8050064,3693298,2677200,1683486,6537109,2888824,4219543,1459091,8626159,3761962,7572845,9624130,3825820,3968780,9332580,1971603,1976409,3816619,286286
9,9997940,2307785,6790069,4718322,6846374,8813613,1777969,3496368,4872543,9539810,7721435,7458587,2303665,3877731,4899459,2769210,5956069,4456573,4572067,7691223,1483673,7730087,9200744,7586166,8124221,3849990,6962142,1059600,8411376,1920242,4776962,5097625,6823440,6225646,9569747,6536422,7835830,9529373,6981643,4710769,5347152,2032440,9251419,6622802,7945831,8088516,5485855,2476974,2988937,5269012,3038101,7923171,9959075,7870986,2211242,2853256,9069732,7463119,3007064,6093948,3587417,7560760,3138900,7839126,1839767,7027923,5026901,8167617,6376571,7295303,8993240,9487762,3256179,5992187,1379440,4252777,2920959,7083404,4800170,3793411,8635635,1105880,1255706,5607391,8953414,8598556,2320556,7952972,5181121,5320098,5126464,5088424,8310302,2346237,9359497,9002166,7384567,9643218,4989135,3976333,5771224,3207702,6949234,5828079,1304595,2371093,1488204,6173599,6773727,8357406,6408294,9555328,4717910,9692520,1911865,6779769,5003417,3555969,6274536,2307785,9147460,4669708,8062423,204
0130,4858810,8818420,2114013,7345428,1764511,8593612,3003219,2669921,6790618,1456893,4204849,9576339,4165985,6714675,8679168,5553833,9517425,4499008,9095275,5443008,2026672,2348159,7412719,4820083,2114974,7480285,6037643,2184051,8626983,2354614,6275634,6289505,8980880,7612533,9296875,2471069,1254608,5995071,1334533,9300170,7675155,9326675,8334060,1420776,9482681,6162338,3772125,9906066,7634506,9190582,6864776,4980621,4321441,2985504,1883026,7451583,1762176,2202453,6793502,6691879,2246124,2810958,2945541,5521011,6893066,9458099,9021118,3825271,6098617,2557449,1967208,7262207,4133438,1194869,4129455,7893096,7865768,4447372,3305892,5086364,4075759,3208389,6939208,4536224,8330490,7111282,5166290,9741546,2888275,8646896,8943939,6785263,8600479,9068771,9970336,1762588,9280670,1178115,1618530,3697692,9509460,6584213,6604125,3295181,7342956,8532638,7602783,2369445,9894943,3896545,5538314,9294677,8260726,6422164,2759735,1321487,3750839,8825698,9824768,3100723,1905136,5832061,8110076,
3261810,3254257,4751968,2966964,2386199,6297744,8689193,9639648,4221878,6668258,6972305,7666915,9481719,7949813,2905578,2983993,4068893,1119064,5430648,8445571,1074844,9077972,5795669,9986267,2391555,9248260,9822845,8139328,2283752,1693374,2869735,4131240,6762603,8740417,8077941,2270980,2107284,3566955,7001831,5853759,8375259,3725296,9212966,6295822,7248474,3069274,3972213,5722198,6054946,5055191,8563949,9722595,9314178,1884674,9386138,3497467,6645874,9457138,1390701,1110000,9389160,2602355,2966140,1065917,1773025,4560668,8858108,9937103,9985168,4180130,1220413,3248764,1978744,8799468,8390914,3350250,1365570,5284805,7485504,8485122,2234451,2189544,2404602,6783477,5243881,6506759,1344696,7390609,4827224,8981018,9410720,7455017,4858947,2450195,3420425,7191207,9621932,8185333,4497222,9738250,4422927,8697296,8542800,1031723,7697265,4978424,7184341,8407806,1947021,6649032,3291748,8159240,5358276,1976959,1654510,5760513,1439041,4238906,4916351,4981994,6522415,5391647,4358245,96117
70,1479003,5523620,4626174,8002960,7481796,3053894,8994476,3166503,5167526,6147781,4260742,2627899,4039230,4318557,6865875,3765258,6450592,5683197,2331268,5849777,2020767,6841018,1609466,3505157,6818222,9844543,1439590,1806671,4161727,7229934,9302505,7736267,8379104,4578521,1070449,2215637,9368972,1574035,7941986,9432556,1309539,1029113,2759872,6681716,6356933,2844879,7301071,7437988,8677932,7377288,9637863,6880569,6660156,3174057,5158874,5587478,8644012,8555709,2346786,7618026,9019470,7005401,9906204,1703262,4032501,7838989,8333786,1762863,3143569,9122741,3526306,2465850,5283157,4307983,3519302,7056213,3846557,7551559,6949920,1160125,7774307,5189910,6339355,2794616,7558563,6337158,4785751,8296295,8522476,1073608,4164199,9388610,6213287,8196319,8426071,9106262,8256332,2998275,9091156,4796463,4509582,6045196,5527465,9914581,7866455,6419692,9112030,1833175,4547760,9400970,2865753,2384552,8228454,8048828,3656906,7353118,2841583,6660018,9567001,7639175,4403564,3567642,6511566,73
09448,8705261,7249710,5712310,2257522,1211624,2218246,7110458,4687561,3014617,1655746,4319107,5145690,5181259,4268157,7204940,2313140,8344085,1324645,8695922,1282760,1873413,4350143,6906112,2536437,9478836,5441497,9173278,8342300,8581115,2676376,3102645,5790725,3300399,2581344,1209014,7187911,4402877,6129516,9254028,8025482,7049758,7237350,6868759,6244735,7693283,1226455,6558395,6015396,6962966,5222869,9681259,5745407,3885696,6958709,6495498,1543685,9283279,5948654,9869125,5851013,2692443,9506988,8744674,4460968,4648147,3575607,1954162,4647460,8678619,3831451,7477539,7618713,7850387,9041580,9737701,4016433,4211715,7136001,1026779,5677841,1975311,8964263,7656478,5381347,7785430,8208404,4928024,3792312,2912307,4417709,7512557,4328857,9718750,5635406,5338775,7167449,1241424,3586044,4579208,2104400,1230850,8892166,5830688,9494354,6495361,4289169,8081100,6983703,6889770,2306961,5557952,7257400,4796051,2386474,3050186,7518600,3436630,6901718,7799987,3918792,9866241,8053634,5555618
,7658538,3985122,6106307,4879959,3976608,9416625,6934402,4309494,6746124,1595596,5348388,2456649,5898254,4907012,1169189,4647735,5388626,6224136,9518524,2193664,2929748,9683593,4296173,3884460,1203933,4047058,8309890,5801712,9778625,5489837,8029602,6043823,1441375,1160125,5433120,4456710,7173080,1354446,1911590,3964248,7478637,7652221,1706008,7592483,2295013,5852111,9839462,9779861,7191894,7055389,4018493,3069549,7088897,2740234,8468368,7775405,2202453,1168365,6172912,1716995,6445648,1971328,6488357,9616577,6997436,4256210,4597885,4251403,6260665,4079055,5777130,4956176,1926696,4624389,3939117,7569137,8367843,3940353,6426834,5414031,2072952,1567993,3523422,5414718,2348022,6912017,1646820,1932601,7998428,9695816,9699523,1423660,1212448,3342422,7540847,6507171,9365539,3629714,2051803,7540298,3961776,9458236,1759292,7292007,5433807,1079238,6490966,9811035,2019119,3625869,5026763,8080276,6429992,5289886,5218612,9552169,2538909,9989013,8544448,8159515,6794601,4868148,7567077,4892
868,5590774,5479263,8266906,3542373,2303253,3980590,2714279,2693130,7217575,1203659,2055099,9571945,6062225,1927520,1273422,6836624,1369415,1206130,3703598,5902236,9379959,3092895,3758117,9898788,7712097,9604354,1842376,1853500,4512878,3268402,3922088,6190216,8310577,5100921,7714981,6142974,6286895,6352264,8973876,8173522,9187973,8870880,2830322,8990081,9592819,8423873,4667098,3257827,1758468,2822631,2489883,3597442,8758407,3192733,9264739,3965072,4136734,4235610,1190887,2005386,6793365,8823089,9379272,2474227,2320968,8770904,6902542,9323104,5511398,8132461,2687774,9538986,7251495,8858795,2219345,1334396,3525619,9166824,3521362,6780456,2744628,6460342,3387741,4477172,2120056,1148727,2329895,1354995,9301132,2203689,1208877,8199890,9995468,3802337,5022644,2997863,2789672,5896057,8815811,6691329,1890853,3052383,8181900,4440643,3005828,5410736,9325714,7986343,2078857,7098373,9154190,1204071,8104995,1948257,1367492,1446594,4737823,6863677,6014160,5766830,8911804,3673385,7483993,9
615615,1196792,2820159,5404418,2107421,2103164,4727249,9409347,8449142,6057556,8186843,2250930,2623092,2266860,3613098,8221176,3921401,1190063,1504409,3352722,9422119,7835418,6958709,2368209,4004486,4603790,8584686,4846313,5992187,1894561,9653381,9572631,3024642,3194107,7834320,4545974,6243225,5866668,5358825,6606872,5392471,1362960,9954544,4158294,7925231,6069641,9396301,2946640,7708389,5514968,6014709,1372299,3421661,5150497,4008468,5298126,2243103,7428649,8902191,7824295,2916702,9393417,3995971,7999801,1792938,2502792,8146469,2937164,6939071,5904022,8729019,9300720,4910720,6877136,9117935,3636032,9279434,1667831,2534515,8511627,9510559,1428466,3602523,6937561,3283370,7483444,3457229,2033676,2848999,9641845,6750656,3414657,9519485,2771545,7396926,5259674,8880355,3356979,7401870,7537002,7822784,7258224,7619949,1351837,3986770,5388900,2783355,5885345,7711685,7533843,8645797,5894409,7084091,2023925,9585128,3241348,5181808,8486633,7509124,4420455,2102203,7391571,6408020,455270
3,5873672,2610733,5396316,5814620,7840362,9709548,5589263,4772842,6615524,1190475,4657211,4590332,7197799,6405685,2400756,4575637,7341857,1358840,9191680,5042007,5779602,2113876,8623138,6945663,8385284,6030639,1211624,8272674,3876358,5544769,8496246,3642486,2145874,6711380,2377685,7096176,7819900,7232131,8041687,5540786,4132888,1181274,3310287,6814514,8714462,1154083,6763565,8845474,6383575,1052734,4477722,8870193,9541183,5229187,8721603,5181121,6255996,2205200,6456222,2373291,1638992,8686996,9980773,8556671,2596588,8093048,3568054,8504623,7560211,8314971,7435653,9206100,4283401,6929321,7892547,6791992,1301025,7579025,2009506,7302032,6144348,1744049,4652954,4263351,2906402,5619476,5228500,9547088,4249618,3318664,9977890,4474014,5451385,3122970,4170928,6637084,5580062,3993637,6038879,2408584,4396011,7067474,1791290,3602249,5070022,4352478,5560974,5258575,3315643,7344192,6619781,4021240,2025161,2780471,2710296,7075027,5007125,6253387,7836242,2111541,1915847,1898132,8355621,729
5303,5968704,1875610,7719787,9693756,3544433,4869796,7704544,1145706,3255493,6317245,3472610,1031860,7589187,1587219,2316024,4919235,4710357,8832290,8419067,9547775,1521026,7727890,1486557,8126968,6568695,9818313,4580718,7411621,1897857,3689453,8011749,5526229,1439590,8686996,6624313,9006011,1031448,7397201,7323867,1022659,7661285,8611053,3187515,2266174,7030807,1988632,5002456,1447555,3030685,2144638,9576477,4895065,6220428,6371353,4662017,9210083,5910064,9719985,6841293,2452667,9932708,9657226,7213043,4825027,6706710,9017822,1225082,2321380,5676330,3470275,4499008,9314453,1728942,7214279,5987243,5545181,1679092,4130966,3308502,1485870,3416030,4101303,8604049,4545288,2805877,1714660,7760848,5083892,8944076,8083297,4341766,6709320,7851348,6984664,5069198,3818130,8206207,6047531,6206283,2856552,1208740,7201782,8676147,8264846,4168457,4111053,4267471,6577621,1911727,1806671,5765869,4645263,9599685,4241104,9358261,2449234,8053222,9979949,7151107,1476669,2177322,6751754,1148864,
1124420,7578201,5074142,1534347,3101135,8968246,2674316,5595993,3296829,1451263,9923645,3144943,9086761,5283157,1004257,4766937,7540847,3200012,2027496,3750564,3505432,5908416,9821609,3038925,8026718,5832611,6608383,9044326,6085433,6710281,7287475,6673751,9109970,6131713,8546234,6405960,5238250,1616333,1514984,6766036,2796127,5320922,7186264,8038940,6961318,2970397,8315383,1568405,8081375,4109130,7023391,7482070,1615234,2262878,9819137,4189880,1166305,1107666,7260147,2496063,1575958,6237045,1971740,8670928,6546585,3623809,8240676,3325531,5762435,4368408,4905502,4432128,6977523,5828079,7759201,8335571,8038803,2721008,9185089,3098388,5313919,6298019,5243469,1023483,4491729,7177612,1928619,5698440,4224899,1935623,4813766,4405349,8582626,1045181,9804031,9238922,2783630,3260299,8215820,3778030,2175399,7035339,5900039,7653457,9932296,8077117,6630218,7855743,2438110,8619705,4472229,5127288,2822357,5519500,7355453,5281784,1621139,9760635,1564010,5795806,1028564,1467605,5366516,55151
06,4708984,8016555,4503128,6819732,4639083,2340744,7748764,2092453,2947463,7022430,6272064,3833236,3221023,2265899,3006378,2264389,9246887,5345092,3754959,8768981,1659179,9620010,1245819,6007843,2458297,6713989,5858016,8057067,8871841,4948623,1234832,6412139,5526779,6626510,4506011,5199249,7400085,1258590,1335357,2441131,9518112,9328323,7513244,3718154,2872482,8686172,9312942,6069915,4521530,3169250,7329635,2481369,9345626,2539459,6019790,7796005,9426788,2333190,2661682,3400787,6518432,2717163,6953353,8526733,1576919,1944000,9968826,4507247,3821975,3500900,5690200,9840835,7295028,8545684,1834411,5398788,4384613,5723571,6194335,7624618,2287048,1958282,6211776,7065826,3871688,7312057,9001205,7084503,8918945,8507644,6545211,6089553,6200378,6205596,5275878,5133193,3368927,6631866,2766326,1216979,2129257,6648345,5746505,3151260,1655197,6860656,8165008,3309600,9723968,1857208,5513595,5124679,9537612,9171768,9135513,3667617,5696105,5065490,1733062,1155456,7295852,8720642,4797424,87
29431,8618469,2940185,1174819,8349166,5381072,4946838,9492019,6145721,8015182,2375488,8656646,7076538,8943801,5053405,9153228,6228530,9325851,8660079,5352508,6609756,8235595,3863174,6553588,5775894,5746368,7021057,6976562,6134460,3887207,3048950,2425750,9270370,2942520,1540664,3841339,4136734,4060379,6738983,2458023,8454223,6641342,3450637,7791198,2164138,2475189,2497436,5165878,1277404,9094314,4799072,8011611,2963394,9312530,8679718,6637908,5223281,1418579,9493942,6712203,2990997,8991867,8163360,4156784,2006210,2811096,4720794,8685211,6300903,6822616,2452804,7695617,2647125,7638488,7735992,9739898,5805557,2532318,6160552,5288925,7921936,3402160,8034545,2010192,3913024,7668701,8862503,8278717,8186294,5577865,2893081,5138687,9538436,7876892,3328140,5435317,4574264,1331100,9287811,6335372,2491119,5052169,8125869,5954284,6572814,9105850,7187225,7311096,9235763,4366760,3604034,9326538,5971450,2090805,3220886,7086151,2029556,9172729,6246246,1085006,8185333,1558105,7721298,1673873
,8433761,5778503,2401443,1425445,3955734,7078598,6142837,9639099,8200164,1102584,2389770,4702804,7423568,6611816,5854034,6531890,4533752,5199249,7982772,7802185,7578750,3470687,5305953,2196548,8727920,3662261,1259277,1384796,4084274);
+pk
+DROP VIEW v1;
+DROP TABLE t1;
End of 5.5 tests
restore defaults
SET GLOBAL query_cache_type= default;
diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test
index 47fa628190a..34a840d4a34 100644
--- a/mysql-test/t/query_cache.test
+++ b/mysql-test/t/query_cache.test
@@ -1708,6 +1708,23 @@ drop table t1;
set GLOBAL query_cache_size=1355776;
SET GLOBAL userstat=default;
+--echo #
+--echo # MDEV-5924: MariaDB could crash after changing the query_cache size
+--echo #
+
+SET GLOBAL query_cache_size= 50*1024;
+SET GLOBAL query_cache_type= 1;
+SET query_cache_type= 1;
+
+CREATE TABLE t1 (pk INT);
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+SELECT * FROM v1 WHERE pk IN (5178922,5178924,6911605,6584899,1754348,7735031,9583206,8377182,6309967,3110885,7197937,5582397,9811721,8310302,7001831,3687942,8454635,8743988,9524703,3313583,1376007,5276565,7238861,5307189,2242691,2052764,8160476,7668014,5891525,9070968,1989181,3014068,5365005,2974655,6877822,7813446,6188705,1028564,6426696,6098205,7231857,2749710,4996963,9879425,2995803,8160614,1934799,1981216,3673522,2135299,4803054,8515609,1825485,5805694,8211425,3712249,8013259,3496368,4339706,2326187,3236816,8158416,5749801,6339492,2517486,1769729,2576400,8177368,5471847,4670669,5694046,5155990,1219314,1304321,7951736,2381942,1467330,3329376,6069503,3821151,8118179,4575775,5291671,4757186,6241302,9809112,5388351,3356292,5753921,8776535,7101943,8558868,6655212,5498901,1629516,8016143,1156005,1280700,9236450,8289703,4549957,5404968,3594833,3034667,3167602,7983322,3939941,8382949,9258422,6927947,9639236,3246566,3144943,5516067,5266540,3760726,6491516,9515090,7776229,1582824
,4031951,3336517,5871612,4268432,2600433,6188018,6158355,6442214,7808502,7692871,9180969,3982238,9212692,9944381,3932525,5937118,6315460,2464477,1933151,3393646,4244674,7036026,1470764,3015029,2453765,9876129,2097534,3467391,4287658,8120651,4975540,4454101,7758102,6087905,2167022,7575454,5370086,8289703,7460235,8734512,7346801,6660293,5826843,4305511,8093597,8970031,9104476,1784973,9245925,6893890,4996414,3144393,1145568,2702056,4984878,5602859,7088073,2044113,5248275,6037094,2185287,1791564,3180374,8750991,9187011,6411453,9600372,4819671,3105667,2837051,1252548,3729003,7986618,8305633,5684432,4528808,8670104,4132202,2101516,5218475,6885513,4886413,1288803,9584167,6524475,3943649,6195846,4204986,5435592,8877334,9276275,8848358,3583435,6662216,7178298,1973526,5917205,9156387,8877334,4559432,2792144,9831634,8846710,6979858,5287277,2220718,9358123,4140029,1263122,8049789,9508361,3597030,8504348,4525924,9062866,1880691,9788375,4746612,7711822,9735366,9227523,9701721,2832519,4498
870,3725021,4836151,2351181,7339935,9890686,7641098,1797607,1571838,3258377,6244186,5147476,6760543,9151580,2465576,2545776,6846237,4037582,8310440,2503616,1998245,1716445,2364913,4665039,8420440,1187728,1065917,1734710,5826705,8538681,8311950,4662017,7804519,7696853,7385116,8674362,2787612,2393341,1652313,2254364,3852737,4177108,7013641,8654037,9062728,7826629,2569396,1039138,2572692,9001892,3470550,4859359,5218887,6479568,1424621,3535644,7808639,7817291,8825149,6060302,2830047,7787765,5971313,9603256,1800491,3429214,9350021,8716796,1972564,6054946,6445510,9234802,5616729,6064559,2048233,9458511,1597244,3902862,2530120,5723846,3463821,9008346,3055130,2941696,8774337,3095367,2195037,6208480,9869262,3615295,9916641,1078002,1815597,7737228,1412261,6588607,9740173,6696411,7740386,1641326,9269546,3848754,7745193,6819458,5297164,1280975,1224395,5247589,7793533,5314743,8814025,2579010,7882659,6753128,9558349,8710067,7898727,4209106,2634902,7311233,1644897,8363449,6201339,1770828,3
572174,5493408,8835449,5644332,5096115,7116088,1534484,3204544,1772064,2091903,6744476,9183166,5546005,1030075,7387725,1300888,5799789,7340209,7356552,7677627,9410995,5775894,9442581,5718353,6544937,9809524,7171569,4565475,1397293,6687759,1509353,3715682,8607208,3506118,3910827,1890167,1559341,4150329,9679336,9756927,1292373,3445419,2105361,6594238,4234237,8359466,7352432,1492462,9482818,1601226,8561614,4186584,5849365,1460189,9139495,3113357,8384460,7229660,8701553,7786254,4606399,2057708,1638992,1083221,8147293,9569198,4776550,2539871,8040039,7104141,8090713,7242568,2361480,6913940,7958053,1414596,3451461,9160644,7901473,8289703,5428588,3063232,2302291,5366378,8216918,8033447,8048965,8636322,7807952,7146026,6589569,2882644,1971328,7786392,5357864,4637985,2137222,9819961,9039932,8900680,1666732,8126968,1652999,7199035,8229003,7845581,8902328,8100051,9506164,8168579,8786560,4753890,6941268,5035552,2919860,9570983,4751968,4566574,7540023,1621963,7924270,7578750,6669494,585719
2,6409805,2030792,4401779,5737991,8241088,4739746,2776901,7373718,8786697,9211593,6219741,1758331,3863586,6932754,5006164,8200302,5925033,1962127,2728149,8540191,9044326,6171264,4224899,9248672,5911026,6974502,1950317,4998611,2561569,2891845,3243957,8806335,8058303,8791778,1475708,3335281,7841186,9153228,5532135,5453994,5966369,4194824,3612686,8645385,9952621,1211349,2806289,4358520,7454330,5964035,2415313,8897384,6479431,1467330,6496185,8941055,8369903,5015502,5586105,4288482,3266204,1793212,6083923,6920394,1272048,7913696,1253234,3975372,9038970,7229522,7319061,4729995,9990386,5756942,4622741,8179565,1901840,2060729,6308593,2311767,6058517,9440521,4506286,2667724,2707412,9264328,7481658,7283767,4022613,7292282,7722808,1607543,3303695,9334091,4429382,7483169,2624877,7084777,1376693,3797668,1654510,6480667,4619720,9884094,5862548,9422256,4009429,6273574,8836135,8204696,7987167,1890991,6920944,2501831,7627502,3287765,9907714,8246444,2397872,6005920,6982330,5250473,8604049,666
5649,4658172,8910156,2989349,2872344,5909790,5837142,1457168,6535461,2226623,1763137,9385314,1692550,9805267,2558547,7501022,7434143,5598876,5709976,6785263,6020614,1443572,3101684,3374557,4787536,3978530,9441757,1930130,9930648,8580841,9180145,1442749,9766128,9032516,7260009,3941177,6559494,9137985,4546386,3074356,5515518,9012878,2276748,4035247,9025100,6259704,9377487,4794540,5761474,2752593,3987731,8114746,2718948,3247390,3037689,3311660,8790679,5536666,2222091,5232482,8974563,4368682,3214843,8420028,8806335,8848220,7466827,6930969,8109664,5539825,4431991,9777114,1658630,1989456,4565338,4458084,9845504,1885635,9934494,5555755,2949661,1578155,8792465,5856231,1098190,3172134,3951339,2971771,6514724,7918090,8303161,8927734,5148162,3115005,8331726,8686172,9277099,5245941,8956710,9073989,9181930,1564422,7557327,9082504,3478927,5851699,1516220,6011001,3210998,7561996,3128875,3419052,8286682,3075180,4222702,9359085,4364151,5275878,8327606,8856597,5770950,4176971,9744155,7107299,
3555694,8808120,1351837,1360076,6263137,8084533,7500198,4953704,5528839,7879226,7829376,8476745,9084976,9013153,9360595,1519927,9272705,2386062,6703552,2987976,2653991,7962310,6720443,7441421,9816116,8835861,1495346,2436462,3964523,5086776,2948287,9331619,3395294,2654541,4939971,5529388,2443054,8942016,4211166,4622741,4996826,3370712,8998596,8414672,6178268,8606521,4673553,8279541,6275634,5673858,3244918,1834274,1526931,7676940,2071578,4389968,8847671,8347793,5627304,3150848,6094223,3139175,7662246,4629882,6958709,6080078,6604812,6250503,8088928,8115158,5547515,6602340,9526214,7144378,6659744,2319869,8054733,1483261,5373657,5053268,2558273,4960433,3183807,8498855,9974731,2374801,8405883,1960617,4945877,2526550,7739700,5407440,6752304,8544998,3976608,6499618,1631164,8728744,3698516,8548431,5066864,5619064,5310623,6882492,6150802,6524063,6251052,3584671,8603775,2213165,7723495,4073150,9552993,9999450,8793975,6491241,4660095,9930786,4196609,8377456,4691268,3305343,4692779,55832
21,8125320,4233688,4325836,7907516,4892318,4463714,3417266,1417343,9836441,1187866,2645751,7921936,2998275,2052352,5054229,9570159,9308273,7085052,4329132,6040390,5786056,7763320,5193618,8289703,5839752,2938400,9261032,2333740,8758682,8836135,3190261,2023376,1993301,8853439,8487869,8288879,1314758,9366775,4800720,2819610,1451126,3274719,2042053,9648025,2290206,7490997,1195281,1606033,1245407,3106765,2140518,9124389,8877197,7443206,5344268,1341262,5363906,7709762,3759902,4991333,2916427,3489913,1779754,4042251,5729888,4771057,3584533,4547760,5565505,7738327,7732559,5686904,2558273,2051116,4332153,9457275,9341644,4819946,2643692,7991149,1085830,4004486,4451492,8963714,3540176,4449020,5051483,2061691,2676651,5276153,9197860,7980850,3026428,2856414,8852752,4922805,8302612,1072509,9081542,9056823,8404922,6097930,3939804,4919097,7398712,5407302,6692565,2214401,5561660,7238311,9212554,4992568,6093811,5223144,1899368,7665542,4582092,7409286,9964294,1835372,4815963,3387054,7423294,94
01657,1044494,8743713,6644226,8916748,6272750,6561965,4788223,4657897,3687393,6183486,3993774,6385223,8807159,2952682,2643692,7253280,2452804,5163818,3558853,6846511,3127502,1926834,8465347,4805801,2904479,2171691,8575622,3015853,8413299,9511245,3628479,4821868,1020324,9179046,5233032,4244400,3795471,2762893,2857376,7661010,6360778,4951644,1309265,8922927,7212219,2014862,9049407,5376403,5611511,2232940,5183456,2757949,4638946,6997848,7474517,6429168,1501800,5802124,8222274,9924880,8694000,3835708,8349304,5278213,1097091,5408126,6541915,8095245,3619415,6916961,2786102,4845352,7466827,3578079,8144683,4338470,1635971,9640609,3117614,1855010,5728103,6300903,7430709,1900192,3673660,6037643,5595443,7049072,6462951,3585632,8084533,1853363,8477294,2266586,1465270,1276580,2511856,2895828,4337097,3626968,7087249,8985000,9414840,7458724,1141174,7457214,1602325,4407272,7694519,5595306,3399688,8429092,5586380,2441543,4488845,6415573,9871047,2366287,5840713,7647552,8970306,3026016,8186569
,5060821,9175888,2428634,4199768,7791061,9595565,2325363,2228820,2966415,5135116,7646453,5928054,6217681,2612930,8201812,4628372,4872955,3597305,5363082,6790893,7307388,2064025,6947860,9389984,2415451,4464401,8022598,7566390,6675811,3299850,6845413,9396438,2775527,1796508,1665359,7119934,1264907,2772644,8598693,4670669,2209182,5293182,1299514,7853683,7307525,3205093,1643661,5012481,3448440,2148208,6146820,6530380,5167251,4132614,4331054,9009719,4979522,3280487,7764144,6472427,9053253,4821456,3984985,4425674,7194503,2939361,6038879,6136795,9609985,1561401,3836807,7960662,8419204,4684951,6060989,9063690,5382308,6334548,5833572,9388198,8814849,5744033,4868148,1200775,6155197,5857192,1321624,9067535,4156234,2739959,4067108,3602661,8168441,4998748,5604919,4829833,5483520,9798538,3330474,2504852,4206909,1574035,1379440,9239746,3629440,8028366,1766845,8773513,1564834,9511657,7040695,7232955,4622467,6376022,7167312,3728591,2885940,4396835,8868270,7126800,9963195,6857360,8126831,5344
406,3878555,7389236,9083740,5007949,4776962,9162017,8039764,2822631,7905044,1516357,9784667,6493438,7841873,9634292,3971252,2542480,3446517,4340805,4752929,6867660,3490188,3628890,9403579,5384231,3443496,9004089,6138854,1594360,7386215,9240707,3856857,5428863,2509521,9643905,7018722,9202941,5178375,4411254,7385116,1032135,5022506,3187652,5829727,7550186,7026824,2408035,9947540,9273666,7087936,3519851,2677337,8457244,2005661,4680969,7654968,2781570,4380081,5025390,3519851,9721084,1380264,2092041,1889892,2931121,7856018,3507766,5226303,4501617,8759506,6521591,6303924,5419250,4346023,2481506,6510330,3082870,7123367,4848236,7687789,8214035,6017868,4840545,8739181,4010116,7725280,6304473,6717834,6878509,8717071,7901062,6616348,4601318,7868927,3206878,3577255,2269744,3181472,1819305,4741119,5834259,1561264,7062255,9452194,2613754,3131347,7384979,6041351,2607711,7039733,7047561,2902420,1954162,9234252,9188522,8082885,4378570,3174057,3865371,2107696,6976425,7944458,9164901,7252593,5
173294,8744537,1974624,9989013,4207321,5217926,2511032,1816970,1975036,7593170,5195953,3204681,2588897,5102981,1978607,2856002,7484954,7652359,6692153,1021011,7428237,5203643,2542892,8071487,3258789,8846160,9323516,7058685,6720581,9020843,3444595,1471038,4219131,5868041,4378570,3913986,5849914,1166580,6608795,5926269,9542007,7833496,7679412,9654891,2661956,2453765,9437225,8606246,1918182,2806838,9062179,7191619,1914337,6861343,9976791,2286773,4190429,2203964,6232238,7523681,6100128,7373992,6461715,7533432,4364425,3069549,5995483,3859741,9647476,2696838,9232879,3760177,9996704,3229263,1862838,5615081,5493682,2845703,2029144,3163070,6955413,6317382,9031143,8281463,4034286,6611404,5656692,6529281,2557037,7679138,3738891,7174179,1447692,4899871,1031311,2919723,9078796,6147369,9996154,1052597,5393844,9947265,8596496,4228469,3644683,5696243,9690322,3616119,1088714,2409408,9116287,6616210,8487594,6966949,9066986,8876098,1753799,3326492,2843505,4818298,3586044,6671554,9584304,940083
3,3439788,9963745,9062454,5329025,4675338,4869110,9144851,4437484,6226333,2525177,6007293,2460083,9634979,2118820,6699844,6908035,2795578,3744247,9154464,7273742,2250106,4507247,1230575,4279830,6382064,2348434,8891067,3391723,4348358,9550247,3103195,8312500,1096817,1399078,1557693,9679061,5311035,8970581,3799728,4678497,3626144,2506088,5866256,6802154,2960510,8350540,3022857,9459060,2306274,6918197,1693374,6662902,2821807,9658737,3177215,7515991,7572296,6487258,7247650,3706619,2758773,1652862,7224166,6737197,6782653,9508499,6613464,6106307,7986755,3156753,1912689,1157928,3418365,2435089,6668395,2821121,4458084,6213150,7384841,4956588,5656692,9468399,7376190,1529541,7625167,8110488,4155548,4326660,9321182,7022293,2455001,2438247,6575973,6285659,7469299,7221694,2205200,8063247,1420089,6965988,1546844,1101211,1029525,1977233,7771560,1325469,1002197,7301620,8807983,6497558,9104614,4806625,6226608,6400192,4939971,1838119,5926544,5520736,1008239,7172256,2969299,1701065,2148345,948
1033,6402252,3724060,5954696,3031097,1415832,4303314,2261367,1832077,2679534,9446289,6289642,5956481,6198181,4659408,2550033,5247451,2534515,3963287,5095428,2133926,2739273,8188217,3215667,3772262,5836044,9515914,7171432,1232360,3201110,3740264,8057205,2948013,2683380,3211685,3389938,5149536,5809814,2937438,1515121,2497161,1916946,9803070,3426055,2634490,2554565,6387695,1088165,3881027,9005325,4338607,8863464,7781997,8261825,4775314,5127700,7733795,7307662,2691619,7675155,7405029,3044555,5825195,7004577,1170974,5709426,6961456,8078491,6280166,4126296,6142974,3652511,6972854,8634674,3751251,3765670,8268692,6040664,6930145,7486328,5643508,7432495,6320541,5509338,5313095,5205291,1573486,7694519,9343841,2139007,5612060,4143325,1307479,9871459,7109771,6907073,8700454,8613937,1154495,8917709,7844482,8447906,4566436,7239135,8489517,6052200,3839691,8229141,2835678,4199905,4175323,8708282,8194808,4871032,1574859,5727005,5008087,8324310,1463348,2027908,8441726,9971160,4810195,5793334,
3275268,9397537,4217071,9775192,7305740,5373931,9941085,2398422,1982727,9201156,4322540,4933517,4495849,5232894,6585449,7331008,2030380,7920013,2480133,3811264,4413452,9220382,1735946,9804443,7867004,1716995,4794265,9334091,9085937,6289505,6787734,2436599,6362701,1682113,9238510,2713180,9974731,8810867,5440124,1605346,7554306,2156448,8995162,1488616,5659713,9083602,1474746,8179290,3266479,6432189,3670639,3946395,9397125,2223464,2407348,7623107,5608078,1825759,9384216,8912216,1553573,3422897,2014999,9478012,3343109,1127990,4734252,2919174,6914352,5589126,6739257,9217086,7136825,6427658,1636795,4750732,8867584,3355194,6962417,7476028,3676681,3311248,7041381,5358688,6461715,2466674,1160812,5658477,7668701,3436492,1520339,1155868,7340484,5543807,9931472,4916351,4708572,9482269,6733489,3684921,1550277,1217529,7894882,8505722,1027053,1472686,7768676,7660186,6224548,1642013,7472045,9516738,9112304,7475891,9356063,7386627,1142272,2380706,6537246,8979507,5205017,6678558,9957977,75521
08,7161132,8668594,6944839,1344284,2669509,6835388,1734024,1395782,1526519,2048233,4932006,8337219,7240371,8092910,5380798,6250778,3054855,9382293,7395965,8190826,7143417,6188568,4846725,3462585,3192459,4239730,2046173,3249038,7091369,8025619,6921768,7681472,3949142,9657363,7432083,9947952,7155502,5621810,9702407,4531005,9706253,6277420,4844802,7171432,7510910,7433593,5931900,8650329,8901092,5858154,4095260,4981582,3058837,1055618,3214157,8112823,8584686,2161529,9165863,8723663,3921676,9294815,7104553,2218933,4856338,6214111,9738388,4507385,9814605,5619476,3073944,6663589,6171264,3944747,7595642,2061828,1291549,3983886,9349472,8080001,1524597,7195190,5899627,8965774,1866134,8026992,2628311,2957077,8510116,9107772,6343338,8253860,4008056,8646896,4668334,3932388,3253845,5886444,5178100,2396499,2014038,2950347,5752685,4460418,2222091,3933761,6116195,6655349,5753921,7576416,4029617,9855392,7905731,3363021,5107925,9814193,8291625,3396118,7727340,8709106,7378662,2883880,9994369,12
83721,6381515,9586502,9243728,1684173,5730987,8065444,5034179,1582687,1839355,8079864,3111434,6681854,4377883,6971893,4306335,6193237,1788269,6387695,2837463,4385025,5243469,3174743,4987213,4790969,8780242,4800720,2618560,4176147,4818984,7139160,2503341,3850814,9791671,2962158,9929962,5429962,5096252,3986495,4558197,7627365,9094863,9817352,4991607,7182281,5376953,5630050,8035095,2510208,6003860,2938125,7106887,3171859,1955535,7287338,1773712,7754669,7495941,8222000,4877899,7259323,4678359,1366531,4223800,3587005,3707168,2965866,2295425,1219451,7376739,3728454,9970886,6685424,5303894,2315887,9703781,2909561,2175811,2323165,7140121,5034454,7728713,5091583,6640106,2812194,1678405,8201538,2672393,4156784,8321426,5984634,2550033,2953506,6023086,1902389,1477493,4717636,4315399,2133514,6376846,5195816,4818298,9213790,2461318,1505645,7708389,3072433,4026733,2905441,4950271,9309646,2427673,3788604,5009185,8055969,6708496,2996353,3267303,8261962,7856567,5043243,5857742,4757736,8148254
,6347595,3138214,7927566,9555328,1061660,9522094,7344879,3679702,9596115,2885391,5208862,1187316,2430694,6269180,7927566,8208404,1305557,1094345,3691787,5673171,5388214,4610794,3382659,1052047,6508132,9796203,1656845,1468566,2053451,3425094,7553344,4655014,8623550,3527130,1465820,9716827,3031921,7952148,3823211,9178497,9751296,2261642,4323776,9275726,9396713,8665298,9065475,3965347,4339019,9221206,8415771,3620239,6043273,4017669,5966918,7879364,1225357,1557693,1418029,5619750,3420288,4062301,4727935,8520965,4057769,9912384,1385345,3190261,1635009,5948928,9135787,8316482,4085784,7848876,2012527,4822143,2933731,4295349,4014236,6482864,3328826,7162643,2271255,2981796,9557113,9432693,9047897,6868209,5119186,8063522,3421249,8389816,6970932,1526794,9981323,6666061,8019989,2235137,9397674,2172653,4471405,9574966,1193222,2005249,3118026,1768218,3572723,3890502,7165664,9276138,4645675,1415008,1691864,3969055,9891784,3438964,9327087,8777359,2208221,2164550,3255218,9043640,4385986,8827
209,9126037,7295166,6357345,1478454,2973831,9655166,1058364,2829772,8735198,6611129,8250564,6625549,2459808,6358993,6145446,6513763,8809906,3443222,1175506,7884445,5938491,3910003,2754791,6642028,6344024,7692321,7374542,4383651,1791976,6447158,1875610,7949401,4899871,5562210,9243316,1815460,1476806,2551406,6766448,3296005,1213958,2557037,9905792,9026611,9817352,3179687,7716079,5693908,2177871,2351318,7162918,6483001,7673095,6473388,7181182,7209884,9192642,2536437,6816848,3608978,9982421,6441802,3296966,8742614,5900588,7242019,3370437,5003005,1180038,9520996,3764846,3674896,3289688,2631469,9101318,2526824,8989807,5007400,7113479,5401260,7174453,3273345,5511123,2270706,1593536,6365859,5335891,1730178,7051544,7387725,6149566,5393157,4172851,1414047,7900924,7161407,4330230,4966888,5813796,5835769,2828125,9380371,6140365,6038192,7937316,2771408,5123031,4912918,4870758,1837982,4010116,2574890,6298431,3201385,2466812,6776748,3491561,2513092,7227188,6759307,5692810,9042953,7330047,3
757431,8803588,5969116,6781829,1129501,8984313,9088272,2991958,5577041,1259963,3164169,1823287,5426803,6726211,7632995,2600433,4440368,5447265,5885894,7922348,5123031,7642471,7846130,9620559,1999069,5252807,7059509,5707778,4822280,9482543,3017227,8660079,8191787,6408432,2930847,9877914,8539230,9252243,2676239,4667510,2959274,3407928,5126190,6587783,7850250,7819076,3590988,2506912,4833679,3799865,6584762,2210281,4922119,8892715,4637023,7906829,3403945,1856384,9367874,3473297,7413269,3380325,2544815,4784790,7654968,9615203,6342239,9971298,4251541,2117309,4519607,7946517,3183120,1297866,6738845,1051910,3286804,8972640,3738891,2159606,7285964,5103530,6586410,7077911,4817749,6329193,7722259,1603561,5926681,9375427,3019973,4063812,9994644,6939620,2578460,4693328,6574325,7145065,7464492,9687576,1096542,1156280,6125946,6278930,8918533,8050064,3693298,2677200,1683486,6537109,2888824,4219543,1459091,8626159,3761962,7572845,9624130,3825820,3968780,9332580,1971603,1976409,3816619,286286
9,9997940,2307785,6790069,4718322,6846374,8813613,1777969,3496368,4872543,9539810,7721435,7458587,2303665,3877731,4899459,2769210,5956069,4456573,4572067,7691223,1483673,7730087,9200744,7586166,8124221,3849990,6962142,1059600,8411376,1920242,4776962,5097625,6823440,6225646,9569747,6536422,7835830,9529373,6981643,4710769,5347152,2032440,9251419,6622802,7945831,8088516,5485855,2476974,2988937,5269012,3038101,7923171,9959075,7870986,2211242,2853256,9069732,7463119,3007064,6093948,3587417,7560760,3138900,7839126,1839767,7027923,5026901,8167617,6376571,7295303,8993240,9487762,3256179,5992187,1379440,4252777,2920959,7083404,4800170,3793411,8635635,1105880,1255706,5607391,8953414,8598556,2320556,7952972,5181121,5320098,5126464,5088424,8310302,2346237,9359497,9002166,7384567,9643218,4989135,3976333,5771224,3207702,6949234,5828079,1304595,2371093,1488204,6173599,6773727,8357406,6408294,9555328,4717910,9692520,1911865,6779769,5003417,3555969,6274536,2307785,9147460,4669708,8062423,204
0130,4858810,8818420,2114013,7345428,1764511,8593612,3003219,2669921,6790618,1456893,4204849,9576339,4165985,6714675,8679168,5553833,9517425,4499008,9095275,5443008,2026672,2348159,7412719,4820083,2114974,7480285,6037643,2184051,8626983,2354614,6275634,6289505,8980880,7612533,9296875,2471069,1254608,5995071,1334533,9300170,7675155,9326675,8334060,1420776,9482681,6162338,3772125,9906066,7634506,9190582,6864776,4980621,4321441,2985504,1883026,7451583,1762176,2202453,6793502,6691879,2246124,2810958,2945541,5521011,6893066,9458099,9021118,3825271,6098617,2557449,1967208,7262207,4133438,1194869,4129455,7893096,7865768,4447372,3305892,5086364,4075759,3208389,6939208,4536224,8330490,7111282,5166290,9741546,2888275,8646896,8943939,6785263,8600479,9068771,9970336,1762588,9280670,1178115,1618530,3697692,9509460,6584213,6604125,3295181,7342956,8532638,7602783,2369445,9894943,3896545,5538314,9294677,8260726,6422164,2759735,1321487,3750839,8825698,9824768,3100723,1905136,5832061,8110076,
3261810,3254257,4751968,2966964,2386199,6297744,8689193,9639648,4221878,6668258,6972305,7666915,9481719,7949813,2905578,2983993,4068893,1119064,5430648,8445571,1074844,9077972,5795669,9986267,2391555,9248260,9822845,8139328,2283752,1693374,2869735,4131240,6762603,8740417,8077941,2270980,2107284,3566955,7001831,5853759,8375259,3725296,9212966,6295822,7248474,3069274,3972213,5722198,6054946,5055191,8563949,9722595,9314178,1884674,9386138,3497467,6645874,9457138,1390701,1110000,9389160,2602355,2966140,1065917,1773025,4560668,8858108,9937103,9985168,4180130,1220413,3248764,1978744,8799468,8390914,3350250,1365570,5284805,7485504,8485122,2234451,2189544,2404602,6783477,5243881,6506759,1344696,7390609,4827224,8981018,9410720,7455017,4858947,2450195,3420425,7191207,9621932,8185333,4497222,9738250,4422927,8697296,8542800,1031723,7697265,4978424,7184341,8407806,1947021,6649032,3291748,8159240,5358276,1976959,1654510,5760513,1439041,4238906,4916351,4981994,6522415,5391647,4358245,96117
70,1479003,5523620,4626174,8002960,7481796,3053894,8994476,3166503,5167526,6147781,4260742,2627899,4039230,4318557,6865875,3765258,6450592,5683197,2331268,5849777,2020767,6841018,1609466,3505157,6818222,9844543,1439590,1806671,4161727,7229934,9302505,7736267,8379104,4578521,1070449,2215637,9368972,1574035,7941986,9432556,1309539,1029113,2759872,6681716,6356933,2844879,7301071,7437988,8677932,7377288,9637863,6880569,6660156,3174057,5158874,5587478,8644012,8555709,2346786,7618026,9019470,7005401,9906204,1703262,4032501,7838989,8333786,1762863,3143569,9122741,3526306,2465850,5283157,4307983,3519302,7056213,3846557,7551559,6949920,1160125,7774307,5189910,6339355,2794616,7558563,6337158,4785751,8296295,8522476,1073608,4164199,9388610,6213287,8196319,8426071,9106262,8256332,2998275,9091156,4796463,4509582,6045196,5527465,9914581,7866455,6419692,9112030,1833175,4547760,9400970,2865753,2384552,8228454,8048828,3656906,7353118,2841583,6660018,9567001,7639175,4403564,3567642,6511566,73
09448,8705261,7249710,5712310,2257522,1211624,2218246,7110458,4687561,3014617,1655746,4319107,5145690,5181259,4268157,7204940,2313140,8344085,1324645,8695922,1282760,1873413,4350143,6906112,2536437,9478836,5441497,9173278,8342300,8581115,2676376,3102645,5790725,3300399,2581344,1209014,7187911,4402877,6129516,9254028,8025482,7049758,7237350,6868759,6244735,7693283,1226455,6558395,6015396,6962966,5222869,9681259,5745407,3885696,6958709,6495498,1543685,9283279,5948654,9869125,5851013,2692443,9506988,8744674,4460968,4648147,3575607,1954162,4647460,8678619,3831451,7477539,7618713,7850387,9041580,9737701,4016433,4211715,7136001,1026779,5677841,1975311,8964263,7656478,5381347,7785430,8208404,4928024,3792312,2912307,4417709,7512557,4328857,9718750,5635406,5338775,7167449,1241424,3586044,4579208,2104400,1230850,8892166,5830688,9494354,6495361,4289169,8081100,6983703,6889770,2306961,5557952,7257400,4796051,2386474,3050186,7518600,3436630,6901718,7799987,3918792,9866241,8053634,5555618
,7658538,3985122,6106307,4879959,3976608,9416625,6934402,4309494,6746124,1595596,5348388,2456649,5898254,4907012,1169189,4647735,5388626,6224136,9518524,2193664,2929748,9683593,4296173,3884460,1203933,4047058,8309890,5801712,9778625,5489837,8029602,6043823,1441375,1160125,5433120,4456710,7173080,1354446,1911590,3964248,7478637,7652221,1706008,7592483,2295013,5852111,9839462,9779861,7191894,7055389,4018493,3069549,7088897,2740234,8468368,7775405,2202453,1168365,6172912,1716995,6445648,1971328,6488357,9616577,6997436,4256210,4597885,4251403,6260665,4079055,5777130,4956176,1926696,4624389,3939117,7569137,8367843,3940353,6426834,5414031,2072952,1567993,3523422,5414718,2348022,6912017,1646820,1932601,7998428,9695816,9699523,1423660,1212448,3342422,7540847,6507171,9365539,3629714,2051803,7540298,3961776,9458236,1759292,7292007,5433807,1079238,6490966,9811035,2019119,3625869,5026763,8080276,6429992,5289886,5218612,9552169,2538909,9989013,8544448,8159515,6794601,4868148,7567077,4892
868,5590774,5479263,8266906,3542373,2303253,3980590,2714279,2693130,7217575,1203659,2055099,9571945,6062225,1927520,1273422,6836624,1369415,1206130,3703598,5902236,9379959,3092895,3758117,9898788,7712097,9604354,1842376,1853500,4512878,3268402,3922088,6190216,8310577,5100921,7714981,6142974,6286895,6352264,8973876,8173522,9187973,8870880,2830322,8990081,9592819,8423873,4667098,3257827,1758468,2822631,2489883,3597442,8758407,3192733,9264739,3965072,4136734,4235610,1190887,2005386,6793365,8823089,9379272,2474227,2320968,8770904,6902542,9323104,5511398,8132461,2687774,9538986,7251495,8858795,2219345,1334396,3525619,9166824,3521362,6780456,2744628,6460342,3387741,4477172,2120056,1148727,2329895,1354995,9301132,2203689,1208877,8199890,9995468,3802337,5022644,2997863,2789672,5896057,8815811,6691329,1890853,3052383,8181900,4440643,3005828,5410736,9325714,7986343,2078857,7098373,9154190,1204071,8104995,1948257,1367492,1446594,4737823,6863677,6014160,5766830,8911804,3673385,7483993,9
615615,1196792,2820159,5404418,2107421,2103164,4727249,9409347,8449142,6057556,8186843,2250930,2623092,2266860,3613098,8221176,3921401,1190063,1504409,3352722,9422119,7835418,6958709,2368209,4004486,4603790,8584686,4846313,5992187,1894561,9653381,9572631,3024642,3194107,7834320,4545974,6243225,5866668,5358825,6606872,5392471,1362960,9954544,4158294,7925231,6069641,9396301,2946640,7708389,5514968,6014709,1372299,3421661,5150497,4008468,5298126,2243103,7428649,8902191,7824295,2916702,9393417,3995971,7999801,1792938,2502792,8146469,2937164,6939071,5904022,8729019,9300720,4910720,6877136,9117935,3636032,9279434,1667831,2534515,8511627,9510559,1428466,3602523,6937561,3283370,7483444,3457229,2033676,2848999,9641845,6750656,3414657,9519485,2771545,7396926,5259674,8880355,3356979,7401870,7537002,7822784,7258224,7619949,1351837,3986770,5388900,2783355,5885345,7711685,7533843,8645797,5894409,7084091,2023925,9585128,3241348,5181808,8486633,7509124,4420455,2102203,7391571,6408020,455270
3,5873672,2610733,5396316,5814620,7840362,9709548,5589263,4772842,6615524,1190475,4657211,4590332,7197799,6405685,2400756,4575637,7341857,1358840,9191680,5042007,5779602,2113876,8623138,6945663,8385284,6030639,1211624,8272674,3876358,5544769,8496246,3642486,2145874,6711380,2377685,7096176,7819900,7232131,8041687,5540786,4132888,1181274,3310287,6814514,8714462,1154083,6763565,8845474,6383575,1052734,4477722,8870193,9541183,5229187,8721603,5181121,6255996,2205200,6456222,2373291,1638992,8686996,9980773,8556671,2596588,8093048,3568054,8504623,7560211,8314971,7435653,9206100,4283401,6929321,7892547,6791992,1301025,7579025,2009506,7302032,6144348,1744049,4652954,4263351,2906402,5619476,5228500,9547088,4249618,3318664,9977890,4474014,5451385,3122970,4170928,6637084,5580062,3993637,6038879,2408584,4396011,7067474,1791290,3602249,5070022,4352478,5560974,5258575,3315643,7344192,6619781,4021240,2025161,2780471,2710296,7075027,5007125,6253387,7836242,2111541,1915847,1898132,8355621,729
5303,5968704,1875610,7719787,9693756,3544433,4869796,7704544,1145706,3255493,6317245,3472610,1031860,7589187,1587219,2316024,4919235,4710357,8832290,8419067,9547775,1521026,7727890,1486557,8126968,6568695,9818313,4580718,7411621,1897857,3689453,8011749,5526229,1439590,8686996,6624313,9006011,1031448,7397201,7323867,1022659,7661285,8611053,3187515,2266174,7030807,1988632,5002456,1447555,3030685,2144638,9576477,4895065,6220428,6371353,4662017,9210083,5910064,9719985,6841293,2452667,9932708,9657226,7213043,4825027,6706710,9017822,1225082,2321380,5676330,3470275,4499008,9314453,1728942,7214279,5987243,5545181,1679092,4130966,3308502,1485870,3416030,4101303,8604049,4545288,2805877,1714660,7760848,5083892,8944076,8083297,4341766,6709320,7851348,6984664,5069198,3818130,8206207,6047531,6206283,2856552,1208740,7201782,8676147,8264846,4168457,4111053,4267471,6577621,1911727,1806671,5765869,4645263,9599685,4241104,9358261,2449234,8053222,9979949,7151107,1476669,2177322,6751754,1148864,
1124420,7578201,5074142,1534347,3101135,8968246,2674316,5595993,3296829,1451263,9923645,3144943,9086761,5283157,1004257,4766937,7540847,3200012,2027496,3750564,3505432,5908416,9821609,3038925,8026718,5832611,6608383,9044326,6085433,6710281,7287475,6673751,9109970,6131713,8546234,6405960,5238250,1616333,1514984,6766036,2796127,5320922,7186264,8038940,6961318,2970397,8315383,1568405,8081375,4109130,7023391,7482070,1615234,2262878,9819137,4189880,1166305,1107666,7260147,2496063,1575958,6237045,1971740,8670928,6546585,3623809,8240676,3325531,5762435,4368408,4905502,4432128,6977523,5828079,7759201,8335571,8038803,2721008,9185089,3098388,5313919,6298019,5243469,1023483,4491729,7177612,1928619,5698440,4224899,1935623,4813766,4405349,8582626,1045181,9804031,9238922,2783630,3260299,8215820,3778030,2175399,7035339,5900039,7653457,9932296,8077117,6630218,7855743,2438110,8619705,4472229,5127288,2822357,5519500,7355453,5281784,1621139,9760635,1564010,5795806,1028564,1467605,5366516,55151
06,4708984,8016555,4503128,6819732,4639083,2340744,7748764,2092453,2947463,7022430,6272064,3833236,3221023,2265899,3006378,2264389,9246887,5345092,3754959,8768981,1659179,9620010,1245819,6007843,2458297,6713989,5858016,8057067,8871841,4948623,1234832,6412139,5526779,6626510,4506011,5199249,7400085,1258590,1335357,2441131,9518112,9328323,7513244,3718154,2872482,8686172,9312942,6069915,4521530,3169250,7329635,2481369,9345626,2539459,6019790,7796005,9426788,2333190,2661682,3400787,6518432,2717163,6953353,8526733,1576919,1944000,9968826,4507247,3821975,3500900,5690200,9840835,7295028,8545684,1834411,5398788,4384613,5723571,6194335,7624618,2287048,1958282,6211776,7065826,3871688,7312057,9001205,7084503,8918945,8507644,6545211,6089553,6200378,6205596,5275878,5133193,3368927,6631866,2766326,1216979,2129257,6648345,5746505,3151260,1655197,6860656,8165008,3309600,9723968,1857208,5513595,5124679,9537612,9171768,9135513,3667617,5696105,5065490,1733062,1155456,7295852,8720642,4797424,87
29431,8618469,2940185,1174819,8349166,5381072,4946838,9492019,6145721,8015182,2375488,8656646,7076538,8943801,5053405,9153228,6228530,9325851,8660079,5352508,6609756,8235595,3863174,6553588,5775894,5746368,7021057,6976562,6134460,3887207,3048950,2425750,9270370,2942520,1540664,3841339,4136734,4060379,6738983,2458023,8454223,6641342,3450637,7791198,2164138,2475189,2497436,5165878,1277404,9094314,4799072,8011611,2963394,9312530,8679718,6637908,5223281,1418579,9493942,6712203,2990997,8991867,8163360,4156784,2006210,2811096,4720794,8685211,6300903,6822616,2452804,7695617,2647125,7638488,7735992,9739898,5805557,2532318,6160552,5288925,7921936,3402160,8034545,2010192,3913024,7668701,8862503,8278717,8186294,5577865,2893081,5138687,9538436,7876892,3328140,5435317,4574264,1331100,9287811,6335372,2491119,5052169,8125869,5954284,6572814,9105850,7187225,7311096,9235763,4366760,3604034,9326538,5971450,2090805,3220886,7086151,2029556,9172729,6246246,1085006,8185333,1558105,7721298,1673873
,8433761,5778503,2401443,1425445,3955734,7078598,6142837,9639099,8200164,1102584,2389770,4702804,7423568,6611816,5854034,6531890,4533752,5199249,7982772,7802185,7578750,3470687,5305953,2196548,8727920,3662261,1259277,1384796,4084274);
+
+# Cleanup
+DROP VIEW v1;
+DROP TABLE t1;
+
--echo End of 5.5 tests
--echo restore defaults
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 5ba32e0bbd7..c1ccd35d5c1 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -3300,7 +3300,12 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used,
if (!insert_table(key_length, key, (*block_table),
tables_used->view_db.length,
HA_CACHE_TBL_NONTRANSACT, 0, 0, TRUE))
+ {
+ // Mark failed
+ (*block_table)->next= (*block_table)->prev= NULL;
+ (*block_table)->parent= NULL;
DBUG_RETURN(0);
+ }
/*
We do not need to register view tables here because they are already
present in the global list.
@@ -3324,11 +3329,21 @@ Query_cache::register_tables_from_list(THD *thd, TABLE_LIST *tables_used,
tables_used->callback_func,
tables_used->engine_data,
TRUE))
+ {
+ // Mark failed
+ (*block_table)->next= (*block_table)->prev= NULL;
+ (*block_table)->parent= NULL;
DBUG_RETURN(0);
+ }
if (tables_used->table->file->
register_query_cache_dependant_tables(thd, this, block_table, &n))
+ {
+ // Mark failed
+ (*block_table)->next= (*block_table)->prev= NULL;
+ (*block_table)->parent= NULL;
DBUG_RETURN(0);
+ }
}
}
DBUG_RETURN(n - counter);
@@ -3365,9 +3380,12 @@ my_bool Query_cache::register_all_tables(THD *thd,
for (Query_cache_block_table *tmp = block->table(0) ;
tmp != block_table;
tmp++)
- unlink_table(tmp);
- if (block_table->parent)
- unlink_table(block_table);
+ {
+ if (tmp->prev) // not marked as failed and unuseable
+ unlink_table(tmp);
+ else
+ break;
+ }
}
return test(n);
}
1
0