diff options
author | unknown <konstantin@mysql.com> | 2004-08-21 02:08:20 +0400 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2004-08-21 02:08:20 +0400 |
commit | 282ec5bd28ba5739f1fe5754e9031646138f3acf (patch) | |
tree | 03d527868f0af6ab03ac466e054bd64503da4a0e /sql/sql_prepare.cc | |
parent | ae99cc1f6707acd839a1e45edaf69202080411b5 (diff) | |
parent | 095b686c09f5c143abbfb99839c1d1e2810a5a35 (diff) | |
download | mariadb-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.cc | 158 |
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; } |