MDEV-33281 Optimizer hints cleanup: add const specifiers, comments

This commit is contained in:
Sergei Petrunia 2024-09-10 18:59:08 +03:00 committed by Oleg Smirnov
parent cd9ac306c3
commit e4af72bd5d
5 changed files with 113 additions and 35 deletions

View File

@ -685,7 +685,7 @@ bool Optimizer_hint_parser::Qb_name_hint::resolve(Parse_context *pc) const
}
bool Optimizer_hint_parser::Hint_list::resolve(Parse_context *pc)
bool Optimizer_hint_parser::Hint_list::resolve(Parse_context *pc) const
{
if (pc->thd->lex->create_view)
{
@ -699,20 +699,20 @@ bool Optimizer_hint_parser::Hint_list::resolve(Parse_context *pc)
if (!get_qb_hints(pc))
return true;
List_iterator_fast<Optimizer_hint_parser::Hint> li(*this);
while(Optimizer_hint_parser::Hint *hint= li++)
for (Hint_list::const_iterator li= this->cbegin(); li != this->cend(); ++li)
{
if (const Table_level_hint &table_hint= *hint)
const Optimizer_hint_parser::Hint &hint= *li;
if (const Table_level_hint &table_hint= hint)
{
if (table_hint.resolve(pc))
return true;
}
else if (const Index_level_hint &index_hint= *hint)
else if (const Index_level_hint &index_hint= hint)
{
if (index_hint.resolve(pc))
return true;
}
else if (const Qb_name_hint &qb_hint= *hint)
else if (const Qb_name_hint &qb_hint= hint)
{
if (qb_hint.resolve(pc))
return true;

View File

@ -15,7 +15,50 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
Parse tree node classes for optimizer hint syntax
HintsArchitecture
== Parsing ==
Hints have a separate parser, see sql/opt_hint_parser.{h,cc}
The parser is invoked separately for each occurence of
SELECT / *+ hint_body * / ...
in the query. The result of parsing is saved in
SELECT_LEX::parsed_optimizer_hints.
== Hint "resolution" ==
This is done using "resolve" method of parsed data structures
This process
- Creates interpreted hint structures: Opt_hints_global, Opt_hints_qb,
Opt_hints_table, Opt_hints_key.
- Interprets QB_NAME hints and assigns Query Block names.
- Table-level hints are put into their Query Block's Opt_hints_qb object.
- Index-level hints are put into their table's Opt_hints_table object.
== Hint "adjustment" ==
During Name Resolution, setup_tables() calls adjust_table_hints() for each
table and sets TABLE_LIST::opt_hints_table to point to its Opt_hints_table.
== Hint hierarchy ==
Hints have this hierarchy, parent to child:
Opt_hints_global
Opt_hints_qb
Opt_hints_table
Opt_hints_key
For some hints, one needs to check the hint's base object and its parent. For
example, MRR can be disabled on a per-index or a per-table basis.
== How the optimizer checks hints ==
The optimizer checks what hints specify using these calls:
hint_table_state()
hint_table_state_or_fallback()
hint_key_state()
*/

View File

@ -218,29 +218,29 @@ public:
private:
using PARSER= Optimizer_hint_parser; // for a shorter notation
using Parser= Optimizer_hint_parser; // for a shorter notation
// Rules consisting of a single token
class TokenAT: public TOKEN<PARSER, TokenID::tAT>
class TokenAT: public TOKEN<Parser, TokenID::tAT>
{
public:
using TOKEN::TOKEN;
};
class TokenEOF: public TOKEN<PARSER, TokenID::tEOF>
class TokenEOF: public TOKEN<Parser, TokenID::tEOF>
{
public:
using TOKEN::TOKEN;
};
class Keyword_QB_NAME: public TOKEN<PARSER, TokenID::keyword_QB_NAME>
class Keyword_QB_NAME: public TOKEN<Parser, TokenID::keyword_QB_NAME>
{
public:
using TOKEN::TOKEN;
};
class Identifier: public TOKEN<PARSER, TokenID::tIDENT>
class Identifier: public TOKEN<Parser, TokenID::tIDENT>
{
public:
using TOKEN::TOKEN;
@ -258,13 +258,13 @@ private:
}
};
class LParen: public TOKEN<PARSER, TokenID::tLPAREN>
class LParen: public TOKEN<Parser, TokenID::tLPAREN>
{
public:
using TOKEN::TOKEN;
};
class RParen: public TOKEN<PARSER, TokenID::tRPAREN>
class RParen: public TOKEN<Parser, TokenID::tRPAREN>
{
public:
using TOKEN::TOKEN;
@ -285,7 +285,7 @@ private:
id == TokenID::keyword_NO_BNL;
}
};
class Table_level_hint_type: public TokenChoice<PARSER,
class Table_level_hint_type: public TokenChoice<Parser,
Table_level_hint_type_cond>
{
public:
@ -305,7 +305,7 @@ private:
id == TokenID::keyword_NO_MRR;
}
};
class Index_level_hint_type: public TokenChoice<PARSER,
class Index_level_hint_type: public TokenChoice<Parser,
Index_level_hint_type_cond>
{
public:
@ -343,7 +343,7 @@ private:
/*
at_query_block_name ::= @ query_block_name
*/
class At_query_block_name: public AND2<PARSER, TokenAT, Query_block_name>
class At_query_block_name: public AND2<Parser, TokenAT, Query_block_name>
{
public:
using AND2::AND2;
@ -353,7 +353,7 @@ private:
/*
opt_qb_name ::= [ @ query_block_name ]
*/
class Opt_qb_name: public OPT<PARSER, At_query_block_name>
class Opt_qb_name: public OPT<Parser, At_query_block_name>
{
public:
using OPT::OPT;
@ -362,7 +362,7 @@ private:
/*
hint_param_table ::= table_name opt_qb_name
*/
class Hint_param_table: public AND2<PARSER, Table_name, Opt_qb_name>
class Hint_param_table: public AND2<Parser, Table_name, Opt_qb_name>
{
public:
using AND2::AND2;
@ -382,7 +382,7 @@ private:
size_t count() const { return elements; }
};
class Opt_hint_param_table_list: public LIST<PARSER,
class Opt_hint_param_table_list: public LIST<Parser,
Hint_param_table_list_container,
Hint_param_table,
TokenID::tCOMMA, 0>
@ -403,7 +403,7 @@ private:
size_t count() const { return elements; }
};
class Opt_table_name_list: public LIST<PARSER,
class Opt_table_name_list: public LIST<Parser,
Table_name_list_container,
Table_name, TokenID::tCOMMA, 0>
{
@ -425,7 +425,7 @@ private:
size_t count() const { return elements; }
};
class Opt_hint_param_index_list: public LIST<PARSER,
class Opt_hint_param_index_list: public LIST<Parser,
Hint_param_index_list_container,
Hint_param_index,
TokenID::tCOMMA, 0>
@ -439,7 +439,7 @@ private:
hint_param_table_ext ::= hint_param_table
| @ query_block_name table_name
*/
class At_query_block_name_table_name: public AND2<PARSER,
class At_query_block_name_table_name: public AND2<Parser,
At_query_block_name,
Table_name>
{
@ -465,7 +465,7 @@ private:
}
};
class Hint_param_table_ext: public OR2C<PARSER,
class Hint_param_table_ext: public OR2C<Parser,
Hint_param_table_ext_container,
Hint_param_table,
At_query_block_name_table_name>
@ -480,7 +480,7 @@ private:
@ query_block_name opt_table_name_list
*/
class At_query_block_name_opt_table_name_list: public AND2<
PARSER,
Parser,
At_query_block_name,
Opt_table_name_list>
{
@ -494,7 +494,7 @@ private:
| opt_hint_param_table_list
*/
class Table_level_hint_body: public OR2<
PARSER,
Parser,
At_query_block_name_opt_table_name_list,
Opt_hint_param_table_list>
{
@ -503,7 +503,7 @@ private:
};
// table_level_hint ::= table_level_hint_type ( table_level_hint_body )
class Table_level_hint: public AND4<PARSER,
class Table_level_hint: public AND4<Parser,
Table_level_hint_type,
LParen,
Table_level_hint_body,
@ -517,7 +517,7 @@ private:
// index_level_hint_body ::= hint_param_table_ext opt_hint_param_index_list
class Index_level_hint_body: public AND2<PARSER,
class Index_level_hint_body: public AND2<Parser,
Hint_param_table_ext,
Opt_hint_param_index_list>
{
@ -527,7 +527,7 @@ private:
// index_level_hint ::= index_level_hint_type ( index_level_hint_body )
class Index_level_hint: public AND4<PARSER,
class Index_level_hint: public AND4<Parser,
Index_level_hint_type,
LParen,
Index_level_hint_body,
@ -541,7 +541,7 @@ private:
// qb_name_hint ::= QB_NAME ( query_block_name )
class Qb_name_hint: public AND4<PARSER,
class Qb_name_hint: public AND4<Parser,
Keyword_QB_NAME,
LParen,
Query_block_name,
@ -559,7 +559,7 @@ private:
| table_level_hint
| qb_name_hint
*/
class Hint: public OR3<PARSER,
class Hint: public OR3<Parser,
Index_level_hint,
Table_level_hint,
Qb_name_hint>
@ -579,13 +579,13 @@ private:
size_t count() const { return elements; }
};
class Hint_list: public LIST<PARSER, Hint_list_container,
class Hint_list: public LIST<Parser, Hint_list_container,
Hint, TokenID::tNULL/*not separated list*/, 1>
{
public:
using LIST::LIST;
bool resolve(Parse_context *pc);
bool resolve(Parse_context *pc) const;
};
public:
@ -593,7 +593,7 @@ public:
The main rule:
hints ::= hint_list EOF
*/
class Hints: public AND2<PARSER, Hint_list, TokenEOF>
class Hints: public AND2<Parser, Hint_list, TokenEOF>
{
public:
using AND2::AND2;

View File

@ -21,6 +21,41 @@
#include "simple_tokenizer.h"
/*
A set of templates for constructing a recursive-descent LL(1) parser.
One is supposed to define classes corresponding to grammar productions.
The class should inherit from the grammar rule template. For example, a
grammar rule
foo := bar, baz
is implemented with
class Bar ... ; // "bar" is parsed into Bar object
class Baz ... ; // "baz" is parsed into Baz object
// "foo" is parsed into a Foo object.
class Foo: public Parser_templates::AND2<PARSER_Impl, Bar, Baz> {
using AND2::AND2;
...
};
Parsing code is generated by inheriting AND2's constructors with "using" like
shown above. All grammar rule-based classes should also have
- a capability to construct an "empty"(i.e. invalid) object with the default
constructor. This will be invoked when parsing fails.
- operator bool() which returns true if the object is non-empty (i.e. valid)
and false otherwise.
Parsing is done by constructing parser output from the parser object:
Foo parsed_output(parser);
PARSER_Impl here is a class implementing a tokenizer and error condition
storage, like Extended_string_tokenizer.
*/
class Parser_templates
{
protected:

View File

@ -1273,7 +1273,7 @@ public:
/* it is for correct printing SELECT options */
thr_lock_type lock_type;
Optimizer_hint_parser_output *parsed_optimizer_hints;
const Optimizer_hint_parser_output *parsed_optimizer_hints;
/** System Versioning */
int vers_setup_conds(THD *thd, TABLE_LIST *tables);