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;
drop procedure zip;
drop procedure zap;
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)
begin
call inc2(x2, y);
......
......@@ -126,6 +126,24 @@ drop procedure zap|
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
create procedure iotest(x1 char(16), x2 char(16), y int)
begin
......
......@@ -353,7 +353,7 @@ bool is_update_query(enum enum_sql_command command);
void free_items(Item *item);
bool alloc_query(THD *thd, char *packet, ulong packet_length);
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);
void create_select_for_variable(const char *var_name);
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)
DBUG_ENTER("db_find_routine");
DBUG_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
extern int yyparse(void *thd);
LEX *tmplex;
TABLE *table;
const char *defstr;
int ret;
......@@ -146,16 +145,30 @@ db_find_routine(THD *thd, int type, char *name, uint namelen, sp_head **sphp)
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;
}
else
{
*sphp= tmplex->sphead;
*sphp= thd->lex->sphead;
(*sphp)->sp_set_info((char *) creator, (uint) strlen(creator),
created, modified, suid,
ptr, length);
}
thd->lex->sql_command= oldcmd;
}
done:
if (table && opened)
......
......@@ -365,54 +365,44 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
void
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. */
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 */
thd->lex->ptr= m_lex.ptr;
thd->lex->end_of_query= m_lex.end_of_query;
sublex->ptr= m_lex->ptr;
sublex->end_of_query= m_lex->end_of_query;
/* And keep the SP stuff too */
thd->lex->sphead = m_lex.sphead;
thd->lex->spcont = m_lex.spcont;
/* Clear all lists. (QQ Why isn't this reset by lex_start()?).
We may be overdoing this, but we know for sure that value_list must
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();
sublex->sphead= m_lex->sphead;
sublex->spcont= m_lex->spcont;
mysql_init_query(thd, true); // Only init lex
DBUG_VOID_RETURN;
}
// Restore lex during parsing, after we have parsed a sub statement.
void
sp_head::restore_lex(THD *thd)
{
DBUG_ENTER("sp_head::restore_lex");
LEX *sublex= thd->lex;
// Update some state in the old one first
m_lex.ptr= thd->lex->ptr;
m_lex.next_state= thd->lex->next_state;
m_lex->ptr= sublex->ptr;
m_lex->next_state= sublex->next_state;
// Collect some data from the sub statement lex.
sp_merge_funs(&m_lex, thd->lex);
sp_merge_funs(m_lex, sublex);
#if 0
// 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
// 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);
char **it;
......@@ -428,7 +418,7 @@ sp_head::restore_lex(THD *thd)
// QQ ...or just open tables in thd->open_tables?
// This is not entirerly clear at the moment, but for now, we collect
// tables here.
for (SELECT_LEX *sl= thd->lex.all_selects_list ;
for (SELECT_LEX *sl= sublex.all_selects_list ;
sl ;
sl= sl->next_select())
{
......@@ -448,7 +438,8 @@ sp_head::restore_lex(THD *thd)
}
#endif
memcpy(thd->lex, &m_lex, sizeof(LEX)); // Restore lex
thd->lex= m_lex;
DBUG_VOID_RETURN;
}
void
......@@ -490,14 +481,14 @@ int
sp_instr_stmt::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_stmt::execute");
DBUG_PRINT("info", ("command: %d", m_lex.sql_command));
LEX olex; // The other lex
DBUG_PRINT("info", ("command: %d", m_lex->sql_command));
LEX *olex; // The other lex
int res;
memcpy(&olex, thd->lex, sizeof(LEX)); // Save the other lex
memcpy(thd->lex, &m_lex, sizeof(LEX)); // Use my own lex
thd->lex->thd = thd;
olex= thd->lex; // Save the other lex
thd->lex= m_lex; // Use my own lex
thd->lex->thd = thd; // QQ Not reentrant!
thd->lex->unit.thd= thd; // QQ Not reentrant
res= mysql_execute_command(thd);
if (thd->lock || thd->open_tables || thd->derived_tables)
......@@ -506,7 +497,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
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;
DBUG_RETURN(res);
......
......@@ -136,7 +136,7 @@ class sp_head : public Sql_alloc
bool m_suid;
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"
typedef struct
{
......@@ -222,18 +222,18 @@ class sp_instr_stmt : public sp_instr
inline void
set_lex(LEX *lex)
{
memcpy(&m_lex, lex, sizeof(LEX));
m_lex= lex;
}
inline LEX *
get_lex()
{
return &m_lex;
return m_lex;
}
private:
LEX m_lex; // My own lex
LEX *m_lex; // My own lex
}; // class sp_instr_stmt : public sp_instr
......
......@@ -320,7 +320,7 @@ class st_select_lex_unit: public st_select_lex_node {
int exec();
int cleanup();
friend void mysql_init_query(THD *thd);
friend void mysql_init_query(THD *thd, bool lexonly);
friend int subselect_union_engine::exec();
private:
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
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() {}
void make_empty_select(st_select_lex *last_select)
......
......@@ -3433,7 +3433,7 @@ bool my_yyoverflow(short **yyss, YYSTYPE **yyvs, int *yystacksize)
****************************************************************************/
void
mysql_init_query(THD *thd)
mysql_init_query(THD *thd, bool lexonly)
{
DBUG_ENTER("mysql_init_query");
LEX *lex=thd->lex;
......@@ -3457,6 +3457,8 @@ mysql_init_query(THD *thd)
lex->lock_option= TL_READ;
lex->found_colon= 0;
lex->safe_to_cache_query= 1;
if (! lexonly)
{
thd->select_number= lex->select_lex.select_number= 1;
thd->free_list= 0;
thd->total_warn_count=0; // Warnings for this query
......@@ -3468,6 +3470,7 @@ mysql_init_query(THD *thd)
if (opt_bin_log)
reset_dynamic(&thd->user_var_events);
thd->clear_error();
}
DBUG_VOID_RETURN;
}
......@@ -3582,7 +3585,11 @@ mysql_parse(THD *thd, char *inBuf, uint length)
else
{
if (thd->net.report_error)
{
send_error(thd, 0, NullS);
if (thd->lex->sphead)
thd->lex->sphead->destroy();
}
else
{
mysql_execute_command(thd);
......@@ -3598,8 +3605,12 @@ mysql_parse(THD *thd, char *inBuf, uint length)
thd->is_fatal_error));
#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
query_cache_abort(&thd->net);
if (thd->lex->sphead)
thd->lex->sphead->destroy();
#endif
}
if (thd->lex->sphead && lex != thd->lex)
thd->lex->sphead->restore_lex(thd);
thd->proc_info="freeing items";
free_items(thd->free_list); /* Free strings used by items */
lex_end(lex);
......
......@@ -71,6 +71,7 @@ Long data handling:
#include "sql_acl.h"
#include "sql_select.h" // for JOIN
#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)
......@@ -761,6 +762,8 @@ static bool parse_prepare_query(PREP_STMT *stmt,
thd->lex->param_count= 0;
if (!yyparse((void *)thd) && !thd->is_fatal_error)
error= send_prepare_results(stmt);
if (thd->lex->sphead && lex != thd->lex)
thd->lex->sphead->restore_lex(thd);
lex_end(lex);
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