summaryrefslogtreecommitdiff
path: root/sql/sql_lex.cc
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2018-06-03 10:34:41 -0700
committerIgor Babaev <igor@askmonty.org>2018-06-03 10:34:41 -0700
commitcab1d6382623f0611335caf2cd056aa7ee04d7cd (patch)
treec33b8118a77a78d87d8fb01e908dbfa6a67ca9a2 /sql/sql_lex.cc
parentffe83e8e7bef32eb2a80aad2d382f0b023dd3a44 (diff)
parentee5124d714ea01f4e1bd6decf6da38b05c1009ad (diff)
downloadmariadb-git-cab1d6382623f0611335caf2cd056aa7ee04d7cd.tar.gz
Merge branch '10.3' into 10.4
Diffstat (limited to 'sql/sql_lex.cc')
-rw-r--r--sql/sql_lex.cc2055
1 files changed, 1236 insertions, 819 deletions
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 93810d2041c..779b6d9c3c1 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -31,6 +31,7 @@
#include "sql_select.h"
#include "sql_cte.h"
#include "sql_signal.h"
+#include "sql_partition.h"
void LEX::parse_error(uint err_number)
@@ -39,9 +40,6 @@ void LEX::parse_error(uint err_number)
}
-static int lex_one_token(YYSTYPE *yylval, THD *thd);
-
-
/**
LEX_STRING constant for null-string to be used in parser and other places.
*/
@@ -125,7 +123,7 @@ const char * index_hint_type_name[] =
inline int lex_casecmp(const char *s, const char *t, uint len)
{
while (len-- != 0 &&
- to_upper_lex[(uchar) *s++] == to_upper_lex[(uchar) *t++]) ;
+ to_upper_lex[(uchar) *s++] == to_upper_lex[(uchar) *t++]) ;
return (int) len+1;
}
@@ -146,7 +144,7 @@ void lex_init(void)
void lex_free(void)
-{ // Call this when daemon ends
+{ // Call this when daemon ends
DBUG_ENTER("lex_free");
DBUG_VOID_RETURN;
}
@@ -189,14 +187,14 @@ init_lex_with_single_table(THD *thd, TABLE *table, LEX *lex)
thd->lex= lex;
lex_start(thd);
context->init();
- if ((!(table_ident= new Table_ident(thd,
- &table->s->db,
- &table->s->table_name,
- TRUE))) ||
- (!(table_list= select_lex->add_table_to_list(thd,
- table_ident,
- NULL,
- 0))))
+ if (unlikely((!(table_ident= new Table_ident(thd,
+ &table->s->db,
+ &table->s->table_name,
+ TRUE)))) ||
+ (unlikely(!(table_list= select_lex->add_table_to_list(thd,
+ table_ident,
+ NULL,
+ 0)))))
return TRUE;
context->resolve_in_table_list_only(table_list);
lex->use_only_table_context= TRUE;
@@ -251,8 +249,8 @@ st_parsing_options::reset()
*/
bool Lex_input_stream::init(THD *thd,
- char* buff,
- size_t length)
+ char* buff,
+ size_t length)
{
DBUG_EXECUTE_IF("bug42064_simulate_oom",
DBUG_SET("+d,simulate_out_of_memory"););
@@ -284,7 +282,6 @@ void
Lex_input_stream::reset(char *buffer, size_t length)
{
yylineno= 1;
- yylval= NULL;
lookahead_token= -1;
lookahead_yylval= NULL;
m_ptr= buffer;
@@ -420,32 +417,18 @@ void Lex_input_stream::body_utf8_append(const char *ptr)
operation.
*/
-void Lex_input_stream::body_utf8_append_ident(THD *thd,
- const LEX_CSTRING *txt,
- const char *end_ptr)
+void
+Lex_input_stream::body_utf8_append_ident(THD *thd,
+ const Lex_string_with_metadata_st *txt,
+ const char *end_ptr)
{
if (!m_cpp_utf8_processed_ptr)
return;
LEX_CSTRING utf_txt;
- CHARSET_INFO *txt_cs= thd->charset();
-
- if (!my_charset_same(txt_cs, &my_charset_utf8_general_ci))
- {
- LEX_STRING to;
- thd->convert_string(&to,
- &my_charset_utf8_general_ci,
- txt->str, (uint) txt->length,
- txt_cs);
- utf_txt.str= to.str;
- utf_txt.length= to.length;
-
- }
- else
- utf_txt= *txt;
+ thd->make_text_string_sys(&utf_txt, txt); // QQ: check return value?
/* NOTE: utf_txt.length is in bytes, not in symbols. */
-
memcpy(m_body_utf8_ptr, utf_txt.str, utf_txt.length);
m_body_utf8_ptr += utf_txt.length;
*m_body_utf8_ptr= 0;
@@ -669,11 +652,11 @@ void lex_start(THD *thd)
void LEX::start(THD *thd_arg)
{
DBUG_ENTER("LEX::start");
- DBUG_PRINT("info", ("This: %p thd_arg->lex: %p thd_arg->stmt_lex: %p",
- this, thd_arg->lex, thd_arg->stmt_lex));
+ DBUG_PRINT("info", ("This: %p thd_arg->lex: %p", this, thd_arg->lex));
thd= unit.thd= thd_arg;
-
+ stmt_lex= this; // default, should be rewritten for VIEWs And CTEs
+
DBUG_ASSERT(!explain);
context_stack.empty();
@@ -842,23 +825,27 @@ Yacc_state::~Yacc_state()
}
}
-static int find_keyword(Lex_input_stream *lip, uint len, bool function)
+int Lex_input_stream::find_keyword(Lex_ident_cli_st *kwd,
+ uint len, bool function)
{
- const char *tok= lip->get_tok_start();
+ const char *tok= m_tok_start;
SYMBOL *symbol= get_hash_symbol(tok, len, function);
if (symbol)
{
- lip->yylval->symbol.symbol=symbol;
- lip->yylval->symbol.str= (char*) tok;
- lip->yylval->symbol.length=len;
+ kwd->set_keyword(tok, len);
+ DBUG_ASSERT(tok >= get_buf());
+ DBUG_ASSERT(tok < get_end_of_query());
if ((symbol->tok == NOT_SYM) &&
- (lip->m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
+ (m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
return NOT2_SYM;
- if ((symbol->tok == OR_OR_SYM) &&
- !(lip->m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
- return OR2_SYM;
+ if ((symbol->tok == OR2_SYM) &&
+ (m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
+ {
+ return (m_thd->variables.sql_mode & MODE_ORACLE) ?
+ ORACLE_CONCAT_SYM : MYSQL_CONCAT_SYM;
+ }
return symbol->tok;
}
@@ -955,54 +942,19 @@ bool is_native_function_with_warn(THD *thd, const LEX_CSTRING *name)
/* make a copy of token before ptr and set yytoklen */
-static LEX_CSTRING get_token(Lex_input_stream *lip, uint skip, uint length)
+LEX_CSTRING Lex_input_stream::get_token(uint skip, uint length)
{
LEX_CSTRING tmp;
- lip->yyUnget(); // ptr points now after last token char
+ yyUnget(); // ptr points now after last token char
tmp.length= length;
- tmp.str= lip->m_thd->strmake(lip->get_tok_start() + skip, tmp.length);
+ tmp.str= m_thd->strmake(m_tok_start + skip, tmp.length);
- lip->m_cpp_text_start= lip->get_cpp_tok_start() + skip;
- lip->m_cpp_text_end= lip->m_cpp_text_start + tmp.length;
+ m_cpp_text_start= m_cpp_tok_start + skip;
+ m_cpp_text_end= m_cpp_text_start + tmp.length;
return tmp;
}
-/*
- todo:
- There are no dangerous charsets in mysql for function
- get_quoted_token yet. But it should be fixed in the
- future to operate multichar strings (like ucs2)
-*/
-
-static LEX_CSTRING get_quoted_token(Lex_input_stream *lip,
- uint skip,
- uint length, char quote)
-{
- LEX_CSTRING tmp;
- const char *from, *end;
- char *to;
- lip->yyUnget(); // ptr points now after last token char
- tmp.length= length;
- tmp.str= to= (char*) lip->m_thd->alloc(tmp.length+1);
- from= lip->get_tok_start() + skip;
- end= to+length;
-
- lip->m_cpp_text_start= lip->get_cpp_tok_start() + skip;
- lip->m_cpp_text_end= lip->m_cpp_text_start + length;
-
- for ( ; to != end; )
- {
- if ((*to++= *from++) == quote)
- {
- from++; // Skip double quotes
- lip->m_cpp_text_start++;
- }
- }
- *to= 0; // End null for safety
- return tmp;
-}
-
static size_t
my_unescape(CHARSET_INFO *cs, char *to, const char *str, const char *end,
@@ -1078,16 +1030,16 @@ Lex_input_stream::unescape(CHARSET_INFO *cs, char *to,
bool Lex_input_stream::get_text(Lex_string_with_metadata_st *dst, uint sep,
int pre_skip, int post_skip)
{
- reg1 uchar c;
+ uchar c;
uint found_escape=0;
CHARSET_INFO *cs= m_thd->charset();
+ bool is_8bit= false;
- dst->set_8bit(false);
while (! eof())
{
c= yyGet();
if (c & 0x80)
- dst->set_8bit(true);
+ is_8bit= true;
#ifdef USE_MB
{
int l;
@@ -1102,10 +1054,10 @@ bool Lex_input_stream::get_text(Lex_string_with_metadata_st *dst, uint sep,
#endif
if (c == '\\' &&
!(m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
- { // Escaped character
+ { // Escaped character
found_escape=1;
if (eof())
- return true;
+ return true;
yySkip();
}
else if (c == sep)
@@ -1113,7 +1065,7 @@ bool Lex_input_stream::get_text(Lex_string_with_metadata_st *dst, uint sep,
if (c == yyGet()) // Check if two separators in a row
{
found_escape=1; // duplicate. Remember for delete
- continue;
+ continue;
}
else
yyUnget();
@@ -1122,7 +1074,7 @@ bool Lex_input_stream::get_text(Lex_string_with_metadata_st *dst, uint sep,
const char *str, *end;
char *to;
- str= get_tok_start();
+ str= m_tok_start;
end= get_ptr();
/* Extract the text from the token */
str += pre_skip;
@@ -1131,23 +1083,24 @@ bool Lex_input_stream::get_text(Lex_string_with_metadata_st *dst, uint sep,
if (!(to= (char*) m_thd->alloc((uint) (end - str) + 1)))
{
- dst->str= ""; // Sql_alloc has set error flag
- dst->length= 0;
- return true;
+ dst->set(&empty_clex_str, 0, '\0');
+ return true; // Sql_alloc has set error flag
}
- dst->str= to;
- m_cpp_text_start= get_cpp_tok_start() + pre_skip;
+ m_cpp_text_start= m_cpp_tok_start + pre_skip;
m_cpp_text_end= get_cpp_ptr() - post_skip;
if (!found_escape)
{
- memcpy(to, str, dst->length= (end - str));
- to[dst->length]= 0;
+ size_t len= (end - str);
+ memcpy(to, str, len);
+ to[len]= '\0';
+ dst->set(to, len, is_8bit, '\0');
}
else
{
- dst->length= unescape(cs, to, str, end, sep);
+ size_t len= unescape(cs, to, str, end, sep);
+ dst->set(to, len, is_8bit, '\0');
}
return false;
}
@@ -1176,11 +1129,11 @@ static const uint unsigned_longlong_len=20;
static inline uint int_token(const char *str,uint length)
{
- if (length < long_len) // quick normal case
+ if (length < long_len) // quick normal case
return NUM;
bool neg=0;
- if (*str == '+') // Remove sign and pre-zeros
+ if (*str == '+') // Remove sign and pre-zeros
{
str++; length--;
}
@@ -1202,9 +1155,9 @@ static inline uint int_token(const char *str,uint length)
{
if (length == long_len)
{
- cmp= signed_long_str+1;
- smaller=NUM; // If <= signed_long_str
- bigger=LONG_NUM; // If >= signed_long_str
+ cmp= signed_long_str + 1;
+ smaller= NUM; // If <= signed_long_str
+ bigger= LONG_NUM; // If >= signed_long_str
}
else if (length < signed_longlong_len)
return LONG_NUM;
@@ -1212,8 +1165,8 @@ static inline uint int_token(const char *str,uint length)
return DECIMAL_NUM;
else
{
- cmp=signed_longlong_str+1;
- smaller=LONG_NUM; // If <= signed_longlong_str
+ cmp= signed_longlong_str + 1;
+ smaller= LONG_NUM; // If <= signed_longlong_str
bigger=DECIMAL_NUM;
}
}
@@ -1259,34 +1212,34 @@ static inline uint int_token(const char *str,uint length)
@retval Whether EOF reached before comment is closed.
*/
-bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted)
+bool Lex_input_stream::consume_comment(int remaining_recursions_permitted)
{
- reg1 uchar c;
- while (! lip->eof())
+ uchar c;
+ while (!eof())
{
- c= lip->yyGet();
+ c= yyGet();
if (remaining_recursions_permitted > 0)
{
- if ((c == '/') && (lip->yyPeek() == '*'))
+ if ((c == '/') && (yyPeek() == '*'))
{
- lip->yySkip(); /* Eat asterisk */
- consume_comment(lip, remaining_recursions_permitted-1);
+ yySkip(); // Eat asterisk
+ consume_comment(remaining_recursions_permitted - 1);
continue;
}
}
if (c == '*')
{
- if (lip->yyPeek() == '/')
+ if (yyPeek() == '/')
{
- lip->yySkip(); /* Eat slash */
+ yySkip(); // Eat slash
return FALSE;
}
}
if (c == '\n')
- lip->yylineno++;
+ yylineno++;
}
return TRUE;
@@ -1299,31 +1252,42 @@ bool consume_comment(Lex_input_stream *lip, int remaining_recursions_permitted)
@param yylval [out] semantic value of the token being parsed (yylval)
@param thd THD
- - MY_LEX_EOQ Found end of query
- - MY_LEX_OPERATOR_OR_IDENT Last state was an ident, text or number
- (which can't be followed by a signed number)
+ - MY_LEX_EOQ Found end of query
+ - MY_LEX_OPERATOR_OR_IDENT Last state was an ident, text or number
+ (which can't be followed by a signed number)
*/
int MYSQLlex(YYSTYPE *yylval, THD *thd)
{
- Lex_input_stream *lip= & thd->m_parser_state->m_lip;
+ return thd->m_parser_state->m_lip.lex_token(yylval, thd);
+}
+
+
+int ORAlex(YYSTYPE *yylval, THD *thd)
+{
+ return thd->m_parser_state->m_lip.lex_token(yylval, thd);
+}
+
+
+int Lex_input_stream::lex_token(YYSTYPE *yylval, THD *thd)
+{
int token;
- if (lip->lookahead_token >= 0)
+ if (lookahead_token >= 0)
{
/*
The next token was already parsed in advance,
return it.
*/
- token= lip->lookahead_token;
- lip->lookahead_token= -1;
- *yylval= *(lip->lookahead_yylval);
- lip->lookahead_yylval= NULL;
+ token= lookahead_token;
+ lookahead_token= -1;
+ *yylval= *(lookahead_yylval);
+ lookahead_yylval= NULL;
return token;
}
token= lex_one_token(yylval, thd);
- lip->add_digest_token(token, yylval);
+ add_digest_token(token, yylval);
switch(token) {
case WITH:
@@ -1335,7 +1299,7 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
which sql_yacc.yy can process.
*/
token= lex_one_token(yylval, thd);
- lip->add_digest_token(token, yylval);
+ add_digest_token(token, yylval);
switch(token) {
case CUBE_SYM:
return WITH_CUBE_SYM;
@@ -1347,9 +1311,8 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
/*
Save the token following 'WITH'
*/
- lip->lookahead_yylval= lip->yylval;
- lip->yylval= NULL;
- lip->lookahead_token= token;
+ lookahead_yylval= yylval;
+ lookahead_token= token;
return WITH;
}
break;
@@ -1360,7 +1323,7 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
* SELECT ... FOR SYSTEM_TIME ... .
*/
token= lex_one_token(yylval, thd);
- lip->add_digest_token(token, yylval);
+ add_digest_token(token, yylval);
switch(token) {
case SYSTEM_TIME_SYM:
return FOR_SYSTEM_TIME_SYM;
@@ -1368,9 +1331,8 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
/*
Save the token following 'FOR_SYM'
*/
- lip->lookahead_yylval= lip->yylval;
- lip->yylval= NULL;
- lip->lookahead_token= token;
+ lookahead_yylval= yylval;
+ lookahead_token= token;
return FOR_SYM;
}
break;
@@ -1379,16 +1341,15 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
thd->lex->current_select->parsing_place == IN_PART_FUNC)
return VALUE_SYM;
token= lex_one_token(yylval, thd);
- lip->add_digest_token(token, yylval);
+ add_digest_token(token, yylval);
switch(token) {
case LESS_SYM:
return VALUES_LESS_SYM;
case IN_SYM:
return VALUES_IN_SYM;
default:
- lip->lookahead_yylval= lip->yylval;
- lip->yylval= NULL;
- lip->lookahead_token= token;
+ lookahead_yylval= yylval;
+ lookahead_token= token;
return VALUES;
}
break;
@@ -1398,71 +1359,64 @@ int MYSQLlex(YYSTYPE *yylval, THD *thd)
return token;
}
-int ORAlex(YYSTYPE *yylval, THD *thd)
-{
- return MYSQLlex(yylval, thd);
-}
-static int lex_one_token(YYSTYPE *yylval, THD *thd)
+int Lex_input_stream::lex_one_token(YYSTYPE *yylval, THD *thd)
{
- reg1 uchar UNINIT_VAR(c);
+ uchar UNINIT_VAR(c);
bool comment_closed;
- int tokval, result_state;
+ int tokval;
uint length;
enum my_lex_states state;
- Lex_input_stream *lip= & thd->m_parser_state->m_lip;
LEX *lex= thd->lex;
CHARSET_INFO *const cs= thd->charset();
const uchar *const state_map= cs->state_map;
const uchar *const ident_map= cs->ident_map;
- lip->yylval=yylval; // The global state
-
- lip->start_token();
- state=lip->next_state;
- lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
+ start_token();
+ state= next_state;
+ next_state= MY_LEX_OPERATOR_OR_IDENT;
for (;;)
{
switch (state) {
- case MY_LEX_OPERATOR_OR_IDENT: // Next is operator or keyword
- case MY_LEX_START: // Start of token
+ case MY_LEX_OPERATOR_OR_IDENT: // Next is operator or keyword
+ case MY_LEX_START: // Start of token
// Skip starting whitespace
- while(state_map[c= lip->yyPeek()] == MY_LEX_SKIP)
+ while(state_map[c= yyPeek()] == MY_LEX_SKIP)
{
- if (c == '\n')
- lip->yylineno++;
+ if (c == '\n')
+ yylineno++;
- lip->yySkip();
+ yySkip();
}
/* Start of real token */
- lip->restart_token();
- c= lip->yyGet();
+ restart_token();
+ c= yyGet();
state= (enum my_lex_states) state_map[c];
break;
case MY_LEX_ESCAPE:
- if (!lip->eof() && lip->yyGet() == 'N')
- { // Allow \N as shortcut for NULL
- yylval->lex_str.str=(char*) "\\N";
- yylval->lex_str.length=2;
- return NULL_SYM;
+ if (!eof() && yyGet() == 'N')
+ { // Allow \N as shortcut for NULL
+ yylval->lex_str.str= (char*) "\\N";
+ yylval->lex_str.length= 2;
+ return NULL_SYM;
}
/* Fall through */
- case MY_LEX_CHAR: // Unknown or single char token
- case MY_LEX_SKIP: // This should not happen
+ case MY_LEX_CHAR: // Unknown or single char token
+ case MY_LEX_SKIP: // This should not happen
if (c != ')')
- lip->next_state= MY_LEX_START; // Allow signed numbers
+ next_state= MY_LEX_START; // Allow signed numbers
return((int) c);
case MY_LEX_MINUS_OR_COMMENT:
- if (lip->yyPeek() == '-' &&
- (my_isspace(cs,lip->yyPeekn(1)) ||
- my_iscntrl(cs,lip->yyPeekn(1))))
+ if (yyPeek() == '-' &&
+ (my_isspace(cs,yyPeekn(1)) ||
+ my_iscntrl(cs,yyPeekn(1))))
{
state=MY_LEX_COMMENT;
break;
}
- lip->next_state= MY_LEX_START; // Allow signed numbers
+ next_state= MY_LEX_START; // Allow signed numbers
return((int) c);
case MY_LEX_PLACEHOLDER:
@@ -1472,13 +1426,13 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
its value in a query for the binlog, the query must stay
grammatically correct.
*/
- lip->next_state= MY_LEX_START; // Allow signed numbers
- if (lip->stmt_prepare_mode && !ident_map[(uchar) lip->yyPeek()])
+ next_state= MY_LEX_START; // Allow signed numbers
+ if (stmt_prepare_mode && !ident_map[(uchar) yyPeek()])
return(PARAM_MARKER);
return((int) c);
case MY_LEX_COMMA:
- lip->next_state= MY_LEX_START; // Allow signed numbers
+ next_state= MY_LEX_START; // Allow signed numbers
/*
Warning:
This is a work around, to make the "remember_name" rule in
@@ -1488,431 +1442,277 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
remember_name (see select_item) *before* actually parsing the
first token of expr2.
*/
- lip->restart_token();
+ restart_token();
return((int) c);
case MY_LEX_IDENT_OR_NCHAR:
{
uint sep;
- if (lip->yyPeek() != '\'')
+ if (yyPeek() != '\'')
{
- state= MY_LEX_IDENT;
- break;
+ state= MY_LEX_IDENT;
+ break;
}
/* Found N'string' */
- lip->yySkip(); // Skip '
- if (lip->get_text(&yylval->lex_string_with_metadata,
- (sep= lip->yyGetLast()), 2, 1))
+ yySkip(); // Skip '
+ if (get_text(&yylval->lex_string_with_metadata, (sep= yyGetLast()), 2, 1))
{
- state= MY_LEX_CHAR; // Read char by char
- break;
+ state= MY_LEX_CHAR; // Read char by char
+ break;
}
- lip->body_utf8_append(lip->m_cpp_text_start);
- lip->body_utf8_append_escape(thd, &yylval->lex_string_with_metadata,
+ body_utf8_append(m_cpp_text_start);
+ body_utf8_append_escape(thd, &yylval->lex_string_with_metadata,
national_charset_info,
- lip->m_cpp_text_end, sep);
+ m_cpp_text_end, sep);
return(NCHAR_STRING);
}
case MY_LEX_IDENT_OR_HEX:
- if (lip->yyPeek() == '\'')
- { // Found x'hex-number'
- state= MY_LEX_HEX_NUMBER;
- break;
+ if (yyPeek() == '\'')
+ { // Found x'hex-number'
+ state= MY_LEX_HEX_NUMBER;
+ break;
}
/* fall through */
case MY_LEX_IDENT_OR_BIN:
- if (lip->yyPeek() == '\'')
+ if (yyPeek() == '\'')
{ // Found b'bin-number'
state= MY_LEX_BIN_NUMBER;
break;
}
/* fall through */
case MY_LEX_IDENT:
- const char *start;
-#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(cs))
- {
- result_state= IDENT_QUOTED;
- int char_length= my_charlen(cs, lip->get_ptr() - 1,
- lip->get_end_of_query());
- if (char_length <= 0)
- {
- state= MY_LEX_CHAR;
- continue;
- }
- lip->skip_binary(char_length - 1);
-
- while (ident_map[c=lip->yyGet()])
- {
- char_length= my_charlen(cs, lip->get_ptr() - 1,
- lip->get_end_of_query());
- if (char_length <= 0)
- break;
- lip->skip_binary(char_length - 1);
- }
- }
- else
-#endif
- {
- for (result_state= c;
- ident_map[(uchar) (c= lip->yyGet())];
- result_state|= c)
- ;
- /* If there were non-ASCII characters, mark that we must convert */
- result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
- }
- length= lip->yyLength();
- start= lip->get_ptr();
- if (lip->ignore_space)
- {
- /*
- If we find a space then this can't be an identifier. We notice this
- below by checking start != lex->ptr.
- */
- for (; state_map[(uchar) c] == MY_LEX_SKIP ; c= lip->yyGet())
- {
- if (c == '\n')
- lip->yylineno++;
- }
- }
- if (start == lip->get_ptr() && c == '.' &&
- ident_map[(uchar) lip->yyPeek()])
- lip->next_state=MY_LEX_IDENT_SEP;
- else
- { // '(' must follow directly if function
- lip->yyUnget();
- if ((tokval = find_keyword(lip, length, c == '(')))
- {
- lip->next_state= MY_LEX_START; // Allow signed numbers
- return(tokval); // Was keyword
- }
- lip->yySkip(); // next state does a unget
- }
- yylval->lex_str=get_token(lip, 0, length);
-
- /*
- Note: "SELECT _bla AS 'alias'"
- _bla should be considered as a IDENT if charset haven't been found.
- So we don't use MYF(MY_WME) with get_charset_by_csname to avoid
- producing an error.
- */
-
- if (yylval->lex_str.str[0] == '_')
- {
- CHARSET_INFO *cs= get_charset_by_csname(yylval->lex_str.str + 1,
- MY_CS_PRIMARY, MYF(0));
- if (cs)
- {
- yylval->charset= cs;
- lip->m_underscore_cs= cs;
-
- lip->body_utf8_append(lip->m_cpp_text_start,
- lip->get_cpp_tok_start() + length);
- return(UNDERSCORE_CHARSET);
- }
- }
-
- lip->body_utf8_append(lip->m_cpp_text_start);
-
- lip->body_utf8_append_ident(thd, &yylval->lex_str, lip->m_cpp_text_end);
-
- return(result_state); // IDENT or IDENT_QUOTED
+ {
+ tokval= scan_ident_middle(thd, &yylval->ident_cli,
+ &yylval->charset, &state);
+ if (!tokval)
+ continue;
+ if (tokval == UNDERSCORE_CHARSET)
+ m_underscore_cs= yylval->charset;
+ return tokval;
+ }
case MY_LEX_IDENT_SEP: // Found ident and now '.'
- yylval->lex_str.str= (char*) lip->get_ptr();
+ yylval->lex_str.str= (char*) get_ptr();
yylval->lex_str.length= 1;
- c= lip->yyGet(); // should be '.'
- lip->next_state= MY_LEX_IDENT_START; // Next is ident (not keyword)
- if (!ident_map[(uchar) lip->yyPeek()]) // Probably ` or "
- lip->next_state= MY_LEX_START;
+ c= yyGet(); // should be '.'
+ next_state= MY_LEX_IDENT_START; // Next is ident (not keyword)
+ if (!ident_map[(uchar) yyPeek()]) // Probably ` or "
+ next_state= MY_LEX_START;
return((int) c);
- case MY_LEX_NUMBER_IDENT: // number or ident which num-start
- if (lip->yyGetLast() == '0')
+ case MY_LEX_NUMBER_IDENT: // number or ident which num-start
+ if (yyGetLast() == '0')
{
- c= lip->yyGet();
+ c= yyGet();
if (c == 'x')
{
- while (my_isxdigit(cs,(c = lip->yyGet()))) ;
- if ((lip->yyLength() >= 3) && !ident_map[c])
+ while (my_isxdigit(cs, (c = yyGet()))) ;
+ if ((yyLength() >= 3) && !ident_map[c])
{
/* skip '0x' */
- yylval->lex_str=get_token(lip, 2, lip->yyLength()-2);
+ yylval->lex_str= get_token(2, yyLength() - 2);
return (HEX_NUM);
}
- lip->yyUnget();
+ yyUnget();
state= MY_LEX_IDENT_START;
break;
}
else if (c == 'b')
{
- while ((c= lip->yyGet()) == '0' || c == '1')
+ while ((c= yyGet()) == '0' || c == '1')
;
- if ((lip->yyLength() >= 3) && !ident_map[c])
+ if ((yyLength() >= 3) && !ident_map[c])
{
/* Skip '0b' */
- yylval->lex_str= get_token(lip, 2, lip->yyLength()-2);
+ yylval->lex_str= get_token(2, yyLength() - 2);
return (BIN_NUM);
}
- lip->yyUnget();
+ yyUnget();
state= MY_LEX_IDENT_START;
break;
}
- lip->yyUnget();
+ yyUnget();
}
- while (my_isdigit(cs, (c = lip->yyGet()))) ;
+ while (my_isdigit(cs, (c= yyGet()))) ;
if (!ident_map[c])
- { // Can't be identifier
- state=MY_LEX_INT_OR_REAL;
- break;
+ { // Can't be identifier
+ state=MY_LEX_INT_OR_REAL;
+ break;
}
if (c == 'e' || c == 'E')
{
- // The following test is written this way to allow numbers of type 1e1
- if (my_isdigit(cs,lip->yyPeek()) ||
- (c=(lip->yyGet())) == '+' || c == '-')
- { // Allow 1E+10
- if (my_isdigit(cs,lip->yyPeek())) // Number must have digit after sign
- {
- lip->yySkip();
- while (my_isdigit(cs,lip->yyGet())) ;
- yylval->lex_str=get_token(lip, 0, lip->yyLength());
- return(FLOAT_NUM);
- }
- }
- lip->yyUnget();
- }
- // fall through
- case MY_LEX_IDENT_START: // We come here after '.'
- result_state= IDENT;
-#if defined(USE_MB) && defined(USE_MB_IDENT)
- if (use_mb(cs))
- {
- result_state= IDENT_QUOTED;
- while (ident_map[c=lip->yyGet()])
- {
- int char_length= my_charlen(cs, lip->get_ptr() - 1,
- lip->get_end_of_query());
- if (char_length <= 0)
- break;
- lip->skip_binary(char_length - 1);
- }
- }
- else
-#endif
- {
- for (result_state=0; ident_map[c= lip->yyGet()]; result_state|= c)
- ;
- /* If there were non-ASCII characters, mark that we must convert */
- result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
- }
- if (c == '.' && ident_map[(uchar) lip->yyPeek()])
- lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
-
- yylval->lex_str= get_token(lip, 0, lip->yyLength());
-
- lip->body_utf8_append(lip->m_cpp_text_start);
-
- lip->body_utf8_append_ident(thd, &yylval->lex_str, lip->m_cpp_text_end);
-
- return(result_state);
-
- case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char
- {
- uint double_quotes= 0;
- char quote_char= c; // Used char
- while ((c=lip->yyGet()))
- {
- int var_length= my_charlen(cs, lip->get_ptr() - 1,
- lip->get_end_of_query());
- if (var_length == 1)
- {
- if (c == quote_char)
- {
- if (lip->yyPeek() != quote_char)
- break;
- c=lip->yyGet();
- double_quotes++;
- continue;
- }
- }
-#ifdef USE_MB
- else if (var_length > 1)
- {
- lip->skip_binary(var_length - 1);
+ // The following test is written this way to allow numbers of type 1e1
+ if (my_isdigit(cs, yyPeek()) ||
+ (c=(yyGet())) == '+' || c == '-')
+ { // Allow 1E+10
+ if (my_isdigit(cs, yyPeek())) // Number must have digit after sign
+ {
+ yySkip();
+ while (my_isdigit(cs, yyGet())) ;
+ yylval->lex_str= get_token(0, yyLength());
+ return(FLOAT_NUM);
+ }
}
-#endif
+ yyUnget();
}
- if (double_quotes)
- yylval->lex_str=get_quoted_token(lip, 1,
- lip->yyLength() - double_quotes -1,
- quote_char);
- else
- yylval->lex_str=get_token(lip, 1, lip->yyLength() -1);
- if (c == quote_char)
- lip->yySkip(); // Skip end `
- lip->next_state= MY_LEX_START;
-
- lip->body_utf8_append(lip->m_cpp_text_start);
+ // fall through
+ case MY_LEX_IDENT_START: // We come here after '.'
+ return scan_ident_start(thd, &yylval->ident_cli);
- lip->body_utf8_append_ident(thd, &yylval->lex_str, lip->m_cpp_text_end);
+ case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char
+ return scan_ident_delimited(thd, &yylval->ident_cli);
- return(IDENT_QUOTED);
- }
- case MY_LEX_INT_OR_REAL: // Complete int or incomplete real
- if (c != '.' || lip->yyPeek() == '.')
+ case MY_LEX_INT_OR_REAL: // Complete int or incomplete real
+ if (c != '.' || yyPeek() == '.')
{
/*
Found a complete integer number:
- the number is either not followed by a dot at all, or
- the number is followed by a double dot as in: FOR i IN 1..10
*/
- yylval->lex_str=get_token(lip, 0, lip->yyLength());
- return int_token(yylval->lex_str.str, (uint) yylval->lex_str.length);
+ yylval->lex_str= get_token(0, yyLength());
+ return int_token(yylval->lex_str.str, (uint) yylval->lex_str.length);
}
// fall through
- case MY_LEX_REAL: // Incomplete real number
- while (my_isdigit(cs,c = lip->yyGet())) ;
+ case MY_LEX_REAL: // Incomplete real number
+ while (my_isdigit(cs, c= yyGet())) ;
if (c == 'e' || c == 'E')
{
- c = lip->yyGet();
- if (c == '-' || c == '+')
- c = lip->yyGet(); // Skip sign
- if (!my_isdigit(cs,c))
- { // No digit after sign
- state= MY_LEX_CHAR;
- break;
- }
- while (my_isdigit(cs,lip->yyGet())) ;
- yylval->lex_str=get_token(lip, 0, lip->yyLength());
- return(FLOAT_NUM);
+ c= yyGet();
+ if (c == '-' || c == '+')
+ c= yyGet(); // Skip sign
+ if (!my_isdigit(cs, c))
+ { // No digit after sign
+ state= MY_LEX_CHAR;
+ break;
+ }
+ while (my_isdigit(cs, yyGet())) ;
+ yylval->lex_str= get_token(0, yyLength());
+ return(FLOAT_NUM);
}
- yylval->lex_str=get_token(lip, 0, lip->yyLength());
+ yylval->lex_str= get_token(0, yyLength());
return(DECIMAL_NUM);
- case MY_LEX_HEX_NUMBER: // Found x'hexstring'
- lip->yySkip(); // Accept opening '
- while (my_isxdigit(cs, (c= lip->yyGet()))) ;
+ case MY_LEX_HEX_NUMBER: // Found x'hexstring'
+ yySkip(); // Accept opening '
+ while (my_isxdigit(cs, (c= yyGet()))) ;
if (c != '\'')
return(ABORT_SYM); // Illegal hex constant
- lip->yySkip(); // Accept closing '
- length= lip->yyLength(); // Length of hexnum+3
+ yySkip(); // Accept closing '
+ length= yyLength(); // Length of hexnum+3
if ((length % 2) == 0)
return(ABORT_SYM); // odd number of hex digits
- yylval->lex_str=get_token(lip,
- 2, // skip x'
- length-3); // don't count x' and last '
+ yylval->lex_str= get_token(2, // skip x'
+ length - 3); // don't count x' and last '
return HEX_STRING;
case MY_LEX_BIN_NUMBER: // Found b'bin-string'
- lip->yySkip(); // Accept opening '
- while ((c= lip->yyGet()) == '0' || c == '1')
+ yySkip(); // Accept opening '
+ while ((c= yyGet()) == '0' || c == '1')
;
if (c != '\'')
return(ABORT_SYM); // Illegal hex constant
- lip->yySkip(); // Accept closing '
- length= lip->yyLength(); // Length of bin-num + 3
- yylval->lex_str= get_token(lip,
- 2, // skip b'
- length-3); // don't count b' and last '
+ yySkip(); // Accept closing '
+ length= yyLength(); // Length of bin-num + 3
+ yylval->lex_str= get_token(2, // skip b'
+ length - 3); // don't count b' and last '
return (BIN_NUM);
- case MY_LEX_CMP_OP: // Incomplete comparison operator
- lip->next_state= MY_LEX_START; // Allow signed numbers
- if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP ||
- state_map[(uchar) lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
+ case MY_LEX_CMP_OP: // Incomplete comparison operator
+ next_state= MY_LEX_START; // Allow signed numbers
+ if (state_map[(uchar) yyPeek()] == MY_LEX_CMP_OP ||
+ state_map[(uchar) yyPeek()] == MY_LEX_LONG_CMP_OP)
{
- lip->yySkip();
- if ((tokval= find_keyword(lip, 2, 0)))
+ yySkip();
+ if ((tokval= find_keyword(&yylval->kwd, 2, 0)))
return(tokval);
- lip->yyUnget();
+ yyUnget();
}
return(c);
- case MY_LEX_LONG_CMP_OP: // Incomplete comparison operator
- lip->next_state= MY_LEX_START;
- if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP ||
- state_map[(uchar) lip->yyPeek()] == MY_LEX_LONG_CMP_OP)
+ case MY_LEX_LONG_CMP_OP: // Incomplete comparison operator
+ next_state= MY_LEX_START;
+ if (state_map[(uchar) yyPeek()] == MY_LEX_CMP_OP ||
+ state_map[(uchar) yyPeek()] == MY_LEX_LONG_CMP_OP)
{
- lip->yySkip();
- if (state_map[(uchar) lip->yyPeek()] == MY_LEX_CMP_OP)
+ yySkip();
+ if (state_map[(uchar) yyPeek()] == MY_LEX_CMP_OP)
{
- lip->yySkip();
- if ((tokval= find_keyword(lip, 3, 0)))
+ yySkip();
+ if ((tokval= find_keyword(&yylval->kwd, 3, 0)))
return(tokval);
- lip->yyUnget();
+ yyUnget();
}
- if ((tokval= find_keyword(lip, 2, 0)))
+ if ((tokval= find_keyword(&yylval->kwd, 2, 0)))
return(tokval);
- lip->yyUnget();
+ yyUnget();
}
return(c);
case MY_LEX_BOOL:
- if (c != lip->yyPeek())
+ if (c != yyPeek())
{
- state=MY_LEX_CHAR;
- break;
+ state= MY_LEX_CHAR;
+ break;
}
- lip->yySkip();
- tokval = find_keyword(lip,2,0); // Is a bool operator
- lip->next_state= MY_LEX_START; // Allow signed numbers
+ yySkip();
+ tokval= find_keyword(&yylval->kwd, 2, 0); // Is a bool operator
+ next_state= MY_LEX_START; // Allow signed numbers
return(tokval);
case MY_LEX_STRING_OR_DELIMITER:
if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
{
- state= MY_LEX_USER_VARIABLE_DELIMITER;
- break;
+ state= MY_LEX_USER_VARIABLE_DELIMITER;
+ break;
}
/* " used for strings */
/* fall through */
- case MY_LEX_STRING: // Incomplete text string
+ case MY_LEX_STRING: // Incomplete text string
{
uint sep;
- if (lip->get_text(&yylval->lex_string_with_metadata,
- (sep= lip->yyGetLast()), 1, 1))
+ if (get_text(&yylval->lex_string_with_metadata, (sep= yyGetLast()), 1, 1))
{
- state= MY_LEX_CHAR; // Read char by char
- break;
+ state= MY_LEX_CHAR; // Read char by char
+ break;
}
- CHARSET_INFO *strcs= lip->m_underscore_cs ? lip->m_underscore_cs : cs;
- lip->body_utf8_append(lip->m_cpp_text_start);
+ CHARSET_INFO *strcs= m_underscore_cs ? m_underscore_cs : cs;
+ body_utf8_append(m_cpp_text_start);
- lip->body_utf8_append_escape(thd, &yylval->lex_string_with_metadata,
- strcs, lip->m_cpp_text_end, sep);
- lip->m_underscore_cs= NULL;
+ body_utf8_append_escape(thd, &yylval->lex_string_with_metadata,
+ strcs, m_cpp_text_end, sep);
+ m_underscore_cs= NULL;
return(TEXT_STRING);
}
- case MY_LEX_COMMENT: // Comment
+ case MY_LEX_COMMENT: // Comment
lex->select_lex.options|= OPTION_FOUND_COMMENT;
- while ((c = lip->yyGet()) != '\n' && c) ;
- lip->yyUnget(); // Safety against eof
- state = MY_LEX_START; // Try again
+ while ((c= yyGet()) != '\n' && c) ;
+ yyUnget(); // Safety against eof
+ state= MY_LEX_START; // Try again
break;
- case MY_LEX_LONG_COMMENT: /* Long C comment? */
- if (lip->yyPeek() != '*')
+ case MY_LEX_LONG_COMMENT: // Long C comment?
+ if (yyPeek() != '*')
{
- state=MY_LEX_CHAR; // Probable division
- break;
+ state= MY_LEX_CHAR; // Probable division
+ break;
}
lex->select_lex.options|= OPTION_FOUND_COMMENT;
/* Reject '/' '*', since we might need to turn off the echo */
- lip->yyUnget();
+ yyUnget();
- lip->save_in_comment_state();
+ save_in_comment_state();
- if (lip->yyPeekn(2) == '!' ||
- (lip->yyPeekn(2) == 'M' && lip->yyPeekn(3) == '!'))
+ if (yyPeekn(2) == '!' ||
+ (yyPeekn(2) == 'M' && yyPeekn(3) == '!'))
{
- bool maria_comment_syntax= lip->yyPeekn(2) == 'M';
- lip->in_comment= DISCARD_COMMENT;
+ bool maria_comment_syntax= yyPeekn(2) == 'M';
+ in_comment= DISCARD_COMMENT;
/* Accept '/' '*' '!', but do not keep this marker. */
- lip->set_echo(FALSE);
- lip->yySkipn(maria_comment_syntax ? 4 : 3);
+ set_echo(FALSE);
+ yySkipn(maria_comment_syntax ? 4 : 3);
/*
The special comment format is very strict:
@@ -1923,24 +1723,24 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
50114 -> 5.1.14
100000 -> 10.0.0
*/
- if ( my_isdigit(cs, lip->yyPeekn(0))
- && my_isdigit(cs, lip->yyPeekn(1))
- && my_isdigit(cs, lip->yyPeekn(2))
- && my_isdigit(cs, lip->yyPeekn(3))
- && my_isdigit(cs, lip->yyPeekn(4))
+ if ( my_isdigit(cs, yyPeekn(0))
+ && my_isdigit(cs, yyPeekn(1))
+ && my_isdigit(cs, yyPeekn(2))
+ && my_isdigit(cs, yyPeekn(3))
+ && my_isdigit(cs, yyPeekn(4))
)
{
ulong version;
uint length= 5;
- char *end_ptr= (char*) lip->get_ptr()+length;
+ char *end_ptr= (char*) get_ptr() + length;
int error;
- if (my_isdigit(cs, lip->yyPeekn(5)))
+ if (my_isdigit(cs, yyPeekn(5)))
{
end_ptr++; // 6 digit number
length++;
}
- version= (ulong) my_strtoll10(lip->get_ptr(), &end_ptr, &error);
+ version= (ulong) my_strtoll10(get_ptr(), &end_ptr, &error);
/*
MySQL-5.7 has new features and might have new SQL syntax that
@@ -1952,31 +1752,31 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
(version < 50700 || version > 99999 || maria_comment_syntax))
{
/* Accept 'M' 'm' 'm' 'd' 'd' */
- lip->yySkipn(length);
+ yySkipn(length);
/* Expand the content of the special comment as real code */
- lip->set_echo(TRUE);
+ set_echo(TRUE);
state=MY_LEX_START;
break; /* Do not treat contents as a comment. */
}
else
{
#ifdef WITH_WSREP
- if (WSREP(thd) && version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE)
- {
- WSREP_DEBUG("consistency check: %s", thd->query());
- thd->wsrep_consistency_check= CONSISTENCY_CHECK_DECLARED;
- lip->yySkipn(5);
- lip->set_echo(TRUE);
- state=MY_LEX_START;
- break; /* Do not treat contents as a comment. */
- }
+ if (WSREP(thd) && version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE)
+ {
+ WSREP_DEBUG("consistency check: %s", thd->query());
+ thd->wsrep_consistency_check= CONSISTENCY_CHECK_DECLARED;
+ yySkipn(5);
+ set_echo(TRUE);
+ state= MY_LEX_START;
+ break; /* Do not treat contents as a comment. */
+ }
#endif /* WITH_WSREP */
/*
Patch and skip the conditional comment to avoid it
being propagated infinitely (eg. to a slave).
*/
- char *pcom= lip->yyUnput(' ');
- comment_closed= ! consume_comment(lip, 1);
+ char *pcom= yyUnput(' ');
+ comment_closed= ! consume_comment(1);
if (! comment_closed)
{
*pcom= '!';
@@ -1988,16 +1788,16 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
{
/* Not a version comment. */
state=MY_LEX_START;
- lip->set_echo(TRUE);
+ set_echo(TRUE);
break;
}
}
else
{
- lip->in_comment= PRESERVE_COMMENT;
- lip->yySkip(); // Accept /
- lip->yySkip(); // Accept *
- comment_closed= ! consume_comment(lip, 0);
+ in_comment= PRESERVE_COMMENT;
+ yySkip(); // Accept /
+ yySkip(); // Accept *
+ comment_closed= ! consume_comment(0);
/* regular comments can have zero comments inside. */
}
/*
@@ -2011,140 +1811,364 @@ static int lex_one_token(YYSTYPE *yylval, THD *thd)
/#!VERSI oned containing /# regular #/ is allowed #/
- Inside one versioned comment, another versioned comment
- is treated as a regular discardable comment. It gets
- no special parsing.
+ Inside one versioned comment, another versioned comment
+ is treated as a regular discardable comment. It gets
+ no special parsing.
*/
/* Unbalanced comments with a missing '*' '/' are a syntax error */
if (! comment_closed)
return (ABORT_SYM);
state = MY_LEX_START; // Try again
- lip->restore_in_comment_state();
+ restore_in_comment_state();
break;
case MY_LEX_END_LONG_COMMENT:
- if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/')
+ if ((in_comment != NO_COMMENT) && yyPeek() == '/')
{
/* Reject '*' '/' */
- lip->yyUnget();
+ yyUnget();
/* Accept '*' '/', with the proper echo */
- lip->set_echo(lip->in_comment == PRESERVE_COMMENT);
- lip->yySkipn(2);
+ set_echo(in_comment == PRESERVE_COMMENT);
+ yySkipn(2);
/* And start recording the tokens again */
- lip->set_echo(TRUE);
- lip->in_comment=NO_COMMENT;
+ set_echo(TRUE);
+ in_comment= NO_COMMENT;
state=MY_LEX_START;
}
else
- state=MY_LEX_CHAR; // Return '*'
+ state= MY_LEX_CHAR; // Return '*'
break;
- case MY_LEX_SET_VAR: // Check if ':='
- if (lip->yyPeek() != '=')
+ case MY_LEX_SET_VAR: // Check if ':='
+ if (yyPeek() != '=')
{
- state=MY_LEX_CHAR; // Return ':'
- break;
+ state= MY_LEX_CHAR; // Return ':'
+ break;
}
- lip->yySkip();
+ yySkip();
return (SET_VAR);
- case MY_LEX_SEMICOLON: // optional line terminator
+ case MY_LEX_SEMICOLON: // optional line terminator
state= MY_LEX_CHAR; // Return ';'
break;
case MY_LEX_EOL:
- if (lip->eof())
+ if (eof())
{
- lip->yyUnget(); // Reject the last '\0'
- lip->set_echo(FALSE);
- lip->yySkip();
- lip->set_echo(TRUE);
+ yyUnget(); // Reject the last '\0'
+ set_echo(FALSE);
+ yySkip();
+ set_echo(TRUE);
/* Unbalanced comments with a missing '*' '/' are a syntax error */
- if (lip->in_comment != NO_COMMENT)
+ if (in_comment != NO_COMMENT)
return (ABORT_SYM);
- lip->next_state=MY_LEX_END; // Mark for next loop
+ next_state= MY_LEX_END; // Mark for next loop
return(END_OF_INPUT);
}
state=MY_LEX_CHAR;
break;
case MY_LEX_END:
- lip->next_state=MY_LEX_END;
- return(0); // We found end of input last time
+ next_state= MY_LEX_END;
+ return(0); // We found end of input last time
/* Actually real shouldn't start with . but allow them anyhow */
case MY_LEX_REAL_OR_POINT:
- if (my_isdigit(cs,(c= lip->yyPeek())))
- state = MY_LEX_REAL; // Real
+ if (my_isdigit(cs, (c= yyPeek())))
+ state = MY_LEX_REAL; // Real
else if (c == '.')
{
- lip->yySkip();
+ yySkip();
return DOT_DOT_SYM;
}
else
{
- state= MY_LEX_IDENT_SEP; // return '.'
- lip->yyUnget(); // Put back '.'
+ state= MY_LEX_IDENT_SEP; // return '.'
+ yyUnget(); // Put back '.'
}
break;
- case MY_LEX_USER_END: // end '@' of user@hostname
- switch (state_map[(uchar) lip->yyPeek()]) {
+ case MY_LEX_USER_END: // end '@' of user@hostname
+ switch (state_map[(uchar) yyPeek()]) {
case MY_LEX_STRING:
case MY_LEX_USER_VARIABLE_DELIMITER:
case MY_LEX_STRING_OR_DELIMITER:
- break;
+ break;
case MY_LEX_USER_END:
- lip->next_state=MY_LEX_SYSTEM_VAR;
- break;
+ next_state= MY_LEX_SYSTEM_VAR;
+ break;
default:
- lip->next_state=MY_LEX_HOSTNAME;
- break;
+ next_state= MY_LEX_HOSTNAME;
+ break;
}
- yylval->lex_str.str=(char*) lip->get_ptr();
- yylval->lex_str.length=1;
+ yylval->lex_str.str= (char*) get_ptr();
+ yylval->lex_str.length= 1;
return((int) '@');
- case MY_LEX_HOSTNAME: // end '@' of user@hostname
- for (c=lip->yyGet() ;
- my_isalnum(cs,c) || c == '.' || c == '_' || c == '$';
- c= lip->yyGet()) ;
- yylval->lex_str=get_token(lip, 0, lip->yyLength());
+ case MY_LEX_HOSTNAME: // end '@' of user@hostname
+ for (c= yyGet() ;
+ my_isalnum(cs, c) || c == '.' || c == '_' || c == '$';
+ c= yyGet()) ;
+ yylval->lex_str= get_token(0, yyLength());
return(LEX_HOSTNAME);
case MY_LEX_SYSTEM_VAR:
- yylval->lex_str.str=(char*) lip->get_ptr();
- yylval->lex_str.length=1;
- lip->yySkip(); // Skip '@'
- lip->next_state= (state_map[(uchar) lip->yyPeek()] ==
- MY_LEX_USER_VARIABLE_DELIMITER ?
- MY_LEX_OPERATOR_OR_IDENT :
- MY_LEX_IDENT_OR_KEYWORD);
+ yylval->lex_str.str= (char*) get_ptr();
+ yylval->lex_str.length= 1;
+ yySkip(); // Skip '@'
+ next_state= (state_map[(uchar) yyPeek()] ==
+ MY_LEX_USER_VARIABLE_DELIMITER ?
+ MY_LEX_OPERATOR_OR_IDENT :
+ MY_LEX_IDENT_OR_KEYWORD);
return((int) '@');
case MY_LEX_IDENT_OR_KEYWORD:
/*
- We come here when we have found two '@' in a row.
- We should now be able to handle:
- [(global | local | session) .]variable_name
+ We come here when we have found two '@' in a row.
+ We should now be able to handle:
+ [(global | local | session) .]variable_name
*/
+ return scan_ident_sysvar(thd, &yylval->ident_cli);
+ }
+ }
+}
+
+
+bool Lex_input_stream::get_7bit_or_8bit_ident(THD *thd, uchar *last_char)
+{
+ uchar c;
+ CHARSET_INFO *const cs= thd->charset();
+ const uchar *const ident_map= cs->ident_map;
+ bool is_8bit= false;
+ for ( ; ident_map[c= yyGet()]; )
+ {
+ if (c & 0x80)
+ is_8bit= true; // will convert
+ }
+ *last_char= c;
+ return is_8bit;
+}
- for (result_state= 0; ident_map[c= lip->yyGet()]; result_state|= c)
- ;
- /* If there were non-ASCII characters, mark that we must convert */
- result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
-
- if (c == '.')
- lip->next_state=MY_LEX_IDENT_SEP;
- length= lip->yyLength();
- if (length == 0)
- return(ABORT_SYM); // Names must be nonempty.
- if ((tokval= find_keyword(lip, length,0)))
- {
- lip->yyUnget(); // Put back 'c'
- return(tokval); // Was keyword
- }
- yylval->lex_str=get_token(lip, 0, length);
- lip->body_utf8_append(lip->m_cpp_text_start);
+int Lex_input_stream::scan_ident_sysvar(THD *thd, Lex_ident_cli_st *str)
+{
+ uchar last_char;
+ uint length;
+ int tokval;
+ bool is_8bit;
+ DBUG_ASSERT(m_tok_start == m_ptr);
+
+ is_8bit= get_7bit_or_8bit_ident(thd, &last_char);
+
+ if (last_char == '.')
+ next_state= MY_LEX_IDENT_SEP;
+ if (!(length= yyLength()))
+ return ABORT_SYM; // Names must be nonempty.
+ if ((tokval= find_keyword(str, length, 0)))
+ {
+ yyUnget(); // Put back 'c'
+ return tokval; // Was keyword
+ }
- lip->body_utf8_append_ident(thd, &yylval->lex_str, lip->m_cpp_text_end);
+ yyUnget(); // ptr points now after last token char
+ str->set_ident(m_tok_start, length, is_8bit);
- return(result_state);
+ m_cpp_text_start= m_cpp_tok_start;
+ m_cpp_text_end= m_cpp_text_start + length;
+ body_utf8_append(m_cpp_text_start);
+ body_utf8_append_ident(thd, str, m_cpp_text_end);
+
+ return is_8bit ? IDENT_QUOTED : IDENT;
+}
+
+
+/*
+ We can come here if different parsing stages:
+ - In an identifier chain:
+ SELECT t1.cccc FROM t1;
+ (when the "cccc" part starts)
+ In this case both m_tok_start and m_ptr point to "cccc".
+ - When a sequence of digits has changed to something else,
+ therefore the token becomes an identifier rather than a number:
+ SELECT 12345_6 FROM t1;
+ In this case m_tok_start points to the entire "12345_678",
+ while m_ptr points to "678".
+*/
+int Lex_input_stream::scan_ident_start(THD *thd, Lex_ident_cli_st *str)
+{
+ uchar c;
+ bool is_8bit;
+ CHARSET_INFO *const cs= thd->charset();
+ const uchar *const ident_map= cs->ident_map;
+ DBUG_ASSERT(m_tok_start <= m_ptr);
+
+ if (use_mb(cs))
+ {
+ is_8bit= true;
+ while (ident_map[c= yyGet()])
+ {
+ int char_length= my_charlen(cs, get_ptr() - 1, get_end_of_query());
+ if (char_length <= 0)
+ break;
+ skip_binary(char_length - 1);
}
}
+ else
+ {
+ is_8bit= get_7bit_or_8bit_ident(thd, &c);
+ }
+ if (c == '.' && ident_map[(uchar) yyPeek()])
+ next_state= MY_LEX_IDENT_SEP;// Next is '.'
+
+ uint length= yyLength();
+ yyUnget(); // ptr points now after last token char
+ str->set_ident(m_tok_start, length, is_8bit);
+ m_cpp_text_start= m_cpp_tok_start;
+ m_cpp_text_end= m_cpp_text_start + length;
+ body_utf8_append(m_cpp_text_start);
+ body_utf8_append_ident(thd, str, m_cpp_text_end);
+ return is_8bit ? IDENT_QUOTED : IDENT;
+}
+
+
+int Lex_input_stream::scan_ident_middle(THD *thd, Lex_ident_cli_st *str,
+ CHARSET_INFO **introducer,
+ my_lex_states *st)
+{
+ CHARSET_INFO *const cs= thd->charset();
+ const uchar *const ident_map= cs->ident_map;
+ const uchar *const state_map= cs->state_map;
+ const char *start;
+ uint length;
+ uchar c;
+ bool is_8bit;
+ bool resolve_introducer= true;
+ DBUG_ASSERT(m_ptr == m_tok_start + 1); // m_ptr points to the second byte
+
+ if (use_mb(cs))
+ {
+ is_8bit= true;
+ int char_length= my_charlen(cs, get_ptr() - 1, get_end_of_query());
+ if (char_length <= 0)
+ {
+ *st= MY_LEX_CHAR;
+ return 0;
+ }
+ skip_binary(char_length - 1);
+
+ while (ident_map[c= yyGet()])
+ {
+ char_length= my_charlen(cs, get_ptr() - 1, get_end_of_query());
+ if (char_length <= 0)
+ break;
+ if (char_length > 1 || (c & 0x80))
+ resolve_introducer= false;
+ skip_binary(char_length - 1);
+ }
+ }
+ else
+ {
+ is_8bit= get_7bit_or_8bit_ident(thd, &c) || (m_tok_start[0] & 0x80);
+ resolve_introducer= !is_8bit;
+ }
+ length= yyLength();
+ start= get_ptr();
+ if (ignore_space)
+ {
+ /*
+ If we find a space then this can't be an identifier. We notice this
+ below by checking start != lex->ptr.
+ */
+ for (; state_map[(uchar) c] == MY_LEX_SKIP ; c= yyGet())
+ {
+ if (c == '\n')
+ yylineno++;
+ }
+ }
+ if (start == get_ptr() && c == '.' && ident_map[(uchar) yyPeek()])
+ next_state= MY_LEX_IDENT_SEP;
+ else
+ { // '(' must follow directly if function
+ int tokval;
+ yyUnget();
+ if ((tokval= find_keyword(str, length, c == '(')))
+ {
+ next_state= MY_LEX_START; // Allow signed numbers
+ return(tokval); // Was keyword
+ }
+ yySkip(); // next state does a unget
+ }
+
+ /*
+ Note: "SELECT _bla AS 'alias'"
+ _bla should be considered as a IDENT if charset haven't been found.
+ So we don't use MYF(MY_WME) with get_charset_by_csname to avoid
+ producing an error.
+ */
+ DBUG_ASSERT(length > 0);
+ if (resolve_introducer && m_tok_start[0] == '_')
+ {
+
+ yyUnget(); // ptr points now after last token char
+ str->set_ident(m_tok_start, length, false);
+
+ m_cpp_text_start= m_cpp_tok_start;
+ m_cpp_text_end= m_cpp_text_start + length;
+ body_utf8_append(m_cpp_text_start, m_cpp_tok_start + length);
+ ErrConvString csname(str->str + 1, str->length - 1, &my_charset_bin);
+ CHARSET_INFO *cs= get_charset_by_csname(csname.ptr(),
+ MY_CS_PRIMARY, MYF(0));
+ if (cs)
+ {
+ *introducer= cs;
+ return UNDERSCORE_CHARSET;
+ }
+ return IDENT;
+ }
+
+ yyUnget(); // ptr points now after last token char
+ str->set_ident(m_tok_start, length, is_8bit);
+ m_cpp_text_start= m_cpp_tok_start;
+ m_cpp_text_end= m_cpp_text_start + length;
+ body_utf8_append(m_cpp_text_start);
+ body_utf8_append_ident(thd, str, m_cpp_text_end);
+ return is_8bit ? IDENT_QUOTED : IDENT;
+}
+
+
+int Lex_input_stream::scan_ident_delimited(THD *thd,
+ Lex_ident_cli_st *str)
+{
+ CHARSET_INFO *const cs= thd->charset();
+ uint double_quotes= 0;
+ uchar c, quote_char= m_tok_start[0];
+ DBUG_ASSERT(m_ptr == m_tok_start + 1);
+
+ while ((c= yyGet()))
+ {
+ int var_length= my_charlen(cs, get_ptr() - 1, get_end_of_query());
+ if (var_length == 1)
+ {
+ if (c == quote_char)
+ {
+ if (yyPeek() != quote_char)
+ break;
+ c= yyGet();
+ double_quotes++;
+ continue;
+ }
+ }
+ else if (var_length > 1)
+ {
+ skip_binary(var_length - 1);
+ }
+ }
+
+ str->set_ident_quoted(m_tok_start + 1, yyLength() - 1, true, quote_char);
+ yyUnget(); // ptr points now after last token char
+
+ m_cpp_text_start= m_cpp_tok_start + 1;
+ m_cpp_text_end= m_cpp_text_start + str->length;
+
+ if (c == quote_char)
+ yySkip(); // Skip end `
+ next_state= MY_LEX_START;
+ body_utf8_append(m_cpp_text_start);
+ // QQQ: shouldn't it add unescaped version ????
+ body_utf8_append_ident(thd, str, m_cpp_text_end);
+ return IDENT_QUOTED;
}
@@ -2251,6 +2275,7 @@ void st_select_lex::init_query()
select_n_having_items= 0;
n_sum_items= 0;
n_child_sum_items= 0;
+ hidden_bit_fields= 0;
subquery_in_having= explicit_limit= 0;
is_item_list_lookup= 0;
first_execution= 1;
@@ -2298,6 +2323,7 @@ void st_select_lex::init_select()
select_limit= 0; /* denotes the default limit = HA_POS_ERROR */
offset_limit= 0; /* denotes the default offset = 0 */
with_sum_func= 0;
+ with_all_modifier= 0;
is_correlated= 0;
cur_pos_in_select_list= UNDEF_POS;
cond_value= having_value= Item::COND_UNDEF;
@@ -2367,7 +2393,7 @@ void st_select_lex_node::add_slave(st_select_lex_node *slave_arg)
ref - references on reference on this node
*/
void st_select_lex_node::include_standalone(st_select_lex_node *upper,
- st_select_lex_node **ref)
+ st_select_lex_node **ref)
{
next= 0;
prev= ref;
@@ -2432,7 +2458,7 @@ void st_select_lex_node::fast_exclude()
*/
st_select_lex_node *st_select_lex_node:: insert_chain_before(
- st_select_lex_node **ptr_pos_to_insert,
+ st_select_lex_node **ptr_pos_to_insert,
st_select_lex_node *end_chain_node)
{
end_chain_node->link_next= *ptr_pos_to_insert;
@@ -2787,6 +2813,10 @@ ulong st_select_lex::get_table_join_options()
bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
{
+
+ if (!((options & SELECT_DISTINCT) && !group_list.elements))
+ hidden_bit_fields= 0;
+
// find_order_in_list() may need some extra space, so multiply by two.
order_group_num*= 2;
@@ -2801,7 +2831,8 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
select_n_reserved +
select_n_having_items +
select_n_where_fields +
- order_group_num) * 5;
+ order_group_num +
+ hidden_bit_fields) * 5;
if (!ref_pointer_array.is_null())
{
/*
@@ -2815,7 +2846,7 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
return false;
}
Item **array= static_cast<Item**>(arena->alloc(sizeof(Item*) * n_elems));
- if (array != NULL)
+ if (likely(array != NULL))
ref_pointer_array= Ref_ptr_array(array, n_elems);
return array == NULL;
@@ -3130,11 +3161,11 @@ bool LEX::can_be_merged()
}
return (selects_allow_merge &&
- select_lex.group_list.elements == 0 &&
- select_lex.having == 0 &&
+ select_lex.group_list.elements == 0 &&
+ select_lex.having == 0 &&
select_lex.with_sum_func == 0 &&
- select_lex.table_list.elements >= 1 &&
- !(select_lex.options & SELECT_DISTINCT) &&
+ select_lex.table_list.elements >= 1 &&
+ !(select_lex.options & SELECT_DISTINCT) &&
select_lex.select_limit == 0);
}
@@ -3515,14 +3546,14 @@ void LEX::set_trg_event_type_for_tables()
SYNOPSIS
unlink_first_table()
- link_to_local Set to 1 if caller should link this table to local list
+ link_to_local Set to 1 if caller should link this table to local list
NOTES
We assume that first tables in both lists is the same table or the local
list is empty.
RETURN
- 0 If 'query_tables' == 0
+ 0 If 'query_tables' == 0
unlinked table
In this case link_to_local is set.
@@ -3549,7 +3580,7 @@ TABLE_LIST *LEX::unlink_first_table(bool *link_to_local)
select_lex.context.table_list=
select_lex.context.first_name_resolution_table= first->next_local;
select_lex.table_list.first= first->next_local;
- select_lex.table_list.elements--; //safety
+ select_lex.table_list.elements--; //safety
first->next_local= 0;
/*
Ensure that the global list has the same first table as the local
@@ -3611,14 +3642,14 @@ void LEX::first_lists_tables_same()
SYNOPSIS
link_first_table_back()
- link_to_local do we need link this table to local
+ link_to_local do we need link this table to local
RETURN
global list
*/
void LEX::link_first_table_back(TABLE_LIST *first,
- bool link_to_local)
+ bool link_to_local)
{
if (first)
{
@@ -3633,7 +3664,7 @@ void LEX::link_first_table_back(TABLE_LIST *first,
first->next_local= select_lex.table_list.first;
select_lex.context.table_list= first;
select_lex.table_list.first= first;
- select_lex.table_list.elements++; //safety
+ select_lex.table_list.elements++; //safety
}
}
}
@@ -3928,15 +3959,15 @@ bool st_select_lex::optimize_unflattened_subqueries(bool const_only)
{
if (!subquery_predicate->fixed)
{
- /*
- This subquery was excluded as part of some expression so it is
- invisible from all prepared expression.
+ /*
+ This subquery was excluded as part of some expression so it is
+ invisible from all prepared expression.
*/
- next_unit= un->next_unit();
- un->exclude_level();
- if (next_unit)
- continue;
- break;
+ next_unit= un->next_unit();
+ un->exclude_level();
+ if (next_unit)
+ continue;
+ break;
}
if (subquery_predicate->substype() == Item_subselect::IN_SUBS)
{
@@ -4257,7 +4288,7 @@ bool SELECT_LEX::merge_subquery(THD *thd, TABLE_LIST *derived,
for (uint i= 0; i < cnt; i++)
{
if (subq_select->expr_cache_may_be_used[i])
- expr_cache_may_be_used[i]= true;
+ expr_cache_may_be_used[i]= true;
}
List_iterator_fast<Item_func_in> it(subq_select->in_funcs);
@@ -4323,7 +4354,7 @@ void SELECT_LEX::update_used_tables()
for (embedding= tl->embedding; embedding; embedding=embedding->embedding)
{
if (embedding->is_view_or_derived())
- {
+ {
DBUG_ASSERT(embedding->is_merged_derived());
TABLE *tab= tl->table;
tab->covering_keys= tab->s->keys_for_keyread;
@@ -4355,7 +4386,7 @@ void SELECT_LEX::update_used_tables()
bool maybe_null;
if ((maybe_null= MY_TEST(embedding->outer_join)))
{
- tl->table->maybe_null= maybe_null;
+ tl->table->maybe_null= maybe_null;
break;
}
}
@@ -4867,14 +4898,14 @@ bool LEX::set_arena_for_set_stmt(Query_arena *backup)
if (!mem_root_for_set_stmt)
{
mem_root_for_set_stmt= new MEM_ROOT();
- if (!(mem_root_for_set_stmt))
+ if (unlikely(!(mem_root_for_set_stmt)))
DBUG_RETURN(1);
init_sql_alloc(mem_root_for_set_stmt, "set_stmt",
ALLOC_ROOT_SET, ALLOC_ROOT_SET, MYF(MY_THREAD_SPECIFIC));
}
- if (!(arena_for_set_stmt= new(mem_root_for_set_stmt)
- Query_arena_memroot(mem_root_for_set_stmt,
- Query_arena::STMT_INITIALIZED)))
+ if (unlikely(!(arena_for_set_stmt= new(mem_root_for_set_stmt)
+ Query_arena_memroot(mem_root_for_set_stmt,
+ Query_arena::STMT_INITIALIZED))))
DBUG_RETURN(1);
DBUG_PRINT("info", ("mem_root: %p arena: %p",
mem_root_for_set_stmt,
@@ -4987,6 +5018,8 @@ int st_select_lex_unit::save_union_explain(Explain_query *output)
Explain_union *eu=
new (output->mem_root) Explain_union(output->mem_root,
thd->lex->analyze_stmt);
+ if (unlikely(!eu))
+ return 0;
if (with_element && with_element->is_recursive)
eu->is_recursive_cte= true;
@@ -5121,9 +5154,9 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
/* add SELECT list*/
Item *item= new (thd->mem_root)
Item_field(thd, context, NULL, NULL, &star_clex_str);
- if (item == NULL)
+ if (unlikely(item == NULL))
DBUG_RETURN(TRUE);
- if (add_item_to_list(thd, item))
+ if (unlikely(add_item_to_list(thd, item)))
DBUG_RETURN(TRUE);
(dummy_select->with_wild)++;
@@ -5136,20 +5169,21 @@ bool LEX::add_unit_in_brackets(SELECT_LEX *nselect)
SELECT_LEX_UNIT *unit= nselect->master_unit();
Table_ident *ti= new (thd->mem_root) Table_ident(unit);
- if (ti == NULL)
+ if (unlikely(ti == NULL))
DBUG_RETURN(TRUE);
char buff[10];
LEX_CSTRING alias;
alias.length= my_snprintf(buff, sizeof(buff),
"__%u", dummy_select->select_number);
alias.str= thd->strmake(buff, alias.length);
- if (!alias.str)
+ if (unlikely(!alias.str))
DBUG_RETURN(TRUE);
TABLE_LIST *table_list;
- if (!(table_list= dummy_select->add_table_to_list(thd, ti, &alias,
- 0, TL_READ,
- MDL_SHARED_READ)))
+ if (unlikely(!(table_list=
+ dummy_select->add_table_to_list(thd, ti, &alias,
+ 0, TL_READ,
+ MDL_SHARED_READ))))
DBUG_RETURN(TRUE);
context->resolve_in_table_list_only(table_list);
dummy_select->add_joined_table(table_list);
@@ -5248,12 +5282,26 @@ LEX::find_variable(const LEX_CSTRING *name,
}
+static bool is_new(const char *str)
+{
+ return (str[0] == 'n' || str[0] == 'N') &&
+ (str[1] == 'e' || str[1] == 'E') &&
+ (str[2] == 'w' || str[2] == 'W');
+}
+
+static bool is_old(const char *str)
+{
+ return (str[0] == 'o' || str[0] == 'O') &&
+ (str[1] == 'l' || str[1] == 'L') &&
+ (str[2] == 'd' || str[2] == 'D');
+}
+
+
bool LEX::is_trigger_new_or_old_reference(const LEX_CSTRING *name) const
{
+ // "name" is not necessarily NULL-terminated!
return sphead && sphead->m_handler->type() == TYPE_ENUM_TRIGGER &&
- name->length == 3 &&
- (!my_strcasecmp(system_charset_info, name->str, "NEW") ||
- !my_strcasecmp(system_charset_info, name->str, "OLD"));
+ name->length == 3 && (is_new(name->str) || is_old(name->str));
}
@@ -5272,7 +5320,7 @@ bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars,
Item *dflt_value_item)
{
if (!dflt_value_item &&
- !(dflt_value_item= new (thd->mem_root) Item_null(thd)))
+ unlikely(!(dflt_value_item= new (thd->mem_root) Item_null(thd))))
return true;
for (uint i= 0 ; i < (uint) nvars ; i++)
@@ -5286,7 +5334,7 @@ bool LEX::sp_variable_declarations_set_default(THD *thd, int nvars,
spcont, &sp_rcontext_handler_local,
spvar->offset, dflt_value_item,
this, last);
- if (is == NULL || sphead->add_instr(is))
+ if (unlikely(is == NULL || sphead->add_instr(is)))
return true;
}
return false;
@@ -5310,7 +5358,8 @@ LEX::sp_variable_declarations_copy_type_finalize(THD *thd, int nvars,
}
spvar->field_def.field_name= spvar->name;
}
- if (sp_variable_declarations_set_default(thd, nvars, default_value))
+ if (unlikely(sp_variable_declarations_set_default(thd, nvars,
+ default_value)))
return true;
spcont->declare_var_boundary(0);
return sphead->restore_lex(thd);
@@ -5411,7 +5460,8 @@ LEX::sp_variable_declarations_table_rowtype_finalize(THD *thd, int nvars,
Item *def)
{
Table_ident *table_ref;
- if (!(table_ref= new (thd->mem_root) Table_ident(thd, &db, &table, false)))
+ if (unlikely(!(table_ref=
+ new (thd->mem_root) Table_ident(thd, &db, &table, false))))
return true;
// Loop through all variables in the same declaration
for (uint i= 0 ; i < (uint) nvars; i++)
@@ -5451,7 +5501,7 @@ LEX::sp_variable_declarations_cursor_rowtype_finalize(THD *thd, int nvars,
sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
}
- if (sp_variable_declarations_set_default(thd, nvars, def))
+ if (unlikely(sp_variable_declarations_set_default(thd, nvars, def)))
return true;
// Make sure sp_rcontext is created using the invoker security context:
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
@@ -5574,7 +5624,7 @@ sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
spvar->field_def.set_handler(&type_handler_longlong);
type_handler_longlong.Column_definition_prepare_stage2(&spvar->field_def,
NULL, HA_CAN_GEOMETRY);
- if (!value && !(value= new (thd->mem_root) Item_null(thd)))
+ if (!value && unlikely(!(value= new (thd->mem_root) Item_null(thd))))
return NULL;
spvar->default_value= value;
@@ -5583,7 +5633,7 @@ sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
spcont, &sp_rcontext_handler_local,
spvar->offset, value,
this, true);
- if (is == NULL || sphead->add_instr(is))
+ if (unlikely(is == NULL || sphead->add_instr(is)))
return NULL;
spcont->declare_var_boundary(0);
return spvar;
@@ -5600,14 +5650,16 @@ bool LEX::sp_for_loop_implicit_cursor_statement(THD *thd,
if (sp_declare_cursor(thd, &name, cur, NULL, true))
return true;
DBUG_ASSERT(thd->lex == this);
- if (!(bounds->m_index= new (thd->mem_root) sp_assignment_lex(thd, this)))
+ if (unlikely(!(bounds->m_index=
+ new (thd->mem_root) sp_assignment_lex(thd, this))))
return true;
bounds->m_index->sp_lex_in_use= true;
sphead->reset_lex(thd, bounds->m_index);
DBUG_ASSERT(thd->lex != this);
- if (!(item= new (thd->mem_root) Item_field(thd,
- thd->lex->current_context(),
- NullS, NullS, &name)))
+ if (unlikely(!(item=
+ new (thd->mem_root) Item_field(thd,
+ thd->lex->current_context(),
+ NullS, NullS, &name))))
return true;
bounds->m_index->set_item_and_free_list(item, NULL);
if (thd->lex->sphead->restore_lex(thd))
@@ -5632,13 +5684,14 @@ LEX::sp_add_for_loop_cursor_variable(THD *thd,
return NULL;
spcont->declare_var_boundary(1);
sphead->fill_spvar_definition(thd, &spvar->field_def, &spvar->name);
- if (!(spvar->default_value= new (thd->mem_root) Item_null(thd)))
+ if (unlikely(!(spvar->default_value= new (thd->mem_root) Item_null(thd))))
return NULL;
spvar->field_def.set_cursor_rowtype_ref(coffset);
- if (sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor, coffset,
- param_lex, parameters))
+ if (unlikely(sphead->add_for_loop_open_cursor(thd, spcont, spvar, pcursor,
+ coffset,
+ param_lex, parameters)))
return NULL;
spcont->declare_var_boundary(0);
@@ -5661,7 +5714,7 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
args[i]= new (thd->mem_root)
Item_splocal(thd, &sp_rcontext_handler_local,
&src->name, src->offset, src->type_handler());
- if (args[i] == NULL)
+ if (unlikely(args[i] == NULL))
return true;
#ifdef DBUG_ASSERT_EXISTS
args[i]->m_sp= sphead;
@@ -5671,7 +5724,7 @@ bool LEX::sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop)
Item *expr= loop.m_direction > 0 ?
(Item *) new (thd->mem_root) Item_func_le(thd, args[0], args[1]) :
(Item *) new (thd->mem_root) Item_func_ge(thd, args[0], args[1]);
- return !expr || sp_while_loop_expression(thd, expr);
+ return unlikely(!expr) || unlikely(sp_while_loop_expression(thd, expr));
}
@@ -5683,7 +5736,7 @@ bool LEX::sp_for_loop_intrange_condition_test(THD *thd,
{
spcont->set_for_loop(loop);
sphead->reset_lex(thd);
- if (thd->lex->sp_for_loop_condition(thd, loop))
+ if (unlikely(thd->lex->sp_for_loop_condition(thd, loop)))
return true;
return thd->lex->sphead->restore_lex(thd);
}
@@ -5698,8 +5751,10 @@ bool LEX::sp_for_loop_cursor_condition_test(THD *thd,
sphead->reset_lex(thd);
cursor_name= spcont->find_cursor(loop.m_cursor_offset);
DBUG_ASSERT(cursor_name);
- if (!(expr= new (thd->mem_root) Item_func_cursor_found(thd, cursor_name,
- loop.m_cursor_offset)))
+ if (unlikely(!(expr=
+ new (thd->mem_root)
+ Item_func_cursor_found(thd, cursor_name,
+ loop.m_cursor_offset))))
return true;
if (thd->lex->sp_while_loop_expression(thd, expr))
return true;
@@ -5711,13 +5766,16 @@ bool LEX::sp_for_loop_intrange_declarations(THD *thd, Lex_for_loop_st *loop,
const LEX_CSTRING *index,
const Lex_for_loop_bounds_st &bounds)
{
- if (!(loop->m_index=
- bounds.m_index->sp_add_for_loop_variable(thd, index,
- bounds.m_index->get_item())))
+ if (unlikely(!(loop->m_index=
+ bounds.m_index->
+ sp_add_for_loop_variable(thd, index,
+ bounds.m_index->get_item()))))
return true;
- if (!(loop->m_upper_bound=
- bounds.m_upper_bound->sp_add_for_loop_upper_bound(thd,
- bounds.m_upper_bound->get_item())))
+ if (unlikely(!(loop->m_upper_bound=
+ bounds.m_upper_bound->
+ sp_add_for_loop_upper_bound(thd,
+ bounds.
+ m_upper_bound->get_item()))))
return true;
loop->m_direction= bounds.m_direction;
loop->m_implicit_cursor= 0;
@@ -5770,8 +5828,9 @@ bool LEX::sp_for_loop_cursor_declarations(THD *thd,
thd->parse_error();
return true;
}
- if (!(pcursor= spcont->find_cursor_with_error(&name, &coffs, false)) ||
- pcursor->check_param_count_with_error(param_count))
+ if (unlikely(!(pcursor= spcont->find_cursor_with_error(&name, &coffs,
+ false)) ||
+ pcursor->check_param_count_with_error(param_count)))
return true;
if (!(loop->m_index= sp_add_for_loop_cursor_variable(thd, index,
@@ -5796,18 +5855,19 @@ bool LEX::sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop)
Item_splocal(thd, &sp_rcontext_handler_local,
&loop.m_index->name, loop.m_index->offset,
loop.m_index->type_handler());
- if (splocal == NULL)
+ if (unlikely(splocal == NULL))
return true;
#ifdef DBUG_ASSERT_EXISTS
splocal->m_sp= sphead;
#endif
Item_int *inc= new (thd->mem_root) Item_int(thd, loop.m_direction);
- if (!inc)
+ if (unlikely(!inc))
return true;
Item *expr= new (thd->mem_root) Item_func_plus(thd, splocal, inc);
- if (!expr ||
- sphead->set_local_variable(thd, spcont, &sp_rcontext_handler_local,
- loop.m_index, expr, this, true))
+ if (unlikely(!expr) ||
+ unlikely(sphead->set_local_variable(thd, spcont,
+ &sp_rcontext_handler_local,
+ loop.m_index, expr, this, true)))
return true;
return false;
}
@@ -5819,8 +5879,8 @@ bool LEX::sp_for_loop_intrange_finalize(THD *thd, const Lex_for_loop_st &loop)
// Generate FOR LOOP index increment in its own lex
DBUG_ASSERT(this != thd->lex);
- if (thd->lex->sp_for_loop_increment(thd, loop) ||
- thd->lex->sphead->restore_lex(thd))
+ if (unlikely(thd->lex->sp_for_loop_increment(thd, loop) ||
+ thd->lex->sphead->restore_lex(thd)))
return true;
// Generate a jump to the beginning of the loop
@@ -5834,7 +5894,7 @@ bool LEX::sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &loop)
sp_instr_cfetch *instr=
new (thd->mem_root) sp_instr_cfetch(sphead->instructions(),
spcont, loop.m_cursor_offset, false);
- if (instr == NULL || sphead->add_instr(instr))
+ if (unlikely(instr == NULL) || unlikely(sphead->add_instr(instr)))
return true;
instr->add_to_varlist(loop.m_index);
// Generate a jump to the beginning of the loop
@@ -5857,7 +5917,7 @@ bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
}
cursor_stmt->set_cursor_name(name);
- if (spcont->add_cursor(name, param_ctx, cursor_stmt))
+ if (unlikely(spcont->add_cursor(name, param_ctx, cursor_stmt)))
return true;
if (add_cpush_instr)
@@ -5865,7 +5925,7 @@ bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
i= new (thd->mem_root)
sp_instr_cpush(sphead->instructions(), spcont, cursor_stmt,
spcont->current_cursor_count() - 1);
- return i == NULL || sphead->add_instr(i);
+ return unlikely(i == NULL) || unlikely(sphead->add_instr(i));
}
return false;
}
@@ -5900,15 +5960,17 @@ bool LEX::sp_handler_declaration_init(THD *thd, int type)
sp_instr_hpush_jump *i=
new (thd->mem_root) sp_instr_hpush_jump(sphead->instructions(), spcont, h);
- if (i == NULL || sphead->add_instr(i))
+ if (unlikely(i == NULL) || unlikely(sphead->add_instr(i)))
return true;
/* For continue handlers, mark end of handler scope. */
if (type == sp_handler::CONTINUE &&
- sphead->push_backpatch(thd, i, spcont->last_label()))
+ unlikely(sphead->push_backpatch(thd, i, spcont->last_label())))
return true;
- if (sphead->push_backpatch(thd, i, spcont->push_label(thd, &empty_clex_str, 0)))
+ if (unlikely(sphead->push_backpatch(thd, i,
+ spcont->push_label(thd, &empty_clex_str,
+ 0))))
return true;
return false;
@@ -5923,16 +5985,16 @@ bool LEX::sp_handler_declaration_finalize(THD *thd, int type)
if (type == sp_handler::CONTINUE)
{
i= new (thd->mem_root) sp_instr_hreturn(sphead->instructions(), spcont);
- if (i == NULL ||
- sphead->add_instr(i))
+ if (unlikely(i == NULL) ||
+ unlikely(sphead->add_instr(i)))
return true;
}
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
i= new (thd->mem_root) sp_instr_hreturn(sphead->instructions(), spcont);
- if (i == NULL ||
- sphead->add_instr(i) ||
- sphead->push_backpatch(thd, i, spcont->last_label())) /* Block end */
+ if (unlikely(i == NULL) ||
+ unlikely(sphead->add_instr(i)) ||
+ unlikely(sphead->push_backpatch(thd, i, spcont->last_label()))) /* Block end */
return true;
}
sphead->backpatch(hlab);
@@ -5960,16 +6022,16 @@ bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
{
i= new (thd->mem_root)
sp_instr_hpop(sp->instructions(), ctx, spblock.hndlrs);
- if (i == NULL ||
- sp->add_instr(i))
+ if (unlikely(i == NULL) ||
+ unlikely(sp->add_instr(i)))
return true;
}
if (spblock.curs)
{
i= new (thd->mem_root)
sp_instr_cpop(sp->instructions(), ctx, spblock.curs);
- if (i == NULL ||
- sp->add_instr(i))
+ if (unlikely(i == NULL) ||
+ unlikely(sp->add_instr(i)))
return true;
}
spcont= ctx->pop_context();
@@ -5982,11 +6044,11 @@ bool LEX::sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
const LEX_CSTRING *end_label)
{
sp_label *splabel;
- if (sp_block_finalize(thd, spblock, &splabel))
+ if (unlikely(sp_block_finalize(thd, spblock, &splabel)))
return true;
- if (end_label->str &&
- lex_string_cmp(system_charset_info,
- end_label, &splabel->name) != 0)
+ if (unlikely(end_label->str &&
+ lex_string_cmp(system_charset_info,
+ end_label, &splabel->name) != 0))
{
my_error(ER_SP_LABEL_MISMATCH, MYF(0), end_label->str);
return true;
@@ -5999,9 +6061,9 @@ sp_name *LEX::make_sp_name(THD *thd, const LEX_CSTRING *name)
{
sp_name *res;
LEX_CSTRING db;
- if (check_routine_name(name) ||
- copy_db_to(&db) ||
- (!(res= new (thd->mem_root) sp_name(&db, name, false))))
+ if (unlikely(check_routine_name(name)) ||
+ unlikely(copy_db_to(&db)) ||
+ unlikely((!(res= new (thd->mem_root) sp_name(&db, name, false)))))
return NULL;
return res;
}
@@ -6023,7 +6085,7 @@ sp_name *LEX::make_sp_name(THD *thd, const LEX_CSTRING *name)
sp_name *LEX::make_sp_name_package_routine(THD *thd, const LEX_CSTRING *name)
{
sp_name *res= make_sp_name(thd, name);
- if (res && strchr(res->m_name.str, '.'))
+ if (likely(res) && unlikely(strchr(res->m_name.str, '.')))
{
my_error(ER_SP_WRONG_NAME, MYF(0), res->m_name.str);
res= NULL;
@@ -6037,15 +6099,16 @@ sp_name *LEX::make_sp_name(THD *thd, const LEX_CSTRING *name1,
{
sp_name *res;
LEX_CSTRING norm_name1;
- if (!name1->str ||
- !thd->make_lex_string(&norm_name1, name1->str, name1->length) ||
- check_db_name((LEX_STRING *) &norm_name1))
+ if (unlikely(!name1->str) ||
+ unlikely(!thd->make_lex_string(&norm_name1, name1->str,
+ name1->length)) ||
+ unlikely(check_db_name((LEX_STRING *) &norm_name1)))
{
my_error(ER_WRONG_DB_NAME, MYF(0), name1->str);
return NULL;
}
- if (check_routine_name(name2) ||
- (!(res= new (thd->mem_root) sp_name(&norm_name1, name2, true))))
+ if (unlikely(check_routine_name(name2)) ||
+ unlikely(!(res= new (thd->mem_root) sp_name(&norm_name1, name2, true))))
return NULL;
return res;
}
@@ -6058,7 +6121,7 @@ sp_head *LEX::make_sp_head(THD *thd, const sp_name *name,
sp_head *sp;
/* Order is important here: new - reset - init */
- if ((sp= new sp_head(package, sph)))
+ if (likely((sp= new sp_head(package, sph))))
{
sp->reset_thd_mem_root(thd);
sp->init(this);
@@ -6210,13 +6273,13 @@ bool LEX::sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive)
if ((n= spcont->diff_handlers(ctx, exclusive)))
{
sp_instr_hpop *hpop= new (thd->mem_root) sp_instr_hpop(ip++, spcont, n);
- if (hpop == NULL || sphead->add_instr(hpop))
+ if (unlikely(hpop == NULL) || unlikely(sphead->add_instr(hpop)))
return true;
}
if ((n= spcont->diff_cursors(ctx, exclusive)))
{
sp_instr_cpop *cpop= new (thd->mem_root) sp_instr_cpop(ip++, spcont, n);
- if (cpop == NULL || sphead->add_instr(cpop))
+ if (unlikely(cpop == NULL) || unlikely(sphead->add_instr(cpop)))
return true;
}
return false;
@@ -6226,7 +6289,7 @@ bool LEX::sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive)
bool LEX::sp_leave_statement(THD *thd, const LEX_CSTRING *label_name)
{
sp_label *lab= spcont->find_label(label_name);
- if (!lab)
+ if (unlikely(!lab))
{
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", label_name->str);
return true;
@@ -6266,7 +6329,7 @@ bool LEX::sp_push_goto_label(THD *thd, const LEX_CSTRING *label_name)
sp_label *lab= spcont->find_goto_label(label_name, false);
if (lab)
{
- if (lab->ip != 0)
+ if (unlikely(lab->ip != 0))
{
my_error(ER_SP_LABEL_REDEFINE, MYF(0), label_name->str);
return true;
@@ -6310,9 +6373,9 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
sp_instr_jump_if_not(sphead->instructions(),
spcont,
when, thd->lex);
- if (i == NULL ||
- sphead->add_instr(i) ||
- sp_exit_block(thd, lab))
+ if (unlikely(i == NULL) ||
+ unlikely(sphead->add_instr(i)) ||
+ unlikely(sp_exit_block(thd, lab)))
return true;
i->backpatch(sphead->instructions(), spcont);
return false;
@@ -6322,7 +6385,7 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
bool LEX::sp_exit_statement(THD *thd, Item *item)
{
sp_label *lab= spcont->find_label_current_loop_start();
- if (!lab)
+ if (unlikely(!lab))
{
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", "");
return true;
@@ -6335,7 +6398,7 @@ bool LEX::sp_exit_statement(THD *thd, Item *item)
bool LEX::sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item)
{
sp_label *lab= spcont->find_label(label_name);
- if (!lab || lab->type != sp_label::ITERATION)
+ if (unlikely(!lab || lab->type != sp_label::ITERATION))
{
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", label_name->str);
return true;
@@ -6347,7 +6410,7 @@ bool LEX::sp_exit_statement(THD *thd, const LEX_CSTRING *label_name, Item *item)
bool LEX::sp_iterate_statement(THD *thd, const LEX_CSTRING *label_name)
{
sp_label *lab= spcont->find_label(label_name);
- if (!lab || lab->type != sp_label::ITERATION)
+ if (unlikely(!lab || lab->type != sp_label::ITERATION))
{
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", label_name->str);
return true;
@@ -6383,9 +6446,9 @@ bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when)
sp_instr_jump_if_not(sphead->instructions(),
spcont,
when, thd->lex);
- if (i == NULL ||
- sphead->add_instr(i) ||
- sp_continue_loop(thd, lab))
+ if (unlikely(i == NULL) ||
+ unlikely(sphead->add_instr(i)) ||
+ unlikely(sp_continue_loop(thd, lab)))
return true;
i->backpatch(sphead->instructions(), spcont);
return false;
@@ -6395,7 +6458,7 @@ bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when)
bool LEX::sp_continue_statement(THD *thd, Item *when)
{
sp_label *lab= spcont->find_label_current_loop_start();
- if (!lab)
+ if (unlikely(!lab))
{
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "CONTINUE", "");
return true;
@@ -6483,11 +6546,11 @@ bool LEX::sp_while_loop_expression(THD *thd, Item *expr)
{
sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(sphead->instructions(), spcont, expr, this);
- return i == NULL ||
- /* Jumping forward */
- sphead->push_backpatch(thd, i, spcont->last_label()) ||
- sphead->new_cont_backpatch(i) ||
- sphead->add_instr(i);
+ return (unlikely(i == NULL) ||
+ /* Jumping forward */
+ unlikely(sphead->push_backpatch(thd, i, spcont->last_label())) ||
+ unlikely(sphead->new_cont_backpatch(i)) ||
+ unlikely(sphead->add_instr(i)));
}
@@ -6496,8 +6559,8 @@ bool LEX::sp_while_loop_finalize(THD *thd)
sp_label *lab= spcont->last_label(); /* Jumping back */
sp_instr_jump *i= new (thd->mem_root)
sp_instr_jump(sphead->instructions(), spcont, lab->ip);
- if (i == NULL ||
- sphead->add_instr(i))
+ if (unlikely(i == NULL) ||
+ unlikely(sphead->add_instr(i)))
return true;
sphead->do_cont_backpatch();
return false;
@@ -6510,13 +6573,13 @@ Item *LEX::create_and_link_Item_trigger_field(THD *thd,
{
Item_trigger_field *trg_fld;
- if (trg_chistics.event == TRG_EVENT_INSERT && !new_row)
+ if (unlikely(trg_chistics.event == TRG_EVENT_INSERT && !new_row))
{
my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
return NULL;
}
- if (trg_chistics.event == TRG_EVENT_DELETE && new_row)
+ if (unlikely(trg_chistics.event == TRG_EVENT_DELETE && new_row))
{
my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
return NULL;
@@ -6538,22 +6601,64 @@ Item *LEX::create_and_link_Item_trigger_field(THD *thd,
Let us add this item to list of all Item_trigger_field objects
in trigger.
*/
- if (trg_fld)
- trg_table_fields.link_in_list(trg_fld, &trg_fld->next_trg_field);
+ if (likely(trg_fld))
+ trg_table_fields.link_in_list(trg_fld, &trg_fld->next_trg_field);
return trg_fld;
}
+Item *LEX::make_item_colon_ident_ident(THD *thd,
+ const Lex_ident_cli_st *ca,
+ const Lex_ident_cli_st *cb)
+{
+ Lex_ident_sys a(thd, ca), b(thd, cb);
+ if (a.is_null() || b.is_null())
+ return NULL; // OEM
+ if (!is_trigger_new_or_old_reference(&a))
+ {
+ thd->parse_error();
+ return NULL;
+ }
+ bool new_row= (a.str[0] == 'N' || a.str[0] == 'n');
+ return create_and_link_Item_trigger_field(thd, &b, new_row);
+}
+
+
+Item *LEX::make_item_sysvar(THD *thd,
+ enum_var_type type,
+ const LEX_CSTRING *name,
+ const LEX_CSTRING *component)
+
+{
+ Item *item;
+ DBUG_ASSERT(name->str);
+ /*
+ "SELECT @@global.global.variable" is not allowed
+ Note, "global" can come through TEXT_STRING_sys.
+ */
+ if (component->str && unlikely(check_reserved_words(name)))
+ {
+ thd->parse_error();
+ return NULL;
+ }
+ if (unlikely(!(item= get_system_var(thd, type, name, component))))
+ return NULL;
+ if (!((Item_func_get_system_var*) item)->is_written_to_binlog())
+ set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_VARIABLE);
+ return item;
+}
+
+
Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name,
const char *start, const char *end)
{
- if (!thd->m_parser_state->m_lip.stmt_prepare_mode)
+ if (unlikely(!thd->m_parser_state->m_lip.stmt_prepare_mode))
{
thd->parse_error(ER_SYNTAX_ERROR, start);
return NULL;
}
- if (!parsing_options.allows_variable)
+ if (unlikely(!parsing_options.allows_variable))
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
return NULL;
@@ -6562,7 +6667,7 @@ Item_param *LEX::add_placeholder(THD *thd, const LEX_CSTRING *name,
Query_fragment pos(thd, sphead, start, end);
Item_param *item= new (thd->mem_root) Item_param(thd, name,
pos.pos(), pos.length());
- if (!item || param_list.push_back(item, thd->mem_root))
+ if (unlikely(!item) || unlikely(param_list.push_back(item, thd->mem_root)))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
return NULL;
@@ -6590,8 +6695,8 @@ bool LEX::add_resignal_statement(THD *thd, const sp_condition_value *v)
Item *LEX::create_item_ident_nospvar(THD *thd,
- const LEX_CSTRING *a,
- const LEX_CSTRING *b)
+ const Lex_ident_sys_st *a,
+ const Lex_ident_sys_st *b)
{
DBUG_ASSERT(this == thd->lex);
/*
@@ -6606,7 +6711,7 @@ Item *LEX::create_item_ident_nospvar(THD *thd,
return create_and_link_Item_trigger_field(thd, b, new_row);
}
- if (current_select->no_table_names_allowed)
+ if (unlikely(current_select->no_table_names_allowed))
{
my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), a->str, thd->where);
return NULL;
@@ -6622,13 +6727,13 @@ Item *LEX::create_item_ident_nospvar(THD *thd,
Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
const Sp_rcontext_handler *rh,
- const LEX_CSTRING *a,
- const LEX_CSTRING *b,
+ const Lex_ident_sys *a,
+ const Lex_ident_sys *b,
sp_variable *spv,
const char *start,
const char *end)
{
- if (!parsing_options.allows_variable)
+ if (unlikely(!parsing_options.allows_variable))
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
return NULL;
@@ -6639,24 +6744,24 @@ Item_splocal *LEX::create_item_spvar_row_field(THD *thd,
if (spv->field_def.is_table_rowtype_ref() ||
spv->field_def.is_cursor_rowtype_ref())
{
- if (!(item= new (thd->mem_root)
- Item_splocal_row_field_by_name(thd, rh, a, b, spv->offset,
- &type_handler_null,
- pos.pos(), pos.length())))
+ if (unlikely(!(item= new (thd->mem_root)
+ Item_splocal_row_field_by_name(thd, rh, a, b, spv->offset,
+ &type_handler_null,
+ pos.pos(), pos.length()))))
return NULL;
}
else
{
uint row_field_offset;
const Spvar_definition *def;
- if (!(def= spv->find_row_field(a, b, &row_field_offset)))
+ if (unlikely(!(def= spv->find_row_field(a, b, &row_field_offset))))
return NULL;
- if (!(item= new (thd->mem_root)
- Item_splocal_row_field(thd, rh, a, b,
- spv->offset, row_field_offset,
- def->type_handler(),
- pos.pos(), pos.length())))
+ if (unlikely(!(item= new (thd->mem_root)
+ Item_splocal_row_field(thd, rh, a, b,
+ spv->offset, row_field_offset,
+ def->type_handler(),
+ pos.pos(), pos.length()))))
return NULL;
}
#ifdef DBUG_ASSERT_EXISTS
@@ -6671,7 +6776,7 @@ my_var *LEX::create_outvar(THD *thd, const LEX_CSTRING *name)
{
const Sp_rcontext_handler *rh;
sp_variable *spv;
- if ((spv= find_variable(name, &rh)))
+ if (likely((spv= find_variable(name, &rh))))
return result ? new (thd->mem_root)
my_var_sp(rh, name, spv->offset,
spv->type_handler(), sphead) :
@@ -6687,7 +6792,7 @@ my_var *LEX::create_outvar(THD *thd,
{
const Sp_rcontext_handler *rh;
sp_variable *t;
- if (!(t= find_variable(a, &rh)))
+ if (unlikely(!(t= find_variable(a, &rh))))
{
my_error(ER_SP_UNDECLARED_VAR, MYF(0), a->str);
return NULL;
@@ -6705,11 +6810,12 @@ my_var *LEX::create_outvar(THD *thd,
Item *LEX::create_item_func_nextval(THD *thd, Table_ident *table_ident)
{
TABLE_LIST *table;
- if (!(table= current_select->add_table_to_list(thd, table_ident, 0,
- TL_OPTION_SEQUENCE,
- TL_WRITE_ALLOW_WRITE,
- MDL_SHARED_WRITE)))
+ if (unlikely(!(table= current_select->add_table_to_list(thd, table_ident, 0,
+ TL_OPTION_SEQUENCE,
+ TL_WRITE_ALLOW_WRITE,
+ MDL_SHARED_WRITE))))
return NULL;
+ thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
return new (thd->mem_root) Item_func_nextval(thd, table);
}
@@ -6717,11 +6823,12 @@ Item *LEX::create_item_func_nextval(THD *thd, Table_ident *table_ident)
Item *LEX::create_item_func_lastval(THD *thd, Table_ident *table_ident)
{
TABLE_LIST *table;
- if (!(table= current_select->add_table_to_list(thd, table_ident, 0,
- TL_OPTION_SEQUENCE,
- TL_READ,
- MDL_SHARED_READ)))
+ if (unlikely(!(table= current_select->add_table_to_list(thd, table_ident, 0,
+ TL_OPTION_SEQUENCE,
+ TL_READ,
+ MDL_SHARED_READ))))
return NULL;
+ thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
return new (thd->mem_root) Item_func_lastval(thd, table);
}
@@ -6731,7 +6838,8 @@ Item *LEX::create_item_func_nextval(THD *thd,
const LEX_CSTRING *name)
{
Table_ident *table_ident;
- if (!(table_ident= new (thd->mem_root) Table_ident(thd, db, name, false)))
+ if (unlikely(!(table_ident=
+ new (thd->mem_root) Table_ident(thd, db, name, false))))
return NULL;
return create_item_func_nextval(thd, table_ident);
}
@@ -6742,7 +6850,8 @@ Item *LEX::create_item_func_lastval(THD *thd,
const LEX_CSTRING *name)
{
Table_ident *table_ident;
- if (!(table_ident= new (thd->mem_root) Table_ident(thd, db, name, false)))
+ if (unlikely(!(table_ident=
+ new (thd->mem_root) Table_ident(thd, db, name, false))))
return NULL;
return create_item_func_lastval(thd, table_ident);
}
@@ -6753,10 +6862,10 @@ Item *LEX::create_item_func_setval(THD *thd, Table_ident *table_ident,
bool is_used)
{
TABLE_LIST *table;
- if (!(table= current_select->add_table_to_list(thd, table_ident, 0,
- TL_OPTION_SEQUENCE,
- TL_WRITE_ALLOW_WRITE,
- MDL_SHARED_WRITE)))
+ if (unlikely(!(table= current_select->add_table_to_list(thd, table_ident, 0,
+ TL_OPTION_SEQUENCE,
+ TL_WRITE_ALLOW_WRITE,
+ MDL_SHARED_WRITE))))
return NULL;
return new (thd->mem_root) Item_func_setval(thd, table, nextval, round,
is_used);
@@ -6764,38 +6873,45 @@ Item *LEX::create_item_func_setval(THD *thd, Table_ident *table_ident,
Item *LEX::create_item_ident(THD *thd,
- const LEX_CSTRING *a,
- const LEX_CSTRING *b,
- const char *start, const char *end)
+ const Lex_ident_cli_st *ca,
+ const Lex_ident_cli_st *cb)
{
+ const char *start= ca->pos();
+ const char *end= cb->end();
const Sp_rcontext_handler *rh;
sp_variable *spv;
- if ((spv= find_variable(a, &rh)) &&
+ DBUG_ASSERT(thd->m_parser_state->m_lip.get_buf() <= start);
+ DBUG_ASSERT(start <= end);
+ DBUG_ASSERT(end <= thd->m_parser_state->m_lip.get_end_of_query());
+ Lex_ident_sys a(thd, ca), b(thd, cb);
+ if (a.is_null() || b.is_null())
+ return NULL; // OEM
+ if ((spv= find_variable(&a, &rh)) &&
(spv->field_def.is_row() ||
spv->field_def.is_table_rowtype_ref() ||
spv->field_def.is_cursor_rowtype_ref()))
- return create_item_spvar_row_field(thd, rh, a, b, spv, start, end);
+ return create_item_spvar_row_field(thd, rh, &a, &b, spv, start, end);
- if ((thd->variables.sql_mode & MODE_ORACLE) && b->length == 7)
+ if ((thd->variables.sql_mode & MODE_ORACLE) && b.length == 7)
{
if (!my_strnncoll(system_charset_info,
- (const uchar *) b->str, 7,
+ (const uchar *) b.str, 7,
(const uchar *) "NEXTVAL", 7))
- return create_item_func_nextval(thd, &null_clex_str, a);
+ return create_item_func_nextval(thd, &null_clex_str, &a);
else if (!my_strnncoll(system_charset_info,
- (const uchar *) b->str, 7,
+ (const uchar *) b.str, 7,
(const uchar *) "CURRVAL", 7))
- return create_item_func_lastval(thd, &null_clex_str, a);
+ return create_item_func_lastval(thd, &null_clex_str, &a);
}
- return create_item_ident_nospvar(thd, a, b);
+ return create_item_ident_nospvar(thd, &a, &b);
}
Item *LEX::create_item_ident(THD *thd,
- const LEX_CSTRING *a,
- const LEX_CSTRING *b,
- const LEX_CSTRING *c)
+ const Lex_ident_sys_st *a,
+ const Lex_ident_sys_st *b,
+ const Lex_ident_sys_st *c)
{
const char *schema= (thd->client_capabilities & CLIENT_NO_SCHEMA ?
NullS : a->str);
@@ -6826,23 +6942,29 @@ Item *LEX::create_item_ident(THD *thd,
}
-Item *LEX::create_item_limit(THD *thd,
- const LEX_CSTRING *a,
- const char *start, const char *end)
+Item *LEX::create_item_limit(THD *thd, const Lex_ident_cli_st *ca)
{
+ DBUG_ASSERT(thd->m_parser_state->m_lip.get_buf() <= ca->pos());
+ DBUG_ASSERT(ca->pos() <= ca->end());
+ DBUG_ASSERT(ca->end() <= thd->m_parser_state->m_lip.get_end_of_query());
+
const Sp_rcontext_handler *rh;
sp_variable *spv;
- if (!(spv= find_variable(a, &rh)))
+ Lex_ident_sys sa(thd, ca);
+ if (sa.is_null())
+ return NULL; // EOM
+ if (!(spv= find_variable(&sa, &rh)))
{
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), a->str);
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), sa.str);
return NULL;
}
- Query_fragment pos(thd, sphead, start, end);
+ Query_fragment pos(thd, sphead, ca->pos(), ca->end());
Item_splocal *item;
- if (!(item= new (thd->mem_root) Item_splocal(thd, rh, a,
- spv->offset, spv->type_handler(),
- pos.pos(), pos.length())))
+ if (unlikely(!(item= new (thd->mem_root)
+ Item_splocal(thd, rh, &sa,
+ spv->offset, spv->type_handler(),
+ pos.pos(), pos.length()))))
return NULL;
#ifdef DBUG_ASSERT_EXISTS
item->m_sp= sphead;
@@ -6858,21 +6980,28 @@ Item *LEX::create_item_limit(THD *thd,
Item *LEX::create_item_limit(THD *thd,
- const LEX_CSTRING *a,
- const LEX_CSTRING *b,
- const char *start, const char *end)
+ const Lex_ident_cli_st *ca,
+ const Lex_ident_cli_st *cb)
{
+ DBUG_ASSERT(thd->m_parser_state->m_lip.get_buf() <= ca->pos());
+ DBUG_ASSERT(ca->pos() <= cb->end());
+ DBUG_ASSERT(cb->end() <= thd->m_parser_state->m_lip.get_end_of_query());
+
const Sp_rcontext_handler *rh;
sp_variable *spv;
- if (!(spv= find_variable(a, &rh)))
+ Lex_ident_sys sa(thd, ca), sb(thd, cb);
+ if (unlikely(sa.is_null() || sb.is_null()))
+ return NULL; // EOM
+ if (!(spv= find_variable(&sa, &rh)))
{
- my_error(ER_SP_UNDECLARED_VAR, MYF(0), a->str);
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), sa.str);
return NULL;
}
// Qualified %TYPE variables are not possible
DBUG_ASSERT(!spv->field_def.column_type_ref());
Item_splocal *item;
- if (!(item= create_item_spvar_row_field(thd, rh, a, b, spv, start, end)))
+ if (unlikely(!(item= create_item_spvar_row_field(thd, rh, &sa, &sb, spv,
+ ca->pos(), cb->end()))))
return NULL;
if (!item->is_valid_limit_clause_variable_with_error())
return NULL;
@@ -6885,15 +7014,17 @@ bool LEX::set_user_variable(THD *thd, const LEX_CSTRING *name, Item *val)
{
Item_func_set_user_var *item;
set_var_user *var;
- if (!(item= new (thd->mem_root) Item_func_set_user_var(thd, name, val)) ||
- !(var= new (thd->mem_root) set_var_user(item)))
+ if (unlikely(!(item= new (thd->mem_root) Item_func_set_user_var(thd, name,
+ val))) ||
+ unlikely(!(var= new (thd->mem_root) set_var_user(item))))
+ return true;
+ if (unlikely(var_list.push_back(var, thd->mem_root)))
return true;
- var_list.push_back(var, thd->mem_root);
return false;
}
-Item *LEX::create_item_ident_nosp(THD *thd, LEX_CSTRING *name)
+Item *LEX::create_item_ident_nosp(THD *thd, Lex_ident_sys_st *name)
{
if (current_select->parsing_place != IN_HAVING ||
current_select->get_in_sum_expr() > 0)
@@ -6905,10 +7036,14 @@ Item *LEX::create_item_ident_nosp(THD *thd, LEX_CSTRING *name)
}
-Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
+Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
const char *start,
const char *end)
{
+ DBUG_ASSERT(thd->m_parser_state->m_lip.get_buf() <= start);
+ DBUG_ASSERT(start <= end);
+ DBUG_ASSERT(end <= thd->m_parser_state->m_lip.get_end_of_query());
+
const Sp_rcontext_handler *rh;
sp_variable *spv;
DBUG_ASSERT(spcont);
@@ -6931,7 +7066,7 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
new (thd->mem_root) Item_splocal(thd, rh, name,
spv->offset, spv->type_handler(),
pos.pos(), pos.length());
- if (splocal == NULL)
+ if (unlikely(splocal == NULL))
return NULL;
#ifdef DBUG_ASSERT_EXISTS
splocal->m_sp= sphead;
@@ -6942,9 +7077,9 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_CSTRING *name,
if (thd->variables.sql_mode & MODE_ORACLE)
{
- if (!my_strcasecmp(system_charset_info, name->str, "SQLCODE"))
+ if (lex_string_eq(name, STRING_WITH_LEN("SQLCODE")))
return new (thd->mem_root) Item_func_sqlcode(thd);
- if (!my_strcasecmp(system_charset_info, name->str, "SQLERRM"))
+ if (lex_string_eq(name, STRING_WITH_LEN("SQLERRM")))
return new (thd->mem_root) Item_func_sqlerrm(thd);
}
return create_item_ident_nosp(thd, name);
@@ -7004,7 +7139,7 @@ bool LEX::set_default_system_variable(enum_var_type var_type,
sys_var *var= find_sys_var(thd, name->str, name->length);
if (!var)
return true;
- if (!var->is_struct())
+ if (unlikely(!var->is_struct()))
{
my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name->str);
return true;
@@ -7019,7 +7154,7 @@ bool LEX::set_system_variable(enum_var_type var_type,
{
sys_var *var= find_sys_var(thd, name->str, name->length);
DBUG_ASSERT(thd->is_error() || var != NULL);
- return var ? set_system_variable(var_type, var, &null_clex_str, val) : true;
+ return likely(var) ? set_system_variable(var_type, var, &null_clex_str, val) : true;
}
@@ -7029,14 +7164,15 @@ bool LEX::set_system_variable(THD *thd, enum_var_type var_type,
Item *val)
{
sys_var *tmp;
- if (check_reserved_words(name1) ||
- !(tmp= find_sys_var_ex(thd, name2->str, name2->length, true, false)))
+ if (unlikely(check_reserved_words(name1)) ||
+ unlikely(!(tmp= find_sys_var_ex(thd, name2->str, name2->length, true,
+ false))))
{
my_error(ER_UNKNOWN_STRUCTURED_VARIABLE, MYF(0),
(int) name1->length, name1->str);
return true;
}
- if (!tmp->is_struct())
+ if (unlikely(!tmp->is_struct()))
{
my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name2->str);
return true;
@@ -7049,17 +7185,17 @@ bool LEX::set_trigger_field(const LEX_CSTRING *name1, const LEX_CSTRING *name2,
Item *val)
{
DBUG_ASSERT(is_trigger_new_or_old_reference(name1));
- if (name1->str[0]=='O' || name1->str[0]=='o')
+ if (unlikely(name1->str[0]=='O' || name1->str[0]=='o'))
{
my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", "");
return true;
}
- if (trg_chistics.event == TRG_EVENT_DELETE)
+ if (unlikely(trg_chistics.event == TRG_EVENT_DELETE))
{
my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
return true;
}
- if (trg_chistics.action_time == TRG_ACTION_AFTER)
+ if (unlikely(trg_chistics.action_time == TRG_ACTION_AFTER))
{
my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
return true;
@@ -7366,8 +7502,8 @@ Item *st_select_lex::build_cond_for_grouping_fields(THD *thd, Item *cond,
}
else
new_cond= new (thd->mem_root) Item_cond_or(thd);
- if (!new_cond)
- return 0;
+ if (unlikely(!new_cond))
+ return 0;
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
while ((item=li++))
@@ -7380,7 +7516,7 @@ Item *st_select_lex::build_cond_for_grouping_fields(THD *thd, Item *cond,
}
Item *fix= build_cond_for_grouping_fields(thd, item,
no_top_clones & cond_and);
- if (!fix)
+ if (unlikely(!fix))
{
if (cond_and)
continue;
@@ -7398,7 +7534,7 @@ Item *st_select_lex::build_cond_for_grouping_fields(THD *thd, Item *cond,
switch (new_cond->argument_list()->elements)
{
case 0:
- return 0;
+ return 0;
case 1:
return new_cond->argument_list()->head();
default:
@@ -7413,12 +7549,12 @@ int set_statement_var_if_exists(THD *thd, const char *var_name,
size_t var_name_length, ulonglong value)
{
sys_var *sysvar;
- if (thd->lex->sql_command == SQLCOM_CREATE_VIEW)
+ if (unlikely(thd->lex->sql_command == SQLCOM_CREATE_VIEW))
{
my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), "[NO]WAIT");
return 1;
}
- if (thd->lex->sphead)
+ if (unlikely(thd->lex->sphead))
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "[NO]WAIT");
return 1;
@@ -7429,7 +7565,8 @@ int set_statement_var_if_exists(THD *thd, const char *var_name,
set_var *var= new (thd->mem_root) set_var(thd, OPT_SESSION, sysvar,
&null_clex_str, item);
- if (!item || !var || thd->lex->stmt_var_list.push_back(var, thd->mem_root))
+ if (unlikely(!item) || unlikely(!var) ||
+ unlikely(thd->lex->stmt_var_list.push_back(var, thd->mem_root)))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
return 1;
@@ -7452,7 +7589,7 @@ bool LEX::sp_add_cfetch(THD *thd, const LEX_CSTRING *name)
i= new (thd->mem_root)
sp_instr_cfetch(sphead->instructions(), spcont, offset,
!(thd->variables.sql_mode & MODE_ORACLE));
- if (i == NULL || sphead->add_instr(i))
+ if (unlikely(i == NULL) || unlikely(sphead->add_instr(i)))
return true;
return false;
}
@@ -7462,10 +7599,10 @@ bool LEX::create_or_alter_view_finalize(THD *thd, Table_ident *table_ident)
{
sql_command= SQLCOM_CREATE_VIEW;
/* first table in list is target VIEW name */
- if (!select_lex.add_table_to_list(thd, table_ident, NULL,
- TL_OPTION_UPDATING,
- TL_IGNORE,
- MDL_EXCLUSIVE))
+ if (unlikely(!select_lex.add_table_to_list(thd, table_ident, NULL,
+ TL_OPTION_UPDATING,
+ TL_IGNORE,
+ MDL_EXCLUSIVE)))
return true;
query_tables->open_strategy= TABLE_LIST::OPEN_STUB;
return false;
@@ -7476,13 +7613,13 @@ bool LEX::add_alter_view(THD *thd, uint16 algorithm,
enum_view_suid suid,
Table_ident *table_ident)
{
- if (sphead)
+ if (unlikely(sphead))
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "ALTER VIEW");
return true;
}
- if (!(create_view= new (thd->mem_root)
- Create_view_info(VIEW_ALTER, algorithm, suid)))
+ if (unlikely(!(create_view= new (thd->mem_root)
+ Create_view_info(VIEW_ALTER, algorithm, suid))))
return true;
return create_or_alter_view_finalize(thd, table_ident);
}
@@ -7492,13 +7629,13 @@ bool LEX::add_create_view(THD *thd, DDL_options_st ddl,
uint16 algorithm, enum_view_suid suid,
Table_ident *table_ident)
{
- if (set_create_options_with_check(ddl))
+ if (unlikely(set_create_options_with_check(ddl)))
return true;
- if (!(create_view= new (thd->mem_root)
- Create_view_info(ddl.or_replace() ?
- VIEW_CREATE_OR_REPLACE :
- VIEW_CREATE_NEW,
- algorithm, suid)))
+ if (unlikely(!(create_view= new (thd->mem_root)
+ Create_view_info(ddl.or_replace() ?
+ VIEW_CREATE_OR_REPLACE :
+ VIEW_CREATE_NEW,
+ algorithm, suid))))
return true;
return create_or_alter_view_finalize(thd, table_ident);
}
@@ -7510,10 +7647,10 @@ bool LEX::call_statement_start(THD *thd, sp_name *name)
const Sp_handler *sph= &sp_handler_procedure;
sql_command= SQLCOM_CALL;
value_list.empty();
- if (sph->sp_resolve_package_routine(thd, thd->lex->sphead,
- name, &sph, &pkgname))
+ if (unlikely(sph->sp_resolve_package_routine(thd, thd->lex->sphead,
+ name, &sph, &pkgname)))
return true;
- if (!(m_sql_cmd= new (thd->mem_root) Sql_cmd_call(name, sph)))
+ if (unlikely(!(m_sql_cmd= new (thd->mem_root) Sql_cmd_call(name, sph))))
return true;
sph->add_used_routine(this, thd, name);
if (pkgname.m_name.length)
@@ -7525,7 +7662,7 @@ bool LEX::call_statement_start(THD *thd, sp_name *name)
bool LEX::call_statement_start(THD *thd, const LEX_CSTRING *name)
{
sp_name *spname= make_sp_name(thd, name);
- return !spname || call_statement_start(thd, spname);
+ return unlikely(!spname) || call_statement_start(thd, spname);
}
@@ -7533,7 +7670,7 @@ bool LEX::call_statement_start(THD *thd, const LEX_CSTRING *name1,
const LEX_CSTRING *name2)
{
sp_name *spname= make_sp_name(thd, name1, name2);
- return !spname || call_statement_start(thd, spname);
+ return unlikely(!spname) || call_statement_start(thd, spname);
}
@@ -7550,12 +7687,13 @@ sp_package *LEX::create_package_start(THD *thd,
DDL_options_st options)
{
sp_package *pkg;
- if (sphead)
+
+ if (unlikely(sphead))
{
my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), sph->type_str());
return NULL;
}
- if (set_command_with_check(command, options))
+ if (unlikely(set_command_with_check(command, options)))
return NULL;
if (sph->type() == TYPE_ENUM_PACKAGE_BODY)
{
@@ -7577,7 +7715,7 @@ sp_package *LEX::create_package_start(THD *thd,
sp_head *spec;
int ret= sp_handler_package_spec.
sp_cache_routine_reentrant(thd, name_arg, &spec);
- if (!spec)
+ if (unlikely(!spec))
{
if (!ret)
my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
@@ -7585,7 +7723,7 @@ sp_package *LEX::create_package_start(THD *thd,
return 0;
}
}
- if (!(pkg= new sp_package(this, name_arg, sph)))
+ if (unlikely(!(pkg= new sp_package(this, name_arg, sph))))
return NULL;
pkg->reset_thd_mem_root(thd);
pkg->init(this);
@@ -7613,7 +7751,8 @@ bool LEX::create_package_finalize(THD *thd,
return true;
}
sphead->m_body.length= body_end - body_start;
- if (!(sphead->m_body.str= thd->strmake(body_start, sphead->m_body.length)))
+ if (unlikely(!(sphead->m_body.str= thd->strmake(body_start,
+ sphead->m_body.length))))
return true;
size_t not_used;
@@ -7670,20 +7809,24 @@ Item *LEX::make_item_func_replace(THD *thd,
}
-bool SELECT_LEX::vers_push_field(THD *thd, TABLE_LIST *table, const LEX_CSTRING field_name)
+bool SELECT_LEX::vers_push_field(THD *thd, TABLE_LIST *table,
+ const LEX_CSTRING field_name)
{
DBUG_ASSERT(field_name.str);
Item_field *fld= new (thd->mem_root) Item_field(thd, &context,
- table->db.str, table->alias.str, &field_name);
- if (!fld || item_list.push_back(fld))
+ table->db.str,
+ table->alias.str,
+ &field_name);
+ if (unlikely(!fld) || unlikely(item_list.push_back(fld)))
return true;
if (thd->lex->view_list.elements)
{
LEX_CSTRING *l;
- if (!(l= thd->make_clex_string(field_name.str, field_name.length)))
+ if (unlikely(!(l= thd->make_clex_string(field_name.str,
+ field_name.length))) ||
+ unlikely(thd->lex->view_list.push_back(l)))
return true;
- thd->lex->view_list.push_back(l);
}
return false;
@@ -7875,3 +8018,277 @@ void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
*remaining_cond= cond;
}
+
+
+Item *LEX::create_item_qualified_asterisk(THD *thd,
+ const Lex_ident_sys_st *name)
+{
+ Item *item;
+ if (!(item= new (thd->mem_root) Item_field(thd, current_context(),
+ NullS, name->str,
+ &star_clex_str)))
+ return NULL;
+ current_select->with_wild++;
+ return item;
+}
+
+
+Item *LEX::make_item_func_call_generic(THD *thd, Lex_ident_cli_st *cdb,
+ Lex_ident_cli_st *cname, List<Item> *args)
+{
+ Lex_ident_sys db(thd, cdb), name(thd, cname);
+ if (db.is_null() || name.is_null())
+ return NULL; // EOM
+ /*
+ The following in practice calls:
+ <code>Create_sp_func::create()</code>
+ and builds a stored function.
+
+ However, it's important to maintain the interface between the
+ parser and the implementation in item_create.cc clean,
+ since this will change with WL#2128 (SQL PATH):
+ - INFORMATION_SCHEMA.version() is the SQL 99 syntax for the native
+ function version(),
+ - MySQL.version() is the SQL 2003 syntax for the native function
+ version() (a vendor can specify any schema).
+ */
+
+ if (!name.str || check_db_name((LEX_STRING*) static_cast<LEX_CSTRING*>(&db)))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
+ return NULL;
+ }
+ if (check_routine_name(&name))
+ return NULL;
+
+ Create_qfunc *builder= find_qualified_function_builder(thd);
+ DBUG_ASSERT(builder);
+ return builder->create_with_db(thd, &db, &name, true, args);
+}
+
+
+Item *LEX::create_item_qualified_asterisk(THD *thd,
+ const Lex_ident_sys_st *a,
+ const Lex_ident_sys_st *b)
+{
+ Item *item;
+ const char* schema= thd->client_capabilities & CLIENT_NO_SCHEMA ?
+ NullS : a->str;
+ if (!(item= new (thd->mem_root) Item_field(thd, current_context(),
+ schema, b->str,
+ &star_clex_str)))
+ return NULL;
+ current_select->with_wild++;
+ return item;
+}
+
+
+bool Lex_ident_sys_st::copy_ident_cli(THD *thd, const Lex_ident_cli_st *str)
+{
+ return thd->to_ident_sys_alloc(this, str);
+}
+
+bool Lex_ident_sys_st::copy_keyword(THD *thd, const Lex_ident_cli_st *str)
+{
+ return thd->make_lex_string(static_cast<LEX_CSTRING*>(this),
+ str->str, str->length) == NULL;
+}
+
+bool Lex_ident_sys_st::copy_or_convert(THD *thd,
+ const Lex_ident_cli_st *src,
+ CHARSET_INFO *cs)
+{
+ if (!src->is_8bit())
+ return copy_keyword(thd, src); // 7bit string makes a wellformed identifier
+ return convert(thd, src, cs);
+}
+
+
+bool Lex_ident_sys_st::copy_sys(THD *thd, const LEX_CSTRING *src)
+{
+ if (thd->check_string_for_wellformedness(src->str, src->length,
+ system_charset_info))
+ return true;
+ return thd->make_lex_string(this, src->str, src->length) == NULL;
+}
+
+
+bool Lex_ident_sys_st::convert(THD *thd,
+ const LEX_CSTRING *src, CHARSET_INFO *cs)
+{
+ LEX_STRING tmp;
+ if (thd->convert_with_error(system_charset_info, &tmp, cs,
+ src->str, src->length))
+ return true;
+ str= tmp.str;
+ length= tmp.length;
+ return false;
+}
+
+
+bool Lex_ident_sys_st::to_size_number(ulonglong *to) const
+{
+ ulonglong number;
+ uint text_shift_number= 0;
+ longlong prefix_number;
+ const char *start_ptr= str;
+ size_t str_len= length;
+ const char *end_ptr= start_ptr + str_len;
+ int error;
+ prefix_number= my_strtoll10(start_ptr, (char**) &end_ptr, &error);
+ if (likely((start_ptr + str_len - 1) == end_ptr))
+ {
+ switch (end_ptr[0])
+ {
+ case 'g':
+ case 'G': text_shift_number+=30; break;
+ case 'm':
+ case 'M': text_shift_number+=20; break;
+ case 'k':
+ case 'K': text_shift_number+=10; break;
+ default:
+ my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
+ return true;
+ }
+ if (unlikely(prefix_number >> 31))
+ {
+ my_error(ER_SIZE_OVERFLOW_ERROR, MYF(0));
+ return true;
+ }
+ number= prefix_number << text_shift_number;
+ }
+ else
+ {
+ my_error(ER_WRONG_SIZE_NUMBER, MYF(0));
+ return true;
+ }
+ *to= number;
+ return false;
+}
+
+
+bool LEX::part_values_current(THD *thd)
+{
+ partition_element *elem= part_info->curr_part_elem;
+ if (!is_partition_management())
+ {
+ if (unlikely(part_info->part_type != VERSIONING_PARTITION))
+ {
+ my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME");
+ return true;
+ }
+ }
+ else
+ {
+ DBUG_ASSERT(create_last_non_select_table);
+ DBUG_ASSERT(create_last_non_select_table->table_name.str);
+ // FIXME: other ALTER commands?
+ my_error(ER_VERS_WRONG_PARTS, MYF(0),
+ create_last_non_select_table->table_name.str);
+ return true;
+ }
+ elem->type(partition_element::CURRENT);
+ DBUG_ASSERT(part_info->vers_info);
+ part_info->vers_info->now_part= elem;
+ if (unlikely(part_info->init_column_part(thd)))
+ return true;
+ return false;
+}
+
+
+bool LEX::part_values_history(THD *thd)
+{
+ partition_element *elem= part_info->curr_part_elem;
+ if (!is_partition_management())
+ {
+ if (unlikely(part_info->part_type != VERSIONING_PARTITION))
+ {
+ my_error(ER_PARTITION_WRONG_TYPE, MYF(0), "SYSTEM_TIME");
+ return true;
+ }
+ }
+ else
+ {
+ part_info->vers_init_info(thd);
+ elem->id= UINT_MAX32;
+ }
+ DBUG_ASSERT(part_info->vers_info);
+ if (unlikely(part_info->vers_info->now_part))
+ {
+ DBUG_ASSERT(create_last_non_select_table);
+ DBUG_ASSERT(create_last_non_select_table->table_name.str);
+ my_error(ER_VERS_WRONG_PARTS, MYF(0),
+ create_last_non_select_table->table_name.str);
+ return true;
+ }
+ elem->type(partition_element::HISTORY);
+ if (unlikely(part_info->init_column_part(thd)))
+ return true;
+ return false;
+}
+
+
+bool LEX::last_field_generated_always_as_row_start_or_end(Lex_ident *p,
+ const char *type,
+ uint flag)
+{
+ if (unlikely(p->str))
+ {
+ my_error(ER_VERS_DUPLICATE_ROW_START_END, MYF(0), type,
+ last_field->field_name.str);
+ return true;
+ }
+ last_field->flags|= (flag | NOT_NULL_FLAG);
+ DBUG_ASSERT(p);
+ *p= last_field->field_name;
+ return false;
+}
+
+
+
+bool LEX::last_field_generated_always_as_row_start()
+{
+ Vers_parse_info &info= vers_get_info();
+ Lex_ident *p= &info.as_row.start;
+ return last_field_generated_always_as_row_start_or_end(p, "START",
+ VERS_SYS_START_FLAG);
+}
+
+
+bool LEX::last_field_generated_always_as_row_end()
+{
+ Vers_parse_info &info= vers_get_info();
+ Lex_ident *p= &info.as_row.end;
+ return last_field_generated_always_as_row_start_or_end(p, "END",
+ VERS_SYS_END_FLAG);
+}
+
+
+bool LEX::tvc_finalize()
+{
+ mysql_init_select(this);
+ if (unlikely(!(current_select->tvc=
+ new (thd->mem_root)
+ table_value_constr(many_values,
+ current_select,
+ current_select->options))))
+ return true;
+ many_values.empty();
+ return false;
+}
+
+
+bool LEX::tvc_finalize_derived()
+{
+ derived_tables|= DERIVED_SUBQUERY;
+ if (unlikely(!expr_allows_subselect || sql_command == (int)SQLCOM_PURGE))
+ {
+ thd->parse_error();
+ return true;
+ }
+ if (current_select->linkage == GLOBAL_OPTIONS_TYPE ||
+ unlikely(mysql_new_select(this, 1, NULL)))
+ return true;
+ current_select->linkage= DERIVED_TABLE_TYPE;
+ return tvc_finalize();
+}