Commit ce18ab4b authored by Oleg Smirnov's avatar Oleg Smirnov

MDEV-34888 Implement SEMIJOIN() and SUBQUERY() hints

parent c8ce9fbb
This diff is collapsed.
CREATE TABLE t1 (a INTEGER NOT NULL, b INT, PRIMARY KEY (a));
CREATE TABLE t2 (a INTEGER NOT NULL, KEY (a));
CREATE TABLE t3 (a INTEGER NOT NULL, b INT, KEY (a));
INSERT INTO t1 VALUES (1,10), (2,20), (3,30), (4,40);
INSERT INTO t2 VALUES (2), (3), (4), (5);
INSERT INTO t3 VALUES (10,3), (20,4), (30,5);
ANALYZE TABLE t1, t2, t3;
--echo # WIP:
--echo # Parser tests
--echo # Correct hints (no warnings):
EXPLAIN EXTENDED
SELECT /*+ SEMIJOIN() */ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ QB_NAME(qb1) SEMIJOIN(@qb1) */ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ QB_NAME(qb1) NO_SEMIJOIN(@qb1 firstmatch) */ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ QB_NAME(qb1) SEMIJOIN( @qb1 firstmatch, dupsweedout ) */ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ NO_SEMIJOIN( FIRSTMATCH, LOOSESCAN,materialization, DUPSWEEDOUT ) */ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ QB_NAME(qb2) NO_SEMIJOIN(@qb2 FIRSTMATCH,LOOSESCAN, materialization, DUPSWEEDOUT) */ a FROM t1;
set optimizer_switch='derived_merge=off';
--echo # Correct 'cause hints refer to different query blocks:
EXPLAIN EXTENDED
SELECT /*+ SEMIJOIN(@qb1) SEMIJOIN(loosescan)*/ a
FROM (SELECT /*+ QB_NAME(qb1)*/ * FROM t2) AS tt;
EXPLAIN EXTENDED
SELECT /*+ SEMIJOIN()*/ a
FROM (SELECT /*+ SEMIJOIN(loosescan)*/ * FROM t2) AS tt;
EXPLAIN EXTENDED
SELECT /*+ SUBQUERY(materialization) */ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ SUBQUERY( INTOEXISTS ) */ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ QB_NAME (qb1) SUBQUERY(@qb1 materialization) */ a FROM t1;
--echo # Incorrect hints (warnings)
SELECT /*+ SEMIJOIN(loosescan @qb1) */ a FROM t1;
SELECT /*+ SEMIJOIN(@qb1 @qb2) */ a FROM t1;
SELECT /*+ SEMIJOIN(@qb1 LOOSESCAN,materialization, unknown_strategy) */ a FROM t1;
SELECT /*+ NO_SEMIJOIN(@qb1, @qb2) */ a FROM t1;
SELECT /*+ NO_SEMIJOIN(FIRSTMATCH, ,LOOSESCAN, materialization) */ a FROM t1;
SELECT /*+ NO_SEMIJOIN(FIRSTMATCH, @qb2,LOOSESCAN) */ a FROM t1;
SELECT /*+ SUBQUERY(wrong_strat) */ a FROM t1;
SELECT /*+ SUBQUERY(materialization, intoexists) */ a FROM t1;
SELECT /*+ SUBQUERY(@qb1 materialization) */ a FROM t1;
SELECT /*+ SUBQUERY() */ a FROM t1;
--echo # Mix of correct and incorrect hints:
EXPLAIN EXTENDED
SELECT /*+ SEMIJOIN(firstmatch ) SEMIJOIN(loosescan @qb1) */ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ NO_SEMIJOIN(@qb1, @qb2) SEMIJOIN()*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ NO_SEMIJOIN() NO_SEMIJOIN(FIRSTMATCH, @qb2,LOOSESCAN) */ a FROM t1;
--echo # Conflicting hints:
EXPLAIN EXTENDED
SELECT /*+ SEMIJOIN() SEMIJOIN(dupsweedout) NO_SEMIJOIN(firstmatch)*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ SEMIJOIN(loosescan,materialization) SEMIJOIN(dupsweedout)*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ NO_SEMIJOIN(firstmatch,loosescan,materialization) SEMIJOIN() NO_SEMIJOIN()*/ a
FROM t1;
EXPLAIN EXTENDED
SELECT /*+ QB_NAME(qb1) SEMIJOIN(@qb1) SEMIJOIN(loosescan) NO_SEMIJOIN(@qb1 dupsweedout)*/ a
FROM t1;
EXPLAIN EXTENDED SELECT /*+ SEMIJOIN(firstmatch) NO_SEMIJOIN()*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ SUBQUERY(materialization) SUBQUERY(intoexists)*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ SEMIJOIN() SUBQUERY(materialization) SUBQUERY(intoexists)*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ SUBQUERY(materialization) SUBQUERY(intoexists)*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ SUBQUERY(materialization) SUBQUERY(intoexists) SUBQUERY(materialization)*/ a
FROM t1;
EXPLAIN EXTENDED
SELECT /*+ SUBQUERY(materialization) SEMIJOIN(firstmatch) SUBQUERY(intoexists)*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ QB_NAME(qb1) SEMIJOIN(@qb1) SUBQUERY(@qb1 materialization) SUBQUERY(intoexists)*/ a FROM t1;
EXPLAIN EXTENDED
SELECT /*+ QB_NAME(qb1) SUBQUERY(@qb1 materialization) SEMIJOIN(@qb1 firstmatch) SUBQUERY(intoexists)*/ a FROM t1;
set optimizer_switch='derived_merge=off';
EXPLAIN EXTENDED
SELECT /*+ SEMIJOIN(@qb1) SEMIJOIN(loosescan) NO_SEMIJOIN(@qb1 dupsweedout)*/ a
FROM (SELECT /*+ QB_NAME(qb1)*/ * FROM t2) AS tt;
DROP TABLE t1,t2,t3;
This diff is collapsed.
......@@ -30,6 +30,7 @@
#include "sql_bitmap.h"
#include "sql_show.h"
#include "mysqld_error.h"
#include "opt_hints_parser.h"
struct LEX;
......@@ -48,7 +49,9 @@ enum opt_hints_enum
MRR_HINT_ENUM,
NO_RANGE_HINT_ENUM,
QB_NAME_HINT_ENUM,
MAX_HINT_ENUM
SEMIJOIN_HINT_ENUM,
SUBQUERY_HINT_ENUM,
MAX_HINT_ENUM // This one must be the last in the list
};
......@@ -261,6 +264,13 @@ class Opt_hints : public Sql_alloc
void check_unresolved(THD *thd);
virtual void append_name(THD *thd, String *str)= 0;
/**
Append additional hint arguments to the printed string if they exist.
For example, SEMIJOIN and SUBQUERY hints may have a list of strategies
as additional arguments
*/
virtual void append_args(THD *thd, String *str) const {}
virtual ~Opt_hints() {}
private:
......@@ -316,7 +326,6 @@ class Opt_hints_qb : public Opt_hints
char buff[32]; // Buffer to hold sys name
public:
Opt_hints_qb(Opt_hints *opt_hints_arg,
MEM_ROOT *mem_root_arg,
uint select_number_arg);
......@@ -354,6 +363,14 @@ class Opt_hints_qb : public Opt_hints
append_identifier(thd, str, &print_name);
}
virtual void append_args(THD *thd, String *str) const override
{
if (semijoin_hint)
semijoin_hint->append_args(thd, str);
if (subquery_hint)
subquery_hint->append_args(thd, str);
}
/**
Function finds Opt_hints_table object corresponding to
table alias in the query block and attaches corresponding
......@@ -367,6 +384,17 @@ class Opt_hints_qb : public Opt_hints
*/
Opt_hints_table *adjust_table_hints(TABLE *table,
const Lex_ident_table &alias);
const Optimizer_hint_parser::Semijoin_hint* semijoin_hint= nullptr;
/*
Bitmap of strategies listed in the SEMIJOIN/NO_SEMIJOIN hint body, e.g.
FIRSTMATCH | LOOSESCAN
*/
uint semijoin_strategies_map= 0;
const Optimizer_hint_parser::Subquery_hint *subquery_hint= nullptr;
uint subquery_strategy= 0;
};
......
......@@ -57,6 +57,37 @@ Optimizer_hint_tokenizer::find_keyword(const LEX_CSTRING &str)
return TokenID::keyword_QB_NAME;
break;
case 8:
if ("SEMIJOIN"_Lex_ident_column.streq(str))
return TokenID::keyword_SEMIJOIN;
else if ("SUBQUERY"_Lex_ident_column.streq(str))
return TokenID::keyword_SUBQUERY;
break;
case 9:
if ("LOOSESCAN"_Lex_ident_column.streq(str))
return TokenID::keyword_LOOSESCAN;
break;
case 10:
if ("FIRSTMATCH"_Lex_ident_column.streq(str))
return TokenID::keyword_FIRSTMATCH;
else if ("INTOEXISTS"_Lex_ident_column.streq(str))
return TokenID::keyword_INTOEXISTS;
break;
case 11:
if ("NO_SEMIJOIN"_Lex_ident_column.streq(str))
return TokenID::keyword_NO_SEMIJOIN;
else if ("DUPSWEEDOUT"_Lex_ident_column.streq(str))
return TokenID::keyword_DUPSWEEDOUT;
break;
case 15:
if ("MATERIALIZATION"_Lex_ident_column.streq(str))
return TokenID::keyword_MATERIALIZATION;
break;
case 21:
if ("NO_RANGE_OPTIMIZATION"_Lex_ident_column.streq(str))
return TokenID::keyword_NO_RANGE_OPTIMIZATION;
......@@ -201,3 +232,16 @@ Optimizer_hint_parser::
*pe= std::move(elem);
return push_back(pe, p->m_thd->mem_root);
}
bool
Optimizer_hint_parser::
Semijoin_strategy_list_container::add(Optimizer_hint_parser *p,
Semijoin_strategy &&elem)
{
Semijoin_strategy *pe= (Semijoin_strategy*) p->m_thd->alloc(sizeof(*pe));
if (!pe)
return true;
*pe= std::move(elem);
return push_back(pe, p->m_thd->mem_root);
}
......@@ -25,6 +25,7 @@
#include "simple_parser.h"
class st_select_lex;
class Opt_hints_qb;
/**
Environment data for the name resolution phase
......@@ -72,6 +73,14 @@ class Optimizer_hint_tokenizer: public Extended_string_tokenizer
keyword_NO_RANGE_OPTIMIZATION,
keyword_MRR,
keyword_QB_NAME,
keyword_SEMIJOIN,
keyword_NO_SEMIJOIN,
keyword_SUBQUERY,
keyword_MATERIALIZATION,
keyword_FIRSTMATCH,
keyword_LOOSESCAN,
keyword_DUPSWEEDOUT,
keyword_INTOEXISTS,
// Other token types
tIDENT
......@@ -240,6 +249,12 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
using TOKEN::TOKEN;
};
class Keyword_SUBQUERY: public TOKEN<PARSER, TokenID::keyword_SUBQUERY>
{
public:
using TOKEN::TOKEN;
};
class Identifier: public TOKEN<PARSER, TokenID::tIDENT>
{
public:
......@@ -312,10 +327,8 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
using TokenChoice::TokenChoice;
};
// Identifiers of various kinds
// query_block_name ::= identifier
class Query_block_name: public Identifier
{
......@@ -554,21 +567,224 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
};
// semijoin_hint_type ::= SEMIJOIN | NO_SEMIJOIN
class Semijoin_hint_type_cond
{
public:
static bool allowed_token_id(TokenID id)
{
return id == TokenID::keyword_SEMIJOIN ||
id == TokenID::keyword_NO_SEMIJOIN;
}
};
class Semijoin_hint_type: public TokenChoice<PARSER,
Semijoin_hint_type_cond>
{
public:
using TokenChoice::TokenChoice;
};
// semijoin_strategy ::= MATERIALIZATION | FIRSTMATCH | LOOSESCAN | DUPSWEEDOUT
class Semijoin_strategy_cond
{
public:
static bool allowed_token_id(TokenID id)
{
return id == TokenID::keyword_MATERIALIZATION ||
id == TokenID::keyword_FIRSTMATCH ||
id == TokenID::keyword_LOOSESCAN ||
id == TokenID::keyword_DUPSWEEDOUT;
}
};
class Semijoin_strategy: public TokenChoice<PARSER, Semijoin_strategy_cond>
{
public:
using TokenChoice::TokenChoice;
};
/*
strategy_list ::= strategy_name [ {, strategy_name }... ]
opt_strategy_list ::= [ strategy_list ]
*/
class Semijoin_strategy_list_container: public List<Semijoin_strategy>
{
public:
Semijoin_strategy_list_container()
{ }
bool add(Optimizer_hint_parser *p, Semijoin_strategy &&strategy);
size_t count() const { return elements; }
};
class Opt_sj_strategy_list: public LIST<PARSER,
Semijoin_strategy_list_container,
Semijoin_strategy, TokenID::tCOMMA, 0>
{
public:
using LIST::LIST;
};
class Hint_param_opt_sj_strategy_list: public LIST<PARSER,
Semijoin_strategy_list_container,
Semijoin_strategy, TokenID::tCOMMA, 0>
{
public:
using LIST::LIST;
};
/*
at_query_block_name_opt_strategies_list ::=
@ query_block_name opt_strategies_list
*/
class At_query_block_name_opt_strategy_list: public AND2<
PARSER,
At_query_block_name,
Opt_sj_strategy_list>
{
public:
using AND2::AND2;
};
/*
semijoin_hint_body: @ query_block_name opt_sj_strategy_list
| opt_sj_strategy_list
*/
class Semijoin_hint_body: public OR2<PARSER,
At_query_block_name_opt_strategy_list,
Hint_param_opt_sj_strategy_list>
{
public:
using OR2::OR2;
};
public:
/*
semijoin_hint ::= semijoin_hint_type ( semijoin_hint_body )
*/
class Semijoin_hint: public AND4<PARSER,
Semijoin_hint_type,
LParen,
Semijoin_hint_body,
RParen>
{
public:
using AND4::AND4;
bool resolve(Parse_context *pc) const;
void append_args(THD *thd, String *str) const;
private:
void fill_strategies_map(Opt_hints_qb *qb) const;
void add_strategy_to_map(TokenID token_id, Opt_hints_qb *qb) const;
void append_strategy_name(TokenID token_id, String *str,
int& appended_count) const;
};
private:
// subquery_strategy ::= MATERIALIZATION | INTOEXISTS
class Subquery_strategy_cond
{
public:
static bool allowed_token_id(TokenID id)
{
return id == TokenID::keyword_MATERIALIZATION ||
id == TokenID::keyword_INTOEXISTS;
}
};
class Subquery_strategy: public TokenChoice<PARSER, Subquery_strategy_cond>
{
public:
using TokenChoice::TokenChoice;
};
class Hint_param_subquery_strategy: public TokenChoice<PARSER,
Subquery_strategy_cond>
{
public:
using TokenChoice::TokenChoice;
};
/*
at_query_block_name_subquery_strategy ::=
@ query_block_name subquery_strategy
*/
class At_query_block_name_subquery_strategy: public AND2<
PARSER,
At_query_block_name,
Subquery_strategy>
{
public:
using AND2::AND2;
};
/*
subquery_hint_body: @ query_block_name subquery_strategy
| subquery_strategy
*/
class Subquery_hint_body: public OR2<PARSER,
At_query_block_name_subquery_strategy,
Hint_param_subquery_strategy>
{
public:
using OR2::OR2;
};
public:
// subquery_hint ::= SUBQUERY( subquery_hint_body )
class Subquery_hint: public AND4<PARSER,
Keyword_SUBQUERY,
LParen,
Subquery_hint_body,
RParen>
{
public:
using AND4::AND4;
bool resolve(Parse_context *pc) const;
void append_args(THD *thd, String *str) const;
private:
void set_subquery_strategy(TokenID token_id, Opt_hints_qb *qb) const;
};
/*
hint ::= index_level_hint
| table_level_hint
| qb_name_hint
| qb_level_hint
*/
class Hint: public OR3<PARSER,
class Hint: public OR5<PARSER,
Index_level_hint,
Table_level_hint,
Qb_name_hint>
Qb_name_hint,
Semijoin_hint,
Subquery_hint>
{
public:
using OR3::OR3;
};
using OR5::OR5;
/**
Append additional hint arguments to the printed string.
Implement this method in Hint specifications if needed:
Table_level_hint, Semijoin_hint, etc
@param thd Pointer to THD object
@param str Pointer to String object
*/
void append_args(THD *thd, String *str) const {}
};
private:
// hint_list ::= hint [ hint... ]
class Hint_list_container: public List<Hint>
{
......@@ -579,6 +795,7 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
size_t count() const { return elements; }
};
class Hint_list: public LIST<PARSER, Hint_list_container,
Hint, TokenID::tNULL/*not separated list*/, 1>
{
......@@ -598,12 +815,11 @@ class Optimizer_hint_parser: public Optimizer_hint_tokenizer,
public:
using AND2::AND2;
};
};
/*
This wrapper class is needed to use a forward declaration in sql_lex.h
These wrapper class is needed to use a forward declarations in sql_lex.h
instead of including the entire opt_hints_parser.h.
(forward declarations of qualified nested classes are not possible in C++)
*/
......@@ -613,5 +829,4 @@ class Optimizer_hint_parser_output: public Optimizer_hint_parser::Hints
using Hints::Hints;
};
#endif // OPT_HINTS_PARSER
......@@ -442,6 +442,92 @@ class Parser_templates
};
/*
A rule consisting of a choice of four rules:
rule ::= rule1 | rule2 | rule3 | rule4
For the case when the four branches have incompatible storage
*/
template<class PARSER, class A, class B, class C, class D>
class OR4: public A, public B, public C, public D
{
public:
OR4()
{ }
OR4(OR4 &&rhs)
:A(std::move(static_cast<A&&>(rhs))),
B(std::move(static_cast<B&&>(rhs))),
C(std::move(static_cast<C&&>(rhs))),
D(std::move(static_cast<D&&>(rhs)))
{ }
OR4 & operator=(OR4 &&rhs)
{
A::operator=(std::move(static_cast<A&&>(rhs)));
B::operator=(std::move(static_cast<B&&>(rhs)));
C::operator=(std::move(static_cast<C&&>(rhs)));
D::operator=(std::move(static_cast<D&&>(rhs)));
return *this;
}
OR4(PARSER *p)
:A(p),
B(A::operator bool() ? B() : B(p)),
C(A::operator bool() || B::operator bool() ? C() : C(p)),
D(A::operator bool() || B::operator bool() || C::operator bool() ?
D() : D(p))
{
DBUG_ASSERT(!operator bool() || !p->is_error());
}
operator bool() const
{
return A::operator bool() || B::operator bool() || C::operator bool() ||
D::operator bool();
}
};
/*
A rule consisting of a choice of five rules:
rule ::= rule1 | rule2 | rule3 | rule4 | rule5
*/
template<class PARSER, class A, class B, class C, class D, class E>
class OR5: public A, public B, public C, public D, public E
{
public:
OR5()
{ }
OR5(OR5 &&rhs)
:A(std::move(static_cast<A&&>(rhs))),
B(std::move(static_cast<B&&>(rhs))),
C(std::move(static_cast<C&&>(rhs))),
D(std::move(static_cast<D&&>(rhs))),
E(std::move(static_cast<E&&>(rhs)))
{ }
OR5 & operator=(OR5 &&rhs)
{
A::operator=(std::move(static_cast<A&&>(rhs)));
B::operator=(std::move(static_cast<B&&>(rhs)));
C::operator=(std::move(static_cast<C&&>(rhs)));
D::operator=(std::move(static_cast<D&&>(rhs)));
E::operator=(std::move(static_cast<E&&>(rhs)));
return *this;
}
OR5(PARSER *p)
:A(p),
B(A::operator bool() ? B() : B(p)),
C(A::operator bool() || B::operator bool() ? C() : C(p)),
D(A::operator bool() || B::operator bool() || C::operator bool() ?
D() : D(p)),
E(A::operator bool() || B::operator bool() || C::operator bool() ||
D::operator bool() ? E() : E(p))
{
DBUG_ASSERT(!operator bool() || !p->is_error());
}
operator bool() const
{
return A::operator bool() || B::operator bool() || C::operator bool() ||
D::operator bool() || E::operator bool();
}
};
/*
A list with at least MIN_COUNT elements (typlically 0 or 1),
with or without a token separator between elements:
......
......@@ -140,41 +140,47 @@
#define OPTIMIZER_SWITCH_DERIVED_WITH_KEYS (1ULL << 7)
#define OPTIMIZER_SWITCH_FIRSTMATCH (1ULL << 8)
#define OPTIMIZER_SWITCH_LOOSE_SCAN (1ULL << 9)
#define OPTIMIZER_SWITCH_MATERIALIZATION (1ULL << 10)
#define OPTIMIZER_SWITCH_IN_TO_EXISTS (1ULL << 11)
#define OPTIMIZER_SWITCH_SEMIJOIN (1ULL << 12)
#define OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE (1ULL << 13)
#define OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN (1ULL << 14)
#define OPTIMIZER_SWITCH_SUBQUERY_CACHE (1ULL << 15)
/*
The following switch is not controlled by optimizer_switch variable,
it is used internally for processing of SEMIJOIN() and NO_SEMIJOIN() hints
OLEGS: actually it's possible to set at optimizer_switch
*/
#define OPTIMIZER_SWITCH_DUPSWEEDOUT (1ULL << 10)
#define OPTIMIZER_SWITCH_MATERIALIZATION (1ULL << 11)
#define OPTIMIZER_SWITCH_IN_TO_EXISTS (1ULL << 12)
#define OPTIMIZER_SWITCH_SEMIJOIN (1ULL << 13)
#define OPTIMIZER_SWITCH_PARTIAL_MATCH_ROWID_MERGE (1ULL << 14)
#define OPTIMIZER_SWITCH_PARTIAL_MATCH_TABLE_SCAN (1ULL << 15)
#define OPTIMIZER_SWITCH_SUBQUERY_CACHE (1ULL << 16)
/** If this is off, MRR is never used. */
#define OPTIMIZER_SWITCH_MRR (1ULL << 16)
#define OPTIMIZER_SWITCH_MRR (1ULL << 17)
/**
If OPTIMIZER_SWITCH_MRR is on and this is on, MRR is used depending on a
cost-based choice ("automatic"). If OPTIMIZER_SWITCH_MRR is on and this is
off, MRR is "forced" (i.e. used as long as the storage engine is capable of
doing it).
*/
#define OPTIMIZER_SWITCH_MRR_COST_BASED (1ULL << 17)
#define OPTIMIZER_SWITCH_MRR_SORT_KEYS (1ULL << 18)
#define OPTIMIZER_SWITCH_OUTER_JOIN_WITH_CACHE (1ULL << 19)
#define OPTIMIZER_SWITCH_SEMIJOIN_WITH_CACHE (1ULL << 20)
#define OPTIMIZER_SWITCH_JOIN_CACHE_INCREMENTAL (1ULL << 21)
#define OPTIMIZER_SWITCH_JOIN_CACHE_HASHED (1ULL << 22)
#define OPTIMIZER_SWITCH_JOIN_CACHE_BKA (1ULL << 23)
#define OPTIMIZER_SWITCH_OPTIMIZE_JOIN_BUFFER_SIZE (1ULL << 24)
#define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1ULL << 25)
#define OPTIMIZER_SWITCH_EXTENDED_KEYS (1ULL << 26)
#define OPTIMIZER_SWITCH_EXISTS_TO_IN (1ULL << 27)
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 28)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 29)
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 30)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 31)
#define OPTIMIZER_SWITCH_USE_ROWID_FILTER (1ULL << 32)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING (1ULL << 33)
#define OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN (1ULL << 34)
#define OPTIMIZER_SWITCH_HASH_JOIN_CARDINALITY (1ULL << 35)
#define OPTIMIZER_SWITCH_CSET_NARROWING (1ULL << 36)
#define OPTIMIZER_SWITCH_SARGABLE_CASEFOLD (1ULL << 37)
#define OPTIMIZER_SWITCH_MRR_COST_BASED (1ULL << 18)
#define OPTIMIZER_SWITCH_MRR_SORT_KEYS (1ULL << 19)
#define OPTIMIZER_SWITCH_OUTER_JOIN_WITH_CACHE (1ULL << 20)
#define OPTIMIZER_SWITCH_SEMIJOIN_WITH_CACHE (1ULL << 21)
#define OPTIMIZER_SWITCH_JOIN_CACHE_INCREMENTAL (1ULL << 22)
#define OPTIMIZER_SWITCH_JOIN_CACHE_HASHED (1ULL << 23)
#define OPTIMIZER_SWITCH_JOIN_CACHE_BKA (1ULL << 24)
#define OPTIMIZER_SWITCH_OPTIMIZE_JOIN_BUFFER_SIZE (1ULL << 25)
#define OPTIMIZER_SWITCH_TABLE_ELIMINATION (1ULL << 26)
#define OPTIMIZER_SWITCH_EXTENDED_KEYS (1ULL << 27)
#define OPTIMIZER_SWITCH_EXISTS_TO_IN (1ULL << 28)
#define OPTIMIZER_SWITCH_ORDERBY_EQ_PROP (1ULL << 29)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
#define OPTIMIZER_SWITCH_USE_ROWID_FILTER (1ULL << 33)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING (1ULL << 34)
#define OPTIMIZER_SWITCH_NOT_NULL_RANGE_SCAN (1ULL << 35)
#define OPTIMIZER_SWITCH_HASH_JOIN_CARDINALITY (1ULL << 36)
#define OPTIMIZER_SWITCH_CSET_NARROWING (1ULL << 37)
#define OPTIMIZER_SWITCH_SARGABLE_CASEFOLD (1ULL << 38)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
......@@ -198,6 +204,7 @@
OPTIMIZER_SWITCH_SEMIJOIN | \
OPTIMIZER_SWITCH_FIRSTMATCH | \
OPTIMIZER_SWITCH_LOOSE_SCAN | \
OPTIMIZER_SWITCH_DUPSWEEDOUT | \
OPTIMIZER_SWITCH_EXISTS_TO_IN | \
OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
......
......@@ -2936,7 +2936,7 @@ export const char *optimizer_switch_names[]=
"index_merge_intersection","index_merge_sort_intersection",
"index_condition_pushdown",
"derived_merge", "derived_with_keys",
"firstmatch","loosescan","materialization","in_to_exists","semijoin",
"firstmatch","loosescan","dupsweedout","materialization","in_to_exists","semijoin",
"partial_match_rowid_merge",
"partial_match_table_scan",
"subquery_cache",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment