summaryrefslogtreecommitdiff
path: root/sql/sql_prepare.cc
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2004-08-21 02:08:20 +0400
committerunknown <konstantin@mysql.com>2004-08-21 02:08:20 +0400
commit282ec5bd28ba5739f1fe5754e9031646138f3acf (patch)
tree03d527868f0af6ab03ac466e054bd64503da4a0e /sql/sql_prepare.cc
parentae99cc1f6707acd839a1e45edaf69202080411b5 (diff)
parent095b686c09f5c143abbfb99839c1d1e2810a5a35 (diff)
downloadmariadb-git-282ec5bd28ba5739f1fe5754e9031646138f3acf.tar.gz
Merge bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/home/kostja/work/mysql-4.1-4912 sql/item_cmpfunc.cc: Auto merged sql/mysql_priv.h: Auto merged sql/sql_base.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_parse.cc: Auto merged sql/sql_prepare.cc: Auto merged sql/sql_select.cc: Auto merged
Diffstat (limited to 'sql/sql_prepare.cc')
-rw-r--r--sql/sql_prepare.cc158
1 files changed, 69 insertions, 89 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 46410ca8772..850d41a030b 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -88,7 +88,6 @@ public:
uint param_count;
uint last_errno;
char last_error[MYSQL_ERRMSG_SIZE];
- bool get_longdata_error;
#ifndef EMBEDDED_LIBRARY
bool (*set_params)(Prepared_statement *st, uchar *data, uchar *data_end,
uchar *read_pos, String *expanded_query);
@@ -102,7 +101,7 @@ public:
Prepared_statement(THD *thd_arg);
virtual ~Prepared_statement();
void setup_set_params();
- virtual Statement::Type type() const;
+ virtual Item_arena::Type type() const;
};
static void execute_stmt(THD *thd, Prepared_statement *stmt,
@@ -133,7 +132,7 @@ find_prepared_statement(THD *thd, ulong id, const char *where,
{
Statement *stmt= thd->stmt_map.find(id);
- if (stmt == 0 || stmt->type() != Statement::PREPARED_STATEMENT)
+ if (stmt == 0 || stmt->type() != Item_arena::PREPARED_STATEMENT)
{
char llbuf[22];
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where);
@@ -896,10 +895,8 @@ static int mysql_test_insert(Prepared_statement *stmt,
open temporary memory pool for temporary data allocated by derived
tables & preparation procedure
*/
- thd->allocate_temporary_memory_pool_for_ps_preparing();
if (open_and_lock_tables(thd, table_list))
{
- thd->free_temporary_memory_pool_for_ps_preparing();
DBUG_RETURN(-1);
}
@@ -934,7 +931,6 @@ static int mysql_test_insert(Prepared_statement *stmt,
res= 0;
error:
lex->unit.cleanup();
- thd->free_temporary_memory_pool_for_ps_preparing();
DBUG_RETURN(res);
}
@@ -963,12 +959,6 @@ static int mysql_test_update(Prepared_statement *stmt,
if ((res= update_precheck(thd, table_list)))
DBUG_RETURN(res);
- /*
- open temporary memory pool for temporary data allocated by derived
- tables & preparation procedure
- */
- thd->allocate_temporary_memory_pool_for_ps_preparing();
-
if (open_and_lock_tables(thd, table_list))
res= -1;
else
@@ -988,7 +978,6 @@ static int mysql_test_update(Prepared_statement *stmt,
}
stmt->lex->unit.cleanup();
}
- thd->free_temporary_memory_pool_for_ps_preparing();
/* TODO: here we should send types of placeholders to the client. */
DBUG_RETURN(res);
}
@@ -1018,12 +1007,6 @@ static int mysql_test_delete(Prepared_statement *stmt,
if ((res= delete_precheck(thd, table_list)))
DBUG_RETURN(res);
- /*
- open temporary memory pool for temporary data allocated by derived
- tables & preparation procedure
- */
- thd->allocate_temporary_memory_pool_for_ps_preparing();
-
if (open_and_lock_tables(thd, table_list))
res= -1;
else
@@ -1031,7 +1014,6 @@ static int mysql_test_delete(Prepared_statement *stmt,
res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
lex->unit.cleanup();
}
- thd->free_temporary_memory_pool_for_ps_preparing();
/* TODO: here we should send types of placeholders to the client. */
DBUG_RETURN(res);
}
@@ -1073,11 +1055,6 @@ static int mysql_test_select(Prepared_statement *stmt,
DBUG_RETURN(1);
#endif
- /*
- open temporary memory pool for temporary data allocated by derived
- tables & preparation procedure
- */
- thd->allocate_temporary_memory_pool_for_ps_preparing();
if (open_and_lock_tables(thd, tables))
{
send_error(thd);
@@ -1092,33 +1069,30 @@ static int mysql_test_select(Prepared_statement *stmt,
send_error(thd);
goto err_prep;
}
- if (lex->describe)
- {
- if (!text_protocol && send_prep_stmt(stmt, 0))
- goto err_prep;
- unit->cleanup();
- }
- else
+ if (!text_protocol)
{
- if (!text_protocol)
+ if (lex->describe)
+ {
+ if (send_prep_stmt(stmt, 0))
+ goto err_prep;
+ }
+ else
{
if (send_prep_stmt(stmt, lex->select_lex.item_list.elements) ||
- thd->protocol_simple.send_fields(&lex->select_lex.item_list, 0)
+ thd->protocol_simple.send_fields(&lex->select_lex.item_list, 0)
#ifndef EMBEDDED_LIBRARY
|| net_flush(&thd->net)
#endif
)
goto err_prep;
}
- unit->cleanup();
}
- thd->free_temporary_memory_pool_for_ps_preparing();
+ unit->cleanup();
DBUG_RETURN(0);
err_prep:
unit->cleanup();
err:
- thd->free_temporary_memory_pool_for_ps_preparing();
DBUG_RETURN(1);
}
@@ -1147,19 +1121,13 @@ static int mysql_test_do_fields(Prepared_statement *stmt,
int res= 0;
if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
DBUG_RETURN(res);
- /*
- open temporary memory pool for temporary data allocated by derived
- tables & preparation procedure
- */
- thd->allocate_temporary_memory_pool_for_ps_preparing();
+
if (tables && (res= open_and_lock_tables(thd, tables)))
{
- thd->free_temporary_memory_pool_for_ps_preparing();
DBUG_RETURN(res);
}
res= setup_fields(thd, 0, 0, *values, 0, 0, 0);
stmt->lex->unit.cleanup();
- thd->free_temporary_memory_pool_for_ps_preparing();
if (res)
DBUG_RETURN(-1);
DBUG_RETURN(0);
@@ -1192,11 +1160,7 @@ static int mysql_test_set_fields(Prepared_statement *stmt,
if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
DBUG_RETURN(res);
- /*
- open temporary memory pool for temporary data allocated by derived
- tables & preparation procedure
- */
- thd->allocate_temporary_memory_pool_for_ps_preparing();
+
if (tables && (res= open_and_lock_tables(thd, tables)))
goto error;
while ((var= it++))
@@ -1210,7 +1174,6 @@ static int mysql_test_set_fields(Prepared_statement *stmt,
}
error:
stmt->lex->unit.cleanup();
- thd->free_temporary_memory_pool_for_ps_preparing();
DBUG_RETURN(res);
}
@@ -1235,11 +1198,7 @@ static int select_like_statement_test(Prepared_statement *stmt,
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
int res= 0;
- /*
- open temporary memory pool for temporary data allocated by derived
- tables & preparation procedure
- */
- thd->allocate_temporary_memory_pool_for_ps_preparing();
+
if (tables && (res= open_and_lock_tables(thd, tables)))
goto end;
@@ -1252,7 +1211,6 @@ static int select_like_statement_test(Prepared_statement *stmt,
}
end:
lex->unit.cleanup();
- thd->free_temporary_memory_pool_for_ps_preparing();
DBUG_RETURN(res);
}
@@ -1596,17 +1554,13 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
DBUG_RETURN(1);
}
- thd->stmt_backup.set_statement(thd);
- thd->stmt_backup.set_item_arena(thd);
- thd->set_statement(stmt);
- thd->set_item_arena(stmt);
+ thd->set_n_backup_statement(stmt, &thd->stmt_backup);
+ thd->set_n_backup_item_arena(stmt, &thd->stmt_backup);
if (alloc_query(thd, packet, packet_length))
{
- stmt->set_statement(thd);
- stmt->set_item_arena(thd);
- thd->set_statement(&thd->stmt_backup);
- thd->set_item_arena(&thd->stmt_backup);
+ thd->restore_backup_statement(stmt, &thd->stmt_backup);
+ thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
send_error(thd, ER_OUT_OF_RESOURCES);
@@ -1615,24 +1569,36 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
mysql_log.write(thd, COM_PREPARE, "%s", packet);
- thd->current_statement= stmt;
+ thd->current_arena= stmt;
mysql_init_query(thd, (uchar *) thd->query, thd->query_length);
lex= thd->lex;
lex->safe_to_cache_query= 0;
error= yyparse((void *)thd) || thd->is_fatal_error ||
- init_param_array(stmt) ||
- send_prepare_results(stmt, test(name));
+ init_param_array(stmt);
+ /*
+ While doing context analysis of the query (in send_prepare_results) we
+ allocate a lot of additional memory: for open tables, JOINs, derived
+ tables, etc. Let's save a snapshot of current parse tree to the
+ statement and restore original THD. In cases when some tree
+ transformation can be reused on execute, we set again thd->mem_root from
+ stmt->mem_root (see setup_wild for one place where we do that).
+ */
+ thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
+
+ if (!error)
+ error= send_prepare_results(stmt, test(name));
/* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),WAIT_PRIOR);
lex_end(lex);
- stmt->set_statement(thd);
- stmt->set_item_arena(thd);
- thd->set_statement(&thd->stmt_backup);
- thd->set_item_arena(&thd->stmt_backup);
- thd->current_statement= 0;
+ thd->restore_backup_statement(stmt, &thd->stmt_backup);
+ cleanup_items(stmt->free_list);
+ close_thread_tables(thd);
+ free_items(thd->free_list);
+ thd->free_list= 0;
+ thd->current_arena= thd;
if (error)
{
@@ -1653,7 +1619,7 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
{
sl->prep_where= sl->where;
}
-
+ stmt->state= Prepared_statement::PREPARED;
}
DBUG_RETURN(!stmt);
@@ -1767,7 +1733,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
DBUG_PRINT("exec_query:", ("%s", stmt->query));
/* Check if we got an error when sending long data */
- if (stmt->get_longdata_error)
+ if (stmt->state == Item_arena::ERROR)
{
send_error(thd, stmt->last_errno, stmt->last_error);
DBUG_VOID_RETURN;
@@ -1791,6 +1757,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
if (stmt->param_count && stmt->set_params_data(stmt, &expanded_query))
goto set_params_data_err;
#endif
+ DBUG_ASSERT(thd->free_list == NULL);
thd->protocol= &thd->protocol_prep; // Switch to binary protocol
execute_stmt(thd, stmt, &expanded_query, true);
thd->protocol= &thd->protocol_simple; // Use normal protocol
@@ -1834,9 +1801,9 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
DBUG_VOID_RETURN;
}
- thd->free_list= NULL;
- thd->stmt_backup.set_statement(thd);
- thd->set_statement(stmt);
+ DBUG_ASSERT(thd->free_list == NULL);
+
+ thd->set_n_backup_statement(stmt, &thd->stmt_backup);
if (stmt->set_params_from_vars(stmt,
thd->stmt_backup.lex->prepared_stmt_params,
&expanded_query))
@@ -1868,11 +1835,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
{
DBUG_ENTER("execute_stmt");
if (set_context)
- {
- thd->free_list= NULL;
- thd->stmt_backup.set_statement(thd);
- thd->set_statement(stmt);
- }
+ thd->set_n_backup_statement(stmt, &thd->stmt_backup);
reset_stmt_for_execute(stmt);
if (expanded_query->length() &&
@@ -1882,6 +1845,13 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
DBUG_VOID_RETURN;
}
+ /*
+ At first execution of prepared statement we will perform logical
+ transformations of the query tree (i.e. negations elimination).
+ This should be done permanently on the parse tree of this statement.
+ */
+ if (stmt->state == Item_arena::PREPARED)
+ thd->current_arena= stmt;
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
@@ -1892,6 +1862,12 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
/* Free Items that were created during this execution of the PS. */
free_items(thd->free_list);
+ thd->free_list= 0;
+ if (stmt->state == Item_arena::PREPARED)
+ {
+ thd->current_arena= thd;
+ stmt->state= Item_arena::EXECUTED;
+ }
cleanup_items(stmt->free_list);
reset_stmt_params(stmt);
close_thread_tables(thd); // to close derived tables
@@ -1929,7 +1905,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
SEND_ERROR)))
DBUG_VOID_RETURN;
- stmt->get_longdata_error= 0;
+ stmt->state= Item_arena::PREPARED;
/*
Clear parameters from data which could be set by
@@ -2017,7 +1993,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
if (param_number >= stmt->param_count)
{
/* Error will be sent in execute call */
- stmt->get_longdata_error= 1;
+ stmt->state= Item_arena::ERROR;
stmt->last_errno= ER_WRONG_ARGUMENTS;
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
"mysql_stmt_send_long_data");
@@ -2028,10 +2004,15 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
param= stmt->param_array[param_number];
#ifndef EMBEDDED_LIBRARY
- param->set_longdata(packet, (ulong) (packet_end - packet));
+ if (param->set_longdata(packet, (ulong) (packet_end - packet)))
#else
- param->set_longdata(thd->extra_data, thd->extra_length);
+ if (param->set_longdata(thd->extra_data, thd->extra_length))
#endif
+ {
+ stmt->state= Item_arena::ERROR;
+ stmt->last_errno= ER_OUTOFMEMORY;
+ sprintf(stmt->last_error, ER(ER_OUTOFMEMORY), 0);
+ }
DBUG_VOID_RETURN;
}
@@ -2041,8 +2022,7 @@ Prepared_statement::Prepared_statement(THD *thd_arg)
thd(thd_arg),
param_array(0),
param_count(0),
- last_errno(0),
- get_longdata_error(0)
+ last_errno(0)
{
*last_error= '\0';
}
@@ -2076,7 +2056,7 @@ Prepared_statement::~Prepared_statement()
}
-Statement::Type Prepared_statement::type() const
+Item_arena::Type Prepared_statement::type() const
{
return PREPARED_STATEMENT;
}