manual merge 5.0-runtime -> 5.1->runtime, with 25411 part I

This commit is contained in:
unknown 2007-04-25 21:38:12 -06:00
parent 5e414cd222
commit 034c11f3cd
18 changed files with 479 additions and 300 deletions

View File

@ -156,10 +156,14 @@ void
Event_parse_data::init_body(THD *thd) Event_parse_data::init_body(THD *thd)
{ {
DBUG_ENTER("Event_parse_data::init_body"); DBUG_ENTER("Event_parse_data::init_body");
DBUG_PRINT("info", ("body: '%s' body_begin: 0x%lx end: 0x%lx", body_begin,
(long) body_begin, (long) thd->lex->ptr));
body.length= thd->lex->ptr - body_begin; /* This method is called from within the parser, from sql_yacc.yy */
DBUG_ASSERT(thd->m_lip != NULL);
DBUG_PRINT("info", ("body: '%s' body_begin: 0x%lx end: 0x%lx", body_begin,
(long) body_begin, (long) thd->m_lip->ptr));
body.length= thd->m_lip->ptr - body_begin;
const char *body_end= body_begin + body.length - 1; const char *body_end= body_begin + body.length - 1;
/* Trim nuls or close-comments ('*'+'/') or spaces at the end */ /* Trim nuls or close-comments ('*'+'/') or spaces at the end */
@ -1912,15 +1916,20 @@ Event_job_data::execute(THD *thd, bool drop)
thd->query= sp_sql.c_ptr_safe(); thd->query= sp_sql.c_ptr_safe();
thd->query_length= sp_sql.length(); thd->query_length= sp_sql.length();
lex_start(thd, thd->query, thd->query_length);
if (MYSQLparse(thd) || thd->is_fatal_error)
{ {
sql_print_error("Event Scheduler: " Lex_input_stream lip(thd, thd->query, thd->query_length);
"%serror during compilation of %s.%s", thd->m_lip= &lip;
thd->is_fatal_error ? "fatal " : "", lex_start(thd);
(const char *) dbname.str, (const char *) name.str); int err= MYSQLparse(thd);
goto end;
if (err || thd->is_fatal_error)
{
sql_print_error("Event Scheduler: "
"%serror during compilation of %s.%s",
thd->is_fatal_error ? "fatal " : "",
(const char *) dbname.str, (const char *) name.str);
goto end;
}
} }
{ {

View File

@ -6564,7 +6564,7 @@ int ndb_create_table_from_engine(THD *thd, const char *db,
LEX *old_lex= thd->lex, newlex; LEX *old_lex= thd->lex, newlex;
thd->lex= &newlex; thd->lex= &newlex;
newlex.current_select= NULL; newlex.current_select= NULL;
lex_start(thd, "", 0); lex_start(thd);
int res= ha_create_table_from_engine(thd, db, table_name); int res= ha_create_table_from_engine(thd, db, table_name);
thd->lex= old_lex; thd->lex= old_lex;
return res; return res;

View File

@ -230,6 +230,7 @@ static void run_query(THD *thd, char *buf, char *end,
ulonglong save_thd_options= thd->options; ulonglong save_thd_options= thd->options;
DBUG_ASSERT(sizeof(save_thd_options) == sizeof(thd->options)); DBUG_ASSERT(sizeof(save_thd_options) == sizeof(thd->options));
NET save_net= thd->net; NET save_net= thd->net;
const char* found_semicolon= NULL;
bzero((char*) &thd->net, sizeof(NET)); bzero((char*) &thd->net, sizeof(NET));
thd->query_length= end - buf; thd->query_length= end - buf;
@ -239,7 +240,7 @@ static void run_query(THD *thd, char *buf, char *end,
thd->options&= ~OPTION_BIN_LOG; thd->options&= ~OPTION_BIN_LOG;
DBUG_PRINT("query", ("%s", thd->query)); DBUG_PRINT("query", ("%s", thd->query));
mysql_parse(thd, thd->query, thd->query_length); mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
if (print_error && thd->query_error) if (print_error && thd->query_error)
{ {

View File

@ -5863,7 +5863,7 @@ int Rows_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
Table_map_log_event::do_apply_event() we don't call Table_map_log_event::do_apply_event() we don't call
mysql_init_query() as that may reset the binlog format. mysql_init_query() as that may reset the binlog format.
*/ */
lex_start(thd, NULL, 0); lex_start(thd);
while ((error= lock_tables(thd, rli->tables_to_lock, while ((error= lock_tables(thd, rli->tables_to_lock,
rli->tables_to_lock_count, &need_reopen))) rli->tables_to_lock_count, &need_reopen)))
@ -6513,7 +6513,8 @@ int Table_map_log_event::do_apply_event(RELAY_LOG_INFO const *rli)
initialized, so we should call lex_start(); to be even safer, we initialized, so we should call lex_start(); to be even safer, we
call mysql_init_query() which does a more complete set of inits. call mysql_init_query() which does a more complete set of inits.
*/ */
mysql_init_query(thd, NULL, 0); lex_start(thd);
mysql_reset_thd_for_next_command(thd);
/* /*
Check if the slave is set to use SBR. If so, it should switch Check if the slave is set to use SBR. If so, it should switch
to using RBR until the end of the "statement", i.e., next to using RBR until the end of the "statement", i.e., next

View File

@ -838,13 +838,15 @@ bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db,
bool skip_error); bool skip_error);
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
bool force_switch); bool force_switch);
void mysql_parse(THD *thd,char *inBuf,uint length);
void mysql_parse(THD *thd, const char *inBuf, uint length,
const char ** semicolon);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length); bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
bool is_update_query(enum enum_sql_command command); bool is_update_query(enum enum_sql_command command);
bool alloc_query(THD *thd, const char *packet, uint packet_length); bool alloc_query(THD *thd, const char *packet, uint packet_length);
void mysql_init_select(LEX *lex); void mysql_init_select(LEX *lex);
void mysql_reset_thd_for_next_command(THD *thd); void mysql_reset_thd_for_next_command(THD *thd);
void mysql_init_query(THD *thd, const char *buf, uint length);
bool mysql_new_select(LEX *lex, bool move_down); bool mysql_new_select(LEX *lex, bool move_down);
void create_select_for_variable(const char *var_name); void create_select_for_variable(const char *var_name);
void mysql_init_multi_delete(LEX *lex); void mysql_init_multi_delete(LEX *lex);

View File

@ -923,6 +923,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
handler *file; handler *file;
ulonglong save_options; ulonglong save_options;
NET *net= &mysql->net; NET *net= &mysql->net;
const char *found_semicolon= NULL;
DBUG_ENTER("create_table_from_dump"); DBUG_ENTER("create_table_from_dump");
packet_len= my_net_read(net); // read create table statement packet_len= my_net_read(net); // read create table statement
@ -974,7 +975,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
thd->db = (char*)db; thd->db = (char*)db;
DBUG_ASSERT(thd->db != 0); DBUG_ASSERT(thd->db != 0);
thd->db_length= strlen(thd->db); thd->db_length= strlen(thd->db);
mysql_parse(thd, thd->query, packet_len); // run create table mysql_parse(thd, thd->query, packet_len, &found_semicolon); // run create table
thd->db = save_db; // leave things the way the were before thd->db = save_db; // leave things the way the were before
thd->db_length= save_db_length; thd->db_length= save_db_length;
thd->options = save_options; thd->options = save_options;

View File

@ -384,10 +384,15 @@ db_load_routine(THD *thd, int type, sp_name *name, sp_head **sphp,
if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged))) if ((ret= sp_use_new_db(thd, name->m_db, &old_db, 1, &dbchanged)))
goto end; goto end;
lex_start(thd, defstr.c_ptr(), defstr.length()); {
Lex_input_stream lip(thd, defstr.c_ptr(), defstr.length());
thd->m_lip= &lip;
lex_start(thd);
ret= MYSQLparse(thd);
}
thd->spcont= 0; thd->spcont= 0;
if (MYSQLparse(thd) || thd->is_fatal_error || newlex.sphead == NULL) if (ret || thd->is_fatal_error || newlex.sphead == NULL)
{ {
sp_head *sp= newlex.sphead; sp_head *sp= newlex.sphead;

View File

@ -557,6 +557,7 @@ sp_head::init_strings(THD *thd, LEX *lex)
const char *endp; /* Used to trim the end */ const char *endp; /* Used to trim the end */
/* During parsing, we must use thd->mem_root */ /* During parsing, we must use thd->mem_root */
MEM_ROOT *root= thd->mem_root; MEM_ROOT *root= thd->mem_root;
Lex_input_stream *lip=thd->m_lip;
if (m_param_begin && m_param_end) if (m_param_begin && m_param_end)
{ {
@ -565,7 +566,7 @@ sp_head::init_strings(THD *thd, LEX *lex)
} }
/* If ptr has overrun end_of_query then end_of_query is the end */ /* If ptr has overrun end_of_query then end_of_query is the end */
endp= (lex->ptr > lex->end_of_query ? lex->end_of_query : lex->ptr); endp= (lip->ptr > lip->end_of_query ? lip->end_of_query : lip->ptr);
/* /*
Trim "garbage" at the end. This is sometimes needed with the Trim "garbage" at the end. This is sometimes needed with the
"/ * ! VERSION... * /" wrapper in dump files. "/ * ! VERSION... * /" wrapper in dump files.
@ -574,8 +575,8 @@ sp_head::init_strings(THD *thd, LEX *lex)
m_body.length= endp - m_body_begin; m_body.length= endp - m_body_begin;
m_body.str= strmake_root(root, m_body_begin, m_body.length); m_body.str= strmake_root(root, m_body_begin, m_body.length);
m_defstr.length= endp - lex->buf; m_defstr.length= endp - lip->buf;
m_defstr.str= strmake_root(root, lex->buf, m_defstr.length); m_defstr.str= strmake_root(root, lip->buf, m_defstr.length);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -1815,25 +1816,13 @@ sp_head::reset_lex(THD *thd)
DBUG_ENTER("sp_head::reset_lex"); DBUG_ENTER("sp_head::reset_lex");
LEX *sublex; LEX *sublex;
LEX *oldlex= thd->lex; LEX *oldlex= thd->lex;
my_lex_states org_next_state= oldlex->next_state;
(void)m_lex.push_front(oldlex); (void)m_lex.push_front(oldlex);
thd->lex= sublex= new st_lex; thd->lex= sublex= new st_lex;
/* Reset most stuff. The length arguments doesn't matter here. */ /* Reset most stuff. */
lex_start(thd, oldlex->buf, (ulong) (oldlex->end_of_query - oldlex->ptr)); lex_start(thd);
/*
next_state is normally the same (0), but it happens that we swap lex in
"mid-sentence", so we must restore it.
*/
sublex->next_state= org_next_state;
/* We must reset ptr and end_of_query again */
sublex->ptr= oldlex->ptr;
sublex->end_of_query= oldlex->end_of_query;
sublex->tok_start= oldlex->tok_start;
sublex->tok_end= oldlex->tok_end;
sublex->yylineno= oldlex->yylineno;
/* And keep the SP stuff too */ /* And keep the SP stuff too */
sublex->sphead= oldlex->sphead; sublex->sphead= oldlex->sphead;
sublex->spcont= oldlex->spcont; sublex->spcont= oldlex->spcont;
@ -1866,10 +1855,6 @@ sp_head::restore_lex(THD *thd)
if (! oldlex) if (! oldlex)
return; // Nothing to restore return; // Nothing to restore
// Update some state in the old one first
oldlex->ptr= sublex->ptr;
oldlex->tok_end= sublex->tok_end;
oldlex->next_state= sublex->next_state;
oldlex->trg_table_fields.push_back(&sublex->trg_table_fields); oldlex->trg_table_fields.push_back(&sublex->trg_table_fields);
/* /*

View File

@ -176,7 +176,9 @@ public:
*/ */
HASH m_sroutines; HASH m_sroutines;
// Pointers set during parsing // Pointers set during parsing
const char *m_param_begin, *m_param_end, *m_body_begin; const char *m_param_begin;
const char *m_param_end;
const char *m_body_begin;
/* /*
Security context for stored routine which should be run under Security context for stored routine which should be run under

View File

@ -31,6 +31,7 @@ class Load_log_event;
class Slave_log_event; class Slave_log_event;
class sp_rcontext; class sp_rcontext;
class sp_cache; class sp_cache;
class Lex_input_stream;
class Rows_log_event; class Rows_log_event;
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE }; enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
@ -1423,6 +1424,16 @@ public:
*/ */
query_id_t first_query_id; query_id_t first_query_id;
} binlog_evt_union; } binlog_evt_union;
/**
Character input stream consumed by the lexical analyser,
used during parsing.
Note that since the parser is not re-entrant, we keep only one input
stream here. This member is valid only when executing code during parsing,
and may point to invalid memory after that.
*/
Lex_input_stream *m_lip;
#ifdef WITH_PARTITION_STORAGE_ENGINE #ifdef WITH_PARTITION_STORAGE_ENGINE
partition_info *work_part_info; partition_info *work_part_info;
#endif #endif

View File

@ -33,13 +33,13 @@ sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
/* Macros to look like lex */ /* Macros to look like lex */
#define yyGet() ((uchar) *(lex->ptr++)) #define yyGet() ((uchar) *(lip->ptr++))
#define yyGetLast() ((uchar) lex->ptr[-1]) #define yyGetLast() ((uchar) lip->ptr[-1])
#define yyPeek() ((uchar) lex->ptr[0]) #define yyPeek() ((uchar) lip->ptr[0])
#define yyPeek2() ((uchar) lex->ptr[1]) #define yyPeek2() ((uchar) lip->ptr[1])
#define yyUnget() lex->ptr-- #define yyUnget() lip->ptr--
#define yySkip() lex->ptr++ #define yySkip() lip->ptr++
#define yyLength() ((uint) (lex->ptr - lex->tok_start)-1) #define yyLength() ((uint) (lip->ptr - lip->tok_start)-1)
/* Longest standard keyword name */ /* Longest standard keyword name */
#define TOCK_NAME_LENGTH 24 #define TOCK_NAME_LENGTH 24
@ -120,6 +120,28 @@ st_parsing_options::reset()
allows_derived= TRUE; allows_derived= TRUE;
} }
Lex_input_stream::Lex_input_stream(THD *thd,
const char* buffer,
unsigned int length)
: m_thd(thd),
yylineno(1),
yytoklen(0),
yylval(NULL),
ptr(buffer),
tok_start(NULL),
tok_end(NULL),
end_of_query(buffer + length),
tok_start_prev(NULL),
buf(buffer),
next_state(MY_LEX_START),
found_semicolon(NULL),
ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE))
{
}
Lex_input_stream::~Lex_input_stream()
{}
/* /*
This is called before every query that is to be parsed. This is called before every query that is to be parsed.
@ -127,14 +149,12 @@ st_parsing_options::reset()
(We already do too much here) (We already do too much here)
*/ */
void lex_start(THD *thd, const char *buf, uint length) void lex_start(THD *thd)
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
DBUG_ENTER("lex_start"); DBUG_ENTER("lex_start");
lex->thd= lex->unit.thd= thd; lex->thd= lex->unit.thd= thd;
lex->buf= lex->ptr= buf;
lex->end_of_query= buf+length;
lex->context_stack.empty(); lex->context_stack.empty();
lex->unit.init_query(); lex->unit.init_query();
@ -167,14 +187,11 @@ void lex_start(THD *thd, const char *buf, uint length)
lex->stmt_prepare_mode= FALSE; lex->stmt_prepare_mode= FALSE;
lex->derived_tables= 0; lex->derived_tables= 0;
lex->lock_option= TL_READ; lex->lock_option= TL_READ;
lex->found_semicolon= 0;
lex->safe_to_cache_query= 1; lex->safe_to_cache_query= 1;
lex->leaf_tables_insert= 0; lex->leaf_tables_insert= 0;
lex->parsing_options.reset(); lex->parsing_options.reset();
lex->empty_field_list_on_rset= 0; lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1; lex->select_lex.select_number= 1;
lex->next_state=MY_LEX_START;
lex->yylineno = 1;
lex->in_comment=0; lex->in_comment=0;
lex->length=0; lex->length=0;
lex->part_info= 0; lex->part_info= 0;
@ -184,7 +201,6 @@ void lex_start(THD *thd, const char *buf, uint length)
lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc;
lex->select_lex.group_list.empty(); lex->select_lex.group_list.empty();
lex->select_lex.order_list.empty(); lex->select_lex.order_list.empty();
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
lex->sql_command= SQLCOM_END; lex->sql_command= SQLCOM_END;
lex->duplicates= DUP_ERROR; lex->duplicates= DUP_ERROR;
lex->ignore= 0; lex->ignore= 0;
@ -236,24 +252,24 @@ void lex_end(LEX *lex)
} }
static int find_keyword(LEX *lex, uint len, bool function) static int find_keyword(Lex_input_stream *lip, uint len, bool function)
{ {
const char *tok= lex->tok_start; const char *tok= lip->tok_start;
SYMBOL *symbol= get_hash_symbol(tok, len, function); SYMBOL *symbol= get_hash_symbol(tok, len, function);
if (symbol) if (symbol)
{ {
lex->yylval->symbol.symbol=symbol; lip->yylval->symbol.symbol=symbol;
lex->yylval->symbol.str= (char*) tok; lip->yylval->symbol.str= (char*) tok;
lex->yylval->symbol.length=len; lip->yylval->symbol.length=len;
if ((symbol->tok == NOT_SYM) && if ((symbol->tok == NOT_SYM) &&
(lex->thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE)) (lip->m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
return NOT2_SYM; return NOT2_SYM;
if ((symbol->tok == OR_OR_SYM) && if ((symbol->tok == OR_OR_SYM) &&
!(lex->thd->variables.sql_mode & MODE_PIPES_AS_CONCAT)) !(lip->m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
return OR2_SYM; return OR2_SYM;
return symbol->tok; return symbol->tok;
} }
return 0; return 0;
@ -286,12 +302,12 @@ bool is_lex_native_function(const LEX_STRING *name)
/* make a copy of token before ptr and set yytoklen */ /* make a copy of token before ptr and set yytoklen */
static LEX_STRING get_token(LEX *lex,uint length) static LEX_STRING get_token(Lex_input_stream *lip, uint length)
{ {
LEX_STRING tmp; LEX_STRING tmp;
yyUnget(); // ptr points now after last token char yyUnget(); // ptr points now after last token char
tmp.length=lex->yytoklen=length; tmp.length=lip->yytoklen=length;
tmp.str=(char*) lex->thd->strmake((char*) lex->tok_start,tmp.length); tmp.str= lip->m_thd->strmake(lip->tok_start, tmp.length);
return tmp; return tmp;
} }
@ -302,15 +318,16 @@ static LEX_STRING get_token(LEX *lex,uint length)
future to operate multichar strings (like ucs2) future to operate multichar strings (like ucs2)
*/ */
static LEX_STRING get_quoted_token(LEX *lex,uint length, char quote) static LEX_STRING get_quoted_token(Lex_input_stream *lip,
uint length, char quote)
{ {
LEX_STRING tmp; LEX_STRING tmp;
const char *from, *end; const char *from, *end;
char *to; char *to;
yyUnget(); // ptr points now after last token char yyUnget(); // ptr points now after last token char
tmp.length=lex->yytoklen=length; tmp.length= lip->yytoklen=length;
tmp.str=(char*) lex->thd->alloc(tmp.length+1); tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
for (from= lex->tok_start, to= tmp.str, end= to+length ; for (from= lip->tok_start, to= tmp.str, end= to+length ;
to != end ; to != end ;
) )
{ {
@ -327,31 +344,31 @@ static LEX_STRING get_quoted_token(LEX *lex,uint length, char quote)
Fix sometimes to do only one scan of the string Fix sometimes to do only one scan of the string
*/ */
static char *get_text(LEX *lex) static char *get_text(Lex_input_stream *lip)
{ {
reg1 uchar c,sep; reg1 uchar c,sep;
uint found_escape=0; uint found_escape=0;
CHARSET_INFO *cs= lex->thd->charset(); CHARSET_INFO *cs= lip->m_thd->charset();
sep= yyGetLast(); // String should end with this sep= yyGetLast(); // String should end with this
while (lex->ptr != lex->end_of_query) while (lip->ptr != lip->end_of_query)
{ {
c = yyGet(); c = yyGet();
#ifdef USE_MB #ifdef USE_MB
{ {
int l; int l;
if (use_mb(cs) && if (use_mb(cs) &&
(l = my_ismbchar(cs, lex->ptr-1, lex->end_of_query))) { (l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query))) {
lex->ptr += l-1; lip->ptr += l-1;
continue; continue;
} }
} }
#endif #endif
if (c == '\\' && if (c == '\\' &&
!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) !(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
{ // Escaped character { // Escaped character
found_escape=1; found_escape=1;
if (lex->ptr == lex->end_of_query) if (lip->ptr == lip->end_of_query)
return 0; return 0;
yySkip(); yySkip();
} }
@ -369,15 +386,15 @@ static char *get_text(LEX *lex)
const char *str, *end; const char *str, *end;
char *start; char *start;
str=lex->tok_start+1; str=lip->tok_start+1;
end=lex->ptr-1; end=lip->ptr-1;
if (!(start= (char*) lex->thd->alloc((uint) (end-str)+1))) if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1)))
return (char*) ""; // Sql_alloc has set error flag return (char*) ""; // Sql_alloc has set error flag
if (!found_escape) if (!found_escape)
{ {
lex->yytoklen=(uint) (end-str); lip->yytoklen=(uint) (end-str);
memcpy(start,str,lex->yytoklen); memcpy(start,str,lip->yytoklen);
start[lex->yytoklen]=0; start[lip->yytoklen]=0;
} }
else else
{ {
@ -395,7 +412,7 @@ static char *get_text(LEX *lex)
continue; continue;
} }
#endif #endif
if (!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) && if (!(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
*str == '\\' && str+1 != end) *str == '\\' && str+1 != end)
{ {
switch(*++str) { switch(*++str) {
@ -432,7 +449,7 @@ static char *get_text(LEX *lex)
*to++ = *str; *to++ = *str;
} }
*to=0; *to=0;
lex->yytoklen=(uint) (to-start); lip->yytoklen=(uint) (to-start);
} }
return start; return start;
} }
@ -545,19 +562,21 @@ int MYSQLlex(void *arg, void *yythd)
int tokval, result_state; int tokval, result_state;
uint length; uint length;
enum my_lex_states state; enum my_lex_states state;
LEX *lex= ((THD *)yythd)->lex; THD *thd= (THD *)yythd;
Lex_input_stream *lip= thd->m_lip;
LEX *lex= thd->lex;
YYSTYPE *yylval=(YYSTYPE*) arg; YYSTYPE *yylval=(YYSTYPE*) arg;
CHARSET_INFO *cs= ((THD *) yythd)->charset(); CHARSET_INFO *cs= thd->charset();
uchar *state_map= cs->state_map; uchar *state_map= cs->state_map;
uchar *ident_map= cs->ident_map; uchar *ident_map= cs->ident_map;
lex->yylval=yylval; // The global state lip->yylval=yylval; // The global state
lex->tok_start_prev= lex->tok_start; lip->tok_start_prev= lip->tok_start;
lex->tok_start=lex->tok_end=lex->ptr; lip->tok_start=lip->tok_end=lip->ptr;
state=lex->next_state; state=lip->next_state;
lex->next_state=MY_LEX_OPERATOR_OR_IDENT; lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
LINT_INIT(c); LINT_INIT(c);
for (;;) for (;;)
{ {
@ -568,9 +587,9 @@ int MYSQLlex(void *arg, void *yythd)
for (c=yyGet() ; (state_map[c] == MY_LEX_SKIP) ; c= yyGet()) for (c=yyGet() ; (state_map[c] == MY_LEX_SKIP) ; c= yyGet())
{ {
if (c == '\n') if (c == '\n')
lex->yylineno++; lip->yylineno++;
} }
lex->tok_start=lex->ptr-1; // Start of real token lip->tok_start=lip->ptr-1; // Start of real token
state= (enum my_lex_states) state_map[c]; state= (enum my_lex_states) state_map[c];
break; break;
case MY_LEX_ESCAPE: case MY_LEX_ESCAPE:
@ -589,13 +608,13 @@ int MYSQLlex(void *arg, void *yythd)
state=MY_LEX_COMMENT; state=MY_LEX_COMMENT;
break; break;
} }
yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first chr yylval->lex_str.str=(char*) (lip->ptr=lip->tok_start);// Set to first chr
yylval->lex_str.length=1; yylval->lex_str.length=1;
c=yyGet(); c=yyGet();
if (c != ')') if (c != ')')
lex->next_state= MY_LEX_START; // Allow signed numbers lip->next_state= MY_LEX_START; // Allow signed numbers
if (c == ',') if (c == ',')
lex->tok_start=lex->ptr; // Let tok_start point at next item lip->tok_start=lip->ptr; // Let tok_start point at next item
/* /*
Check for a placeholder: it should not precede a possible identifier Check for a placeholder: it should not precede a possible identifier
because of binlogging: when a placeholder is replaced with because of binlogging: when a placeholder is replaced with
@ -613,14 +632,14 @@ int MYSQLlex(void *arg, void *yythd)
break; break;
} }
/* Found N'string' */ /* Found N'string' */
lex->tok_start++; // Skip N lip->tok_start++; // Skip N
yySkip(); // Skip ' yySkip(); // Skip '
if (!(yylval->lex_str.str = get_text(lex))) if (!(yylval->lex_str.str = get_text(lip)))
{ {
state= MY_LEX_CHAR; // Read char by char state= MY_LEX_CHAR; // Read char by char
break; break;
} }
yylval->lex_str.length= lex->yytoklen; yylval->lex_str.length= lip->yytoklen;
return(NCHAR_STRING); return(NCHAR_STRING);
case MY_LEX_IDENT_OR_HEX: case MY_LEX_IDENT_OR_HEX:
@ -643,21 +662,21 @@ int MYSQLlex(void *arg, void *yythd)
result_state= IDENT_QUOTED; result_state= IDENT_QUOTED;
if (my_mbcharlen(cs, yyGetLast()) > 1) if (my_mbcharlen(cs, yyGetLast()) > 1)
{ {
int l = my_ismbchar(cs, lex->ptr-1, lex->end_of_query); int l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query);
if (l == 0) { if (l == 0) {
state = MY_LEX_CHAR; state = MY_LEX_CHAR;
continue; continue;
} }
lex->ptr += l - 1; lip->ptr += l - 1;
} }
while (ident_map[c=yyGet()]) while (ident_map[c=yyGet()])
{ {
if (my_mbcharlen(cs, c) > 1) if (my_mbcharlen(cs, c) > 1)
{ {
int l; int l;
if ((l = my_ismbchar(cs, lex->ptr-1, lex->end_of_query)) == 0) if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0)
break; break;
lex->ptr += l-1; lip->ptr += l-1;
} }
} }
} }
@ -668,9 +687,9 @@ int MYSQLlex(void *arg, void *yythd)
/* If there were non-ASCII characters, mark that we must convert */ /* If there were non-ASCII characters, mark that we must convert */
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
} }
length= (uint) (lex->ptr - lex->tok_start)-1; length= (uint) (lip->ptr - lip->tok_start)-1;
start= lex->ptr; start= lip->ptr;
if (lex->ignore_space) if (lip->ignore_space)
{ {
/* /*
If we find a space then this can't be an identifier. We notice this If we find a space then this can't be an identifier. We notice this
@ -678,19 +697,19 @@ int MYSQLlex(void *arg, void *yythd)
*/ */
for (; state_map[c] == MY_LEX_SKIP ; c= yyGet()); for (; state_map[c] == MY_LEX_SKIP ; c= yyGet());
} }
if (start == lex->ptr && c == '.' && ident_map[yyPeek()]) if (start == lip->ptr && c == '.' && ident_map[yyPeek()])
lex->next_state=MY_LEX_IDENT_SEP; lip->next_state=MY_LEX_IDENT_SEP;
else else
{ // '(' must follow directly if function { // '(' must follow directly if function
yyUnget(); yyUnget();
if ((tokval = find_keyword(lex,length,c == '('))) if ((tokval = find_keyword(lip, length,c == '(')))
{ {
lex->next_state= MY_LEX_START; // Allow signed numbers lip->next_state= MY_LEX_START; // Allow signed numbers
return(tokval); // Was keyword return(tokval); // Was keyword
} }
yySkip(); // next state does a unget yySkip(); // next state does a unget
} }
yylval->lex_str=get_token(lex,length); yylval->lex_str=get_token(lip, length);
/* /*
Note: "SELECT _bla AS 'alias'" Note: "SELECT _bla AS 'alias'"
@ -707,12 +726,12 @@ int MYSQLlex(void *arg, void *yythd)
return(result_state); // IDENT or IDENT_QUOTED return(result_state); // IDENT or IDENT_QUOTED
case MY_LEX_IDENT_SEP: // Found ident and now '.' case MY_LEX_IDENT_SEP: // Found ident and now '.'
yylval->lex_str.str=(char*) lex->ptr; yylval->lex_str.str=(char*) lip->ptr;
yylval->lex_str.length=1; yylval->lex_str.length=1;
c=yyGet(); // should be '.' c=yyGet(); // should be '.'
lex->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword) lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
if (!ident_map[yyPeek()]) // Probably ` or " if (!ident_map[yyPeek()]) // Probably ` or "
lex->next_state= MY_LEX_START; lip->next_state= MY_LEX_START;
return((int) c); return((int) c);
case MY_LEX_NUMBER_IDENT: // number or ident which num-start case MY_LEX_NUMBER_IDENT: // number or ident which num-start
@ -732,36 +751,36 @@ int MYSQLlex(void *arg, void *yythd)
{ {
yySkip(); yySkip();
while (my_isdigit(cs,yyGet())) ; while (my_isdigit(cs,yyGet())) ;
yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str=get_token(lip, yyLength());
return(FLOAT_NUM); return(FLOAT_NUM);
} }
} }
yyUnget(); /* purecov: inspected */ yyUnget(); /* purecov: inspected */
} }
else if (c == 'x' && (lex->ptr - lex->tok_start) == 2 && else if (c == 'x' && (lip->ptr - lip->tok_start) == 2 &&
lex->tok_start[0] == '0' ) lip->tok_start[0] == '0' )
{ // Varbinary { // Varbinary
while (my_isxdigit(cs,(c = yyGet()))) ; while (my_isxdigit(cs,(c = yyGet()))) ;
if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c]) if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c])
{ {
yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str=get_token(lip, yyLength());
yylval->lex_str.str+=2; // Skip 0x yylval->lex_str.str+=2; // Skip 0x
yylval->lex_str.length-=2; yylval->lex_str.length-=2;
lex->yytoklen-=2; lip->yytoklen-=2;
return (HEX_NUM); return (HEX_NUM);
} }
yyUnget(); yyUnget();
} }
else if (c == 'b' && (lex->ptr - lex->tok_start) == 2 && else if (c == 'b' && (lip->ptr - lip->tok_start) == 2 &&
lex->tok_start[0] == '0' ) lip->tok_start[0] == '0' )
{ // b'bin-number' { // b'bin-number'
while (my_isxdigit(cs,(c = yyGet()))) ; while (my_isxdigit(cs,(c = yyGet()))) ;
if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c]) if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c])
{ {
yylval->lex_str= get_token(lex, yyLength()); yylval->lex_str= get_token(lip, yyLength());
yylval->lex_str.str+= 2; // Skip 0x yylval->lex_str.str+= 2; // Skip 0x
yylval->lex_str.length-= 2; yylval->lex_str.length-= 2;
lex->yytoklen-= 2; lip->yytoklen-= 2;
return (BIN_NUM); return (BIN_NUM);
} }
yyUnget(); yyUnget();
@ -778,9 +797,9 @@ int MYSQLlex(void *arg, void *yythd)
if (my_mbcharlen(cs, c) > 1) if (my_mbcharlen(cs, c) > 1)
{ {
int l; int l;
if ((l = my_ismbchar(cs, lex->ptr-1, lex->end_of_query)) == 0) if ((l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query)) == 0)
break; break;
lex->ptr += l-1; lip->ptr += l-1;
} }
} }
} }
@ -792,16 +811,16 @@ int MYSQLlex(void *arg, void *yythd)
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
} }
if (c == '.' && ident_map[yyPeek()]) if (c == '.' && ident_map[yyPeek()])
lex->next_state=MY_LEX_IDENT_SEP;// Next is '.' lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
yylval->lex_str= get_token(lex,yyLength()); yylval->lex_str= get_token(lip, yyLength());
return(result_state); return(result_state);
case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char
{ {
uint double_quotes= 0; uint double_quotes= 0;
char quote_char= c; // Used char char quote_char= c; // Used char
lex->tok_start=lex->ptr; // Skip first ` lip->tok_start=lip->ptr; // Skip first `
while ((c=yyGet())) while ((c=yyGet()))
{ {
int var_length; int var_length;
@ -819,23 +838,23 @@ int MYSQLlex(void *arg, void *yythd)
#ifdef USE_MB #ifdef USE_MB
else if (var_length < 1) else if (var_length < 1)
break; // Error break; // Error
lex->ptr+= var_length-1; lip->ptr+= var_length-1;
#endif #endif
} }
if (double_quotes) if (double_quotes)
yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes, yylval->lex_str=get_quoted_token(lip, yyLength() - double_quotes,
quote_char); quote_char);
else else
yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str=get_token(lip, yyLength());
if (c == quote_char) if (c == quote_char)
yySkip(); // Skip end ` yySkip(); // Skip end `
lex->next_state= MY_LEX_START; lip->next_state= MY_LEX_START;
return(IDENT_QUOTED); return(IDENT_QUOTED);
} }
case MY_LEX_INT_OR_REAL: // Compleat int or incompleat real case MY_LEX_INT_OR_REAL: // Compleat int or incompleat real
if (c != '.') if (c != '.')
{ // Found complete integer number. { // Found complete integer number.
yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str=get_token(lip, yyLength());
return int_token(yylval->lex_str.str,yylval->lex_str.length); return int_token(yylval->lex_str.str,yylval->lex_str.length);
} }
// fall through // fall through
@ -853,47 +872,47 @@ int MYSQLlex(void *arg, void *yythd)
break; break;
} }
while (my_isdigit(cs,yyGet())) ; while (my_isdigit(cs,yyGet())) ;
yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str=get_token(lip, yyLength());
return(FLOAT_NUM); return(FLOAT_NUM);
} }
yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str=get_token(lip, yyLength());
return(DECIMAL_NUM); return(DECIMAL_NUM);
case MY_LEX_HEX_NUMBER: // Found x'hexstring' case MY_LEX_HEX_NUMBER: // Found x'hexstring'
yyGet(); // Skip ' yyGet(); // Skip '
while (my_isxdigit(cs,(c = yyGet()))) ; while (my_isxdigit(cs,(c = yyGet()))) ;
length=(lex->ptr - lex->tok_start); // Length of hexnum+3 length=(lip->ptr - lip->tok_start); // Length of hexnum+3
if (!(length & 1) || c != '\'') if (!(length & 1) || c != '\'')
{ {
return(ABORT_SYM); // Illegal hex constant return(ABORT_SYM); // Illegal hex constant
} }
yyGet(); // get_token makes an unget yyGet(); // get_token makes an unget
yylval->lex_str=get_token(lex,length); yylval->lex_str=get_token(lip, length);
yylval->lex_str.str+=2; // Skip x' yylval->lex_str.str+=2; // Skip x'
yylval->lex_str.length-=3; // Don't count x' and last ' yylval->lex_str.length-=3; // Don't count x' and last '
lex->yytoklen-=3; lip->yytoklen-=3;
return (HEX_NUM); return (HEX_NUM);
case MY_LEX_BIN_NUMBER: // Found b'bin-string' case MY_LEX_BIN_NUMBER: // Found b'bin-string'
yyGet(); // Skip ' yyGet(); // Skip '
while ((c= yyGet()) == '0' || c == '1'); while ((c= yyGet()) == '0' || c == '1');
length= (lex->ptr - lex->tok_start); // Length of bin-num + 3 length= (lip->ptr - lip->tok_start); // Length of bin-num + 3
if (c != '\'') if (c != '\'')
return(ABORT_SYM); // Illegal hex constant return(ABORT_SYM); // Illegal hex constant
yyGet(); // get_token makes an unget yyGet(); // get_token makes an unget
yylval->lex_str= get_token(lex, length); yylval->lex_str= get_token(lip, length);
yylval->lex_str.str+= 2; // Skip b' yylval->lex_str.str+= 2; // Skip b'
yylval->lex_str.length-= 3; // Don't count b' and last ' yylval->lex_str.length-= 3; // Don't count b' and last '
lex->yytoklen-= 3; lip->yytoklen-= 3;
return (BIN_NUM); return (BIN_NUM);
case MY_LEX_CMP_OP: // Incomplete comparison operator case MY_LEX_CMP_OP: // Incomplete comparison operator
if (state_map[yyPeek()] == MY_LEX_CMP_OP || if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
state_map[yyPeek()] == MY_LEX_LONG_CMP_OP) state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
yySkip(); yySkip();
if ((tokval = find_keyword(lex,(uint) (lex->ptr - lex->tok_start),0))) if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0)))
{ {
lex->next_state= MY_LEX_START; // Allow signed numbers lip->next_state= MY_LEX_START; // Allow signed numbers
return(tokval); return(tokval);
} }
state = MY_LEX_CHAR; // Something fishy found state = MY_LEX_CHAR; // Something fishy found
@ -907,9 +926,9 @@ int MYSQLlex(void *arg, void *yythd)
if (state_map[yyPeek()] == MY_LEX_CMP_OP) if (state_map[yyPeek()] == MY_LEX_CMP_OP)
yySkip(); yySkip();
} }
if ((tokval = find_keyword(lex,(uint) (lex->ptr - lex->tok_start),0))) if ((tokval = find_keyword(lip, (uint) (lip->ptr - lip->tok_start),0)))
{ {
lex->next_state= MY_LEX_START; // Found long op lip->next_state= MY_LEX_START; // Found long op
return(tokval); return(tokval);
} }
state = MY_LEX_CHAR; // Something fishy found state = MY_LEX_CHAR; // Something fishy found
@ -922,24 +941,24 @@ int MYSQLlex(void *arg, void *yythd)
break; break;
} }
yySkip(); yySkip();
tokval = find_keyword(lex,2,0); // Is a bool operator tokval = find_keyword(lip,2,0); // Is a bool operator
lex->next_state= MY_LEX_START; // Allow signed numbers lip->next_state= MY_LEX_START; // Allow signed numbers
return(tokval); return(tokval);
case MY_LEX_STRING_OR_DELIMITER: case MY_LEX_STRING_OR_DELIMITER:
if (((THD *) yythd)->variables.sql_mode & MODE_ANSI_QUOTES) if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
{ {
state= MY_LEX_USER_VARIABLE_DELIMITER; state= MY_LEX_USER_VARIABLE_DELIMITER;
break; break;
} }
/* " used for strings */ /* " used for strings */
case MY_LEX_STRING: // Incomplete text string case MY_LEX_STRING: // Incomplete text string
if (!(yylval->lex_str.str = get_text(lex))) if (!(yylval->lex_str.str = get_text(lip)))
{ {
state= MY_LEX_CHAR; // Read char by char state= MY_LEX_CHAR; // Read char by char
break; break;
} }
yylval->lex_str.length=lex->yytoklen; yylval->lex_str.length=lip->yytoklen;
return(TEXT_STRING); return(TEXT_STRING);
case MY_LEX_COMMENT: // Comment case MY_LEX_COMMENT: // Comment
@ -963,7 +982,7 @@ int MYSQLlex(void *arg, void *yythd)
state=MY_LEX_START; state=MY_LEX_START;
if (my_isdigit(cs,yyPeek())) if (my_isdigit(cs,yyPeek()))
{ // Version number { // Version number
version=strtol((char*) lex->ptr,(char**) &lex->ptr,10); version=strtol((char*) lip->ptr,(char**) &lip->ptr,10);
} }
if (version <= MYSQL_VERSION_ID) if (version <= MYSQL_VERSION_ID)
{ {
@ -971,13 +990,13 @@ int MYSQLlex(void *arg, void *yythd)
break; break;
} }
} }
while (lex->ptr != lex->end_of_query && while (lip->ptr != lip->end_of_query &&
((c=yyGet()) != '*' || yyPeek() != '/')) ((c=yyGet()) != '*' || yyPeek() != '/'))
{ {
if (c == '\n') if (c == '\n')
lex->yylineno++; lip->yylineno++;
} }
if (lex->ptr != lex->end_of_query) if (lip->ptr != lip->end_of_query)
yySkip(); // remove last '/' yySkip(); // remove last '/'
state = MY_LEX_START; // Try again state = MY_LEX_START; // Try again
break; break;
@ -1002,14 +1021,13 @@ int MYSQLlex(void *arg, void *yythd)
case MY_LEX_SEMICOLON: // optional line terminator case MY_LEX_SEMICOLON: // optional line terminator
if (yyPeek()) if (yyPeek())
{ {
THD* thd= (THD*)yythd;
if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) && if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) &&
!lex->stmt_prepare_mode) !lex->stmt_prepare_mode)
{ {
lex->safe_to_cache_query= 0; lex->safe_to_cache_query= 0;
lex->found_semicolon=(char*) lex->ptr; lip->found_semicolon= lip->ptr;
thd->server_status|= SERVER_MORE_RESULTS_EXISTS; thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
lex->next_state= MY_LEX_END; lip->next_state= MY_LEX_END;
return (END_OF_INPUT); return (END_OF_INPUT);
} }
state= MY_LEX_CHAR; // Return ';' state= MY_LEX_CHAR; // Return ';'
@ -1017,15 +1035,15 @@ int MYSQLlex(void *arg, void *yythd)
} }
/* fall true */ /* fall true */
case MY_LEX_EOL: case MY_LEX_EOL:
if (lex->ptr >= lex->end_of_query) if (lip->ptr >= lip->end_of_query)
{ {
lex->next_state=MY_LEX_END; // Mark for next loop lip->next_state=MY_LEX_END; // Mark for next loop
return(END_OF_INPUT); return(END_OF_INPUT);
} }
state=MY_LEX_CHAR; state=MY_LEX_CHAR;
break; break;
case MY_LEX_END: case MY_LEX_END:
lex->next_state=MY_LEX_END; lip->next_state=MY_LEX_END;
return(0); // We found end of input last time return(0); // We found end of input last time
/* Actually real shouldn't start with . but allow them anyhow */ /* Actually real shouldn't start with . but allow them anyhow */
@ -1045,26 +1063,26 @@ int MYSQLlex(void *arg, void *yythd)
case MY_LEX_STRING_OR_DELIMITER: case MY_LEX_STRING_OR_DELIMITER:
break; break;
case MY_LEX_USER_END: case MY_LEX_USER_END:
lex->next_state=MY_LEX_SYSTEM_VAR; lip->next_state=MY_LEX_SYSTEM_VAR;
break; break;
default: default:
lex->next_state=MY_LEX_HOSTNAME; lip->next_state=MY_LEX_HOSTNAME;
break; break;
} }
yylval->lex_str.str=(char*) lex->ptr; yylval->lex_str.str=(char*) lip->ptr;
yylval->lex_str.length=1; yylval->lex_str.length=1;
return((int) '@'); return((int) '@');
case MY_LEX_HOSTNAME: // end '@' of user@hostname case MY_LEX_HOSTNAME: // end '@' of user@hostname
for (c=yyGet() ; for (c=yyGet() ;
my_isalnum(cs,c) || c == '.' || c == '_' || c == '$'; my_isalnum(cs,c) || c == '.' || c == '_' || c == '$';
c= yyGet()) ; c= yyGet()) ;
yylval->lex_str=get_token(lex,yyLength()); yylval->lex_str=get_token(lip, yyLength());
return(LEX_HOSTNAME); return(LEX_HOSTNAME);
case MY_LEX_SYSTEM_VAR: case MY_LEX_SYSTEM_VAR:
yylval->lex_str.str=(char*) lex->ptr; yylval->lex_str.str=(char*) lip->ptr;
yylval->lex_str.length=1; yylval->lex_str.length=1;
yySkip(); // Skip '@' yySkip(); // Skip '@'
lex->next_state= (state_map[yyPeek()] == lip->next_state= (state_map[yyPeek()] ==
MY_LEX_USER_VARIABLE_DELIMITER ? MY_LEX_USER_VARIABLE_DELIMITER ?
MY_LEX_OPERATOR_OR_IDENT : MY_LEX_OPERATOR_OR_IDENT :
MY_LEX_IDENT_OR_KEYWORD); MY_LEX_IDENT_OR_KEYWORD);
@ -1081,16 +1099,16 @@ int MYSQLlex(void *arg, void *yythd)
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT; result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
if (c == '.') if (c == '.')
lex->next_state=MY_LEX_IDENT_SEP; lip->next_state=MY_LEX_IDENT_SEP;
length= (uint) (lex->ptr - lex->tok_start)-1; length= (uint) (lip->ptr - lip->tok_start)-1;
if (length == 0) if (length == 0)
return(ABORT_SYM); // Names must be nonempty. return(ABORT_SYM); // Names must be nonempty.
if ((tokval= find_keyword(lex,length,0))) if ((tokval= find_keyword(lip, length,0)))
{ {
yyUnget(); // Put back 'c' yyUnget(); // Put back 'c'
return(tokval); // Was keyword return(tokval); // Was keyword
} }
yylval->lex_str=get_token(lex,length); yylval->lex_str=get_token(lip, length);
return(result_state); return(result_state);
} }
} }

View File

@ -543,7 +543,7 @@ public:
void set_thd(THD *thd_arg) { thd= thd_arg; } void set_thd(THD *thd_arg) { thd= thd_arg; }
inline bool is_union (); inline bool is_union ();
friend void lex_start(THD *thd, const char *buf, uint length); friend void lex_start(THD *thd);
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
List<Item> *get_unit_column_types(); List<Item> *get_unit_column_types();
@ -744,7 +744,7 @@ public:
void cut_subtree() { slave= 0; } void cut_subtree() { slave= 0; }
bool test_limit(); bool test_limit();
friend void lex_start(THD *thd, const char *buf, uint length); friend void lex_start(THD *thd);
st_select_lex() : n_sum_items(0), n_child_sum_items(0) {} st_select_lex() : n_sum_items(0), n_child_sum_items(0) {}
void make_empty_select() void make_empty_select()
{ {
@ -992,23 +992,67 @@ struct st_parsing_options
}; };
/**
This class represents the character input stream consumed during
lexical analysis.
*/
class Lex_input_stream
{
public:
Lex_input_stream(THD *thd, const char* buff, unsigned int length);
~Lex_input_stream();
/** Current thread. */
THD *m_thd;
/** Current line number. */
uint yylineno;
/** Length of the last token parsed. */
uint yytoklen;
/** Interface with bison, value of the last token parsed. */
LEX_YYSTYPE yylval;
/** Pointer to the current position in the input stream. */
const char* ptr;
/** Starting position of the last token parsed. */
const char* tok_start;
/** Ending position of the last token parsed. */
const char* tok_end;
/** End of the query text in the input stream. */
const char* end_of_query;
/** Starting position of the previous token parsed. */
const char* tok_start_prev;
/** Begining of the query text in the input stream. */
const char* buf;
/** Current state of the lexical analyser. */
enum my_lex_states next_state;
/** Position of ';' in the stream, to delimit multiple queries. */
const char* found_semicolon;
/** SQL_MODE = IGNORE_SPACE. */
bool ignore_space;
};
/* The state of the lex parsing. This is saved in the THD struct */ /* The state of the lex parsing. This is saved in the THD struct */
typedef struct st_lex : public Query_tables_list typedef struct st_lex : public Query_tables_list
{ {
uint yylineno,yytoklen; /* Simulate lex */
LEX_YYSTYPE yylval;
SELECT_LEX_UNIT unit; /* most upper unit */ SELECT_LEX_UNIT unit; /* most upper unit */
SELECT_LEX select_lex; /* first SELECT_LEX */ SELECT_LEX select_lex; /* first SELECT_LEX */
/* current SELECT_LEX in parsing */ /* current SELECT_LEX in parsing */
SELECT_LEX *current_select; SELECT_LEX *current_select;
/* list of all SELECT_LEX */ /* list of all SELECT_LEX */
SELECT_LEX *all_selects_list; SELECT_LEX *all_selects_list;
const char *buf; /* The beginning of string, used by SPs */
const char *ptr,*tok_start,*tok_end,*end_of_query;
/* The value of tok_start as they were one call of MYSQLlex before */
const char *tok_start_prev;
char *length,*dec,*change; char *length,*dec,*change;
LEX_STRING name; LEX_STRING name;
@ -1017,7 +1061,6 @@ typedef struct st_lex : public Query_tables_list
char *backup_dir; /* For RESTORE/BACKUP */ char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */ char* to_log; /* For PURGE MASTER LOGS TO */
char* x509_subject,*x509_issuer,*ssl_cipher; char* x509_subject,*x509_issuer,*ssl_cipher;
char* found_semicolon; /* For multi queries - next query */
String *wild; String *wild;
sql_exchange *exchange; sql_exchange *exchange;
select_result *result; select_result *result;
@ -1101,7 +1144,6 @@ typedef struct st_lex : public Query_tables_list
thr_lock_type lock_option; thr_lock_type lock_option;
enum SSL_type ssl_type; /* defined in violite.h */ enum SSL_type ssl_type; /* defined in violite.h */
enum my_lex_states next_state;
enum enum_duplicates duplicates; enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation; enum enum_tx_isolation tx_isolation;
enum enum_ha_read_modes ha_read_mode; enum enum_ha_read_modes ha_read_mode;
@ -1133,7 +1175,7 @@ typedef struct st_lex : public Query_tables_list
uint8 create_view_algorithm; uint8 create_view_algorithm;
uint8 create_view_check; uint8 create_view_check;
bool drop_if_exists, drop_temporary, local_file, one_shot_set; bool drop_if_exists, drop_temporary, local_file, one_shot_set;
bool in_comment, ignore_space, verbose, no_write_to_binlog; bool in_comment, verbose, no_write_to_binlog;
bool tx_chain, tx_release; bool tx_chain, tx_release;
/* /*
Special JOIN::prepare mode: changing of query is prohibited. Special JOIN::prepare mode: changing of query is prohibited.
@ -1210,7 +1252,8 @@ typedef struct st_lex : public Query_tables_list
Pointers to part of LOAD DATA statement that should be rewritten Pointers to part of LOAD DATA statement that should be rewritten
during replication ("LOCAL 'filename' REPLACE INTO" part). during replication ("LOCAL 'filename' REPLACE INTO" part).
*/ */
const char *fname_start, *fname_end; const char *fname_start;
const char *fname_end;
/* /*
Reference to a struct that contains information in various commands Reference to a struct that contains information in various commands
@ -1327,7 +1370,7 @@ struct st_lex_local: public st_lex
extern void lex_init(void); extern void lex_init(void);
extern void lex_free(void); extern void lex_free(void);
extern void lex_start(THD *thd, const char *buf, uint length); extern void lex_start(THD *thd);
extern void lex_end(LEX *lex); extern void lex_end(LEX *lex);
extern int MYSQLlex(void *arg, void *yythd); extern int MYSQLlex(void *arg, void *yythd);
extern const char *skip_rear_comments(const char *ubegin, const char *uend); extern const char *skip_rear_comments(const char *ubegin, const char *uend);

View File

@ -300,6 +300,7 @@ pthread_handler_t handle_bootstrap(void *arg)
THD *thd=(THD*) arg; THD *thd=(THD*) arg;
FILE *file=bootstrap_file; FILE *file=bootstrap_file;
char *buff; char *buff;
const char* found_semicolon= NULL;
/* The following must be called before DBUG_ENTER */ /* The following must be called before DBUG_ENTER */
thd->thread_stack= (char*) &thd; thd->thread_stack= (char*) &thd;
@ -375,7 +376,7 @@ pthread_handler_t handle_bootstrap(void *arg)
*/ */
thd->query_id=next_query_id(); thd->query_id=next_query_id();
thd->set_time(); thd->set_time();
mysql_parse(thd,thd->query,length); mysql_parse(thd, thd->query, length, & found_semicolon);
close_thread_tables(thd); // Free tables close_thread_tables(thd); // Free tables
if (thd->is_fatal_error) if (thd->is_fatal_error)
@ -889,17 +890,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
char *packet_end= thd->query + thd->query_length; char *packet_end= thd->query + thd->query_length;
/* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */ /* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
const char *format= "%.*b"; const char *format= "%.*b";
const char* found_semicolon= NULL;
general_log_print(thd, command, format, thd->query_length, thd->query); general_log_print(thd, command, format, thd->query_length, thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query)); DBUG_PRINT("query",("%-.4096s",thd->query));
if (!(specialflag & SPECIAL_NO_PRIOR)) if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR); my_pthread_setprio(pthread_self(),QUERY_PRIOR);
mysql_parse(thd,thd->query, thd->query_length); mysql_parse(thd, thd->query, thd->query_length, & found_semicolon);
while (!thd->killed && thd->lex->found_semicolon && !thd->net.report_error) while (!thd->killed && found_semicolon && !thd->net.report_error)
{ {
char *next_packet= thd->lex->found_semicolon; char *next_packet= (char*) found_semicolon;
net->no_send_error= 0; net->no_send_error= 0;
/* /*
Multiple queries exits, execute them individually Multiple queries exits, execute them individually
@ -924,7 +927,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->set_time(); /* Reset the query start time. */ thd->set_time(); /* Reset the query start time. */
/* TODO: set thd->lex->sql_command to SQLCOM_END here */ /* TODO: set thd->lex->sql_command to SQLCOM_END here */
VOID(pthread_mutex_unlock(&LOCK_thread_count)); VOID(pthread_mutex_unlock(&LOCK_thread_count));
mysql_parse(thd, next_packet, length); mysql_parse(thd, next_packet, length, & found_semicolon);
} }
if (!(specialflag & SPECIAL_NO_PRIOR)) if (!(specialflag & SPECIAL_NO_PRIOR))
@ -946,7 +949,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint dummy; uint dummy;
/* used as fields initializator */ /* used as fields initializator */
lex_start(thd, 0, 0); lex_start(thd);
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS], statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
&LOCK_status); &LOCK_status);
@ -985,7 +988,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break; break;
/* init structures for VIEW processing */ /* init structures for VIEW processing */
table_list.select_lex= &(thd->lex->select_lex); table_list.select_lex= &(thd->lex->select_lex);
mysql_init_query(thd, "", 0);
lex_start(thd);
mysql_reset_thd_for_next_command(thd);
thd->lex-> thd->lex->
select_lex.table_list.link_in_list((byte*) &table_list, select_lex.table_list.link_in_list((byte*) &table_list,
(byte**) &table_list.next_local); (byte**) &table_list.next_local);
@ -5038,20 +5044,6 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
} }
/****************************************************************************
Initialize global thd variables needed for query
****************************************************************************/
void
mysql_init_query(THD *thd, const char *buf, uint length)
{
DBUG_ENTER("mysql_init_query");
lex_start(thd, buf, length);
mysql_reset_thd_for_next_command(thd);
DBUG_VOID_RETURN;
}
/* /*
Reset THD part responsible for command processing state. Reset THD part responsible for command processing state.
@ -5263,22 +5255,55 @@ void mysql_init_multi_delete(LEX *lex)
mysql_test_parse_for_slave() in this same file. mysql_test_parse_for_slave() in this same file.
*/ */
void mysql_parse(THD *thd, char *inBuf, uint length) /**
Parse a query.
@param thd Current thread
@param inBuf Begining of the query text
@param length Length of the query text
@param [out] semicolon For multi queries, position of the character of
the next query in the query text.
*/
void mysql_parse(THD *thd, const char *inBuf, uint length,
const char ** found_semicolon)
{ {
DBUG_ENTER("mysql_parse"); DBUG_ENTER("mysql_parse");
DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on();); DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
mysql_init_query(thd, inBuf, length); /*
Warning.
The purpose of query_cache_send_result_to_client() is to lookup the
query in the query cache first, to avoid parsing and executing it.
So, the natural implementation would be to:
- first, call query_cache_send_result_to_client,
- second, if caching failed, initialise the lexical and syntactic parser.
The problem is that the query cache depends on a clean initialization
of (among others) lex->safe_to_cache_query and thd->server_status,
which are reset respectively in
- lex_start()
- mysql_reset_thd_for_next_command()
So, initializing the lexical analyser *before* using the query cache
is required for the cache to work properly.
FIXME: cleanup the dependencies in the code to simplify this.
*/
lex_start(thd);
mysql_reset_thd_for_next_command(thd);
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0) if (query_cache_send_result_to_client(thd, (char*) inBuf, length) <= 0)
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
sp_cache_flush_obsolete(&thd->sp_proc_cache); sp_cache_flush_obsolete(&thd->sp_proc_cache);
sp_cache_flush_obsolete(&thd->sp_func_cache); sp_cache_flush_obsolete(&thd->sp_func_cache);
if (!MYSQLparse((void *)thd) && ! thd->is_fatal_error) Lex_input_stream lip(thd, inBuf, length);
thd->m_lip= &lip;
int err= MYSQLparse(thd);
*found_semicolon= lip.found_semicolon;
if (!err && ! thd->is_fatal_error)
{ {
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
if (mqh_used && thd->user_connect && if (mqh_used && thd->user_connect &&
@ -5301,8 +5326,8 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
PROCESSLIST. PROCESSLIST.
Note that we don't need LOCK_thread_count to modify query_length. Note that we don't need LOCK_thread_count to modify query_length.
*/ */
if (lex->found_semicolon && if (lip.found_semicolon &&
(thd->query_length= (ulong)(lex->found_semicolon - thd->query))) (thd->query_length= (ulong)(lip.found_semicolon - thd->query)))
thd->query_length--; thd->query_length--;
/* Actually execute the query */ /* Actually execute the query */
mysql_execute_command(thd); mysql_execute_command(thd);
@ -5329,6 +5354,12 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
thd->cleanup_after_query(); thd->cleanup_after_query();
DBUG_ASSERT(thd->change_list.is_empty()); DBUG_ASSERT(thd->change_list.is_empty());
} }
else
{
/* There are no multi queries in the cache. */
*found_semicolon= NULL;
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
@ -5349,8 +5380,13 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
bool error= 0; bool error= 0;
DBUG_ENTER("mysql_test_parse_for_slave"); DBUG_ENTER("mysql_test_parse_for_slave");
mysql_init_query(thd, inBuf, length); Lex_input_stream lip(thd, inBuf, length);
if (!MYSQLparse((void*) thd) && ! thd->is_fatal_error && thd->m_lip= &lip;
lex_start(thd);
mysql_reset_thd_for_next_command(thd);
int err= MYSQLparse((void*) thd);
if (!err && ! thd->is_fatal_error &&
all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first)) all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
error= 1; /* Ignore question */ error= 1; /* Ignore question */
thd->end_statement(); thd->end_statement();
@ -6401,8 +6437,9 @@ bool check_simple_select()
if (lex->current_select != &lex->select_lex) if (lex->current_select != &lex->select_lex)
{ {
char command[80]; char command[80];
strmake(command, lex->yylval->symbol.str, Lex_input_stream *lip= thd->m_lip;
min(lex->yylval->symbol.length, sizeof(command)-1)); strmake(command, lip->yylval->symbol.str,
min(lip->yylval->symbol.length, sizeof(command)-1));
my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command); my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
return 1; return 1;
} }

View File

@ -3718,7 +3718,11 @@ bool mysql_unpack_partition(THD *thd,
thd->lex= &lex; thd->lex= &lex;
thd->variables.character_set_client= system_charset_info; thd->variables.character_set_client= system_charset_info;
lex_start(thd, part_buf, part_info_len);
Lex_input_stream lip(thd, part_buf, part_info_len);
thd->m_lip= &lip;
lex_start(thd);
/* /*
We need to use the current SELECT_LEX since I need to keep the We need to use the current SELECT_LEX since I need to keep the
Name_resolution_context object which is referenced from the Name_resolution_context object which is referenced from the

View File

@ -2850,10 +2850,14 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
old_stmt_arena= thd->stmt_arena; old_stmt_arena= thd->stmt_arena;
thd->stmt_arena= this; thd->stmt_arena= this;
lex_start(thd, thd->query, thd->query_length);
lex->stmt_prepare_mode= TRUE;
error= MYSQLparse((void *)thd) || thd->is_fatal_error || Lex_input_stream lip(thd, thd->query, thd->query_length);
thd->m_lip= &lip;
lex_start(thd);
lex->stmt_prepare_mode= TRUE;
int err= MYSQLparse((void *)thd);
error= err || thd->is_fatal_error ||
thd->net.report_error || init_param_array(this); thd->net.report_error || init_param_array(this);
/* /*

View File

@ -976,10 +976,14 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
LEX_STRING *trg_definer= it_definer++; LEX_STRING *trg_definer= it_definer++;
thd->variables.sql_mode= (ulong)*trg_sql_mode; thd->variables.sql_mode= (ulong)*trg_sql_mode;
lex_start(thd, trg_create_str->str, trg_create_str->length);
thd->spcont= 0; Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length);
if (MYSQLparse((void *)thd) || thd->is_fatal_error) thd->m_lip= &lip;
lex_start(thd);
thd->spcont= 0;
int err= MYSQLparse((void *)thd);
if (err || thd->is_fatal_error)
{ {
/* Currently sphead is always deleted in case of a parse error */ /* Currently sphead is always deleted in case of a parse error */
DBUG_ASSERT(lex.sphead == 0); DBUG_ASSERT(lex.sphead == 0);

View File

@ -985,10 +985,14 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
now Lex placed in statement memory now Lex placed in statement memory
*/ */
table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local; table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
lex_start(thd, table->query.str, table->query.length);
view_select= &lex->select_lex;
view_select->select_number= ++thd->select_number;
{ {
Lex_input_stream lip(thd, table->query.str, table->query.length);
thd->m_lip= &lip;
lex_start(thd);
view_select= &lex->select_lex;
view_select->select_number= ++thd->select_number;
ulong save_mode= thd->variables.sql_mode; ulong save_mode= thd->variables.sql_mode;
/* switch off modes which can prevent normal parsing of VIEW /* switch off modes which can prevent normal parsing of VIEW
- MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing - MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing

View File

@ -104,12 +104,13 @@ const LEX_STRING null_lex_str={0,0};
void my_parse_error(const char *s) void my_parse_error(const char *s)
{ {
THD *thd= current_thd; THD *thd= current_thd;
Lex_input_stream *lip= thd->m_lip;
char *yytext= (char*) thd->lex->tok_start; const char *yytext= lip->tok_start;
/* Push an error into the error stack */ /* Push an error into the error stack */
my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s, my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
(yytext ? (char*) yytext : ""), (yytext ? yytext : ""),
thd->lex->yylineno); lip->yylineno);
} }
/** /**
@ -1837,7 +1838,9 @@ opt_ev_comment: /* empty */ { $$= 0; }
ev_sql_stmt: ev_sql_stmt:
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
/* /*
This stops the following : This stops the following :
@ -1874,22 +1877,23 @@ ev_sql_stmt:
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->ptr; lex->sphead->m_body_begin= lip->ptr;
Lex->event_parse_data->body_begin= lex->ptr; lex->event_parse_data->body_begin= lip->ptr;
} }
ev_sql_stmt_inner ev_sql_stmt_inner
{ {
LEX *lex=Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
/* return back to the original memory root ASAP */ /* return back to the original memory root ASAP */
lex->sphead->init_strings(YYTHD, lex); lex->sphead->init_strings(thd, lex);
lex->sphead->restore_thd_mem_root(YYTHD); lex->sphead->restore_thd_mem_root(thd);
lex->sp_chistics.suid= SP_IS_SUID; //always the definer! lex->sp_chistics.suid= SP_IS_SUID; //always the definer!
Lex->event_parse_data->init_body(YYTHD); lex->event_parse_data->init_body(thd);
} }
; ;
@ -1983,7 +1987,9 @@ create_function_tail:
} }
| '(' | '('
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
sp_head *sp; sp_head *sp;
/* /*
@ -2003,9 +2009,9 @@ create_function_tail:
} }
/* Order is important here: new - reset - init */ /* Order is important here: new - reset - init */
sp= new sp_head(); sp= new sp_head();
sp->reset_thd_mem_root(YYTHD); sp->reset_thd_mem_root(thd);
sp->init(lex); sp->init(lex);
sp->init_sp_name(YYTHD, lex->spname); sp->init_sp_name(thd, lex->spname);
sp->m_type= TYPE_ENUM_FUNCTION; sp->m_type= TYPE_ENUM_FUNCTION;
lex->sphead= sp; lex->sphead= sp;
@ -2014,15 +2020,17 @@ create_function_tail:
stored procedure, otherwise yylex will chop it into pieces stored procedure, otherwise yylex will chop it into pieces
at each ';'. at each ';'.
*/ */
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; $<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
lex->sphead->m_param_begin= lex->tok_start+1; lex->sphead->m_param_begin= lip->tok_start+1;
} }
sp_fdparam_list ')' sp_fdparam_list ')'
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_param_end= lex->tok_start; lex->sphead->m_param_end= lip->tok_start;
} }
RETURNS_SYM RETURNS_SYM
{ {
@ -2057,10 +2065,12 @@ create_function_tail:
} }
sp_c_chistics sp_c_chistics
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->tok_start; lex->sphead->m_body_begin= lip->tok_start;
} }
sp_proc_stmt sp_proc_stmt
{ {
@ -2666,14 +2676,18 @@ sp_proc_stmt_if:
sp_proc_stmt_statement: sp_proc_stmt_statement:
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->reset_lex(YYTHD); lex->sphead->reset_lex(thd);
lex->sphead->m_tmp_query= lex->tok_start; lex->sphead->m_tmp_query= lip->tok_start;
} }
statement statement
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
sp->m_flags|= sp_get_flags_for_command(lex); sp->m_flags|= sp_get_flags_for_command(lex);
@ -2700,15 +2714,15 @@ sp_proc_stmt_statement:
lex->tok_end otherwise. lex->tok_end otherwise.
*/ */
if (yychar == YYEMPTY) if (yychar == YYEMPTY)
i->m_query.length= lex->ptr - sp->m_tmp_query; i->m_query.length= lip->ptr - sp->m_tmp_query;
else else
i->m_query.length= lex->tok_end - sp->m_tmp_query; i->m_query.length= lip->tok_end - sp->m_tmp_query;
i->m_query.str= strmake_root(YYTHD->mem_root, i->m_query.str= strmake_root(thd->mem_root,
sp->m_tmp_query, sp->m_tmp_query,
i->m_query.length); i->m_query.length);
sp->add_instr(i); sp->add_instr(i);
} }
sp->restore_lex(YYTHD); sp->restore_lex(thd);
} }
; ;
@ -6212,10 +6226,18 @@ select_item:
}; };
remember_name: remember_name:
{ $$=(char*) Lex->tok_start; }; {
THD *thd= YYTHD;
Lex_input_stream *lip= thd->m_lip;
$$= (char*) lip->tok_start;
};
remember_end: remember_end:
{ $$=(char*) Lex->tok_end; }; {
THD *thd= YYTHD;
Lex_input_stream *lip= thd->m_lip;
$$=(char*) lip->tok_end;
};
select_item2: select_item2:
table_wild { $$=$1; } /* table.* */ table_wild { $$=$1; } /* table.* */
@ -7983,12 +8005,14 @@ procedure_list2:
procedure_item: procedure_item:
remember_name expr remember_name expr
{ {
LEX *lex= Lex; THD *thd= YYTHD;
if (add_proc_to_list(lex->thd, $2)) Lex_input_stream *lip= thd->m_lip;
if (add_proc_to_list(thd, $2))
MYSQL_YYABORT; MYSQL_YYABORT;
if (!$2->name) if (!$2->name)
$2->set_name($1,(uint) ((char*) lex->tok_end - $1), $2->set_name($1,(uint) ((char*) lip->tok_end - $1),
YYTHD->charset()); thd->charset());
} }
; ;
@ -9078,13 +9102,16 @@ use: USE_SYM ident
load: LOAD DATA_SYM load: LOAD DATA_SYM
{ {
LEX *lex=Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
if (lex->sphead) if (lex->sphead)
{ {
my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA"); my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
MYSQL_YYABORT; MYSQL_YYABORT;
} }
lex->fname_start= lex->ptr; lex->fname_start= lip->ptr;
} }
load_data load_data
{} {}
@ -9118,8 +9145,10 @@ load_data:
} }
opt_duplicate INTO opt_duplicate INTO
{ {
LEX *lex=Lex; THD *thd= YYTHD;
lex->fname_end= lex->ptr; LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->fname_end= lip->ptr;
} }
TABLE_SYM table_ident TABLE_SYM table_ident
{ {
@ -9300,14 +9329,15 @@ param_marker:
PARAM_MARKER PARAM_MARKER
{ {
THD *thd= YYTHD; THD *thd= YYTHD;
LEX *lex= thd->lex; LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
Item_param *item; Item_param *item;
if (! lex->parsing_options.allows_variable) if (! lex->parsing_options.allows_variable)
{ {
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0)); my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
MYSQL_YYABORT; MYSQL_YYABORT;
} }
item= new Item_param((uint) (lex->tok_start - thd->query)); item= new Item_param((uint) (lip->tok_start - thd->query));
if (!($$= item) || lex->param_list.push_back(item)) if (!($$= item) || lex->param_list.push_back(item))
{ {
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
@ -9330,8 +9360,11 @@ signed_literal:
literal: literal:
text_literal { $$ = $1; } text_literal { $$ = $1; }
| NUM_literal { $$ = $1; } | NUM_literal { $$ = $1; }
| NULL_SYM { $$ = new Item_null(); | NULL_SYM
Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;} {
$$ = new Item_null();
YYTHD->m_lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
}
| FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); } | FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); }
| TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); } | TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); }
| HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);} | HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);}
@ -9421,8 +9454,10 @@ order_ident:
simple_ident: simple_ident:
ident ident
{ {
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
sp_variable_t *spv; sp_variable_t *spv;
LEX *lex = Lex;
sp_pcontext *spc = lex->spcont; sp_pcontext *spc = lex->spcont;
if (spc && (spv = spc->find_variable(&$1))) if (spc && (spv = spc->find_variable(&$1)))
{ {
@ -9435,7 +9470,7 @@ simple_ident:
Item_splocal *splocal; Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, spv->type, splocal= new Item_splocal($1, spv->offset, spv->type,
lex->tok_start_prev - lip->tok_start_prev -
lex->sphead->m_tmp_query); lex->sphead->m_tmp_query);
#ifndef DBUG_OFF #ifndef DBUG_OFF
if (splocal) if (splocal)
@ -10085,7 +10120,11 @@ option_value_list:
option_type_value: option_type_value:
{ {
if (Lex->sphead) THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
if (lex->sphead)
{ {
/* /*
If we are in SP we want have own LEX for each assignment. If we are in SP we want have own LEX for each assignment.
@ -10097,9 +10136,8 @@ option_type_value:
QQ: May be we should simply prohibit group assignments in SP? QQ: May be we should simply prohibit group assignments in SP?
*/ */
LEX *lex; lex->sphead->reset_lex(thd);
Lex->sphead->reset_lex(YYTHD); lex= thd->lex;
lex= Lex;
/* Set new LEX as if we at start of set rule. */ /* Set new LEX as if we at start of set rule. */
lex->sql_command= SQLCOM_SET_OPTION; lex->sql_command= SQLCOM_SET_OPTION;
@ -10107,12 +10145,14 @@ option_type_value:
lex->option_type=OPT_SESSION; lex->option_type=OPT_SESSION;
lex->var_list.empty(); lex->var_list.empty();
lex->one_shot_set= 0; lex->one_shot_set= 0;
lex->sphead->m_tmp_query= lex->tok_start; lex->sphead->m_tmp_query= lip->tok_start;
} }
} }
ext_option_value ext_option_value
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
if (lex->sphead) if (lex->sphead)
{ {
@ -10134,15 +10174,15 @@ option_type_value:
/* /*
Extract the query statement from the tokenizer. The Extract the query statement from the tokenizer. The
end is either lex->ptr, if there was no lookahead, end is either lip->ptr, if there was no lookahead,
lex->tok_end otherwise. lip->tok_end otherwise.
*/ */
if (yychar == YYEMPTY) if (yychar == YYEMPTY)
qbuff.length= lex->ptr - sp->m_tmp_query; qbuff.length= lip->ptr - sp->m_tmp_query;
else else
qbuff.length= lex->tok_end - sp->m_tmp_query; qbuff.length= lip->tok_end - sp->m_tmp_query;
if (!(qbuff.str= alloc_root(YYTHD->mem_root, qbuff.length + 5))) if (!(qbuff.str= alloc_root(thd->mem_root, qbuff.length + 5)))
MYSQL_YYABORT; MYSQL_YYABORT;
strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query, strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
@ -10151,7 +10191,7 @@ option_type_value:
i->m_query= qbuff; i->m_query= qbuff;
sp->add_instr(i); sp->add_instr(i);
} }
lex->sphead->restore_lex(YYTHD); lex->sphead->restore_lex(thd);
} }
}; };
@ -11400,7 +11440,9 @@ trigger_tail:
TRIGGER_SYM remember_name sp_name trg_action_time trg_event TRIGGER_SYM remember_name sp_name trg_action_time trg_event
ON remember_name table_ident FOR_SYM remember_name EACH_SYM ROW_SYM ON remember_name table_ident FOR_SYM remember_name EACH_SYM ROW_SYM
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
sp_head *sp; sp_head *sp;
if (lex->sphead) if (lex->sphead)
@ -11411,9 +11453,9 @@ trigger_tail:
if (!(sp= new sp_head())) if (!(sp= new sp_head()))
MYSQL_YYABORT; MYSQL_YYABORT;
sp->reset_thd_mem_root(YYTHD); sp->reset_thd_mem_root(thd);
sp->init(lex); sp->init(lex);
sp->init_sp_name(YYTHD, $3); sp->init_sp_name(thd, $3);
lex->stmt_definition_begin= $2; lex->stmt_definition_begin= $2;
lex->ident.str= $7; lex->ident.str= $7;
lex->ident.length= $10 - $7; lex->ident.length= $10 - $7;
@ -11426,12 +11468,12 @@ trigger_tail:
stored procedure, otherwise yylex will chop it into pieces stored procedure, otherwise yylex will chop it into pieces
at each ';'. at each ';'.
*/ */
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES; $<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES; thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->ptr; lex->sphead->m_body_begin= lip->ptr;
while (my_isspace(system_charset_info, lex->sphead->m_body_begin[0])) while (my_isspace(system_charset_info, lex->sphead->m_body_begin[0]))
++lex->sphead->m_body_begin; ++lex->sphead->m_body_begin;
} }
@ -11510,24 +11552,30 @@ sp_tail:
} }
'(' '('
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_param_begin= lex->tok_start+1; lex->sphead->m_param_begin= lip->tok_start+1;
} }
sp_pdparam_list sp_pdparam_list
')' ')'
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_param_end= lex->tok_start; lex->sphead->m_param_end= lip->tok_start;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics)); bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
} }
sp_c_chistics sp_c_chistics
{ {
LEX *lex= Lex; THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->sphead->m_chistics= &lex->sp_chistics; lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->tok_start; lex->sphead->m_body_begin= lip->tok_start;
} }
sp_proc_stmt sp_proc_stmt
{ {