mirror of
https://github.com/MariaDB/server.git
synced 2025-08-05 13:16:09 +03:00
MDEV-34888 Implement SEMIJOIN() and SUBQUERY() hints
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
#include "simple_parser.h"
|
||||
|
||||
class st_select_lex;
|
||||
class Opt_hints_qb;
|
||||
|
||||
/**
|
||||
Environment data for the name resolution phase
|
||||
@@ -74,6 +75,14 @@ public:
|
||||
keyword_MRR,
|
||||
keyword_QB_NAME,
|
||||
keyword_MAX_EXECUTION_TIME,
|
||||
keyword_SEMIJOIN,
|
||||
keyword_NO_SEMIJOIN,
|
||||
keyword_SUBQUERY,
|
||||
keyword_MATERIALIZATION,
|
||||
keyword_FIRSTMATCH,
|
||||
keyword_LOOSESCAN,
|
||||
keyword_DUPSWEEDOUT,
|
||||
keyword_INTOEXISTS,
|
||||
|
||||
// Other token types
|
||||
tIDENT,
|
||||
@@ -250,6 +259,12 @@ private:
|
||||
using TOKEN::TOKEN;
|
||||
};
|
||||
|
||||
class Keyword_SUBQUERY: public TOKEN<Parser, TokenID::keyword_SUBQUERY>
|
||||
{
|
||||
public:
|
||||
using TOKEN::TOKEN;
|
||||
};
|
||||
|
||||
class Identifier: public TOKEN<Parser, TokenID::tIDENT>
|
||||
{
|
||||
public:
|
||||
@@ -344,10 +359,8 @@ private:
|
||||
using TokenChoice::TokenChoice;
|
||||
};
|
||||
|
||||
|
||||
// Identifiers of various kinds
|
||||
|
||||
|
||||
// query_block_name ::= identifier
|
||||
class Query_block_name: public Identifier
|
||||
{
|
||||
@@ -599,25 +612,230 @@ public:
|
||||
|
||||
bool resolve(Parse_context *pc) const;
|
||||
void append_args(THD *thd, String *str) const;
|
||||
ulong get_milliseconds() const;
|
||||
ulonglong get_milliseconds() const;
|
||||
};
|
||||
|
||||
// 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:
|
||||
Opt_hints_qb* resolve_for_qb_name(Parse_context *pc, bool hint_state,
|
||||
const Lex_ident_sys *qb_name) const;
|
||||
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) 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;
|
||||
Opt_hints_qb* resolve_for_qb_name(Parse_context *pc, TokenID token_id,
|
||||
const Lex_ident_sys *qb_name) const;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
hint ::= index_level_hint
|
||||
| table_level_hint
|
||||
| qb_name_hint
|
||||
| statement_level_hint
|
||||
| max_execution_time_hint
|
||||
| semijoin_hint
|
||||
| subquery_hint
|
||||
*/
|
||||
class Hint: public OR4<Parser,
|
||||
class Hint: public OR6<Parser,
|
||||
Index_level_hint,
|
||||
Table_level_hint,
|
||||
Qb_name_hint,
|
||||
Max_execution_time_hint>
|
||||
Max_execution_time_hint,
|
||||
Semijoin_hint,
|
||||
Subquery_hint>
|
||||
{
|
||||
public:
|
||||
using OR4::OR4;
|
||||
};
|
||||
using OR6::OR6;
|
||||
|
||||
/**
|
||||
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... ]
|
||||
@@ -630,6 +848,7 @@ private:
|
||||
size_t count() const { return elements; }
|
||||
};
|
||||
|
||||
|
||||
class Hint_list: public LIST<Parser, Hint_list_container,
|
||||
Hint, TokenID::tNULL/*not separated list*/, 1>
|
||||
{
|
||||
@@ -649,12 +868,11 @@ public:
|
||||
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++)
|
||||
*/
|
||||
@@ -664,5 +882,4 @@ public:
|
||||
using Hints::Hints;
|
||||
};
|
||||
|
||||
|
||||
#endif // OPT_HINTS_PARSER
|
||||
|
Reference in New Issue
Block a user