diff options
author | unknown <konstantin@mysql.com> | 2005-06-08 19:31:34 +0400 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2005-06-08 19:31:34 +0400 |
commit | 70c0f3108609be10902139d48907d62228f284fa (patch) | |
tree | 64c32a225ecffabca687dd73a16d99da1b1717e2 | |
parent | dbfce2a55576b0a55b219110193e8fce32a78981 (diff) | |
download | mariadb-git-70c0f3108609be10902139d48907d62228f284fa.tar.gz |
Cleanup sql_prepare.cc
sql/sql_prepare.cc:
Cleanup mysql_test_* family of calls: now we don't send error message
from mysql_stmt_prepare, so no need to support -1 return code
(meaning error is not sent to client) in these functions.
Move unit->cleanup() to mysql_stmt_prepare() as it's done in most
of the mysql_test_ functions, and is a no-op for those which don't
call unit->prepare(). This should make fixing of Bug#10729 (cursors)
easier.
-rw-r--r-- | sql/sql_prepare.cc | 312 |
1 files changed, 136 insertions, 176 deletions
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 4440e542434..1d1ea37a15b 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -889,8 +889,8 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt, tables global/local table list RETURN VALUE - FALSE OK - TRUE error + FALSE success + TRUE error, error message is set in THD */ static bool mysql_test_insert(Prepared_statement *stmt, @@ -905,11 +905,10 @@ static bool mysql_test_insert(Prepared_statement *stmt, LEX *lex= stmt->lex; List_iterator_fast<List_item> its(values_list); List_item *values; - bool res; DBUG_ENTER("mysql_test_insert"); - if ((res= insert_precheck(thd, table_list))) - DBUG_RETURN(res); + if (insert_precheck(thd, table_list)) + goto error; /* open temporary memory pool for temporary data allocated by derived @@ -920,10 +919,7 @@ static bool mysql_test_insert(Prepared_statement *stmt, TL_WRITE_DELAYED as having two such locks can cause table corruption. */ if (open_normal_and_derived_tables(thd, table_list)) - { - DBUG_RETURN(TRUE); - } - + goto error; if ((values= its++)) { @@ -937,17 +933,14 @@ static bool mysql_test_insert(Prepared_statement *stmt, table_list->table->insert_values=(byte *)1; } - if ((res= mysql_prepare_insert(thd, table_list, table_list->table, - fields, values, update_fields, - update_values, duplic, - &unused_conds, FALSE))) + if (mysql_prepare_insert(thd, table_list, table_list->table, fields, + values, update_fields, update_values, duplic, + &unused_conds, FALSE)) goto error; value_count= values->elements; its.rewind(); - res= TRUE; - if (table_list->lock_type == TL_WRITE_DELAYED && !(table_list->table->file->table_flags() & HA_CAN_INSERT_DELAYED)) { @@ -968,12 +961,11 @@ static bool mysql_test_insert(Prepared_statement *stmt, goto error; } } + DBUG_RETURN(FALSE); - res= FALSE; error: - lex->unit.cleanup(); /* insert_values is cleared in open_table */ - DBUG_RETURN(res); + DBUG_RETURN(TRUE); } @@ -987,9 +979,10 @@ error: RETURN VALUE 0 success + 1 error, error message is set in THD 2 convert to multi_update - 1 error */ + static int mysql_test_update(Prepared_statement *stmt, TABLE_LIST *table_list) { @@ -1003,69 +996,60 @@ static int mysql_test_update(Prepared_statement *stmt, DBUG_ENTER("mysql_test_update"); if (update_precheck(thd, table_list)) - DBUG_RETURN(1); + goto error; + + if (open_tables(thd, &table_list, &table_count)) + goto error; - if (!open_tables(thd, &table_list, &table_count)) + if (table_list->multitable_view) { - if (table_list->multitable_view) - { - DBUG_ASSERT(table_list->view != 0); - DBUG_PRINT("info", ("Switch to multi-update")); - /* pass counter value */ - thd->lex->table_count= table_count; - /* convert to multiupdate */ - return 2; - } + DBUG_ASSERT(table_list->view != 0); + DBUG_PRINT("info", ("Switch to multi-update")); + /* pass counter value */ + thd->lex->table_count= table_count; + /* convert to multiupdate */ + DBUG_RETURN(2); + } - /* - thd->fill_derived_tables() is false here for sure (because it is - preparation of PS, so we even do not check it - */ - if (lock_tables(thd, table_list, table_count) || - mysql_handle_derived(thd->lex, &mysql_derived_prepare)) - DBUG_RETURN(1); + /* + thd->fill_derived_tables() is false here for sure (because it is + preparation of PS, so we even do not check it). + */ + if (lock_tables(thd, table_list, table_count) || + mysql_handle_derived(thd->lex, &mysql_derived_prepare)) + goto error; #ifndef NO_EMBEDDED_ACCESS_CHECKS /* TABLE_LIST contain right privilages request */ want_privilege= table_list->grant.want_privilege; #endif - if (!(res= mysql_prepare_update(thd, table_list, - &select->where, - select->order_list.elements, - (ORDER *) select->order_list.first))) - { + if (mysql_prepare_update(thd, table_list, &select->where, + select->order_list.elements, + (ORDER *) select->order_list.first)) + goto error; + #ifndef NO_EMBEDDED_ACCESS_CHECKS - table_list->grant.want_privilege= - table_list->table->grant.want_privilege= - want_privilege; + table_list->grant.want_privilege= want_privilege; + table_list->table->grant.want_privilege= want_privilege; #endif - thd->lex->select_lex.no_wrap_view_item= 1; - if (setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0)) - { - res= 1; - thd->lex->select_lex.no_wrap_view_item= 0; - } - else - { - thd->lex->select_lex.no_wrap_view_item= 0; + thd->lex->select_lex.no_wrap_view_item= 1; + res= setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0); + thd->lex->select_lex.no_wrap_view_item= 0; + if (res) + goto error; #ifndef NO_EMBEDDED_ACCESS_CHECKS - /* Check values */ - table_list->grant.want_privilege= - table_list->table->grant.want_privilege= - (SELECT_ACL & ~table_list->table->grant.privilege); + /* Check values */ + table_list->grant.want_privilege= + table_list->table->grant.want_privilege= + (SELECT_ACL & ~table_list->table->grant.privilege); #endif - if (setup_fields(thd, 0, table_list, - stmt->lex->value_list, 0, 0, 0)) - res= 1; - } - } - stmt->lex->unit.cleanup(); - } - else - res= 1; + if (setup_fields(thd, 0, table_list, stmt->lex->value_list, 0, 0, 0)) + goto error; /* TODO: here we should send types of placeholders to the client. */ - DBUG_RETURN(res); + DBUG_RETURN(0); +error: + DBUG_RETURN(1); } @@ -1079,33 +1063,29 @@ static int mysql_test_update(Prepared_statement *stmt, RETURN VALUE FALSE success - TRUE error + TRUE error, error message is set in THD */ -static int mysql_test_delete(Prepared_statement *stmt, - TABLE_LIST *table_list) + +static bool mysql_test_delete(Prepared_statement *stmt, + TABLE_LIST *table_list) { THD *thd= stmt->thd; LEX *lex= stmt->lex; DBUG_ENTER("mysql_test_delete"); - if (delete_precheck(thd, table_list)) - DBUG_RETURN(TRUE); + if (delete_precheck(thd, table_list) || + open_and_lock_tables(thd, table_list)) + goto error; - if (!open_and_lock_tables(thd, table_list)) + if (!table_list->table) { - bool res; - if (!table_list->table) - { - my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), - table_list->view_db.str, table_list->view_name.str); - DBUG_RETURN(-1); - } - - res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where); - lex->unit.cleanup(); - DBUG_RETURN(res); + my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), + table_list->view_db.str, table_list->view_name.str); + goto error; } - /* TODO: here we should send types of placeholders to the client. */ + + DBUG_RETURN(mysql_prepare_delete(thd, table_list, &lex->select_lex.where)); +error: DBUG_RETURN(TRUE); } @@ -1125,13 +1105,12 @@ static int mysql_test_delete(Prepared_statement *stmt, TRUE error, sent to client */ -static int mysql_test_select(Prepared_statement *stmt, - TABLE_LIST *tables, bool text_protocol) +static bool mysql_test_select(Prepared_statement *stmt, + TABLE_LIST *tables, bool text_protocol) { THD *thd= stmt->thd; LEX *lex= stmt->lex; SELECT_LEX_UNIT *unit= &lex->unit; - bool result; DBUG_ENTER("mysql_test_select"); #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -1139,19 +1118,20 @@ static int mysql_test_select(Prepared_statement *stmt, if (tables) { if (check_table_access(thd, privilege, tables,0)) - DBUG_RETURN(TRUE); + goto error; } else if (check_access(thd, privilege, any_db,0,0,0)) - DBUG_RETURN(TRUE); + goto error; #endif - result= TRUE; if (!lex->result && !(lex->result= new (stmt->mem_root) select_send)) - goto err; + { + my_error(ER_OUTOFMEMORY, MYF(0), sizeof(select_send)); + goto error; + } if (open_and_lock_tables(thd, tables)) - goto err; - + goto error; thd->used_tables= 0; // Updated by setup_fields @@ -1161,15 +1141,13 @@ static int mysql_test_select(Prepared_statement *stmt, usual, and we pass 0 as setup_tables_done_option */ if (unit->prepare(thd, 0, 0, "")) - { - goto err_prep; - } + goto error; if (!text_protocol) { if (lex->describe) { if (send_prep_stmt(stmt, 0) || thd->protocol->flush()) - goto err_prep; + goto error; } else { @@ -1179,7 +1157,7 @@ static int mysql_test_select(Prepared_statement *stmt, /* Change columns if a procedure like analyse() */ if (unit->last_procedure && unit->last_procedure->change_columns(fields)) - goto err_prep; + goto error; /* We can use lex->result as it should've been @@ -1188,15 +1166,12 @@ static int mysql_test_select(Prepared_statement *stmt, if (send_prep_stmt(stmt, lex->result->field_count(fields)) || lex->result->send_fields(fields, Protocol::SEND_EOF) || thd->protocol->flush()) - goto err_prep; + goto error; } } - result= FALSE; // ok - -err_prep: - unit->cleanup(); -err: - DBUG_RETURN(result); + DBUG_RETURN(FALSE); +error: + DBUG_RETURN(TRUE); } @@ -1211,26 +1186,22 @@ err: RETURN VALUE FALSE success - TRUE error, sent to client + TRUE error, error message is set in THD */ static bool mysql_test_do_fields(Prepared_statement *stmt, TABLE_LIST *tables, List<Item> *values) { - DBUG_ENTER("mysql_test_do_fields"); THD *thd= stmt->thd; - bool res; + + DBUG_ENTER("mysql_test_do_fields"); if (tables && check_table_access(thd, SELECT_ACL, tables, 0)) DBUG_RETURN(TRUE); if (open_and_lock_tables(thd, tables)) - { DBUG_RETURN(TRUE); - } - res= setup_fields(thd, 0, 0, *values, 0, 0, 0); - stmt->lex->unit.cleanup(); - DBUG_RETURN(res); + DBUG_RETURN(setup_fields(thd, 0, 0, *values, 0, 0, 0)); } @@ -1247,6 +1218,7 @@ static bool mysql_test_do_fields(Prepared_statement *stmt, FALSE success TRUE error */ + static bool mysql_test_set_fields(Prepared_statement *stmt, TABLE_LIST *tables, List<set_var_base> *var_list) @@ -1255,25 +1227,19 @@ static bool mysql_test_set_fields(Prepared_statement *stmt, List_iterator_fast<set_var_base> it(*var_list); THD *thd= stmt->thd; set_var_base *var; - bool res; - - if (tables && check_table_access(thd, SELECT_ACL, tables, 0)) - DBUG_RETURN(TRUE); - if ((res= open_and_lock_tables(thd, tables))) + if (tables && check_table_access(thd, SELECT_ACL, tables, 0) || + open_and_lock_tables(thd, tables)) goto error; + while ((var= it++)) { if (var->light_check(thd)) - { - stmt->lex->unit.cleanup(); - res= TRUE; goto error; - } } + DBUG_RETURN(FALSE); error: - stmt->lex->unit.cleanup(); - DBUG_RETURN(res); + DBUG_RETURN(TRUE); } @@ -1294,7 +1260,7 @@ error: RETURN VALUE FALSE success - TRUE error + TRUE error, error message is set in THD */ static bool select_like_stmt_test(Prepared_statement *stmt, @@ -1304,24 +1270,16 @@ static bool select_like_stmt_test(Prepared_statement *stmt, DBUG_ENTER("select_like_stmt_test"); THD *thd= stmt->thd; LEX *lex= stmt->lex; - bool res= FALSE; - if (specific_prepare && (res= (*specific_prepare)(thd))) - goto end; + if (specific_prepare && (*specific_prepare)(thd)) + DBUG_RETURN(TRUE); thd->used_tables= 0; // Updated by setup_fields - // JOIN::prepare calls - if (lex->unit.prepare(thd, 0, setup_tables_done_option, "")) - { - res= TRUE; - } -end: - lex->unit.cleanup(); - DBUG_RETURN(res); + /* Calls JOIN::prepare */ + DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option, "")); } - /* Check internal SELECT of the prepared command (with opening and locking tables used). @@ -1369,25 +1327,26 @@ select_like_stmt_test_with_open_n_lock(Prepared_statement *stmt, tables list of tables queries RETURN VALUE - 0 success - 1 error, sent to client - -1 error, not sent to client + FALSE success + TRUE error, error message is set in THD */ -static int mysql_test_create_table(Prepared_statement *stmt) +static bool mysql_test_create_table(Prepared_statement *stmt) { DBUG_ENTER("mysql_test_create_table"); THD *thd= stmt->thd; LEX *lex= stmt->lex; SELECT_LEX *select_lex= &lex->select_lex; - int res= 0; + bool res= FALSE; /* Skip first table, which is the table we are creating */ bool link_to_local; TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local); TABLE_LIST *tables= lex->query_tables; - if (!(res= create_table_precheck(thd, tables, create_table)) && - select_lex->item_list.elements) + if (create_table_precheck(thd, tables, create_table)) + DBUG_RETURN(TRUE); + + if (select_lex->item_list.elements) { select_lex->resolve_mode= SELECT_LEX::SELECT_MODE; res= select_like_stmt_test_with_open_n_lock(stmt, tables, 0, 0); @@ -1437,32 +1396,35 @@ static bool mysql_test_multiupdate(Prepared_statement *stmt, RETURN VALUE 0 success - 1 error, sent to client - -1 error, not sent to client + 1 error, error message in THD is set. */ -static int mysql_test_multidelete(Prepared_statement *stmt, + +static bool mysql_test_multidelete(Prepared_statement *stmt, TABLE_LIST *tables) { - int res; + uint fake_counter; + stmt->thd->lex->current_select= &stmt->thd->lex->select_lex; if (add_item_to_list(stmt->thd, new Item_null())) - return -1; + { + my_error(ER_OUTOFMEMORY, MYF(0), 0); + goto error; + } - uint fake_counter; - if ((res= multi_delete_precheck(stmt->thd, tables, &fake_counter))) - return res; - if ((res= select_like_stmt_test_with_open_n_lock(stmt, tables, - &mysql_multi_delete_prepare, - OPTION_SETUP_TABLES_DONE))) - return res; + if (multi_delete_precheck(stmt->thd, tables, &fake_counter) || + select_like_stmt_test_with_open_n_lock(stmt, tables, + &mysql_multi_delete_prepare, + OPTION_SETUP_TABLES_DONE)) + goto error; if (!tables->table) { my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0), tables->view_db.str, tables->view_name.str); - return -1; + goto error; } - return 0; - + return FALSE; +error: + return TRUE; } @@ -1520,8 +1482,8 @@ static int mysql_test_insert_select(Prepared_statement *stmt, tables->table->insert_values=(byte *)1; } - if ((res= insert_precheck(stmt->thd, tables))) - return res; + if (insert_precheck(stmt->thd, tables)) + return 1; /* store it, because mysql_insert_select_prepare_tester change it */ first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first; @@ -1552,12 +1514,12 @@ static int mysql_test_insert_select(Prepared_statement *stmt, by calling fix_fields. RETURN VALUE - 0 success - 1 error, sent to client + FALSE success, statement metadata is sent to client + TRUE error, error message is set (but not sent) */ -static int check_prepared_statement(Prepared_statement *stmt, - bool text_protocol) +static bool check_prepared_statement(Prepared_statement *stmt, + bool text_protocol) { THD *thd= stmt->thd; LEX *lex= stmt->lex; @@ -1583,7 +1545,7 @@ static int check_prepared_statement(Prepared_statement *stmt, case SQLCOM_UPDATE: res= mysql_test_update(stmt, tables); - /* mysql_test_update return 2 if we need to switch to multi-update */ + /* mysql_test_update returns 2 if we need to switch to multi-update */ if (res != 2) break; @@ -1599,7 +1561,7 @@ static int check_prepared_statement(Prepared_statement *stmt, if ((res= mysql_test_select(stmt, tables, text_protocol))) goto error; /* Statement and field info has already been sent */ - DBUG_RETURN(0); + DBUG_RETURN(FALSE); case SQLCOM_CREATE_TABLE: res= mysql_test_create_table(stmt); @@ -1650,18 +1612,15 @@ static int check_prepared_statement(Prepared_statement *stmt, break; default: - /* - All other is not supported yet - */ - res= -1; + /* All other statements are not supported yet. */ my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0)); goto error; } if (res == 0) - DBUG_RETURN(text_protocol? 0 : (send_prep_stmt(stmt, 0) || - thd->protocol->flush())); + DBUG_RETURN(text_protocol? FALSE : (send_prep_stmt(stmt, 0) || + thd->protocol->flush())); error: - DBUG_RETURN(1); + DBUG_RETURN(TRUE); } /* @@ -1803,6 +1762,7 @@ bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length, thd->lex->sphead= NULL; } lex_end(lex); + lex->unit.cleanup(); close_thread_tables(thd); thd->restore_backup_statement(stmt, &thd->stmt_backup); cleanup_items(stmt->free_list); |