mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Adopt SP stuff to the new lex pointer.
This commit is contained in:
@ -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|
|
|||||||
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);
|
|||||||
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);
|
||||||
|
31
sql/sp.cc
31
sql/sp.cc
@ -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,15 +145,29 @@ 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)
|
|
||||||
ret= SP_PARSE_ERROR;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
*sphp= tmplex->sphead;
|
LEX *oldlex= thd->lex;
|
||||||
(*sphp)->sp_set_info((char *) creator, (uint) strlen(creator),
|
enum enum_sql_command oldcmd= thd->lex->sql_command;
|
||||||
created, modified, suid,
|
|
||||||
ptr, length);
|
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= thd->lex->sphead;
|
||||||
|
(*sphp)->sp_set_info((char *) creator, (uint) strlen(creator),
|
||||||
|
created, modified, suid,
|
||||||
|
ptr, length);
|
||||||
|
}
|
||||||
|
thd->lex->sql_command= oldcmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
@ -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)
|
|||||||
// 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)
|
|||||||
}
|
}
|
||||||
#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
|
|||||||
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)
|
|||||||
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 @@ private:
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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 @@ public:
|
|||||||
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)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
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,17 +3457,20 @@ 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;
|
||||||
thd->select_number= lex->select_lex.select_number= 1;
|
if (! lexonly)
|
||||||
thd->free_list= 0;
|
{
|
||||||
thd->total_warn_count=0; // Warnings for this query
|
thd->select_number= lex->select_lex.select_number= 1;
|
||||||
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
|
thd->free_list= 0;
|
||||||
thd->sent_row_count= thd->examined_row_count= 0;
|
thd->total_warn_count=0; // Warnings for this query
|
||||||
thd->is_fatal_error= thd->rand_used= 0;
|
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
|
||||||
thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
|
thd->sent_row_count= thd->examined_row_count= 0;
|
||||||
thd->tmp_table_used= 0;
|
thd->is_fatal_error= thd->rand_used= 0;
|
||||||
if (opt_bin_log)
|
thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
|
||||||
reset_dynamic(&thd->user_var_events);
|
thd->tmp_table_used= 0;
|
||||||
thd->clear_error();
|
if (opt_bin_log)
|
||||||
|
reset_dynamic(&thd->user_var_events);
|
||||||
|
thd->clear_error();
|
||||||
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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)
|
|||||||
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:
|
|||||||
#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,
|
|||||||
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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user