summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorpem@mysql.com <>2003-05-23 15:32:31 +0200
committerpem@mysql.com <>2003-05-23 15:32:31 +0200
commit4523a7b179d3ef869ec232dc54cda653b3ab1abf (patch)
treebf6e2f760151613d8a7067a4374ba87418c81ee7 /sql
parent384b10e2af883845179cbc2e4b8825a4d6adeddc (diff)
downloadmariadb-git-4523a7b179d3ef869ec232dc54cda653b3ab1abf.tar.gz
Adopt SP stuff to the new lex pointer.
Diffstat (limited to 'sql')
-rw-r--r--sql/mysql_priv.h2
-rw-r--r--sql/sp.cc31
-rw-r--r--sql/sp_head.cc71
-rw-r--r--sql/sp_head.h8
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_parse.cc35
-rw-r--r--sql/sql_prepare.cc3
7 files changed, 86 insertions, 68 deletions
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 64b84858282..57a7fd0f553 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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);
diff --git a/sql/sp.cc b/sql/sp.cc
index b1b73f30811..5c87488bcda 100644
--- a/sql/sp.cc
+++ b/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_PRINT("enter", ("type: %d name: %*s", type, namelen, name));
extern int yyparse(void *thd);
- LEX *tmplex;
TABLE *table;
const char *defstr;
int ret;
@@ -146,15 +145,29 @@ 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)
- ret= SP_PARSE_ERROR;
- else
{
- *sphp= tmplex->sphead;
- (*sphp)->sp_set_info((char *) creator, (uint) strlen(creator),
- created, modified, suid,
- ptr, length);
+ 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= thd->lex->sphead;
+ (*sphp)->sp_set_info((char *) creator, (uint) strlen(creator),
+ created, modified, suid,
+ ptr, length);
+ }
+ thd->lex->sql_command= oldcmd;
}
done:
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 15a85173f8f..96624430307 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -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);
diff --git a/sql/sp_head.h b/sql/sp_head.h
index d5bf7138785..f25e141cd18 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -136,7 +136,7 @@ private:
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 @@ public:
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
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index ecf04c1575c..09cbe107ffa 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -320,7 +320,7 @@ public:
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 @@ public:
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)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d1b9fecee35..e434524957e 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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,17 +3457,20 @@ mysql_init_query(THD *thd)
lex->lock_option= TL_READ;
lex->found_colon= 0;
lex->safe_to_cache_query= 1;
- thd->select_number= lex->select_lex.select_number= 1;
- thd->free_list= 0;
- thd->total_warn_count=0; // Warnings for this query
- thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
- thd->sent_row_count= thd->examined_row_count= 0;
- thd->is_fatal_error= thd->rand_used= 0;
- thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
- thd->tmp_table_used= 0;
- if (opt_bin_log)
- reset_dynamic(&thd->user_var_events);
- thd->clear_error();
+ if (! lexonly)
+ {
+ thd->select_number= lex->select_lex.select_number= 1;
+ thd->free_list= 0;
+ thd->total_warn_count=0; // Warnings for this query
+ thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
+ thd->sent_row_count= thd->examined_row_count= 0;
+ thd->is_fatal_error= thd->rand_used= 0;
+ thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ thd->tmp_table_used= 0;
+ 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);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 43376012d4c..bd0a3a09422 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -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);
}