[Commits] 140fcab9571: Fixed compilation failure with dynamic InnoDB (-DPLUGIN_INNOBASE=DYNAMIC)
by jan 18 Jan '19
by jan 18 Jan '19
18 Jan '19
revision-id: 140fcab9571dbd15652ed7c7b798818556e3805d (mariadb-10.3.6-329-g140fcab9571)
parent(s): 06fd4e7ffbeacbcd951d07eab30d7cef709940c5
author: Jan Lindström
committer: Jan Lindström
timestamp: 2019-01-18 16:19:31 +0200
message:
Fixed compilation failure with dynamic InnoDB (-DPLUGIN_INNOBASE=DYNAMIC)
Fixed test failure on galera_var_slave_threads
---
include/mysql/service_wsrep.h | 60 ++-
.../suite/galera/r/galera_var_slave_threads.result | 402 +--------------------
.../suite/galera/t/galera_var_slave_threads.cnf | 7 +
.../suite/galera/t/galera_var_slave_threads.test | 10 +-
sql/service_wsrep.cc | 10 +
sql/sql_plugin_services.ic | 16 +-
storage/innobase/buf/buf0dump.cc | 2 +-
storage/innobase/handler/ha_innodb.cc | 14 +-
storage/innobase/row/row0ins.cc | 4 +-
storage/innobase/row/row0sel.cc | 2 +-
storage/innobase/row/row0upd.cc | 6 +-
storage/innobase/srv/srv0conc.cc | 6 +-
storage/innobase/srv/srv0start.cc | 2 +-
13 files changed, 108 insertions(+), 433 deletions(-)
diff --git a/include/mysql/service_wsrep.h b/include/mysql/service_wsrep.h
index 4c485d92659..5aa97cdb47e 100644
--- a/include/mysql/service_wsrep.h
+++ b/include/mysql/service_wsrep.h
@@ -1,6 +1,14 @@
#ifndef MYSQL_SERVICE_WSREP_INCLUDED
#define MYSQL_SERVICE_WSREP_INCLUDED
+enum Wsrep_service_key_type
+{
+ WSREP_SERVICE_KEY_SHARED,
+ WSREP_SERVICE_KEY_REFERENCE,
+ WSREP_SERVICE_KEY_UPDATE,
+ WSREP_SERVICE_KEY_EXCLUSIVE
+};
+
#if (defined (MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_DYNAMIC_INCLUDED)) || (!defined(MYSQL_DYNAMIC_PLUGIN) && defined(MYSQL_SERVICE_WSREP_STATIC_INCLUDED))
#else
@@ -36,6 +44,10 @@ struct xid_t;
struct wsrep_ws_handle;
struct wsrep_buf;
+/* Must match to definition in sql/mysqld.h */
+typedef int64 query_id_t;
+
+
extern struct wsrep_service_st {
my_bool (*get_wsrep_recovery_func)();
bool (*wsrep_consistency_check_func)(MYSQL_THD thd);
@@ -52,6 +64,23 @@ extern struct wsrep_service_st {
long long (*wsrep_thd_trx_seqno_func)(const MYSQL_THD thd);
my_bool (*wsrep_thd_is_aborting_func)(const MYSQL_THD thd);
void (*wsrep_set_data_home_dir_func)(const char *data_dir);
+ my_bool (*wsrep_thd_is_BF_func)(const MYSQL_THD thd, my_bool sync);
+ my_bool (*wsrep_thd_is_local_func)(const MYSQL_THD thd);
+ void (*wsrep_thd_self_abort_func)(MYSQL_THD thd);
+ int (*wsrep_thd_append_key_func)(MYSQL_THD thd, const struct wsrep_key* key,
+ int n_keys, enum Wsrep_service_key_type);
+ const char* (*wsrep_thd_client_state_str_func)(const MYSQL_THD thd);
+ const char* (*wsrep_thd_client_mode_str_func)(const MYSQL_THD thd);
+ const char* (*wsrep_thd_transaction_state_str_func)(const MYSQL_THD thd);
+ query_id_t (*wsrep_thd_transaction_id_func)(const MYSQL_THD thd);
+ my_bool (*wsrep_thd_bf_abort_func)(const MYSQL_THD bf_thd,
+ MYSQL_THD victim_thd,
+ my_bool signal);
+ my_bool (*wsrep_thd_order_before_func)(const MYSQL_THD left, const MYSQL_THD right);
+ void (*wsrep_handle_SR_rollback_func)(MYSQL_THD BF_thd, MYSQL_THD victim_thd);
+ my_bool (*wsrep_thd_skip_locking_func)(const MYSQL_THD thd);
+ const char* (*wsrep_get_sr_table_name_func)();
+ my_bool (*wsrep_get_debug_func)();
} *wsrep_service;
#define MYSQL_SERVICE_WSREP_INCLUDED
@@ -66,7 +95,7 @@ extern struct wsrep_service_st {
#define wsrep_xid_seqno(X) wsrep_service->wsrep_xid_seqno_func(X)
#define wsrep_xid_uuid(X) wsrep_service->wsrep_xid_uuid_func(X)
#define wsrep_on(X) wsrep_service->wsrep_on_func(X)
-#define wsrep_prepare_key_for_innodb(A,B,C,D,E,F,G) wsrep_service->wsrep_prepare_key_for_innodb_func(A,B,C,D,E,F.G)
+#define wsrep_prepare_key_for_innodb(A,B,C,D,E,F,G) wsrep_service->wsrep_prepare_key_for_innodb_func(A,B,C,D,E,F,G)
#define wsrep_thd_LOCK(T) wsrep_service->wsrep_thd_LOCK_func(T)
#define wsrep_thd_UNLOCK(T) wsrep_service->wsrep_thd_UNLOCK_func(T)
#define wsrep_thd_query(T) wsrep_service->wsrep_thd_query_func(T)
@@ -74,8 +103,21 @@ extern struct wsrep_service_st {
#define wsrep_thd_ignore_table(T) wsrep_service->wsrep_thd_ignore_table_func(T)
#define wsrep_thd_trx_seqno(T) wsrep_service->wsrep_thd_trx_seqno_func(T)
#define wsrep_set_data_home_dir(A) wsrep_service->wsrep_set_data_home_dir_func(A)
-
#define wsrep_thd_is_BF(T,S) wsrep_service->wsrep_thd_is_BF_func(T,S)
+#define wsrep_thd_is_aborting(T) wsrep_service->wsrep_thd_is_aborting_func(T)
+#define wsrep_thd_is_local(T) wsrep_service->wsrep_thd_is_local_func(T)
+#define wsrep_thd_self_abort(T) wsrep_service->wsrep_thd_self_abort_func(T)
+#define wsrep_thd_append_key(T,W,N,K) wsrep_service->wsrep_thd_append_key_func(T,W,N,K)
+#define wsrep_thd_client_state_str(T) wsrep_service->wsrep_thd_client_state_str_func(T)
+#define wsrep_thd_client_mode_str(T) wsrep_service->wsrep_thd_client_mode_str_func(T)
+#define wsrep_thd_transaction_state_str(T) wsrep_service->wsrep_thd_transaction_state_str_func(T)
+#define wsrep_thd_transaction_id(T) wsrep_service->wsrep_thd_transaction_id_func(T)
+#define wsrep_thd_bf_abort(T,T2,S) wsrep_service->wsrep_thd_bf_abort_func(T,T2,S)
+#define wsrep_thd_order_before(L,R) wsrep_service->wsrep_thd_order_before_func(L,R)
+#define wsrep_handle_SR_rollback(B,V) wsrep_service->wsrep_handle_SR_rollback_func(B,V)
+#define wsrep_thd_skip_locking(T) wsrep_service->wsrep_thd_skip_locking_func(T)
+#define wsrep_get_sr_table_name() wsrep_service->wsrep_get_sr_table_name_func()
+#define wsrep_get_debug() wsrep_service->wsrep_get_debug_func()
#else
@@ -99,12 +141,9 @@ my_bool get_wsrep_recovery();
bool wsrep_thd_ignore_table(MYSQL_THD thd);
void wsrep_set_data_home_dir(const char *data_dir);
-
/* from mysql wsrep-lib */
#include "my_global.h"
#include "my_pthread.h"
-/* Must match to definition in sql/mysqld.h */
-typedef int64 query_id_t;
/* Return true if wsrep is enabled for a thd. This means that
wsrep is enabled globally and the thd has wsrep on */
@@ -155,14 +194,6 @@ extern "C" my_bool wsrep_thd_skip_locking(const MYSQL_THD thd);
/* Return true if thd is aborting */
extern "C" my_bool wsrep_thd_is_aborting(const MYSQL_THD thd);
-
-enum Wsrep_service_key_type
-{
- WSREP_SERVICE_KEY_SHARED,
- WSREP_SERVICE_KEY_REFERENCE,
- WSREP_SERVICE_KEY_UPDATE,
- WSREP_SERVICE_KEY_EXCLUSIVE
-};
struct wsrep_key;
struct wsrep_key_array;
extern "C" int wsrep_thd_append_key(MYSQL_THD thd,
@@ -172,5 +203,8 @@ extern "C" int wsrep_thd_append_key(MYSQL_THD thd,
extern const char* wsrep_sr_table_name_full;
+extern "C" const char* wsrep_get_sr_table_name();
+
+extern "C" my_bool wsrep_get_debug();
#endif
#endif /* MYSQL_SERVICE_WSREP_INCLUDED */
diff --git a/mysql-test/suite/galera/r/galera_var_slave_threads.result b/mysql-test/suite/galera/r/galera_var_slave_threads.result
index 108908551f6..168b45154b8 100644
--- a/mysql-test/suite/galera/r/galera_var_slave_threads.result
+++ b/mysql-test/suite/galera/r/galera_var_slave_threads.result
@@ -27,8 +27,8 @@ SET GLOBAL wsrep_slave_threads = 64;
connection node_1;
INSERT INTO t1 VALUES (1);
connection node_2;
-SELECT COUNT(*) = 1 FROM t1;
-COUNT(*) = 1
+SELECT COUNT(*) FROM t1;
+COUNT(*)
1
SELECT COUNT(*) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE USER = 'system user' AND STATE LIKE '%wsrep aborter%';
COUNT(*)
@@ -65,401 +65,19 @@ connection node_2;
SET GLOBAL wsrep_slave_threads = 1;
connection node_1;
connection node_2;
-SELECT * FROM t1;
-f1
+SELECT COUNT(*) FROM t1;
+COUNT(*)
1
-SELECT * FROM t2;
-f1
-3
-5
-7
-9
-11
-13
-15
-17
-19
-21
-23
-25
-27
-29
-31
-33
-35
-37
-39
-41
-43
-45
-47
-49
-51
-53
-55
-57
-59
-61
-63
-65
-67
-69
-71
-73
-75
-77
-79
-81
-83
-85
-87
-89
-91
-93
-95
-97
-99
-101
-103
-105
-107
-109
-111
-113
-115
-117
-119
-121
-123
-125
-127
-129
-132
-134
-136
-138
-140
-142
-144
-146
-148
-150
-152
-154
-156
-158
-160
-162
-164
-166
-168
-170
-172
-174
-176
-178
-180
-182
-184
-186
-188
-190
+SELECT COUNT(*) FROM t2;
+COUNT(*)
192
-194
-196
-198
-200
-202
-204
-206
-208
-210
-212
-214
-216
-218
-220
-222
-224
-226
-228
-230
-232
-234
-236
-238
-240
-242
-244
-246
-248
-250
-252
-254
-256
-258
-259
-261
-263
-265
-267
-269
-271
-273
-275
-277
-279
-281
-283
-285
-287
-289
-291
-293
-295
-297
-299
-301
-303
-305
-307
-309
-311
-313
-315
-317
-319
-321
-323
-325
-327
-329
-331
-333
-335
-337
-339
-341
-343
-345
-347
-349
-351
-353
-355
-357
-359
-361
-363
-365
-367
-369
-371
-373
-375
-377
-379
-381
-383
-385
connection node_1;
-SELECT * FROM t1;
-f1
+SELECT COUNT(*) FROM t1;
+COUNT(*)
1
-SELECT * FROM t2;
-f1
-3
-5
-7
-9
-11
-13
-15
-17
-19
-21
-23
-25
-27
-29
-31
-33
-35
-37
-39
-41
-43
-45
-47
-49
-51
-53
-55
-57
-59
-61
-63
-65
-67
-69
-71
-73
-75
-77
-79
-81
-83
-85
-87
-89
-91
-93
-95
-97
-99
-101
-103
-105
-107
-109
-111
-113
-115
-117
-119
-121
-123
-125
-127
-129
-132
-134
-136
-138
-140
-142
-144
-146
-148
-150
-152
-154
-156
-158
-160
-162
-164
-166
-168
-170
-172
-174
-176
-178
-180
-182
-184
-186
-188
-190
+SELECT COUNT(*) FROM t2;
+COUNT(*)
192
-194
-196
-198
-200
-202
-204
-206
-208
-210
-212
-214
-216
-218
-220
-222
-224
-226
-228
-230
-232
-234
-236
-238
-240
-242
-244
-246
-248
-250
-252
-254
-256
-258
-259
-261
-263
-265
-267
-269
-271
-273
-275
-277
-279
-281
-283
-285
-287
-289
-291
-293
-295
-297
-299
-301
-303
-305
-307
-309
-311
-313
-315
-317
-319
-321
-323
-325
-327
-329
-331
-333
-335
-337
-339
-341
-343
-345
-347
-349
-351
-353
-355
-357
-359
-361
-363
-365
-367
-369
-371
-373
-375
-377
-379
-381
-383
-385
DROP TABLE t1;
DROP TABLE t2;
# End of tests
diff --git a/mysql-test/suite/galera/t/galera_var_slave_threads.cnf b/mysql-test/suite/galera/t/galera_var_slave_threads.cnf
new file mode 100644
index 00000000000..889c81b4a0a
--- /dev/null
+++ b/mysql-test/suite/galera/t/galera_var_slave_threads.cnf
@@ -0,0 +1,7 @@
+!include ../galera_2nodes.cnf
+
+[mysqld.1]
+auto_increment_offset=1
+
+[mysqld.2]
+auto_increment_offset=2
diff --git a/mysql-test/suite/galera/t/galera_var_slave_threads.test b/mysql-test/suite/galera/t/galera_var_slave_threads.test
index d0784bfd871..12d8006db4b 100644
--- a/mysql-test/suite/galera/t/galera_var_slave_threads.test
+++ b/mysql-test/suite/galera/t/galera_var_slave_threads.test
@@ -39,7 +39,7 @@ SET GLOBAL wsrep_slave_threads = 64;
INSERT INTO t1 VALUES (1);
--connection node_2
-SELECT COUNT(*) = 1 FROM t1;
+SELECT COUNT(*) FROM t1;
#
# note, in wsrep API #26, we have 2 rollbacker threads, counted as system user's
@@ -177,13 +177,13 @@ while ($count)
--let $wait_condition = SELECT VARIABLE_VALUE = @@wsrep_slave_threads + 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_thread_count';
--source include/wait_condition.inc
-SELECT * FROM t1;
-SELECT * FROM t2;
+SELECT COUNT(*) FROM t1;
+SELECT COUNT(*) FROM t2;
--connection node_1
-SELECT * FROM t1;
-SELECT * FROM t2;
+SELECT COUNT(*) FROM t1;
+SELECT COUNT(*) FROM t2;
DROP TABLE t1;
DROP TABLE t2;
diff --git a/sql/service_wsrep.cc b/sql/service_wsrep.cc
index 3375073311f..f4cf49b9b84 100644
--- a/sql/service_wsrep.cc
+++ b/sql/service_wsrep.cc
@@ -80,6 +80,16 @@ extern "C" void wsrep_thd_self_abort(THD *thd)
thd->wsrep_cs().bf_abort(wsrep::seqno(0));
}
+extern "C" const char* wsrep_get_sr_table_name()
+{
+ return wsrep_sr_table_name_full;
+}
+
+extern "C" my_bool wsrep_get_debug()
+{
+ return wsrep_debug;
+}
+
extern "C" my_bool wsrep_thd_is_local(const THD *thd)
{
return thd->wsrep_cs().mode() == wsrep::client_state::m_local;
diff --git a/sql/sql_plugin_services.ic b/sql/sql_plugin_services.ic
index 0feecf219bd..8893ea361e3 100644
--- a/sql/sql_plugin_services.ic
+++ b/sql/sql_plugin_services.ic
@@ -156,7 +156,21 @@ static struct wsrep_service_st wsrep_handler = {
wsrep_thd_ignore_table,
wsrep_thd_trx_seqno,
wsrep_thd_is_aborting,
- wsrep_set_data_home_dir
+ wsrep_set_data_home_dir,
+ wsrep_thd_is_BF,
+ wsrep_thd_is_local,
+ wsrep_thd_self_abort,
+ wsrep_thd_append_key,
+ wsrep_thd_client_state_str,
+ wsrep_thd_client_mode_str,
+ wsrep_thd_transaction_state_str,
+ wsrep_thd_transaction_id,
+ wsrep_thd_bf_abort,
+ wsrep_thd_order_before,
+ wsrep_handle_SR_rollback,
+ wsrep_thd_skip_locking,
+ wsrep_get_sr_table_name,
+ wsrep_get_debug
};
static struct thd_specifics_service_st thd_specifics_handler=
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc
index c745bc9f4c3..2747a6fa338 100644
--- a/storage/innobase/buf/buf0dump.cc
+++ b/storage/innobase/buf/buf0dump.cc
@@ -856,7 +856,7 @@ DECLARE_THREAD(buf_dump_thread)(void*)
"Dumping of buffer pool not started"
" as load was incomplete");
#ifdef WITH_WSREP
- } else if (wsrep_recovery) {
+ } else if (get_wsrep_recovery()) {
#endif /* WITH_WSREP */
} else {
buf_dump(FALSE/* do complete dump at shutdown */);
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index e194c47a518..9511051fbe2 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -131,6 +131,9 @@ void close_thread_tables(THD* thd);
#define tdc_size 400
#endif
+#include <mysql/plugin.h>
+#include <mysql/service_wsrep.h>
+
#include "ha_innodb.h"
#include "i_s.h"
#include "sync0sync.h"
@@ -138,9 +141,6 @@ void close_thread_tables(THD* thd);
#include <string>
#include <sstream>
-#include <mysql/plugin.h>
-#include <mysql/service_wsrep.h>
-
#ifdef WITH_WSREP
#include "dict0priv.h"
#include <mysql/service_md5.h>
@@ -148,14 +148,6 @@ void close_thread_tables(THD* thd);
extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
-extern bool wsrep_prepare_key_for_innodb(
- THD* thd,
- const uchar *cache_key,
- size_t cache_key_len,
- const uchar* row_id,
- size_t row_id_len,
- wsrep_buf_t* key,
- size_t* key_len);
#endif /* WITH_WSREP */
/** to force correct commit order in binlog */
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 4acf244bf55..ed72f6d482b 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -3241,11 +3241,11 @@ row_ins_clust_index_entry(
: (index->table->is_temporary() || skip_locking)
? BTR_NO_LOCKING_FLAG : 0;
#ifdef UNIV_DEBUG
- if (skip_locking && strcmp(wsrep_sr_table_name_full,
+ if (skip_locking && strcmp(wsrep_get_sr_table_name(),
index->table->name.m_name)) {
WSREP_ERROR("Record locking is disabled in this thread, "
"but the table being modified is not "
- "`%s`: `%s`.", wsrep_sr_table_name_full,
+ "`%s`: `%s`.", wsrep_get_sr_table_name(),
index->table->name.m_name);
ut_error;
}
diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc
index aeaa98b5676..2657839c93e 100644
--- a/storage/innobase/row/row0sel.cc
+++ b/storage/innobase/row/row0sel.cc
@@ -4468,7 +4468,7 @@ row_search_mvcc(
}
#ifdef WITH_WSREP
else if (wsrep_thd_skip_locking(trx->mysql_thd)) {
- ut_ad(!strcmp(wsrep_sr_table_name_full,
+ ut_ad(!strcmp(wsrep_get_sr_table_name(),
prebuilt->table->name.m_name));
set_also_gap_locks = FALSE;
}
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc
index 591ae238c43..a60210c77c8 100644
--- a/storage/innobase/row/row0upd.cc
+++ b/storage/innobase/row/row0upd.cc
@@ -2458,7 +2458,7 @@ row_upd_sec_index_entry(
err = DB_SUCCESS;
break;
case DB_DEADLOCK:
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::warn() << "WSREP: sec index FK check fail for deadlock"
<< " index " << index->name
<< " table " << index->table->name;
@@ -2773,7 +2773,7 @@ row_upd_clust_rec_by_insert(
err = DB_SUCCESS;
break;
case DB_DEADLOCK:
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::warn() << "WSREP: sec index FK check fail for deadlock"
<< " index " << index->name
<< " table " << index->table->name;
@@ -3002,7 +3002,7 @@ row_upd_del_mark_clust_rec(
err = DB_SUCCESS;
break;
case DB_DEADLOCK:
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::warn() << "WSREP: sec index FK check fail for deadlock"
<< " index " << index->name
<< " table " << index->table->name;
diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc
index ec1e151c03b..b2b464e31fa 100644
--- a/storage/innobase/srv/srv0conc.cc
+++ b/storage/innobase/srv/srv0conc.cc
@@ -120,7 +120,7 @@ srv_conc_enter_innodb_with_atomics(
#ifdef WITH_WSREP
if (wsrep_on(trx->mysql_thd) &&
wsrep_thd_is_aborting(trx->mysql_thd)) {
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::info() <<
"srv_conc_enter due to MUST_ABORT";
}
@@ -308,14 +308,14 @@ wsrep_srv_conc_cancel_wait(
srv_conc_enter_innodb_with_atomics(). No need to cancel here,
thr will wake up after os_sleep and let to enter innodb
*/
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::info() << "WSREP: conc slot cancel, no atomics";
}
#else
// JAN: TODO: MySQL 5.7
//os_fast_mutex_lock(&srv_conc_mutex);
if (trx->wsrep_event) {
- if (wsrep_debug) {
+ if (wsrep_get_debug()) {
ib::info() << "WSREP: conc slot cancel";
}
os_event_set(trx->wsrep_event);
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 54b0e75fd80..e15afcf9cd7 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -2328,7 +2328,7 @@ dberr_t srv_start(bool create_new_db)
Create the dump/load thread only when not running with
--wsrep-recover.
*/
- if (!wsrep_recovery) {
+ if (!get_wsrep_recovery()) {
#endif /* WITH_WSREP */
/* Create the buffer pool dump/load thread */
1
0
revision-id: 79b48d9a6656b5cf7aa43742e28aa53e6c110604 (mariadb-10.1.37-65-g79b48d9a665)
parent(s): 71463b21321ea3532d6e78f811b191eee61e7841
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2019-01-18 14:30:15 +0100
message:
c
---
sql/sql_view.cc | 31 ++++++++++++-------------------
sql/sql_view.h | 2 +-
sql/table.cc | 21 ++++++++++++++-------
sql/table.h | 26 ++++++++++++++++++++++++++
4 files changed, 53 insertions(+), 27 deletions(-)
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index ee169de4c93..45f5426b117 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -1135,7 +1135,6 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
DBUG_RETURN(error);
}
-#define MD5_LEN 32
/**
Check is TABLE_LEST and SHARE match
@param[in] view TABLE_LIST of the view
@@ -1144,28 +1143,22 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
@return false on error or misspatch
*/
-bool mariadb_view_version_check(TABLE_LIST *view, TABLE_SHARE *share)
+bool mariadb_view_version_get(TABLE_SHARE *share)
{
- LEX_STRING md5;
- char md5_buffer[MD5_LEN + 1];
- md5.str= md5_buffer;
- md5.length= MD5_LEN;
+ DBUG_ASSERT(share->is_view);
- /*
- Check that both were views (view->is_view() could not be checked
- because it is not opened).
- */
- if (!share->is_view || view->md5.length != MD5_LEN)
- return FALSE;
+ if (!(share->tabledef_version.str=
+ (uchar*) alloc_root(&share->mem_root, VIEW_MD5_LEN + 1)))
+ return TRUE;
+ share->tabledef_version.length= VIEW_MD5_LEN;
DBUG_ASSERT(share->view_def != NULL);
- if (share->view_def->parse((uchar*)&md5, NULL,
- view_md5_parameters,
- 1,
- &file_parser_dummy_hook))
- return FALSE;
- DBUG_ASSERT(md5.length == MD5_LEN);
- return (strncmp(md5.str, view->md5.str, MD5_LEN) == 0);
+ if (share->view_def->parse((uchar *) &share->tabledef_version, NULL,
+ view_md5_parameters, 1,
+ &file_parser_dummy_hook))
+ return TRUE;
+ DBUG_ASSERT(share->tabledef_version.length == VIEW_MD5_LEN);
+ return FALSE;
}
/**
diff --git a/sql/sql_view.h b/sql/sql_view.h
index 1685169420d..67187a0624a 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -37,7 +37,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *view,
bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table,
bool open_view_no_parse);
-bool mariadb_view_version_check(TABLE_LIST *view, TABLE_SHARE *share);
+bool mariadb_view_version_get(TABLE_SHARE *share);
bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
diff --git a/sql/table.cc b/sql/table.cc
index 60f263ee841..7d1d5d3a85a 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -609,7 +609,11 @@ enum open_frm_error open_table_def(THD *thd, TABLE_SHARE *share, uint flags)
if (!share->view_def)
share->error= OPEN_FRM_ERROR_ALREADY_ISSUED;
else
+ {
share->error= OPEN_FRM_OK;
+ if (mariadb_view_version_get(share))
+ share->error= OPEN_FRM_CORRUPTED;
+ }
}
else
share->error= OPEN_FRM_NOT_A_TABLE;
@@ -7504,19 +7508,22 @@ bool TABLE_LIST::is_table_ref_id_equal(TABLE_SHARE *s)
bool res= m_table_ref_version == s->get_table_ref_version();
/*
- If definition is different object with view we can check MD5 in frm
- to check if the same view got into table definition cache again.
+ If definition is different check content version
*/
- if (!res &&
- tp == TABLE_REF_VIEW &&
- mariadb_view_version_check(this, s))
+ if (tabledef_version.length &&
+ tabledef_version.length == s->tabledef_version.length &&
+ memcmp(tabledef_version.str, s->tabledef_version.str,
+ tabledef_version.length) == 0)
{
- // to avoid relatively expensive parsing of frm next time
- set_table_ref_id(s);
+ set_table_id(s);
return TRUE;
}
+ else
+ tabledef_version.length= 0;
return res;
}
+ else
+ set_tabledef_version(s);
return FALSE;
}
diff --git a/sql/table.h b/sql/table.h
index 9e1a061e606..c9dd8d0146c 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -61,6 +61,8 @@ class TDC_element;
*/
typedef ulonglong nested_join_map;
+#define VIEW_MD5_LEN 32
+
#define tmp_file_prefix "#sql" /**< Prefix for tmp tables */
#define tmp_file_prefix_length 4
@@ -1998,6 +2000,10 @@ struct TABLE_LIST
to view with SQL SECURITY DEFINER)
*/
Security_context *security_ctx;
+ uchar tabledef_version_buf[MY_UUID_SIZE > VIEW_MD5_LEN ?
+ MY_UUID_SIZE + 1 : VIEW_MD5_LEN + 1];
+ LEX_CUSTRING tabledef_version;
+
/*
This view security context (non-zero only for views with
SQL SECURITY DEFINER)
@@ -2290,6 +2296,26 @@ struct TABLE_LIST
m_table_ref_version= table_ref_version_arg;
}
+ void set_table_id(TABLE_SHARE *s)
+ {
+ set_table_ref_id(s);
+ set_tabledef_version(s);
+ }
+
+ void set_tabledef_version(TABLE_SHARE *s)
+ {
+ if (!tabledef_version.length && s->tabledef_version.length)
+ {
+ DBUG_ASSERT(s->tabledef_version.length <
+ sizeof(tabledef_version_buf));
+ tabledef_version.str= tabledef_version_buf;
+ memcpy(tabledef_version_buf, s->tabledef_version.str,
+ (tabledef_version.length= s->tabledef_version.length));
+ // safety
+ tabledef_version_buf[tabledef_version.length]= 0;
+ }
+ }
+
/* Set of functions returning/setting state of a derived table/view. */
inline bool is_non_derived()
{
1
0
revision-id: cc18a5db9bce667c9b8722cdf6f51ee83b55a4b0 (mariadb-10.4.1-98-gcc18a5d)
parent(s): dd03cb3776e6d25dc1dd2c3a83473a1b78ae99f9
committer: Alexey Botchkov
timestamp: 2019-01-18 03:18:02 +0400
message:
MDEV-5313 Improving audit API.
json_locate_key() implemented.
get rid of 'key_len' argument in functions.
---
include/json_lib.h | 5 ++
include/mysql/plugin_audit.h.pp | 4 +-
include/mysql/plugin_auth.h.pp | 4 +-
include/mysql/plugin_encryption.h.pp | 4 +-
include/mysql/plugin_ftparser.h.pp | 4 +-
include/mysql/plugin_password_validation.h.pp | 4 +-
include/mysql/service_json.h | 4 +-
sql/sql_acl.cc | 100 +++++++++++++-------------
strings/json_lib.c | 94 +++++++++++++++++++++++-
unittest/strings/json-t.c | 28 +++++++-
10 files changed, 185 insertions(+), 66 deletions(-)
diff --git a/include/json_lib.h b/include/json_lib.h
index a347538..b6add6d 100644
--- a/include/json_lib.h
+++ b/include/json_lib.h
@@ -425,6 +425,11 @@ int json_path_compare(const json_path_t *a, const json_path_t *b,
int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs);
+int json_locate_key(const char *js, const char *js_end,
+ const char *kname,
+ const char **key_start, const char **key_end,
+ int *comma_pos);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/mysql/plugin_audit.h.pp b/include/mysql/plugin_audit.h.pp
index 47f07ae..c5ae678 100644
--- a/include/mysql/plugin_audit.h.pp
+++ b/include/mysql/plugin_audit.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
int n_item,
const char **value, int *value_len);
enum json_types (*json_get_object_key)(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
int n_item,
const char **value, int *value_len);
enum json_types json_get_object_key(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
const char **keyname, const char **keyname_end,
diff --git a/include/mysql/plugin_auth.h.pp b/include/mysql/plugin_auth.h.pp
index f9d01a8..41cb7d07 100644
--- a/include/mysql/plugin_auth.h.pp
+++ b/include/mysql/plugin_auth.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
int n_item,
const char **value, int *value_len);
enum json_types (*json_get_object_key)(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
int n_item,
const char **value, int *value_len);
enum json_types json_get_object_key(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
const char **keyname, const char **keyname_end,
diff --git a/include/mysql/plugin_encryption.h.pp b/include/mysql/plugin_encryption.h.pp
index e55a034..6597dec 100644
--- a/include/mysql/plugin_encryption.h.pp
+++ b/include/mysql/plugin_encryption.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
int n_item,
const char **value, int *value_len);
enum json_types (*json_get_object_key)(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
int n_item,
const char **value, int *value_len);
enum json_types json_get_object_key(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
const char **keyname, const char **keyname_end,
diff --git a/include/mysql/plugin_ftparser.h.pp b/include/mysql/plugin_ftparser.h.pp
index f9d9844..bd1cfc7 100644
--- a/include/mysql/plugin_ftparser.h.pp
+++ b/include/mysql/plugin_ftparser.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
int n_item,
const char **value, int *value_len);
enum json_types (*json_get_object_key)(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
int n_item,
const char **value, int *value_len);
enum json_types json_get_object_key(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
const char **keyname, const char **keyname_end,
diff --git a/include/mysql/plugin_password_validation.h.pp b/include/mysql/plugin_password_validation.h.pp
index b672db6..2f9d229 100644
--- a/include/mysql/plugin_password_validation.h.pp
+++ b/include/mysql/plugin_password_validation.h.pp
@@ -393,7 +393,7 @@ extern struct json_service_st {
int n_item,
const char **value, int *value_len);
enum json_types (*json_get_object_key)(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
int nkey,
@@ -410,7 +410,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
int n_item,
const char **value, int *value_len);
enum json_types json_get_object_key(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
const char **keyname, const char **keyname_end,
diff --git a/include/mysql/service_json.h b/include/mysql/service_json.h
index 734787a..141b762 100644
--- a/include/mysql/service_json.h
+++ b/include/mysql/service_json.h
@@ -66,7 +66,7 @@ extern struct json_service_st {
int n_item,
const char **value, int *value_len);
enum json_types (*json_get_object_key)(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types (*json_get_object_nkey)(const char *js,const char *js_end,
int nkey,
@@ -95,7 +95,7 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
int n_item,
const char **value, int *value_len);
enum json_types json_get_object_key(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len);
enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey,
const char **keyname, const char **keyname_end,
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 61d6812..bb5a397 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -1204,16 +1204,16 @@ class User_table_json: public User_table
int get_auth(THD *thd, MEM_ROOT *root, const char **plugin, const char **authstr) const
{
- *plugin= get_str_value(root, STRING_WITH_LEN("plugin"));
+ *plugin= get_str_value(root, "plugin");
if (!**plugin)
*plugin= native_password_plugin_name.str;
- *authstr= get_str_value(root, STRING_WITH_LEN("authentication_string"));
+ *authstr= get_str_value(root, "authentication_string");
return *plugin == NULL || *authstr == NULL;
}
void set_auth(const char *p, size_t pl, const char *as, size_t asl) const
{
- set_str_value(STRING_WITH_LEN("plugin"), p, pl);
- set_str_value(STRING_WITH_LEN("authentication_string"), as, asl);
+ set_str_value("plugin", p, pl);
+ set_str_value("authentication_string", as, asl);
}
ulong get_access() const
{
@@ -1222,7 +1222,7 @@ class User_table_json: public User_table
(or, for example, my_count_bits(GLOBAL_ACLS))
in the json too, and it'll allow us to do privilege upgrades
*/
- return get_int_value(STRING_WITH_LEN("access")) & GLOBAL_ACLS;
+ return get_int_value("access") & GLOBAL_ACLS;
}
void set_access(ulong rights, bool revoke) const
{
@@ -1231,53 +1231,53 @@ class User_table_json: public User_table
access&= ~rights;
else
access|= rights;
- set_int_value(STRING_WITH_LEN("access"), access & GLOBAL_ACLS);
+ set_int_value("access", access & GLOBAL_ACLS);
}
SSL_type get_ssl_type () const
- { return (SSL_type)get_int_value(STRING_WITH_LEN("ssl_type")); }
+ { return (SSL_type)get_int_value("ssl_type"); }
int set_ssl_type (SSL_type x) const
- { return set_int_value(STRING_WITH_LEN("ssl_type"), x); }
+ { return set_int_value("ssl_type", x); }
const char* get_ssl_cipher (MEM_ROOT *root) const
- { return get_str_value(root, STRING_WITH_LEN("ssl_cipher")); }
+ { return get_str_value(root, "ssl_cipher"); }
int set_ssl_cipher (const char *s, size_t l) const
- { return set_str_value(STRING_WITH_LEN("ssl_cipher"), s, l); }
+ { return set_str_value("ssl_cipher", s, l); }
const char* get_x509_issuer (MEM_ROOT *root) const
- { return get_str_value(root, STRING_WITH_LEN("x509_issuer")); }
+ { return get_str_value(root, "x509_issuer"); }
int set_x509_issuer (const char *s, size_t l) const
- { return set_str_value(STRING_WITH_LEN("x509_issuer"), s, l); }
+ { return set_str_value("x509_issuer", s, l); }
const char* get_x509_subject (MEM_ROOT *root) const
- { return get_str_value(root, STRING_WITH_LEN("x509_subject")); }
+ { return get_str_value(root, "x509_subject"); }
int set_x509_subject (const char *s, size_t l) const
- { return set_str_value(STRING_WITH_LEN("x509_subject"), s, l); }
+ { return set_str_value("x509_subject", s, l); }
longlong get_max_questions () const
- { return get_int_value(STRING_WITH_LEN("max_questions")); }
+ { return get_int_value("max_questions"); }
int set_max_questions (longlong x) const
- { return set_int_value(STRING_WITH_LEN("max_questions"), x); }
+ { return set_int_value("max_questions", x); }
longlong get_max_updates () const
- { return get_int_value(STRING_WITH_LEN("max_updates")); }
+ { return get_int_value("max_updates"); }
int set_max_updates (longlong x) const
- { return set_int_value(STRING_WITH_LEN("max_updates"), x); }
+ { return set_int_value("max_updates", x); }
longlong get_max_connections () const
- { return get_int_value(STRING_WITH_LEN("max_connections")); }
+ { return get_int_value("max_connections"); }
int set_max_connections (longlong x) const
- { return set_int_value(STRING_WITH_LEN("max_connections"), x); }
+ { return set_int_value("max_connections", x); }
longlong get_max_user_connections () const
- { return get_int_value(STRING_WITH_LEN("max_user_connections")); }
+ { return get_int_value("max_user_connections"); }
int set_max_user_connections (longlong x) const
- { return set_int_value(STRING_WITH_LEN("max_user_connections"), x); }
+ { return set_int_value("max_user_connections", x); }
double get_max_statement_time () const
- { return get_double_value(STRING_WITH_LEN("max_statement_time")); }
+ { return get_double_value("max_statement_time"); }
int set_max_statement_time (double x) const
- { return set_double_value(STRING_WITH_LEN("max_statement_time"), x); }
+ { return set_double_value("max_statement_time", x); }
bool get_is_role () const
- { return get_bool_value(STRING_WITH_LEN("is_role")); }
+ { return get_bool_value("is_role"); }
int set_is_role (bool x) const
- { return set_bool_value(STRING_WITH_LEN("is_role"), x); }
+ { return set_bool_value("is_role", x); }
const char* get_default_role (MEM_ROOT *root) const
- { return get_str_value(root, STRING_WITH_LEN("default_role")); }
+ { return get_str_value(root, "default_role"); }
int set_default_role (const char *s, size_t l) const
- { return set_str_value(STRING_WITH_LEN("default_role"), s, l); }
+ { return set_str_value("default_role", s, l); }
~User_table_json() {}
private:
@@ -1290,24 +1290,24 @@ class User_table_json: public User_table
USERNAME_CHAR_LENGTH);
return 0;
}
- bool get_value(const char *key, size_t klen,
+ bool get_value(const char *key,
enum json_types vt, const char **v, size_t *vl) const
{
enum json_types value_type;
int int_vl;
String str, *res= m_table->field[2]->val_str(&str);
if (!res ||
- (value_type= json_get_object_key(res->ptr(), res->end(),
- key, key+klen, v, &int_vl)) == JSV_BAD_JSON)
+ (value_type= json_get_object_key(res->ptr(), res->end(), key,
+ v, &int_vl)) == JSV_BAD_JSON)
return 1; // invalid
*vl= int_vl;
return value_type != vt;
}
- const char *get_str_value(MEM_ROOT *root, const char *key, size_t klen) const
+ const char *get_str_value(MEM_ROOT *root, const char *key) const
{
size_t value_len;
const char *value_start;
- if (get_value(key, klen, JSV_STRING, &value_start, &value_len))
+ if (get_value(key, JSV_STRING, &value_start, &value_len))
return "";
char *ptr= (char*)alloca(value_len);
int len= json_unescape(m_table->field[2]->charset(),
@@ -1319,35 +1319,35 @@ class User_table_json: public User_table
return NULL;
return strmake_root(root, ptr, len);
}
- longlong get_int_value(const char *key, size_t klen) const
+ longlong get_int_value(const char *key) const
{
int err;
size_t value_len;
const char *value_start;
- if (get_value(key, klen, JSV_NUMBER, &value_start, &value_len))
+ if (get_value(key, JSV_NUMBER, &value_start, &value_len))
return 0;
const char *value_end= value_start + value_len;
return my_strtoll10(value_start, (char**)&value_end, &err);
}
- double get_double_value(const char *key, size_t klen) const
+ double get_double_value(const char *key) const
{
int err;
size_t value_len;
const char *value_start;
- if (get_value(key, klen, JSV_NUMBER, &value_start, &value_len))
+ if (get_value(key, JSV_NUMBER, &value_start, &value_len))
return 0;
const char *value_end= value_start + value_len;
return my_strtod(value_start, (char**)&value_end, &err);
}
- bool get_bool_value(const char *key, size_t klen) const
+ bool get_bool_value(const char *key) const
{
size_t value_len;
const char *value_start;
- if (get_value(key, klen, JSV_TRUE, &value_start, &value_len))
+ if (get_value(key, JSV_TRUE, &value_start, &value_len))
return false;
return true;
}
- bool set_value(const char *key, size_t klen,
+ bool set_value(const char *key,
const char *val, size_t vlen, bool string) const
{
int value_len;
@@ -1356,7 +1356,7 @@ class User_table_json: public User_table
String str, *res= m_table->field[2]->val_str(&str);
if (!res || !res->length())
(res= &str)->set(STRING_WITH_LEN("{}"), m_table->field[2]->charset());
- value_type= json_get_object_key(res->ptr(), res->end(), key, key+klen,
+ value_type= json_get_object_key(res->ptr(), res->end(), key,
&value_start, &value_len);
if (value_type == JSV_BAD_JSON)
return 1; // invalid
@@ -1367,7 +1367,7 @@ class User_table_json: public User_table
if (value_len)
json.append(',');
json.append('"');
- json.append(key, klen);
+ json.append(STRING_WITH_LEN(key));
json.append(STRING_WITH_LEN("\":"));
if (string)
json.append('"');
@@ -1382,7 +1382,7 @@ class User_table_json: public User_table
m_table->field[2]->store(json.ptr(), json.length(), json.charset());
return 0;
}
- bool set_str_value(const char *key, size_t klen, const char *val, size_t vlen) const
+ bool set_str_value(const char *key, const char *val, size_t vlen) const
{
char buf[JSON_SIZE];
int blen= json_escape(system_charset_info,
@@ -1391,22 +1391,22 @@ class User_table_json: public User_table
(uchar*)buf, (uchar*)buf+sizeof(buf));
if (blen < 0)
return 1;
- return set_value(key, klen, buf, blen, true);
+ return set_value(key, buf, blen, true);
}
- bool set_int_value(const char *key, size_t klen, longlong val) const
+ bool set_int_value(const char *key, longlong val) const
{
char v[MY_INT64_NUM_DECIMAL_DIGITS+1];
size_t vlen= longlong10_to_str(val, v, -10) - v;
- return set_value(key, klen, v, vlen, false);
+ return set_value(key, v, vlen, false);
}
- bool set_double_value(const char *key, size_t klen, double val) const
+ bool set_double_value(const char *key, double val) const
{
char v[FLOATING_POINT_BUFFER+1];
size_t vlen= my_fcvt(val, TIME_SECOND_PART_DIGITS, v, NULL);
- return set_value(key, klen, v, vlen, false);
+ return set_value(key, v, vlen, false);
}
- bool set_bool_value(const char *key, size_t klen, bool val) const
- { return set_value(key, klen, val ? "true" : "false", val ? 4 : 5, false); }
+ bool set_bool_value(const char *key, bool val) const
+ { return set_value(key, val ? "true" : "false", val ? 4 : 5, false); }
};
class Db_table: public Grant_table_base
diff --git a/strings/json_lib.c b/strings/json_lib.c
index e28ec3c..6c94ce2 100644
--- a/strings/json_lib.c
+++ b/strings/json_lib.c
@@ -1943,9 +1943,10 @@ enum json_types json_get_array_item(const char *js, const char *js_end,
@retval JSV_NOTHING - no such key found.
*/
enum json_types json_get_object_key(const char *js, const char *js_end,
- const char *key, const char *key_end,
+ const char *key,
const char **value, int *value_len)
{
+ const char *key_end= key + strlen(key);
json_engine_t je;
json_string_t key_name;
int n_keys= 0;
@@ -1999,10 +2000,99 @@ enum json_types json_get_object_nkey(const char *js,const char *js_end, int nkey
@retval 0 - success, json is well-formed
@retval 1 - error, json is invalid
-*/int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs)
+*/
+int json_valid(const char *js, size_t js_len, CHARSET_INFO *cs)
{
json_engine_t je;
json_scan_start(&je, cs, (const uchar *) js, (const uchar *) js + js_len);
while (json_scan_next(&je) == 0) /* no-op */ ;
return je.s.error == 0;
}
+
+
+/*
+ Expects the JSON object as an js argument, and the key name.
+ Looks for this key in the object and returns
+ the location of all the text related to it.
+ The text includes the comma, separating this key.
+
+ comma_pos - the hint where the comma is. It is important
+ if you plan to replace the key rather than just cut.
+ 1 - comma is on the left
+ 2 - comma is on the right.
+ 0 - no comma at all (the object has just this single key)
+
+ if no such key found *key_start is set to NULL.
+*/
+int json_locate_key(const char *js, const char *js_end,
+ const char *kname,
+ const char **key_start, const char **key_end,
+ int *comma_pos)
+{
+ const char *kname_end= kname + strlen(kname);
+ json_engine_t je;
+ json_string_t key_name;
+ int t_next, c_len, match_result;
+
+ json_string_set_cs(&key_name, &my_charset_utf8mb4_bin);
+
+ json_scan_start(&je, &my_charset_utf8mb4_bin,(const uchar *) js,
+ (const uchar *) js_end);
+
+ if (json_read_value(&je) ||
+ je.value_type != JSON_VALUE_OBJECT)
+ goto err_return;
+
+ *key_start= (const char *) je.s.c_str;
+ *comma_pos= 0;
+
+ while (!json_scan_next(&je))
+ {
+ switch (je.state)
+ {
+ case JST_KEY:
+ json_string_set_str(&key_name, (const uchar *) kname,
+ (const uchar *) kname_end);
+ match_result= json_key_matches(&je, &key_name);
+ if (json_skip_key(&je))
+ goto err_return;
+ get_first_nonspace(&je.s, &t_next, &c_len);
+ je.s.c_str-= c_len;
+
+ if (match_result)
+ {
+ *key_end= (const char *) je.s.c_str;
+
+ if (*comma_pos == 1)
+ return 0;
+
+ DBUG_ASSERT(*comma_pos == 0);
+
+ if (t_next == C_COMMA)
+ {
+ *key_end+= c_len;
+ *comma_pos= 2;
+ }
+ else if (t_next == C_RCURB)
+ *comma_pos= 0;
+ else
+ goto err_return;
+ return 0;
+ }
+
+ *key_start= (const char *) je.s.c_str;
+ *comma_pos= 1;
+ break;
+
+ case JST_OBJ_END:
+ *key_start= NULL;
+ return 0;
+ }
+ }
+
+err_return:
+ return 1;
+
+}
+
+
diff --git a/unittest/strings/json-t.c b/unittest/strings/json-t.c
index 8af8636..ce0f04d 100644
--- a/unittest/strings/json-t.c
+++ b/unittest/strings/json-t.c
@@ -17,21 +17,29 @@
#include <my_sys.h>
#include <json_lib.h>
+int json_locate_key(const char *js, const char *js_end, const char *kname,
+ const char **key_start, const char **key_end,
+ int *comma_pos);
int main()
{
const char *json="{\"int\":1, \"str\":\"foo bar\", "
"\"array\":[10,20,{\"c\":\"d\"}],\"bool\":false}";
const char *json_ar="[1, \"foo bar\", " "[10,20,{\"c\":\"d\"}], false]";
+ const char *json_w="{\"int\" : 1 , \"str\" : \"foo bar\" , "
+ "\"array\" : [10,20,{\"c\":\"d\"}] , \"bool\" : false }";
+ const char *json_1="{ \"str\" : \"foo bar\" }";
enum json_types value_type;
const char *value_start;
int value_len;
+ const char *key_start, *key_end;
+ int result, comma_pos;
- plan(10);
+ plan(15);
#define do_json(V) \
do { \
value_type= json_get_object_key(json, json+strlen(json), \
- V, V + (sizeof(V) - 1),&value_start, &value_len); \
+ V, &value_start, &value_len); \
ok(value_type != JSV_BAD_JSON, V); \
diag("type=%d, value=\"%.*s\"", value_type, (int)value_len, value_start); \
} while(0)
@@ -42,6 +50,16 @@ int main()
ok(value_type != JSV_BAD_JSON, #N); \
diag("type=%d, value=\"%.*s\"", value_type, (int)value_len, value_start); \
} while(0)
+#define do_json_locate(J, V) \
+ do { \
+ result= json_locate_key(J, J+strlen(J), \
+ V, &key_start, &key_end, &comma_pos); \
+ ok(result == 0, V); \
+ if (key_start) \
+ diag("key_str=\"%.*s\" comma_pos= %d", (int)(key_end - key_start), key_start, comma_pos); \
+ else \
+ diag("no key found"); \
+ } while(0)
do_json("int");
do_json("str");
@@ -54,5 +72,11 @@ int main()
do_json_ar(2);
do_json_ar(3);
do_json_ar(4);
+
+ do_json_locate(json_w, "bool");
+ do_json_locate(json_w, "int");
+ do_json_locate(json_w, "array");
+ do_json_locate(json_1, "str");
+ do_json_locate(json_w, "c");
return exit_status();
}
1
0
revision-id: 8a9532f2cc1a8eeb53ff04ca2c28b4756afc845b (mariadb-10.3.6-102-g8a9532f)
parent(s): 5c4b7e6878126cc498f87391875807c68739914f
author: Igor Babaev
committer: Igor Babaev
timestamp: 2019-01-17 11:29:13 -0800
message:
MDEV-16188: Fixed several problems and bugs.
1. Completely re-wrote the function that prunes range filter candidates.
The function now properly takes into account filter indexes that overlap.
2. Fixed bugs that calculate the cost of using filter. Ensured that the
gain promised by usage of a filter would never be greater than the cost
of accessing a table without it.
3. Fixed a bug that led to an improper detection of overlapping indexes.
4. Fixed a few other bugs.
5. Adjusted test cases and their output.
---
mysql-test/main/index_intersect.result | 2 +
mysql-test/main/index_intersect.test | 2 +
mysql-test/main/index_intersect_innodb.result | 2 +
mysql-test/main/index_merge_innodb.result | 1 +
mysql-test/main/index_merge_innodb.test | 1 +
mysql-test/main/index_merge_myisam.result | 25 +-
mysql-test/main/index_merge_myisam.test | 25 +-
mysql-test/main/join_outer_innodb.result | 8 +-
mysql-test/main/key_cache.result | 6 +-
mysql-test/main/mrr_icp_extra.result | 1 +
mysql-test/main/mrr_icp_extra.test | 1 +
mysql-test/main/null_key.result | 2 +-
mysql-test/main/order_by.result | 2 +-
mysql-test/main/partition_innodb.result | 2 +
mysql-test/main/partition_innodb.test | 2 +
mysql-test/main/range_mrr_icp.result | 21 +-
mysql-test/main/range_mrr_icp.test | 1 +
mysql-test/main/rowid_filter.result | 675 +++++++++++++++++++++++++-
mysql-test/main/rowid_filter.test | 78 +++
mysql-test/main/select.result | 13 +-
mysql-test/main/select.test | 2 +
mysql-test/main/select_jcl6.result | 13 +-
mysql-test/main/select_pkeycache.result | 13 +-
mysql-test/main/subselect2.result | 2 +-
mysql-test/main/subselect_mat_cost.result | 4 +-
mysql-test/main/subselect_mat_cost.test | 4 +
sql/handler.h | 2 +
sql/opt_range.cc | 2 +
sql/rowid_filter.cc | 269 +++++-----
sql/rowid_filter.h | 45 +-
sql/sql_select.cc | 59 ++-
sql/structs.h | 2 +-
sql/table.cc | 35 +-
sql/table.h | 21 +-
storage/innobase/handler/ha_innodb.cc | 3 +-
storage/myisam/ha_myisam.cc | 3 +-
36 files changed, 1068 insertions(+), 281 deletions(-)
diff --git a/mysql-test/main/index_intersect.result b/mysql-test/main/index_intersect.result
index 04484c7..bb2478c 100644
--- a/mysql-test/main/index_intersect.result
+++ b/mysql-test/main/index_intersect.result
@@ -38,6 +38,7 @@ SELECT COUNT(*) FROM CountryLanguage;
COUNT(*)
984
CREATE INDEX Name ON City(Name);
+SET SESSION optimizer_switch='rowid_filter=off';
SET SESSION optimizer_switch='index_merge_sort_intersection=on';
SELECT COUNT(*) FROM City;
COUNT(*)
@@ -972,3 +973,4 @@ f1 f4 f5
998 a 0
DROP TABLE t1;
SET SESSION optimizer_switch='index_merge_sort_intersection=on';
+SET SESSION optimizer_switch='rowid_filter=default';
diff --git a/mysql-test/main/index_intersect.test b/mysql-test/main/index_intersect.test
index 51a3b29..c77eccc 100644
--- a/mysql-test/main/index_intersect.test
+++ b/mysql-test/main/index_intersect.test
@@ -33,6 +33,7 @@ ANALYZE TABLE City;
--enable_result_log
--enable_query_log
+SET SESSION optimizer_switch='rowid_filter=off';
SET SESSION optimizer_switch='index_merge_sort_intersection=on';
SELECT COUNT(*) FROM City;
@@ -460,3 +461,4 @@ WHERE (f1 < 535 OR f1 > 985) AND ( f4='r' OR f4 LIKE 'a%' ) ;
DROP TABLE t1;
SET SESSION optimizer_switch='index_merge_sort_intersection=on';
+SET SESSION optimizer_switch='rowid_filter=default';
diff --git a/mysql-test/main/index_intersect_innodb.result b/mysql-test/main/index_intersect_innodb.result
index c305886..854bcd7 100644
--- a/mysql-test/main/index_intersect_innodb.result
+++ b/mysql-test/main/index_intersect_innodb.result
@@ -44,6 +44,7 @@ SELECT COUNT(*) FROM CountryLanguage;
COUNT(*)
984
CREATE INDEX Name ON City(Name);
+SET SESSION optimizer_switch='rowid_filter=off';
SET SESSION optimizer_switch='index_merge_sort_intersection=on';
SELECT COUNT(*) FROM City;
COUNT(*)
@@ -978,6 +979,7 @@ f1 f4 f5
998 a 0
DROP TABLE t1;
SET SESSION optimizer_switch='index_merge_sort_intersection=on';
+SET SESSION optimizer_switch='rowid_filter=default';
set global innodb_stats_persistent= @innodb_stats_persistent_save;
set global innodb_stats_persistent_sample_pages=
@innodb_stats_persistent_sample_pages_save;
diff --git a/mysql-test/main/index_merge_innodb.result b/mysql-test/main/index_merge_innodb.result
index 6a3ea83..26b51ba 100644
--- a/mysql-test/main/index_merge_innodb.result
+++ b/mysql-test/main/index_merge_innodb.result
@@ -1,5 +1,6 @@
set @optimizer_switch_save= @@optimizer_switch;
set optimizer_switch='index_merge_sort_intersection=off';
+set optimizer_switch='rowid_filter=off';
#---------------- Index merge test 2 -------------------------------------------
SET SESSION STORAGE_ENGINE = InnoDB;
drop table if exists t1,t2;
diff --git a/mysql-test/main/index_merge_innodb.test b/mysql-test/main/index_merge_innodb.test
index 53ce311..e8dc837 100644
--- a/mysql-test/main/index_merge_innodb.test
+++ b/mysql-test/main/index_merge_innodb.test
@@ -20,6 +20,7 @@ let $merge_table_support= 0;
set @optimizer_switch_save= @@optimizer_switch;
set optimizer_switch='index_merge_sort_intersection=off';
+set optimizer_switch='rowid_filter=off';
# The first two tests are disabled because of non deterministic explain output.
# If include/index_merge1.inc can be enabled for InnoDB and all other
diff --git a/mysql-test/main/index_merge_myisam.result b/mysql-test/main/index_merge_myisam.result
index eebdf6c..8e83bdf 100644
--- a/mysql-test/main/index_merge_myisam.result
+++ b/mysql-test/main/index_merge_myisam.result
@@ -1,4 +1,5 @@
set @optimizer_switch_save= @@optimizer_switch;
+set optimizer_switch='rowid_filter=off';
set optimizer_switch='index_merge_sort_intersection=off';
#---------------- Index merge test 1 -------------------------------------------
SET SESSION STORAGE_ENGINE = MyISAM;
@@ -1520,12 +1521,12 @@ explain select * from t1 where a=1 or b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 2 Using union(a,b); Using where
This should use ALL:
-set optimizer_switch='default,index_merge=off';
+set optimizer_switch='default,index_merge=off,rowid_filter=off';
explain select * from t1 where a=1 or b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This should use sort-union:
-set optimizer_switch='default,index_merge_union=off';
+set optimizer_switch='default,index_merge_union=off,rowid_filter=off';
explain select * from t1 where a=1 or b=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 2 Using sort_union(a,b); Using where
@@ -1535,17 +1536,17 @@ explain select * from t1 where a<1 or b <1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 38 Using sort_union(a,b); Using where
This should use ALL:
-set optimizer_switch='default,index_merge_sort_union=off';
+set optimizer_switch='default,index_merge_sort_union=off,rowid_filter=off';
explain select * from t1 where a<1 or b <1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This should use ALL:
-set optimizer_switch='default,index_merge=off';
+set optimizer_switch='default,index_merge=off,rowid_filter=off';
explain select * from t1 where a<1 or b <1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL a,b NULL NULL NULL 1000 Using where
This will use sort-union:
-set optimizer_switch='default,index_merge_union=off';
+set optimizer_switch='default,index_merge_union=off,rowid_filter=off';
explain select * from t1 where a<1 or b <1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 38 Using sort_union(a,b); Using where
@@ -1557,7 +1558,7 @@ explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c,d a,b 5,5 NULL 3 Using sort_union(a,b); Using where
And if we disable sort_union, union:
-set optimizer_switch='default,index_merge_sort_union=off';
+set optimizer_switch='default,index_merge_sort_union=off,rowid_filter=off';
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c,d c,d 5,5 NULL 100 Using union(c,d); Using where
@@ -1576,22 +1577,22 @@ explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where
No intersect when index_merge is disabled:
-set optimizer_switch='default,index_merge=off';
+set optimizer_switch='default,index_merge=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 49 Using where
No intersect if it is disabled:
-set optimizer_switch='default,index_merge_sort_intersection=off,index_merge_intersection=off';
+set optimizer_switch='default,index_merge_sort_intersection=off,index_merge_intersection=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref a,b a 5 const 49 Using where
Do intersect when union was disabled
-set optimizer_switch='default,index_merge_union=off';
+set optimizer_switch='default,index_merge_union=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where
Do intersect when sort_union was disabled
-set optimizer_switch='default,index_merge_sort_union=off';
+set optimizer_switch='default,index_merge_sort_union=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b a,b 5,5 NULL 1 Using intersect(a,b); Using where
@@ -1601,13 +1602,13 @@ explain select * from t1 where a=10 and b=10 or c=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c a,b,c 5,5,5 NULL 6 Using union(intersect(a,b),c); Using where
Should be only union left:
-set optimizer_switch='default,index_merge_intersection=off';
+set optimizer_switch='default,index_merge_intersection=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10 or c=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c a,c 5,5 NULL 54 Using union(a,c); Using where
This will switch to sort-union (intersection will be gone, too,
that's a known limitation:
-set optimizer_switch='default,index_merge_union=off';
+set optimizer_switch='default,index_merge_union=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10 or c=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge a,b,c a,c 5,5 NULL 54 Using sort_union(a,c); Using where
diff --git a/mysql-test/main/index_merge_myisam.test b/mysql-test/main/index_merge_myisam.test
index 75beb9b..c3ac7fd 100644
--- a/mysql-test/main/index_merge_myisam.test
+++ b/mysql-test/main/index_merge_myisam.test
@@ -16,6 +16,7 @@ let $merge_table_support= 1;
set @optimizer_switch_save= @@optimizer_switch;
+set optimizer_switch='rowid_filter=off';
set optimizer_switch='index_merge_sort_intersection=off';
--source include/index_merge1.inc
@@ -39,11 +40,11 @@ from t0 A, t0 B, t0 C;
explain select * from t1 where a=1 or b=1;
--echo This should use ALL:
-set optimizer_switch='default,index_merge=off';
+set optimizer_switch='default,index_merge=off,rowid_filter=off';
explain select * from t1 where a=1 or b=1;
--echo This should use sort-union:
-set optimizer_switch='default,index_merge_union=off';
+set optimizer_switch='default,index_merge_union=off,rowid_filter=off';
explain select * from t1 where a=1 or b=1;
--echo This will use sort-union:
@@ -51,16 +52,16 @@ set optimizer_switch=default;
explain select * from t1 where a<1 or b <1;
--echo This should use ALL:
-set optimizer_switch='default,index_merge_sort_union=off';
+set optimizer_switch='default,index_merge_sort_union=off,rowid_filter=off';
explain select * from t1 where a<1 or b <1;
--echo This should use ALL:
-set optimizer_switch='default,index_merge=off';
+set optimizer_switch='default,index_merge=off,rowid_filter=off';
explain select * from t1 where a<1 or b <1;
--echo This will use sort-union:
-set optimizer_switch='default,index_merge_union=off';
+set optimizer_switch='default,index_merge_union=off,rowid_filter=off';
explain select * from t1 where a<1 or b <1;
alter table t1 add d int, add key(d);
@@ -71,7 +72,7 @@ set optimizer_switch=default;
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
--echo And if we disable sort_union, union:
-set optimizer_switch='default,index_merge_sort_union=off';
+set optimizer_switch='default,index_merge_sort_union=off,rowid_filter=off';
explain select * from t1 where (a=3 or b in (1,2)) and (c=3 or d=4);
drop table t1;
@@ -92,19 +93,19 @@ set optimizer_switch=default;
explain select * from t1 where a=10 and b=10;
--echo No intersect when index_merge is disabled:
-set optimizer_switch='default,index_merge=off';
+set optimizer_switch='default,index_merge=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10;
--echo No intersect if it is disabled:
-set optimizer_switch='default,index_merge_sort_intersection=off,index_merge_intersection=off';
+set optimizer_switch='default,index_merge_sort_intersection=off,index_merge_intersection=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10;
--echo Do intersect when union was disabled
-set optimizer_switch='default,index_merge_union=off';
+set optimizer_switch='default,index_merge_union=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10;
--echo Do intersect when sort_union was disabled
-set optimizer_switch='default,index_merge_sort_union=off';
+set optimizer_switch='default,index_merge_sort_union=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10;
# Now take union-of-intersection and see how we can disable parts of it
@@ -113,12 +114,12 @@ set optimizer_switch=default;
explain select * from t1 where a=10 and b=10 or c=10;
--echo Should be only union left:
-set optimizer_switch='default,index_merge_intersection=off';
+set optimizer_switch='default,index_merge_intersection=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10 or c=10;
--echo This will switch to sort-union (intersection will be gone, too,
--echo that's a known limitation:
-set optimizer_switch='default,index_merge_union=off';
+set optimizer_switch='default,index_merge_union=off,rowid_filter=off';
explain select * from t1 where a=10 and b=10 or c=10;
set optimizer_switch=default;
diff --git a/mysql-test/main/join_outer_innodb.result b/mysql-test/main/join_outer_innodb.result
index f00a723..6f3fb09 100644
--- a/mysql-test/main/join_outer_innodb.result
+++ b/mysql-test/main/join_outer_innodb.result
@@ -444,9 +444,9 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t11 eq_ref PRIMARY PRIMARY 4 test.t1.a5 1
1 SIMPLE t12 eq_ref PRIMARY PRIMARY 4 test.t11.k3 1 Using where
1 SIMPLE l2 eq_ref PRIMARY PRIMARY 4 test.t11.k4 1 Using where
-1 SIMPLE t13 ref|filter PRIMARY,m3 PRIMARY|m3 4|4 test.t1.a1 1 (33%) Using where; Using index; Using filter
+1 SIMPLE t13 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where; Using index
1 SIMPLE l4 eq_ref PRIMARY PRIMARY 4 test.t13.m2 1 Using where; Using index
-1 SIMPLE m2 ref|filter PRIMARY,m3 PRIMARY|m3 4|4 test.t1.a1 1 (33%) Using where; Using index; Using filter
+1 SIMPLE m2 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where; Using index
1 SIMPLE l3 eq_ref PRIMARY PRIMARY 4 test.m2.m2 1 Using where
1 SIMPLE t14 eq_ref PRIMARY PRIMARY 2 test.t1.a8 1 Using where
1 SIMPLE t15 eq_ref PRIMARY PRIMARY 2 test.t1.a9 1 Using where; Using index
@@ -466,9 +466,9 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t11 eq_ref PRIMARY PRIMARY 4 test.t1.a5 1
1 SIMPLE t12 eq_ref PRIMARY PRIMARY 4 test.t11.k3 1 Using where
1 SIMPLE l2 eq_ref PRIMARY PRIMARY 4 test.t11.k4 1 Using where
-1 SIMPLE t13 ref|filter PRIMARY,m3 PRIMARY|m3 4|4 test.t1.a1 1 (33%) Using where; Using index; Using filter
+1 SIMPLE t13 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where; Using index
1 SIMPLE l4 eq_ref PRIMARY PRIMARY 4 test.t13.m2 1 Using where; Using index
-1 SIMPLE m2 ref|filter PRIMARY,m3 PRIMARY|m3 4|4 test.t1.a1 1 (33%) Using where; Using index; Using filter
+1 SIMPLE m2 ref PRIMARY,m3 PRIMARY 4 test.t1.a1 1 Using where; Using index
1 SIMPLE l3 eq_ref PRIMARY PRIMARY 4 test.m2.m2 1 Using where
1 SIMPLE t14 eq_ref PRIMARY PRIMARY 2 test.t1.a8 1 Using where
1 SIMPLE t15 eq_ref PRIMARY PRIMARY 2 test.t1.a9 1 Using where; Using index
diff --git a/mysql-test/main/key_cache.result b/mysql-test/main/key_cache.result
index 36c75ad..b3368b2 100644
--- a/mysql-test/main/key_cache.result
+++ b/mysql-test/main/key_cache.result
@@ -739,13 +739,13 @@ p
1019
explain select i from t2 where a='yyyy' and i=3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref k1,k2 k1 5 const 189 Using where
+1 SIMPLE t2 ref|filter k1,k2 k1|k2 5|11 const 189 (27%) Using where; Using filter
select i from t2 where a='yyyy' and i=3;
i
3
explain select a from t2 where a='yyyy' and i=3;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ref k1,k2 k1 5 const 189 Using where
+1 SIMPLE t2 ref|filter k1,k2 k1|k2 5|11 const 189 (27%) Using where; Using filter
select a from t2 where a='yyyy' and i=3 ;
a
yyyy
@@ -753,7 +753,7 @@ select * from information_schema.key_caches where segment_number is null;
KEY_CACHE_NAME SEGMENTS SEGMENT_NUMBER FULL_SIZE BLOCK_SIZE USED_BLOCKS UNUSED_BLOCKS DIRTY_BLOCKS READ_REQUESTS READS WRITE_REQUESTS WRITES
default 2 NULL 32768 1024 # # 0 3178 24 1552 18
small NULL NULL 1048576 1024 # # 0 0 0 0 0
-keycache1 7 NULL 262143 2048 # # 0 3231 43 1594 30
+keycache1 7 NULL 262143 2048 # # 0 3283 43 1594 30
keycache2 NULL NULL 1048576 1024 # # 0 6 6 3 3
set global keycache1.key_cache_block_size=2*1024;
insert into t2 values (7000, 3, 'yyyy');
diff --git a/mysql-test/main/mrr_icp_extra.result b/mysql-test/main/mrr_icp_extra.result
index 6943f12..49acd7b 100644
--- a/mysql-test/main/mrr_icp_extra.result
+++ b/mysql-test/main/mrr_icp_extra.result
@@ -1,6 +1,7 @@
call mtr.add_suppression("Can't find record in .*");
set @mrr_icp_extra_tmp=@@optimizer_switch;
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
+set optimizer_switch='rowid_filter=off';
SET NAMES latin1;
CREATE TABLE t1
(s1 char(10) COLLATE latin1_german1_ci,
diff --git a/mysql-test/main/mrr_icp_extra.test b/mysql-test/main/mrr_icp_extra.test
index 75ddc85..38306f5 100644
--- a/mysql-test/main/mrr_icp_extra.test
+++ b/mysql-test/main/mrr_icp_extra.test
@@ -4,6 +4,7 @@ call mtr.add_suppression("Can't find record in .*");
set @mrr_icp_extra_tmp=@@optimizer_switch;
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
+set optimizer_switch='rowid_filter=off';
SET NAMES latin1;
CREATE TABLE t1
(s1 char(10) COLLATE latin1_german1_ci,
diff --git a/mysql-test/main/null_key.result b/mysql-test/main/null_key.result
index afb9b42..525a121 100644
--- a/mysql-test/main/null_key.result
+++ b/mysql-test/main/null_key.result
@@ -181,7 +181,7 @@ insert into t2 values (7),(8);
explain select * from t2 straight_join t1 where t1.a=t2.a and b is null;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where
-1 SIMPLE t1 ref|filter a,b a|b 10|5 test.t2.a,const 2 (13%) Using where; Using index; Using filter
+1 SIMPLE t1 ref a,b a 10 test.t2.a,const 2 Using where; Using index
drop index b on t1;
explain select * from t2,t1 where t1.a=t2.a and b is null;
id select_type table type possible_keys key key_len ref rows Extra
diff --git a/mysql-test/main/order_by.result b/mysql-test/main/order_by.result
index 17c5a94..6e1518f 100644
--- a/mysql-test/main/order_by.result
+++ b/mysql-test/main/order_by.result
@@ -1577,7 +1577,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 t1 ref a,b b 4 const 4 Using index condition; Using where; Using temporary; Using filesort
-1 SIMPLE t2 ref|filter a,b,c a|b 40|5 test.t1.a,const 11 (26%) Using index condition; Using filter
+1 SIMPLE t2 ref a,b,c a 40 test.t1.a,const 11 Using index condition
SELECT d FROM t1, 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/partition_innodb.result b/mysql-test/main/partition_innodb.result
index 151218f..46353c6 100644
--- a/mysql-test/main/partition_innodb.result
+++ b/mysql-test/main/partition_innodb.result
@@ -704,9 +704,11 @@ insert into t1 select 10+A.a + 10*B.a + 100*C.a + 1000*D.a,
10+A.a + 10*B.a + 100*C.a + 1000*D.a,
2000 + A.a + 10*B.a + 100*C.a + 1000*D.a
from t2 A, t2 B, t2 C ,t2 D;
+set statement optimizer_switch='rowid_filter=off' for
explain select * from t1 where a=1 and b=2 and pk between 1 and 999999 ;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,a,b b,a 4,4 NULL # Using intersect(b,a); Using where; Using index
+set statement optimizer_switch='rowid_filter=off' for
create temporary table t3 as
select * from t1 where a=1 and b=2 and pk between 1 and 999 ;
select count(*) from t3;
diff --git a/mysql-test/main/partition_innodb.test b/mysql-test/main/partition_innodb.test
index bc1b323..a8bbb7c 100644
--- a/mysql-test/main/partition_innodb.test
+++ b/mysql-test/main/partition_innodb.test
@@ -782,8 +782,10 @@ insert into t1 select 10+A.a + 10*B.a + 100*C.a + 1000*D.a,
# This should show index_merge, using intersect
--replace_column 9 #
+set statement optimizer_switch='rowid_filter=off' for
explain select * from t1 where a=1 and b=2 and pk between 1 and 999999 ;
# 794 rows in output
+set statement optimizer_switch='rowid_filter=off' for
create temporary table t3 as
select * from t1 where a=1 and b=2 and pk between 1 and 999 ;
select count(*) from t3;
diff --git a/mysql-test/main/range_mrr_icp.result b/mysql-test/main/range_mrr_icp.result
index a39237b..91fd84a 100644
--- a/mysql-test/main/range_mrr_icp.result
+++ b/mysql-test/main/range_mrr_icp.result
@@ -1,5 +1,6 @@
set @mrr_icp_extra_tmp=@@optimizer_switch;
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
+set optimizer_switch='rowid_filter=off';
set @innodb_stats_persistent_save= @@innodb_stats_persistent;
set @innodb_stats_persistent_sample_pages_save=
@@innodb_stats_persistent_sample_pages;
@@ -2592,7 +2593,7 @@ explain select * from t1,t2
where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range idx idx 5 NULL 6 Using index condition; Rowid-ordered scan
-1 SIMPLE t2 ref|filter idx1,idx2 idx1|idx2 5|5 test.t1.a 12 (14%) Using where; Using filter
+1 SIMPLE t2 ref idx1,idx2 idx1 5 test.t1.a 12 Using where
explain format=json select * from t1,t2
where a = d and (a,e) in ((3,3),(7,7),(8,8)) and length(f) = 1;
EXPLAIN
@@ -2619,14 +2620,6 @@ EXPLAIN
"key_length": "5",
"used_key_parts": ["d"],
"ref": ["test.t1.a"],
- "rowid_filter": {
- "range": {
- "key": "idx2",
- "used_key_parts": ["e"]
- },
- "rows": 15,
- "selectivity_pct": 14.423
- },
"rows": 12,
"filtered": 100,
"attached_condition": "(t1.a,t2.e) in (<cache>((3,3)),<cache>((7,7)),<cache>((8,8))) and octet_length(t2.f) = 1"
@@ -2697,7 +2690,7 @@ insert into t1 select * from t1;
explain select * from t1,t2
where a = d and (a,e) in ((4,4),(7,7),(8,8)) and length(f) = 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range|filter idx1,idx2 idx1|idx2 5|5 NULL 7 (7%) Using index condition; Using where; Rowid-ordered scan; Using filter
+1 SIMPLE t2 range idx1,idx2 idx1 5 NULL 7 Using index condition; Using where; Rowid-ordered scan
1 SIMPLE t1 ref idx idx 5 test.t2.d 11
explain format=json select * from t1,t2
where a = d and (a,e) in ((4,4),(7,7),(8,8)) and length(f) = 1;
@@ -2712,14 +2705,6 @@ EXPLAIN
"key": "idx1",
"key_length": "5",
"used_key_parts": ["d"],
- "rowid_filter": {
- "range": {
- "key": "idx2",
- "used_key_parts": ["e"]
- },
- "rows": 7,
- "selectivity_pct": 6.7308
- },
"rows": 7,
"filtered": 100,
"index_condition": "t2.d is not null",
diff --git a/mysql-test/main/range_mrr_icp.test b/mysql-test/main/range_mrr_icp.test
index 29e7af3..4c6983c 100644
--- a/mysql-test/main/range_mrr_icp.test
+++ b/mysql-test/main/range_mrr_icp.test
@@ -1,5 +1,6 @@
set @mrr_icp_extra_tmp=@@optimizer_switch;
set optimizer_switch='mrr=on,mrr_sort_keys=on,index_condition_pushdown=on';
+set optimizer_switch='rowid_filter=off';
--source range.test
diff --git a/mysql-test/main/rowid_filter.result b/mysql-test/main/rowid_filter.result
index eb20ad1..8d224ee 100644
--- a/mysql-test/main/rowid_filter.result
+++ b/mysql-test/main/rowid_filter.result
@@ -1,13 +1,678 @@
DROP DATABASE IF EXISTS dbt3_s001;
CREATE DATABASE dbt3_s001;
use dbt3_s001;
+CREATE INDEX i_l_quantity ON lineitem(l_quantity);
+CREATE INDEX i_o_totalprice ON orders(o_totalprice);
+ANALYZE TABLE lineitem, orders;
+Table Op Msg_type Msg_text
+dbt3_s001.lineitem analyze status Table is already up to date
+dbt3_s001.orders analyze status Table is already up to date
+set optimizer_use_condition_selectivity=2;
+set statement optimizer_switch='rowid_filter=on' for EXPLAIN SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE lineitem range|filter i_l_shipdate,i_l_quantity i_l_shipdate|i_l_quantity 4|9 NULL 509 (11%) Using index condition; Using where; Using filter
+set statement optimizer_switch='rowid_filter=on' for EXPLAIN FORMAT=JSON SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "lineitem",
+ "access_type": "range",
+ "possible_keys": ["i_l_shipdate", "i_l_quantity"],
+ "key": "i_l_shipdate",
+ "key_length": "4",
+ "used_key_parts": ["l_shipDATE"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_l_quantity",
+ "used_key_parts": ["l_quantity"]
+ },
+ "rows": 662,
+ "selectivity_pct": 11.024
+ },
+ "rows": 509,
+ "filtered": 11.024,
+ "index_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30'",
+ "attached_condition": "lineitem.l_quantity > 45"
+ }
+ }
+}
+set statement optimizer_switch='rowid_filter=on' for SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45;
+l_orderkey l_linenumber l_shipdate l_quantity
+1121 5 1997-04-27 47
+1121 6 1997-04-21 50
+1441 7 1997-06-07 50
+1443 1 1997-02-05 47
+1473 1 1997-05-05 50
+1568 2 1997-04-06 46
+1632 1 1997-01-25 47
+1632 3 1997-01-29 47
+1954 7 1997-06-04 49
+1959 1 1997-05-05 46
+2151 3 1997-01-20 49
+2177 5 1997-05-10 46
+2369 2 1997-01-02 47
+2469 3 1997-01-11 48
+2469 6 1997-03-03 49
+2470 2 1997-06-02 50
+260 1 1997-03-24 50
+288 2 1997-04-19 49
+289 4 1997-03-14 48
+3009 1 1997-03-19 48
+3105 3 1997-02-28 48
+3106 2 1997-02-27 49
+3429 1 1997-04-08 48
+3490 2 1997-06-27 50
+3619 1 1997-01-22 49
+3619 3 1997-01-31 46
+3969 3 1997-05-29 46
+4005 4 1997-01-31 49
+4036 1 1997-06-21 46
+4066 4 1997-02-17 49
+4098 1 1997-01-26 46
+422 3 1997-06-21 46
+4258 3 1997-01-02 46
+4421 2 1997-04-21 46
+4421 3 1997-05-25 46
+4453 3 1997-05-29 48
+4484 7 1997-03-17 50
+4609 3 1997-02-11 46
+484 1 1997-03-06 49
+484 3 1997-01-24 50
+484 5 1997-03-05 48
+485 1 1997-03-28 50
+4868 1 1997-04-29 47
+4868 3 1997-04-23 49
+4934 1 1997-05-20 48
+4967 1 1997-05-27 50
+5090 2 1997-04-05 46
+5152 2 1997-03-10 50
+5158 4 1997-04-10 49
+5606 3 1997-03-11 46
+5606 7 1997-02-01 46
+5762 4 1997-03-02 47
+581 3 1997-02-27 49
+5829 5 1997-01-31 49
+5831 4 1997-02-24 46
+5895 2 1997-04-27 47
+5895 3 1997-03-15 49
+5952 1 1997-06-30 49
+705 1 1997-04-18 46
+836 3 1997-03-21 46
+set statement optimizer_switch='rowid_filter=off' for EXPLAIN SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE lineitem range i_l_shipdate,i_l_quantity i_l_shipdate 4 NULL 509 Using index condition; Using where
+set statement optimizer_switch='rowid_filter=off' for EXPLAIN FORMAT=JSON SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "lineitem",
+ "access_type": "range",
+ "possible_keys": ["i_l_shipdate", "i_l_quantity"],
+ "key": "i_l_shipdate",
+ "key_length": "4",
+ "used_key_parts": ["l_shipDATE"],
+ "rows": 509,
+ "filtered": 11.024,
+ "index_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30'",
+ "attached_condition": "lineitem.l_quantity > 45"
+ }
+ }
+}
+set statement optimizer_switch='rowid_filter=off' for SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45;
+l_orderkey l_linenumber l_shipdate l_quantity
+1121 5 1997-04-27 47
+1121 6 1997-04-21 50
+1441 7 1997-06-07 50
+1443 1 1997-02-05 47
+1473 1 1997-05-05 50
+1568 2 1997-04-06 46
+1632 1 1997-01-25 47
+1632 3 1997-01-29 47
+1954 7 1997-06-04 49
+1959 1 1997-05-05 46
+2151 3 1997-01-20 49
+2177 5 1997-05-10 46
+2369 2 1997-01-02 47
+2469 3 1997-01-11 48
+2469 6 1997-03-03 49
+2470 2 1997-06-02 50
+260 1 1997-03-24 50
+288 2 1997-04-19 49
+289 4 1997-03-14 48
+3009 1 1997-03-19 48
+3105 3 1997-02-28 48
+3106 2 1997-02-27 49
+3429 1 1997-04-08 48
+3490 2 1997-06-27 50
+3619 1 1997-01-22 49
+3619 3 1997-01-31 46
+3969 3 1997-05-29 46
+4005 4 1997-01-31 49
+4036 1 1997-06-21 46
+4066 4 1997-02-17 49
+4098 1 1997-01-26 46
+422 3 1997-06-21 46
+4258 3 1997-01-02 46
+4421 2 1997-04-21 46
+4421 3 1997-05-25 46
+4453 3 1997-05-29 48
+4484 7 1997-03-17 50
+4609 3 1997-02-11 46
+484 1 1997-03-06 49
+484 3 1997-01-24 50
+484 5 1997-03-05 48
+485 1 1997-03-28 50
+4868 1 1997-04-29 47
+4868 3 1997-04-23 49
+4934 1 1997-05-20 48
+4967 1 1997-05-27 50
+5090 2 1997-04-05 46
+5152 2 1997-03-10 50
+5158 4 1997-04-10 49
+5606 3 1997-03-11 46
+5606 7 1997-02-01 46
+5762 4 1997-03-02 47
+581 3 1997-02-27 49
+5829 5 1997-01-31 49
+5831 4 1997-02-24 46
+5895 2 1997-04-27 47
+5895 3 1997-03-15 49
+5952 1 1997-06-30 49
+705 1 1997-04-18 46
+836 3 1997-03-21 46
+set statement optimizer_switch='rowid_filter=on' for EXPLAIN SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-01-31' AND
+o_totalprice between 200000 and 230000;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE lineitem range PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 NULL 98 Using index condition
+1 SIMPLE orders eq_ref|filter PRIMARY,i_o_totalprice PRIMARY|i_o_totalprice 4|9 dbt3_s001.lineitem.l_orderkey 1 (5%) Using where; Using filter
+set statement optimizer_switch='rowid_filter=on' for EXPLAIN FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-01-31' AND
+o_totalprice between 200000 and 230000;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "lineitem",
+ "access_type": "range",
+ "possible_keys": [
+ "PRIMARY",
+ "i_l_shipdate",
+ "i_l_orderkey",
+ "i_l_orderkey_quantity"
+ ],
+ "key": "i_l_shipdate",
+ "key_length": "4",
+ "used_key_parts": ["l_shipDATE"],
+ "rows": 98,
+ "filtered": 100,
+ "index_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-01-31'"
+ },
+ "table": {
+ "table_name": "orders",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_o_totalprice"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["o_orderkey"],
+ "ref": ["dbt3_s001.lineitem.l_orderkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_totalprice",
+ "used_key_parts": ["o_totalprice"]
+ },
+ "rows": 81,
+ "selectivity_pct": 5.4
+ },
+ "rows": 1,
+ "filtered": 5.4,
+ "attached_condition": "orders.o_totalprice between 200000 and 230000"
+ }
+ }
+}
+set statement optimizer_switch='rowid_filter=on' for SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-01-31' AND
+o_totalprice between 200000 and 230000;
+o_orderkey l_linenumber l_shipdate o_totalprice
+1156 3 1997-01-24 217682.81
+1156 4 1997-01-18 217682.81
+1156 6 1997-01-27 217682.81
+1156 7 1997-01-01 217682.81
+2180 2 1997-01-03 208481.57
+2180 3 1997-01-03 208481.57
+3619 1 1997-01-22 222274.54
+3619 3 1997-01-31 222274.54
+3619 6 1997-01-25 222274.54
+484 3 1997-01-24 219920.62
+5606 6 1997-01-11 219959.08
+set statement optimizer_switch='rowid_filter=off' for EXPLAIN SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-01-31' AND
+o_totalprice between 200000 and 230000;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE lineitem range PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity i_l_shipdate 4 NULL 98 Using index condition
+1 SIMPLE orders eq_ref PRIMARY,i_o_totalprice PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1 Using where
+set statement optimizer_switch='rowid_filter=off' for EXPLAIN FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-01-31' AND
+o_totalprice between 200000 and 230000;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "lineitem",
+ "access_type": "range",
+ "possible_keys": [
+ "PRIMARY",
+ "i_l_shipdate",
+ "i_l_orderkey",
+ "i_l_orderkey_quantity"
+ ],
+ "key": "i_l_shipdate",
+ "key_length": "4",
+ "used_key_parts": ["l_shipDATE"],
+ "rows": 98,
+ "filtered": 100,
+ "index_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-01-31'"
+ },
+ "table": {
+ "table_name": "orders",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_o_totalprice"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["o_orderkey"],
+ "ref": ["dbt3_s001.lineitem.l_orderkey"],
+ "rows": 1,
+ "filtered": 5.4,
+ "attached_condition": "orders.o_totalprice between 200000 and 230000"
+ }
+ }
+}
+set statement optimizer_switch='rowid_filter=off' for SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-01-31' AND
+o_totalprice between 200000 and 230000;
+o_orderkey l_linenumber l_shipdate o_totalprice
+1156 3 1997-01-24 217682.81
+1156 4 1997-01-18 217682.81
+1156 6 1997-01-27 217682.81
+1156 7 1997-01-01 217682.81
+2180 2 1997-01-03 208481.57
+2180 3 1997-01-03 208481.57
+3619 1 1997-01-22 222274.54
+3619 3 1997-01-31 222274.54
+3619 6 1997-01-25 222274.54
+484 3 1997-01-24 219920.62
+5606 6 1997-01-11 219959.08
+set statement optimizer_switch='rowid_filter=on' for EXPLAIN SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45 AND
+o_totalprice between 180000 and 230000;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity,i_l_quantity i_l_shipdate|i_l_quantity 4|9 NULL 509 (11%) Using index condition; Using where; Using filter
+1 SIMPLE orders eq_ref|filter PRIMARY,i_o_totalprice PRIMARY|i_o_totalprice 4|9 dbt3_s001.lineitem.l_orderkey 1 (10%) Using where; Using filter
+set statement optimizer_switch='rowid_filter=on' for EXPLAIN FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45 AND
+o_totalprice between 180000 and 230000;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "lineitem",
+ "access_type": "range",
+ "possible_keys": [
+ "PRIMARY",
+ "i_l_shipdate",
+ "i_l_orderkey",
+ "i_l_orderkey_quantity",
+ "i_l_quantity"
+ ],
+ "key": "i_l_shipdate",
+ "key_length": "4",
+ "used_key_parts": ["l_shipDATE"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_l_quantity",
+ "used_key_parts": ["l_quantity"]
+ },
+ "rows": 662,
+ "selectivity_pct": 11.024
+ },
+ "rows": 509,
+ "filtered": 11.024,
+ "index_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30'",
+ "attached_condition": "lineitem.l_quantity > 45"
+ },
+ "table": {
+ "table_name": "orders",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_o_totalprice"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["o_orderkey"],
+ "ref": ["dbt3_s001.lineitem.l_orderkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_o_totalprice",
+ "used_key_parts": ["o_totalprice"]
+ },
+ "rows": 152,
+ "selectivity_pct": 10.133
+ },
+ "rows": 1,
+ "filtered": 10.133,
+ "attached_condition": "orders.o_totalprice between 180000 and 230000"
+ }
+ }
+}
+set statement optimizer_switch='rowid_filter=on' for SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45 AND
+o_totalprice between 180000 and 230000;
+o_orderkey l_linenumber l_shipdate l_quantity o_totalprice
+1632 1 1997-01-25 47 183286.33
+1632 3 1997-01-29 47 183286.33
+2177 5 1997-05-10 46 183493.42
+2469 3 1997-01-11 48 192074.23
+2469 6 1997-03-03 49 192074.23
+3619 1 1997-01-22 49 222274.54
+3619 3 1997-01-31 46 222274.54
+484 1 1997-03-06 49 219920.62
+484 3 1997-01-24 50 219920.62
+484 5 1997-03-05 48 219920.62
+4934 1 1997-05-20 48 180478.16
+5606 3 1997-03-11 46 219959.08
+5606 7 1997-02-01 46 219959.08
+5829 5 1997-01-31 49 183734.56
+5895 2 1997-04-27 47 201419.83
+5895 3 1997-03-15 49 201419.83
+set statement optimizer_switch='rowid_filter=off' for EXPLAIN SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45 AND
+o_totalprice between 180000 and 230000;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE lineitem range PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity,i_l_quantity i_l_shipdate 4 NULL 509 Using index condition; Using where
+1 SIMPLE orders eq_ref PRIMARY,i_o_totalprice PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1 Using where
+set statement optimizer_switch='rowid_filter=off' for EXPLAIN FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45 AND
+o_totalprice between 180000 and 230000;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "lineitem",
+ "access_type": "range",
+ "possible_keys": [
+ "PRIMARY",
+ "i_l_shipdate",
+ "i_l_orderkey",
+ "i_l_orderkey_quantity",
+ "i_l_quantity"
+ ],
+ "key": "i_l_shipdate",
+ "key_length": "4",
+ "used_key_parts": ["l_shipDATE"],
+ "rows": 509,
+ "filtered": 11.024,
+ "index_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30'",
+ "attached_condition": "lineitem.l_quantity > 45"
+ },
+ "table": {
+ "table_name": "orders",
+ "access_type": "eq_ref",
+ "possible_keys": ["PRIMARY", "i_o_totalprice"],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["o_orderkey"],
+ "ref": ["dbt3_s001.lineitem.l_orderkey"],
+ "rows": 1,
+ "filtered": 10.133,
+ "attached_condition": "orders.o_totalprice between 180000 and 230000"
+ }
+ }
+}
+set statement optimizer_switch='rowid_filter=off' for SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+l_quantity > 45 AND
+o_totalprice between 180000 and 230000;
+o_orderkey l_linenumber l_shipdate l_quantity o_totalprice
+1632 1 1997-01-25 47 183286.33
+1632 3 1997-01-29 47 183286.33
+2177 5 1997-05-10 46 183493.42
+2469 3 1997-01-11 48 192074.23
+2469 6 1997-03-03 49 192074.23
+3619 1 1997-01-22 49 222274.54
+3619 3 1997-01-31 46 222274.54
+484 1 1997-03-06 49 219920.62
+484 3 1997-01-24 50 219920.62
+484 5 1997-03-05 48 219920.62
+4934 1 1997-05-20 48 180478.16
+5606 3 1997-03-11 46 219959.08
+5606 7 1997-02-01 46 219959.08
+5829 5 1997-01-31 49 183734.56
+5895 2 1997-04-27 47 201419.83
+5895 3 1997-03-15 49 201419.83
+set statement optimizer_switch='rowid_filter=on' for EXPLAIN SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+o_totalprice between 200000 and 230000;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE orders range PRIMARY,i_o_totalprice i_o_totalprice 9 NULL 81 Using index condition
+1 SIMPLE lineitem ref|filter PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY|i_l_shipdate 4|4 dbt3_s001.orders.o_orderkey 4 (8%) Using where; Using filter
+set statement optimizer_switch='rowid_filter=on' for EXPLAIN FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+o_totalprice between 200000 and 230000;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["PRIMARY", "i_o_totalprice"],
+ "key": "i_o_totalprice",
+ "key_length": "9",
+ "used_key_parts": ["o_totalprice"],
+ "rows": 81,
+ "filtered": 100,
+ "index_condition": "orders.o_totalprice between 200000 and 230000"
+ },
+ "table": {
+ "table_name": "lineitem",
+ "access_type": "ref",
+ "possible_keys": [
+ "PRIMARY",
+ "i_l_shipdate",
+ "i_l_orderkey",
+ "i_l_orderkey_quantity"
+ ],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["l_orderkey"],
+ "ref": ["dbt3_s001.orders.o_orderkey"],
+ "rowid_filter": {
+ "range": {
+ "key": "i_l_shipdate",
+ "used_key_parts": ["l_shipDATE"]
+ },
+ "rows": 509,
+ "selectivity_pct": 8.4763
+ },
+ "rows": 4,
+ "filtered": 8.4763,
+ "attached_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30'"
+ }
+ }
+}
+set statement optimizer_switch='rowid_filter=on' for SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+o_totalprice between 200000 and 230000;
+o_orderkey l_linenumber l_shipdate o_totalprice
+1156 3 1997-01-24 217682.81
+1156 4 1997-01-18 217682.81
+1156 6 1997-01-27 217682.81
+1156 7 1997-01-01 217682.81
+1890 1 1997-04-02 202364.58
+1890 3 1997-02-09 202364.58
+1890 4 1997-04-08 202364.58
+1890 5 1997-04-15 202364.58
+1890 6 1997-02-13 202364.58
+2180 2 1997-01-03 208481.57
+2180 3 1997-01-03 208481.57
+3619 1 1997-01-22 222274.54
+3619 3 1997-01-31 222274.54
+3619 4 1997-03-18 222274.54
+3619 6 1997-01-25 222274.54
+453 1 1997-06-30 216826.73
+453 2 1997-06-30 216826.73
+484 1 1997-03-06 219920.62
+484 2 1997-04-09 219920.62
+484 3 1997-01-24 219920.62
+484 4 1997-04-29 219920.62
+484 5 1997-03-05 219920.62
+484 6 1997-04-06 219920.62
+5606 2 1997-02-23 219959.08
+5606 3 1997-03-11 219959.08
+5606 4 1997-02-06 219959.08
+5606 6 1997-01-11 219959.08
+5606 7 1997-02-01 219959.08
+5859 2 1997-05-15 210643.96
+5859 5 1997-05-28 210643.96
+5859 6 1997-06-15 210643.96
+5895 1 1997-04-05 201419.83
+5895 2 1997-04-27 201419.83
+5895 3 1997-03-15 201419.83
+5895 4 1997-03-03 201419.83
+5895 5 1997-04-30 201419.83
+5895 6 1997-04-19 201419.83
+set statement optimizer_switch='rowid_filter=off' for EXPLAIN SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+o_totalprice between 200000 and 230000;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE orders range PRIMARY,i_o_totalprice i_o_totalprice 9 NULL 81 Using index condition
+1 SIMPLE lineitem ref PRIMARY,i_l_shipdate,i_l_orderkey,i_l_orderkey_quantity PRIMARY 4 dbt3_s001.orders.o_orderkey 4 Using where
+set statement optimizer_switch='rowid_filter=off' for EXPLAIN FORMAT=JSON SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+o_totalprice between 200000 and 230000;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "orders",
+ "access_type": "range",
+ "possible_keys": ["PRIMARY", "i_o_totalprice"],
+ "key": "i_o_totalprice",
+ "key_length": "9",
+ "used_key_parts": ["o_totalprice"],
+ "rows": 81,
+ "filtered": 100,
+ "index_condition": "orders.o_totalprice between 200000 and 230000"
+ },
+ "table": {
+ "table_name": "lineitem",
+ "access_type": "ref",
+ "possible_keys": [
+ "PRIMARY",
+ "i_l_shipdate",
+ "i_l_orderkey",
+ "i_l_orderkey_quantity"
+ ],
+ "key": "PRIMARY",
+ "key_length": "4",
+ "used_key_parts": ["l_orderkey"],
+ "ref": ["dbt3_s001.orders.o_orderkey"],
+ "rows": 4,
+ "filtered": 8.4763,
+ "attached_condition": "lineitem.l_shipDATE between '1997-01-01' and '1997-06-30'"
+ }
+ }
+}
+set statement optimizer_switch='rowid_filter=off' for SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+o_totalprice between 200000 and 230000;
+o_orderkey l_linenumber l_shipdate o_totalprice
+1156 3 1997-01-24 217682.81
+1156 4 1997-01-18 217682.81
+1156 6 1997-01-27 217682.81
+1156 7 1997-01-01 217682.81
+1890 1 1997-04-02 202364.58
+1890 3 1997-02-09 202364.58
+1890 4 1997-04-08 202364.58
+1890 5 1997-04-15 202364.58
+1890 6 1997-02-13 202364.58
+2180 2 1997-01-03 208481.57
+2180 3 1997-01-03 208481.57
+3619 1 1997-01-22 222274.54
+3619 3 1997-01-31 222274.54
+3619 4 1997-03-18 222274.54
+3619 6 1997-01-25 222274.54
+453 1 1997-06-30 216826.73
+453 2 1997-06-30 216826.73
+484 1 1997-03-06 219920.62
+484 2 1997-04-09 219920.62
+484 3 1997-01-24 219920.62
+484 4 1997-04-29 219920.62
+484 5 1997-03-05 219920.62
+484 6 1997-04-06 219920.62
+5606 2 1997-02-23 219959.08
+5606 3 1997-03-11 219959.08
+5606 4 1997-02-06 219959.08
+5606 6 1997-01-11 219959.08
+5606 7 1997-02-01 219959.08
+5859 2 1997-05-15 210643.96
+5859 5 1997-05-28 210643.96
+5859 6 1997-06-15 210643.96
+5895 1 1997-04-05 201419.83
+5895 2 1997-04-27 201419.83
+5895 3 1997-03-15 201419.83
+5895 4 1997-03-03 201419.83
+5895 5 1997-04-30 201419.83
+5895 6 1997-04-19 201419.83
# lineitem : {i_l_receiptdate, i_l_shipdate} -> i_l_receiptdate
EXPLAIN SELECT *
FROM orders JOIN lineitem ON o_orderkey=l_orderkey
WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-02-01' AND
l_receiptdate BETWEEN '1997-01-10' AND '1997-01-25';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity i_l_receiptdate|i_l_shipdate 4|4 NULL 60 (1%) Using index condition; Using where; Using filter
+1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity i_l_receiptdate|i_l_shipdate 4|4 NULL 53 (2%) Using index condition; Using where; Using filter
1 SIMPLE orders eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1
# lineitem : {i_l_receiptdate, i_l_shipdate} -> i_l_receiptdate
# orders : {i_o_orderdate} -> i_o_orderdate
@@ -17,7 +682,7 @@ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-02-01' AND
l_receiptdate BETWEEN '1997-01-10' AND '1997-01-25' AND
o_orderdate > '1997-01-15';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity i_l_receiptdate|i_l_shipdate 4|4 NULL 60 (1%) Using index condition; Using where; Using filter
+1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity i_l_receiptdate|i_l_shipdate 4|4 NULL 53 (2%) Using index condition; Using where; Using filter
1 SIMPLE orders eq_ref PRIMARY,i_o_orderdate PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1 Using where
# lineitem : {i_l_receiptdate, i_l_shipdate,
# i_l_commitdate} -> i_l_receiptdate
@@ -27,7 +692,7 @@ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-02-01' AND
l_receiptdate BETWEEN '1997-01-10' AND '1997-01-25' AND
l_commitdate BETWEEN '1997-01-05' AND '1997-01-25';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity,i_l_commitdate i_l_receiptdate|i_l_commitdate 4|4 NULL 60 (1%) Using index condition; Using where; Using filter
+1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity,i_l_commitdate i_l_receiptdate|i_l_commitdate 4|4 NULL 53 (1%) Using index condition; Using where; Using filter
1 SIMPLE orders eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1
# lineitem : {i_l_receiptdate, i_l_shipdate,
# i_l_commitdate} -> i_l_commitdate
@@ -37,7 +702,7 @@ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-02-01' AND
l_receiptdate BETWEEN '1997-01-01' AND '1997-01-25' AND
l_commitdate BETWEEN '1997-01-15' AND '1997-01-25';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity,i_l_commitdate i_l_commitdate|i_l_shipdate 4|4 NULL 35 (1%) Using index condition; Using where; Using filter
+1 SIMPLE lineitem range|filter PRIMARY,i_l_shipdate,i_l_receiptdate,i_l_orderkey,i_l_orderkey_quantity,i_l_commitdate i_l_commitdate|i_l_receiptdate 4|4 NULL 28 (1%) Using index condition; Using where; Using filter
1 SIMPLE orders eq_ref PRIMARY PRIMARY 4 dbt3_s001.lineitem.l_orderkey 1
CREATE INDEX i_l_extendedprice ON lineitem(l_extendedprice);
# lineitem : {i_l_receiptdate, i_l_shipdate, i_l_commitdate,
@@ -179,7 +844,7 @@ EXPLAIN
"selectivity_pct": 0.1332
},
"rows": 6,
- "filtered": 100,
+ "filtered": 0.1332,
"index_condition": "lineitem.l_receiptDATE between '1997-01-09' and '1997-01-10'",
"attached_condition": "lineitem.l_shipDATE between '1997-01-09' and '1997-01-10'"
},
diff --git a/mysql-test/main/rowid_filter.test b/mysql-test/main/rowid_filter.test
index 73d7326..274fab6 100644
--- a/mysql-test/main/rowid_filter.test
+++ b/mysql-test/main/rowid_filter.test
@@ -14,6 +14,84 @@ use dbt3_s001;
--enable_result_log
--enable_query_log
+CREATE INDEX i_l_quantity ON lineitem(l_quantity);
+
+CREATE INDEX i_o_totalprice ON orders(o_totalprice);
+
+ANALYZE TABLE lineitem, orders;
+
+set optimizer_use_condition_selectivity=2;
+
+let $with_filter=
+set statement optimizer_switch='rowid_filter=on' for;
+
+let $without_filter=
+set statement optimizer_switch='rowid_filter=off' for;
+
+let $q1=
+SELECT l_orderkey, l_linenumber, l_shipdate, l_quantity FROM lineitem
+ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+ l_quantity > 45;
+
+eval $with_filter EXPLAIN $q1;
+eval $with_filter EXPLAIN FORMAT=JSON $q1;
+--sorted_result
+eval $with_filter $q1;
+
+eval $without_filter EXPLAIN $q1;
+eval $without_filter EXPLAIN FORMAT=JSON $q1;
+--sorted_result
+eval $without_filter $q1;
+
+let $q2=
+SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+ FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-01-31' AND
+ o_totalprice between 200000 and 230000;
+
+eval $with_filter EXPLAIN $q2;
+eval $with_filter EXPLAIN FORMAT=JSON $q2;
+--sorted_result
+eval $with_filter $q2;
+
+eval $without_filter EXPLAIN $q2;
+eval $without_filter EXPLAIN FORMAT=JSON $q2;
+--sorted_result
+eval $without_filter $q2;
+
+let $q3=
+SELECT o_orderkey, l_linenumber, l_shipdate, l_quantity, o_totalprice
+ FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+ l_quantity > 45 AND
+ o_totalprice between 180000 and 230000;
+
+eval $with_filter EXPLAIN $q3;
+eval $with_filter EXPLAIN FORMAT=JSON $q3;
+--sorted_result
+eval $with_filter $q3;
+
+eval $without_filter EXPLAIN $q3;
+eval $without_filter EXPLAIN FORMAT=JSON $q3;
+--sorted_result
+eval $without_filter $q3;
+
+let $q4=
+SELECT o_orderkey, l_linenumber, l_shipdate, o_totalprice
+ FROM orders JOIN lineitem ON o_orderkey=l_orderkey
+ WHERE l_shipdate BETWEEN '1997-01-01' AND '1997-06-30' AND
+ o_totalprice between 200000 and 230000;
+
+eval $with_filter EXPLAIN $q4;
+eval $with_filter EXPLAIN FORMAT=JSON $q4;
+--sorted_result
+eval $with_filter $q4;
+
+eval $without_filter EXPLAIN $q4;
+eval $without_filter EXPLAIN FORMAT=JSON $q4;
+--sorted_result
+eval $without_filter $q4;
+
--echo # lineitem : {i_l_receiptdate, i_l_shipdate} -> i_l_receiptdate
EXPLAIN SELECT *
FROM orders JOIN lineitem ON o_orderkey=l_orderkey
diff --git a/mysql-test/main/select.result b/mysql-test/main/select.result
index 75106b5..220f500 100644
--- a/mysql-test/main/select.result
+++ b/mysql-test/main/select.result
@@ -3474,13 +3474,13 @@ INSERT INTO t2 VALUES
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL c NULL NULL NULL 18 Using where
-1 SIMPLE t1 eq_ref|filter PRIMARY,b PRIMARY|b 4|5 test.t2.c 1 (30%) Using where; Using filter
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition
+1 SIMPLE t2 ref c c 5 test.t1.a 2
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL c NULL NULL NULL 18 Using where
-1 SIMPLE t1 eq_ref|filter PRIMARY,b PRIMARY|b 4|5 test.t2.c 1 (30%) Using where; Using filter
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition; Using where
+1 SIMPLE t2 ref c c 5 test.t1.a 2
DROP TABLE t1, t2;
create table t1 (
a int unsigned not null auto_increment primary key,
@@ -3698,6 +3698,9 @@ INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null=3;
COUNT(*)
24
@@ -3740,7 +3743,7 @@ EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref idx1,idx2 idx1 5 const 2 Using index condition; Using where
+1 SIMPLE t1 ref|filter idx1,idx2 idx1|idx2 5|4 const 2 (1%) Using index condition; Using where; Using filter
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/main/select.test b/mysql-test/main/select.test
index e7525f8..0d43dfd 100644
--- a/mysql-test/main/select.test
+++ b/mysql-test/main/select.test
@@ -3230,6 +3230,8 @@ INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+ANALYZE TABLE t1;
+
SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null=3;
SELECT COUNT(*) FROM t1 WHERE ID1_with_null=3 AND ID2_with_null IS NULL;
SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null IS NULL;
diff --git a/mysql-test/main/select_jcl6.result b/mysql-test/main/select_jcl6.result
index 16672bd..bc86a27 100644
--- a/mysql-test/main/select_jcl6.result
+++ b/mysql-test/main/select_jcl6.result
@@ -3485,13 +3485,13 @@ INSERT INTO t2 VALUES
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL c NULL NULL NULL 18 Using where
-1 SIMPLE t1 eq_ref|filter PRIMARY,b PRIMARY|b 4|5 test.t2.c 1 (30%) Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan; Using filter
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition; Rowid-ordered scan
+1 SIMPLE t2 ref c c 5 test.t1.a 2 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL c NULL NULL NULL 18 Using where
-1 SIMPLE t1 eq_ref|filter PRIMARY,b PRIMARY|b 4|5 test.t2.c 1 (30%) Using where; Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan; Using filter
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition; Using where; Rowid-ordered scan
+1 SIMPLE t2 ref c c 5 test.t1.a 2 Using join buffer (flat, BKA join); Key-ordered Rowid-ordered scan
DROP TABLE t1, t2;
create table t1 (
a int unsigned not null auto_increment primary key,
@@ -3709,6 +3709,9 @@ INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null=3;
COUNT(*)
24
@@ -3751,7 +3754,7 @@ EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref idx1,idx2 idx1 5 const 2 Using index condition; Using where
+1 SIMPLE t1 ref|filter idx1,idx2 idx1|idx2 5|4 const 2 (1%) Using index condition; Using where; Using filter
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/main/select_pkeycache.result b/mysql-test/main/select_pkeycache.result
index 75106b5..220f500 100644
--- a/mysql-test/main/select_pkeycache.result
+++ b/mysql-test/main/select_pkeycache.result
@@ -3474,13 +3474,13 @@ INSERT INTO t2 VALUES
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL c NULL NULL NULL 18 Using where
-1 SIMPLE t1 eq_ref|filter PRIMARY,b PRIMARY|b 4|5 test.t2.c 1 (30%) Using where; Using filter
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition
+1 SIMPLE t2 ref c c 5 test.t1.a 2
EXPLAIN
SELECT a, c, d, f FROM t1,t2 WHERE a=c AND b BETWEEN 4 AND 6 AND a > 0;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 ALL c NULL NULL NULL 18 Using where
-1 SIMPLE t1 eq_ref|filter PRIMARY,b PRIMARY|b 4|5 test.t2.c 1 (30%) Using where; Using filter
+1 SIMPLE t1 range PRIMARY,b b 5 NULL 3 Using index condition; Using where
+1 SIMPLE t2 ref c c 5 test.t1.a 2
DROP TABLE t1, t2;
create table t1 (
a int unsigned not null auto_increment primary key,
@@ -3698,6 +3698,9 @@ INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID1_with_null IS NULL;
INSERT INTO t1 SELECT * FROM t1 WHERE ID2_with_null IS NULL;
+ANALYZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
SELECT COUNT(*) FROM t1 WHERE ID1_with_null IS NULL AND ID2_with_null=3;
COUNT(*)
24
@@ -3740,7 +3743,7 @@ EXPLAIN SELECT * FROM t1
WHERE ID_better=1 AND ID1_with_null IS NULL AND
(ID2_with_null=1 OR ID2_with_null=2);
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref idx1,idx2 idx1 5 const 2 Using index condition; Using where
+1 SIMPLE t1 ref|filter idx1,idx2 idx1|idx2 5|4 const 2 (1%) Using index condition; Using where; Using filter
DROP TABLE t1;
CREATE TABLE t1 (a INT, ts TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, KEY ts(ts));
INSERT INTO t1 VALUES (30,"2006-01-03 23:00:00"), (31,"2006-01-03 23:00:00");
diff --git a/mysql-test/main/subselect2.result b/mysql-test/main/subselect2.result
index f2047bf..7620842 100644
--- a/mysql-test/main/subselect2.result
+++ b/mysql-test/main/subselect2.result
@@ -132,7 +132,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3.PARENTID 1 Using where
1 PRIMARY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3.PARENTID 1 Using where
1 PRIMARY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3.PARENTID 1 Using where
-1 PRIMARY t3 eq_ref|filter PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY|CMFLDRPARNT_IDX 34|35 test.t3.PARENTID 1 (29%) Using where; Using filter
+1 PRIMARY t3 eq_ref PRIMARY,FFOLDERID_IDX,CMFLDRPARNT_IDX PRIMARY 34 test.t3.PARENTID 1 Using where
drop table t1, t2, t3, t4;
CREATE TABLE t1 (a int(10) , PRIMARY KEY (a)) Engine=InnoDB;
INSERT INTO t1 VALUES (1),(2);
diff --git a/mysql-test/main/subselect_mat_cost.result b/mysql-test/main/subselect_mat_cost.result
index 245739c..5acf8cb 100644
--- a/mysql-test/main/subselect_mat_cost.result
+++ b/mysql-test/main/subselect_mat_cost.result
@@ -280,6 +280,7 @@ Q2.2m:
Countries that speak French OR Spanish, but do not speak English
MATERIALIZATION because the outer query filters less rows than Q5-a,
so there are more lookups.
+set statement optimizer_switch='rowid_filter=off' for
EXPLAIN
SELECT Country.Name
FROM Country, CountryLanguage
@@ -289,7 +290,8 @@ AND Code = Country;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY CountryLanguage range PRIMARY,Language Language 30 NULL 44 Using index condition; Using where; Rowid-ordered scan
1 PRIMARY Country eq_ref PRIMARY PRIMARY 3 world.CountryLanguage.Country 1 Using where
-2 MATERIALIZED CountryLanguage ref PRIMARY,Language Language 30 const 48 Using index condition
+3 MATERIALIZED CountryLanguage ref PRIMARY,Language Language 30 const 48 Using index condition
+set statement optimizer_switch='rowid_filter=off' for
SELECT Country.Name
FROM Country, CountryLanguage
WHERE Code NOT IN (SELECT Country FROM CountryLanguage WHERE Language = 'English')
diff --git a/mysql-test/main/subselect_mat_cost.test b/mysql-test/main/subselect_mat_cost.test
index 5a1fb55..5f44d0d 100644
--- a/mysql-test/main/subselect_mat_cost.test
+++ b/mysql-test/main/subselect_mat_cost.test
@@ -205,6 +205,9 @@ WHERE Code NOT IN (SELECT Country FROM CountryLanguage WHERE Language = 'English
-- echo Countries that speak French OR Spanish, but do not speak English
-- echo MATERIALIZATION because the outer query filters less rows than Q5-a,
-- echo so there are more lookups.
+
+
+set statement optimizer_switch='rowid_filter=off' for
EXPLAIN
SELECT Country.Name
FROM Country, CountryLanguage
@@ -212,6 +215,7 @@ WHERE Code NOT IN (SELECT Country FROM CountryLanguage WHERE Language = 'English
AND (CountryLanguage.Language = 'French' OR CountryLanguage.Language = 'Spanish')
AND Code = Country;
+set statement optimizer_switch='rowid_filter=off' for
SELECT Country.Name
FROM Country, CountryLanguage
WHERE Code NOT IN (SELECT Country FROM CountryLanguage WHERE Language = 'English')
diff --git a/sql/handler.h b/sql/handler.h
index f122a26..8869d3d 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -325,6 +325,8 @@ enum enum_alter_inplace_result {
*/
#define HA_CLUSTERED_INDEX 512
+#define HA_DO_RANGE_FILTER_PUSHDOWN 1024
+
/*
bits in alter_table_flags:
*/
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 4fc321f..ba2705b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2520,6 +2520,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
quick=0;
needed_reg.clear_all();
quick_keys.clear_all();
+ head->with_impossible_ranges.clear_all();
DBUG_ASSERT(!head->is_filled_at_execution());
if (keys_to_use.is_clear_all() || head->is_filled_at_execution())
DBUG_RETURN(0);
@@ -8556,6 +8557,7 @@ int and_range_trees(RANGE_OPT_PARAM *param, SEL_TREE *tree1, SEL_TREE *tree2,
if (key && key->type == SEL_ARG::IMPOSSIBLE)
{
result->type= SEL_TREE::IMPOSSIBLE;
+ param->table->with_impossible_ranges.set_bit(param->real_keynr[key_no]);
DBUG_RETURN(1);
}
result_keys.set_bit(key_no);
diff --git a/sql/rowid_filter.cc b/sql/rowid_filter.cc
index 2ce6d83..7af9c4e 100644
--- a/sql/rowid_filter.cc
+++ b/sql/rowid_filter.cc
@@ -5,6 +5,27 @@
#include "rowid_filter.h"
#include "sql_select.h"
+inline
+double Range_filter_cost_info::lookup_cost(
+ Rowid_filter_container_type cont_type)
+{
+ switch (cont_type) {
+ case ORDERED_ARRAY_CONTAINER:
+ return log(est_elements)*0.01;
+ default:
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
+
+inline
+double Range_filter_cost_info::avg_access_and_eval_gain_per_row(
+ Rowid_filter_container_type cont_type)
+{
+ return (1+1.0/TIME_FOR_COMPARE) * (1 - selectivity) -
+ lookup_cost(cont_type);
+}
/**
Sets information about filter with key_numb index.
@@ -12,15 +33,19 @@
and gets slope and interscept values.
*/
-void Range_filter_cost_info::init(TABLE *tab, uint key_numb)
+void Range_filter_cost_info::init(Rowid_filter_container_type cont_type,
+ TABLE *tab, uint idx)
{
+ container_type= cont_type;
table= tab;
- key_no= key_numb;
+ key_no= idx;
est_elements= table->quick_rows[key_no];
- b= build_cost(ORDERED_ARRAY_CONTAINER);
+ b= build_cost(container_type);
selectivity= est_elements/((double) table->stat_records());
- a= (1 + COST_COND_EVAL)*(1 - selectivity) - lookup_cost();
- intersect_x_axis_abcissa= b/a;
+ a= avg_access_and_eval_gain_per_row(container_type);
+ if (a > 0)
+ cross_x= b/a;
+ abs_independent.clear_all();
}
double
@@ -43,128 +68,99 @@ Range_filter_cost_info::build_cost(Rowid_filter_container_type container_type)
return cost;
}
-/**
- @brief
- Sort available filters by their building cost in the increasing order
-
- @details
- The method starts sorting available filters from the first filter that
- is not defined as the best filter. If there are two filters that are
- defined as the best filters there is no need to sort other filters.
- Best filters are already sorted by their building cost and have the
- smallest bulding cost in comparison with other filters by definition.
-
- As the sorting method bubble sort is used.
-*/
-void TABLE::sort_range_filter_cost_info_array()
+static
+int compare_range_filter_cost_info_by_a(Range_filter_cost_info **filter_ptr_1,
+ Range_filter_cost_info **filter_ptr_2)
{
- if (best_filter_count <= 2)
- return;
-
- for (uint i= best_filter_count; i < range_filter_cost_info_elements-1; i++)
- {
- for (uint j= i+1; j < range_filter_cost_info_elements; j++)
- {
- if (range_filter_cost_info[i].intersect_x_axis_abcissa >
- range_filter_cost_info[j].intersect_x_axis_abcissa)
- swap_variables(Range_filter_cost_info,
- range_filter_cost_info[i],
- range_filter_cost_info[j]);
- }
- }
+ double diff= (*filter_ptr_2)->a - (*filter_ptr_1)->a;
+ return (diff < 0 ? -1 : (diff > 0 ? 1 : 0));
}
-
/**
@brief
- The method searches for the filters that can reduce the join cost the most
@details
- The method looks through the available filters trying to choose the best
- filter and eliminate as many filters as possible.
-
- Filters are considered as a linear functions. The best filter is the linear
- function that intersects all other linear functions not in the I quadrant
- and has the biggest a (slope) value. This filter will reduce the partial
- join cost the most. If it is possible the second best filter is also
- chosen. The second best filter can be used if the ref access is made on
- the index of the first best filter.
-
- So there is no need to store all other filters except filters that
- intersect in the I quadrant. It is impossible to say on this step which
- filter is better and will give the biggest gain.
-
- The number of filters that can be used is stored in the
- range_filter_cost_info_elements variable.
*/
void TABLE::prune_range_filters()
{
- key_map pruned_filter_map;
- pruned_filter_map.clear_all();
- Range_filter_cost_info *max_slope_filters[2] = {0, 0};
+ uint i, j;
- for (uint i= 0; i < range_filter_cost_info_elements; i++)
+ Range_filter_cost_info **filter_ptr_1= range_filter_cost_info_ptr;
+ for (i= 0; i < range_filter_cost_info_elems; i++, filter_ptr_1++)
{
- Range_filter_cost_info *filter= &range_filter_cost_info[i];
- if (filter->a < 0)
+ uint key_no= (*filter_ptr_1)->key_no;
+ Range_filter_cost_info **filter_ptr_2= filter_ptr_1 + 1;
+ for (j= i+1; j < range_filter_cost_info_elems; j++, filter_ptr_2++)
{
- range_filter_cost_info_elements--;
- swap_variables(Range_filter_cost_info, range_filter_cost_info[i],
- range_filter_cost_info[range_filter_cost_info_elements]);
- i--;
- continue;
+ key_map map= key_info[key_no].overlapped;
+ map.intersect(key_info[(*filter_ptr_2)->key_no].overlapped);
+ if (map.is_clear_all())
+ {
+ (*filter_ptr_1)->abs_independent.set_bit((*filter_ptr_2)->key_no);
+ (*filter_ptr_2)->abs_independent.set_bit(key_no);
+ }
}
- for (uint j= i+1; j < range_filter_cost_info_elements; j++)
- {
- Range_filter_cost_info *cand_filter= &range_filter_cost_info[j];
+ }
- double intersect_x= filter->get_intersect_x(cand_filter);
- double intersect_y= filter->get_intersect_y(intersect_x);
+ /* Sort the array range_filter_cost_info by 'a' */
+ my_qsort(range_filter_cost_info_ptr,
+ range_filter_cost_info_elems,
+ sizeof(Range_filter_cost_info *),
+ (qsort_cmp) compare_range_filter_cost_info_by_a);
- if (intersect_x > 0 && intersect_y > 0)
+ Range_filter_cost_info **cand_filter_ptr= range_filter_cost_info_ptr;
+ for (i= 0; i < range_filter_cost_info_elems; i++, cand_filter_ptr++)
+ {
+ bool is_pruned= false;
+ Range_filter_cost_info **usable_filter_ptr= range_filter_cost_info_ptr;
+ key_map abs_indep;
+ abs_indep.clear_all();
+ for (uint j= 0; j < i; j++, usable_filter_ptr++)
+ {
+ if ((*cand_filter_ptr)->cross_x >= (*usable_filter_ptr)->cross_x)
{
- pruned_filter_map.set_bit(cand_filter->key_no);
- pruned_filter_map.set_bit(filter->key_no);
+ if (abs_indep.is_set((*usable_filter_ptr)->key_no))
+ {
+ is_pruned= true;
+ break;
+ }
+ abs_indep.merge((*usable_filter_ptr)->abs_independent);
}
- }
- if (!pruned_filter_map.is_set(filter->key_no))
- {
- if (!max_slope_filters[0])
- max_slope_filters[0]= filter;
else
{
- if (!max_slope_filters[1] ||
- max_slope_filters[1]->a < filter->a)
- max_slope_filters[1]= filter;
- if (max_slope_filters[0]->a < max_slope_filters[1]->a)
- swap_variables(Range_filter_cost_info*, max_slope_filters[0],
- max_slope_filters[1]);
+ Range_filter_cost_info *moved= *cand_filter_ptr;
+ memmove(usable_filter_ptr+1, usable_filter_ptr,
+ sizeof(Range_filter_cost_info *) * (i-j-1));
+ *usable_filter_ptr= moved;
}
}
- }
-
- for (uint i= 0; i<2; i++)
- {
- if (max_slope_filters[i])
+ if (is_pruned)
{
- swap_variables(Range_filter_cost_info,
- range_filter_cost_info[i],
- *max_slope_filters[i]);
- if (i == 0 &&
- max_slope_filters[1] == &range_filter_cost_info[0])
- max_slope_filters[1]= max_slope_filters[0];
-
- best_filter_count++;
- max_slope_filters[i]= &range_filter_cost_info[i];
+ memmove(cand_filter_ptr, cand_filter_ptr+1,
+ sizeof(Range_filter_cost_info *) *
+ (range_filter_cost_info_elems - 1 - i));
+ range_filter_cost_info_elems--;
}
}
- sort_range_filter_cost_info_array();
}
-void TABLE::select_usable_range_filters(THD *thd)
+static uint
+get_max_range_filter_elements_for_table(THD *thd, TABLE *tab,
+ Rowid_filter_container_type cont_type)
+{
+ switch (cont_type) {
+ case ORDERED_ARRAY_CONTAINER :
+ return thd->variables.max_rowid_filter_size/tab->file->ref_length;
+ default :
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
+void TABLE::init_cost_info_for_usable_range_filters(THD *thd)
{
uint key_no;
key_map usable_range_filter_keys;
@@ -172,73 +168,74 @@ void TABLE::select_usable_range_filters(THD *thd)
key_map::Iterator it(quick_keys);
while ((key_no= it++) != key_map::Iterator::BITMAP_END)
{
- if (quick_rows[key_no] >
- thd->variables.max_rowid_filter_size/file->ref_length)
+ if (!(file->index_flags(key_no, 0, 1) & HA_DO_RANGE_FILTER_PUSHDOWN))
+ continue;
+ if (key_no == s->primary_key && file->primary_key_is_clustered())
+ continue;
+ if (quick_rows[key_no] >
+ get_max_range_filter_elements_for_table(thd, this,
+ ORDERED_ARRAY_CONTAINER))
continue;
usable_range_filter_keys.set_bit(key_no);
}
- if (usable_range_filter_keys.is_clear_all())
+ range_filter_cost_info_elems= usable_range_filter_keys.bits_set();
+ if (!range_filter_cost_info_elems)
return;
- range_filter_cost_info_elements= usable_range_filter_keys.bits_set();
+ range_filter_cost_info_ptr=
+ (Range_filter_cost_info **) thd->calloc(sizeof(Range_filter_cost_info *) *
+ range_filter_cost_info_elems);
range_filter_cost_info=
- new (thd->mem_root) Range_filter_cost_info [range_filter_cost_info_elements];
+ new (thd->mem_root) Range_filter_cost_info[range_filter_cost_info_elems];
+ if (!range_filter_cost_info_ptr || !range_filter_cost_info)
+ {
+ range_filter_cost_info_elems= 0;
+ return;
+ }
+
+ Range_filter_cost_info **curr_ptr= range_filter_cost_info_ptr;
Range_filter_cost_info *curr_filter_cost_info= range_filter_cost_info;
key_map::Iterator li(usable_range_filter_keys);
while ((key_no= li++) != key_map::Iterator::BITMAP_END)
{
- curr_filter_cost_info->init(this, key_no);
+ *curr_ptr= curr_filter_cost_info;
+ curr_filter_cost_info->init(ORDERED_ARRAY_CONTAINER, this, key_no);
+ curr_ptr++;
curr_filter_cost_info++;
}
prune_range_filters();
}
-Range_filter_cost_info
-*TABLE::best_filter_for_current_join_order(uint ref_key_no,
- double record_count,
- double records)
+Range_filter_cost_info *TABLE::best_filter_for_partial_join(uint access_key_no,
+ double records)
{
- if (!this || range_filter_cost_info_elements == 0)
+ if (!this || range_filter_cost_info_elems == 0 ||
+ covering_keys.is_set(access_key_no))
return 0;
- double card= record_count*records;
- Range_filter_cost_info *best_filter= &range_filter_cost_info[0];
-
- if (card < best_filter->intersect_x_axis_abcissa)
+ if (access_key_no == s->primary_key && file->primary_key_is_clustered())
return 0;
- if (best_filter_count != 0)
- {
- if (best_filter->key_no == ref_key_no)
- {
- if (best_filter_count == 2)
- {
- best_filter= &range_filter_cost_info[1];
- if (card < best_filter->intersect_x_axis_abcissa)
- return 0;
- return best_filter;
- }
- }
- else
- return best_filter;
- }
- double best_filter_improvement= 0.0;
- best_filter= 0;
+ Range_filter_cost_info *best_filter= 0;
+ double best_filter_gain= 0;
- key_map *intersected_with= &key_info->intersected_with;
- for (uint i= best_filter_count; i < range_filter_cost_info_elements; i++)
+ key_map *overlapped= &key_info[access_key_no].overlapped;
+ for (uint i= 0; i < range_filter_cost_info_elems ; i++)
{
- Range_filter_cost_info *filter= &range_filter_cost_info[i];
- if ((filter->key_no == ref_key_no) || intersected_with->is_set(filter->key_no))
+ double curr_gain = 0;
+ Range_filter_cost_info *filter= range_filter_cost_info_ptr[i];
+ if ((filter->key_no == access_key_no) ||
+ overlapped->is_set(filter->key_no))
continue;
- if (card < filter->intersect_x_axis_abcissa)
+ if (records < filter->cross_x)
break;
- if (best_filter_improvement < filter->get_filter_gain(card))
+ curr_gain= filter->get_gain(records);
+ if (best_filter_gain < curr_gain)
{
- best_filter_improvement= filter->get_filter_gain(card);
+ best_filter_gain= curr_gain;
best_filter= filter;
}
}
diff --git a/sql/rowid_filter.h b/sql/rowid_filter.h
index 9b93679..7cec865 100644
--- a/sql/rowid_filter.h
+++ b/sql/rowid_filter.h
@@ -129,48 +129,51 @@ typedef enum
class Range_filter_cost_info : public Sql_alloc
{
public:
+ Rowid_filter_container_type container_type;
TABLE *table;
uint key_no;
double est_elements;
double b; // intercept of the linear function
double a; // slope of the linear function
double selectivity;
- double intersect_x_axis_abcissa;
+ double cross_x;
+ key_map abs_independent;
/**
Filter cost functions
*/
- /* Cost to lookup into filter */
- inline double lookup_cost()
- {
- return log(est_elements)*0.01;
- }
Range_filter_cost_info() : table(0), key_no(0) {}
- void init(TABLE *tab, uint key_numb);
+ void init(Rowid_filter_container_type cont_type,
+ TABLE *tab, uint key_numb);
double build_cost(Rowid_filter_container_type container_type);
- inline double get_intersect_x(Range_filter_cost_info *filter)
+ inline double lookup_cost(Rowid_filter_container_type cont_type);
+
+ inline double
+ avg_access_and_eval_gain_per_row(Rowid_filter_container_type cont_type);
+
+ /**
+ Get the gain that usage of filter promises for 'rows' key entries
+ */
+ inline double get_gain(double rows)
+ {
+ return rows * a - b;
+ }
+
+ inline double get_adjusted_gain(double rows, double worst_seeks)
{
- if (a == filter->a)
- return DBL_MAX;
- return (b - filter->b)/(a - filter->a);
+ return get_gain(rows) -
+ (1 - selectivity) * (rows - MY_MIN(rows, worst_seeks));
}
- inline double get_intersect_y(double intersect_x)
+
+ inline double get_cmp_gain(double rows)
{
- if (intersect_x == DBL_MAX)
- return DBL_MAX;
- return intersect_x*a - b;
+ return rows * (1 - selectivity) / TIME_FOR_COMPARE;
}
- /**
- Get a gain that a usage of filter in some partial join order
- with the cardinaly card gives
- */
- inline double get_filter_gain(double card)
- { return card*a - b; }
};
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3edf63f..724e156 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1490,6 +1490,7 @@ bool JOIN::make_range_filters()
key_map filter_map;
filter_map.clear_all();
filter_map.set_bit(tab->filter->key_no);
+ filter_map.merge(tab->table->with_impossible_ranges);
bool force_index_save= tab->table->force_index;
tab->table->force_index= true;
(void) sel->test_quick_select(thd, filter_map, (table_map) 0,
@@ -5118,9 +5119,8 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
select->quick=0;
impossible_range= records == 0 && s->table->reginfo.impossible_range;
if (join->thd->lex->sql_command == SQLCOM_SELECT &&
- join->table_count > 1 &&
optimizer_flag(join->thd, OPTIMIZER_SWITCH_USE_ROWID_FILTER))
- s->table->select_usable_range_filters(join->thd);
+ s->table->init_cost_info_for_usable_range_filters(join->thd);
}
if (!impossible_range)
{
@@ -7328,11 +7328,14 @@ best_access_path(JOIN *join,
if (records < DBL_MAX)
{
- filter= table->best_filter_for_current_join_order(start_key->key,
- records,
- record_count);
- if (filter && (filter->get_filter_gain(record_count*records) < tmp))
- tmp= tmp - filter->get_filter_gain(record_count*records);
+ double rows= record_count * records;
+ filter= table->best_filter_for_partial_join(start_key->key, rows);
+ if (filter)
+ {
+ tmp-= filter->get_adjusted_gain(rows, s->worst_seeks) -
+ filter->get_cmp_gain(rows);
+ DBUG_ASSERT(tmp >= 0);
+ }
}
if (tmp + 0.0001 < best_time - records/(double) TIME_FOR_COMPARE)
@@ -7438,6 +7441,7 @@ best_access_path(JOIN *join,
Here we estimate its cost.
*/
+ filter= 0;
if (s->quick)
{
/*
@@ -7453,6 +7457,18 @@ best_access_path(JOIN *join,
(s->quick->read_time +
(s->found_records - rnd_records)/(double) TIME_FOR_COMPARE);
+ if ( s->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE)
+ {
+ double rows= record_count * s->found_records;
+ uint key_no= s->quick->index;
+ filter= s->table->best_filter_for_partial_join(key_no, rows);
+ if (filter)
+ {
+ tmp-= filter->get_gain(rows);
+ DBUG_ASSERT(tmp >= 0);
+ }
+ }
+
loose_scan_opt.check_range_access(join, idx, s->quick);
}
else
@@ -7498,24 +7514,23 @@ best_access_path(JOIN *join,
else
tmp+= s->startup_cost;
- if (s->quick && s->quick->get_type() == QUICK_SELECT_I::QS_TYPE_RANGE)
- {
- filter= s->table->best_filter_for_current_join_order(s->quick->index,
- rnd_records,
- record_count);
- if (filter && (filter->get_filter_gain(record_count*rnd_records) < tmp))
- tmp= tmp - filter->get_filter_gain(record_count*rnd_records);
- }
-
/*
We estimate the cost of evaluating WHERE clause for found records
as record_count * rnd_records / TIME_FOR_COMPARE. This cost plus
tmp give us total cost of using TABLE SCAN
*/
+
+ double filter_cmp_gain= 0;
+ if (filter)
+ {
+ filter_cmp_gain= filter->get_cmp_gain(record_count * s->found_records);
+ }
+
if (best == DBL_MAX ||
(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)))
+ best + record_count/(double) TIME_FOR_COMPARE*records -
+ filter_cmp_gain)))
{
/*
If the table has a range (s->quick is set) make_join_select()
@@ -12708,9 +12723,7 @@ ha_rows JOIN_TAB::get_examined_rows()
double examined_rows;
SQL_SELECT *sel= filesort? filesort->select : this->select;
- if (filter)
- examined_rows= records_read;
- else if (sel && sel->quick && use_quick != 2)
+ if (sel && sel->quick && use_quick != 2)
examined_rows= (double)sel->quick->records;
else if (type == JT_NEXT || type == JT_ALL ||
type == JT_HASH || type ==JT_HASH_NEXT)
@@ -22477,6 +22490,12 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
tab->use_quick=1;
tab->ref.key= -1;
tab->ref.key_parts=0; // Don't use ref key.
+ tab->filter= 0;
+ if (tab->rowid_filter)
+ {
+ delete tab->rowid_filter;
+ tab->rowid_filter= 0;
+ }
tab->read_first_record= join_init_read_record;
if (tab->is_using_loose_index_scan())
tab->join->tmp_table_param.precomputed_group_by= TRUE;
diff --git a/sql/structs.h b/sql/structs.h
index 5cc64c1..a45cc34 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -120,7 +120,7 @@ typedef struct st_key {
*/
LEX_CSTRING name;
key_part_map ext_key_part_map;
- key_map intersected_with;
+ key_map overlapped;
uint block_size;
enum ha_key_alg algorithm;
/*
diff --git a/sql/table.cc b/sql/table.cc
index a2408d6..67c369f 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1228,12 +1228,13 @@ static const Type_handler *old_frm_type_handler(uint pack_flag,
}
-void TABLE_SHARE::set_intersected_keys()
+void TABLE_SHARE::set_overlapped_keys()
{
KEY *key1= key_info;
for (uint i= 0; i < keys; i++, key1++)
{
- key1->intersected_with.clear_all();
+ key1->overlapped.clear_all();
+ key1->overlapped.set_bit(i);
}
key1= key_info;
for (uint i= 0; i < keys; i++, key1++)
@@ -1242,18 +1243,23 @@ void TABLE_SHARE::set_intersected_keys()
for (uint j= i+1; j < keys; j++, key2++)
{
KEY_PART_INFO *key_part1= key1->key_part;
- KEY_PART_INFO *key_part2= key2->key_part;
- uint n= key1->user_defined_key_parts;
- set_if_smaller(n, key2->user_defined_key_parts);
- for (uint k= 0; k < n; k++, key_part1++, key_part2++)
+ uint n1= key1->user_defined_key_parts;
+ uint n2= key2->user_defined_key_parts;
+ for (uint k= 0; k < n1; k++, key_part1++)
{
- if (key_part1->fieldnr == key_part2->fieldnr)
+ KEY_PART_INFO *key_part2= key2->key_part;
+ for (uint l= 0; l < n2; l++, key_part2++)
{
- key1->intersected_with.set_bit(j);
- key2->intersected_with.set_bit(i);
- break;
+ if (key_part1->fieldnr == key_part2->fieldnr)
+ {
+ key1->overlapped.set_bit(j);
+ key2->overlapped.set_bit(i);
+ goto end_checking_overlap;
+ }
}
- }
+ }
+ end_checking_overlap:
+ ;
}
}
}
@@ -2553,7 +2559,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
null_length, 255);
}
- set_intersected_keys();
+ set_overlapped_keys();
/* Handle virtual expressions */
if (vcol_screen_length && share->frm_version >= FRM_VER_EXPRESSSIONS)
@@ -4689,8 +4695,9 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
created= TRUE;
cond_selectivity= 1.0;
cond_selectivity_sampling_explain= NULL;
- best_filter_count= 0;
- range_filter_cost_info_elements= 0;
+ range_filter_cost_info_elems= 0;
+ range_filter_cost_info_ptr= NULL;
+ range_filter_cost_info= NULL;
#ifdef HAVE_REPLICATION
/* used in RBR Triggers */
master_had_triggers= 0;
diff --git a/sql/table.h b/sql/table.h
index a027c85..feeb9ee 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1003,7 +1003,7 @@ struct TABLE_SHARE
/* frees the memory allocated in read_frm_image */
void free_frm_image(const uchar *frm);
- void set_intersected_keys();
+ void set_overlapped_keys();
};
@@ -1503,21 +1503,14 @@ struct TABLE
double get_materialization_cost(); // Now used only if is_splittable()==true
void add_splitting_info_for_key_field(struct KEY_FIELD *key_field);
-
- /**
- Range filter info
- */
- /* Minimum possible #T value to apply filter*/
- uint best_filter_count;
- uint range_filter_cost_info_elements;
+ key_map with_impossible_ranges;
+ uint range_filter_cost_info_elems;
+ Range_filter_cost_info **range_filter_cost_info_ptr;
Range_filter_cost_info *range_filter_cost_info;
- Range_filter_cost_info
- *best_filter_for_current_join_order(uint ref_key_no,
- double record_count,
- double records);
- void sort_range_filter_cost_info_array();
+ void init_cost_info_for_usable_range_filters(THD *thd);
void prune_range_filters();
- void select_usable_range_filters(THD *thd);
+ Range_filter_cost_info *best_filter_for_partial_join(uint access_key_no,
+ double records);
/**
System Versioning support
*/
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index e43019b..8a092d6 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -5250,7 +5250,8 @@ ha_innobase::index_flags(
ulong flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
| HA_READ_RANGE | HA_KEYREAD_ONLY
| extra_flag
- | HA_DO_INDEX_COND_PUSHDOWN;
+ | HA_DO_INDEX_COND_PUSHDOWN
+ | HA_DO_RANGE_FILTER_PUSHDOWN;
/* For spatial index, we don't support descending scan
and ICP so far. */
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index de7a71d..012691e 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -769,7 +769,8 @@ ulong ha_myisam::index_flags(uint inx, uint part, bool all_parts) const
else
{
flags= HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
- HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN;
+ HA_READ_ORDER | HA_KEYREAD_ONLY | HA_DO_INDEX_COND_PUSHDOWN |
+ HA_DO_RANGE_FILTER_PUSHDOWN;
}
return flags;
}
1
0
[Commits] a90b739d4b9: Merge remote-tracking branch 'origin/10.4' into bb-10.4-galera4
by jan 17 Jan '19
by jan 17 Jan '19
17 Jan '19
revision-id: a90b739d4b925729b7135c785a5f255f5a7fced2 (mariadb-10.3.6-327-ga90b739d4b9)
parent(s): e5a7ef0e34e72b87818af52fc0c8447c2bb49432 5fb4e4ab3939402ff6864e14ddbc9dd564a9d44f
author: Jan Lindström
committer: Jan Lindström
timestamp: 2019-01-17 17:22:02 +0200
message:
Merge remote-tracking branch 'origin/10.4' into bb-10.4-galera4
extra/mariabackup/CMakeLists.txt | 26 +-
extra/mariabackup/backup_copy.cc | 130 ++++---
extra/mariabackup/backup_mysql.cc | 100 +++---
extra/mariabackup/changed_page_bitmap.cc | 26 +-
extra/mariabackup/common.h | 71 ++--
extra/mariabackup/{datasink.c => datasink.cc} | 11 +-
extra/mariabackup/{ds_archive.c => ds_archive.cc} | 0
extra/mariabackup/{ds_buffer.c => ds_buffer.cc} | 4 +-
.../mariabackup/{ds_compress.c => ds_compress.cc} | 8 +-
extra/mariabackup/{ds_stdout.c => ds_stdout.cc} | 2 +-
extra/mariabackup/{ds_tmpfile.c => ds_tmpfile.cc} | 22 +-
.../mariabackup/{ds_xbstream.c => ds_xbstream.cc} | 12 +-
extra/mariabackup/encryption_plugin.cc | 9 +-
extra/mariabackup/fil_cur.cc | 32 +-
extra/mariabackup/innobackupex.cc | 2 +-
extra/mariabackup/write_filt.cc | 11 +-
extra/mariabackup/wsrep.cc | 7 +-
extra/mariabackup/{xbstream.c => xbstream.cc} | 37 +-
extra/mariabackup/xbstream.h | 2 +-
.../{xbstream_read.c => xbstream_read.cc} | 24 +-
.../{xbstream_write.c => xbstream_write.cc} | 6 +-
extra/mariabackup/xtrabackup.cc | 385 +++++++++------------
extra/mariabackup/xtrabackup.h | 14 +-
include/json_lib.h | 4 -
include/mysql/plugin_audit.h.pp | 20 +-
include/mysql/plugin_auth.h.pp | 20 +-
include/mysql/plugin_encryption.h.pp | 20 +-
include/mysql/plugin_ftparser.h.pp | 20 +-
include/mysql/plugin_password_validation.h.pp | 20 +-
include/mysql/service_json.h | 20 +-
mysql-test/main/subselect_exists2in.result | 4 +-
mysql-test/main/union.result | 38 ++
mysql-test/main/union.test | 35 ++
mysql-test/main/view.result | 4 +-
.../encryption/r/innodb-encryption-alter.result | 28 +-
.../encryption/t/innodb-encryption-alter.test | 38 +-
.../r/galera_FK_duplicate_client_insert.result | 380 ++++++++++++++++++++
.../t/galera_FK_duplicate_client_insert.test | 161 +++++++++
.../galera/t/galera_gtid_slave_sst_rsync.test | 4 +
.../suite/innodb/r/innodb-virtual-columns.result | 13 +
mysql-test/suite/innodb/r/instant_alter.result | 50 ++-
.../suite/innodb/t/innodb-virtual-columns.test | 11 +
mysql-test/suite/innodb/t/instant_alter.test | 19 +
.../sys_vars/r/sysvars_server_embedded.result | 2 +-
.../sys_vars/r/sysvars_server_notembedded.result | 2 +-
.../sys_vars/r/table_definition_cache_basic.result | 16 +-
.../sys_vars/t/table_definition_cache_basic.test | 6 +-
mysys/safemalloc.c | 4 +-
sql/sql_acl.cc | 30 +-
sql/sql_class.cc | 21 +-
sql/sql_lex.cc | 1 +
sql/sys_vars.cc | 8 +-
storage/innobase/fil/fil0crypt.cc | 11 +-
storage/innobase/handler/handler0alter.cc | 8 +-
storage/innobase/include/buf0buf.h | 6 +-
storage/innobase/include/dict0mem.h | 15 +-
storage/innobase/include/fil0fil.h | 4 +-
storage/innobase/include/univ.i | 11 +-
storage/innobase/os/os0proc.cc | 3 -
storage/innobase/row/row0ftsort.cc | 11 +-
storage/innobase/row/row0ins.cc | 3 +-
strings/json_lib.c | 145 +++++---
unittest/strings/CMakeLists.txt | 2 +-
unittest/strings/json-t.c | 58 ++++
64 files changed, 1494 insertions(+), 723 deletions(-)
diff --cc mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
index a525a35ead3,3ed7ec1d09e..d03445d537a
--- a/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
+++ b/mysql-test/suite/galera/t/galera_gtid_slave_sst_rsync.test
@@@ -181,15 -196,15 +181,19 @@@ DROP TABLE t2,t1
--connection node_2
STOP SLAVE;
RESET SLAVE ALL;
+set global wsrep_on=OFF;
+reset master;
+set global wsrep_on=ON;
++
+ --disable_warnings
set global gtid_slave_pos="";
+ --enable_warnings
-reset master;
-
---echo #Connection 3
---connection node_3
-reset master;
+
--echo #Connection 1
--connection node_1
+set global wsrep_on=OFF;
+reset master;
+set global wsrep_on=ON;
+--echo #Connection 3
+--connection node_3
reset master;
1
0
17 Jan '19
revision-id: e6273f9771bb084df0b65d024ef93d3f02bf961d (mariadb-10.0.37-41-ge6273f9771b)
parent(s): d0d0f88f2cd4da23c2c2da702da51fb533e7fb8a
author: Varun Gupta
committer: Varun Gupta
timestamp: 2019-01-17 18:35:45 +0530
message:
MDEV-18255: Server crashes in Bitmap<64u>::intersect
Calling st_select_lex::update_used_tables in JOIN::optimize_unflattened_subqueries
only when we are sure that the join have not been cleaned up.
This can happen for a case when we have a non-merged semi-join and an impossible
where which would lead to the cleanup of the join which has the non-merged semi-join
---
mysql-test/r/subselect_mat.result | 16 ++++++++++++++++
mysql-test/t/subselect_mat.test | 13 +++++++++++++
sql/sql_lex.cc | 3 ++-
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result
index aa0ac73abd2..7907b86135e 100644
--- a/mysql-test/r/subselect_mat.result
+++ b/mysql-test/r/subselect_mat.result
@@ -2822,3 +2822,19 @@ id select_type table type possible_keys key key_len ref rows Extra
SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 );
f
DROP TABLE t1, t2;
+#
+# MDEV-18255: Server crashes in Bitmap<64u>::intersect
+#
+create table t1 (v1 varchar(1)) engine=myisam ;
+create table t2 (v1 varchar(1)) engine=myisam ;
+explain
+select 1 from t1 where exists
+(select 1 from t1 where t1.v1 in (select t2.v1 from t2 having t2.v1 < 'j')) ;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
+2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+3 MATERIALIZED NULL NULL NULL NULL NULL NULL NULL no matching row in const table
+select 1 from t1 where exists
+(select 1 from t1 where t1.v1 in (select t2.v1 from t2 having t2.v1 < 'j')) ;
+1
+drop table t1,t2;
diff --git a/mysql-test/t/subselect_mat.test b/mysql-test/t/subselect_mat.test
index 5211f35b48b..66a6cc97acb 100644
--- a/mysql-test/t/subselect_mat.test
+++ b/mysql-test/t/subselect_mat.test
@@ -267,3 +267,16 @@ explain
SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 );
SELECT * FROM t2 WHERE f IN ( SELECT LEFT('foo',0) FROM t1 ORDER BY 1 );
DROP TABLE t1, t2;
+
+--echo #
+--echo # MDEV-18255: Server crashes in Bitmap<64u>::intersect
+--echo #
+create table t1 (v1 varchar(1)) engine=myisam ;
+create table t2 (v1 varchar(1)) engine=myisam ;
+
+explain
+select 1 from t1 where exists
+ (select 1 from t1 where t1.v1 in (select t2.v1 from t2 having t2.v1 < 'j')) ;
+select 1 from t1 where exists
+ (select 1 from t1 where t1.v1 in (select t2.v1 from t2 having t2.v1 < 'j')) ;
+drop table t1,t2;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 08c169c5999..2fb239ed498 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -3551,7 +3551,8 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
inner_join->select_options|= SELECT_DESCRIBE;
}
res= inner_join->optimize();
- sl->update_used_tables();
+ if (!inner_join->cleaned)
+ sl->update_used_tables();
sl->update_correlated_cache();
is_correlated_unit|= sl->is_correlated;
inner_join->select_options= save_options;
1
0
revision-id: f40f2d7737b5b57fefe31d9ed36f0fc5dee2b749 (mariadb-10.3.6-325-gf40f2d7737b)
parent(s): d1950ccd0733e393574df497d004b58bde29a77c
author: Jan Lindström
committer: Jan Lindström
timestamp: 2019-01-17 15:11:20 +0200
message:
Disable failing test case galera.GCF-1081
Run only with debug Galera library.
---
mysql-test/suite/galera/disabled.def | 1 +
1 file changed, 1 insertion(+)
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index e7b91b33050..b179c9d2a63 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -62,3 +62,4 @@ galera.galera_many_tables_nopk : MDEV-18182 Galera test failure on galera.galera
galera.galera_kill_nochanges : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges
galera.galera_split_brain : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges
galera.galera_bf_abort_group_commit : MDEV-18282 Galera test failure on galera.galera_bf_abort_group_commit
+galera.GCF-1081 : MDEV-18283 Galera test failure on galera.GCF-1081
1
0
revision-id: 437f6678d49e67e4dc5ecb7ee70d27458cb8d78a (mariadb-10.3.6-324-g437f6678d49)
parent(s): 6b0f83fcc0564eba3050a77bc90e67771990277c
author: Jan Lindström
committer: Jan Lindström
timestamp: 2019-01-17 14:59:53 +0200
message:
Re-record sysvars_wsrep after NBO removal
---
mysql-test/suite/sys_vars/r/sysvars_wsrep.result | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
index 709e9f60f54..ac83a0a8c7f 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_wsrep.result
@@ -376,7 +376,7 @@ VARIABLE_COMMENT Method for Online Schema Upgrade
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST TOI,RSU,NBO
+ENUM_VALUE_LIST TOI,RSU
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME WSREP_PATCH_VERSION
1
0
17 Jan '19
revision-id: a2417b84633326a88d3434c45b5be9e72fe17d90 (mariadb-10.3.6-322-ga2417b84633)
parent(s): 5e5ab9c664e1af0f498fde43137acb627515e524
author: Jan Lindström
committer: Jan Lindström
timestamp: 2019-01-17 14:34:42 +0200
message:
Fix failing test case galera.galera#500 and disable
galera.galera.galera_bf_abort_group_commit both run
only with debug build galera library.
---
mysql-test/suite/galera/disabled.def | 1 +
mysql-test/suite/galera/r/galera#500.result | 2 ++
mysql-test/suite/galera/t/galera#500.test | 6 ++++++
3 files changed, 9 insertions(+)
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index cb6c1d05e36..e7b91b33050 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -61,3 +61,4 @@ galera.galera_var_retry_autocommit: MDEV-18181 Galera test failure on galera.gal
galera.galera_many_tables_nopk : MDEV-18182 Galera test failure on galera.galera_many_tables_nopk
galera.galera_kill_nochanges : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges
galera.galera_split_brain : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges
+galera.galera_bf_abort_group_commit : MDEV-18282 Galera test failure on galera.galera_bf_abort_group_commit
diff --git a/mysql-test/suite/galera/r/galera#500.result b/mysql-test/suite/galera/r/galera#500.result
index 22d38777369..a5ab0b19718 100644
--- a/mysql-test/suite/galera/r/galera#500.result
+++ b/mysql-test/suite/galera/r/galera#500.result
@@ -1,5 +1,7 @@
connection node_2;
connection node_1;
+connection node_1;
+connection node_2;
connection node_2;
SET SESSION wsrep_sync_wait = 0;
SET GLOBAL wsrep_provider_options="gmcast.isolate=2";
diff --git a/mysql-test/suite/galera/t/galera#500.test b/mysql-test/suite/galera/t/galera#500.test
index 3c8490b6907..60f303b7103 100644
--- a/mysql-test/suite/galera/t/galera#500.test
+++ b/mysql-test/suite/galera/t/galera#500.test
@@ -8,6 +8,10 @@
--source include/galera_cluster.inc
--source include/galera_have_debug_sync.inc
+--let $node_1=node_1
+--let $node_2=node_2
+--source suite/galera/include/auto_increment_offset_save.inc
+
# Force node_2 gcomm background thread to terminate via exception.
--connection node_2
--let $wsrep_cluster_address = `SELECT @@wsrep_cluster_address`
@@ -36,3 +40,5 @@ SET SESSION wsrep_on=0;
--connection node_2
CALL mtr.add_suppression("WSREP: exception from gcomm, backend must be restarted: Gcomm backend termination was requested by setting gmcast.isolate=2.");
+
+--source suite/galera/include/auto_increment_offset_restore.inc
1
0
17 Jan '19
revision-id: aa6a2c23465173c4b62e9c829b82e3b9cbd96314 (mariadb-10.3.6-318-gaa6a2c23465)
parent(s): 994c25b18b1a8a5658c0f3efa8a4edb899ff55e3
author: Jan Lindström
committer: Jan Lindström
timestamp: 2019-01-17 10:59:55 +0200
message:
Disable tests that were already disabled earlier
galera_as_slave_gtid_replicate_do_db_cc : Requires MySQL GTID
galera.galera_kill_nochanges : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges
galera.galera_split_brain : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges
wsrep_append_foreign_key
Fix compiler warning
wsrep_append_key
ha_innobase::wsrep_append_keys
Fix output formating
wsrep_kill_victim
Remove unnecessary bf_this and unnecessary comparison to bf_other
trx_get_trx_by_xid_callback
Add comment to #endif
modified: mysql-test/suite/galera/disabled.def
modified: storage/innobase/handler/ha_innodb.cc
modified: storage/innobase/lock/lock0lock.cc
modified: storage/innobase/trx/trx0trx.cc
---
mysql-test/suite/galera/disabled.def | 3 +++
storage/innobase/handler/ha_innodb.cc | 10 +++++-----
storage/innobase/lock/lock0lock.cc | 14 +++++---------
storage/innobase/trx/trx0trx.cc | 2 +-
4 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def
index 61d4698180f..cb6c1d05e36 100644
--- a/mysql-test/suite/galera/disabled.def
+++ b/mysql-test/suite/galera/disabled.def
@@ -16,6 +16,7 @@ galera_binlog_rows_query_log_events: MariaDB does not support binlog_rows_query_
galera_migrate : MariaDB does not support START SLAVE USER
galera_as_master_gtid : Requires MySQL GTID
galera_as_master_gtid_change_master : Requires MySQL GTID
+galera_as_slave_gtid_replicate_do_db_cc : Requires MySQL GTID
galera_as_slave_preordered : wsrep-preordered feature not merged to MariaDB
GAL-419 : MDEV-13549 Galera test failures
galera_var_notify_cmd : MDEV-13549 Galera test failures
@@ -58,3 +59,5 @@ galera.galera_kill_largechanges : MDEV-18179 Galera test failure on galera.galer
galera.galera_concurrent_ctas : MDEV-18180 Galera test failure on galera.galera_concurrent_ctas
galera.galera_var_retry_autocommit: MDEV-18181 Galera test failure on galera.galera_var_retry_autocommit
galera.galera_many_tables_nopk : MDEV-18182 Galera test failure on galera.galera_many_tables_nopk
+galera.galera_kill_nochanges : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges
+galera.galera_split_brain : MDEV-18280 Galera test failure on galera_split_brain and galera_kill_nochanges
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index f18ab5ecdb3..e194c47a518 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -10283,7 +10283,7 @@ wsrep_append_foreign_key(
if (rcode != DB_SUCCESS) {
WSREP_ERROR(
"FK key set failed: " ULINTPF
- " (" ULINTPF " " ULINTPF "%s), index: %s %s, %s",
+ " (" ULINTPF "%s), index: %s %s, %s",
rcode, referenced, wsrep_key_type_to_str(key_type),
(index) ? index->name() : "void index",
(index && index->table) ? index->table->name.m_name :
@@ -10364,9 +10364,9 @@ wsrep_append_key(
("thd: %lu trx: %lld", thd_get_thread_id(thd),
(long long)trx->id));
#ifdef WSREP_DEBUG_PRINT
- fprintf(stderr, "%s conn %lu, trx %llu, keylen %d, key %s.%s\n",
+ fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", keylen %d, key %s.%s\n",
wsrep_key_type_to_str(key_type),
- thd_get_thread_id(thd), (long long)trx->id, key_len,
+ thd_get_thread_id(thd), trx->id, key_len,
table_share->table_name.str, key);
for (int i=0; i<key_len; i++) {
fprintf(stderr, "%hhX, ", key[i]);
@@ -10448,9 +10448,9 @@ ha_innobase::wsrep_append_keys(
trx_t *trx = thd_to_trx(thd);
#ifdef WSREP_DEBUG_PRINT
- fprintf(stderr, "%s conn %lu, trx %llu, table %s\nSQL: %s\n",
+ fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", table %s\nSQL: %s\n",
wsrep_key_type_to_str(key_type),
- thd_get_thread_id(thd), (long long)trx->id,
+ thd_get_thread_id(thd), trx->id,
table_share->table_name.str, wsrep_thd_query(thd));
#endif
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc
index c3de4e4f732..f8003157351 100644
--- a/storage/innobase/lock/lock0lock.cc
+++ b/storage/innobase/lock/lock0lock.cc
@@ -1095,15 +1095,15 @@ wsrep_kill_victim(
return;
}
- my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE);
- if (!bf_this) return;
+ if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
+ return;
+ }
my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE);
if ((!bf_other) ||
- (bf_other && wsrep_thd_order_before(
+ (wsrep_thd_order_before(
trx->mysql_thd, lock->trx->mysql_thd))) {
- ut_ad(bf_this);
if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) {
if (wsrep_debug) {
@@ -1113,11 +1113,7 @@ wsrep_kill_victim(
is in the queue*/
} else if (lock->trx != trx) {
if (wsrep_log_conflicts) {
- if (bf_this) {
- ib::info() << "*** Priority TRANSACTION:";
- } else {
- ib::info() << "*** Victim TRANSACTION:";
- }
+ ib::info() << "*** Priority TRANSACTION:";
trx_print_latched(stderr, trx, 3000);
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index d222e3f017c..7be760c6221 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -2152,7 +2152,7 @@ static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element,
transaction needs a valid trx->xid for
invoking trx_sys_update_wsrep_checkpoint(). */
if (!wsrep_is_wsrep_xid(trx->xid))
-#endif
+#endif /* WITH_WSREP */
/* Invalidate the XID, so that subsequent calls will not find it. */
trx->xid->null();
arg->trx= trx;
1
0