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)
{
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;
/* 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_length= sp_sql.length();
lex_start(thd, thd->query, thd->query_length);
if (MYSQLparse(thd) || 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;
Lex_input_stream lip(thd, thd->query, thd->query_length);
thd->m_lip= &lip;
lex_start(thd);
int err= MYSQLparse(thd);
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;
thd->lex= &newlex;
newlex.current_select= NULL;
lex_start(thd, "", 0);
lex_start(thd);
int res= ha_create_table_from_engine(thd, db, table_name);
thd->lex= old_lex;
return res;

View file

@ -230,6 +230,7 @@ static void run_query(THD *thd, char *buf, char *end,
ulonglong save_thd_options= thd->options;
DBUG_ASSERT(sizeof(save_thd_options) == sizeof(thd->options));
NET save_net= thd->net;
const char* found_semicolon= NULL;
bzero((char*) &thd->net, sizeof(NET));
thd->query_length= end - buf;
@ -239,7 +240,7 @@ static void run_query(THD *thd, char *buf, char *end,
thd->options&= ~OPTION_BIN_LOG;
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)
{

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
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,
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
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
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 mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
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 is_update_query(enum enum_sql_command command);
bool alloc_query(THD *thd, const char *packet, uint packet_length);
void mysql_init_select(LEX *lex);
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);
void create_select_for_variable(const char *var_name);
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;
ulonglong save_options;
NET *net= &mysql->net;
const char *found_semicolon= NULL;
DBUG_ENTER("create_table_from_dump");
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;
DBUG_ASSERT(thd->db != 0);
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_length= save_db_length;
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)))
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;
if (MYSQLparse(thd) || thd->is_fatal_error || newlex.sphead == NULL)
if (ret || thd->is_fatal_error || newlex.sphead == NULL)
{
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 */
/* During parsing, we must use thd->mem_root */
MEM_ROOT *root= thd->mem_root;
Lex_input_stream *lip=thd->m_lip;
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 */
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
"/ * ! 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.str= strmake_root(root, m_body_begin, m_body.length);
m_defstr.length= endp - lex->buf;
m_defstr.str= strmake_root(root, lex->buf, m_defstr.length);
m_defstr.length= endp - lip->buf;
m_defstr.str= strmake_root(root, lip->buf, m_defstr.length);
DBUG_VOID_RETURN;
}
@ -1815,25 +1816,13 @@ sp_head::reset_lex(THD *thd)
DBUG_ENTER("sp_head::reset_lex");
LEX *sublex;
LEX *oldlex= thd->lex;
my_lex_states org_next_state= oldlex->next_state;
(void)m_lex.push_front(oldlex);
thd->lex= sublex= new st_lex;
/* Reset most stuff. The length arguments doesn't matter here. */
lex_start(thd, oldlex->buf, (ulong) (oldlex->end_of_query - oldlex->ptr));
/* Reset most stuff. */
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 */
sublex->sphead= oldlex->sphead;
sublex->spcont= oldlex->spcont;
@ -1866,10 +1855,6 @@ sp_head::restore_lex(THD *thd)
if (! oldlex)
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);
/*

View file

@ -176,7 +176,9 @@ public:
*/
HASH m_sroutines;
// 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

View file

@ -31,6 +31,7 @@ class Load_log_event;
class Slave_log_event;
class sp_rcontext;
class sp_cache;
class Lex_input_stream;
class Rows_log_event;
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
@ -1423,6 +1424,16 @@ public:
*/
query_id_t first_query_id;
} 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
partition_info *work_part_info;
#endif

View file

@ -33,13 +33,13 @@ sys_var *trg_new_row_fake_var= (sys_var*) 0x01;
/* Macros to look like lex */
#define yyGet() ((uchar) *(lex->ptr++))
#define yyGetLast() ((uchar) lex->ptr[-1])
#define yyPeek() ((uchar) lex->ptr[0])
#define yyPeek2() ((uchar) lex->ptr[1])
#define yyUnget() lex->ptr--
#define yySkip() lex->ptr++
#define yyLength() ((uint) (lex->ptr - lex->tok_start)-1)
#define yyGet() ((uchar) *(lip->ptr++))
#define yyGetLast() ((uchar) lip->ptr[-1])
#define yyPeek() ((uchar) lip->ptr[0])
#define yyPeek2() ((uchar) lip->ptr[1])
#define yyUnget() lip->ptr--
#define yySkip() lip->ptr++
#define yyLength() ((uint) (lip->ptr - lip->tok_start)-1)
/* Longest standard keyword name */
#define TOCK_NAME_LENGTH 24
@ -120,6 +120,28 @@ st_parsing_options::reset()
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.
@ -127,14 +149,12 @@ st_parsing_options::reset()
(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;
DBUG_ENTER("lex_start");
lex->thd= lex->unit.thd= thd;
lex->buf= lex->ptr= buf;
lex->end_of_query= buf+length;
lex->context_stack.empty();
lex->unit.init_query();
@ -167,14 +187,11 @@ void lex_start(THD *thd, const char *buf, uint length)
lex->stmt_prepare_mode= FALSE;
lex->derived_tables= 0;
lex->lock_option= TL_READ;
lex->found_semicolon= 0;
lex->safe_to_cache_query= 1;
lex->leaf_tables_insert= 0;
lex->parsing_options.reset();
lex->empty_field_list_on_rset= 0;
lex->select_lex.select_number= 1;
lex->next_state=MY_LEX_START;
lex->yylineno = 1;
lex->in_comment=0;
lex->length=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.group_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->duplicates= DUP_ERROR;
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);
if (symbol)
{
lex->yylval->symbol.symbol=symbol;
lex->yylval->symbol.str= (char*) tok;
lex->yylval->symbol.length=len;
lip->yylval->symbol.symbol=symbol;
lip->yylval->symbol.str= (char*) tok;
lip->yylval->symbol.length=len;
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;
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 symbol->tok;
}
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 */
static LEX_STRING get_token(LEX *lex,uint length)
static LEX_STRING get_token(Lex_input_stream *lip, uint length)
{
LEX_STRING tmp;
yyUnget(); // ptr points now after last token char
tmp.length=lex->yytoklen=length;
tmp.str=(char*) lex->thd->strmake((char*) lex->tok_start,tmp.length);
tmp.length=lip->yytoklen=length;
tmp.str= lip->m_thd->strmake(lip->tok_start, tmp.length);
return tmp;
}
@ -302,15 +318,16 @@ static LEX_STRING get_token(LEX *lex,uint length)
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;
const char *from, *end;
char *to;
yyUnget(); // ptr points now after last token char
tmp.length=lex->yytoklen=length;
tmp.str=(char*) lex->thd->alloc(tmp.length+1);
for (from= lex->tok_start, to= tmp.str, end= to+length ;
tmp.length= lip->yytoklen=length;
tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
for (from= lip->tok_start, to= tmp.str, end= to+length ;
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
*/
static char *get_text(LEX *lex)
static char *get_text(Lex_input_stream *lip)
{
reg1 uchar c,sep;
uint found_escape=0;
CHARSET_INFO *cs= lex->thd->charset();
CHARSET_INFO *cs= lip->m_thd->charset();
sep= yyGetLast(); // String should end with this
while (lex->ptr != lex->end_of_query)
while (lip->ptr != lip->end_of_query)
{
c = yyGet();
#ifdef USE_MB
{
int l;
if (use_mb(cs) &&
(l = my_ismbchar(cs, lex->ptr-1, lex->end_of_query))) {
lex->ptr += l-1;
(l = my_ismbchar(cs, lip->ptr-1, lip->end_of_query))) {
lip->ptr += l-1;
continue;
}
}
#endif
if (c == '\\' &&
!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
!(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
{ // Escaped character
found_escape=1;
if (lex->ptr == lex->end_of_query)
if (lip->ptr == lip->end_of_query)
return 0;
yySkip();
}
@ -369,15 +386,15 @@ static char *get_text(LEX *lex)
const char *str, *end;
char *start;
str=lex->tok_start+1;
end=lex->ptr-1;
if (!(start= (char*) lex->thd->alloc((uint) (end-str)+1)))
str=lip->tok_start+1;
end=lip->ptr-1;
if (!(start= (char*) lip->m_thd->alloc((uint) (end-str)+1)))
return (char*) ""; // Sql_alloc has set error flag
if (!found_escape)
{
lex->yytoklen=(uint) (end-str);
memcpy(start,str,lex->yytoklen);
start[lex->yytoklen]=0;
lip->yytoklen=(uint) (end-str);
memcpy(start,str,lip->yytoklen);
start[lip->yytoklen]=0;
}
else
{
@ -395,7 +412,7 @@ static char *get_text(LEX *lex)
continue;
}
#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)
{
switch(*++str) {
@ -432,7 +449,7 @@ static char *get_text(LEX *lex)
*to++ = *str;
}
*to=0;
lex->yytoklen=(uint) (to-start);
lip->yytoklen=(uint) (to-start);
}
return start;
}
@ -545,19 +562,21 @@ int MYSQLlex(void *arg, void *yythd)
int tokval, result_state;
uint length;
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;
CHARSET_INFO *cs= ((THD *) yythd)->charset();
CHARSET_INFO *cs= thd->charset();
uchar *state_map= cs->state_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;
state=lex->next_state;
lex->next_state=MY_LEX_OPERATOR_OR_IDENT;
lip->tok_start=lip->tok_end=lip->ptr;
state=lip->next_state;
lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
LINT_INIT(c);
for (;;)
{
@ -568,9 +587,9 @@ int MYSQLlex(void *arg, void *yythd)
for (c=yyGet() ; (state_map[c] == MY_LEX_SKIP) ; c= yyGet())
{
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];
break;
case MY_LEX_ESCAPE:
@ -589,13 +608,13 @@ int MYSQLlex(void *arg, void *yythd)
state=MY_LEX_COMMENT;
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;
c=yyGet();
if (c != ')')
lex->next_state= MY_LEX_START; // Allow signed numbers
lip->next_state= MY_LEX_START; // Allow signed numbers
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
because of binlogging: when a placeholder is replaced with
@ -613,14 +632,14 @@ int MYSQLlex(void *arg, void *yythd)
break;
}
/* Found N'string' */
lex->tok_start++; // Skip N
lip->tok_start++; // Skip N
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
break;
}
yylval->lex_str.length= lex->yytoklen;
yylval->lex_str.length= lip->yytoklen;
return(NCHAR_STRING);
case MY_LEX_IDENT_OR_HEX:
@ -643,21 +662,21 @@ int MYSQLlex(void *arg, void *yythd)
result_state= IDENT_QUOTED;
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) {
state = MY_LEX_CHAR;
continue;
}
lex->ptr += l - 1;
lip->ptr += l - 1;
}
while (ident_map[c=yyGet()])
{
if (my_mbcharlen(cs, c) > 1)
{
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;
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 */
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
}
length= (uint) (lex->ptr - lex->tok_start)-1;
start= lex->ptr;
if (lex->ignore_space)
length= (uint) (lip->ptr - lip->tok_start)-1;
start= lip->ptr;
if (lip->ignore_space)
{
/*
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());
}
if (start == lex->ptr && c == '.' && ident_map[yyPeek()])
lex->next_state=MY_LEX_IDENT_SEP;
if (start == lip->ptr && c == '.' && ident_map[yyPeek()])
lip->next_state=MY_LEX_IDENT_SEP;
else
{ // '(' must follow directly if function
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
}
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'"
@ -707,12 +726,12 @@ int MYSQLlex(void *arg, void *yythd)
return(result_state); // IDENT or IDENT_QUOTED
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;
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 "
lex->next_state= MY_LEX_START;
lip->next_state= MY_LEX_START;
return((int) c);
case MY_LEX_NUMBER_IDENT: // number or ident which num-start
@ -732,36 +751,36 @@ int MYSQLlex(void *arg, void *yythd)
{
yySkip();
while (my_isdigit(cs,yyGet())) ;
yylval->lex_str=get_token(lex,yyLength());
yylval->lex_str=get_token(lip, yyLength());
return(FLOAT_NUM);
}
}
yyUnget(); /* purecov: inspected */
}
else if (c == 'x' && (lex->ptr - lex->tok_start) == 2 &&
lex->tok_start[0] == '0' )
else if (c == 'x' && (lip->ptr - lip->tok_start) == 2 &&
lip->tok_start[0] == '0' )
{ // Varbinary
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.length-=2;
lex->yytoklen-=2;
lip->yytoklen-=2;
return (HEX_NUM);
}
yyUnget();
}
else if (c == 'b' && (lex->ptr - lex->tok_start) == 2 &&
lex->tok_start[0] == '0' )
else if (c == 'b' && (lip->ptr - lip->tok_start) == 2 &&
lip->tok_start[0] == '0' )
{ // b'bin-number'
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.length-= 2;
lex->yytoklen-= 2;
lip->yytoklen-= 2;
return (BIN_NUM);
}
yyUnget();
@ -778,9 +797,9 @@ int MYSQLlex(void *arg, void *yythd)
if (my_mbcharlen(cs, c) > 1)
{
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;
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;
}
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);
case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char
{
uint double_quotes= 0;
char quote_char= c; // Used char
lex->tok_start=lex->ptr; // Skip first `
lip->tok_start=lip->ptr; // Skip first `
while ((c=yyGet()))
{
int var_length;
@ -819,23 +838,23 @@ int MYSQLlex(void *arg, void *yythd)
#ifdef USE_MB
else if (var_length < 1)
break; // Error
lex->ptr+= var_length-1;
lip->ptr+= var_length-1;
#endif
}
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);
else
yylval->lex_str=get_token(lex,yyLength());
yylval->lex_str=get_token(lip, yyLength());
if (c == quote_char)
yySkip(); // Skip end `
lex->next_state= MY_LEX_START;
lip->next_state= MY_LEX_START;
return(IDENT_QUOTED);
}
case MY_LEX_INT_OR_REAL: // Compleat int or incompleat real
if (c != '.')
{ // 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);
}
// fall through
@ -853,47 +872,47 @@ int MYSQLlex(void *arg, void *yythd)
break;
}
while (my_isdigit(cs,yyGet())) ;
yylval->lex_str=get_token(lex,yyLength());
yylval->lex_str=get_token(lip, yyLength());
return(FLOAT_NUM);
}
yylval->lex_str=get_token(lex,yyLength());
yylval->lex_str=get_token(lip, yyLength());
return(DECIMAL_NUM);
case MY_LEX_HEX_NUMBER: // Found x'hexstring'
yyGet(); // Skip '
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 != '\'')
{
return(ABORT_SYM); // Illegal hex constant
}
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.length-=3; // Don't count x' and last '
lex->yytoklen-=3;
lip->yytoklen-=3;
return (HEX_NUM);
case MY_LEX_BIN_NUMBER: // Found b'bin-string'
yyGet(); // Skip '
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 != '\'')
return(ABORT_SYM); // Illegal hex constant
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.length-= 3; // Don't count b' and last '
lex->yytoklen-= 3;
lip->yytoklen-= 3;
return (BIN_NUM);
case MY_LEX_CMP_OP: // Incomplete comparison operator
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
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);
}
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)
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);
}
state = MY_LEX_CHAR; // Something fishy found
@ -922,24 +941,24 @@ int MYSQLlex(void *arg, void *yythd)
break;
}
yySkip();
tokval = find_keyword(lex,2,0); // Is a bool operator
lex->next_state= MY_LEX_START; // Allow signed numbers
tokval = find_keyword(lip,2,0); // Is a bool operator
lip->next_state= MY_LEX_START; // Allow signed numbers
return(tokval);
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;
break;
}
/* " used for strings */
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
break;
}
yylval->lex_str.length=lex->yytoklen;
yylval->lex_str.length=lip->yytoklen;
return(TEXT_STRING);
case MY_LEX_COMMENT: // Comment
@ -963,7 +982,7 @@ int MYSQLlex(void *arg, void *yythd)
state=MY_LEX_START;
if (my_isdigit(cs,yyPeek()))
{ // 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)
{
@ -971,13 +990,13 @@ int MYSQLlex(void *arg, void *yythd)
break;
}
}
while (lex->ptr != lex->end_of_query &&
while (lip->ptr != lip->end_of_query &&
((c=yyGet()) != '*' || yyPeek() != '/'))
{
if (c == '\n')
lex->yylineno++;
lip->yylineno++;
}
if (lex->ptr != lex->end_of_query)
if (lip->ptr != lip->end_of_query)
yySkip(); // remove last '/'
state = MY_LEX_START; // Try again
break;
@ -1002,14 +1021,13 @@ int MYSQLlex(void *arg, void *yythd)
case MY_LEX_SEMICOLON: // optional line terminator
if (yyPeek())
{
THD* thd= (THD*)yythd;
if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) &&
!lex->stmt_prepare_mode)
{
lex->safe_to_cache_query= 0;
lex->found_semicolon=(char*) lex->ptr;
lip->found_semicolon= lip->ptr;
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
lex->next_state= MY_LEX_END;
lip->next_state= MY_LEX_END;
return (END_OF_INPUT);
}
state= MY_LEX_CHAR; // Return ';'
@ -1017,15 +1035,15 @@ int MYSQLlex(void *arg, void *yythd)
}
/* fall true */
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);
}
state=MY_LEX_CHAR;
break;
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
/* 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:
break;
case MY_LEX_USER_END:
lex->next_state=MY_LEX_SYSTEM_VAR;
lip->next_state=MY_LEX_SYSTEM_VAR;
break;
default:
lex->next_state=MY_LEX_HOSTNAME;
lip->next_state=MY_LEX_HOSTNAME;
break;
}
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.str=(char*) lip->ptr;
yylval->lex_str.length=1;
return((int) '@');
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(lex,yyLength());
yylval->lex_str=get_token(lip, yyLength());
return(LEX_HOSTNAME);
case MY_LEX_SYSTEM_VAR:
yylval->lex_str.str=(char*) lex->ptr;
yylval->lex_str.str=(char*) lip->ptr;
yylval->lex_str.length=1;
yySkip(); // Skip '@'
lex->next_state= (state_map[yyPeek()] ==
lip->next_state= (state_map[yyPeek()] ==
MY_LEX_USER_VARIABLE_DELIMITER ?
MY_LEX_OPERATOR_OR_IDENT :
MY_LEX_IDENT_OR_KEYWORD);
@ -1081,16 +1099,16 @@ int MYSQLlex(void *arg, void *yythd)
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
if (c == '.')
lex->next_state=MY_LEX_IDENT_SEP;
length= (uint) (lex->ptr - lex->tok_start)-1;
lip->next_state=MY_LEX_IDENT_SEP;
length= (uint) (lip->ptr - lip->tok_start)-1;
if (length == 0)
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'
return(tokval); // Was keyword
}
yylval->lex_str=get_token(lex,length);
yylval->lex_str=get_token(lip, length);
return(result_state);
}
}

View file

@ -543,7 +543,7 @@ public:
void set_thd(THD *thd_arg) { thd= thd_arg; }
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();
List<Item> *get_unit_column_types();
@ -744,7 +744,7 @@ public:
void cut_subtree() { slave= 0; }
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) {}
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 */
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 select_lex; /* first SELECT_LEX */
/* current SELECT_LEX in parsing */
SELECT_LEX *current_select;
/* list of all SELECT_LEX */
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;
LEX_STRING name;
@ -1017,7 +1061,6 @@ typedef struct st_lex : public Query_tables_list
char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */
char* x509_subject,*x509_issuer,*ssl_cipher;
char* found_semicolon; /* For multi queries - next query */
String *wild;
sql_exchange *exchange;
select_result *result;
@ -1101,7 +1144,6 @@ typedef struct st_lex : public Query_tables_list
thr_lock_type lock_option;
enum SSL_type ssl_type; /* defined in violite.h */
enum my_lex_states next_state;
enum enum_duplicates duplicates;
enum enum_tx_isolation tx_isolation;
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_check;
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;
/*
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
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
@ -1327,7 +1370,7 @@ struct st_lex_local: public st_lex
extern void lex_init(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 int MYSQLlex(void *arg, void *yythd);
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;
FILE *file=bootstrap_file;
char *buff;
const char* found_semicolon= NULL;
/* The following must be called before DBUG_ENTER */
thd->thread_stack= (char*) &thd;
@ -375,7 +376,7 @@ pthread_handler_t handle_bootstrap(void *arg)
*/
thd->query_id=next_query_id();
thd->set_time();
mysql_parse(thd,thd->query,length);
mysql_parse(thd, thd->query, length, & found_semicolon);
close_thread_tables(thd); // Free tables
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;
/* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
const char *format= "%.*b";
const char* found_semicolon= NULL;
general_log_print(thd, command, format, thd->query_length, thd->query);
DBUG_PRINT("query",("%-.4096s",thd->query));
if (!(specialflag & SPECIAL_NO_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;
/*
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. */
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
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))
@ -946,7 +949,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
uint dummy;
/* used as fields initializator */
lex_start(thd, 0, 0);
lex_start(thd);
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
&LOCK_status);
@ -985,7 +988,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
/* init structures for VIEW processing */
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->
select_lex.table_list.link_in_list((byte*) &table_list,
(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.
@ -5263,22 +5255,55 @@ void mysql_init_multi_delete(LEX *lex)
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_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;
sp_cache_flush_obsolete(&thd->sp_proc_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
if (mqh_used && thd->user_connect &&
@ -5301,8 +5326,8 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
PROCESSLIST.
Note that we don't need LOCK_thread_count to modify query_length.
*/
if (lex->found_semicolon &&
(thd->query_length= (ulong)(lex->found_semicolon - thd->query)))
if (lip.found_semicolon &&
(thd->query_length= (ulong)(lip.found_semicolon - thd->query)))
thd->query_length--;
/* Actually execute the query */
mysql_execute_command(thd);
@ -5329,6 +5354,12 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
thd->cleanup_after_query();
DBUG_ASSERT(thd->change_list.is_empty());
}
else
{
/* There are no multi queries in the cache. */
*found_semicolon= NULL;
}
DBUG_VOID_RETURN;
}
@ -5349,8 +5380,13 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
bool error= 0;
DBUG_ENTER("mysql_test_parse_for_slave");
mysql_init_query(thd, inBuf, length);
if (!MYSQLparse((void*) thd) && ! thd->is_fatal_error &&
Lex_input_stream lip(thd, inBuf, length);
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))
error= 1; /* Ignore question */
thd->end_statement();
@ -6401,8 +6437,9 @@ bool check_simple_select()
if (lex->current_select != &lex->select_lex)
{
char command[80];
strmake(command, lex->yylval->symbol.str,
min(lex->yylval->symbol.length, sizeof(command)-1));
Lex_input_stream *lip= thd->m_lip;
strmake(command, lip->yylval->symbol.str,
min(lip->yylval->symbol.length, sizeof(command)-1));
my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
return 1;
}

View file

@ -3718,7 +3718,11 @@ bool mysql_unpack_partition(THD *thd,
thd->lex= &lex;
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
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;
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);
/*

View file

@ -976,10 +976,14 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
LEX_STRING *trg_definer= it_definer++;
thd->variables.sql_mode= (ulong)*trg_sql_mode;
lex_start(thd, trg_create_str->str, trg_create_str->length);
thd->spcont= 0;
if (MYSQLparse((void *)thd) || thd->is_fatal_error)
Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length);
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 */
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
*/
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;
/* switch off modes which can prevent normal parsing of VIEW
- 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)
{
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 */
my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
(yytext ? (char*) yytext : ""),
thd->lex->yylineno);
(yytext ? yytext : ""),
lip->yylineno);
}
/**
@ -1837,7 +1838,9 @@ opt_ev_comment: /* empty */ { $$= 0; }
ev_sql_stmt:
{
LEX *lex= Lex;
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
/*
This stops the following :
@ -1874,22 +1877,23 @@ ev_sql_stmt:
bzero((char *)&lex->sp_chistics, sizeof(st_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
{
LEX *lex=Lex;
THD *thd= YYTHD;
LEX *lex= thd->lex;
/* return back to the original memory root ASAP */
lex->sphead->init_strings(YYTHD, lex);
lex->sphead->restore_thd_mem_root(YYTHD);
lex->sphead->init_strings(thd, lex);
lex->sphead->restore_thd_mem_root(thd);
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;
/*
@ -2003,9 +2009,9 @@ create_function_tail:
}
/* Order is important here: new - reset - init */
sp= new sp_head();
sp->reset_thd_mem_root(YYTHD);
sp->reset_thd_mem_root(thd);
sp->init(lex);
sp->init_sp_name(YYTHD, lex->spname);
sp->init_sp_name(thd, lex->spname);
sp->m_type= TYPE_ENUM_FUNCTION;
lex->sphead= sp;
@ -2014,15 +2020,17 @@ create_function_tail:
stored procedure, otherwise yylex will chop it into pieces
at each ';'.
*/
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
lex->sphead->m_param_begin= lex->tok_start+1;
$<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES;
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
lex->sphead->m_param_begin= lip->tok_start+1;
}
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
{
@ -2057,10 +2065,12 @@ create_function_tail:
}
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_body_begin= lex->tok_start;
lex->sphead->m_body_begin= lip->tok_start;
}
sp_proc_stmt
{
@ -2666,14 +2676,18 @@ sp_proc_stmt_if:
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->m_tmp_query= lex->tok_start;
lex->sphead->reset_lex(thd);
lex->sphead->m_tmp_query= lip->tok_start;
}
statement
{
LEX *lex= Lex;
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
sp_head *sp= lex->sphead;
sp->m_flags|= sp_get_flags_for_command(lex);
@ -2700,15 +2714,15 @@ sp_proc_stmt_statement:
lex->tok_end otherwise.
*/
if (yychar == YYEMPTY)
i->m_query.length= lex->ptr - sp->m_tmp_query;
i->m_query.length= lip->ptr - sp->m_tmp_query;
else
i->m_query.length= lex->tok_end - sp->m_tmp_query;
i->m_query.str= strmake_root(YYTHD->mem_root,
i->m_query.length= lip->tok_end - sp->m_tmp_query;
i->m_query.str= strmake_root(thd->mem_root,
sp->m_tmp_query,
i->m_query.length);
sp->add_instr(i);
}
sp->restore_lex(YYTHD);
sp->restore_lex(thd);
}
;
@ -6212,10 +6226,18 @@ select_item:
};
remember_name:
{ $$=(char*) Lex->tok_start; };
{
THD *thd= YYTHD;
Lex_input_stream *lip= thd->m_lip;
$$= (char*) lip->tok_start;
};
remember_end:
{ $$=(char*) Lex->tok_end; };
{
THD *thd= YYTHD;
Lex_input_stream *lip= thd->m_lip;
$$=(char*) lip->tok_end;
};
select_item2:
table_wild { $$=$1; } /* table.* */
@ -7983,12 +8005,14 @@ procedure_list2:
procedure_item:
remember_name expr
{
LEX *lex= Lex;
if (add_proc_to_list(lex->thd, $2))
THD *thd= YYTHD;
Lex_input_stream *lip= thd->m_lip;
if (add_proc_to_list(thd, $2))
MYSQL_YYABORT;
if (!$2->name)
$2->set_name($1,(uint) ((char*) lex->tok_end - $1),
YYTHD->charset());
$2->set_name($1,(uint) ((char*) lip->tok_end - $1),
thd->charset());
}
;
@ -9078,13 +9102,16 @@ use: USE_SYM ident
load: LOAD DATA_SYM
{
LEX *lex=Lex;
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
if (lex->sphead)
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
MYSQL_YYABORT;
}
lex->fname_start= lex->ptr;
lex->fname_start= lip->ptr;
}
load_data
{}
@ -9118,8 +9145,10 @@ load_data:
}
opt_duplicate INTO
{
LEX *lex=Lex;
lex->fname_end= lex->ptr;
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
lex->fname_end= lip->ptr;
}
TABLE_SYM table_ident
{
@ -9300,14 +9329,15 @@ param_marker:
PARAM_MARKER
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
Item_param *item;
if (! lex->parsing_options.allows_variable)
{
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
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))
{
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
@ -9330,8 +9360,11 @@ signed_literal:
literal:
text_literal { $$ = $1; }
| NUM_literal { $$ = $1; }
| NULL_SYM { $$ = new Item_null();
Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;}
| NULL_SYM
{
$$ = new Item_null();
YYTHD->m_lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
}
| FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); }
| TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); }
| HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);}
@ -9421,8 +9454,10 @@ order_ident:
simple_ident:
ident
{
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
sp_variable_t *spv;
LEX *lex = Lex;
sp_pcontext *spc = lex->spcont;
if (spc && (spv = spc->find_variable(&$1)))
{
@ -9435,7 +9470,7 @@ simple_ident:
Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, spv->type,
lex->tok_start_prev -
lip->tok_start_prev -
lex->sphead->m_tmp_query);
#ifndef DBUG_OFF
if (splocal)
@ -10085,7 +10120,11 @@ option_value_list:
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.
@ -10097,9 +10136,8 @@ option_type_value:
QQ: May be we should simply prohibit group assignments in SP?
*/
LEX *lex;
Lex->sphead->reset_lex(YYTHD);
lex= Lex;
lex->sphead->reset_lex(thd);
lex= thd->lex;
/* Set new LEX as if we at start of set rule. */
lex->sql_command= SQLCOM_SET_OPTION;
@ -10107,12 +10145,14 @@ option_type_value:
lex->option_type=OPT_SESSION;
lex->var_list.empty();
lex->one_shot_set= 0;
lex->sphead->m_tmp_query= lex->tok_start;
lex->sphead->m_tmp_query= lip->tok_start;
}
}
ext_option_value
{
LEX *lex= Lex;
THD *thd= YYTHD;
LEX *lex= thd->lex;
Lex_input_stream *lip= thd->m_lip;
if (lex->sphead)
{
@ -10134,15 +10174,15 @@ option_type_value:
/*
Extract the query statement from the tokenizer. The
end is either lex->ptr, if there was no lookahead,
lex->tok_end otherwise.
end is either lip->ptr, if there was no lookahead,
lip->tok_end otherwise.
*/
if (yychar == YYEMPTY)
qbuff.length= lex->ptr - sp->m_tmp_query;
qbuff.length= lip->ptr - sp->m_tmp_query;
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;
strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
@ -10151,7 +10191,7 @@ option_type_value:
i->m_query= qbuff;
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
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;
if (lex->sphead)
@ -11411,9 +11453,9 @@ trigger_tail:
if (!(sp= new sp_head()))
MYSQL_YYABORT;
sp->reset_thd_mem_root(YYTHD);
sp->reset_thd_mem_root(thd);
sp->init(lex);
sp->init_sp_name(YYTHD, $3);
sp->init_sp_name(thd, $3);
lex->stmt_definition_begin= $2;
lex->ident.str= $7;
lex->ident.length= $10 - $7;
@ -11426,12 +11468,12 @@ trigger_tail:
stored procedure, otherwise yylex will chop it into pieces
at each ';'.
*/
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
$<ulong_num>$= thd->client_capabilities & CLIENT_MULTI_QUERIES;
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
bzero((char *)&lex->sp_chistics, sizeof(st_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]))
++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
')'
{
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));
}
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_body_begin= lex->tok_start;
lex->sphead->m_body_begin= lip->tok_start;
}
sp_proc_stmt
{