mysql5/mysql-5.7.27/sql/sql_lex_hints.cc

165 lines
4.6 KiB
C++

/*
Copyright (c) 2014, 2015, Oracle 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 as published by
the Free Software Foundation; version 2 of the License.
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 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 */
/* A lexical scanner for optimizer hints pseudo-commentary syntax */
#include "sql_lex_hints.h"
#include "lex_hash.h"
#include "parse_tree_helpers.h"
#include "sql_class.h"
/*
Generated sources:
*/
#include "sql_yacc.h"
#include "lex_token.h"
/**
Consrtuctor.
@param thd_arg The thread handler.
@param lineno_arg The starting line number of a hint string in a query.
@param buf The rest of a query buffer with hints at the start.
@param len The length of the buf.
@param digest_state_arg The digest buffer to output scanned token data.
*/
Hint_scanner::Hint_scanner(THD *thd_arg,
size_t lineno_arg,
const char *buf,
size_t len,
sql_digest_state *digest_state_arg)
: thd(thd_arg),
cs(thd->charset()),
is_ansi_quotes(thd->variables.sql_mode & MODE_ANSI_QUOTES),
lineno(lineno_arg),
char_classes(cs->state_maps->hint_map),
input_buf(buf),
input_buf_end(input_buf + len),
ptr(input_buf + 3), // skip "/*+"
prev_token(0),
digest_state(digest_state_arg),
raw_yytext(ptr),
yytext(ptr),
yyleng(0),
has_hints(false)
{}
void HINT_PARSER_error(THD *thd, Hint_scanner *scanner, PT_hint_list **,
const char *msg)
{
if (strcmp(msg, "syntax error") == 0)
msg= ER_THD(thd, ER_WARN_OPTIMIZER_HINT_SYNTAX_ERROR);
scanner->syntax_warning(msg);
}
/**
@brief Push a warning message into MySQL error stack with line
and position information.
This function provides semantic action implementers with a way
to push the famous "You have a syntax error near..." error
message into the error stack, which is normally produced only if
a parse error is discovered internally by the Bison generated
parser.
*/
void Hint_scanner::syntax_warning(const char *msg) const
{
/* Push an error into the error stack */
ErrConvString err(raw_yytext, input_buf_end - raw_yytext,
thd->variables.character_set_client);
push_warning_printf(thd, Sql_condition::SL_WARNING,
ER_PARSE_ERROR, ER_THD(thd, ER_PARSE_ERROR),
msg, err.ptr(), lineno);
}
/**
Add hint tokens to main lexer's digest calculation buffer.
@note This function adds transformed hint keyword token values with the help
of the TOK_HINT_ADJUST() adjustment macro.
*/
void Hint_scanner::add_hint_token_digest()
{
if (digest_state == NULL)
return; // cant add: digest buffer is full
if (prev_token == 0 || prev_token == HINT_ERROR)
return; // nothing to add
if (prev_token == HINT_CLOSE)
{
if (has_hints)
add_digest(TOK_HINT_COMMENT_CLOSE);
return;
}
if (!has_hints)
{ // the 1st hint in the comment
add_digest(TOK_HINT_COMMENT_OPEN);
has_hints= true;
}
switch (prev_token) {
case HINT_ARG_NUMBER:
add_digest(NUM);
break;
case HINT_ARG_IDENT:
add_digest((peek_class() == HINT_CHR_AT) ? TOK_IDENT_AT : IDENT);
break;
case HINT_ARG_QB_NAME:
add_digest('@');
add_digest(IDENT);
break;
default:
if (prev_token <= UCHAR_MAX) // Single-char token.
add_digest(prev_token);
else // keyword
{
/* Make sure this is a known hint keyword: */
switch (prev_token) {
case BKA_HINT:
case BNL_HINT:
case DUPSWEEDOUT_HINT:
case FIRSTMATCH_HINT:
case INTOEXISTS_HINT:
case LOOSESCAN_HINT:
case MATERIALIZATION_HINT:
case MAX_EXECUTION_TIME_HINT:
case MRR_HINT:
case NO_BKA_HINT:
case NO_BNL_HINT:
case NO_ICP_HINT:
case NO_MRR_HINT:
case NO_RANGE_OPTIMIZATION_HINT:
case NO_SEMIJOIN_HINT:
case QB_NAME_HINT:
case SEMIJOIN_HINT:
case SUBQUERY_HINT:
break;
default:
DBUG_ASSERT(false);
}
add_digest(TOK_HINT_ADJUST(prev_token));
}
}
}