Commit 4523a7b1 authored by pem@mysql.com's avatar pem@mysql.com

Adopt SP stuff to the new lex pointer.

parent 384b10e2
...@@ -95,6 +95,23 @@ delete from t1; ...@@ -95,6 +95,23 @@ delete from t1;
drop procedure zip; drop procedure zip;
drop procedure zap; drop procedure zap;
drop procedure bar; drop procedure bar;
create procedure c1(x int)
call c2("c", x);
create procedure c2(s char(16), x int)
call c3(x, s);
create procedure c3(x int, s char(16))
call c4("level", x, s);
create procedure c4(l char(8), x int, s char(16))
insert into t1 values (concat(l,s), x);
call c1(42);
select * from t1;
id data
levelc 42
delete from t1;
drop procedure c1;
drop procedure c2;
drop procedure c3;
drop procedure c4;
create procedure iotest(x1 char(16), x2 char(16), y int) create procedure iotest(x1 char(16), x2 char(16), y int)
begin begin
call inc2(x2, y); call inc2(x2, y);
......
...@@ -126,6 +126,24 @@ drop procedure zap| ...@@ -126,6 +126,24 @@ drop procedure zap|
drop procedure bar| drop procedure bar|
# "Deep" calls...
create procedure c1(x int)
call c2("c", x)|
create procedure c2(s char(16), x int)
call c3(x, s)|
create procedure c3(x int, s char(16))
call c4("level", x, s)|
create procedure c4(l char(8), x int, s char(16))
insert into t1 values (concat(l,s), x)|
call c1(42)|
select * from t1|
delete from t1|
drop procedure c1|
drop procedure c2|
drop procedure c3|
drop procedure c4|
# INOUT test # INOUT test
create procedure iotest(x1 char(16), x2 char(16), y int) create procedure iotest(x1 char(16), x2 char(16), y int)
begin begin
......
...@@ -353,7 +353,7 @@ bool is_update_query(enum enum_sql_command command); ...@@ -353,7 +353,7 @@ bool is_update_query(enum enum_sql_command command);
void free_items(Item *item); void free_items(Item *item);
bool alloc_query(THD *thd, char *packet, ulong packet_length); bool alloc_query(THD *thd, char *packet, ulong packet_length);
void mysql_init_select(LEX *lex); void mysql_init_select(LEX *lex);
void mysql_init_query(THD *thd); void mysql_init_query(THD *thd, bool lexonly=0);
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);
......
...@@ -88,7 +88,6 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -88,7 +88,6 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
DBUG_ENTER("db_find_routine"); DBUG_ENTER("db_find_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name)); DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
extern int yyparse(void *thd); extern int yyparse(void *thd);
LEX *tmplex;
TABLE *table; TABLE *table;
const char *defstr; const char *defstr;
int ret; int ret;
...@@ -146,16 +145,30 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp) ...@@ -146,16 +145,30 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
table= NULL; table= NULL;
} }
tmplex= lex_start(thd, (uchar*)defstr, strlen(defstr)); {
if (yyparse(thd) || thd->is_fatal_error || tmplex->sphead == NULL) LEX *oldlex= thd->lex;
enum enum_sql_command oldcmd= thd->lex->sql_command;
lex_start(thd, (uchar*)defstr, strlen(defstr));
if (yyparse(thd) || thd->is_fatal_error || thd->lex->sphead == NULL)
{
if (thd->lex->sphead)
{
if (oldlex != thd->lex)
thd->lex->sphead->restore_lex(thd);
thd->lex->sphead->destroy();
}
ret= SP_PARSE_ERROR; ret= SP_PARSE_ERROR;
}
else else
{ {
*sphp= tmplex->sphead; *sphp= thd->lex->sphead;
(*sphp)->sp_set_info((char *) creator, (uint) strlen(creator), (*sphp)->sp_set_info((char *) creator, (uint) strlen(creator),
created, modified, suid, created, modified, suid,
ptr, length); ptr, length);
} }
thd->lex->sql_command= oldcmd;
}
done: done:
if (table && opened) if (table && opened)
......
...@@ -365,54 +365,44 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) ...@@ -365,54 +365,44 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
void void
sp_head::reset_lex(THD *thd) sp_head::reset_lex(THD *thd)
{ {
memcpy(&m_lex, thd->lex, sizeof(LEX)); // Save old one DBUG_ENTER("sp_head::reset_lex");
LEX *sublex;
m_lex= thd->lex;
thd->lex= sublex= new st_lex;
sublex->yylineno= m_lex->yylineno;
/* Reset most stuff. The length arguments doesn't matter here. */ /* Reset most stuff. The length arguments doesn't matter here. */
lex_start(thd, m_lex.buf, m_lex.end_of_query - m_lex.ptr); lex_start(thd, m_lex->buf, m_lex->end_of_query - m_lex->ptr);
/* We must reset ptr and end_of_query again */ /* We must reset ptr and end_of_query again */
thd->lex->ptr= m_lex.ptr; sublex->ptr= m_lex->ptr;
thd->lex->end_of_query= m_lex.end_of_query; sublex->end_of_query= m_lex->end_of_query;
/* And keep the SP stuff too */ /* And keep the SP stuff too */
thd->lex->sphead = m_lex.sphead; sublex->sphead= m_lex->sphead;
thd->lex->spcont = m_lex.spcont; sublex->spcont= m_lex->spcont;
/* Clear all lists. (QQ Why isn't this reset by lex_start()?). mysql_init_query(thd, true); // Only init lex
We may be overdoing this, but we know for sure that value_list must DBUG_VOID_RETURN;
be cleared at least. */
thd->lex->col_list.empty();
thd->lex->ref_list.empty();
thd->lex->drop_list.empty();
thd->lex->alter_list.empty();
thd->lex->interval_list.empty();
thd->lex->users_list.empty();
thd->lex->columns.empty();
thd->lex->key_list.empty();
thd->lex->create_list.empty();
thd->lex->insert_list= NULL;
thd->lex->field_list.empty();
thd->lex->value_list.empty();
thd->lex->many_values.empty();
thd->lex->var_list.empty();
thd->lex->param_list.empty();
thd->lex->proc_list.empty();
thd->lex->auxilliary_table_list.empty();
} }
// Restore lex during parsing, after we have parsed a sub statement. // Restore lex during parsing, after we have parsed a sub statement.
void void
sp_head::restore_lex(THD *thd) sp_head::restore_lex(THD *thd)
{ {
DBUG_ENTER("sp_head::restore_lex");
LEX *sublex= thd->lex;
// Update some state in the old one first // Update some state in the old one first
m_lex.ptr= thd->lex->ptr; m_lex->ptr= sublex->ptr;
m_lex.next_state= thd->lex->next_state; m_lex->next_state= sublex->next_state;
// Collect some data from the sub statement lex. // Collect some data from the sub statement lex.
sp_merge_funs(&m_lex, thd->lex); sp_merge_funs(m_lex, sublex);
#if 0 #if 0
// QQ We're not using this at the moment. // QQ We're not using this at the moment.
if (thd->lex.sql_command == SQLCOM_CALL) if (sublex.sql_command == SQLCOM_CALL)
{ {
// It would be slightly faster to keep the list sorted, but we need // It would be slightly faster to keep the list sorted, but we need
// an "insert before" method to do that. // an "insert before" method to do that.
char *proc= thd->lex.udf.name.str; char *proc= sublex.udf.name.str;
List_iterator_fast<char *> li(m_calls); List_iterator_fast<char *> li(m_calls);
char **it; char **it;
...@@ -428,7 +418,7 @@ sp_head::restore_lex(THD *thd) ...@@ -428,7 +418,7 @@ sp_head::restore_lex(THD *thd)
// QQ ...or just open tables in thd->open_tables? // QQ ...or just open tables in thd->open_tables?
// This is not entirerly clear at the moment, but for now, we collect // This is not entirerly clear at the moment, but for now, we collect
// tables here. // tables here.
for (SELECT_LEX *sl= thd->lex.all_selects_list ; for (SELECT_LEX *sl= sublex.all_selects_list ;
sl ; sl ;
sl= sl->next_select()) sl= sl->next_select())
{ {
...@@ -448,7 +438,8 @@ sp_head::restore_lex(THD *thd) ...@@ -448,7 +438,8 @@ sp_head::restore_lex(THD *thd)
} }
#endif #endif
memcpy(thd->lex, &m_lex, sizeof(LEX)); // Restore lex thd->lex= m_lex;
DBUG_VOID_RETURN;
} }
void void
...@@ -490,14 +481,14 @@ int ...@@ -490,14 +481,14 @@ int
sp_instr_stmt::execute(THD *thd, uint *nextp) sp_instr_stmt::execute(THD *thd, uint *nextp)
{ {
DBUG_ENTER("sp_instr_stmt::execute"); DBUG_ENTER("sp_instr_stmt::execute");
DBUG_PRINT("info", ("command: %d", m_lex.sql_command)); DBUG_PRINT("info", ("command: %d", m_lex->sql_command));
LEX olex; // The other lex LEX *olex; // The other lex
int res; int res;
memcpy(&olex, thd->lex, sizeof(LEX)); // Save the other lex olex= thd->lex; // Save the other lex
thd->lex= m_lex; // Use my own lex
memcpy(thd->lex, &m_lex, sizeof(LEX)); // Use my own lex thd->lex->thd = thd; // QQ Not reentrant!
thd->lex->thd = thd; thd->lex->unit.thd= thd; // QQ Not reentrant
res= mysql_execute_command(thd); res= mysql_execute_command(thd);
if (thd->lock || thd->open_tables || thd->derived_tables) if (thd->lock || thd->open_tables || thd->derived_tables)
...@@ -506,7 +497,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) ...@@ -506,7 +497,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
close_thread_tables(thd); /* Free tables */ close_thread_tables(thd); /* Free tables */
} }
memcpy(thd->lex, &olex, sizeof(LEX)); // Restore the other lex thd->lex= olex; // Restore the other lex
*nextp = m_ip+1; *nextp = m_ip+1;
DBUG_RETURN(res); DBUG_RETURN(res);
......
...@@ -136,7 +136,7 @@ class sp_head : public Sql_alloc ...@@ -136,7 +136,7 @@ class sp_head : public Sql_alloc
bool m_suid; bool m_suid;
sp_pcontext *m_pcont; // Parse context sp_pcontext *m_pcont; // Parse context
LEX m_lex; // Temp. store for the other lex LEX *m_lex; // Temp. store for the other lex
DYNAMIC_ARRAY m_instr; // The "instructions" DYNAMIC_ARRAY m_instr; // The "instructions"
typedef struct typedef struct
{ {
...@@ -222,18 +222,18 @@ class sp_instr_stmt : public sp_instr ...@@ -222,18 +222,18 @@ class sp_instr_stmt : public sp_instr
inline void inline void
set_lex(LEX *lex) set_lex(LEX *lex)
{ {
memcpy(&m_lex, lex, sizeof(LEX)); m_lex= lex;
} }
inline LEX * inline LEX *
get_lex() get_lex()
{ {
return &m_lex; return m_lex;
} }
private: private:
LEX m_lex; // My own lex LEX *m_lex; // My own lex
}; // class sp_instr_stmt : public sp_instr }; // class sp_instr_stmt : public sp_instr
......
...@@ -320,7 +320,7 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -320,7 +320,7 @@ class st_select_lex_unit: public st_select_lex_node {
int exec(); int exec();
int cleanup(); int cleanup();
friend void mysql_init_query(THD *thd); friend void mysql_init_query(THD *thd, bool lexonly);
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
private: private:
bool create_total_list_n_last_return(THD *thd, st_lex *lex, bool create_total_list_n_last_return(THD *thd, st_lex *lex,
...@@ -408,7 +408,7 @@ class st_select_lex: public st_select_lex_node ...@@ -408,7 +408,7 @@ class st_select_lex: public st_select_lex_node
order_list.next= (byte**) &order_list.first; order_list.next= (byte**) &order_list.first;
} }
friend void mysql_init_query(THD *thd); friend void mysql_init_query(THD *thd, bool lexonly);
st_select_lex(struct st_lex *lex); st_select_lex(struct st_lex *lex);
st_select_lex() {} st_select_lex() {}
void make_empty_select(st_select_lex *last_select) void make_empty_select(st_select_lex *last_select)
......
...@@ -3433,7 +3433,7 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize) ...@@ -3433,7 +3433,7 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize)
****************************************************************************/ ****************************************************************************/
void void
mysql_init_query(THD *thd) mysql_init_query(THD *thd, bool lexonly)
{ {
DBUG_ENTER("mysql_init_query"); DBUG_ENTER("mysql_init_query");
LEX *lex=thd->lex; LEX *lex=thd->lex;
...@@ -3457,6 +3457,8 @@ mysql_init_query(THD *thd) ...@@ -3457,6 +3457,8 @@ mysql_init_query(THD *thd)
lex->lock_option= TL_READ; lex->lock_option= TL_READ;
lex->found_colon= 0; lex->found_colon= 0;
lex->safe_to_cache_query= 1; lex->safe_to_cache_query= 1;
if (! lexonly)
{
thd->select_number= lex->select_lex.select_number= 1; thd->select_number= lex->select_lex.select_number= 1;
thd->free_list= 0; thd->free_list= 0;
thd->total_warn_count=0; // Warnings for this query thd->total_warn_count=0; // Warnings for this query
...@@ -3468,6 +3470,7 @@ mysql_init_query(THD *thd) ...@@ -3468,6 +3470,7 @@ mysql_init_query(THD *thd)
if (opt_bin_log) if (opt_bin_log)
reset_dynamic(&thd->user_var_events); reset_dynamic(&thd->user_var_events);
thd->clear_error(); thd->clear_error();
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -3582,7 +3585,11 @@ mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -3582,7 +3585,11 @@ mysql_parse(THD *thd, char *inBuf, uint length)
else else
{ {
if (thd->net.report_error) if (thd->net.report_error)
{
send_error(thd, 0, NullS); send_error(thd, 0, NullS);
if (thd->lex->sphead)
thd->lex->sphead->destroy();
}
else else
{ {
mysql_execute_command(thd); mysql_execute_command(thd);
...@@ -3598,8 +3605,12 @@ mysql_parse(THD *thd, char *inBuf, uint length) ...@@ -3598,8 +3605,12 @@ mysql_parse(THD *thd, char *inBuf, uint length)
thd->is_fatal_error)); thd->is_fatal_error));
#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/ #ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
query_cache_abort(&thd->net); query_cache_abort(&thd->net);
if (thd->lex->sphead)
thd->lex->sphead->destroy();
#endif #endif
} }
if (thd->lex->sphead && lex != thd->lex)
thd->lex->sphead->restore_lex(thd);
thd->proc_info="freeing items"; thd->proc_info="freeing items";
free_items(thd->free_list); /* Free strings used by items */ free_items(thd->free_list); /* Free strings used by items */
lex_end(lex); lex_end(lex);
......
...@@ -71,6 +71,7 @@ Long data handling: ...@@ -71,6 +71,7 @@ Long data handling:
#include "sql_acl.h" #include "sql_acl.h"
#include "sql_select.h" // for JOIN #include "sql_select.h" // for JOIN
#include <m_ctype.h> // for isspace() #include <m_ctype.h> // for isspace()
#include "sp_head.h"
#define IS_PARAM_NULL(pos, param_no) pos[param_no/8] & (1 << param_no & 7) #define IS_PARAM_NULL(pos, param_no) pos[param_no/8] & (1 << param_no & 7)
...@@ -761,6 +762,8 @@ static bool parse_prepare_query(PREP_STMT *stmt, ...@@ -761,6 +762,8 @@ static bool parse_prepare_query(PREP_STMT *stmt,
thd->lex->param_count= 0; thd->lex->param_count= 0;
if (!yyparse((void *)thd) && !thd->is_fatal_error) if (!yyparse((void *)thd) && !thd->is_fatal_error)
error= send_prepare_results(stmt); error= send_prepare_results(stmt);
if (thd->lex->sphead && lex != thd->lex)
thd->lex->sphead->restore_lex(thd);
lex_end(lex); lex_end(lex);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment