From a1ea633a192669bc89d30bd6b799a2c737fa5e61 Mon Sep 17 00:00:00 2001 From: Gagan Goel Date: Fri, 25 Sep 2020 01:29:21 -0400 Subject: [PATCH] MCOL-4282 Follow up version 2. Mutate the optimizer flags for prepared statements in: 1. ha_mcs::open 2. ha_mcs::discover_check_version This is done to ensure the optimizer flags are disabled before JOIN::prepare() is called during "PREPARE stmt FROM ...". --- dbcon/mysql/ha_mcs.cpp | 29 +++++++++++++++++++++++++++++ dbcon/mysql/ha_mcs.h | 14 ++++++++++++++ dbcon/mysql/ha_mcs_pushdown.cpp | 10 ++++++++-- 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/dbcon/mysql/ha_mcs.cpp b/dbcon/mysql/ha_mcs.cpp index 7f8f51b40..1072b9099 100644 --- a/dbcon/mysql/ha_mcs.cpp +++ b/dbcon/mysql/ha_mcs.cpp @@ -220,6 +220,20 @@ int ha_mcs::open(const char* name, int mode, uint32_t test_if_locked) { DBUG_ENTER("ha_mcs::open"); + bool isPS = current_thd->stmt_arena && + (current_thd->stmt_arena->is_stmt_prepare() || + current_thd->stmt_arena->is_stmt_execute()); + + // MCOL-4282 See the description for discover_check_version() in ha_mcs.h + // for why we need to mutate optimizer flags here. Sequence of SQL + // statements that will lead to this execution path for prepared + // statements: + // CREATE TABLE t1 (a int, b int) engine=columnstore; + // PREPARE stmt1 FROM "SELECT * FROM t1"; + // EXECUTE stmt1; + if (isPS) + mutate_optimizer_flags(current_thd); + int rc; try { @@ -234,6 +248,17 @@ int ha_mcs::open(const char* name, int mode, uint32_t test_if_locked) DBUG_RETURN(rc); } +int ha_mcs::discover_check_version() +{ + bool isPS = current_thd->stmt_arena && + (current_thd->stmt_arena->is_stmt_prepare() || + current_thd->stmt_arena->is_stmt_execute()); + + if (isPS) + mutate_optimizer_flags(current_thd); + + return 0; +} /** @brief @@ -1096,6 +1121,10 @@ int ha_mcs::reset() condStack.clear(); } + // Restore the optimizer flags which were mutated earlier in + // ha_mcs::open/ha_mcs::discover_check_version + restore_optimizer_flags(current_thd); + DBUG_RETURN(0); } diff --git a/dbcon/mysql/ha_mcs.h b/dbcon/mysql/ha_mcs.h index 9de1f8478..b44bb87ae 100644 --- a/dbcon/mysql/ha_mcs.h +++ b/dbcon/mysql/ha_mcs.h @@ -138,6 +138,20 @@ public: */ int open(const char* name, int mode, uint32_t test_if_locked); // required + // MCOL-4282 This function is called by open_tables in sql_base.cc. + // We mutate the optimizer flags here for prepared statements as this + // handler function is called before JOIN::prepare, and we need to + // disable the default optimizer flags before JOIN::prepare (which is + // called during "PREPARE stmt FROM ..." SQL) is called. + // Sequence of SQL statements that will lead to this execution path + // for prepared statements: + // CREATE TABLE t1 (a int, b int) engine=columnstore; + // INSERT INTO t1 VALUES (1, 2), (2, 4), (3, 1); + // PREPARE stmt1 FROM "SELECT * FROM t1"; + // EXECUTE stmt1; + + int discover_check_version() override; + /** @brief We implement this in ha_example.cc; it's a required method. */ diff --git a/dbcon/mysql/ha_mcs_pushdown.cpp b/dbcon/mysql/ha_mcs_pushdown.cpp index 4b098eaed..ca6d52a11 100644 --- a/dbcon/mysql/ha_mcs_pushdown.cpp +++ b/dbcon/mysql/ha_mcs_pushdown.cpp @@ -47,10 +47,16 @@ void mutate_optimizer_flags(THD *thd_) // MCOL-2178 Disable all optimizer flags as it was in the fork. // CS restores it later in SH::scan_end() and in case of an error // in SH::scan_init() - set_original_optimizer_flags(thd_->variables.optimizer_switch, thd_); - thd_->variables.optimizer_switch = OPTIMIZER_SWITCH_IN_TO_EXISTS | + + ulonglong flags_to_set = OPTIMIZER_SWITCH_IN_TO_EXISTS | OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING; + + if (thd_->variables.optimizer_switch == flags_to_set) + return; + + set_original_optimizer_flags(thd_->variables.optimizer_switch, thd_); + thd_->variables.optimizer_switch = flags_to_set; } void restore_optimizer_flags(THD *thd_)