Merge malff@bk-internal.mysql.com:/home/bk/mysql-5.0-runtime
into weblab.(none):/home/marcsql/TREE/mysql-5.0-25411_d sql/item_func.cc: Auto merged sql/log_event.cc: Auto merged sql/mysql_priv.h: Auto merged sql/slave.cc: Auto merged sql/sp.cc: Auto merged sql/sp_head.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_lex.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/sql_view.cc: Auto merged
This commit is contained in:
commit
6f5cacfae8
@ -4274,7 +4274,7 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
|
|||||||
List<set_var_base> tmp_var_list;
|
List<set_var_base> tmp_var_list;
|
||||||
LEX *sav_lex= thd->lex, lex_tmp;
|
LEX *sav_lex= thd->lex, lex_tmp;
|
||||||
thd->lex= &lex_tmp;
|
thd->lex= &lex_tmp;
|
||||||
lex_start(thd, NULL, 0);
|
lex_start(thd);
|
||||||
tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
|
tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
|
||||||
new Item_null())));
|
new Item_null())));
|
||||||
/* Create the variable */
|
/* Create the variable */
|
||||||
|
@ -1879,7 +1879,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli,
|
|||||||
thd->variables.collation_database= thd->db_charset;
|
thd->variables.collation_database= thd->db_charset;
|
||||||
|
|
||||||
/* Execute the query (note that we bypass dispatch_command()) */
|
/* Execute the query (note that we bypass dispatch_command()) */
|
||||||
mysql_parse(thd, thd->query, thd->query_length);
|
const char* found_semicolon= NULL;
|
||||||
|
mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -2987,10 +2988,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
|||||||
thd->query_error= 0;
|
thd->query_error= 0;
|
||||||
clear_all_errors(thd, rli);
|
clear_all_errors(thd, rli);
|
||||||
/*
|
/*
|
||||||
Usually mysql_init_query() is called by mysql_parse(), but we need it here
|
Usually lex_start() is called by mysql_parse(), but we need it here
|
||||||
as the present method does not call mysql_parse().
|
as the present method does not call mysql_parse().
|
||||||
*/
|
*/
|
||||||
mysql_init_query(thd, 0, 0);
|
lex_start(thd);
|
||||||
|
mysql_reset_thd_for_next_command(thd);
|
||||||
|
|
||||||
if (!use_rli_only_for_errors)
|
if (!use_rli_only_for_errors)
|
||||||
{
|
{
|
||||||
/* Saved for InnoDB, see comment in Query_log_event::exec_event() */
|
/* Saved for InnoDB, see comment in Query_log_event::exec_event() */
|
||||||
|
@ -696,13 +696,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, uchar *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);
|
||||||
|
@ -1517,6 +1517,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
|
||||||
@ -1567,7 +1568,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
|
|||||||
save_db_length= thd->db_length;
|
save_db_length= thd->db_length;
|
||||||
DBUG_ASSERT(db != 0);
|
DBUG_ASSERT(db != 0);
|
||||||
thd->reset_db((char*)db, strlen(db));
|
thd->reset_db((char*)db, strlen(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;
|
||||||
|
@ -434,10 +434,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, (uchar*)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;
|
||||||
|
|
||||||
|
@ -519,9 +519,10 @@ void
|
|||||||
sp_head::init_strings(THD *thd, LEX *lex)
|
sp_head::init_strings(THD *thd, LEX *lex)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("sp_head::init_strings");
|
DBUG_ENTER("sp_head::init_strings");
|
||||||
uchar *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)
|
||||||
{
|
{
|
||||||
@ -531,17 +532,17 @@ 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.
|
||||||
*/
|
*/
|
||||||
endp= skip_rear_comments(m_body_begin, endp);
|
endp= skip_rear_comments((char*) m_body_begin, (char*) endp);
|
||||||
|
|
||||||
m_body.length= endp - m_body_begin;
|
m_body.length= endp - m_body_begin;
|
||||||
m_body.str= strmake_root(root, (char *)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, (char *)lex->buf, m_defstr.length);
|
m_defstr.str= strmake_root(root, lip->buf, m_defstr.length);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1756,24 +1757,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->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;
|
||||||
@ -1806,9 +1796,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->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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -125,7 +125,7 @@ public:
|
|||||||
|
|
||||||
create_field m_return_field_def; /* This is used for FUNCTIONs only. */
|
create_field m_return_field_def; /* This is used for FUNCTIONs only. */
|
||||||
|
|
||||||
uchar *m_tmp_query; // Temporary pointer to sub query string
|
const char *m_tmp_query; // Temporary pointer to sub query string
|
||||||
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
|
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
|
||||||
st_sp_chistics *m_chistics;
|
st_sp_chistics *m_chistics;
|
||||||
ulong m_sql_mode; // For SHOW CREATE and execution
|
ulong m_sql_mode; // For SHOW CREATE and execution
|
||||||
@ -174,7 +174,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
HASH m_sroutines;
|
HASH m_sroutines;
|
||||||
// Pointers set during parsing
|
// Pointers set during parsing
|
||||||
uchar *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
|
||||||
|
@ -176,7 +176,7 @@ THD::THD()
|
|||||||
rand_used(0), time_zone_used(0),
|
rand_used(0), time_zone_used(0),
|
||||||
last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0),
|
last_insert_id_used(0), last_insert_id_used_bin_log(0), insert_id_used(0),
|
||||||
clear_next_insert_id(0), in_lock_tables(0), bootstrap(0),
|
clear_next_insert_id(0), in_lock_tables(0), bootstrap(0),
|
||||||
derived_tables_processing(FALSE), spcont(NULL)
|
derived_tables_processing(FALSE), spcont(NULL), m_lip(NULL)
|
||||||
{
|
{
|
||||||
ulong tmp;
|
ulong tmp;
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ class Slave_log_event;
|
|||||||
class Format_description_log_event;
|
class Format_description_log_event;
|
||||||
class sp_rcontext;
|
class sp_rcontext;
|
||||||
class sp_cache;
|
class sp_cache;
|
||||||
|
class Lex_input_stream;
|
||||||
|
|
||||||
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
|
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
|
||||||
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
|
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
|
||||||
@ -1496,6 +1497,15 @@ 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;
|
||||||
|
|
||||||
THD();
|
THD();
|
||||||
~THD();
|
~THD();
|
||||||
|
|
||||||
|
299
sql/sql_lex.cc
299
sql/sql_lex.cc
@ -32,13 +32,13 @@ sys_var_long_ptr trg_new_row_fake_var(0, 0);
|
|||||||
|
|
||||||
/* Macros to look like lex */
|
/* Macros to look like lex */
|
||||||
|
|
||||||
#define yyGet() *(lex->ptr++)
|
#define yyGet() *(lip->ptr++)
|
||||||
#define yyGetLast() lex->ptr[-1]
|
#define yyGetLast() lip->ptr[-1]
|
||||||
#define yyPeek() lex->ptr[0]
|
#define yyPeek() lip->ptr[0]
|
||||||
#define yyPeek2() lex->ptr[1]
|
#define yyPeek2() 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
|
||||||
@ -108,6 +108,27 @@ 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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
@ -115,14 +136,12 @@ st_parsing_options::reset()
|
|||||||
(We already do too much here)
|
(We already do too much here)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void lex_start(THD *thd, uchar *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();
|
||||||
@ -155,15 +174,13 @@ void lex_start(THD *thd, uchar *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->time_zone_tables_used= 0;
|
lex->time_zone_tables_used= 0;
|
||||||
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->select_lex.in_sum_expr=0;
|
lex->select_lex.in_sum_expr=0;
|
||||||
@ -201,22 +218,22 @@ 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)
|
||||||
{
|
{
|
||||||
uchar *tok=lex->tok_start;
|
const char *tok= lip->tok_start;
|
||||||
|
|
||||||
SYMBOL *symbol = get_hash_symbol((const char *)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;
|
||||||
@ -245,12 +262,12 @@ bool is_keyword(const char *name, uint len)
|
|||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,14 +278,15 @@ 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;
|
||||||
byte *from, *to, *end;
|
byte *from, *to, *end;
|
||||||
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= (byte*) lex->tok_start, to= (byte*) tmp.str, end= to+length ;
|
for (from= (byte*) lip->tok_start, to= (byte*) tmp.str, end= to+length ;
|
||||||
to != end ;
|
to != end ;
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -285,15 +303,14 @@ 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
|
||||||
//lex->tok_start=lex->ptr-1; // Remember '
|
while (lip->ptr != lip->end_of_query)
|
||||||
while (lex->ptr != lex->end_of_query)
|
|
||||||
{
|
{
|
||||||
c = yyGet();
|
c = yyGet();
|
||||||
#ifdef USE_MB
|
#ifdef USE_MB
|
||||||
@ -301,18 +318,18 @@ static char *get_text(LEX *lex)
|
|||||||
int l;
|
int l;
|
||||||
if (use_mb(cs) &&
|
if (use_mb(cs) &&
|
||||||
(l = my_ismbchar(cs,
|
(l = my_ismbchar(cs,
|
||||||
(const char *)lex->ptr-1,
|
lip->ptr-1,
|
||||||
(const char *)lex->end_of_query))) {
|
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();
|
||||||
}
|
}
|
||||||
@ -327,21 +344,23 @@ static char *get_text(LEX *lex)
|
|||||||
yyUnget();
|
yyUnget();
|
||||||
|
|
||||||
/* Found end. Unescape and return string */
|
/* Found end. Unescape and return string */
|
||||||
uchar *str,*end,*start;
|
const char *str;
|
||||||
|
const char *end;
|
||||||
|
char *start;
|
||||||
|
|
||||||
str=lex->tok_start+1;
|
str=lip->tok_start+1;
|
||||||
end=lex->ptr-1;
|
end=lip->ptr-1;
|
||||||
if (!(start=(uchar*) 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
|
||||||
{
|
{
|
||||||
uchar *to;
|
char *to;
|
||||||
|
|
||||||
for (to=start ; str != end ; str++)
|
for (to=start ; str != end ; str++)
|
||||||
{
|
{
|
||||||
@ -356,7 +375,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) {
|
||||||
@ -393,7 +412,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 (char*) start;
|
return (char*) start;
|
||||||
}
|
}
|
||||||
@ -506,20 +525,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_end_prev= lex->tok_end;
|
lip->tok_start_prev= lip->tok_start;
|
||||||
lex->tok_start_prev= lex->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 (;;)
|
||||||
{
|
{
|
||||||
@ -530,9 +550,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:
|
||||||
@ -551,13 +571,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
|
||||||
@ -575,14 +595,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:
|
||||||
@ -598,7 +618,7 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MY_LEX_IDENT:
|
case MY_LEX_IDENT:
|
||||||
uchar *start;
|
const char *start;
|
||||||
#if defined(USE_MB) && defined(USE_MB_IDENT)
|
#if defined(USE_MB) && defined(USE_MB_IDENT)
|
||||||
if (use_mb(cs))
|
if (use_mb(cs))
|
||||||
{
|
{
|
||||||
@ -606,13 +626,13 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
if (my_mbcharlen(cs, yyGetLast()) > 1)
|
if (my_mbcharlen(cs, yyGetLast()) > 1)
|
||||||
{
|
{
|
||||||
int l = my_ismbchar(cs,
|
int l = my_ismbchar(cs,
|
||||||
(const char *)lex->ptr-1,
|
lip->ptr-1,
|
||||||
(const char *)lex->end_of_query);
|
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()])
|
||||||
{
|
{
|
||||||
@ -620,10 +640,10 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
if ((l = my_ismbchar(cs,
|
if ((l = my_ismbchar(cs,
|
||||||
(const char *)lex->ptr-1,
|
lip->ptr-1,
|
||||||
(const char *)lex->end_of_query)) == 0)
|
lip->end_of_query)) == 0)
|
||||||
break;
|
break;
|
||||||
lex->ptr += l-1;
|
lip->ptr += l-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -634,8 +654,8 @@ 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 (lex->ignore_space)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -644,19 +664,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'"
|
||||||
@ -673,12 +693,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
|
||||||
@ -698,36 +718,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();
|
||||||
@ -745,10 +765,10 @@ int MYSQLlex(void *arg, void *yythd)
|
|||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
if ((l = my_ismbchar(cs,
|
if ((l = my_ismbchar(cs,
|
||||||
(const char *)lex->ptr-1,
|
lip->ptr-1,
|
||||||
(const char *)lex->end_of_query)) == 0)
|
lip->end_of_query)) == 0)
|
||||||
break;
|
break;
|
||||||
lex->ptr += l-1;
|
lip->ptr += l-1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -760,16 +780,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;
|
||||||
@ -789,23 +809,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
|
||||||
@ -823,47 +843,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
|
||||||
@ -877,9 +897,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
|
||||||
@ -892,24 +912,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
|
||||||
@ -933,7 +953,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)
|
||||||
{
|
{
|
||||||
@ -941,13 +961,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;
|
||||||
@ -972,14 +992,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 ';'
|
||||||
@ -987,15 +1006,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 */
|
||||||
@ -1015,26 +1034,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);
|
||||||
@ -1051,16 +1070,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1093,7 +1112,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
|
|||||||
Pointer to the last non-comment symbol of the statement.
|
Pointer to the last non-comment symbol of the statement.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uchar *skip_rear_comments(uchar *begin, uchar *end)
|
char *skip_rear_comments(char *begin, char *end)
|
||||||
{
|
{
|
||||||
while (begin < end && (end[-1] <= ' ' || end[-1] == '*' ||
|
while (begin < end && (end[-1] <= ' ' || end[-1] == '*' ||
|
||||||
end[-1] == '/' || end[-1] == ';'))
|
end[-1] == '/' || end[-1] == ';'))
|
||||||
|
@ -470,7 +470,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, uchar *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();
|
||||||
@ -676,7 +676,7 @@ public:
|
|||||||
void cut_subtree() { slave= 0; }
|
void cut_subtree() { slave= 0; }
|
||||||
bool test_limit();
|
bool test_limit();
|
||||||
|
|
||||||
friend void lex_start(THD *thd, uchar *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()
|
||||||
{
|
{
|
||||||
@ -906,30 +906,70 @@ 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* 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;
|
||||||
uchar *buf; /* The beginning of string, used by SPs */
|
|
||||||
uchar *ptr,*tok_start,*tok_end,*end_of_query;
|
|
||||||
|
|
||||||
/* The values of tok_start/tok_end as they were one call of MYSQLlex before */
|
|
||||||
uchar *tok_start_prev, *tok_end_prev;
|
|
||||||
|
|
||||||
char *length,*dec,*change,*name;
|
char *length,*dec,*change,*name;
|
||||||
char *help_arg;
|
char *help_arg;
|
||||||
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;
|
||||||
@ -998,7 +1038,6 @@ typedef struct st_lex : public Query_tables_list
|
|||||||
enum_sql_command sql_command, orig_sql_command;
|
enum_sql_command sql_command, orig_sql_command;
|
||||||
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;
|
||||||
@ -1109,7 +1148,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).
|
||||||
*/
|
*/
|
||||||
uchar *fname_start, *fname_end;
|
const char *fname_start;
|
||||||
|
const char *fname_end;
|
||||||
|
|
||||||
bool escape_used;
|
bool escape_used;
|
||||||
|
|
||||||
@ -1219,7 +1259,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, uchar *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 uchar *skip_rear_comments(uchar *begin, uchar *end);
|
extern char *skip_rear_comments(char *begin, char *end);
|
||||||
|
@ -1238,6 +1238,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;
|
||||||
@ -1314,7 +1315,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)
|
||||||
@ -1793,17 +1794,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;
|
||||||
|
|
||||||
mysql_log.write(thd,command, format, thd->query_length, thd->query);
|
mysql_log.write(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
|
||||||
@ -1828,7 +1831,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))
|
||||||
@ -1849,7 +1852,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
LEX_STRING conv_name;
|
LEX_STRING conv_name;
|
||||||
|
|
||||||
/* 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);
|
||||||
@ -1886,7 +1889,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, (uchar*)"", 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);
|
||||||
@ -5774,20 +5780,6 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, ulong *yystacksize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************
|
|
||||||
Initialize global thd variables needed for query
|
|
||||||
****************************************************************************/
|
|
||||||
|
|
||||||
void
|
|
||||||
mysql_init_query(THD *thd, uchar *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.
|
||||||
|
|
||||||
@ -5974,21 +5966,54 @@ 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, (uchar*) inBuf, length);
|
/*
|
||||||
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
|
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 the thd and thd->lex structures, which happen to be implemented
|
||||||
|
by:
|
||||||
|
- 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_input_stream lip(thd, inBuf, length);
|
||||||
|
thd->m_lip= &lip;
|
||||||
|
lex_start(thd);
|
||||||
|
mysql_reset_thd_for_next_command(thd);
|
||||||
|
|
||||||
|
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)
|
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 &&
|
||||||
@ -6011,8 +6036,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);
|
||||||
@ -6039,6 +6064,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6059,8 +6090,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, (uchar*) 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();
|
||||||
@ -7119,8 +7155,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;
|
||||||
}
|
}
|
||||||
|
@ -2799,11 +2799,15 @@ 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, (uchar*) thd->query, thd->query_length);
|
|
||||||
|
Lex_input_stream lip(thd, thd->query, thd->query_length);
|
||||||
|
thd->m_lip= &lip;
|
||||||
|
lex_start(thd);
|
||||||
lex->safe_to_cache_query= FALSE;
|
lex->safe_to_cache_query= FALSE;
|
||||||
lex->stmt_prepare_mode= TRUE;
|
lex->stmt_prepare_mode= TRUE;
|
||||||
|
int err= MYSQLparse((void *)thd);
|
||||||
|
|
||||||
error= MYSQLparse((void *)thd) || thd->is_fatal_error ||
|
error= err || thd->is_fatal_error ||
|
||||||
thd->net.report_error || init_param_array(this);
|
thd->net.report_error || init_param_array(this);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -978,10 +978,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, (uchar*)trg_create_str->str, trg_create_str->length);
|
|
||||||
|
|
||||||
|
Lex_input_stream lip(thd, trg_create_str->str, trg_create_str->length);
|
||||||
|
thd->m_lip= &lip;
|
||||||
|
lex_start(thd);
|
||||||
thd->spcont= 0;
|
thd->spcont= 0;
|
||||||
if (MYSQLparse((void *)thd) || thd->is_fatal_error)
|
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);
|
||||||
|
@ -772,8 +772,8 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
|
|||||||
view->query.str= (char*)str.ptr();
|
view->query.str= (char*)str.ptr();
|
||||||
view->query.length= str.length()-1; // we do not need last \0
|
view->query.length= str.length()-1; // we do not need last \0
|
||||||
view->source.str= thd->query + thd->lex->create_view_select_start;
|
view->source.str= thd->query + thd->lex->create_view_select_start;
|
||||||
view->source.length= (char *)skip_rear_comments((uchar *)view->source.str,
|
view->source.length= (char *)skip_rear_comments((char *)view->source.str,
|
||||||
(uchar *)thd->query +
|
(char *)thd->query +
|
||||||
thd->query_length) -
|
thd->query_length) -
|
||||||
view->source.str;
|
view->source.str;
|
||||||
view->file_version= 1;
|
view->file_version= 1;
|
||||||
@ -984,10 +984,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, (uchar*)table->query.str, table->query.length);
|
|
||||||
|
{
|
||||||
|
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= &lex->select_lex;
|
||||||
view_select->select_number= ++thd->select_number;
|
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
|
||||||
|
171
sql/sql_yacc.yy
171
sql/sql_yacc.yy
@ -86,12 +86,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1619,7 +1620,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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1639,9 +1642,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;
|
||||||
@ -1650,15 +1653,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 ';'.
|
||||||
*/
|
*/
|
||||||
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
sp->m_old_cmq= 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
|
||||||
{
|
{
|
||||||
@ -1682,10 +1687,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
|
||||||
{
|
{
|
||||||
@ -2233,14 +2240,18 @@ sp_opt_default:
|
|||||||
|
|
||||||
sp_proc_stmt:
|
sp_proc_stmt:
|
||||||
{
|
{
|
||||||
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);
|
||||||
@ -2267,15 +2278,15 @@ sp_proc_stmt:
|
|||||||
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,
|
||||||
(char *)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);
|
||||||
}
|
}
|
||||||
| RETURN_SYM
|
| RETURN_SYM
|
||||||
{ Lex->sphead->reset_lex(YYTHD); }
|
{ Lex->sphead->reset_lex(YYTHD); }
|
||||||
@ -4444,10 +4455,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.* */
|
||||||
@ -6292,12 +6311,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());
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -7337,13 +7358,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
|
||||||
{}
|
{}
|
||||||
@ -7378,8 +7402,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
|
||||||
{
|
{
|
||||||
@ -7559,15 +7585,16 @@ text_string:
|
|||||||
param_marker:
|
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 - (uchar *) 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));
|
||||||
@ -7590,8 +7617,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);}
|
||||||
@ -7681,8 +7711,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)))
|
||||||
{
|
{
|
||||||
@ -7695,7 +7727,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)
|
||||||
@ -8291,7 +8323,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.
|
||||||
@ -8303,9 +8339,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;
|
||||||
@ -8313,12 +8348,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)
|
||||||
{
|
{
|
||||||
@ -8340,24 +8377,24 @@ 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), (char *)sp->m_tmp_query,
|
strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
|
||||||
qbuff.length);
|
qbuff.length);
|
||||||
qbuff.length+= 4;
|
qbuff.length+= 4;
|
||||||
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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -9615,7 +9652,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)
|
||||||
@ -9626,9 +9665,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;
|
||||||
@ -9642,12 +9681,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 ';'.
|
||||||
*/
|
*/
|
||||||
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
sp->m_old_cmq= 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;
|
||||||
}
|
}
|
||||||
@ -9726,24 +9765,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