manual merge 5.0-runtime -> 5.1->runtime, with 25411 part I
This commit is contained in:
parent
5e414cd222
commit
034c11f3cd
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
284
sql/sql_lex.cc
284
sql/sql_lex.cc
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
103
sql/sql_parse.cc
103
sql/sql_parse.cc
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
184
sql/sql_yacc.yy
184
sql/sql_yacc.yy
@ -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
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user