206 lines
6.7 KiB
C++
206 lines
6.7 KiB
C++
/* Copyright (c) 2018, 2021, Alibaba and/or its affiliates. All rights reserved.
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License, version 2.0,
|
|
as published by the Free Software Foundation.
|
|
This program is also distributed with certain software (including
|
|
but not limited to OpenSSL) that is licensed under separate terms,
|
|
as designated in a particular file or component or in included license
|
|
documentation. The authors of MySQL/PolarDB-X Engine hereby grant you an
|
|
additional permission to link the program and your derivative works with the
|
|
separately licensed software that they have included with
|
|
MySQL/PolarDB-X Engine.
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License, version 2.0, for more details.
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
|
|
#ifndef SQL_OUTLINE_OUTLINE_DIGEST_INCLUDED
|
|
#define SQL_OUTLINE_OUTLINE_DIGEST_INCLUDED
|
|
|
|
#include "sql/error_handler.h"
|
|
#include "sql/outline/outline.h"
|
|
#include "sql/sql_class.h"
|
|
#include "sql/sql_lex.h"
|
|
|
|
namespace im {
|
|
|
|
/**
|
|
Save the current parser context
|
|
|
|
We can safely get statement digest through parser.
|
|
*/
|
|
class Thd_parser_context {
|
|
public:
|
|
Thd_parser_context(THD *thd, const LEX_CSTRING &db)
|
|
: m_thd(thd),
|
|
m_arena(&m_mem_root, Query_arena::STMT_REGULAR_EXECUTION),
|
|
m_backed_up_lex(thd->lex),
|
|
m_saved_parser_state(thd->m_parser_state),
|
|
m_saved_digest(thd->m_digest),
|
|
m_save_db(thd->db()) {
|
|
thd->reset_db(db);
|
|
thd->m_digest = &m_digest_state;
|
|
m_digest_state.reset(thd->m_token_array, get_max_digest_length());
|
|
m_arena.set_query_arena(*thd);
|
|
thd->lex = &m_lex;
|
|
lex_start(thd);
|
|
}
|
|
|
|
~Thd_parser_context() {
|
|
lex_end(&m_lex);
|
|
m_thd->lex = m_backed_up_lex;
|
|
m_thd->set_query_arena(m_arena);
|
|
m_thd->m_parser_state = m_saved_parser_state;
|
|
m_thd->m_digest = m_saved_digest;
|
|
m_thd->reset_db(m_save_db);
|
|
}
|
|
|
|
private:
|
|
THD *m_thd;
|
|
MEM_ROOT m_mem_root;
|
|
Query_arena m_arena;
|
|
LEX *m_backed_up_lex;
|
|
LEX m_lex;
|
|
sql_digest_state m_digest_state;
|
|
Parser_state *m_saved_parser_state;
|
|
sql_digest_state *m_saved_digest;
|
|
LEX_CSTRING m_save_db;
|
|
};
|
|
|
|
/**
|
|
Backup the parser state, it will be used when comsume optimizer hint.
|
|
*/
|
|
class Thd_backup_parser_state {
|
|
public:
|
|
Thd_backup_parser_state(THD * thd)
|
|
: m_thd(thd), m_saved_parser_state(thd->m_parser_state) {}
|
|
|
|
~Thd_backup_parser_state() { m_thd->m_parser_state = m_saved_parser_state; }
|
|
|
|
private:
|
|
THD *m_thd;
|
|
Parser_state *m_saved_parser_state;
|
|
};
|
|
|
|
class Parser_error_handler : public Internal_error_handler {
|
|
public:
|
|
Parser_error_handler(THD * thd) : m_thd(thd) {
|
|
thd->push_internal_handler(this);
|
|
}
|
|
|
|
bool handle_condition(THD *, uint, const char *,
|
|
Sql_condition::enum_severity_level *level,
|
|
const char *message) override {
|
|
// Silence warnings.
|
|
if (*level == Sql_condition::SL_WARNING) return true;
|
|
|
|
if (is_handling) return false;
|
|
|
|
is_handling = true;
|
|
my_error(ER_STATEMENT_DIGEST_PARSE, MYF(0), message);
|
|
is_handling = false;
|
|
return true;
|
|
}
|
|
|
|
virtual ~Parser_error_handler() { m_thd->pop_internal_handler(); }
|
|
|
|
private:
|
|
THD *m_thd;
|
|
/* Avoid infinite recursive call through my_error() */
|
|
bool is_handling = false;
|
|
};
|
|
|
|
/**
|
|
Calculate the offset of the real query in the digest storage.
|
|
|
|
EXPLAIN query is a special case in the calculation of digest. The digest of a
|
|
EXPLAIN query could be used in two different methods:
|
|
|
|
1. Only read the explained query (e.g. "SELECT * FROM t1;" of "EXPLAIN SELECT
|
|
* FORM t1;"). In the invoking of outline, to generate the correct execution
|
|
plan, the digest of the explained query instead of the whole EXPLAIN query is
|
|
needed to look up the outline rules.
|
|
|
|
2. Pass the digest of the whole query to performance schema to distinguish
|
|
EXPLAIN queries and the real queries themselves. For example, The "EXPLAIN"
|
|
token should be kept in the performance schema summary tables to distinguish
|
|
between SELECT query and EXPLAIN query. Otherwise, performance schema would
|
|
keep a wrong number of SELECT query executed and misestimate the performance.
|
|
|
|
@param[in] digest_storage Digest storage
|
|
|
|
@retval strip_length The number of bytes that need to be stripped
|
|
to skip the EXPLAIN token
|
|
*/
|
|
uint calculate_strip_length_for_explain(
|
|
const sql_digest_storage *digest_storage);
|
|
|
|
/**
|
|
Generate statement digest and digest text.
|
|
|
|
@param[in] thd Thread context
|
|
@param[in] db Target db context
|
|
@param[in] query Statement
|
|
@param[in] query_lenth Statement string length
|
|
@param[out] digest Digest hash string
|
|
@param[out] digest_text Digest text string
|
|
@param[out] truncated Whether truncated sql text
|
|
|
|
|
|
@retval true failure
|
|
@retval fase success
|
|
*/
|
|
bool generate_statement_digest(THD *thd, const LEX_CSTRING &db,
|
|
const LEX_CSTRING &query, String *digest,
|
|
String *digest_text, bool *truncated);
|
|
|
|
/**
|
|
Parse the optimizer hint for one query block.
|
|
|
|
@param[in] thd Thread context
|
|
@param[in] hint Optimizer hint
|
|
|
|
@reval hint list Optimizer hint list
|
|
*/
|
|
PT_hint_list *parse_optimizer_hint(THD *thd, LEX_CSTRING &hint);
|
|
/**
|
|
Contextualize the parsed hint list.
|
|
|
|
@param[in] thd Thread context
|
|
@param[in] select_lex Target query block
|
|
*/
|
|
void contextualize_optimizer_hint(THD *thd, SELECT_LEX *select_lex);
|
|
/**
|
|
Preview the statement outline;
|
|
It will parse the statement once, and invoke the outlines.
|
|
|
|
@param[in] thd thread context
|
|
@param[in] db schema name
|
|
@param[in] query statement string
|
|
@param[in/out] container outline preview result container
|
|
|
|
@retval false success
|
|
@retval true failure
|
|
*/
|
|
bool preview_statement_outline(THD *thd, LEX_CSTRING &db, LEX_CSTRING &query,
|
|
Outline_preview_result_container *container);
|
|
|
|
/**
|
|
Trim input query as follows:
|
|
Left trim ' '
|
|
Right trim ' ' and ';'
|
|
|
|
@param[in] thd Thread context
|
|
@param[in] str query string
|
|
@param[in] len query length
|
|
@param[out] query Trimed query
|
|
*/
|
|
void alloc_query(THD *thd, const char *str, size_t len, LEX_CSTRING &query);
|
|
|
|
} /* namespace im */
|
|
|
|
#endif
|