mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
Merge weblab.(none):/home/marcsql/TREE/mysql-5.0-base
into weblab.(none):/home/marcsql/TREE/mysql-5.0-rt-merge mysql-test/t/sp.test: Auto merged sql/item.cc: Auto merged sql/item_func.cc: Auto merged sql/mysql_priv.h: Auto merged sql/sql_lex.cc: Auto merged sql/sql_parse.cc: Auto merged
This commit is contained in:
commit
03e7683565
19 changed files with 498 additions and 317 deletions
|
@ -6118,6 +6118,13 @@ Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
|||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
DROP FUNCTION bug5274_f1|
|
||||
DROP FUNCTION bug5274_f2|
|
||||
drop procedure if exists proc_21513|
|
||||
create procedure proc_21513()`my_label`:BEGIN END|
|
||||
show create procedure proc_21513|
|
||||
Procedure sql_mode Create Procedure
|
||||
proc_21513 CREATE DEFINER=`root`@`localhost` PROCEDURE `proc_21513`()
|
||||
`my_label`:BEGIN END
|
||||
drop procedure proc_21513|
|
||||
End of 5.0 tests.
|
||||
drop table t1,t2;
|
||||
CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
|
||||
|
|
|
@ -7054,6 +7054,17 @@ SELECT bug5274_f2()|
|
|||
DROP FUNCTION bug5274_f1|
|
||||
DROP FUNCTION bug5274_f2|
|
||||
|
||||
#
|
||||
# Bug#21513 (SP having body starting with quoted label rendered unusable)
|
||||
#
|
||||
--disable_warnings
|
||||
drop procedure if exists proc_21513|
|
||||
--enable_warnings
|
||||
|
||||
create procedure proc_21513()`my_label`:BEGIN END|
|
||||
show create procedure proc_21513|
|
||||
|
||||
drop procedure proc_21513|
|
||||
|
||||
###
|
||||
--echo End of 5.0 tests.
|
||||
|
|
|
@ -4621,7 +4621,6 @@ inline uint char_val(char X)
|
|||
|
||||
Item_hex_string::Item_hex_string(const char *str, uint str_length)
|
||||
{
|
||||
name=(char*) str-2; // Lex makes this start with 0x
|
||||
max_length=(str_length+1)/2;
|
||||
char *ptr=(char*) sql_alloc(max_length+1);
|
||||
if (!ptr)
|
||||
|
@ -4732,7 +4731,6 @@ Item_bin_string::Item_bin_string(const char *str, uint str_length)
|
|||
uchar bits= 0;
|
||||
uint power= 1;
|
||||
|
||||
name= (char*) str - 2;
|
||||
max_length= (str_length + 7) >> 3;
|
||||
char *ptr= (char*) sql_alloc(max_length + 1);
|
||||
if (!ptr)
|
||||
|
|
|
@ -4315,7 +4315,7 @@ int get_var_with_binlog(THD *thd, enum_sql_command sql_command,
|
|||
List<set_var_base> tmp_var_list;
|
||||
LEX *sav_lex= 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,
|
||||
new Item_null())));
|
||||
/* 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;
|
||||
|
||||
/* 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
|
||||
|
@ -2987,10 +2988,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
|
|||
thd->query_error= 0;
|
||||
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().
|
||||
*/
|
||||
mysql_init_query(thd, 0, 0);
|
||||
lex_start(thd);
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
|
||||
if (!use_rli_only_for_errors)
|
||||
{
|
||||
/* Saved for InnoDB, see comment in Query_log_event::exec_event() */
|
||||
|
|
|
@ -694,13 +694,15 @@ bool do_rename(THD *thd, TABLE_LIST *ren_table, char *new_db,
|
|||
bool skip_error);
|
||||
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name,
|
||||
bool force_switch);
|
||||
void mysql_parse(THD *thd,char *inBuf,uint length);
|
||||
|
||||
void mysql_parse(THD *thd, const char *inBuf, uint length,
|
||||
const char ** semicolon);
|
||||
|
||||
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
|
||||
bool is_update_query(enum enum_sql_command command);
|
||||
bool alloc_query(THD *thd, const char *packet, uint packet_length);
|
||||
void mysql_init_select(LEX *lex);
|
||||
void mysql_reset_thd_for_next_command(THD *thd);
|
||||
void mysql_init_query(THD *thd, uchar *buf, uint length);
|
||||
bool mysql_new_select(LEX *lex, bool move_down);
|
||||
void create_select_for_variable(const char *var_name);
|
||||
void mysql_init_multi_delete(LEX *lex);
|
||||
|
|
|
@ -1517,6 +1517,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
|
|||
handler *file;
|
||||
ulonglong save_options;
|
||||
NET *net= &mysql->net;
|
||||
const char *found_semicolon= NULL;
|
||||
DBUG_ENTER("create_table_from_dump");
|
||||
|
||||
packet_len= my_net_read(net); // read create table statement
|
||||
|
@ -1567,7 +1568,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
|
|||
save_db_length= thd->db_length;
|
||||
DBUG_ASSERT(db != 0);
|
||||
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_length= save_db_length;
|
||||
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)))
|
||||
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;
|
||||
if (MYSQLparse(thd) || thd->is_fatal_error || newlex.sphead == NULL)
|
||||
if (ret || thd->is_fatal_error || newlex.sphead == NULL)
|
||||
{
|
||||
sp_head *sp= newlex.sphead;
|
||||
|
||||
|
|
|
@ -519,9 +519,10 @@ void
|
|||
sp_head::init_strings(THD *thd, LEX *lex)
|
||||
{
|
||||
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 */
|
||||
MEM_ROOT *root= thd->mem_root;
|
||||
Lex_input_stream *lip=thd->m_lip;
|
||||
|
||||
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 */
|
||||
endp= (lex->ptr > lex->end_of_query ? lex->end_of_query : lex->ptr);
|
||||
endp= (lip->ptr > lip->end_of_query ? lip->end_of_query : lip->ptr);
|
||||
/*
|
||||
Trim "garbage" at the end. This is sometimes needed with the
|
||||
"/ * ! VERSION... * /" wrapper in dump files.
|
||||
*/
|
||||
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.str= strmake_root(root, (char *)m_body_begin, m_body.length);
|
||||
m_defstr.length= endp - lex->buf;
|
||||
m_defstr.str= strmake_root(root, (char *)lex->buf, m_defstr.length);
|
||||
m_body.str= strmake_root(root, m_body_begin, m_body.length);
|
||||
m_defstr.length= endp - lip->buf;
|
||||
m_defstr.str= strmake_root(root, lip->buf, m_defstr.length);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -1756,24 +1757,13 @@ sp_head::reset_lex(THD *thd)
|
|||
DBUG_ENTER("sp_head::reset_lex");
|
||||
LEX *sublex;
|
||||
LEX *oldlex= thd->lex;
|
||||
my_lex_states org_next_state= oldlex->next_state;
|
||||
|
||||
(void)m_lex.push_front(oldlex);
|
||||
thd->lex= sublex= new st_lex;
|
||||
|
||||
/* Reset most stuff. The length arguments doesn't matter here. */
|
||||
lex_start(thd, oldlex->buf, (ulong) (oldlex->end_of_query - oldlex->ptr));
|
||||
/* Reset most stuff. */
|
||||
lex_start(thd);
|
||||
|
||||
/*
|
||||
next_state is normally the same (0), but it happens that we swap lex in
|
||||
"mid-sentence", so we must restore it.
|
||||
*/
|
||||
sublex->next_state= org_next_state;
|
||||
/* We must reset ptr and end_of_query again */
|
||||
sublex->ptr= oldlex->ptr;
|
||||
sublex->end_of_query= oldlex->end_of_query;
|
||||
sublex->tok_start= oldlex->tok_start;
|
||||
sublex->yylineno= oldlex->yylineno;
|
||||
/* And keep the SP stuff too */
|
||||
sublex->sphead= oldlex->sphead;
|
||||
sublex->spcont= oldlex->spcont;
|
||||
|
@ -1806,9 +1796,6 @@ sp_head::restore_lex(THD *thd)
|
|||
if (! oldlex)
|
||||
return; // Nothing to restore
|
||||
|
||||
// Update some state in the old one first
|
||||
oldlex->ptr= sublex->ptr;
|
||||
oldlex->next_state= sublex->next_state;
|
||||
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. */
|
||||
|
||||
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
|
||||
st_sp_chistics *m_chistics;
|
||||
ulong m_sql_mode; // For SHOW CREATE and execution
|
||||
|
@ -174,7 +174,9 @@ public:
|
|||
*/
|
||||
HASH m_sroutines;
|
||||
// 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
|
||||
|
|
|
@ -176,7 +176,7 @@ THD::THD()
|
|||
rand_used(0), time_zone_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),
|
||||
derived_tables_processing(FALSE), spcont(NULL)
|
||||
derived_tables_processing(FALSE), spcont(NULL), m_lip(NULL)
|
||||
{
|
||||
ulong tmp;
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ class Slave_log_event;
|
|||
class Format_description_log_event;
|
||||
class sp_rcontext;
|
||||
class sp_cache;
|
||||
class Lex_input_stream;
|
||||
|
||||
enum enum_enable_or_disable { LEAVE_AS_IS, ENABLE, DISABLE };
|
||||
enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME };
|
||||
|
@ -1496,6 +1497,15 @@ public:
|
|||
query_id_t first_query_id;
|
||||
} binlog_evt_union;
|
||||
|
||||
/**
|
||||
Character input stream consumed by the lexical analyser,
|
||||
used during parsing.
|
||||
Note that since the parser is not re-entrant, we keep only one input
|
||||
stream here. This member is valid only when executing code during parsing,
|
||||
and may point to invalid memory after that.
|
||||
*/
|
||||
Lex_input_stream *m_lip;
|
||||
|
||||
THD();
|
||||
~THD();
|
||||
|
||||
|
|
323
sql/sql_lex.cc
323
sql/sql_lex.cc
|
@ -32,13 +32,13 @@ sys_var_long_ptr trg_new_row_fake_var(0, 0);
|
|||
|
||||
/* Macros to look like lex */
|
||||
|
||||
#define yyGet() *(lex->ptr++)
|
||||
#define yyGetLast() lex->ptr[-1]
|
||||
#define yyPeek() lex->ptr[0]
|
||||
#define yyPeek2() lex->ptr[1]
|
||||
#define yyUnget() lex->ptr--
|
||||
#define yySkip() lex->ptr++
|
||||
#define yyLength() ((uint) (lex->ptr - lex->tok_start)-1)
|
||||
#define yyGet() *(lip->ptr++)
|
||||
#define yyGetLast() lip->ptr[-1]
|
||||
#define yyPeek() lip->ptr[0]
|
||||
#define yyPeek2() lip->ptr[1]
|
||||
#define yyUnget() lip->ptr--
|
||||
#define yySkip() lip->ptr++
|
||||
#define yyLength() ((uint) (lip->ptr - lip->tok_start)-1)
|
||||
|
||||
/* Longest standard keyword name */
|
||||
#define TOCK_NAME_LENGTH 24
|
||||
|
@ -108,6 +108,28 @@ st_parsing_options::reset()
|
|||
allows_derived= TRUE;
|
||||
}
|
||||
|
||||
Lex_input_stream::Lex_input_stream(THD *thd,
|
||||
const char* buffer,
|
||||
unsigned int length)
|
||||
: m_thd(thd),
|
||||
yylineno(1),
|
||||
yytoklen(0),
|
||||
yylval(NULL),
|
||||
ptr(buffer),
|
||||
tok_start(NULL),
|
||||
tok_end(NULL),
|
||||
end_of_query(buffer + length),
|
||||
tok_start_prev(NULL),
|
||||
buf(buffer),
|
||||
next_state(MY_LEX_START),
|
||||
found_semicolon(NULL),
|
||||
ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE))
|
||||
{
|
||||
}
|
||||
|
||||
Lex_input_stream::~Lex_input_stream()
|
||||
{}
|
||||
|
||||
|
||||
/*
|
||||
This is called before every query that is to be parsed.
|
||||
|
@ -115,14 +137,12 @@ st_parsing_options::reset()
|
|||
(We already do too much here)
|
||||
*/
|
||||
|
||||
void lex_start(THD *thd, uchar *buf,uint length)
|
||||
void lex_start(THD *thd)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
DBUG_ENTER("lex_start");
|
||||
|
||||
lex->thd= lex->unit.thd= thd;
|
||||
lex->buf= lex->ptr= buf;
|
||||
lex->end_of_query= buf+length;
|
||||
|
||||
lex->context_stack.empty();
|
||||
lex->unit.init_query();
|
||||
|
@ -155,15 +175,13 @@ void lex_start(THD *thd, uchar *buf,uint length)
|
|||
lex->stmt_prepare_mode= FALSE;
|
||||
lex->derived_tables= 0;
|
||||
lex->lock_option= TL_READ;
|
||||
lex->found_semicolon= 0;
|
||||
lex->safe_to_cache_query= 1;
|
||||
lex->time_zone_tables_used= 0;
|
||||
lex->leaf_tables_insert= 0;
|
||||
lex->parsing_options.reset();
|
||||
lex->empty_field_list_on_rset= 0;
|
||||
lex->select_lex.select_number= 1;
|
||||
lex->next_state=MY_LEX_START;
|
||||
lex->yylineno = 1;
|
||||
|
||||
lex->in_comment=0;
|
||||
lex->length=0;
|
||||
lex->select_lex.in_sum_expr=0;
|
||||
|
@ -175,7 +193,6 @@ void lex_start(THD *thd, uchar *buf,uint length)
|
|||
lex->select_lex.udf_list.empty();
|
||||
lex->current_select= &lex->select_lex;
|
||||
lex->yacc_yyss=lex->yacc_yyvs=0;
|
||||
lex->ignore_space=test(thd->variables.sql_mode & MODE_IGNORE_SPACE);
|
||||
lex->sql_command= lex->orig_sql_command= SQLCOM_END;
|
||||
lex->duplicates= DUP_ERROR;
|
||||
lex->ignore= 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)
|
||||
{
|
||||
lex->yylval->symbol.symbol=symbol;
|
||||
lex->yylval->symbol.str= (char*) tok;
|
||||
lex->yylval->symbol.length=len;
|
||||
lip->yylval->symbol.symbol=symbol;
|
||||
lip->yylval->symbol.str= (char*) tok;
|
||||
lip->yylval->symbol.length=len;
|
||||
|
||||
if ((symbol->tok == NOT_SYM) &&
|
||||
(lex->thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
|
||||
(lip->m_thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
|
||||
return NOT2_SYM;
|
||||
if ((symbol->tok == OR_OR_SYM) &&
|
||||
!(lex->thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
|
||||
!(lip->m_thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
|
||||
return OR2_SYM;
|
||||
|
||||
return symbol->tok;
|
||||
|
@ -245,12 +262,12 @@ bool is_keyword(const char *name, uint len)
|
|||
|
||||
/* 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 skip, uint length)
|
||||
{
|
||||
LEX_STRING tmp;
|
||||
yyUnget(); // ptr points now after last token char
|
||||
tmp.length=lex->yytoklen=length;
|
||||
tmp.str=(char*) lex->thd->strmake((char*) lex->tok_start,tmp.length);
|
||||
tmp.length=lip->yytoklen=length;
|
||||
tmp.str= lip->m_thd->strmake(lip->tok_start + skip, tmp.length);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
@ -261,16 +278,19 @@ static LEX_STRING get_token(LEX *lex,uint length)
|
|||
future to operate multichar strings (like ucs2)
|
||||
*/
|
||||
|
||||
static LEX_STRING get_quoted_token(LEX *lex,uint length, char quote)
|
||||
static LEX_STRING get_quoted_token(Lex_input_stream *lip,
|
||||
uint skip,
|
||||
uint length, char quote)
|
||||
{
|
||||
LEX_STRING tmp;
|
||||
byte *from, *to, *end;
|
||||
yyUnget(); // ptr points now after last token char
|
||||
tmp.length=lex->yytoklen=length;
|
||||
tmp.str=(char*) lex->thd->alloc(tmp.length+1);
|
||||
for (from= (byte*) lex->tok_start, to= (byte*) tmp.str, end= to+length ;
|
||||
to != end ;
|
||||
)
|
||||
tmp.length=lip->yytoklen=length;
|
||||
tmp.str=(char*) lip->m_thd->alloc(tmp.length+1);
|
||||
from= (byte*) lip->tok_start + skip;
|
||||
to= (byte*) tmp.str;
|
||||
end= to+length;
|
||||
for ( ; to != end; )
|
||||
{
|
||||
if ((*to++= *from++) == quote)
|
||||
from++; // Skip double quotes
|
||||
|
@ -285,15 +305,14 @@ static LEX_STRING get_quoted_token(LEX *lex,uint length, char quote)
|
|||
Fix sometimes to do only one scan of the string
|
||||
*/
|
||||
|
||||
static char *get_text(LEX *lex)
|
||||
static char *get_text(Lex_input_stream *lip)
|
||||
{
|
||||
reg1 uchar c,sep;
|
||||
uint found_escape=0;
|
||||
CHARSET_INFO *cs= lex->thd->charset();
|
||||
CHARSET_INFO *cs= lip->m_thd->charset();
|
||||
|
||||
sep= yyGetLast(); // String should end with this
|
||||
//lex->tok_start=lex->ptr-1; // Remember '
|
||||
while (lex->ptr != lex->end_of_query)
|
||||
while (lip->ptr != lip->end_of_query)
|
||||
{
|
||||
c = yyGet();
|
||||
#ifdef USE_MB
|
||||
|
@ -301,18 +320,18 @@ static char *get_text(LEX *lex)
|
|||
int l;
|
||||
if (use_mb(cs) &&
|
||||
(l = my_ismbchar(cs,
|
||||
(const char *)lex->ptr-1,
|
||||
(const char *)lex->end_of_query))) {
|
||||
lex->ptr += l-1;
|
||||
lip->ptr-1,
|
||||
lip->end_of_query))) {
|
||||
lip->ptr += l-1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (c == '\\' &&
|
||||
!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
|
||||
!(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
|
||||
{ // Escaped character
|
||||
found_escape=1;
|
||||
if (lex->ptr == lex->end_of_query)
|
||||
if (lip->ptr == lip->end_of_query)
|
||||
return 0;
|
||||
yySkip();
|
||||
}
|
||||
|
@ -327,21 +346,23 @@ static char *get_text(LEX *lex)
|
|||
yyUnget();
|
||||
|
||||
/* Found end. Unescape and return string */
|
||||
uchar *str,*end,*start;
|
||||
const char *str;
|
||||
const char *end;
|
||||
char *start;
|
||||
|
||||
str=lex->tok_start+1;
|
||||
end=lex->ptr-1;
|
||||
if (!(start=(uchar*) lex->thd->alloc((uint) (end-str)+1)))
|
||||
str=lip->tok_start+1;
|
||||
end=lip->ptr-1;
|
||||
if (!(start=(char*) lip->m_thd->alloc((uint) (end-str)+1)))
|
||||
return (char*) ""; // Sql_alloc has set error flag
|
||||
if (!found_escape)
|
||||
{
|
||||
lex->yytoklen=(uint) (end-str);
|
||||
memcpy(start,str,lex->yytoklen);
|
||||
start[lex->yytoklen]=0;
|
||||
lip->yytoklen=(uint) (end-str);
|
||||
memcpy(start,str,lip->yytoklen);
|
||||
start[lip->yytoklen]=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uchar *to;
|
||||
char *to;
|
||||
|
||||
for (to=start ; str != end ; str++)
|
||||
{
|
||||
|
@ -356,7 +377,7 @@ static char *get_text(LEX *lex)
|
|||
continue;
|
||||
}
|
||||
#endif
|
||||
if (!(lex->thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
|
||||
if (!(lip->m_thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES) &&
|
||||
*str == '\\' && str+1 != end)
|
||||
{
|
||||
switch(*++str) {
|
||||
|
@ -393,7 +414,7 @@ static char *get_text(LEX *lex)
|
|||
*to++ = *str;
|
||||
}
|
||||
*to=0;
|
||||
lex->yytoklen=(uint) (to-start);
|
||||
lip->yytoklen=(uint) (to-start);
|
||||
}
|
||||
return (char*) start;
|
||||
}
|
||||
|
@ -506,20 +527,21 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
int tokval, result_state;
|
||||
uint length;
|
||||
enum my_lex_states state;
|
||||
LEX *lex= ((THD *)yythd)->lex;
|
||||
THD *thd= (THD *)yythd;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
LEX *lex= thd->lex;
|
||||
YYSTYPE *yylval=(YYSTYPE*) arg;
|
||||
CHARSET_INFO *cs= ((THD *) yythd)->charset();
|
||||
CHARSET_INFO *cs= thd->charset();
|
||||
uchar *state_map= cs->state_map;
|
||||
uchar *ident_map= cs->ident_map;
|
||||
|
||||
lex->yylval=yylval; // The global state
|
||||
lip->yylval=yylval; // The global state
|
||||
|
||||
lex->tok_end_prev= lex->tok_end;
|
||||
lex->tok_start_prev= lex->tok_start;
|
||||
lip->tok_start_prev= lip->tok_start;
|
||||
|
||||
lex->tok_start=lex->tok_end=lex->ptr;
|
||||
state=lex->next_state;
|
||||
lex->next_state=MY_LEX_OPERATOR_OR_IDENT;
|
||||
lip->tok_start=lip->tok_end=lip->ptr;
|
||||
state=lip->next_state;
|
||||
lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
|
||||
LINT_INIT(c);
|
||||
for (;;)
|
||||
{
|
||||
|
@ -530,9 +552,9 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
for (c=yyGet() ; (state_map[c] == MY_LEX_SKIP) ; c= yyGet())
|
||||
{
|
||||
if (c == '\n')
|
||||
lex->yylineno++;
|
||||
lip->yylineno++;
|
||||
}
|
||||
lex->tok_start=lex->ptr-1; // Start of real token
|
||||
lip->tok_start=lip->ptr-1; // Start of real token
|
||||
state= (enum my_lex_states) state_map[c];
|
||||
break;
|
||||
case MY_LEX_ESCAPE:
|
||||
|
@ -551,13 +573,13 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
state=MY_LEX_COMMENT;
|
||||
break;
|
||||
}
|
||||
yylval->lex_str.str=(char*) (lex->ptr=lex->tok_start);// Set to first chr
|
||||
yylval->lex_str.str=(char*) (lip->ptr=lip->tok_start);// Set to first chr
|
||||
yylval->lex_str.length=1;
|
||||
c=yyGet();
|
||||
if (c != ')')
|
||||
lex->next_state= MY_LEX_START; // Allow signed numbers
|
||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||
if (c == ',')
|
||||
lex->tok_start=lex->ptr; // Let tok_start point at next item
|
||||
lip->tok_start=lip->ptr; // Let tok_start point at next item
|
||||
/*
|
||||
Check for a placeholder: it should not precede a possible identifier
|
||||
because of binlogging: when a placeholder is replaced with
|
||||
|
@ -575,14 +597,14 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
break;
|
||||
}
|
||||
/* Found N'string' */
|
||||
lex->tok_start++; // Skip N
|
||||
lip->tok_start++; // Skip N
|
||||
yySkip(); // Skip '
|
||||
if (!(yylval->lex_str.str = get_text(lex)))
|
||||
if (!(yylval->lex_str.str = get_text(lip)))
|
||||
{
|
||||
state= MY_LEX_CHAR; // Read char by char
|
||||
break;
|
||||
}
|
||||
yylval->lex_str.length= lex->yytoklen;
|
||||
yylval->lex_str.length= lip->yytoklen;
|
||||
return(NCHAR_STRING);
|
||||
|
||||
case MY_LEX_IDENT_OR_HEX:
|
||||
|
@ -598,7 +620,7 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
break;
|
||||
}
|
||||
case MY_LEX_IDENT:
|
||||
uchar *start;
|
||||
const char *start;
|
||||
#if defined(USE_MB) && defined(USE_MB_IDENT)
|
||||
if (use_mb(cs))
|
||||
{
|
||||
|
@ -606,13 +628,13 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
if (my_mbcharlen(cs, yyGetLast()) > 1)
|
||||
{
|
||||
int l = my_ismbchar(cs,
|
||||
(const char *)lex->ptr-1,
|
||||
(const char *)lex->end_of_query);
|
||||
lip->ptr-1,
|
||||
lip->end_of_query);
|
||||
if (l == 0) {
|
||||
state = MY_LEX_CHAR;
|
||||
continue;
|
||||
}
|
||||
lex->ptr += l - 1;
|
||||
lip->ptr += l - 1;
|
||||
}
|
||||
while (ident_map[c=yyGet()])
|
||||
{
|
||||
|
@ -620,10 +642,10 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
{
|
||||
int l;
|
||||
if ((l = my_ismbchar(cs,
|
||||
(const char *)lex->ptr-1,
|
||||
(const char *)lex->end_of_query)) == 0)
|
||||
lip->ptr-1,
|
||||
lip->end_of_query)) == 0)
|
||||
break;
|
||||
lex->ptr += l-1;
|
||||
lip->ptr += l-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -634,9 +656,9 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
/* If there were non-ASCII characters, mark that we must convert */
|
||||
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
||||
}
|
||||
length= (uint) (lex->ptr - lex->tok_start)-1;
|
||||
start= lex->ptr;
|
||||
if (lex->ignore_space)
|
||||
length= (uint) (lip->ptr - lip->tok_start)-1;
|
||||
start= lip->ptr;
|
||||
if (lip->ignore_space)
|
||||
{
|
||||
/*
|
||||
If we find a space then this can't be an identifier. We notice this
|
||||
|
@ -644,19 +666,19 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
*/
|
||||
for (; state_map[c] == MY_LEX_SKIP ; c= yyGet());
|
||||
}
|
||||
if (start == lex->ptr && c == '.' && ident_map[yyPeek()])
|
||||
lex->next_state=MY_LEX_IDENT_SEP;
|
||||
if (start == lip->ptr && c == '.' && ident_map[yyPeek()])
|
||||
lip->next_state=MY_LEX_IDENT_SEP;
|
||||
else
|
||||
{ // '(' must follow directly if function
|
||||
yyUnget();
|
||||
if ((tokval = find_keyword(lex,length,c == '(')))
|
||||
if ((tokval = find_keyword(lip, length, c == '(')))
|
||||
{
|
||||
lex->next_state= MY_LEX_START; // Allow signed numbers
|
||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||
return(tokval); // Was keyword
|
||||
}
|
||||
yySkip(); // next state does a unget
|
||||
}
|
||||
yylval->lex_str=get_token(lex,length);
|
||||
yylval->lex_str=get_token(lip, 0, length);
|
||||
|
||||
/*
|
||||
Note: "SELECT _bla AS 'alias'"
|
||||
|
@ -673,12 +695,12 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
return(result_state); // IDENT or IDENT_QUOTED
|
||||
|
||||
case MY_LEX_IDENT_SEP: // Found ident and now '.'
|
||||
yylval->lex_str.str=(char*) lex->ptr;
|
||||
yylval->lex_str.str=(char*) lip->ptr;
|
||||
yylval->lex_str.length=1;
|
||||
c=yyGet(); // should be '.'
|
||||
lex->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
|
||||
lip->next_state= MY_LEX_IDENT_START;// Next is an ident (not a keyword)
|
||||
if (!ident_map[yyPeek()]) // Probably ` or "
|
||||
lex->next_state= MY_LEX_START;
|
||||
lip->next_state= MY_LEX_START;
|
||||
return((int) c);
|
||||
|
||||
case MY_LEX_NUMBER_IDENT: // number or ident which num-start
|
||||
|
@ -698,36 +720,32 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
{
|
||||
yySkip();
|
||||
while (my_isdigit(cs,yyGet())) ;
|
||||
yylval->lex_str=get_token(lex,yyLength());
|
||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
||||
return(FLOAT_NUM);
|
||||
}
|
||||
}
|
||||
yyUnget(); /* purecov: inspected */
|
||||
}
|
||||
else if (c == 'x' && (lex->ptr - lex->tok_start) == 2 &&
|
||||
lex->tok_start[0] == '0' )
|
||||
else if (c == 'x' && (lip->ptr - lip->tok_start) == 2 &&
|
||||
lip->tok_start[0] == '0' )
|
||||
{ // Varbinary
|
||||
while (my_isxdigit(cs,(c = yyGet()))) ;
|
||||
if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c])
|
||||
if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c])
|
||||
{
|
||||
yylval->lex_str=get_token(lex,yyLength());
|
||||
yylval->lex_str.str+=2; // Skip 0x
|
||||
yylval->lex_str.length-=2;
|
||||
lex->yytoklen-=2;
|
||||
/* skip '0x' */
|
||||
yylval->lex_str=get_token(lip, 2, yyLength()-2);
|
||||
return (HEX_NUM);
|
||||
}
|
||||
yyUnget();
|
||||
}
|
||||
else if (c == 'b' && (lex->ptr - lex->tok_start) == 2 &&
|
||||
lex->tok_start[0] == '0' )
|
||||
else if (c == 'b' && (lip->ptr - lip->tok_start) == 2 &&
|
||||
lip->tok_start[0] == '0' )
|
||||
{ // b'bin-number'
|
||||
while (my_isxdigit(cs,(c = yyGet()))) ;
|
||||
if ((lex->ptr - lex->tok_start) >= 4 && !ident_map[c])
|
||||
if ((lip->ptr - lip->tok_start) >= 4 && !ident_map[c])
|
||||
{
|
||||
yylval->lex_str= get_token(lex, yyLength());
|
||||
yylval->lex_str.str+= 2; // Skip 0x
|
||||
yylval->lex_str.length-= 2;
|
||||
lex->yytoklen-= 2;
|
||||
/* Skip '0b' */
|
||||
yylval->lex_str= get_token(lip, 2, yyLength()-2);
|
||||
return (BIN_NUM);
|
||||
}
|
||||
yyUnget();
|
||||
|
@ -745,10 +763,10 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
{
|
||||
int l;
|
||||
if ((l = my_ismbchar(cs,
|
||||
(const char *)lex->ptr-1,
|
||||
(const char *)lex->end_of_query)) == 0)
|
||||
lip->ptr-1,
|
||||
lip->end_of_query)) == 0)
|
||||
break;
|
||||
lex->ptr += l-1;
|
||||
lip->ptr += l-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -760,16 +778,15 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
||||
}
|
||||
if (c == '.' && ident_map[yyPeek()])
|
||||
lex->next_state=MY_LEX_IDENT_SEP;// Next is '.'
|
||||
lip->next_state=MY_LEX_IDENT_SEP;// Next is '.'
|
||||
|
||||
yylval->lex_str= get_token(lex,yyLength());
|
||||
yylval->lex_str= get_token(lip, 0, yyLength());
|
||||
return(result_state);
|
||||
|
||||
case MY_LEX_USER_VARIABLE_DELIMITER: // Found quote char
|
||||
{
|
||||
uint double_quotes= 0;
|
||||
char quote_char= c; // Used char
|
||||
lex->tok_start=lex->ptr; // Skip first `
|
||||
while ((c=yyGet()))
|
||||
{
|
||||
int var_length;
|
||||
|
@ -789,23 +806,24 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
#ifdef USE_MB
|
||||
else if (var_length < 1)
|
||||
break; // Error
|
||||
lex->ptr+= var_length-1;
|
||||
lip->ptr+= var_length-1;
|
||||
#endif
|
||||
}
|
||||
if (double_quotes)
|
||||
yylval->lex_str=get_quoted_token(lex,yyLength() - double_quotes,
|
||||
yylval->lex_str=get_quoted_token(lip, 1,
|
||||
yyLength() - double_quotes -1,
|
||||
quote_char);
|
||||
else
|
||||
yylval->lex_str=get_token(lex,yyLength());
|
||||
yylval->lex_str=get_token(lip, 1, yyLength() -1);
|
||||
if (c == quote_char)
|
||||
yySkip(); // Skip end `
|
||||
lex->next_state= MY_LEX_START;
|
||||
lip->next_state= MY_LEX_START;
|
||||
return(IDENT_QUOTED);
|
||||
}
|
||||
case MY_LEX_INT_OR_REAL: // Compleat int or incompleat real
|
||||
case MY_LEX_INT_OR_REAL: // Complete int or incomplete real
|
||||
if (c != '.')
|
||||
{ // Found complete integer number.
|
||||
yylval->lex_str=get_token(lex,yyLength());
|
||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
||||
return int_token(yylval->lex_str.str,yylval->lex_str.length);
|
||||
}
|
||||
// fall through
|
||||
|
@ -823,47 +841,45 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
break;
|
||||
}
|
||||
while (my_isdigit(cs,yyGet())) ;
|
||||
yylval->lex_str=get_token(lex,yyLength());
|
||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
||||
return(FLOAT_NUM);
|
||||
}
|
||||
yylval->lex_str=get_token(lex,yyLength());
|
||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
||||
return(DECIMAL_NUM);
|
||||
|
||||
case MY_LEX_HEX_NUMBER: // Found x'hexstring'
|
||||
yyGet(); // Skip '
|
||||
while (my_isxdigit(cs,(c = yyGet()))) ;
|
||||
length=(lex->ptr - lex->tok_start); // Length of hexnum+3
|
||||
length=(lip->ptr - lip->tok_start); // Length of hexnum+3
|
||||
if (!(length & 1) || c != '\'')
|
||||
{
|
||||
return(ABORT_SYM); // Illegal hex constant
|
||||
}
|
||||
yyGet(); // get_token makes an unget
|
||||
yylval->lex_str=get_token(lex,length);
|
||||
yylval->lex_str.str+=2; // Skip x'
|
||||
yylval->lex_str.length-=3; // Don't count x' and last '
|
||||
lex->yytoklen-=3;
|
||||
yylval->lex_str=get_token(lip,
|
||||
2, // skip x'
|
||||
length-3); // don't count x' and last '
|
||||
return (HEX_NUM);
|
||||
|
||||
case MY_LEX_BIN_NUMBER: // Found b'bin-string'
|
||||
yyGet(); // Skip '
|
||||
while ((c= yyGet()) == '0' || c == '1');
|
||||
length= (lex->ptr - lex->tok_start); // Length of bin-num + 3
|
||||
length= (lip->ptr - lip->tok_start); // Length of bin-num + 3
|
||||
if (c != '\'')
|
||||
return(ABORT_SYM); // Illegal hex constant
|
||||
yyGet(); // get_token makes an unget
|
||||
yylval->lex_str= get_token(lex, length);
|
||||
yylval->lex_str.str+= 2; // Skip b'
|
||||
yylval->lex_str.length-= 3; // Don't count b' and last '
|
||||
lex->yytoklen-= 3;
|
||||
return (BIN_NUM);
|
||||
yylval->lex_str= get_token(lip,
|
||||
2, // skip b'
|
||||
length-3); // don't count b' and last '
|
||||
return (BIN_NUM);
|
||||
|
||||
case MY_LEX_CMP_OP: // Incomplete comparison operator
|
||||
if (state_map[yyPeek()] == MY_LEX_CMP_OP ||
|
||||
state_map[yyPeek()] == MY_LEX_LONG_CMP_OP)
|
||||
yySkip();
|
||||
if ((tokval = find_keyword(lex,(uint) (lex->ptr - lex->tok_start),0)))
|
||||
if ((tokval = find_keyword(lip,(uint) (lip->ptr - lip->tok_start),0)))
|
||||
{
|
||||
lex->next_state= MY_LEX_START; // Allow signed numbers
|
||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||
return(tokval);
|
||||
}
|
||||
state = MY_LEX_CHAR; // Something fishy found
|
||||
|
@ -877,9 +893,9 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
if (state_map[yyPeek()] == MY_LEX_CMP_OP)
|
||||
yySkip();
|
||||
}
|
||||
if ((tokval = find_keyword(lex,(uint) (lex->ptr - lex->tok_start),0)))
|
||||
if ((tokval = find_keyword(lip,(uint) (lip->ptr - lip->tok_start),0)))
|
||||
{
|
||||
lex->next_state= MY_LEX_START; // Found long op
|
||||
lip->next_state= MY_LEX_START; // Found long op
|
||||
return(tokval);
|
||||
}
|
||||
state = MY_LEX_CHAR; // Something fishy found
|
||||
|
@ -892,24 +908,24 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
break;
|
||||
}
|
||||
yySkip();
|
||||
tokval = find_keyword(lex,2,0); // Is a bool operator
|
||||
lex->next_state= MY_LEX_START; // Allow signed numbers
|
||||
tokval = find_keyword(lip,2,0); // Is a bool operator
|
||||
lip->next_state= MY_LEX_START; // Allow signed numbers
|
||||
return(tokval);
|
||||
|
||||
case MY_LEX_STRING_OR_DELIMITER:
|
||||
if (((THD *) yythd)->variables.sql_mode & MODE_ANSI_QUOTES)
|
||||
if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
|
||||
{
|
||||
state= MY_LEX_USER_VARIABLE_DELIMITER;
|
||||
break;
|
||||
}
|
||||
/* " used for strings */
|
||||
case MY_LEX_STRING: // Incomplete text string
|
||||
if (!(yylval->lex_str.str = get_text(lex)))
|
||||
if (!(yylval->lex_str.str = get_text(lip)))
|
||||
{
|
||||
state= MY_LEX_CHAR; // Read char by char
|
||||
break;
|
||||
}
|
||||
yylval->lex_str.length=lex->yytoklen;
|
||||
yylval->lex_str.length=lip->yytoklen;
|
||||
return(TEXT_STRING);
|
||||
|
||||
case MY_LEX_COMMENT: // Comment
|
||||
|
@ -933,7 +949,7 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
state=MY_LEX_START;
|
||||
if (my_isdigit(cs,yyPeek()))
|
||||
{ // Version number
|
||||
version=strtol((char*) lex->ptr,(char**) &lex->ptr,10);
|
||||
version=strtol((char*) lip->ptr,(char**) &lip->ptr,10);
|
||||
}
|
||||
if (version <= MYSQL_VERSION_ID)
|
||||
{
|
||||
|
@ -941,13 +957,13 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
break;
|
||||
}
|
||||
}
|
||||
while (lex->ptr != lex->end_of_query &&
|
||||
while (lip->ptr != lip->end_of_query &&
|
||||
((c=yyGet()) != '*' || yyPeek() != '/'))
|
||||
{
|
||||
if (c == '\n')
|
||||
lex->yylineno++;
|
||||
lip->yylineno++;
|
||||
}
|
||||
if (lex->ptr != lex->end_of_query)
|
||||
if (lip->ptr != lip->end_of_query)
|
||||
yySkip(); // remove last '/'
|
||||
state = MY_LEX_START; // Try again
|
||||
break;
|
||||
|
@ -972,14 +988,13 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
case MY_LEX_SEMICOLON: // optional line terminator
|
||||
if (yyPeek())
|
||||
{
|
||||
THD* thd= (THD*)yythd;
|
||||
if ((thd->client_capabilities & CLIENT_MULTI_STATEMENTS) &&
|
||||
!lex->stmt_prepare_mode)
|
||||
{
|
||||
lex->safe_to_cache_query= 0;
|
||||
lex->found_semicolon=(char*) lex->ptr;
|
||||
lip->found_semicolon= lip->ptr;
|
||||
thd->server_status|= SERVER_MORE_RESULTS_EXISTS;
|
||||
lex->next_state= MY_LEX_END;
|
||||
lip->next_state= MY_LEX_END;
|
||||
return (END_OF_INPUT);
|
||||
}
|
||||
state= MY_LEX_CHAR; // Return ';'
|
||||
|
@ -987,15 +1002,15 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
}
|
||||
/* fall true */
|
||||
case MY_LEX_EOL:
|
||||
if (lex->ptr >= lex->end_of_query)
|
||||
if (lip->ptr >= lip->end_of_query)
|
||||
{
|
||||
lex->next_state=MY_LEX_END; // Mark for next loop
|
||||
lip->next_state=MY_LEX_END; // Mark for next loop
|
||||
return(END_OF_INPUT);
|
||||
}
|
||||
state=MY_LEX_CHAR;
|
||||
break;
|
||||
case MY_LEX_END:
|
||||
lex->next_state=MY_LEX_END;
|
||||
lip->next_state=MY_LEX_END;
|
||||
return(0); // We found end of input last time
|
||||
|
||||
/* Actually real shouldn't start with . but allow them anyhow */
|
||||
|
@ -1015,26 +1030,26 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
case MY_LEX_STRING_OR_DELIMITER:
|
||||
break;
|
||||
case MY_LEX_USER_END:
|
||||
lex->next_state=MY_LEX_SYSTEM_VAR;
|
||||
lip->next_state=MY_LEX_SYSTEM_VAR;
|
||||
break;
|
||||
default:
|
||||
lex->next_state=MY_LEX_HOSTNAME;
|
||||
lip->next_state=MY_LEX_HOSTNAME;
|
||||
break;
|
||||
}
|
||||
yylval->lex_str.str=(char*) lex->ptr;
|
||||
yylval->lex_str.str=(char*) lip->ptr;
|
||||
yylval->lex_str.length=1;
|
||||
return((int) '@');
|
||||
case MY_LEX_HOSTNAME: // end '@' of user@hostname
|
||||
for (c=yyGet() ;
|
||||
my_isalnum(cs,c) || c == '.' || c == '_' || c == '$';
|
||||
c= yyGet()) ;
|
||||
yylval->lex_str=get_token(lex,yyLength());
|
||||
yylval->lex_str=get_token(lip, 0, yyLength());
|
||||
return(LEX_HOSTNAME);
|
||||
case MY_LEX_SYSTEM_VAR:
|
||||
yylval->lex_str.str=(char*) lex->ptr;
|
||||
yylval->lex_str.str=(char*) lip->ptr;
|
||||
yylval->lex_str.length=1;
|
||||
yySkip(); // Skip '@'
|
||||
lex->next_state= (state_map[yyPeek()] ==
|
||||
lip->next_state= (state_map[yyPeek()] ==
|
||||
MY_LEX_USER_VARIABLE_DELIMITER ?
|
||||
MY_LEX_OPERATOR_OR_IDENT :
|
||||
MY_LEX_IDENT_OR_KEYWORD);
|
||||
|
@ -1051,16 +1066,16 @@ int MYSQLlex(void *arg, void *yythd)
|
|||
result_state= result_state & 0x80 ? IDENT_QUOTED : IDENT;
|
||||
|
||||
if (c == '.')
|
||||
lex->next_state=MY_LEX_IDENT_SEP;
|
||||
length= (uint) (lex->ptr - lex->tok_start)-1;
|
||||
lip->next_state=MY_LEX_IDENT_SEP;
|
||||
length= (uint) (lip->ptr - lip->tok_start)-1;
|
||||
if (length == 0)
|
||||
return(ABORT_SYM); // Names must be nonempty.
|
||||
if ((tokval= find_keyword(lex,length,0)))
|
||||
if ((tokval= find_keyword(lip, length,0)))
|
||||
{
|
||||
yyUnget(); // Put back 'c'
|
||||
return(tokval); // Was keyword
|
||||
}
|
||||
yylval->lex_str=get_token(lex,length);
|
||||
yylval->lex_str=get_token(lip, 0, length);
|
||||
return(result_state);
|
||||
}
|
||||
}
|
||||
|
@ -1093,7 +1108,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
|
|||
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] == '*' ||
|
||||
end[-1] == '/' || end[-1] == ';'))
|
||||
|
|
|
@ -470,7 +470,7 @@ public:
|
|||
void set_thd(THD *thd_arg) { thd= thd_arg; }
|
||||
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();
|
||||
|
||||
List<Item> *get_unit_column_types();
|
||||
|
@ -676,7 +676,7 @@ public:
|
|||
void cut_subtree() { slave= 0; }
|
||||
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) {}
|
||||
void make_empty_select()
|
||||
{
|
||||
|
@ -906,30 +906,73 @@ struct st_parsing_options
|
|||
};
|
||||
|
||||
|
||||
/**
|
||||
This class represents the character input stream consumed during
|
||||
lexical analysis.
|
||||
*/
|
||||
class Lex_input_stream
|
||||
{
|
||||
public:
|
||||
Lex_input_stream(THD *thd, const char* buff, unsigned int length);
|
||||
~Lex_input_stream();
|
||||
|
||||
/** Current thread. */
|
||||
THD *m_thd;
|
||||
|
||||
/** Current line number. */
|
||||
uint yylineno;
|
||||
|
||||
/** Length of the last token parsed. */
|
||||
uint yytoklen;
|
||||
|
||||
/** Interface with bison, value of the last token parsed. */
|
||||
LEX_YYSTYPE yylval;
|
||||
|
||||
/** Pointer to the current position in the input stream. */
|
||||
const char* ptr;
|
||||
|
||||
/** Starting position of the last token parsed. */
|
||||
const char* tok_start;
|
||||
|
||||
/** Ending position of the last token parsed. */
|
||||
const char* tok_end;
|
||||
|
||||
/** End of the query text in the input stream. */
|
||||
const char* end_of_query;
|
||||
|
||||
/** Starting position of the previous token parsed. */
|
||||
const char* tok_start_prev;
|
||||
|
||||
/** Begining of the query text in the input stream. */
|
||||
const char* buf;
|
||||
|
||||
/** Current state of the lexical analyser. */
|
||||
enum my_lex_states next_state;
|
||||
|
||||
/** Position of ';' in the stream, to delimit multiple queries. */
|
||||
const char* found_semicolon;
|
||||
|
||||
/** SQL_MODE = IGNORE_SPACE. */
|
||||
bool ignore_space;
|
||||
};
|
||||
|
||||
|
||||
/* The state of the lex parsing. This is saved in the THD struct */
|
||||
|
||||
typedef struct st_lex : public Query_tables_list
|
||||
{
|
||||
uint yylineno,yytoklen; /* Simulate lex */
|
||||
LEX_YYSTYPE yylval;
|
||||
SELECT_LEX_UNIT unit; /* most upper unit */
|
||||
SELECT_LEX select_lex; /* first SELECT_LEX */
|
||||
/* current SELECT_LEX in parsing */
|
||||
SELECT_LEX *current_select;
|
||||
/* list of all SELECT_LEX */
|
||||
SELECT_LEX *all_selects_list;
|
||||
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 *help_arg;
|
||||
char *backup_dir; /* For RESTORE/BACKUP */
|
||||
char* to_log; /* For PURGE MASTER LOGS TO */
|
||||
char* x509_subject,*x509_issuer,*ssl_cipher;
|
||||
char* found_semicolon; /* For multi queries - next query */
|
||||
String *wild;
|
||||
sql_exchange *exchange;
|
||||
select_result *result;
|
||||
|
@ -998,7 +1041,6 @@ typedef struct st_lex : public Query_tables_list
|
|||
enum_sql_command sql_command, orig_sql_command;
|
||||
thr_lock_type lock_option;
|
||||
enum SSL_type ssl_type; /* defined in violite.h */
|
||||
enum my_lex_states next_state;
|
||||
enum enum_duplicates duplicates;
|
||||
enum enum_tx_isolation tx_isolation;
|
||||
enum enum_ha_read_modes ha_read_mode;
|
||||
|
@ -1030,7 +1072,7 @@ typedef struct st_lex : public Query_tables_list
|
|||
uint8 create_view_algorithm;
|
||||
uint8 create_view_check;
|
||||
bool drop_if_exists, drop_temporary, local_file, one_shot_set;
|
||||
bool in_comment, ignore_space, verbose, no_write_to_binlog;
|
||||
bool in_comment, verbose, no_write_to_binlog;
|
||||
bool tx_chain, tx_release;
|
||||
/*
|
||||
Special JOIN::prepare mode: changing of query is prohibited.
|
||||
|
@ -1109,8 +1151,9 @@ typedef struct st_lex : public Query_tables_list
|
|||
Pointers to part of LOAD DATA statement that should be rewritten
|
||||
during replication ("LOCAL 'filename' REPLACE INTO" part).
|
||||
*/
|
||||
uchar *fname_start, *fname_end;
|
||||
|
||||
const char *fname_start;
|
||||
const char *fname_end;
|
||||
|
||||
bool escape_used;
|
||||
|
||||
st_lex();
|
||||
|
@ -1219,7 +1262,7 @@ struct st_lex_local: public st_lex
|
|||
|
||||
extern void lex_init(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 int MYSQLlex(void *arg, void *yythd);
|
||||
extern uchar *skip_rear_comments(uchar *begin, uchar *end);
|
||||
extern char *skip_rear_comments(char *begin, char *end);
|
||||
|
|
104
sql/sql_parse.cc
104
sql/sql_parse.cc
|
@ -1238,6 +1238,7 @@ pthread_handler_t handle_bootstrap(void *arg)
|
|||
THD *thd=(THD*) arg;
|
||||
FILE *file=bootstrap_file;
|
||||
char *buff;
|
||||
const char* found_semicolon= NULL;
|
||||
|
||||
/* The following must be called before DBUG_ENTER */
|
||||
thd->thread_stack= (char*) &thd;
|
||||
|
@ -1314,7 +1315,7 @@ pthread_handler_t handle_bootstrap(void *arg)
|
|||
*/
|
||||
thd->query_id=next_query_id();
|
||||
thd->set_time();
|
||||
mysql_parse(thd,thd->query,length);
|
||||
mysql_parse(thd, thd->query, length, & found_semicolon);
|
||||
close_thread_tables(thd); // Free tables
|
||||
|
||||
if (thd->is_fatal_error)
|
||||
|
@ -1793,17 +1794,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
char *packet_end= thd->query + thd->query_length;
|
||||
/* 'b' stands for 'buffer' parameter', special for 'my_snprintf' */
|
||||
const char *format= "%.*b";
|
||||
const char* found_semicolon= NULL;
|
||||
|
||||
mysql_log.write(thd,command, format, thd->query_length, thd->query);
|
||||
DBUG_PRINT("query",("%-.4096s",thd->query));
|
||||
|
||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
|
||||
|
||||
mysql_parse(thd,thd->query, thd->query_length);
|
||||
mysql_parse(thd, thd->query, thd->query_length, & found_semicolon);
|
||||
|
||||
while (!thd->killed && thd->lex->found_semicolon && !thd->net.report_error)
|
||||
while (!thd->killed && found_semicolon && !thd->net.report_error)
|
||||
{
|
||||
char *next_packet= thd->lex->found_semicolon;
|
||||
char *next_packet= (char*) found_semicolon;
|
||||
net->no_send_error= 0;
|
||||
/*
|
||||
Multiple queries exits, execute them individually
|
||||
|
@ -1828,7 +1831,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
thd->set_time(); /* Reset the query start time. */
|
||||
/* TODO: set thd->lex->sql_command to SQLCOM_END here */
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
mysql_parse(thd, next_packet, length);
|
||||
mysql_parse(thd, next_packet, length, & found_semicolon);
|
||||
}
|
||||
|
||||
if (!(specialflag & SPECIAL_NO_PRIOR))
|
||||
|
@ -1849,7 +1852,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
LEX_STRING conv_name;
|
||||
|
||||
/* used as fields initializator */
|
||||
lex_start(thd, 0, 0);
|
||||
lex_start(thd);
|
||||
|
||||
statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS],
|
||||
&LOCK_status);
|
||||
|
@ -1886,7 +1889,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
break;
|
||||
/* init structures for VIEW processing */
|
||||
table_list.select_lex= &(thd->lex->select_lex);
|
||||
mysql_init_query(thd, (uchar*)"", 0);
|
||||
|
||||
lex_start(thd);
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
|
||||
thd->lex->
|
||||
select_lex.table_list.link_in_list((byte*) &table_list,
|
||||
(byte**) &table_list.next_local);
|
||||
|
@ -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.
|
||||
|
||||
|
@ -5974,21 +5966,55 @@ void mysql_init_multi_delete(LEX *lex)
|
|||
mysql_test_parse_for_slave() in this same file.
|
||||
*/
|
||||
|
||||
void mysql_parse(THD *thd, char *inBuf, uint length)
|
||||
/**
|
||||
Parse a query.
|
||||
@param thd Current thread
|
||||
@param inBuf Begining of the query text
|
||||
@param length Length of the query text
|
||||
@param [out] semicolon For multi queries, position of the character of
|
||||
the next query in the query text.
|
||||
*/
|
||||
|
||||
void mysql_parse(THD *thd, const char *inBuf, uint length,
|
||||
const char ** found_semicolon)
|
||||
{
|
||||
DBUG_ENTER("mysql_parse");
|
||||
|
||||
DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
|
||||
|
||||
mysql_init_query(thd, (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 (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, (char*) inBuf, length) <= 0)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
|
||||
|
||||
sp_cache_flush_obsolete(&thd->sp_proc_cache);
|
||||
sp_cache_flush_obsolete(&thd->sp_func_cache);
|
||||
|
||||
if (!MYSQLparse((void *)thd) && ! thd->is_fatal_error)
|
||||
|
||||
Lex_input_stream lip(thd, inBuf, length);
|
||||
thd->m_lip= &lip;
|
||||
|
||||
int err= MYSQLparse(thd);
|
||||
*found_semicolon= lip.found_semicolon;
|
||||
|
||||
if (!err && ! thd->is_fatal_error)
|
||||
{
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (mqh_used && thd->user_connect &&
|
||||
|
@ -6011,8 +6037,8 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
|
|||
PROCESSLIST.
|
||||
Note that we don't need LOCK_thread_count to modify query_length.
|
||||
*/
|
||||
if (lex->found_semicolon &&
|
||||
(thd->query_length= (ulong)(lex->found_semicolon - thd->query)))
|
||||
if (lip.found_semicolon &&
|
||||
(thd->query_length= (ulong)(lip.found_semicolon - thd->query)))
|
||||
thd->query_length--;
|
||||
/* Actually execute the query */
|
||||
mysql_execute_command(thd);
|
||||
|
@ -6039,6 +6065,12 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
|
|||
thd->cleanup_after_query();
|
||||
DBUG_ASSERT(thd->change_list.is_empty());
|
||||
}
|
||||
else
|
||||
{
|
||||
/* There are no multi queries in the cache. */
|
||||
*found_semicolon= NULL;
|
||||
}
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -6059,8 +6091,13 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
|
|||
bool error= 0;
|
||||
DBUG_ENTER("mysql_test_parse_for_slave");
|
||||
|
||||
mysql_init_query(thd, (uchar*) inBuf, length);
|
||||
if (!MYSQLparse((void*) thd) && ! thd->is_fatal_error &&
|
||||
Lex_input_stream lip(thd, inBuf, length);
|
||||
thd->m_lip= &lip;
|
||||
lex_start(thd);
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
int err= MYSQLparse((void*) thd);
|
||||
|
||||
if (!err && ! thd->is_fatal_error &&
|
||||
all_tables_not_ok(thd,(TABLE_LIST*) lex->select_lex.table_list.first))
|
||||
error= 1; /* Ignore question */
|
||||
thd->end_statement();
|
||||
|
@ -7119,8 +7156,9 @@ bool check_simple_select()
|
|||
if (lex->current_select != &lex->select_lex)
|
||||
{
|
||||
char command[80];
|
||||
strmake(command, lex->yylval->symbol.str,
|
||||
min(lex->yylval->symbol.length, sizeof(command)-1));
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
strmake(command, lip->yylval->symbol.str,
|
||||
min(lip->yylval->symbol.length, sizeof(command)-1));
|
||||
my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -2799,11 +2799,15 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
|
|||
|
||||
old_stmt_arena= thd->stmt_arena;
|
||||
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->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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -978,10 +978,14 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
|
|||
LEX_STRING *trg_definer= it_definer++;
|
||||
|
||||
thd->variables.sql_mode= (ulong)*trg_sql_mode;
|
||||
lex_start(thd, (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;
|
||||
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 */
|
||||
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.length= str.length()-1; // we do not need last \0
|
||||
view->source.str= thd->query + thd->lex->create_view_select_start;
|
||||
view->source.length= (char *)skip_rear_comments((uchar *)view->source.str,
|
||||
(uchar *)thd->query +
|
||||
view->source.length= (char *)skip_rear_comments((char *)view->source.str,
|
||||
(char *)thd->query +
|
||||
thd->query_length) -
|
||||
view->source.str;
|
||||
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
|
||||
*/
|
||||
table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
|
||||
lex_start(thd, (uchar*)table->query.str, table->query.length);
|
||||
view_select= &lex->select_lex;
|
||||
view_select->select_number= ++thd->select_number;
|
||||
|
||||
{
|
||||
Lex_input_stream lip(thd, table->query.str, table->query.length);
|
||||
thd->m_lip= &lip;
|
||||
lex_start(thd);
|
||||
view_select= &lex->select_lex;
|
||||
view_select->select_number= ++thd->select_number;
|
||||
|
||||
ulong save_mode= thd->variables.sql_mode;
|
||||
/* switch off modes which can prevent normal parsing of VIEW
|
||||
- MODE_REAL_AS_FLOAT affect only CREATE TABLE parsing
|
||||
|
|
185
sql/sql_yacc.yy
185
sql/sql_yacc.yy
|
@ -86,12 +86,13 @@ const LEX_STRING null_lex_str={0,0};
|
|||
void my_parse_error(const char *s)
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
char *yytext= (char*) thd->lex->tok_start;
|
||||
const char *yytext= lip->tok_start;
|
||||
/* Push an error into the error stack */
|
||||
my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
|
||||
(yytext ? (char*) yytext : ""),
|
||||
thd->lex->yylineno);
|
||||
(yytext ? yytext : ""),
|
||||
lip->yylineno);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
|
||||
/*
|
||||
|
@ -1639,9 +1642,9 @@ create_function_tail:
|
|||
}
|
||||
/* Order is important here: new - reset - init */
|
||||
sp= new sp_head();
|
||||
sp->reset_thd_mem_root(YYTHD);
|
||||
sp->reset_thd_mem_root(thd);
|
||||
sp->init(lex);
|
||||
sp->init_sp_name(YYTHD, lex->spname);
|
||||
sp->init_sp_name(thd, lex->spname);
|
||||
|
||||
sp->m_type= TYPE_ENUM_FUNCTION;
|
||||
lex->sphead= sp;
|
||||
|
@ -1650,15 +1653,17 @@ create_function_tail:
|
|||
* stored procedure, otherwise yylex will chop it into pieces
|
||||
* at each ';'.
|
||||
*/
|
||||
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
||||
lex->sphead->m_param_begin= lex->tok_start+1;
|
||||
sp->m_old_cmq= thd->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
||||
lex->sphead->m_param_begin= lip->tok_start+1;
|
||||
}
|
||||
sp_fdparam_list ')'
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
lex->sphead->m_param_end= lex->tok_start;
|
||||
lex->sphead->m_param_end= lip->tok_start;
|
||||
}
|
||||
RETURNS_SYM
|
||||
{
|
||||
|
@ -1682,10 +1687,12 @@ create_function_tail:
|
|||
}
|
||||
sp_c_chistics
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||
lex->sphead->m_body_begin= lex->tok_start;
|
||||
lex->sphead->m_body_begin= lip->tok_start;
|
||||
}
|
||||
sp_proc_stmt
|
||||
{
|
||||
|
@ -2233,14 +2240,18 @@ sp_opt_default:
|
|||
|
||||
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->m_tmp_query= lex->tok_start;
|
||||
lex->sphead->reset_lex(thd);
|
||||
lex->sphead->m_tmp_query= lip->tok_start;
|
||||
}
|
||||
statement
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
sp_head *sp= lex->sphead;
|
||||
|
||||
sp->m_flags|= sp_get_flags_for_command(lex);
|
||||
|
@ -2267,15 +2278,15 @@ sp_proc_stmt:
|
|||
lex->tok_end otherwise.
|
||||
*/
|
||||
if (yychar == YYEMPTY)
|
||||
i->m_query.length= lex->ptr - sp->m_tmp_query;
|
||||
i->m_query.length= lip->ptr - sp->m_tmp_query;
|
||||
else
|
||||
i->m_query.length= lex->tok_end - sp->m_tmp_query;
|
||||
i->m_query.str= strmake_root(YYTHD->mem_root,
|
||||
(char *)sp->m_tmp_query,
|
||||
i->m_query.length= lip->tok_end - sp->m_tmp_query;
|
||||
i->m_query.str= strmake_root(thd->mem_root,
|
||||
sp->m_tmp_query,
|
||||
i->m_query.length);
|
||||
sp->add_instr(i);
|
||||
}
|
||||
sp->restore_lex(YYTHD);
|
||||
sp->restore_lex(thd);
|
||||
}
|
||||
| RETURN_SYM
|
||||
{ Lex->sphead->reset_lex(YYTHD); }
|
||||
|
@ -4428,26 +4439,36 @@ select_item_list:
|
|||
select_item:
|
||||
remember_name select_item2 remember_end select_alias
|
||||
{
|
||||
if (add_item_to_list(YYTHD, $2))
|
||||
THD *thd= YYTHD;
|
||||
DBUG_ASSERT($1 < $3);
|
||||
|
||||
if (add_item_to_list(thd, $2))
|
||||
MYSQL_YYABORT;
|
||||
if ($4.str)
|
||||
{
|
||||
$2->is_autogenerated_name= FALSE;
|
||||
$2->set_name($4.str, $4.length, system_charset_info);
|
||||
}
|
||||
else if (!$2->name) {
|
||||
char *str = $1;
|
||||
if (str[-1] == '`')
|
||||
str--;
|
||||
$2->set_name(str,(uint) ($3 - str), YYTHD->charset());
|
||||
else if (!$2->name)
|
||||
{
|
||||
$2->set_name($1, (uint) ($3 - $1), thd->charset());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
remember_name:
|
||||
{ $$=(char*) Lex->tok_start; };
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
$$= (char*) lip->tok_start;
|
||||
};
|
||||
|
||||
remember_end:
|
||||
{ $$=(char*) Lex->tok_end; };
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
$$=(char*) lip->tok_end;
|
||||
};
|
||||
|
||||
select_item2:
|
||||
table_wild { $$=$1; } /* table.* */
|
||||
|
@ -6292,12 +6313,14 @@ procedure_list2:
|
|||
procedure_item:
|
||||
remember_name expr
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (add_proc_to_list(lex->thd, $2))
|
||||
THD *thd= YYTHD;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
if (add_proc_to_list(thd, $2))
|
||||
MYSQL_YYABORT;
|
||||
if (!$2->name)
|
||||
$2->set_name($1,(uint) ((char*) lex->tok_end - $1),
|
||||
YYTHD->charset());
|
||||
$2->set_name($1,(uint) ((char*) lip->tok_end - $1),
|
||||
thd->charset());
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -7337,13 +7360,16 @@ use: USE_SYM ident
|
|||
|
||||
load: LOAD DATA_SYM
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
if (lex->sphead)
|
||||
{
|
||||
my_error(ER_SP_BADSTATEMENT, MYF(0), "LOAD DATA");
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
lex->fname_start= lex->ptr;
|
||||
lex->fname_start= lip->ptr;
|
||||
}
|
||||
load_data
|
||||
{}
|
||||
|
@ -7378,8 +7404,10 @@ load_data:
|
|||
}
|
||||
opt_duplicate INTO
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->fname_end= lex->ptr;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
lex->fname_end= lip->ptr;
|
||||
}
|
||||
TABLE_SYM table_ident
|
||||
{
|
||||
|
@ -7559,15 +7587,16 @@ text_string:
|
|||
param_marker:
|
||||
PARAM_MARKER
|
||||
{
|
||||
THD *thd=YYTHD;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
Item_param *item;
|
||||
if (! lex->parsing_options.allows_variable)
|
||||
{
|
||||
my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
item= new Item_param((uint) (lex->tok_start - (uchar *) thd->query));
|
||||
item= new Item_param((uint) (lip->tok_start - thd->query));
|
||||
if (!($$= item) || lex->param_list.push_back(item))
|
||||
{
|
||||
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
||||
|
@ -7590,8 +7619,11 @@ signed_literal:
|
|||
literal:
|
||||
text_literal { $$ = $1; }
|
||||
| NUM_literal { $$ = $1; }
|
||||
| NULL_SYM { $$ = new Item_null();
|
||||
Lex->next_state=MY_LEX_OPERATOR_OR_IDENT;}
|
||||
| NULL_SYM
|
||||
{
|
||||
$$ = new Item_null();
|
||||
YYTHD->m_lip->next_state=MY_LEX_OPERATOR_OR_IDENT;
|
||||
}
|
||||
| FALSE_SYM { $$= new Item_int((char*) "FALSE",0,1); }
|
||||
| TRUE_SYM { $$= new Item_int((char*) "TRUE",1,1); }
|
||||
| HEX_NUM { $$ = new Item_hex_string($1.str, $1.length);}
|
||||
|
@ -7681,8 +7713,10 @@ order_ident:
|
|||
simple_ident:
|
||||
ident
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
sp_variable_t *spv;
|
||||
LEX *lex = Lex;
|
||||
sp_pcontext *spc = lex->spcont;
|
||||
if (spc && (spv = spc->find_variable(&$1)))
|
||||
{
|
||||
|
@ -7695,7 +7729,7 @@ simple_ident:
|
|||
|
||||
Item_splocal *splocal;
|
||||
splocal= new Item_splocal($1, spv->offset, spv->type,
|
||||
lex->tok_start_prev -
|
||||
lip->tok_start_prev -
|
||||
lex->sphead->m_tmp_query);
|
||||
#ifndef DBUG_OFF
|
||||
if (splocal)
|
||||
|
@ -8291,7 +8325,11 @@ option_value_list:
|
|||
|
||||
option_type_value:
|
||||
{
|
||||
if (Lex->sphead)
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
if (lex->sphead)
|
||||
{
|
||||
/*
|
||||
If we are in SP we want have own LEX for each assignment.
|
||||
|
@ -8303,9 +8341,8 @@ option_type_value:
|
|||
|
||||
QQ: May be we should simply prohibit group assignments in SP?
|
||||
*/
|
||||
LEX *lex;
|
||||
Lex->sphead->reset_lex(YYTHD);
|
||||
lex= Lex;
|
||||
Lex->sphead->reset_lex(thd);
|
||||
lex= thd->lex;
|
||||
|
||||
/* Set new LEX as if we at start of set rule. */
|
||||
lex->sql_command= SQLCOM_SET_OPTION;
|
||||
|
@ -8313,12 +8350,14 @@ option_type_value:
|
|||
lex->option_type=OPT_SESSION;
|
||||
lex->var_list.empty();
|
||||
lex->one_shot_set= 0;
|
||||
lex->sphead->m_tmp_query= lex->tok_start;
|
||||
lex->sphead->m_tmp_query= lip->tok_start;
|
||||
}
|
||||
}
|
||||
ext_option_value
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
if (lex->sphead)
|
||||
{
|
||||
|
@ -8340,24 +8379,24 @@ option_type_value:
|
|||
|
||||
/*
|
||||
Extract the query statement from the tokenizer. The
|
||||
end is either lex->ptr, if there was no lookahead,
|
||||
lex->tok_end otherwise.
|
||||
end is either lip->ptr, if there was no lookahead,
|
||||
lip->tok_end otherwise.
|
||||
*/
|
||||
if (yychar == YYEMPTY)
|
||||
qbuff.length= lex->ptr - sp->m_tmp_query;
|
||||
qbuff.length= lip->ptr - sp->m_tmp_query;
|
||||
else
|
||||
qbuff.length= lex->tok_end - sp->m_tmp_query;
|
||||
qbuff.length= lip->tok_end - sp->m_tmp_query;
|
||||
|
||||
if (!(qbuff.str= alloc_root(YYTHD->mem_root, qbuff.length + 5)))
|
||||
if (!(qbuff.str= alloc_root(thd->mem_root, qbuff.length + 5)))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
strmake(strmake(qbuff.str, "SET ", 4), (char *)sp->m_tmp_query,
|
||||
strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
|
||||
qbuff.length);
|
||||
qbuff.length+= 4;
|
||||
i->m_query= qbuff;
|
||||
sp->add_instr(i);
|
||||
}
|
||||
lex->sphead->restore_lex(YYTHD);
|
||||
lex->sphead->restore_lex(thd);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -9615,7 +9654,9 @@ trigger_tail:
|
|||
TRIGGER_SYM remember_name sp_name trg_action_time trg_event
|
||||
ON remember_name table_ident FOR_SYM remember_name EACH_SYM ROW_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
sp_head *sp;
|
||||
|
||||
if (lex->sphead)
|
||||
|
@ -9626,9 +9667,9 @@ trigger_tail:
|
|||
|
||||
if (!(sp= new sp_head()))
|
||||
MYSQL_YYABORT;
|
||||
sp->reset_thd_mem_root(YYTHD);
|
||||
sp->reset_thd_mem_root(thd);
|
||||
sp->init(lex);
|
||||
sp->init_sp_name(YYTHD, $3);
|
||||
sp->init_sp_name(thd, $3);
|
||||
|
||||
lex->stmt_definition_begin= $2;
|
||||
lex->ident.str= $7;
|
||||
|
@ -9642,12 +9683,12 @@ trigger_tail:
|
|||
stored procedure, otherwise yylex will chop it into pieces
|
||||
at each ';'.
|
||||
*/
|
||||
sp->m_old_cmq= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
||||
sp->m_old_cmq= thd->client_capabilities & CLIENT_MULTI_QUERIES;
|
||||
thd->client_capabilities &= ~CLIENT_MULTI_QUERIES;
|
||||
|
||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||
lex->sphead->m_body_begin= lex->ptr;
|
||||
lex->sphead->m_body_begin= lip->ptr;
|
||||
while (my_isspace(system_charset_info, lex->sphead->m_body_begin[0]))
|
||||
++lex->sphead->m_body_begin;
|
||||
}
|
||||
|
@ -9726,24 +9767,30 @@ sp_tail:
|
|||
}
|
||||
'('
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
lex->sphead->m_param_begin= lex->tok_start+1;
|
||||
lex->sphead->m_param_begin= lip->tok_start+1;
|
||||
}
|
||||
sp_pdparam_list
|
||||
')'
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
lex->sphead->m_param_end= lex->tok_start;
|
||||
lex->sphead->m_param_end= lip->tok_start;
|
||||
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
|
||||
}
|
||||
sp_c_chistics
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
THD *thd= YYTHD;
|
||||
LEX *lex= thd->lex;
|
||||
Lex_input_stream *lip= thd->m_lip;
|
||||
|
||||
lex->sphead->m_chistics= &lex->sp_chistics;
|
||||
lex->sphead->m_body_begin= lex->tok_start;
|
||||
lex->sphead->m_body_begin= lip->tok_start;
|
||||
}
|
||||
sp_proc_stmt
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue