The world's most popular open source database
#include "mysql_priv.h"#include "sql_repl.h"#include "rpl_filter.h"#include "repl_failsafe.h"#include <m_ctype.h>#include <myisam.h>#include <my_dir.h>#include "sp_head.h"#include "sp.h"#include "sp_cache.h"#include "events.h"#include "event_timed.h"Include dependency graph for sql_parse.cc:

Go to the source code of this file.
Defines | |
| #define | MYSQL_LEX 1 |
| #define | MIN_HANDSHAKE_SIZE 6 |
| #define | SP_TYPE_STRING(LP) ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE") |
| #define | SP_COM_STRING(LP) |
| #define | used_stack(A, B) (long) (B - A) |
| #define | MY_YACC_INIT 1000 |
| #define | MY_YACC_MAX 32000 |
Functions | |
| static void | time_out_user_resource_limits (THD *thd, USER_CONN *uc) |
| static int | check_for_max_user_connections (THD *thd, USER_CONN *uc) |
| static void | decrease_user_connections (USER_CONN *uc) |
| static bool | check_multi_update_lock (THD *thd) |
| static void | remove_escape (char *name) |
| static bool | execute_sqlcom_select (THD *thd, TABLE_LIST *all_tables) |
| static void | unlock_locked_tables (THD *thd) |
| bool | end_active_trans (THD *thd) |
| bool | begin_trans (THD *thd) |
| static bool | some_non_temp_table_to_be_updated (THD *thd, TABLE_LIST *tables) |
| static int | get_or_create_user_conn (THD *thd, const char *user, const char *host, USER_RESOURCES *mqh) |
| int | check_user (THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count) |
| byte * | get_key_conn (user_conn *buff, uint *length, my_bool not_used __attribute__((unused))) |
| void | free_user (struct user_conn *uc) |
| void | init_max_user_conn (void) |
| void | free_max_user_conn (void) |
| void | init_update_queries (void) |
| bool | is_update_query (enum enum_sql_command command) |
| static bool | check_mqh (THD *thd, uint check_command) |
| static void | reset_mqh (LEX_USER *lu, bool get_them=0) |
| void | thd_init_client_charset (THD *thd, uint cs_number) |
| static int | check_connection (THD *thd) |
| void | execute_init_command (THD *thd, sys_var_str *init_command_var, rw_lock_t *var_mutex) |
| pthread_handler_t | handle_one_connection (void *arg) |
| pthread_handler_t | handle_bootstrap (void *arg) |
| void | free_items (Item *item) |
| void | cleanup_items (Item *item) |
| static int | mysql_table_dump (THD *thd, char *db, char *tbl_name) |
| int | end_trans (THD *thd, enum enum_mysql_completiontype completion) |
| bool | do_command (THD *thd) |
| bool | dispatch_command (enum enum_server_command command, THD *thd, char *packet, uint packet_length) |
| void | log_slow_statement (THD *thd) |
| int | prepare_schema_table (THD *thd, LEX *lex, Table_ident *table_ident, enum enum_schema_tables schema_table_idx) |
| bool | alloc_query (THD *thd, const char *packet, uint packet_length) |
| static void | reset_one_shot_variables (THD *thd) |
| bool | mysql_execute_command (THD *thd) |
| bool | check_single_table_access (THD *thd, ulong privilege, TABLE_LIST *all_tables) |
| bool | check_one_table_access (THD *thd, ulong privilege, TABLE_LIST *all_tables) |
| bool | check_access (THD *thd, ulong want_access, const char *db, ulong *save_priv, bool dont_check_global_grants, bool no_errors, bool schema_db) |
| bool | check_global_access (THD *thd, ulong want_access) |
| bool | check_table_access (THD *thd, ulong want_access, TABLE_LIST *tables, bool no_errors) |
| bool | check_routine_access (THD *thd, ulong want_access, char *db, char *name, bool is_proc, bool no_errors) |
| bool | check_some_routine_access (THD *thd, const char *db, const char *name, bool is_proc) |
| bool | check_some_access (THD *thd, ulong want_access, TABLE_LIST *table) |
| bool | check_merge_table_access (THD *thd, char *db, TABLE_LIST *table_list) |
| bool | check_stack_overrun (THD *thd, long margin, char *buf __attribute__((unused))) |
| bool | my_yyoverflow (short **yyss, YYSTYPE **yyvs, ulong *yystacksize) |
| void | mysql_init_query (THD *thd, uchar *buf, uint length) |
| void | mysql_reset_thd_for_next_command (THD *thd) |
| void | mysql_init_select (LEX *lex) |
| 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) |
| void | mysql_parse (THD *thd, char *inBuf, uint length) |
| bool | add_field_to_list (THD *thd, char *field_name, enum_field_types type, char *length, char *decimals, uint type_modifier, Item *default_value, Item *on_update_value, LEX_STRING *comment, char *change, List< String > *interval_list, CHARSET_INFO *cs, uint uint_geom_type) |
| void | store_position_for_column (const char *name) |
| bool | add_proc_to_list (THD *thd, Item *item) |
| bool | add_to_list (THD *thd, SQL_LIST &list, Item *item, bool asc) |
| bool | push_new_name_resolution_context (THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op) |
| void | add_join_on (TABLE_LIST *b, Item *expr) |
| void | add_join_natural (TABLE_LIST *a, TABLE_LIST *b, List< String > *using_fields) |
| bool | reload_acl_and_cache (THD *thd, ulong options, TABLE_LIST *tables, bool *write_to_binlog) |
| uint | kill_one_thread (THD *thd, ulong id, bool only_kill_query) |
| void | sql_kill (THD *thd, ulong id, bool only_kill_query) |
| bool | append_file_to_dir (THD *thd, const char **filename_ptr, const char *table_name) |
| bool | check_simple_select () |
| Comp_creator * | comp_eq_creator (bool invert) |
| Comp_creator * | comp_ge_creator (bool invert) |
| Comp_creator * | comp_gt_creator (bool invert) |
| Comp_creator * | comp_le_creator (bool invert) |
| Comp_creator * | comp_lt_creator (bool invert) |
| Comp_creator * | comp_ne_creator (bool invert) |
| Item * | all_any_subquery_creator (Item *left_expr, chooser_compare_func_creator cmp, bool all, SELECT_LEX *select_lex) |
| bool | mysql_create_index (THD *thd, TABLE_LIST *table_list, List< Key > &keys) |
| bool | mysql_drop_index (THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info) |
| bool | multi_update_precheck (THD *thd, TABLE_LIST *tables) |
| bool | multi_delete_precheck (THD *thd, TABLE_LIST *tables) |
| bool | multi_delete_set_locks_and_link_aux_tables (LEX *lex) |
| bool | update_precheck (THD *thd, TABLE_LIST *tables) |
| bool | delete_precheck (THD *thd, TABLE_LIST *tables) |
| bool | insert_precheck (THD *thd, TABLE_LIST *tables) |
| bool | create_table_precheck (THD *thd, TABLE_LIST *tables, TABLE_LIST *create_table) |
| Item * | negate_expression (THD *thd, Item *expr) |
| void | get_default_definer (THD *thd, LEX_USER *definer) |
| LEX_USER * | create_default_definer (THD *thd) |
| LEX_USER * | create_definer (THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) |
| LEX_USER * | get_current_user (THD *thd, LEX_USER *user) |
Variables | |
| const char * | any_db = "*any*" |
| const LEX_STRING | command_name [] |
| const char * | xa_state_names [] |
| static HASH | hash_user_connections |
| uint | sql_command_flags [SQLCOM_END+1] |
| long | max_stack_used |
| #define MIN_HANDSHAKE_SIZE 6 |
Definition at line 47 of file sql_parse.cc.
Referenced by check_connection(), and Mysql_connection_thread::check_connection().
| #define MY_YACC_INIT 1000 |
| #define MY_YACC_MAX 32000 |
| #define MYSQL_LEX 1 |
Definition at line 17 of file sql_parse.cc.
| #define SP_COM_STRING | ( | LP | ) |
Value:
((LP)->sql_command == SQLCOM_CREATE_SPFUNCTION || \ (LP)->sql_command == SQLCOM_ALTER_FUNCTION || \ (LP)->sql_command == SQLCOM_SHOW_CREATE_FUNC || \ (LP)->sql_command == SQLCOM_DROP_FUNCTION ? \ "FUNCTION" : "PROCEDURE")
Definition at line 53 of file sql_parse.cc.
Referenced by mysql_execute_command().
| #define SP_TYPE_STRING | ( | LP | ) | ((LP)->sphead->m_type == TYPE_ENUM_FUNCTION ? "FUNCTION" : "PROCEDURE") |
| bool add_field_to_list | ( | THD * | thd, | |
| char * | field_name, | |||
| enum_field_types | type, | |||
| char * | length, | |||
| char * | decimals, | |||
| uint | type_modifier, | |||
| Item * | default_value, | |||
| Item * | on_update_value, | |||
| LEX_STRING * | comment, | |||
| char * | change, | |||
| List< String > * | interval_list, | |||
| CHARSET_INFO * | cs, | |||
| uint | uint_geom_type | |||
| ) |
Definition at line 6156 of file sql_parse.cc.
References AUTO_INCREMENT_FLAG, buf, comment, DBUG_ENTER, DBUG_RETURN, default_key_create_info, ER_INVALID_DEFAULT, ER_INVALID_ON_UPDATE, ER_TOO_LONG_IDENT, FIELD_TYPE_TIMESTAMP, Item::FUNC_ITEM, create_field::init(), my_error(), my_snprintf(), MYF, NAME_LEN, NOT_NULL_FLAG, Item_func::NOW_FUNC, Item::NULL_ITEM, NullS, PRI_KEY_FLAG, Key::PRIMARY, strlen(), Item::type(), Key::UNIQUE, UNIQUE_FLAG, UNIQUE_KEY_FLAG, and WARN_DEPRECATED.
06164 { 06165 register create_field *new_field; 06166 LEX *lex= thd->lex; 06167 DBUG_ENTER("add_field_to_list"); 06168 06169 if (strlen(field_name) > NAME_LEN) 06170 { 06171 my_error(ER_TOO_LONG_IDENT, MYF(0), field_name); /* purecov: inspected */ 06172 DBUG_RETURN(1); /* purecov: inspected */ 06173 } 06174 if (type_modifier & PRI_KEY_FLAG) 06175 { 06176 lex->col_list.push_back(new key_part_spec(field_name,0)); 06177 lex->key_list.push_back(new Key(Key::PRIMARY, NullS, 06178 &default_key_create_info, 06179 0, lex->col_list)); 06180 lex->col_list.empty(); 06181 } 06182 if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG)) 06183 { 06184 lex->col_list.push_back(new key_part_spec(field_name,0)); 06185 lex->key_list.push_back(new Key(Key::UNIQUE, NullS, 06186 &default_key_create_info, 0, 06187 lex->col_list)); 06188 lex->col_list.empty(); 06189 } 06190 06191 if (default_value) 06192 { 06193 /* 06194 Default value should be literal => basic constants => 06195 no need fix_fields() 06196 06197 We allow only one function as part of default value - 06198 NOW() as default for TIMESTAMP type. 06199 */ 06200 if (default_value->type() == Item::FUNC_ITEM && 06201 !(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC && 06202 type == FIELD_TYPE_TIMESTAMP)) 06203 { 06204 my_error(ER_INVALID_DEFAULT, MYF(0), field_name); 06205 DBUG_RETURN(1); 06206 } 06207 else if (default_value->type() == Item::NULL_ITEM) 06208 { 06209 default_value= 0; 06210 if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) == 06211 NOT_NULL_FLAG) 06212 { 06213 my_error(ER_INVALID_DEFAULT, MYF(0), field_name); 06214 DBUG_RETURN(1); 06215 } 06216 } 06217 else if (type_modifier & AUTO_INCREMENT_FLAG) 06218 { 06219 my_error(ER_INVALID_DEFAULT, MYF(0), field_name); 06220 DBUG_RETURN(1); 06221 } 06222 } 06223 06224 if (on_update_value && type != FIELD_TYPE_TIMESTAMP) 06225 { 06226 my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name); 06227 DBUG_RETURN(1); 06228 } 06229 06230 if (type == FIELD_TYPE_TIMESTAMP && length) 06231 { 06232 /* Display widths are no longer supported for TIMSTAMP as of MySQL 4.1. 06233 In other words, for declarations such as TIMESTAMP(2), TIMESTAMP(4), 06234 and so on, the display width is ignored. 06235 */ 06236 char buf[32]; 06237 my_snprintf(buf, sizeof(buf), "TIMESTAMP(%s)", length); 06238 WARN_DEPRECATED(thd, "5.2", buf, "'TIMESTAMP'"); 06239 } 06240 06241 if (!(new_field= new create_field()) || 06242 new_field->init(thd, field_name, type, length, decimals, type_modifier, 06243 default_value, on_update_value, comment, change, 06244 interval_list, cs, uint_geom_type)) 06245 DBUG_RETURN(1); 06246 06247 lex->create_list.push_back(new_field); 06248 lex->last_field=new_field; 06249 DBUG_RETURN(0); 06250 }
Here is the call graph for this function:

| void add_join_natural | ( | TABLE_LIST * | a, | |
| TABLE_LIST * | b, | |||
| List< String > * | using_fields | |||
| ) |
Definition at line 6912 of file sql_parse.cc.
References st_table_list::join_using_fields, and st_table_list::natural_join.
06913 { 06914 b->natural_join= a; 06915 b->join_using_fields= using_fields; 06916 }
| void add_join_on | ( | TABLE_LIST * | b, | |
| Item * | expr | |||
| ) |
Definition at line 6855 of file sql_parse.cc.
References st_table_list::on_expr, and Item::top_level_item().
Referenced by mark_common_columns().
06856 { 06857 if (expr) 06858 { 06859 if (!b->on_expr) 06860 b->on_expr= expr; 06861 else 06862 { 06863 /* 06864 If called from the parser, this happens if you have both a 06865 right and left join. If called later, it happens if we add more 06866 than one condition to the ON clause. 06867 */ 06868 b->on_expr= new Item_cond_and(b->on_expr,expr); 06869 } 06870 b->on_expr->top_level_item(); 06871 } 06872 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 6261 of file sql_parse.cc.
References order.
06262 { 06263 ORDER *order; 06264 Item **item_ptr; 06265 06266 if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)+sizeof(Item*)))) 06267 return 1; 06268 item_ptr = (Item**) (order+1); 06269 *item_ptr= item; 06270 order->item=item_ptr; 06271 order->free_me=0; 06272 thd->lex->proc_list.link_in_list((byte*) order,(byte**) &order->next); 06273 return 0; 06274 }
Definition at line 6312 of file sql_parse.cc.
References DBUG_ENTER, DBUG_RETURN, list(), and order.
Referenced by trx_undo_mem_create_at_db_start().
06313 { 06314 ORDER *order; 06315 DBUG_ENTER("add_to_list"); 06316 if (!(order = (ORDER *) thd->alloc(sizeof(ORDER)))) 06317 DBUG_RETURN(1); 06318 order->item_ptr= item; 06319 order->item= &order->item_ptr; 06320 order->asc = asc; 06321 order->free_me=0; 06322 order->used=0; 06323 order->counter_used= 0; 06324 list.link_in_list((byte*) order,(byte**) &order->next); 06325 DBUG_RETURN(0); 06326 }
Here is the call graph for this function:

Here is the caller graph for this function:

| Item* all_any_subquery_creator | ( | Item * | left_expr, | |
| chooser_compare_func_creator | cmp, | |||
| bool | all, | |||
| SELECT_LEX * | select_lex | |||
| ) |
Definition at line 7282 of file sql_parse.cc.
References comp_eq_creator(), comp_ne_creator(), and Item_in_subselect::upper_item.
07286 { 07287 if ((cmp == &comp_eq_creator) && !all) // = ANY <=> IN 07288 return new Item_in_subselect(left_expr, select_lex); 07289 07290 if ((cmp == &comp_ne_creator) && all) // <> ALL <=> NOT IN 07291 return new Item_func_not(new Item_in_subselect(left_expr, select_lex)); 07292 07293 Item_allany_subselect *it= 07294 new Item_allany_subselect(left_expr, cmp, select_lex, all); 07295 if (all) 07296 return it->upper_item= new Item_func_not_all(it); /* ALL */ 07297 07298 return it->upper_item= new Item_func_nop_all(it); /* ANY/SOME */ 07299 }
Here is the call graph for this function:

Definition at line 2397 of file sql_parse.cc.
References FALSE, my_isspace, pos(), and TRUE.
Referenced by dispatch_command(), Prepared_statement::execute(), sp_instr_stmt::execute(), and Prepared_statement::prepare().
02398 { 02399 packet_length--; // Remove end null 02400 /* Remove garbage at start and end of query */ 02401 while (my_isspace(thd->charset(),packet[0]) && packet_length > 0) 02402 { 02403 packet++; 02404 packet_length--; 02405 } 02406 const char *pos= packet + packet_length; // Point at end null 02407 while (packet_length > 0 && 02408 (pos[-1] == ';' || my_isspace(thd->charset() ,pos[-1]))) 02409 { 02410 pos--; 02411 packet_length--; 02412 } 02413 /* We must allocate some extra memory for query cache */ 02414 thd->query_length= 0; // Extra safety: Avoid races 02415 if (!(thd->query= (char*) thd->memdup_w_gap((gptr) (packet), 02416 packet_length, 02417 thd->db_length+ 1 + 02418 QUERY_CACHE_FLAGS_SIZE))) 02419 return TRUE; 02420 thd->query[packet_length]=0; 02421 thd->query_length= packet_length; 02422 02423 /* Reclaim some memory */ 02424 thd->packet.shrink(thd->variables.net_buffer_length); 02425 thd->convert_buffer.shrink(thd->variables.net_buffer_length); 02426 02427 return FALSE; 02428 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool append_file_to_dir | ( | THD * | thd, | |
| const char ** | filename_ptr, | |||
| const char * | table_name | |||
| ) |
Definition at line 7181 of file sql_parse.cc.
References convert_dirname(), ER_WRONG_TABLE_NAME, FN_REFLEN, my_error(), MYF, NullS, strlen(), strmov(), strxmov(), and test_if_hard_path().
Referenced by mysql_execute_command().
07183 { 07184 char buff[FN_REFLEN],*ptr, *end; 07185 if (!*filename_ptr) 07186 return 0; // nothing to do 07187 07188 /* Check that the filename is not too long and it's a hard path */ 07189 if (strlen(*filename_ptr)+strlen(table_name) >= FN_REFLEN-1 || 07190 !test_if_hard_path(*filename_ptr)) 07191 { 07192 my_error(ER_WRONG_TABLE_NAME, MYF(0), *filename_ptr); 07193 return 1; 07194 } 07195 /* Fix is using unix filename format on dos */ 07196 strmov(buff,*filename_ptr); 07197 end=convert_dirname(buff, *filename_ptr, NullS); 07198 if (!(ptr=thd->alloc((uint) (end-buff)+(uint) strlen(table_name)+1))) 07199 return 1; // End of memory 07200 *filename_ptr=ptr; 07201 strxmov(ptr,buff,table_name,NullS); 07202 return 0; 07203 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool begin_trans | ( | THD * | thd | ) |
Definition at line 170 of file sql_parse.cc.
References close_thread_tables(), end_active_trans(), ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, error, ha_start_consistent_snapshot(), my_error(), MYF, MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT, OPTION_BEGIN, SERVER_STATUS_IN_TRANS, and unlikely.
00171 { 00172 int error=0; 00173 if (unlikely(thd->in_sub_stmt)) 00174 { 00175 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); 00176 return 1; 00177 } 00178 if (thd->locked_tables) 00179 { 00180 thd->lock=thd->locked_tables; 00181 thd->locked_tables=0; // Will be automatically closed 00182 close_thread_tables(thd); // Free tables 00183 } 00184 if (end_active_trans(thd)) 00185 error= -1; 00186 else 00187 { 00188 LEX *lex= thd->lex; 00189 thd->options|= OPTION_BEGIN; 00190 thd->server_status|= SERVER_STATUS_IN_TRANS; 00191 if (lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) 00192 error= ha_start_consistent_snapshot(thd); 00193 } 00194 return error; 00195 }
Here is the call graph for this function:

| bool check_access | ( | THD * | thd, | |
| ulong | want_access, | |||
| const char * | db, | |||
| ulong * | save_priv, | |||
| bool | dont_check_global_grants, | |||
| bool | no_errors, | |||
| bool | schema_db | |||
| ) |
Definition at line 5387 of file sql_parse.cc.
References acl_get(), any_db, DB_ACLS, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ER, ER_ACCESS_DENIED_ERROR, ER_DBACCESS_DENIED_ERROR, ER_NO, ER_NO_DB_ERROR, ER_YES, EXTRA_ACL, FALSE, GRANT_ACL, grant_option, my_error(), my_message(), MYF, PROC_ACLS, SELECT_ACL, strcmp(), TABLE_ACLS, test, and TRUE.
Referenced by check_change_password(), check_routine_access(), check_single_table_access(), check_some_access(), check_some_routine_access(), check_table_access(), copy_event_to_schema_table(), create_table_precheck(), dispatch_command(), Event_timed::execute(), fill_schema_column_privileges(), fill_schema_events(), fill_schema_schema_privileges(), fill_schema_table_privileges(), fill_schema_user_privileges(), get_all_tables(), get_schema_column_record(), multi_update_precheck(), mysql_create_view(), mysql_execute_command(), mysql_test_select(), and prepare_schema_table().
05389 { 05390 Security_context *sctx= thd->security_ctx; 05391 #ifndef NO_EMBEDDED_ACCESS_CHECKS 05392 ulong db_access; 05393 bool db_is_pattern= test(want_access & GRANT_ACL); 05394 #endif 05395 ulong dummy; 05396 DBUG_ENTER("check_access"); 05397 DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu", 05398 db ? db : "", want_access, sctx->master_access)); 05399 if (save_priv) 05400 *save_priv=0; 05401 else 05402 save_priv= &dummy; 05403 05404 if ((!db || !db[0]) && !thd->db && !dont_check_global_grants) 05405 { 05406 DBUG_PRINT("error",("No database")); 05407 if (!no_errors) 05408 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), 05409 MYF(0)); /* purecov: tested */ 05410 DBUG_RETURN(TRUE); /* purecov: tested */ 05411 } 05412 05413 if (schema_db) 05414 { 05415 if (want_access & ~(SELECT_ACL | EXTRA_ACL)) 05416 { 05417 if (!no_errors) 05418 { 05419 const char *db_name= db ? db : thd->db; 05420 my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), 05421 sctx->priv_user, sctx->priv_host, db_name); 05422 } 05423 DBUG_RETURN(TRUE); 05424 } 05425 else 05426 { 05427 *save_priv= SELECT_ACL; 05428 DBUG_RETURN(FALSE); 05429 } 05430 } 05431 05432 #ifdef NO_EMBEDDED_ACCESS_CHECKS 05433 DBUG_RETURN(0); 05434 #else 05435 if ((sctx->master_access & want_access) == want_access) 05436 { 05437 /* 05438 If we don't have a global SELECT privilege, we have to get the database 05439 specific access rights to be able to handle queries of type 05440 UPDATE t1 SET a=1 WHERE b > 0 05441 */ 05442 db_access= sctx->db_access; 05443 if (!(sctx->master_access & SELECT_ACL) && 05444 (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))) 05445 db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 05446 db_is_pattern); 05447 *save_priv=sctx->master_access | db_access; 05448 DBUG_RETURN(FALSE); 05449 } 05450 if (((want_access & ~sctx->master_access) & ~(DB_ACLS | EXTRA_ACL)) || 05451 ! db && dont_check_global_grants) 05452 { // We can never grant this 05453 DBUG_PRINT("error",("No possible access")); 05454 if (!no_errors) 05455 my_error(ER_ACCESS_DENIED_ERROR, MYF(0), 05456 sctx->priv_user, 05457 sctx->priv_host, 05458 (thd->password ? 05459 ER(ER_YES) : 05460 ER(ER_NO))); /* purecov: tested */ 05461 DBUG_RETURN(TRUE); /* purecov: tested */ 05462 } 05463 05464 if (db == any_db) 05465 DBUG_RETURN(FALSE); // Allow select on anything 05466 05467 if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db))) 05468 db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 05469 db_is_pattern); 05470 else 05471 db_access= sctx->db_access; 05472 DBUG_PRINT("info",("db_access: %lu", db_access)); 05473 /* Remove SHOW attribute and access rights we already have */ 05474 want_access &= ~(sctx->master_access | EXTRA_ACL); 05475 DBUG_PRINT("info",("db_access: %lu want_access: %lu", 05476 db_access, want_access)); 05477 db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access); 05478 05479 /* grant_option is set if there exists a single table or column grant */ 05480 if (db_access == want_access || 05481 (grant_option && !dont_check_global_grants && 05482 !(want_access & ~(db_access | TABLE_ACLS | PROC_ACLS)))) 05483 DBUG_RETURN(FALSE); /* Ok */ 05484 05485 DBUG_PRINT("error",("Access denied")); 05486 if (!no_errors) 05487 my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), 05488 sctx->priv_user, sctx->priv_host, 05489 (db ? db : (thd->db ? 05490 thd->db : 05491 "unknown"))); /* purecov: tested */ 05492 DBUG_RETURN(TRUE); /* purecov: tested */ 05493 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 05494 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int check_connection | ( | THD * | thd | ) | [static] |
Definition at line 871 of file sql_parse.cc.
References acl_check_host(), bzero, check_user(), CLIENT_COMPRESS, CLIENT_CONNECT_WITH_DB, CLIENT_IGNORE_SPACE, CLIENT_INTERACTIVE, CLIENT_LONG_FLAG, CLIENT_PROTOCOL_41, CLIENT_SECURE_CONNECTION, CLIENT_SSL, CLIENT_TRANSACTIONS, COM_CONNECT, copy_and_convert(), create_random_string(), db, DBUG_PRINT, default_charset_info, ER_BAD_HOST_ERROR, ER_HANDSHAKE_ERROR, ER_HOST_IS_BLOCKED, ER_HOST_NOT_PRIVILEGED, ER_OUT_OF_RESOURCES, HOSTNAME_LENGTH, inc_host_errors(), int2store, int4store, ip_to_hostname(), max_connect_errors, min, MIN_HANDSHAKE_SIZE, MODE_IGNORE_SPACE, my_localhost, my_net_read(), my_strdup(), MYF, NAME_LEN, net_write_command(), charset_info_st::number, opt_using_transactions, packet_error, protocol_version, st_net::read_pos, st_net::read_timeout, st_vio::remote, reset_host_errors(), st_net::return_status, SCRAMBLE_LENGTH, SCRAMBLE_LENGTH_323, server_version, SERVER_VERSION_LENGTH, SPECIAL_NO_RESOLVE, specialflag, strend(), strlen(), strmake(), strnmov(), system_charset_info, thd_init_client_charset(), TRUE, uint2korr, uint3korr, uint4korr, user, USERNAME_LENGTH, st_net::vio, vio_description(), vio_in_addr, vio_keepalive, vio_peer_addr, and x_free.
Referenced by handle_one_connection().
00872 { 00873 uint connect_errors= 0; 00874 NET *net= &thd->net; 00875 ulong pkt_len= 0; 00876 char *end; 00877 00878 DBUG_PRINT("info", 00879 ("New connection received on %s", vio_description(net->vio))); 00880 #ifdef SIGNAL_WITH_VIO_CLOSE 00881 thd->set_active_vio(net->vio); 00882 #endif 00883 00884 if (!thd->main_security_ctx.host) // If TCP/IP connection 00885 { 00886 char ip[30]; 00887 00888 if (vio_peer_addr(net->vio, ip, &thd->peer_port)) 00889 return (ER_BAD_HOST_ERROR); 00890 if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(0)))) 00891 return (ER_OUT_OF_RESOURCES); 00892 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip; 00893 vio_in_addr(net->vio,&thd->remote.sin_addr); 00894 if (!(specialflag & SPECIAL_NO_RESOLVE)) 00895 { 00896 vio_in_addr(net->vio,&thd->remote.sin_addr); 00897 thd->main_security_ctx.host= 00898 ip_to_hostname(&thd->remote.sin_addr, &connect_errors); 00899 /* Cut very long hostnames to avoid possible overflows */ 00900 if (thd->main_security_ctx.host) 00901 { 00902 if (thd->main_security_ctx.host != my_localhost) 00903 thd->main_security_ctx.host[min(strlen(thd->main_security_ctx.host), 00904 HOSTNAME_LENGTH)]= 0; 00905 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; 00906 } 00907 if (connect_errors > max_connect_errors) 00908 return(ER_HOST_IS_BLOCKED); 00909 } 00910 DBUG_PRINT("info",("Host: %s ip: %s", 00911 (thd->main_security_ctx.host ? 00912 thd->main_security_ctx.host : "unknown host"), 00913 (thd->main_security_ctx.ip ? 00914 thd->main_security_ctx.ip : "unknown ip"))); 00915 if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip)) 00916 return(ER_HOST_NOT_PRIVILEGED); 00917 } 00918 else /* Hostname given means that the connection was on a socket */ 00919 { 00920 DBUG_PRINT("info",("Host: %s", thd->main_security_ctx.host)); 00921 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; 00922 thd->main_security_ctx.ip= 0; 00923 /* Reset sin_addr */ 00924 bzero((char*) &thd->remote, sizeof(thd->remote)); 00925 } 00926 vio_keepalive(net->vio, TRUE); 00927 { 00928 /* buff[] needs to big enough to hold the server_version variable */ 00929 char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64]; 00930 ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | 00931 CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION); 00932 00933 if (opt_using_transactions) 00934 client_flags|=CLIENT_TRANSACTIONS; 00935 #ifdef HAVE_COMPRESS 00936 client_flags |= CLIENT_COMPRESS; 00937 #endif /* HAVE_COMPRESS */ 00938 #ifdef HAVE_OPENSSL 00939 if (ssl_acceptor_fd) 00940 client_flags |= CLIENT_SSL; /* Wow, SSL is available! */ 00941 #endif /* HAVE_OPENSSL */ 00942 00943 end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1; 00944 int4store((uchar*) end, thd->thread_id); 00945 end+= 4; 00946 /* 00947 So as check_connection is the only entry point to authorization 00948 procedure, scramble is set here. This gives us new scramble for 00949 each handshake. 00950 */ 00951 create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand); 00952 /* 00953 Old clients does not understand long scrambles, but can ignore packet 00954 tail: that's why first part of the scramble is placed here, and second 00955 part at the end of packet. 00956 */ 00957 end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1; 00958 00959 int2store(end, client_flags); 00960 /* write server characteristics: up to 16 bytes allowed */ 00961 end[2]=(char) default_charset_info->number; 00962 int2store(end+3, thd->server_status); 00963 bzero(end+5, 13); 00964 end+= 18; 00965 /* write scramble tail */ 00966 end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 00967 SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1; 00968 00969 /* At this point we write connection message and read reply */ 00970 if (net_write_command(net, (uchar) protocol_version, "", 0, buff, 00971 (uint) (end-buff)) || 00972 (pkt_len= my_net_read(net)) == packet_error || 00973 pkt_len < MIN_HANDSHAKE_SIZE) 00974 { 00975 inc_host_errors(&thd->remote.sin_addr); 00976 return(ER_HANDSHAKE_ERROR); 00977 } 00978 } 00979 #ifdef _CUSTOMCONFIG_ 00980 #include "_cust_sql_parse.h" 00981 #endif 00982 if (connect_errors) 00983 reset_host_errors(&thd->remote.sin_addr); 00984 if (thd->packet.alloc(thd->variables.net_buffer_length)) 00985 return(ER_OUT_OF_RESOURCES); 00986 00987 thd->client_capabilities=uint2korr(net->read_pos); 00988 if (thd->client_capabilities & CLIENT_PROTOCOL_41) 00989 { 00990 thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16; 00991 thd->max_client_packet_length= uint4korr(net->read_pos+4); 00992 DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8])); 00993 thd_init_client_charset(thd, (uint) net->read_pos[8]); 00994 thd->update_charset(); 00995 end= (char*) net->read_pos+32; 00996 } 00997 else 00998 { 00999 thd->max_client_packet_length= uint3korr(net->read_pos+2); 01000 end= (char*) net->read_pos+5; 01001 } 01002 01003 if (thd->client_capabilities & CLIENT_IGNORE_SPACE) 01004 thd->variables.sql_mode|= MODE_IGNORE_SPACE; 01005 #ifdef HAVE_OPENSSL 01006 DBUG_PRINT("info", ("client capabilities: %d", thd->client_capabilities)); 01007 if (thd->client_capabilities & CLIENT_SSL) 01008 { 01009 /* Do the SSL layering. */ 01010 if (!ssl_acceptor_fd) 01011 { 01012 inc_host_errors(&thd->remote.sin_addr); 01013 return(ER_HANDSHAKE_ERROR); 01014 } 01015 DBUG_PRINT("info", ("IO layer change in progress...")); 01016 if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout)) 01017 { 01018 DBUG_PRINT("error", ("Failed to accept new SSL connection")); 01019 inc_host_errors(&thd->remote.sin_addr); 01020 return(ER_HANDSHAKE_ERROR); 01021 } 01022 DBUG_PRINT("info", ("Reading user information over SSL layer")); 01023 if ((pkt_len= my_net_read(net)) == packet_error || 01024 pkt_len < NORMAL_HANDSHAKE_SIZE) 01025 { 01026 DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", 01027 pkt_len)); 01028 inc_host_errors(&thd->remote.sin_addr); 01029 return(ER_HANDSHAKE_ERROR); 01030 } 01031 } 01032 #endif 01033 01034 if (end >= (char*) net->read_pos+ pkt_len +2) 01035 { 01036 inc_host_errors(&thd->remote.sin_addr); 01037 return(ER_HANDSHAKE_ERROR); 01038 } 01039 01040 if (thd->client_capabilities & CLIENT_INTERACTIVE) 01041 thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout; 01042 if ((thd->client_capabilities & CLIENT_TRANSACTIONS) && 01043 opt_using_transactions) 01044 net->return_status= &thd->server_status; 01045 net->read_timeout=(uint) thd->variables.net_read_timeout; 01046 01047 char *user= end; 01048 char *passwd= strend(user)+1; 01049 uint user_len= passwd - user - 1; 01050 char *db= passwd; 01051 char db_buff[NAME_LEN+1]; // buffer to store db in utf8 01052 char user_buff[USERNAME_LENGTH+1]; // buffer to store user in utf8 01053 uint dummy_errors; 01054 01055 /* 01056 Old clients send null-terminated string as password; new clients send 01057 the size (1 byte) + string (not null-terminated). Hence in case of empty 01058 password both send '\0'. 01059 */ 01060 uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? 01061 *passwd++ : strlen(passwd); 01062 db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ? 01063 db + passwd_len + 1 : 0; 01064 uint db_len= db ? strlen(db) : 0; 01065 01066 if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len) 01067 { 01068 inc_host_errors(&thd->remote.sin_addr); 01069 return ER_HANDSHAKE_ERROR; 01070 } 01071 01072 /* Since 4.1 all database names are stored in utf8 */ 01073 if (db) 01074 { 01075 db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, 01076 system_charset_info, 01077 db, db_len, 01078 thd->charset(), &dummy_errors)]= 0; 01079 db= db_buff; 01080 } 01081 01082 user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1, 01083 system_charset_info, user, user_len, 01084 thd->charset(), &dummy_errors)]= '\0'; 01085 user= user_buff; 01086 01087 /* If username starts and ends in "'", chop them off */ 01088 if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'') 01089 { 01090 user[user_len-1]= 0; 01091 user++; 01092 user_len-= 2; 01093 } 01094 01095 if (thd->main_security_ctx.user) 01096 x_free(thd->main_security_ctx.user); 01097 if (!(thd->main_security_ctx.user= my_strdup(user, MYF(0)))) 01098 return (ER_OUT_OF_RESOURCES); 01099 return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE); 01100 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static int check_for_max_user_connections | ( | THD * | thd, | |
| USER_CONN * | uc | |||
| ) | [static] |
Definition at line 540 of file sql_parse.cc.
References user_conn::conn_per_hour, user_resources::conn_per_hour, user_conn::connections, DBUG_ENTER, DBUG_RETURN, ER_TOO_MANY_USER_CONNECTIONS, ER_USER_LIMIT_REACHED, error, LOCK_user_conn, max_user_connections, net_printf_error(), pthread_mutex_lock, pthread_mutex_unlock, time_out_user_resource_limits(), user_conn::user, user_resources::user_conn, and user_conn::user_resources.
Referenced by check_user().
00541 { 00542 int error=0; 00543 DBUG_ENTER("check_for_max_user_connections"); 00544 00545 (void) pthread_mutex_lock(&LOCK_user_conn); 00546 if (max_user_connections && !uc->user_resources.user_conn && 00547 max_user_connections < (uint) uc->connections) 00548 { 00549 net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user); 00550 error=1; 00551 goto end; 00552 } 00553 time_out_user_resource_limits(thd, uc); 00554 if (uc->user_resources.user_conn && 00555 uc->user_resources.user_conn < uc->connections) 00556 { 00557 net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, 00558 "max_user_connections", 00559 (long) uc->user_resources.user_conn); 00560 error= 1; 00561 goto end; 00562 } 00563 if (uc->user_resources.conn_per_hour && 00564 uc->user_resources.conn_per_hour <= uc->conn_per_hour) 00565 { 00566 net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, 00567 "max_connections_per_hour", 00568 (long) uc->user_resources.conn_per_hour); 00569 error=1; 00570 goto end; 00571 } 00572 uc->conn_per_hour++; 00573 00574 end: 00575 if (error) 00576 uc->connections--; // no need for decrease_user_connections() here 00577 (void) pthread_mutex_unlock(&LOCK_user_conn); 00578 DBUG_RETURN(error); 00579 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 5516 of file sql_parse.cc.
References ER_SPECIFIC_ACCESS_DENIED_ERROR, get_privilege_desc(), my_error(), and MYF.
Referenced by sys_var_thd_dbug::check(), set_var::check(), Table_triggers_list::create_trigger(), dispatch_command(), set_var::light_check(), mysql_execute_command(), and prepare_schema_table().
05517 { 05518 #ifdef NO_EMBEDDED_ACCESS_CHECKS 05519 return 0; 05520 #else 05521 char command[128]; 05522 if ((thd->security_ctx->master_access & want_access)) 05523 return 0; 05524 get_privilege_desc(command, sizeof(command), want_access); 05525 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command); 05526 return 1; 05527 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 05528 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool check_merge_table_access | ( | THD * | thd, | |
| char * | db, | |||
| TABLE_LIST * | table_list | |||
| ) |
Definition at line 5725 of file sql_parse.cc.
References check_table_access(), st_table_list::db, DELETE_ACL, error, st_table_list::next_local, SELECT_ACL, and UPDATE_ACL.
05727 { 05728 int error=0; 05729 if (table_list) 05730 { 05731 /* Check that all tables use the current database */ 05732 TABLE_LIST *tmp; 05733 for (tmp= table_list; tmp; tmp= tmp->next_local) 05734 { 05735 if (!tmp->db || !tmp->db[0]) 05736 tmp->db=db; 05737 } 05738 error=check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL, 05739 table_list,0); 05740 } 05741 return error; 05742 }
Here is the call graph for this function:

Definition at line 744 of file sql_parse.cc.
References DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, ER_USER_LIMIT_REACHED, error, LOCK_user_conn, net_printf_error(), pthread_mutex_lock, pthread_mutex_unlock, user_conn::questions, user_resources::questions, SQLCOM_END, time_out_user_resource_limits(), user_conn::updates, user_resources::updates, user_conn::user, and user_conn::user_resources.
Referenced by mysql_parse().
00745 { 00746 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00747 bool error= 0; 00748 USER_CONN *uc=thd->user_connect; 00749 DBUG_ENTER("check_mqh"); 00750 DBUG_ASSERT(uc != 0); 00751 00752 (void) pthread_mutex_lock(&LOCK_user_conn); 00753 00754 time_out_user_resource_limits(thd, uc); 00755 00756 /* Check that we have not done too many questions / hour */ 00757 if (uc->user_resources.questions && 00758 uc->questions++ >= uc->user_resources.questions) 00759 { 00760 net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions", 00761 (long) uc->user_resources.questions); 00762 error=1; 00763 goto end; 00764 } 00765 if (check_command < (uint) SQLCOM_END) 00766 { 00767 /* Check that we have not done too many updates / hour */ 00768 if (uc->user_resources.updates && 00769 (sql_command_flags[check_command] & CF_CHANGES_DATA) && 00770 uc->updates++ >= uc->user_resources.updates) 00771 { 00772 net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates", 00773 (long) uc->user_resources.updates); 00774 error=1; 00775 goto end; 00776 } 00777 } 00778 end: 00779 (void) pthread_mutex_unlock(&LOCK_user_conn); 00780 DBUG_RETURN(error); 00781 #else 00782 return (0); 00783 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00784 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool check_multi_update_lock | ( | THD * | thd | ) | [static] |
| bool check_one_table_access | ( | THD * | thd, | |
| ulong | privilege, | |||
| TABLE_LIST * | all_tables | |||
| ) |
Definition at line 5351 of file sql_parse.cc.
References check_single_table_access(), check_table_access(), st_table_list::next_global, and SELECT_ACL.
05352 { 05353 if (check_single_table_access (thd,privilege,all_tables)) 05354 return 1; 05355 05356 /* Check rights on tables of subselects and implictly opened tables */ 05357 TABLE_LIST *subselects_tables; 05358 if ((subselects_tables= all_tables->next_global)) 05359 { 05360 if ((check_table_access(thd, SELECT_ACL, subselects_tables, 0))) 05361 return 1; 05362 } 05363 return 0; 05364 }
Here is the call graph for this function:

| bool check_routine_access | ( | THD * | thd, | |
| ulong | want_access, | |||
| char * | db, | |||
| char * | name, | |||
| bool | is_proc, | |||
| bool | no_errors | |||
| ) |
Definition at line 5628 of file sql_parse.cc.
References bzero, check_access(), check_grant_routine(), FALSE, grant_option, and TRUE.
05630 { 05631 TABLE_LIST tables[1]; 05632 05633 bzero((char *)tables, sizeof(TABLE_LIST)); 05634 tables->db= db; 05635 tables->table_name= tables->alias= name; 05636 05637 /* 05638 The following test is just a shortcut for check_access() (to avoid 05639 calculating db_access) under the assumption that it's common to 05640 give persons global right to execute all stored SP (but not 05641 necessary to create them). 05642 */ 05643 if ((thd->security_ctx->master_access & want_access) == want_access) 05644 tables->grant.privilege= want_access; 05645 else if (check_access(thd,want_access,db,&tables->grant.privilege, 05646 0, no_errors, 0)) 05647 return TRUE; 05648 05649 #ifndef NO_EMBEDDED_ACCESS_CHECKS 05650 if (grant_option) 05651 return check_grant_routine(thd, want_access, tables, is_proc, no_errors); 05652 #endif 05653 05654 return FALSE; 05655 }
Here is the call graph for this function:

| bool check_simple_select | ( | ) |
Definition at line 7217 of file sql_parse.cc.
References current_thd, ER_CANT_USE_OPTION_HERE, min, my_error(), MYF, and strmake().
07218 { 07219 THD *thd= current_thd; 07220 LEX *lex= thd->lex; 07221 if (lex->current_select != &lex->select_lex) 07222 { 07223 char command[80]; 07224 strmake(command, lex->yylval->symbol.str, 07225 min(lex->yylval->symbol.length, sizeof(command)-1)); 07226 my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command); 07227 return 1; 07228 } 07229 return 0; 07230 }
Here is the call graph for this function:

| bool check_single_table_access | ( | THD * | thd, | |
| ulong | privilege, | |||
| TABLE_LIST * | all_tables | |||
| ) |
Definition at line 5303 of file sql_parse.cc.
References check_access(), check_grant(), st_table_list::db, st_table_list::field_translation, st_table_list::grant, grant_option, st_grant_info::privilege, st_table_list::schema_table, st_table_list::security_ctx, LEX_STRING::str, test, st_table_list::view, and st_table_list::view_db.
05305 { 05306 Security_context * backup_ctx= thd->security_ctx; 05307 05308 /* we need to switch to the saved context (if any) */ 05309 if (all_tables->security_ctx) 05310 thd->security_ctx= all_tables->security_ctx; 05311 05312 const char *db_name; 05313 if ((all_tables->view || all_tables->field_translation) && 05314 !all_tables->schema_table) 05315 db_name= all_tables->view_db.str; 05316 else 05317 db_name= all_tables->db; 05318 05319 if (check_access(thd, privilege, db_name, 05320 &all_tables->grant.privilege, 0, 0, 05321 test(all_tables->schema_table))) 05322 goto deny; 05323 05324 /* Show only 1 table for check_grant */ 05325 if (grant_option && check_grant(thd, privilege, all_tables, 0, 1, 0)) 05326 goto deny; 05327 05328 thd->security_ctx= backup_ctx; 05329 return 0; 05330 05331 deny: 05332 thd->security_ctx= backup_ctx; 05333 return 1; 05334 }
Here is the call graph for this function:

| bool check_some_access | ( | THD * | thd, | |
| ulong | want_access, | |||
| TABLE_LIST * | table | |||
| ) |
Definition at line 5703 of file sql_parse.cc.
References access, check_access(), check_grant(), st_table_list::db, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, st_table_list::grant, grant_option, st_grant_info::privilege, st_table_list::schema_table, and test.
05704 { 05705 ulong access; 05706 DBUG_ENTER("check_some_access"); 05707 05708 /* This loop will work as long as we have less than 32 privileges */ 05709 for (access= 1; access < want_access ; access<<= 1) 05710 { 05711 if (access & want_access) 05712 { 05713 if (!check_access(thd, access, table->db, 05714 &table->grant.privilege, 0, 1, 05715 test(table->schema_table)) && 05716 !grant_option || !check_grant(thd, access, table, 0, 1, 1)) 05717 DBUG_RETURN(0); 05718 } 05719 } 05720 DBUG_PRINT("exit",("no matching access rights")); 05721 DBUG_RETURN(1); 05722 }
Here is the call graph for this function:

Definition at line 5672 of file sql_parse.cc.
References check_access(), check_routine_level_acl(), FALSE, and SHOW_PROC_ACLS.
05674 { 05675 ulong save_priv; 05676 if (thd->security_ctx->master_access & SHOW_PROC_ACLS) 05677 return FALSE; 05678 /* 05679 There are no routines in information_schema db. So we can safely 05680 pass zero to last paramter of check_access function 05681 */ 05682 if (!check_access(thd, SHOW_PROC_ACLS, db, &save_priv, 0, 1, 0) || 05683 (save_priv & SHOW_PROC_ACLS)) 05684 return FALSE; 05685 return check_routine_level_acl(thd, db, name, is_proc); 05686 }
Here is the call graph for this function:

Definition at line 5766 of file sql_parse.cc.
References current_thd, DBUG_ASSERT, ER, ER_STACK_OVERRUN_NEED_MORE, errbuff, max, my_message(), MYF, thread_stack, and used_stack.
Referenced by sp_head::execute(), Item_subselect::fix_fields(), Item_func::fix_fields(), Item_cond::fix_fields(), Item_func_case::fix_fields(), open_table(), and st_table_list::setup_underlying().
05768 { 05769 long stack_used; 05770 DBUG_ASSERT(thd == current_thd); 05771 if ((stack_used=used_stack(thd->thread_stack,(char*) &stack_used)) >= 05772 (long) (thread_stack - margin)) 05773 { 05774 sprintf(errbuff[0],ER(ER_STACK_OVERRUN_NEED_MORE), 05775 stack_used,thread_stack,margin); 05776 my_message(ER_STACK_OVERRUN_NEED_MORE,errbuff[0],MYF(0)); 05777 thd->fatal_error(); 05778 return 1; 05779 } 05780 #ifndef DBUG_OFF 05781 max_stack_used= max(max_stack_used, stack_used); 05782 #endif 05783 return 0; 05784 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool check_table_access | ( | THD * | thd, | |
| ulong | want_access, | |||
| TABLE_LIST * | tables, | |||
| bool | no_errors | |||
| ) |
Definition at line 5555 of file sql_parse.cc.
References check_access(), st_table_list::db, st_table_list::derived, ER_DBACCESS_DENIED_ERROR, EXTRA_ACL, FILE_ACL, st_table_list::grant, grant_option, information_schema_name, my_error(), my_tz_check_n_skip_implicit_tables(), MYF, st_table_list::next_global, st_grant_info::orig_want_privilege, st_grant_info::privilege, st_table::s, st_table_list::schema_table, st_table_list::security_ctx, SELECT_ACL, SHOW_VIEW_ACL, LEX_STRING::str, strcmp(), st_table_list::table, test, st_table_share::tmp_table, and TRUE.
Referenced by check_merge_table_access(), check_one_table_access(), check_show_routine_access(), create_table_precheck(), fill_schema_proc(), list_open_tables(), multi_delete_precheck(), mysql_create_or_drop_trigger(), mysql_execute_command(), mysql_install_plugin(), mysql_make_view(), mysql_test_do_fields(), mysql_test_select(), mysql_test_set_fields(), and sp_lex_keeper::reset_lex_and_exec_core().
05557 { 05558 uint found=0; 05559 ulong found_access=0; 05560 TABLE_LIST *org_tables= tables; 05561 TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); 05562 Security_context *sctx= thd->security_ctx, *backup_ctx= thd->security_ctx; 05563 /* 05564 The check that first_not_own_table is not reached is for the case when 05565 the given table list refers to the list for prelocking (contains tables 05566 of other queries). For simple queries first_not_own_table is 0. 05567 */ 05568 for (; tables != first_not_own_table; tables= tables->next_global) 05569 { 05570 if (tables->security_ctx) 05571 sctx= tables->security_ctx; 05572 else 05573 sctx= backup_ctx; 05574 05575 if (tables->schema_table && 05576 (want_access & ~(SELECT_ACL | EXTRA_ACL | FILE_ACL))) 05577 { 05578 if (!no_errors) 05579 my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), 05580 sctx->priv_user, sctx->priv_host, 05581 information_schema_name.str); 05582 return TRUE; 05583 } 05584 /* 05585 Register access for view underlying table. 05586 Remove SHOW_VIEW_ACL, because it will be checked during making view 05587 */ 05588 tables->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL); 05589 if (tables->derived || tables->schema_table || 05590 (tables->table && (int)tables->table->s->tmp_table) || 05591 my_tz_check_n_skip_implicit_tables(&tables, 05592 thd->lex->time_zone_tables_used)) 05593 continue; 05594 thd->security_ctx= sctx; 05595 if ((sctx->master_access & want_access) == 05596 (want_access & ~EXTRA_ACL) && 05597 thd->db) 05598 tables->grant.privilege= want_access; 05599 else if (tables->db && thd->db && strcmp(tables->db, thd->db) == 0) 05600 { 05601 if (found && !grant_option) // db already checked 05602 tables->grant.privilege=found_access; 05603 else 05604 { 05605 if (check_access(thd,want_access,tables->db,&tables->grant.privilege, 05606 0, no_errors, test(tables->schema_table))) 05607 goto deny; // Access denied 05608 found_access=tables->grant.privilege; 05609 found=1; 05610 } 05611 } 05612 else if (check_access(thd,want_access,tables->db,&tables->grant.privilege, 05613 0, no_errors, test(tables->schema_table))) 05614 goto deny; 05615 } 05616 thd->security_ctx= backup_ctx; 05617 if (grant_option) 05618 return check_grant(thd,want_access & ~EXTRA_ACL,org_tables, 05619 test(want_access & EXTRA_ACL), UINT_MAX, no_errors); 05620 return FALSE; 05621 deny: 05622 thd->security_ctx= backup_ctx; 05623 return TRUE; 05624 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int check_user | ( | THD * | thd, | |
| enum enum_server_command | command, | |||
| const char * | passwd, | |||
| uint | passwd_len, | |||
| const char * | db, | |||
| bool | check_count | |||
| ) |
Definition at line 302 of file sql_parse.cc.
References acl_getroot(), check_for_max_user_connections(), COM_CONNECT, user_resources::conn_per_hour, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, decrease_user_connections(), delayed_insert_threads, ER, ER_ACCESS_DENIED_ERROR, ER_CON_COUNT_ERROR, ER_HANDSHAKE_ERROR, ER_NO, ER_NOT_SUPPORTED_AUTH_MODE, ER_SERVER_IS_IN_SECURE_AUTH_MODE, ER_YES, FALSE, general_log_print(), get_or_create_user_conn(), GLOBAL_ACLS, inc_host_errors(), LOCK_global_system_variables, LOCK_thread_count, max_connections, max_user_connections, my_net_read(), mysql_change_db(), net_printf_error(), net_send_error(), NO_ACCESS, NULL, opt_old_style_user_limits, opt_secure_auth, pthread_mutex_lock, pthread_mutex_unlock, user_resources::questions, st_net::read_pos, SCRAMBLE_LENGTH, SCRAMBLE_LENGTH_323, send_ok(), send_old_password_request(), SUPER_ACL, test, thread_count, user_resources::updates, user_resources::user_conn, and VOID.
00305 { 00306 DBUG_ENTER("check_user"); 00307 00308 #ifdef NO_EMBEDDED_ACCESS_CHECKS 00309 thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights 00310 /* Change database if necessary */ 00311 if (db && db[0]) 00312 { 00313 /* 00314 thd->db is saved in caller and needs to be freed by caller if this 00315 function returns 0 00316 */ 00317 thd->reset_db(NULL, 0); 00318 if (mysql_change_db(thd, db, FALSE)) 00319 { 00320 /* Send the error to the client */ 00321 net_send_error(thd); 00322 DBUG_RETURN(-1); 00323 } 00324 } 00325 send_ok(thd); 00326 DBUG_RETURN(0); 00327 #else 00328 00329 my_bool opt_secure_auth_local; 00330 pthread_mutex_lock(&LOCK_global_system_variables); 00331 opt_secure_auth_local= opt_secure_auth; 00332 pthread_mutex_unlock(&LOCK_global_system_variables); 00333 00334 /* 00335 If the server is running in secure auth mode, short scrambles are 00336 forbidden. 00337 */ 00338 if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323) 00339 { 00340 net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE); 00341 general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); 00342 DBUG_RETURN(-1); 00343 } 00344 if (passwd_len != 0 && 00345 passwd_len != SCRAMBLE_LENGTH && 00346 passwd_len != SCRAMBLE_LENGTH_323) 00347 DBUG_RETURN(ER_HANDSHAKE_ERROR); 00348 00349 /* 00350 Clear thd->db as it points to something, that will be freed when 00351 connection is closed. We don't want to accidentally free a wrong pointer 00352 if connect failed. Also in case of 'CHANGE USER' failure, current 00353 database will be switched to 'no database selected'. 00354 */ 00355 thd->reset_db(NULL, 0); 00356 00357 USER_RESOURCES ur; 00358 int res= acl_getroot(thd, &ur, passwd, passwd_len); 00359 #ifndef EMBEDDED_LIBRARY 00360 if (res == -1) 00361 { 00362 /* 00363 This happens when client (new) sends password scrambled with 00364 scramble(), but database holds old value (scrambled with 00365 scramble_323()). Here we please client to send scrambled_password 00366 in old format. 00367 */ 00368 NET *net= &thd->net; 00369 if (opt_secure_auth_local) 00370 { 00371 net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE, 00372 thd->main_security_ctx.user, 00373 thd->main_security_ctx.host_or_ip); 00374 general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE), 00375 thd->main_security_ctx.user, 00376 thd->main_security_ctx.host_or_ip); 00377 DBUG_RETURN(-1); 00378 } 00379 /* We have to read very specific packet size */ 00380 if (send_old_password_request(thd) || 00381 my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) 00382 { 00383 inc_host_errors(&thd->remote.sin_addr); 00384 DBUG_RETURN(ER_HANDSHAKE_ERROR); 00385 } 00386 /* Final attempt to check the user based on reply */ 00387 /* So as passwd is short, errcode is always >= 0 */ 00388 res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323); 00389 } 00390 #endif /*EMBEDDED_LIBRARY*/ 00391 /* here res is always >= 0 */ 00392 if (res == 0) 00393 { 00394 if (!(thd->main_security_ctx.master_access & 00395 NO_ACCESS)) // authentication is OK 00396 { 00397 DBUG_PRINT("info", 00398 ("Capabilities: %lx packet_length: %ld Host: '%s' " 00399 "Login user: '%s' Priv_user: '%s' Using password: %s " 00400 "Access: %u db: '%s'", 00401 thd->client_capabilities, 00402 thd->max_client_packet_length, 00403 thd->main_security_ctx.host_or_ip, 00404 thd->main_security_ctx.user, 00405 thd->main_security_ctx.priv_user, 00406 passwd_len ? "yes": "no", 00407 thd->main_security_ctx.master_access, 00408 (thd->db ? thd->db : "*none*"))); 00409 00410 if (check_count) 00411 { 00412 VOID(pthread_mutex_lock(&LOCK_thread_count)); 00413 bool count_ok= thread_count <= max_connections + delayed_insert_threads 00414 || (thd->main_security_ctx.master_access & SUPER_ACL); 00415 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 00416 if (!count_ok) 00417 { // too many connections 00418 net_send_error(thd, ER_CON_COUNT_ERROR); 00419 DBUG_RETURN(-1); 00420 } 00421 } 00422 00423 /* Why logging is performed before all checks've passed? */ 00424 general_log_print(thd, command, 00425 (thd->main_security_ctx.priv_user == 00426 thd->main_security_ctx.user ? 00427 (char*) "%s@%s on %s" : 00428 (char*) "%s@%s as anonymous on %s"), 00429 thd->main_security_ctx.user, 00430 thd->main_security_ctx.host_or_ip, 00431 db ? db : (char*) ""); 00432 00433 /* 00434 This is the default access rights for the current database. It's 00435 set to 0 here because we don't have an active database yet (and we 00436 may not have an active database to set. 00437 */ 00438 thd->main_security_ctx.db_access=0; 00439 00440 /* Don't allow user to connect if he has done too many queries */ 00441 if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn || 00442 max_user_connections) && 00443 get_or_create_user_conn(thd, 00444 (opt_old_style_user_limits ? thd->main_security_ctx.user : 00445 thd->main_security_ctx.priv_user), 00446 (opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip : 00447 thd->main_security_ctx.priv_host), 00448 &ur)) 00449 DBUG_RETURN(-1); 00450 if (thd->user_connect && 00451 (thd->user_connect->user_resources.conn_per_hour || 00452 thd->user_connect->user_resources.user_conn || 00453 max_user_connections) && 00454 check_for_max_user_connections(thd, thd->user_connect)) 00455 DBUG_RETURN(-1); 00456 00457 /* Change database if necessary */ 00458 if (db && db[0]) 00459 { 00460 if (mysql_change_db(thd, db, FALSE)) 00461 { 00462 /* Send error to the client */ 00463 net_send_error(thd); 00464 if (thd->user_connect) 00465 decrease_user_connections(thd->user_connect); 00466 DBUG_RETURN(-1); 00467 } 00468 } 00469 send_ok(thd); 00470 thd->password= test(passwd_len); // remember for error messages 00471 /* Ready to handle queries */ 00472 DBUG_RETURN(0); 00473 } 00474 } 00475 else if (res == 2) // client gave short hash, server has long hash 00476 { 00477 net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE); 00478 general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE)); 00479 DBUG_RETURN(-1); 00480 } 00481 net_printf_error(thd, ER_ACCESS_DENIED_ERROR, 00482 thd->main_security_ctx.user, 00483 thd->main_security_ctx.host_or_ip, 00484 passwd_len ? ER(ER_YES) : ER(ER_NO)); 00485 general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR), 00486 thd->main_security_ctx.user, 00487 thd->main_security_ctx.host_or_ip, 00488 passwd_len ? ER(ER_YES) : ER(ER_NO)); 00489 DBUG_RETURN(-1); 00490 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00491 }
Here is the call graph for this function:

| void cleanup_items | ( | Item * | item | ) |
Definition at line 1397 of file sql_parse.cc.
References Item::cleanup(), DBUG_ENTER, DBUG_VOID_RETURN, and Item::next.
01398 { 01399 DBUG_ENTER("cleanup_items"); 01400 for (; item ; item=item->next) 01401 item->cleanup(); 01402 DBUG_VOID_RETURN; 01403 }
Here is the call graph for this function:

| Comp_creator* comp_eq_creator | ( | bool | invert | ) |
Definition at line 7233 of file sql_parse.cc.
References eq_creator, and ne_creator.
Referenced by all_any_subquery_creator().
07234 { 07235 return invert?(Comp_creator *)&ne_creator:(Comp_creator *)&eq_creator; 07236 }
Here is the caller graph for this function:

| Comp_creator* comp_ge_creator | ( | bool | invert | ) |
Definition at line 7239 of file sql_parse.cc.
References ge_creator, and lt_creator.
07240 { 07241 return invert?(Comp_creator *)<_creator:(Comp_creator *)&ge_creator; 07242 }
| Comp_creator* comp_gt_creator | ( | bool | invert | ) |
Definition at line 7245 of file sql_parse.cc.
References gt_creator, and le_creator.
07246 { 07247 return invert?(Comp_creator *)&le_creator:(Comp_creator *)>_creator; 07248 }
| Comp_creator* comp_le_creator | ( | bool | invert | ) |
Definition at line 7251 of file sql_parse.cc.
References gt_creator, and le_creator.
07252 { 07253 return invert?(Comp_creator *)>_creator:(Comp_creator *)&le_creator; 07254 }
| Comp_creator* comp_lt_creator | ( | bool | invert | ) |
Definition at line 7257 of file sql_parse.cc.
References ge_creator, and lt_creator.
07258 { 07259 return invert?(Comp_creator *)&ge_creator:(Comp_creator *)<_creator; 07260 }
| Comp_creator* comp_ne_creator | ( | bool | invert | ) |
Definition at line 7263 of file sql_parse.cc.
References eq_creator, and ne_creator.
Referenced by all_any_subquery_creator().
07264 { 07265 return invert?(Comp_creator *)&eq_creator:(Comp_creator *)&ne_creator; 07266 }
Here is the caller graph for this function:

| LEX_USER* create_default_definer | ( | THD * | thd | ) |
Definition at line 7760 of file sql_parse.cc.
References get_default_definer().
07761 { 07762 LEX_USER *definer; 07763 07764 if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) 07765 return 0; 07766 07767 get_default_definer(thd, definer); 07768 07769 return definer; 07770 }
Here is the call graph for this function:

| LEX_USER* create_definer | ( | THD * | thd, | |
| LEX_STRING * | user_name, | |||
| LEX_STRING * | host_name | |||
| ) |
Definition at line 7788 of file sql_parse.cc.
References st_lex_user::host, and st_lex_user::user.
07789 { 07790 LEX_USER *definer; 07791 07792 /* Create and initialize. */ 07793 07794 if (! (definer= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) 07795 return 0; 07796 07797 definer->user= *user_name; 07798 definer->host= *host_name; 07799 07800 return definer; 07801 }
| void create_select_for_variable | ( | const char * | var_name | ) |
Definition at line 5989 of file sql_parse.cc.
References bzero, current_thd, DBUG_ENTER, DBUG_VOID_RETURN, get_system_var(), LEX_STRING::length, MAX_SYS_VAR_LENGTH, mysql_init_select(), NullS, OPT_SESSION, Item::set_name(), SQLCOM_SELECT, LEX_STRING::str, strlen(), strxmov(), and system_charset_info.
05990 { 05991 THD *thd; 05992 LEX *lex; 05993 LEX_STRING tmp, null_lex_string; 05994 Item *var; 05995 char buff[MAX_SYS_VAR_LENGTH*2+4+8], *end; 05996 DBUG_ENTER("create_select_for_variable"); 05997 05998 thd= current_thd; 05999 lex= thd->lex; 06000 mysql_init_select(lex); 06001 lex->sql_command= SQLCOM_SELECT; 06002 tmp.str= (char*) var_name; 06003 tmp.length=strlen(var_name); 06004 bzero((char*) &null_lex_string.str, sizeof(null_lex_string)); 06005 /* 06006 We set the name of Item to @@session.var_name because that then is used 06007 as the column name in the output. 06008 */ 06009 if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string))) 06010 { 06011 end= strxmov(buff, "@@session.", var_name, NullS); 06012 var->set_name(buff, end-buff, system_charset_info); 06013 add_item_to_list(thd, var); 06014 } 06015 DBUG_VOID_RETURN; 06016 }
Here is the call graph for this function:

| bool create_table_precheck | ( | THD * | thd, | |
| TABLE_LIST * | tables, | |||
| TABLE_LIST * | create_table | |||
| ) |
Definition at line 7632 of file sql_parse.cc.
References check_access(), check_grant(), check_merge_table_access(), check_table_access(), CREATE_ACL, create_table(), CREATE_TMP_ACL, DBUG_ENTER, DBUG_RETURN, err, FALSE, grant_option, HA_LEX_CREATE_TMP_TABLE, SELECT_ACL, test, and TRUE.
07634 { 07635 LEX *lex= thd->lex; 07636 SELECT_LEX *select_lex= &lex->select_lex; 07637 ulong want_priv; 07638 bool error= TRUE; // Error message is given 07639 DBUG_ENTER("create_table_precheck"); 07640 07641 want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? 07642 CREATE_TMP_ACL : CREATE_ACL); 07643 lex->create_info.alias= create_table->alias; 07644 if (check_access(thd, want_priv, create_table->db, 07645 &create_table->grant.privilege, 0, 0, 07646 test(create_table->schema_table)) || 07647 check_merge_table_access(thd, create_table->db, 07648 (TABLE_LIST *) 07649 lex->create_info.merge_list.first)) 07650 goto err; 07651 if (grant_option && want_priv != CREATE_TMP_ACL && 07652 check_grant(thd, want_priv, create_table, 0, 1, 0)) 07653 goto err; 07654 07655 if (select_lex->item_list.elements) 07656 { 07657 /* Check permissions for used tables in CREATE TABLE ... SELECT */ 07658 07659 #ifdef NOT_NECESSARY_TO_CHECK_CREATE_TABLE_EXIST_WHEN_PREPARING_STATEMENT 07660 /* This code throws an ill error for CREATE TABLE t1 SELECT * FROM t1 */ 07661 /* 07662 Only do the check for PS, becasue we on execute we have to check that 07663 against the opened tables to ensure we don't use a table that is part 07664 of the view (which can only be done after the table has been opened). 07665 */ 07666 if (thd->stmt_arena->is_stmt_prepare_or_first_sp_execute()) 07667 { 07668 /* 07669 For temporary tables we don't have to check if the created table exists 07670 */ 07671 if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && 07672 find_table_in_global_list(tables, create_table->db, 07673 create_table->table_name)) 07674 { 07675 error= FALSE; 07676 goto err; 07677 } 07678 } 07679 #endif 07680 if (tables && check_table_access(thd, SELECT_ACL, tables,0)) 07681 goto err; 07682 } 07683 error= FALSE; 07684 07685 err: 07686 DBUG_RETURN(error); 07687 }
Here is the call graph for this function:

| static void decrease_user_connections | ( | USER_CONN * | uc | ) | [static] |
Definition at line 599 of file sql_parse.cc.
References user_conn::connections, DBUG_ASSERT, DBUG_ENTER, DBUG_VOID_RETURN, hash_delete(), hash_user_connections, LOCK_user_conn, mqh_used, pthread_mutex_lock, and pthread_mutex_unlock.
Referenced by check_user(), dispatch_command(), and handle_one_connection().
00600 { 00601 DBUG_ENTER("decrease_user_connections"); 00602 (void) pthread_mutex_lock(&LOCK_user_conn); 00603 DBUG_ASSERT(uc->connections); 00604 if (!--uc->connections && !mqh_used) 00605 { 00606 /* Last connection for user; Delete it */ 00607 (void) hash_delete(&hash_user_connections,(byte*) uc); 00608 } 00609 (void) pthread_mutex_unlock(&LOCK_user_conn); 00610 DBUG_VOID_RETURN; 00611 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool delete_precheck | ( | THD * | thd, | |
| TABLE_LIST * | tables | |||
| ) |
Definition at line 7569 of file sql_parse.cc.
References check_one_table_access(), DBUG_ENTER, DBUG_RETURN, DELETE_ACL, FALSE, st_table_list::grant, st_grant_info::privilege, SELECT_ACL, TRUE, and st_grant_info::want_privilege.
07570 { 07571 DBUG_ENTER("delete_precheck"); 07572 if (check_one_table_access(thd, DELETE_ACL, tables)) 07573 DBUG_RETURN(TRUE); 07574 /* Set privilege for the WHERE clause */ 07575 tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege); 07576 DBUG_RETURN(FALSE); 07577 }
Here is the call graph for this function:

| bool dispatch_command | ( | enum enum_server_command | command, | |
| THD * | thd, | |||
| char * | packet, | |||
| uint | packet_length | |||
| ) |
Definition at line 1636 of file sql_parse.cc.
References alloc_query(), bzero, cached_open_tables(), calc_sum_of_all_status(), check_access(), check_db_name(), check_global_access(), check_grant(), check_user(), CLIENT_MULTI_STATEMENTS, CLIENT_SECURE_CONNECTION, close_connection(), close_thread_tables(), COM_BINLOG_DUMP, COM_CHANGE_USER, COM_CONNECT, COM_CREATE_DB, COM_DEBUG, COM_DELAYED_INSERT, COM_DROP_DB, COM_END, COM_FIELD_LIST, COM_INIT_DB, COM_PING, COM_PROCESS_INFO, COM_PROCESS_KILL, COM_QUERY, COM_QUIT, COM_REFRESH, COM_REGISTER_SLAVE, COM_SET_OPTION, COM_SHUTDOWN, COM_SLEEP, COM_STATISTICS, COM_STMT_CLOSE, COM_STMT_EXECUTE, COM_STMT_FETCH, COM_STMT_PREPARE, COM_STMT_RESET, COM_STMT_SEND_LONG_DATA, COM_TABLE_DUMP, COM_TIME, copy_and_convert(), CREATE_ACL, db, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, decrease_user_connections(), DROP_ACL, ER, ER_LOCK_OR_ACTIVE_TRANSACTION, ER_NOT_ALLOWED_COMMAND, ER_NOT_SUPPORTED_YET, ER_OUT_OF_RESOURCES, ER_UNKNOWN_COM_ERROR, ER_WRONG_DB_NAME, st_net::error, error, FALSE, files_charset_info, find_schema_table(), flags, free_root(), general_log_print(), grant_option, information_schema_name, kill_mysql(), lex_start(), LOCK_status, LOCK_thread_count, log_slow_statement(), system_status_var::long_query_count, lower_case_table_names, my_casedn_str, my_error(), my_isspace, MY_KEEP_PREALLOC, my_message(), my_net_write(), my_pthread_setprio(), my_strcasecmp, my_strdup(), MYF, mysql_change_db(), mysql_create_db(), mysql_init_query(), MYSQL_OPTION_MULTI_STATEMENTS_OFF, MYSQL_OPTION_MULTI_STATEMENTS_ON, mysql_parse(), mysql_print_status(), mysql_rm_db(), mysql_stmt_close(), mysql_stmt_execute(), mysql_stmt_fetch(), mysql_stmt_get_longdata(), mysql_stmt_prepare(), mysql_stmt_reset(), mysql_table_dump(), mysqld_list_fields(), mysqld_list_processes(), NAME_LEN, net_flush(), net_send_error(), next_query_id(), st_net::no_send_error, NULL, NullS, system_status_var::opened_tables, opt_log_slow_admin_statements, options(), pos(), PROCESS_ACL, pthread_mutex_lock, pthread_mutex_unlock, query_id, QUERY_PRIOR, st_net::read_pos, refresh_version, RELOAD_ACL, reload_acl_and_cache(), remove_escape(), REPL_SLAVE_ACL, SELECT_ACL, send_eof(), send_ok(), SERVER_QUERY_NO_GOOD_INDEX_USED, SERVER_QUERY_NO_INDEX_USED, sf_malloc_cur_memory, sf_malloc_max_memory, SHUTDOWN_ACL, SHUTDOWN_DEFAULT, SHUTDOWN_WAIT_ALL_BUFFERS, sleep, SPECIAL_NO_PRIOR, specialflag, sql_kill(), SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_END, SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_SET_OPTION, SQLCOM_SHOW_FIELDS, SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_STATUS, start_time, statistic_increment, LEX_STRING::str, strend(), strlen(), strmake(), SUPER_ACL, system_charset_info, test, thread_count, thread_running, TRUE, uint2korr, uint4korr, ulonglong2double, user, VOID, WAIT_PRIOR, and x_free.
Referenced by do_command(), and execute_init_command().
01638 { 01639 NET *net= &thd->net; 01640 bool error= 0; 01641 DBUG_ENTER("dispatch_command"); 01642 01643 if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA) 01644 thd->killed= THD::NOT_KILLED; 01645 01646 thd->command=command; 01647 /* 01648 Commands which always take a long time are logged into 01649 the slow log only if opt_log_slow_admin_statements is set. 01650 */ 01651 thd->enable_slow_log= TRUE; 01652 thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */ 01653 thd->set_time(); 01654 VOID(pthread_mutex_lock(&LOCK_thread_count)); 01655 thd->query_id=query_id; 01656 if (command != COM_STATISTICS && command != COM_PING) 01657 next_query_id(); 01658 thread_running++; 01659 /* TODO: set thd->lex->sql_command to SQLCOM_END here */ 01660 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 01661 01662 thd->server_status&= 01663 ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED); 01664 switch (command) { 01665 case COM_INIT_DB: 01666 { 01667 LEX_STRING tmp; 01668 statistic_increment(thd->status_var.com_stat[SQLCOM_CHANGE_DB], 01669 &LOCK_status); 01670 thd->convert_string(&tmp, system_charset_info, 01671 packet, strlen(packet), thd->charset()); 01672 if (!mysql_change_db(thd, tmp.str, FALSE)) 01673 { 01674 general_log_print(thd, command, "%s",thd->db); 01675 send_ok(thd); 01676 } 01677 break; 01678 } 01679 #ifdef HAVE_REPLICATION 01680 case COM_REGISTER_SLAVE: 01681 { 01682 if (!register_slave(thd, (uchar*)packet, packet_length)) 01683 send_ok(thd); 01684 break; 01685 } 01686 #endif 01687 case COM_TABLE_DUMP: 01688 { 01689 char *db, *tbl_name; 01690 uint db_len= *(uchar*) packet; 01691 if (db_len >= packet_length || db_len > NAME_LEN) 01692 { 01693 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 01694 break; 01695 } 01696 uint tbl_len= *(uchar*) (packet + db_len + 1); 01697 if (db_len+tbl_len+2 > packet_length || tbl_len > NAME_LEN) 01698 { 01699 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 01700 break; 01701 } 01702 01703 statistic_increment(thd->status_var.com_other, &LOCK_status); 01704 thd->enable_slow_log= opt_log_slow_admin_statements; 01705 db= thd->alloc(db_len + tbl_len + 2); 01706 if (!db) 01707 { 01708 my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); 01709 break; 01710 } 01711 tbl_name= strmake(db, packet + 1, db_len)+1; 01712 strmake(tbl_name, packet + db_len + 2, tbl_len); 01713 mysql_table_dump(thd, db, tbl_name); 01714 break; 01715 } 01716 case COM_CHANGE_USER: 01717 { 01718 thd->change_user(); 01719 thd->clear_error(); // if errors from rollback 01720 01721 statistic_increment(thd->status_var.com_other, &LOCK_status); 01722 char *user= (char*) packet; 01723 char *passwd= strend(user)+1; 01724 /* 01725 Old clients send null-terminated string ('\0' for empty string) for 01726 password. New clients send the size (1 byte) + string (not null 01727 terminated, so also '\0' for empty string). 01728 */ 01729 char db_buff[NAME_LEN+1]; // buffer to store db in utf8 01730 char *db= passwd; 01731 uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ? 01732 *passwd++ : strlen(passwd); 01733 db+= passwd_len + 1; 01734 #ifndef EMBEDDED_LIBRARY 01735 /* Small check for incoming packet */ 01736 if ((uint) ((uchar*) db - net->read_pos) > packet_length) 01737 { 01738 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 01739 break; 01740 } 01741 #endif 01742 /* Convert database name to utf8 */ 01743 uint dummy_errors; 01744 db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1, 01745 system_charset_info, db, strlen(db), 01746 thd->charset(), &dummy_errors)]= 0; 01747 db= db_buff; 01748 01749 /* Save user and privileges */ 01750 uint save_db_length= thd->db_length; 01751 char *save_db= thd->db; 01752 Security_context save_security_ctx= *thd->security_ctx; 01753 USER_CONN *save_user_connect= thd->user_connect; 01754 01755 if (!(thd->security_ctx->user= my_strdup(user, MYF(0)))) 01756 { 01757 thd->security_ctx->user= save_security_ctx.user; 01758 my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); 01759 break; 01760 } 01761 01762 /* Clear variables that are allocated */ 01763 thd->user_connect= 0; 01764 int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, FALSE); 01765 01766 if (res) 01767 { 01768 /* authentication failure, we shall restore old user */ 01769 if (res > 0) 01770 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 01771 x_free(thd->security_ctx->user); 01772 *thd->security_ctx= save_security_ctx; 01773 thd->user_connect= save_user_connect; 01774 thd->db= save_db; 01775 thd->db_length= save_db_length; 01776 } 01777 else 01778 { 01779 #ifndef NO_EMBEDDED_ACCESS_CHECKS 01780 /* we've authenticated new user */ 01781 if (save_user_connect) 01782 decrease_user_connections(save_user_connect); 01783 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 01784 x_free((gptr) save_db); 01785 x_free((gptr) save_security_ctx.user); 01786 } 01787 break; 01788 } 01789 case COM_STMT_EXECUTE: 01790 { 01791 mysql_stmt_execute(thd, packet, packet_length); 01792 break; 01793 } 01794 case COM_STMT_FETCH: 01795 { 01796 mysql_stmt_fetch(thd, packet, packet_length); 01797 break; 01798 } 01799 case COM_STMT_SEND_LONG_DATA: 01800 { 01801 mysql_stmt_get_longdata(thd, packet, packet_length); 01802 break; 01803 } 01804 case COM_STMT_PREPARE: 01805 { 01806 mysql_stmt_prepare(thd, packet, packet_length); 01807 break; 01808 } 01809 case COM_STMT_CLOSE: 01810 { 01811 mysql_stmt_close(thd, packet); 01812 break; 01813 } 01814 case COM_STMT_RESET: 01815 { 01816 mysql_stmt_reset(thd, packet); 01817 break; 01818 } 01819 case COM_QUERY: 01820 { 01821 if (alloc_query(thd, packet, packet_length)) 01822 break; // fatal error is set 01823 char *packet_end= thd->query + thd->query_length; 01824 general_log_print(thd, command, "%.*b", thd->query_length, thd->query); 01825 DBUG_PRINT("query",("%-.4096s",thd->query)); 01826 01827 if (!(specialflag & SPECIAL_NO_PRIOR)) 01828 my_pthread_setprio(pthread_self(),QUERY_PRIOR); 01829 01830 mysql_parse(thd,thd->query, thd->query_length); 01831 01832 while (!thd->killed && thd->lex->found_semicolon && !thd->net.report_error) 01833 { 01834 char *packet= thd->lex->found_semicolon; 01835 net->no_send_error= 0; 01836 /* 01837 Multiple queries exits, execute them individually 01838 */ 01839 if (thd->lock || thd->open_tables || thd->derived_tables || 01840 thd->prelocked_mode) 01841 close_thread_tables(thd); 01842 ulong length= (ulong)(packet_end-packet); 01843 01844 log_slow_statement(thd); 01845 01846 /* Remove garbage at start of query */ 01847 while (my_isspace(thd->charset(), *packet) && length > 0) 01848 { 01849 packet++; 01850 length--; 01851 } 01852 VOID(pthread_mutex_lock(&LOCK_thread_count)); 01853 thd->query_length= length; 01854 thd->query= packet; 01855 thd->query_id= next_query_id(); 01856 thd->set_time(); /* Reset the query start time. */ 01857 /* TODO: set thd->lex->sql_command to SQLCOM_END here */ 01858 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 01859 mysql_parse(thd, packet, length); 01860 } 01861 01862 if (!(specialflag & SPECIAL_NO_PRIOR)) 01863 my_pthread_setprio(pthread_self(),WAIT_PRIOR); 01864 DBUG_PRINT("info",("query ready")); 01865 break; 01866 } 01867 case COM_FIELD_LIST: // This isn't actually needed 01868 #ifdef DONT_ALLOW_SHOW_COMMANDS 01869 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 01870 MYF(0)); /* purecov: inspected */ 01871 break; 01872 #else 01873 { 01874 char *fields, *pend; 01875 /* Locked closure of all tables */ 01876 TABLE_LIST *locked_tables= NULL; 01877 TABLE_LIST table_list; 01878 LEX_STRING conv_name; 01879 /* Saved variable value */ 01880 my_bool old_innodb_table_locks= thd->variables.innodb_table_locks; 01881 01882 01883 /* used as fields initializator */ 01884 lex_start(thd, 0, 0); 01885 01886 01887 statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_FIELDS], 01888 &LOCK_status); 01889 bzero((char*) &table_list,sizeof(table_list)); 01890 if (thd->copy_db_to(&table_list.db, 0)) 01891 break; 01892 pend= strend(packet); 01893 thd->convert_string(&conv_name, system_charset_info, 01894 packet, (uint) (pend-packet), thd->charset()); 01895 table_list.alias= table_list.table_name= conv_name.str; 01896 packet= pend+1; 01897 01898 if (!my_strcasecmp(system_charset_info, table_list.db, 01899 information_schema_name.str)) 01900 { 01901 ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, table_list.alias); 01902 if (schema_table) 01903 table_list.schema_table= schema_table; 01904 } 01905 01906 thd->query_length= strlen(packet); // for simplicity: don't optimize 01907 if (!(thd->query=fields=thd->memdup(packet,thd->query_length+1))) 01908 break; 01909 general_log_print(thd, command, "%s %s", table_list.table_name, fields); 01910 if (lower_case_table_names) 01911 my_casedn_str(files_charset_info, table_list.table_name); 01912 remove_escape(table_list.table_name); // This can't have wildcards 01913 01914 if (check_access(thd,SELECT_ACL,table_list.db,&table_list.grant.privilege, 01915 0, 0, test(table_list.schema_table))) 01916 break; 01917 if (grant_option && 01918 check_grant(thd, SELECT_ACL, &table_list, 2, UINT_MAX, 0)) 01919 break; 01920 /* init structures for VIEW processing */ 01921 table_list.select_lex= &(thd->lex->select_lex); 01922 mysql_init_query(thd, (uchar*)"", 0); 01923 thd->lex-> 01924 select_lex.table_list.link_in_list((byte*) &table_list, 01925 (byte**) &table_list.next_local); 01926 thd->lex->add_to_query_tables(&table_list); 01927 01928 /* switch on VIEW optimisation: do not fill temporary tables */ 01929 thd->lex->sql_command= SQLCOM_SHOW_FIELDS; 01930 mysqld_list_fields(thd,&table_list,fields); 01931 thd->lex->unit.cleanup(); 01932 thd->cleanup_after_query(); 01933 break; 01934 } 01935 #endif 01936 case COM_QUIT: 01937 /* We don't calculate statistics for this command */ 01938 general_log_print(thd, command, NullS); 01939 net->error=0; // Don't give 'abort' message 01940 error=TRUE; // End server 01941 break; 01942 01943 case COM_CREATE_DB: // QQ: To be removed 01944 { 01945 char *db=thd->strdup(packet), *alias; 01946 HA_CREATE_INFO create_info; 01947 01948 statistic_increment(thd->status_var.com_stat[SQLCOM_CREATE_DB], 01949 &LOCK_status); 01950 // null test to handle EOM 01951 if (!db || !(alias= thd->strdup(db)) || check_db_name(db)) 01952 { 01953 my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); 01954 break; 01955 } 01956 if (check_access(thd,CREATE_ACL,db,0,1,0,is_schema_db(db))) 01957 break; 01958 general_log_print(thd, command, packet); 01959 bzero(&create_info, sizeof(create_info)); 01960 mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db), 01961 &create_info, 0); 01962 break; 01963 } 01964 case COM_DROP_DB: // QQ: To be removed 01965 { 01966 statistic_increment(thd->status_var.com_stat[SQLCOM_DROP_DB], 01967 &LOCK_status); 01968 char *db=thd->strdup(packet); 01969 /* null test to handle EOM */ 01970 if (!db || check_db_name(db)) 01971 { 01972 my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL"); 01973 break; 01974 } 01975 if (check_access(thd,DROP_ACL,db,0,1,0,is_schema_db(db))) 01976 break; 01977 if (thd->locked_tables || thd->active_transaction()) 01978 { 01979 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 01980 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 01981 break; 01982 } 01983 general_log_print(thd, command, db); 01984 mysql_rm_db(thd, db, 0, 0); 01985 break; 01986 } 01987 #ifndef EMBEDDED_LIBRARY 01988 case COM_BINLOG_DUMP: 01989 { 01990 ulong pos; 01991 ushort flags; 01992 uint32 slave_server_id; 01993 01994 statistic_increment(thd->status_var.com_other,&LOCK_status); 01995 thd->enable_slow_log= opt_log_slow_admin_statements; 01996 if (check_global_access(thd, REPL_SLAVE_ACL)) 01997 break; 01998 01999 /* TODO: The following has to be changed to an 8 byte integer */ 02000 pos = uint4korr(packet); 02001 flags = uint2korr(packet + 4); 02002 thd->server_id=0; /* avoid suicide */ 02003 if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0 02004 kill_zombie_dump_threads(slave_server_id); 02005 thd->server_id = slave_server_id; 02006 02007 general_log_print(thd, command, "Log: '%s' Pos: %ld", packet+10, 02008 (long) pos); 02009 mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags); 02010 unregister_slave(thd,1,1); 02011 /* fake COM_QUIT -- if we get here, the thread needs to terminate */ 02012 error = TRUE; 02013 net->error = 0; 02014 break; 02015 } 02016 #endif 02017 case COM_REFRESH: 02018 { 02019 bool not_used; 02020 statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH], 02021 &LOCK_status); 02022 ulong options= (ulong) (uchar) packet[0]; 02023 if (check_global_access(thd,RELOAD_ACL)) 02024 break; 02025 general_log_print(thd, command, NullS); 02026 if (!reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, ¬_used)) 02027 send_ok(thd); 02028 break; 02029 } 02030 #ifndef EMBEDDED_LIBRARY 02031 case COM_SHUTDOWN: 02032 { 02033 statistic_increment(thd->status_var.com_other, &LOCK_status); 02034 if (check_global_access(thd,SHUTDOWN_ACL)) 02035 break; /* purecov: inspected */ 02036 /* 02037 If the client is < 4.1.3, it is going to send us no argument; then 02038 packet_length is 1, packet[0] is the end 0 of the packet. Note that 02039 SHUTDOWN_DEFAULT is 0. If client is >= 4.1.3, the shutdown level is in 02040 packet[0]. 02041 */ 02042 enum mysql_enum_shutdown_level level= 02043 (enum mysql_enum_shutdown_level) (uchar) packet[0]; 02044 DBUG_PRINT("quit",("Got shutdown command for level %u", level)); 02045 if (level == SHUTDOWN_DEFAULT) 02046 level= SHUTDOWN_WAIT_ALL_BUFFERS; // soon default will be configurable 02047 else if (level != SHUTDOWN_WAIT_ALL_BUFFERS) 02048 { 02049 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level"); 02050 break; 02051 } 02052 DBUG_PRINT("quit",("Got shutdown command for level %u", level)); 02053 general_log_print(thd, command, NullS); 02054 send_eof(thd); 02055 #ifdef __WIN__ 02056 sleep(1); // must wait after eof() 02057 #endif 02058 send_eof(thd); // This is for 'quit request' 02059 close_connection(thd, 0, 1); 02060 close_thread_tables(thd); // Free before kill 02061 kill_mysql(); 02062 error=TRUE; 02063 break; 02064 } 02065 #endif 02066 case COM_STATISTICS: 02067 { 02068 general_log_print(thd, command, NullS); 02069 statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS], 02070 &LOCK_status); 02071 #ifndef EMBEDDED_LIBRARY 02072 char buff[200]; 02073 #else 02074 char *buff= thd->net.last_error; 02075 #endif 02076 02077 STATUS_VAR current_global_status_var; 02078 calc_sum_of_all_status(¤t_global_status_var); 02079 02080 ulong uptime = (ulong) (thd->start_time - start_time); 02081 sprintf((char*) buff, 02082 "Uptime: %lu Threads: %d Questions: %lu Slow queries: %lu Opens: %lu Flush tables: %lu Open tables: %u Queries per second avg: %.3f", 02083 uptime, 02084 (int) thread_count, (ulong) thd->query_id, 02085 current_global_status_var.long_query_count, 02086 current_global_status_var.opened_tables, refresh_version, 02087 cached_open_tables(), 02088 (uptime ? (ulonglong2double(thd->query_id) / (double) uptime) : 02089 (double) 0)); 02090 #ifdef SAFEMALLOC 02091 if (sf_malloc_cur_memory) // Using SAFEMALLOC 02092 sprintf(strend(buff), " Memory in use: %ldK Max memory used: %ldK", 02093 (sf_malloc_cur_memory+1023L)/1024L, 02094 (sf_malloc_max_memory+1023L)/1024L); 02095 #endif 02096 #ifndef EMBEDDED_LIBRARY 02097 VOID(my_net_write(net, buff,(uint) strlen(buff))); 02098 VOID(net_flush(net)); 02099 #endif 02100 break; 02101 } 02102 case COM_PING: 02103 statistic_increment(thd->status_var.com_other, &LOCK_status); 02104 send_ok(thd); // Tell client we are alive 02105 break; 02106 case COM_PROCESS_INFO: 02107 statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST], 02108 &LOCK_status); 02109 if (!thd->security_ctx->priv_user[0] && 02110 check_global_access(thd, PROCESS_ACL)) 02111 break; 02112 general_log_print(thd, command, NullS); 02113 mysqld_list_processes(thd, 02114 thd->security_ctx->master_access & PROCESS_ACL ? 02115 NullS : thd->security_ctx->priv_user, 0); 02116 break; 02117 case COM_PROCESS_KILL: 02118 { 02119 statistic_increment(thd->status_var.com_stat[SQLCOM_KILL], &LOCK_status); 02120 ulong id=(ulong) uint4korr(packet); 02121 sql_kill(thd,id,false); 02122 break; 02123 } 02124 case COM_SET_OPTION: 02125 { 02126 statistic_increment(thd->status_var.com_stat[SQLCOM_SET_OPTION], 02127 &LOCK_status); 02128 enum_mysql_set_option command= (enum_mysql_set_option) uint2korr(packet); 02129 switch (command) { 02130 case MYSQL_OPTION_MULTI_STATEMENTS_ON: 02131 thd->client_capabilities|= CLIENT_MULTI_STATEMENTS; 02132 send_eof(thd); 02133 break; 02134 case MYSQL_OPTION_MULTI_STATEMENTS_OFF: 02135 thd->client_capabilities&= ~CLIENT_MULTI_STATEMENTS; 02136 send_eof(thd); 02137 break; 02138 default: 02139 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 02140 break; 02141 } 02142 break; 02143 } 02144 case COM_DEBUG: 02145 statistic_increment(thd->status_var.com_other, &LOCK_status); 02146 if (check_global_access(thd, SUPER_ACL)) 02147 break; /* purecov: inspected */ 02148 mysql_print_status(); 02149 general_log_print(thd, command, NullS); 02150 send_eof(thd); 02151 break; 02152 case COM_SLEEP: 02153 case COM_CONNECT: // Impossible here 02154 case COM_TIME: // Impossible from client 02155 case COM_DELAYED_INSERT: 02156 case COM_END: 02157 default: 02158 my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); 02159 break; 02160 } 02161 if (thd->lock || thd->open_tables || thd->derived_tables || 02162 thd->prelocked_mode) 02163 { 02164 thd->proc_info="closing tables"; 02165 close_thread_tables(thd); /* Free tables */ 02166 } 02167 /* 02168 assume handlers auto-commit (if some doesn't - transaction handling 02169 in MySQL should be redesigned to support it; it's a big change, 02170 and it's not worth it - better to commit explicitly only writing 02171 transactions, read-only ones should better take care of themselves. 02172 saves some work in 2pc too) 02173 see also sql_base.cc - close_thread_tables() 02174 */ 02175 bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt)); 02176 if (!thd->active_transaction()) 02177 thd->transaction.xid_state.xid.null(); 02178 02179 /* report error issued during command execution */ 02180 if (thd->killed_errno() && !thd->net.report_error) 02181 thd->send_kill_message(); 02182 if (thd->net.report_error) 02183 net_send_error(thd); 02184 02185 log_slow_statement(thd); 02186 02187 thd->proc_info="cleaning up"; 02188 VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list 02189 thd->proc_info=0; 02190 thd->command=COM_SLEEP; 02191 thd->query=0; 02192 thd->query_length=0; 02193 thread_running--; 02194 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 02195 thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory 02196 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); 02197 DBUG_RETURN(error); 02198 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool do_command | ( | THD * | thd | ) |
Definition at line 1556 of file sql_parse.cc.
References aborted_threads, COM_END, command_name, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, dispatch_command(), st_net::error, FALSE, st_net::last_errno, LOCK_status, my_net_read(), net_new_transaction, net_send_error(), NullS, packet_error, st_net::read_pos, st_net::read_timeout, statistic_increment, TRUE, st_net::vio, and vio_description().
Referenced by handle_one_connection().
01557 { 01558 char *packet; 01559 uint old_timeout; 01560 ulong packet_length; 01561 NET *net; 01562 enum enum_server_command command; 01563 DBUG_ENTER("do_command"); 01564 01565 net= &thd->net; 01566 /* 01567 indicator of uninitialized lex => normal flow of errors handling 01568 (see my_message_sql) 01569 */ 01570 thd->lex->current_select= 0; 01571 01572 packet=0; 01573 old_timeout=net->read_timeout; 01574 /* Wait max for 8 hours */ 01575 net->read_timeout=(uint) thd->variables.net_wait_timeout; 01576 thd->clear_error(); // Clear error message 01577 01578 net_new_transaction(net); 01579 if ((packet_length=my_net_read(net)) == packet_error) 01580 { 01581 DBUG_PRINT("info",("Got error %d reading command from socket %s", 01582 net->error, 01583 vio_description(net->vio))); 01584 /* Check if we can continue without closing the connection */ 01585 if (net->error != 3) 01586 { 01587 statistic_increment(aborted_threads,&LOCK_status); 01588 DBUG_RETURN(TRUE); // We have to close it. 01589 } 01590 net_send_error(thd, net->last_errno, NullS); 01591 net->error= 0; 01592 DBUG_RETURN(FALSE); 01593 } 01594 else 01595 { 01596 packet=(char*) net->read_pos; 01597 command = (enum enum_server_command) (uchar) packet[0]; 01598 if (command >= COM_END) 01599 command= COM_END; // Wrong command 01600 DBUG_PRINT("info",("Command on %s = %d (%s)", 01601 vio_description(net->vio), command, 01602 command_name[command])); 01603 } 01604 net->read_timeout=old_timeout; // restore it 01605 /* 01606 packet_length contains length of data, as it was stored in packet 01607 header. In case of malformed header, packet_length can be zero. 01608 If packet_length is not zero, my_net_read ensures that this number 01609 of bytes was actually read from network. Additionally my_net_read 01610 sets packet[packet_length]= 0 (thus if packet_length == 0, 01611 command == packet[0] == COM_SLEEP). 01612 In dispatch_command packet[packet_length] points beyond the end of packet. 01613 */ 01614 DBUG_RETURN(dispatch_command(command,thd, packet+1, (uint) packet_length)); 01615 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool end_active_trans | ( | THD * | thd | ) |
Definition at line 139 of file sql_parse.cc.
References DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, ER_XAER_RMFAIL, error, ha_commit, my_error(), MYF, OPTION_BEGIN, OPTION_KEEP_LOG, OPTION_NOT_AUTOCOMMIT, OPTION_STATUS_NO_TRANS_UPDATE, OPTION_TABLE_LOCK, SERVER_STATUS_IN_TRANS, unlikely, and xa_state_names.
00140 { 00141 int error=0; 00142 DBUG_ENTER("end_active_trans"); 00143 if (unlikely(thd->in_sub_stmt)) 00144 { 00145 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); 00146 DBUG_RETURN(1); 00147 } 00148 if (thd->transaction.xid_state.xa_state != XA_NOTR) 00149 { 00150 my_error(ER_XAER_RMFAIL, MYF(0), 00151 xa_state_names[thd->transaction.xid_state.xa_state]); 00152 DBUG_RETURN(1); 00153 } 00154 if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN | 00155 OPTION_TABLE_LOCK)) 00156 { 00157 DBUG_PRINT("info",("options: 0x%lx", (ulong) thd->options)); 00158 /* Safety if one did "drop table" on locked tables */ 00159 if (!thd->locked_tables) 00160 thd->options&= ~OPTION_TABLE_LOCK; 00161 thd->server_status&= ~SERVER_STATUS_IN_TRANS; 00162 if (ha_commit(thd)) 00163 error=1; 00164 } 00165 thd->options&= ~(OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE | 00166 OPTION_KEEP_LOG); 00167 DBUG_RETURN(error); 00168 }
Here is the call graph for this function:

| int end_trans | ( | THD * | thd, | |
| enum enum_mysql_completiontype | completion | |||
| ) |
Definition at line 1480 of file sql_parse.cc.
References begin_trans(), COMMIT, COMMIT_AND_CHAIN, COMMIT_RELEASE, DBUG_ENTER, DBUG_RETURN, end_active_trans(), ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, ER_UNKNOWN_COM_ERROR, ER_XAER_RMFAIL, ha_commit, ha_rollback, KILL_CONNECTION, my_error(), MYF, OPTION_BEGIN, OPTION_KEEP_LOG, OPTION_STATUS_NO_TRANS_UPDATE, ROLLBACK, ROLLBACK_AND_CHAIN, ROLLBACK_RELEASE, SERVER_STATUS_IN_TRANS, unlikely, and xa_state_names.
01481 { 01482 bool do_release= 0; 01483 int res= 0; 01484 DBUG_ENTER("end_trans"); 01485 01486 if (unlikely(thd->in_sub_stmt)) 01487 { 01488 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0)); 01489 DBUG_RETURN(1); 01490 } 01491 if (thd->transaction.xid_state.xa_state != XA_NOTR) 01492 { 01493 my_error(ER_XAER_RMFAIL, MYF(0), 01494 xa_state_names[thd->transaction.xid_state.xa_state]); 01495 DBUG_RETURN(1); 01496 } 01497 switch (completion) { 01498 case COMMIT: 01499 /* 01500 We don't use end_active_trans() here to ensure that this works 01501 even if there is a problem with the OPTION_AUTO_COMMIT flag 01502 (Which of course should never happen...) 01503 */ 01504 thd->server_status&= ~SERVER_STATUS_IN_TRANS; 01505 res= ha_commit(thd); 01506 thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE | 01507 OPTION_KEEP_LOG); 01508 break; 01509 case COMMIT_RELEASE: 01510 do_release= 1; /* fall through */ 01511 case COMMIT_AND_CHAIN: 01512 res= end_active_trans(thd); 01513 if (!res && completion == COMMIT_AND_CHAIN) 01514 res= begin_trans(thd); 01515 break; 01516 case ROLLBACK_RELEASE: 01517 do_release= 1; /* fall through */ 01518 case ROLLBACK: 01519 case ROLLBACK_AND_CHAIN: 01520 { 01521 thd->server_status&= ~SERVER_STATUS_IN_TRANS; 01522 if (ha_rollback(thd)) 01523 res= -1; 01524 thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE | 01525 OPTION_KEEP_LOG); 01526 if (!res && (completion == ROLLBACK_AND_CHAIN)) 01527 res= begin_trans(thd); 01528 break; 01529 } 01530 default: 01531 res= -1; 01532 my_error(ER_UNKNOWN_COM_ERROR, MYF(0)); 01533 DBUG_RETURN(-1); 01534 } 01535 01536 if (res < 0) 01537 my_error(thd->killed_errno(), MYF(0)); 01538 else if ((res == 0) && do_release) 01539 thd->killed= THD::KILL_CONNECTION; 01540 01541 DBUG_RETURN(res); 01542 }
Here is the call graph for this function:

| void execute_init_command | ( | THD * | thd, | |
| sys_var_str * | init_command_var, | |||
| rw_lock_t * | var_mutex | |||
| ) |
Definition at line 1103 of file sql_parse.cc.
References CLIENT_MULTI_QUERIES, COM_QUERY, dispatch_command(), rw_rdlock, rw_unlock, sys_var_str::value, and sys_var_str::value_length.
Referenced by handle_one_connection().
01105 { 01106 Vio* save_vio; 01107 ulong save_client_capabilities; 01108 01109 thd->proc_info= "Execution of init_command"; 01110 /* 01111 We need to lock init_command_var because 01112 during execution of init_command_var query 01113 values of init_command_var can't be changed 01114 */ 01115 rw_rdlock(var_mutex); 01116 thd->query= init_command_var->value; 01117 thd->query_length= init_command_var->value_length; 01118 save_client_capabilities= thd->client_capabilities; 01119 thd->client_capabilities|= CLIENT_MULTI_QUERIES; 01120 /* 01121 We don't need return result of execution to client side. 01122 To forbid this we should set thd->net.vio to 0. 01123 */ 01124 save_vio= thd->net.vio; 01125 thd->net.vio= 0; 01126 thd->net.no_send_error= 0; 01127 dispatch_command(COM_QUERY, thd, thd->query, thd->query_length+1); 01128 rw_unlock(var_mutex); 01129 thd->client_capabilities= save_client_capabilities; 01130 thd->net.vio= save_vio; 01131 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static bool execute_sqlcom_select | ( | THD * | thd, | |
| TABLE_LIST * | all_tables | |||
| ) | [static] |
Definition at line 5236 of file sql_parse.cc.
References String::append(), DESCRIBE_EXTENDED, ER_YES, handle_select(), String::length(), mysql_explain_union(), open_and_lock_tables(), String::ptr(), push_warning(), system_charset_info, and MYSQL_ERROR::WARN_LEVEL_NOTE.
Referenced by mysql_execute_command().
05237 { 05238 LEX *lex= thd->lex; 05239 select_result *result=lex->result; 05240 bool res; 05241 /* assign global limit variable if limit is not given */ 05242 { 05243 SELECT_LEX *param= lex->unit.global_parameters; 05244 if (!param->explicit_limit) 05245 param->select_limit= 05246 new Item_int((ulonglong) thd->variables.select_limit); 05247 } 05248 if (!(res= open_and_lock_tables(thd, all_tables))) 05249 { 05250 if (lex->describe) 05251 { 05252 /* 05253 We always use select_send for EXPLAIN, even if it's an EXPLAIN 05254 for SELECT ... INTO OUTFILE: a user application should be able 05255 to prepend EXPLAIN to any query and receive output for it, 05256 even if the query itself redirects the output. 05257 */ 05258 if (!(result= new select_send())) 05259 return 1; /* purecov: inspected */ 05260 thd->send_explain_fields(result); 05261 res= mysql_explain_union(thd, &thd->lex->unit, result); 05262 if (lex->describe & DESCRIBE_EXTENDED) 05263 { 05264 char buff[1024]; 05265 String str(buff,(uint32) sizeof(buff), system_charset_info); 05266 str.length(0); 05267 thd->lex->unit.print(&str); 05268 str.append('\0'); 05269 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 05270 ER_YES, str.ptr()); 05271 } 05272 result->send_eof(); 05273 delete result; 05274 } 05275 else 05276 { 05277 if (!result && !(result= new select_send())) 05278 return 1; /* purecov: inspected */ 05279 query_cache_store_query(thd, all_tables); 05280 res= handle_select(thd, lex, result, 0); 05281 if (result != lex->result) 05282 delete result; 05283 } 05284 } 05285 return res; 05286 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void free_items | ( | Item * | item | ) |
Definition at line 1383 of file sql_parse.cc.
References DBUG_ENTER, DBUG_VOID_RETURN, Item::delete_self(), and Item::next.
01384 { 01385 Item *next; 01386 DBUG_ENTER("free_items"); 01387 for (; item ; item=next) 01388 { 01389 next=item->next; 01390 item->delete_self(); 01391 } 01392 DBUG_VOID_RETURN; 01393 }
Here is the call graph for this function:

| void free_max_user_conn | ( | void | ) |
Definition at line 616 of file sql_parse.cc.
References hash_free(), and hash_user_connections.
Referenced by clean_up().
00617 { 00618 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00619 hash_free(&hash_user_connections); 00620 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 00621 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void free_user | ( | struct user_conn * | uc | ) |
Definition at line 505 of file sql_parse.cc.
Referenced by init_max_user_conn().
Here is the caller graph for this function:

Definition at line 7818 of file sql_parse.cc.
References ER_OUTOFMEMORY, get_default_definer(), my_error(), MYF, and user.
07819 { 07820 LEX_USER *curr_user; 07821 if (!user->user.str) // current_user 07822 { 07823 if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(LEX_USER)))) 07824 { 07825 my_error(ER_OUTOFMEMORY, MYF(0), sizeof(LEX_USER)); 07826 return 0; 07827 } 07828 get_default_definer(thd, curr_user); 07829 return curr_user; 07830 } 07831 return user; 07832 }
Here is the call graph for this function:

| void get_default_definer | ( | THD * | thd, | |
| LEX_USER * | definer | |||
| ) |
Definition at line 7735 of file sql_parse.cc.
References st_lex_user::host, LEX_STRING::length, LEX_STRING::str, strlen(), and st_lex_user::user.
07736 { 07737 const Security_context *sctx= thd->security_ctx; 07738 07739 definer->user.str= (char *) sctx->priv_user; 07740 definer->user.length= strlen(definer->user.str); 07741 07742 definer->host.str= (char *) sctx->priv_host; 07743 definer->host.length= strlen(definer->host.str); 07744 }
Here is the call graph for this function:

Definition at line 498 of file sql_parse.cc.
References user_conn::len, and user_conn::user.
Referenced by init_max_user_conn().
Here is the caller graph for this function:

| static int get_or_create_user_conn | ( | THD * | thd, | |
| const char * | user, | |||
| const char * | host, | |||
| USER_RESOURCES * | mqh | |||
| ) | [static] |
Definition at line 224 of file sql_parse.cc.
References user_conn::conn_per_hour, user_conn::connections, DBUG_ASSERT, hash_search(), hash_user_connections, user_conn::host, user_conn::intime, user_conn::len, LOCK_user_conn, memcpy, my_free, my_hash_insert(), my_malloc(), MY_WME, MYF, net_send_error(), NullS, pthread_mutex_lock, pthread_mutex_unlock, user_conn::questions, strlen(), strmov(), user_conn::updates, user_conn::user, USER_HOST_BUFF_SIZE, and user_conn::user_resources.
Referenced by check_user().
00227 { 00228 int return_val= 0; 00229 uint temp_len, user_len; 00230 char temp_user[USER_HOST_BUFF_SIZE]; 00231 struct user_conn *uc; 00232 00233 DBUG_ASSERT(user != 0); 00234 DBUG_ASSERT(host != 0); 00235 00236 user_len= strlen(user); 00237 temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1; 00238 (void) pthread_mutex_lock(&LOCK_user_conn); 00239 if (!(uc = (struct user_conn *) hash_search(&hash_user_connections, 00240 (byte*) temp_user, temp_len))) 00241 { 00242 /* First connection for user; Create a user connection object */ 00243 if (!(uc= ((struct user_conn*) 00244 my_malloc(sizeof(struct user_conn) + temp_len+1, 00245 MYF(MY_WME))))) 00246 { 00247 net_send_error(thd, 0, NullS); // Out of memory 00248 return_val= 1; 00249 goto end; 00250 } 00251 uc->user=(char*) (uc+1); 00252 memcpy(uc->user,temp_user,temp_len+1); 00253 uc->host= uc->user + user_len + 1; 00254 uc->len= temp_len; 00255 uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0; 00256 uc->user_resources= *mqh; 00257 uc->intime= thd->thr_create_time; 00258 if (my_hash_insert(&hash_user_connections, (byte*) uc)) 00259 { 00260 my_free((char*) uc,0); 00261 net_send_error(thd, 0, NullS); // Out of memory 00262 return_val= 1; 00263 goto end; 00264 } 00265 } 00266 thd->user_connect=uc; 00267 uc->connections++; 00268 end: 00269 (void) pthread_mutex_unlock(&LOCK_user_conn); 00270 return return_val; 00271 00272 }
Here is the call graph for this function:

Here is the caller graph for this function:

| pthread_handler_t handle_bootstrap | ( | void * | arg | ) |
Definition at line 1271 of file sql_parse.cc.
References bootstrap_error, bootstrap_file, CLIENT_MULTI_RESULTS, close_connection(), close_thread_tables(), COND_thread_count, DBUG_ENTER, DBUG_RETURN, ER_NET_PACKET_TOO_LARGE, ER_OUT_OF_RESOURCES, free_root(), HA_POS_ERROR, LOCK_thread_count, my_isspace, MY_KEEP_PREALLOC, my_strdup(), my_thread_end(), my_thread_init(), MY_WME, MYF, mysql_parse(), net_end(), net_realloc(), net_send_error(), next_query_id(), NullS, OPTION_BIG_SELECTS, pthread_detach_this_thread, pthread_mutex_lock, pthread_mutex_unlock, refresh_version, sigemptyset, strlen(), thread_count, and VOID.
Referenced by bootstrap().
01272 { 01273 THD *thd=(THD*) arg; 01274 FILE *file=bootstrap_file; 01275 char *buff; 01276 01277 /* The following must be called before DBUG_ENTER */ 01278 thd->thread_stack= (char*) &thd; 01279 if (my_thread_init() || thd->store_globals()) 01280 { 01281 #ifndef EMBEDDED_LIBRARY 01282 close_connection(thd, ER_OUT_OF_RESOURCES, 1); 01283 #endif 01284 thd->fatal_error(); 01285 goto end; 01286 } 01287 DBUG_ENTER("handle_bootstrap"); 01288 01289 #ifndef EMBEDDED_LIBRARY 01290 pthread_detach_this_thread(); 01291 thd->thread_stack= (char*) &thd; 01292 #if !defined(__WIN__) && !defined(__NETWARE__) 01293 sigset_t set; 01294 VOID(sigemptyset(&set)); // Get mask in use 01295 VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals)); 01296 #endif 01297 #endif /* EMBEDDED_LIBRARY */ 01298 01299 if (thd->variables.max_join_size == HA_POS_ERROR) 01300 thd->options |= OPTION_BIG_SELECTS; 01301 01302 thd->proc_info=0; 01303 thd->version=refresh_version; 01304 thd->security_ctx->priv_user= 01305 thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); 01306 thd->security_ctx->priv_host[0]=0; 01307 /* 01308 Make the "client" handle multiple results. This is necessary 01309 to enable stored procedures with SELECTs and Dynamic SQL 01310 in init-file. 01311 */ 01312 thd->client_capabilities|= CLIENT_MULTI_RESULTS; 01313 01314 buff= (char*) thd->net.buff; 01315 thd->init_for_queries(); 01316 while (fgets(buff, thd->net.max_packet, file)) 01317 { 01318 ulong length= (ulong) strlen(buff); 01319 while (buff[length-1] != '\n' && !feof(file)) 01320 { 01321 /* 01322 We got only a part of the current string. Will try to increase 01323 net buffer then read the rest of the current string. 01324 */ 01325 if (net_realloc(&(thd->net), 2 * thd->net.max_packet)) 01326 { 01327 net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS); 01328 thd->fatal_error(); 01329 break; 01330 } 01331 buff= (char*) thd->net.buff; 01332 fgets(buff + length, thd->net.max_packet - length, file); 01333 length+= (ulong) strlen(buff + length); 01334 } 01335 if (thd->is_fatal_error) 01336 break; 01337 01338 while (length && (my_isspace(thd->charset(), buff[length-1]) || 01339 buff[length-1] == ';')) 01340 length--; 01341 buff[length]=0; 01342 thd->query_length=length; 01343 thd->query= thd->memdup_w_gap(buff, length+1, 01344 thd->db_length+1+QUERY_CACHE_FLAGS_SIZE); 01345 thd->query[length] = '\0'; 01346 /* 01347 We don't need to obtain LOCK_thread_count here because in bootstrap 01348 mode we have only one thread. 01349 */ 01350 thd->query_id=next_query_id(); 01351 mysql_parse(thd,thd->query,length); 01352 close_thread_tables(thd); // Free tables 01353 if (thd->is_fatal_error) 01354 break; 01355 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC)); 01356 #ifdef USING_TRANSACTIONS 01357 free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC)); 01358 #endif 01359 } 01360 01361 /* thd->fatal_error should be set in case something went wrong */ 01362 end: 01363 bootstrap_error= thd->is_fatal_error; 01364 01365 net_end(&thd->net); 01366 thd->cleanup(); 01367 delete thd; 01368 01369 #ifndef EMBEDDED_LIBRARY 01370 (void) pthread_mutex_lock(&LOCK_thread_count); 01371 thread_count--; 01372 (void) pthread_mutex_unlock(&LOCK_thread_count); 01373 (void) pthread_cond_broadcast(&COND_thread_count); 01374 my_thread_end(); 01375 pthread_exit(0); 01376 #endif 01377 DBUG_RETURN(0); 01378 }
Here is the call graph for this function:

Here is the caller graph for this function:

| pthread_handler_t handle_one_connection | ( | void * | arg | ) |
Definition at line 1134 of file sql_parse.cc.
References aborted_connects, aborted_threads, check_connection(), CLIENT_COMPRESS, close_connection(), COM_SLEEP, st_net::compress, current_thd, DBUG_PRINT, decrease_user_connections(), do_command(), end_thread(), ER, ER_NEW_ABORTING_CONNECTION, ER_OUT_OF_RESOURCES, ER_UNKNOWN_ERROR, st_net::error, error, execute_init_command(), HA_POS_ERROR, init_signals(), KILL_CONNECTION, st_net::last_errno, LOCK_status, LOCK_sys_init_connect, my_sleep(), my_thread_init(), net_printf_error(), net_send_error(), st_net::no_send_error, NULL, NullS, OPTION_BIG_SELECTS, pthread_detach_this_thread, refresh_version, st_net::report_error, sigemptyset, slow_launch_threads, slow_launch_time, sql_print_warning(), statistic_increment, SUPER_ACL, sys_init_connect, test_flags, TEST_NO_THREADS, sys_var_str::value_length, st_net::vio, vio_type(), VIO_TYPE_NAMEDPIPE, and VOID.
Referenced by create_new_thread().
01135 { 01136 THD *thd=(THD*) arg; 01137 uint launch_time = 01138 (uint) ((thd->thr_create_time = time(NULL)) - thd->connect_time); 01139 if (launch_time >= slow_launch_time) 01140 statistic_increment(slow_launch_threads,&LOCK_status ); 01141 01142 pthread_detach_this_thread(); 01143 01144 #if !defined( __WIN__) // Win32 calls this in pthread_create 01145 /* The following calls needs to be done before we call DBUG_ macros */ 01146 if (!(test_flags & TEST_NO_THREADS) & my_thread_init()) 01147 { 01148 close_connection(thd, ER_OUT_OF_RESOURCES, 1); 01149 statistic_increment(aborted_connects,&LOCK_status); 01150 end_thread(thd,0); 01151 return 0; 01152 } 01153 #endif 01154 01155 /* 01156 handle_one_connection() is the only way a thread would start 01157 and would always be on top of the stack, therefore, the thread 01158 stack always starts at the address of the first local variable 01159 of handle_one_connection, which is thd. We need to know the 01160 start of the stack so that we could check for stack overruns. 01161 */ 01162 DBUG_PRINT("info", ("handle_one_connection called by thread %d\n", 01163 thd->thread_id)); 01164 /* now that we've called my_thread_init(), it is safe to call DBUG_* */ 01165 01166 #if defined(__WIN__) 01167 init_signals(); 01168 #elif !defined(__NETWARE__) 01169 sigset_t set; 01170 VOID(sigemptyset(&set)); // Get mask in use 01171 VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals)); 01172 #endif 01173 thd->thread_stack= (char*) &thd; 01174 if (thd->store_globals()) 01175 { 01176 close_connection(thd, ER_OUT_OF_RESOURCES, 1); 01177 statistic_increment(aborted_connects,&LOCK_status); 01178 end_thread(thd,0); 01179 return 0; 01180 } 01181 01182 do 01183 { 01184 int error; 01185 NET *net= &thd->net; 01186 Security_context *sctx= thd->security_ctx; 01187 net->no_send_error= 0; 01188 01189 if ((error=check_connection(thd))) 01190 { // Wrong permissions 01191 if (error > 0) 01192 net_printf_error(thd, error, sctx->host_or_ip); 01193 #ifdef __NT__ 01194 if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) 01195 my_sleep(1000); /* must wait after eof() */ 01196 #endif 01197 statistic_increment(aborted_connects,&LOCK_status); 01198 goto end_thread; 01199 } 01200 #ifdef __NETWARE__ 01201 netware_reg_user(sctx->ip, sctx->user, "MySQL"); 01202 #endif 01203 if (thd->variables.max_join_size == HA_POS_ERROR) 01204 thd->options |= OPTION_BIG_SELECTS; 01205 if (thd->client_capabilities & CLIENT_COMPRESS) 01206 net->compress=1; // Use compression 01207 01208 thd->version= refresh_version; 01209 thd->proc_info= 0; 01210 thd->command= COM_SLEEP; 01211 thd->set_time(); 01212 thd->init_for_queries(); 01213 01214 if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL)) 01215 { 01216 execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect); 01217 if (thd->query_error) 01218 thd->killed= THD::KILL_CONNECTION; 01219 thd->proc_info=0; 01220 thd->set_time(); 01221 thd->init_for_queries(); 01222 } 01223 01224 while (!net->error && net->vio != 0 && 01225 !(thd->killed == THD::KILL_CONNECTION)) 01226 { 01227 net->no_send_error= 0; 01228 if (do_command(thd)) 01229 break; 01230 } 01231 if (thd->user_connect) 01232 decrease_user_connections(thd->user_connect); 01233 if (net->error && net->vio != 0 && net->report_error) 01234 { 01235 if (!thd->killed && thd->variables.log_warnings > 1) 01236 sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), 01237 thd->thread_id,(thd->db ? thd->db : "unconnected"), 01238 sctx->user ? sctx->user : "unauthenticated", 01239 sctx->host_or_ip, 01240 (net->last_errno ? ER(net->last_errno) : 01241 ER(ER_UNKNOWN_ERROR))); 01242 net_send_error(thd, net->last_errno, NullS); 01243 statistic_increment(aborted_threads,&LOCK_status); 01244 } 01245 else if (thd->killed) 01246 { 01247 statistic_increment(aborted_threads,&LOCK_status); 01248 } 01249 01250 end_thread: 01251 close_connection(thd, 0, 1); 01252 end_thread(thd,1); 01253 /* 01254 If end_thread returns, we are either running with --one-thread 01255 or this thread has been schedule to handle the next query 01256 */ 01257 thd= current_thd; 01258 thd->thread_stack= (char*) &thd; 01259 } while (!(test_flags & TEST_NO_THREADS)); 01260 /* The following is only executed if we are not using --one-thread */ 01261 return(0); /* purecov: deadcode */ 01262 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void init_max_user_conn | ( | void | ) |
Definition at line 510 of file sql_parse.cc.
References free_user(), get_key_conn(), hash_init, hash_user_connections, max_connections, and system_charset_info.
Referenced by init_server_components().
00511 { 00512 #ifndef NO_EMBEDDED_ACCESS_CHECKS 00513 (void) hash_init(&hash_user_connections,system_charset_info,max_connections, 00514 0,0, 00515 (hash_get_key) get_key_conn, (hash_free_key) free_user, 00516 0); 00517 #endif 00518 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void init_update_queries | ( | void | ) |
Definition at line 639 of file sql_parse.cc.
References bzero, SQLCOM_ALTER_EVENT, SQLCOM_ALTER_TABLE, SQLCOM_BACKUP_TABLE, SQLCOM_CALL, SQLCOM_CREATE_DB, SQLCOM_CREATE_EVENT, SQLCOM_CREATE_INDEX, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_VIEW, SQLCOM_DELETE, SQLCOM_DELETE_MULTI, SQLCOM_DROP_DB, SQLCOM_DROP_EVENT, SQLCOM_DROP_INDEX, SQLCOM_DROP_TABLE, SQLCOM_DROP_VIEW, SQLCOM_EXECUTE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT, SQLCOM_LOAD, SQLCOM_RENAME_TABLE, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_RESTORE_TABLE, SQLCOM_SHOW_CHARSETS, SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_EVENTS, SQLCOM_SHOW_FIELDS, SQLCOM_SHOW_KEYS, SQLCOM_SHOW_OPEN_TABLES, SQLCOM_SHOW_PLUGINS, SQLCOM_SHOW_STATUS, SQLCOM_SHOW_STATUS_FUNC, SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_TABLE_STATUS, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_TRIGGERS, SQLCOM_SHOW_VARIABLES, SQLCOM_TRUNCATE, SQLCOM_UPDATE, and SQLCOM_UPDATE_MULTI.
Referenced by init_server_components().
00640 { 00641 bzero((gptr) &sql_command_flags, sizeof(sql_command_flags)); 00642 00643 sql_command_flags[SQLCOM_CREATE_TABLE]= CF_CHANGES_DATA; 00644 sql_command_flags[SQLCOM_CREATE_INDEX]= CF_CHANGES_DATA; 00645 sql_command_flags[SQLCOM_ALTER_TABLE]= CF_CHANGES_DATA; 00646 sql_command_flags[SQLCOM_TRUNCATE]= CF_CHANGES_DATA; 00647 sql_command_flags[SQLCOM_DROP_TABLE]= CF_CHANGES_DATA; 00648 sql_command_flags[SQLCOM_LOAD]= CF_CHANGES_DATA; 00649 sql_command_flags[SQLCOM_CREATE_DB]= CF_CHANGES_DATA; 00650 sql_command_flags[SQLCOM_DROP_DB]= CF_CHANGES_DATA; 00651 sql_command_flags[SQLCOM_RENAME_TABLE]= CF_CHANGES_DATA; 00652 sql_command_flags[SQLCOM_BACKUP_TABLE]= CF_CHANGES_DATA; 00653 sql_command_flags[SQLCOM_RESTORE_TABLE]= CF_CHANGES_DATA; 00654 sql_command_flags[SQLCOM_DROP_INDEX]= CF_CHANGES_DATA; 00655 sql_command_flags[SQLCOM_CREATE_VIEW]= CF_CHANGES_DATA; 00656 sql_command_flags[SQLCOM_DROP_VIEW]= CF_CHANGES_DATA; 00657 sql_command_flags[SQLCOM_CREATE_EVENT]= CF_CHANGES_DATA; 00658 sql_command_flags[SQLCOM_ALTER_EVENT]= CF_CHANGES_DATA; 00659 sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA; 00660 00661 sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00662 sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00663 sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00664 sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00665 sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00666 sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00667 sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00668 sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT; 00669 00670 sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND; 00671 sql_command_flags[SQLCOM_SHOW_STATUS_FUNC]= CF_STATUS_COMMAND; 00672 sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND; 00673 sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND; 00674 sql_command_flags[SQLCOM_SHOW_TRIGGERS]= CF_STATUS_COMMAND; 00675 sql_command_flags[SQLCOM_SHOW_EVENTS]= CF_STATUS_COMMAND; 00676 sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND; 00677 sql_command_flags[SQLCOM_SHOW_PLUGINS]= CF_STATUS_COMMAND; 00678 sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND; 00679 sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND; 00680 sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND; 00681 sql_command_flags[SQLCOM_SHOW_CHARSETS]= CF_STATUS_COMMAND; 00682 sql_command_flags[SQLCOM_SHOW_COLLATIONS]= CF_STATUS_COMMAND; 00683 sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND; 00684 00685 sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND | 00686 CF_SHOW_TABLE_COMMAND); 00687 sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND | 00688 CF_SHOW_TABLE_COMMAND); 00689 00690 /* 00691 The following is used to preserver CF_ROW_COUNT during the 00692 a CALL or EXECUTE statement, so the value generated by the 00693 last called (or executed) statement is preserved. 00694 See mysql_execute_command() for how CF_ROW_COUNT is used. 00695 */ 00696 sql_command_flags[SQLCOM_CALL]= CF_HAS_ROW_COUNT; 00697 sql_command_flags[SQLCOM_EXECUTE]= CF_HAS_ROW_COUNT; 00698 }
Here is the caller graph for this function:

| bool insert_precheck | ( | THD * | thd, | |
| TABLE_LIST * | tables | |||
| ) |
Definition at line 7593 of file sql_parse.cc.
References check_one_table_access(), DBUG_ENTER, DBUG_RETURN, DELETE_ACL, DUP_REPLACE, ER, ER_WRONG_VALUE_COUNT, FALSE, INSERT_ACL, my_message(), MYF, TRUE, and UPDATE_ACL.
07594 { 07595 LEX *lex= thd->lex; 07596 DBUG_ENTER("insert_precheck"); 07597 07598 /* 07599 Check that we have modify privileges for the first table and 07600 select privileges for the rest 07601 */ 07602 ulong privilege= (INSERT_ACL | 07603 (lex->duplicates == DUP_REPLACE ? DELETE_ACL : 0) | 07604 (lex->value_list.elements ? UPDATE_ACL : 0)); 07605 07606 if (check_one_table_access(thd, privilege, tables)) 07607 DBUG_RETURN(TRUE); 07608 07609 if (lex->update_list.elements != lex->value_list.elements) 07610 { 07611 my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0)); 07612 DBUG_RETURN(TRUE); 07613 } 07614 DBUG_RETURN(FALSE); 07615 }
Here is the call graph for this function:

| bool is_update_query | ( | enum enum_sql_command | command | ) |
Definition at line 701 of file sql_parse.cc.
References DBUG_ASSERT, and SQLCOM_END.
Referenced by get_var_with_binlog(), and Prepared_statement::setup_set_params().
00702 { 00703 DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); 00704 return (sql_command_flags[command] & CF_CHANGES_DATA) != 0; 00705 }
Here is the caller graph for this function:

Definition at line 7123 of file sql_parse.cc.
References COM_DAEMON, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ER_KILL_DENIED_ERROR, ER_NO_SUCH_THREAD, KILL_CONNECTION, LOCK_thread_count, pthread_mutex_lock, pthread_mutex_unlock, strcmp(), SUPER_ACL, threads, and VOID.
07124 { 07125 THD *tmp; 07126 uint error=ER_NO_SUCH_THREAD; 07127 DBUG_ENTER("kill_one_thread"); 07128 DBUG_PRINT("enter", ("id=%lu only_kill=%d", id, only_kill_query)); 07129 VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list 07130 I_List_iterator<THD> it(threads); 07131 while ((tmp=it++)) 07132 { 07133 if (tmp->command == COM_DAEMON) 07134 continue; 07135 if (tmp->thread_id == id) 07136 { 07137 pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete 07138 break; 07139 } 07140 } 07141 VOID(pthread_mutex_unlock(&LOCK_thread_count)); 07142 if (tmp) 07143 { 07144 if ((thd->security_ctx->master_access & SUPER_ACL) || 07145 !strcmp(thd->security_ctx->user, tmp->security_ctx->user)) 07146 { 07147 tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION); 07148 error=0; 07149 } 07150 else 07151 error=ER_KILL_DENIED_ERROR; 07152 pthread_mutex_unlock(&tmp->LOCK_delete); 07153 } 07154 DBUG_PRINT("exit", ("%d", error)); 07155 DBUG_RETURN(error); 07156 }
Here is the call graph for this function:

| void log_slow_statement | ( | THD * | thd | ) |
Definition at line 2201 of file sql_parse.cc.
References DBUG_ENTER, DBUG_VOID_RETURN, SERVER_QUERY_NO_GOOD_INDEX_USED, SERVER_QUERY_NO_INDEX_USED, slow_log_print(), SPECIAL_LOG_QUERIES_NOT_USING_INDEXES, specialflag, and unlikely.
Referenced by dispatch_command(), and sp_instr_stmt::execute().
02202 { 02203 time_t start_of_query; 02204 DBUG_ENTER("log_slow_statement"); 02205 02206 /* 02207 The following should never be true with our current code base, 02208 but better to keep this here so we don't accidently try to log a 02209 statement in a trigger or stored function 02210 */ 02211 if (unlikely(thd->in_sub_stmt)) 02212 DBUG_VOID_RETURN; // Don't set time for sub stmt 02213 02214 start_of_query= thd->start_time; 02215 thd->end_time(); // Set start time 02216 02217 /* 02218 Do not log administrative statements unless the appropriate option is 02219 set; do not log into slow log if reading from backup. 02220 */ 02221 if (thd->enable_slow_log && !thd->user_time) 02222 { 02223 thd->proc_info="logging slow query"; 02224 02225 if ((ulong) (thd->start_time - thd->time_after_lock) > 02226 thd->variables.long_query_time || 02227 ((thd->server_status & 02228 (SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) && 02229 (specialflag & SPECIAL_LOG_QUERIES_NOT_USING_INDEXES))) 02230 { 02231 thd->status_var.long_query_count++; 02232 slow_log_print(thd, thd->query, thd->query_length, start_of_query); 02233 } 02234 } 02235 DBUG_VOID_RETURN; 02236 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool multi_delete_precheck | ( | THD * | thd, | |
| TABLE_LIST * | tables | |||
| ) |
Definition at line 7442 of file sql_parse.cc.
References check_table_access(), DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, DELETE_ACL, ER, ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, FALSE, my_message(), MYF, OPTION_SAFE_UPDATES, SELECT_ACL, and TRUE.
07443 { 07444 SELECT_LEX *select_lex= &thd->lex->select_lex; 07445 TABLE_LIST *aux_tables= 07446 (TABLE_LIST *)thd->lex->auxiliary_table_list.first; 07447 TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; 07448 DBUG_ENTER("multi_delete_precheck"); 07449 07450 /* sql_yacc guarantees that tables and aux_tables are not zero */ 07451 DBUG_ASSERT(aux_tables != 0); 07452 if (check_table_access(thd, SELECT_ACL, tables, 0)) 07453 DBUG_RETURN(TRUE); 07454 07455 /* 07456 Since aux_tables list is not part of LEX::query_tables list we 07457 have to juggle with LEX::query_tables_own_last value to be able 07458 call check_table_access() safely. 07459 */ 07460 thd->lex->query_tables_own_last= 0; 07461 if (check_table_access(thd, DELETE_ACL, aux_tables, 0)) 07462 { 07463 thd->lex->query_tables_own_last= save_query_tables_own_last; 07464 DBUG_RETURN(TRUE); 07465 } 07466 thd->lex->query_tables_own_last= save_query_tables_own_last; 07467 07468 if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) 07469 { 07470 my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, 07471 ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0)); 07472 DBUG_RETURN(TRUE); 07473 } 07474 DBUG_RETURN(FALSE); 07475 }
Here is the call graph for this function:

| bool multi_delete_set_locks_and_link_aux_tables | ( | LEX * | lex | ) |
Definition at line 7491 of file sql_parse.cc.
References st_table_list::alias, st_table_list::correspondent_table, st_table_list::db, DBUG_ENTER, DBUG_RETURN, st_table_list::derived, ER_UNKNOWN_TABLE, st_table_list::lock_type, my_error(), my_strcasecmp, MYF, st_table_list::next_local, st_table_list::select_lex, strcmp(), table_alias_charset, st_table_list::table_name, st_table_list::table_name_length, TRUE, and st_table_list::updating.
07492 { 07493 TABLE_LIST *tables= (TABLE_LIST*)lex->select_lex.table_list.first; 07494 TABLE_LIST *target_tbl; 07495 DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables"); 07496 07497 lex->table_count= 0; 07498 07499 for (target_tbl= (TABLE_LIST *)lex->auxiliary_table_list.first; 07500 target_tbl; target_tbl= target_tbl->next_local) 07501 { 07502 lex->table_count++; 07503 /* All tables in aux_tables must be found in FROM PART */ 07504 TABLE_LIST *walk; 07505 for (walk= tables; walk; walk= walk->next_local) 07506 { 07507 if (!my_strcasecmp(table_alias_charset, 07508 target_tbl->alias, walk->alias) && 07509 !strcmp(walk->db, target_tbl->db)) 07510 break; 07511 } 07512 if (!walk) 07513 { 07514 my_error(ER_UNKNOWN_TABLE, MYF(0), 07515 target_tbl->table_name, "MULTI DELETE"); 07516 DBUG_RETURN(TRUE); 07517 } 07518 if (!walk->derived) 07519 { 07520 target_tbl->table_name= walk->table_name; 07521 target_tbl->table_name_length= walk->table_name_length; 07522 } 07523 walk->updating= target_tbl->updating; 07524 walk->lock_type= target_tbl->lock_type; 07525 target_tbl->correspondent_table= walk; // Remember corresponding table 07526 } 07527 DBUG_RETURN(FALSE); 07528 }
Here is the call graph for this function:

| bool multi_update_precheck | ( | THD * | thd, | |
| TABLE_LIST * | tables | |||
| ) |
Definition at line 7362 of file sql_parse.cc.
References check_access(), check_grant(), st_table_list::db, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, st_table_list::derived, ER, ER_WRONG_VALUE_COUNT, st_table_list::grant, grant_option, my_message(), my_tz_check_n_skip_implicit_tables(), MYF, st_table_list::next_global, st_table_list::next_local, st_grant_info::privilege, st_table_list::schema_table, SELECT_ACL, st_table_list::select_lex, st_table_list::table_in_first_from_clause, test, TRUE, and UPDATE_ACL.
07363 { 07364 const char *msg= 0; 07365 TABLE_LIST *table; 07366 LEX *lex= thd->lex; 07367 SELECT_LEX *select_lex= &lex->select_lex; 07368 DBUG_ENTER("multi_update_precheck"); 07369 07370 if (select_lex->item_list.elements != lex->value_list.elements) 07371 { 07372 my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0)); 07373 DBUG_RETURN(TRUE); 07374 } 07375 /* 07376 Ensure that we have UPDATE or SELECT privilege for each table 07377 The exact privilege is checked in mysql_multi_update() 07378 */ 07379 for (table= tables; table; table= table->next_local) 07380 { 07381 if (table->derived) 07382 table->grant.privilege= SELECT_ACL; 07383 else if ((check_access(thd, UPDATE_ACL, table->db, 07384 &table->grant.privilege, 0, 1, 07385 test(table->schema_table)) || 07386 grant_option && 07387 check_grant(thd, UPDATE_ACL, table, 0, 1, 1)) && 07388 (check_access(thd, SELECT_ACL, table->db, 07389 &table->grant.privilege, 0, 0, 07390 test(table->schema_table)) || 07391 grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))) 07392 DBUG_RETURN(TRUE); 07393 07394 table->table_in_first_from_clause= 1; 07395 } 07396 /* 07397 Is there tables of subqueries? 07398 */ 07399 if (&lex->select_lex != lex->all_selects_list || lex->time_zone_tables_used) 07400 { 07401 DBUG_PRINT("info",("Checking sub query list")); 07402 for (table= tables; table; table= table->next_global) 07403 { 07404 if (!my_tz_check_n_skip_implicit_tables(&table, 07405 lex->time_zone_tables_used) && 07406 !table->table_in_first_from_clause) 07407 { 07408 if (check_access(thd, SELECT_ACL, table->db, 07409 &table->grant.privilege, 0, 0, 07410 test(table->schema_table)) || 07411 grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)) 07412 DBUG_RETURN(TRUE); 07413 } 07414 } 07415 } 07416 07417 if (select_lex->order_list.elements) 07418 msg= "ORDER BY"; 07419 else if (select_lex->select_limit) 07420 msg= "LIMIT"; 07421 if (msg) 07422 { 07423 my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg); 07424 DBUG_RETURN(TRUE); 07425 } 07426 DBUG_RETURN(FALSE); 07427 }
Here is the call graph for this function:

Definition at line 5790 of file sql_parse.cc.
References current_thd, memcpy, MY_ALLOW_ZERO_PTR, MY_FREE_ON_ERROR, my_realloc(), MY_YACC_INIT, MY_YACC_MAX, MYF, and set_zone().
05791 { 05792 LEX *lex= current_thd->lex; 05793 ulong old_info=0; 05794 if ((uint) *yystacksize >= MY_YACC_MAX) 05795 return 1; 05796 if (!lex->yacc_yyvs) 05797 old_info= *yystacksize; 05798 *yystacksize= set_zone((*yystacksize)*2,MY_YACC_INIT,MY_YACC_MAX); 05799 if (!(lex->yacc_yyvs= (char*) 05800 my_realloc((gptr) lex->yacc_yyvs, 05801 *yystacksize*sizeof(**yyvs), 05802 MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR))) || 05803 !(lex->yacc_yyss= (char*) 05804 my_realloc((gptr) lex->yacc_yyss, 05805 *yystacksize*sizeof(**yyss), 05806 MYF(MY_ALLOW_ZERO_PTR | MY_FREE_ON_ERROR)))) 05807 return 1; 05808 if (old_info) 05809 { // Copy old info from stack 05810 memcpy(lex->yacc_yyss, (gptr) *yyss, old_info*sizeof(**yyss)); 05811 memcpy(lex->yacc_yyvs, (gptr) *yyvs, old_info*sizeof(**yyvs)); 05812 } 05813 *yyss=(short*) lex->yacc_yyss; 05814 *yyvs=(YYSTYPE*) lex->yacc_yyvs; 05815 return 0; 05816 }
Here is the call graph for this function:

| bool mysql_create_index | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| List< Key > & | keys | |||
| ) |
Definition at line 7314 of file sql_parse.cc.
References bzero, st_table_list::db, DBUG_ENTER, DBUG_RETURN, keys, mysql_alter_table(), and st_table_list::table_name.
Referenced by mysql_execute_command().
07315 { 07316 List<create_field> fields; 07317 ALTER_INFO alter_info; 07318 alter_info.flags= ALTER_ADD_INDEX; 07319 HA_CREATE_INFO create_info; 07320 DBUG_ENTER("mysql_create_index"); 07321 bzero((char*) &create_info,sizeof(create_info)); 07322 create_info.db_type= 0; 07323 create_info.default_table_charset= thd->variables.collation_database; 07324 DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, 07325 &create_info, table_list, 07326 fields, keys, 0, (ORDER*)0, 07327 0, &alter_info, 1)); 07328 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_drop_index | ( | THD * | thd, | |
| TABLE_LIST * | table_list, | |||
| ALTER_INFO * | alter_info | |||
| ) |
Definition at line 7331 of file sql_parse.cc.
References bzero, st_table_list::db, DBUG_ENTER, DBUG_RETURN, keys, mysql_alter_table(), and st_table_list::table_name.
Referenced by mysql_execute_command().
07332 { 07333 List<create_field> fields; 07334 List<Key> keys; 07335 HA_CREATE_INFO create_info; 07336 DBUG_ENTER("mysql_drop_index"); 07337 bzero((char*) &create_info,sizeof(create_info)); 07338 create_info.db_type= 0; 07339 create_info.default_table_charset= thd->variables.collation_database; 07340 alter_info->clear(); 07341 alter_info->flags= ALTER_DROP_INDEX; 07342 DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->table_name, 07343 &create_info, table_list, 07344 fields, keys, 0, (ORDER*)0, 07345 0, alter_info, 1)); 07346 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool mysql_execute_command | ( | THD * | thd | ) |
Definition at line 2472 of file sql_parse.cc.
References add_diff_to_status(), alloc_root(), ALTER_ACL, ALTER_PROC_ACL, any_db, append_file_to_dir(), append_identifier(), begin_trans(), bzero, C_STRING_WITH_LEN, check_access(), Item::check_cols(), check_db_name(), check_global_access(), check_grant(), check_grant_routine(), check_merge_table_access(), check_one_table_access(), check_routine_access(), check_table_access(), CLIENT_LOCAL_FILES, CLIENT_MULTI_RESULTS, close_thread_tables(), COMMIT, COMMIT_AND_CHAIN, COMMIT_RELEASE, st_table_list::contain_auto_increment, CREATE_ACL, create_default_definer(), Events::create_event(), CREATE_PROC_ACL, create_table(), create_table_precheck(), CREATE_USER_ACL, db, st_table_list::db, st_table_list::db_length, Rpl_filter::db_ok(), Rpl_filter::db_ok_with_wild_table(), DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, DEFAULT_CREATE_PROC_ACLS, DELETE_ACL, delete_precheck(), DROP_ACL, Events::drop_event(), Events::dump_internal_status(), DUP_REPLACE, end_active_trans(), end_trans(), ER, ER_BAD_DB_ERROR, ER_BINLOG_UNSAFE_ROUTINE, ER_CANT_OPEN_LIBRARY, ER_ILLEGAL_GRANT_FOR_TABLE, ER_LOCK_OR_ACTIVE_TRANSACTION, ER_NO_DB_ERROR, ER_NO_SUCH_USER, ER_NOT_ALLOWED_COMMAND, ER_NOT_SUPPORTED_YET, ER_OPTION_PREVENTS_STATEMENT, ER_OUT_OF_RESOURCES, ER_PASSWORD_NOT_ALLOWED, ER_PROC_AUTO_GRANT_FAIL, ER_PROC_AUTO_REVOKE_FAIL, ER_RESERVED_SYNTAX, ER_SET_CONSTANTS_ONLY, ER_SLAVE_IGNORED_TABLE, ER_SP_ALREADY_EXISTS, ER_SP_BADSELECT, ER_SP_CANT_ALTER, ER_SP_DOES_NOT_EXIST, ER_SP_DROP_FAILED, ER_SP_STORE_FAILED, ER_SPECIFIC_ACCESS_DENIED_ERROR, ER_TOO_LONG_BODY, ER_TOO_LONG_IDENT, ER_UDF_EXISTS, ER_WARN_HOSTNAME_WONT_WORK, ER_WARNING_NOT_COMPLETE_ROLLBACK, ER_WRONG_ARGUMENTS, ER_WRONG_DB_NAME, ER_WRONG_TABLE_NAME, ER_XA_RBROLLBACK, ER_XAER_DUPID, ER_XAER_INVAL, ER_XAER_NOTA, ER_XAER_OUTSIDE, ER_XAER_RMERR, ER_XAER_RMFAIL, error, EVENT_ACL, EXECUTE_ACL, sp_head::execute_procedure(), execute_sqlcom_select(), EXTRA_ACL, FALSE, FILE_ACL, Item::fix_fields(), Item::fixed, partition_info::get_clone(), get_current_user(), global_status_var, st_table_list::grant, GRANT_ACL, grant_option, ha_commit, ha_commit_one_phase(), ha_commit_or_rollback_by_xid(), HA_CREATE_USED_CHARSET, HA_CREATE_USED_DEFAULT_CHARSET, HA_CREATE_USED_UNION, HA_ENGINE_LOGS, HA_ENGINE_MUTEX, HA_ENGINE_STATUS, HA_LEX_CREATE_TMP_TABLE, HA_POS_ERROR, ha_prepare(), ha_release_savepoint(), ha_rollback, ha_rollback_to_savepoint(), ha_savepoint(), ha_show_status(), handle_select(), hostname_requires_resolving(), INDEX_ACL, INSERT_ACL, insert_precheck(), Query_cache::invalidate_locked_for_write(), is_acl_user(), sp_head::is_not_allowed_in_function(), MYSQL_LOG::is_open(), LEX_STRING::length, LOCK_active_mi, LOCK_status, LOCK_TABLES_ACL, st_table_list::lock_type, lower_case_table_names, sp_head::m_chistics, sp_head::m_db, sp_head::m_flags, sp_head::m_name, sp_head::m_qname, sp_head::m_type, memcpy, multi_delete_precheck(), sp_head::MULTI_RESULTS, multi_update_precheck(), my_error(), my_message(), my_strcasecmp, my_strnncoll, MYF, mysql_alter_db(), mysql_alter_table(), mysql_alter_tablespace(), mysql_analyze_table(), mysql_assign_to_keycache(), mysql_backup_table(), mysql_bin_log, mysql_change_db(), mysql_check_table(), mysql_checksum_table(), mysql_client_binlog_statement(), mysql_create_db(), mysql_create_index(), mysql_create_like_table(), mysql_create_or_drop_trigger(), mysql_create_table(), mysql_create_user(), mysql_create_view(), mysql_delete(), mysql_do(), mysql_drop_index(), mysql_drop_user(), mysql_drop_view(), mysql_grant(), mysql_ha_close(), mysql_ha_open(), mysql_ha_read(), mysql_insert(), mysql_insert_select_prepare(), mysql_install_plugin(), mysql_load(), mysql_multi_delete_prepare(), mysql_multi_update(), mysql_multi_update_prepare(), mysql_optimize_table(), mysql_preload_keys(), mysql_recreate_table(), mysql_rename_db(), mysql_rename_tables(), mysql_rename_user(), mysql_repair_table(), mysql_reset_errors(), mysql_restore_table(), mysql_revoke_all(), mysql_rm_db(), mysql_rm_table(), mysql_routine_grant(), mysql_select(), mysql_show_grants(), mysql_sql_stmt_close(), mysql_sql_stmt_execute(), mysql_sql_stmt_prepare(), mysql_table_grant(), mysql_truncate(), mysql_uninstall_plugin(), mysql_unlock_tables(), mysql_update(), mysql_xa_recover(), mysqld_help(), mysqld_list_processes(), mysqld_show_authors(), mysqld_show_column_types(), mysqld_show_contributors(), mysqld_show_create(), mysqld_show_create_db(), mysqld_show_privileges(), mysqld_show_storage_engines(), mysqld_show_warnings(), name, charset_info_st::name, NAME_LEN, st_table_list::next_local, not_all_support_one_shot(), NULL, NullS, ONLY_KILL_QUERY, open_and_lock_tables(), opt_local_infile, opt_log_slow_admin_statements, opt_noacl, opt_readonly, opt_using_transactions, OPTION_BEGIN, OPTION_KEEP_LOG, OPTION_NOT_AUTOCOMMIT, OPTION_SETUP_TABLES_DONE, OPTION_STATUS_NO_TRANS_UPDATE, OPTION_TABLE_LOCK, st_grant_info::privilege, PROC_ACLS, PROCESS_ACL, pthread_mutex_lock, pthread_mutex_unlock, push_warning(), push_warning_printf(), query_cache, Item::quick_fix_field(), RELOAD_ACL, reload_acl_and_cache(), REPL_CLIENT_ACL, REPL_SLAVE_ACL, reset_mqh(), reset_one_shot_variables(), ROLLBACK, ROLLBACK_AND_CHAIN, ROLLBACK_RELEASE, rpl_filter, savepoint_alloc_size, st_table_list::schema_table, SELECT_ACL, select_limit, SELECT_NO_JOIN_CACHE, SELECT_NO_UNLOCK, send_ok(), SERVER_MORE_RESULTS_EXISTS, SERVER_QUERY_NO_GOOD_INDEX_USED, SERVER_QUERY_NO_INDEX_USED, SERVER_STATUS_IN_TRANS, Events::show_create_event(), sp_head::show_routine_code(), simple_open_n_lock_tables(), st_table_list::skip_temporary, some_non_temp_table_to_be_updated(), st_table_list::source, sp_automatic_privileges, SP_BAD_IDENTIFIER, SP_BODY_TOO_LONG, SP_COM_STRING, sp_drop_function(), sp_drop_procedure(), sp_find_routine(), sp_grant_privileges(), SP_INTERNAL_ERROR, SP_KEY_NOT_FOUND, SP_NO_DB_ERROR, SP_OK, sp_revoke_privileges(), sp_routine_exists_in_table(), sp_show_create_function(), sp_show_create_procedure(), sp_show_status_function(), sp_show_status_procedure(), SP_TYPE_STRING, sp_update_function(), sp_update_procedure(), SP_WRITE_ROW_FAILED, SPECIAL_NO_NEW_FUNC, SPECIAL_NO_RESOLVE, SPECIAL_SAFE_MODE, specialflag, sql_kill(), sql_set_variables(), SQLCOM_ALTER_DB, SQLCOM_ALTER_EVENT, SQLCOM_ALTER_FUNCTION, SQLCOM_ALTER_PROCEDURE, SQLCOM_ALTER_TABLE, SQLCOM_ALTER_TABLESPACE, SQLCOM_ANALYZE, SQLCOM_ASSIGN_TO_KEYCACHE, SQLCOM_BACKUP_TABLE, SQLCOM_BEGIN, SQLCOM_BINLOG_BASE64_EVENT, SQLCOM_CALL, SQLCOM_CHANGE_DB, SQLCOM_CHANGE_MASTER, SQLCOM_CHECK, SQLCOM_CHECKSUM, SQLCOM_COMMIT, SQLCOM_CREATE_DB, SQLCOM_CREATE_EVENT, SQLCOM_CREATE_FUNCTION, SQLCOM_CREATE_INDEX, SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_TRIGGER, SQLCOM_CREATE_USER, SQLCOM_CREATE_VIEW, SQLCOM_DEALLOCATE_PREPARE, SQLCOM_DELETE, SQLCOM_DELETE_MULTI, SQLCOM_DO, SQLCOM_DROP_DB, SQLCOM_DROP_EVENT, SQLCOM_DROP_FUNCTION, SQLCOM_DROP_INDEX, SQLCOM_DROP_PROCEDURE, SQLCOM_DROP_TABLE, SQLCOM_DROP_TRIGGER, SQLCOM_DROP_USER, SQLCOM_DROP_VIEW, SQLCOM_EMPTY_QUERY, SQLCOM_EXECUTE, SQLCOM_FLUSH, SQLCOM_GRANT, SQLCOM_HA_CLOSE, SQLCOM_HA_OPEN, SQLCOM_HA_READ, SQLCOM_HELP, SQLCOM_INSERT, SQLCOM_INSERT_SELECT, SQLCOM_INSTALL_PLUGIN, SQLCOM_KILL, SQLCOM_LOAD, SQLCOM_LOAD_MASTER_DATA, SQLCOM_LOAD_MASTER_TABLE, SQLCOM_LOCK_TABLES, SQLCOM_OPTIMIZE, SQLCOM_PRELOAD_KEYS, SQLCOM_PREPARE, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_RELEASE_SAVEPOINT, SQLCOM_RENAME_DB, SQLCOM_RENAME_TABLE, SQLCOM_RENAME_USER, SQLCOM_REPAIR, SQLCOM_REPLACE, SQLCOM_REPLACE_SELECT, SQLCOM_RESTORE_TABLE, SQLCOM_REVOKE, SQLCOM_REVOKE_ALL, SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT, SQLCOM_SAVEPOINT, SQLCOM_SELECT, SQLCOM_SET_OPTION, SQLCOM_SHOW_AUTHORS, SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_BINLOGS, SQLCOM_SHOW_CHARSETS, SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_CONTRIBUTORS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_CREATE_EVENT, SQLCOM_SHOW_CREATE_FUNC, SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_DATABASES, SQLCOM_SHOW_ENGINE_LOGS, SQLCOM_SHOW_ENGINE_MUTEX, SQLCOM_SHOW_ENGINE_STATUS, SQLCOM_SHOW_ERRORS, SQLCOM_SHOW_EVENTS, SQLCOM_SHOW_FIELDS, SQLCOM_SHOW_FUNC_CODE, SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_KEYS, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_NEW_MASTER, SQLCOM_SHOW_OPEN_TABLES, SQLCOM_SHOW_PLUGINS, SQLCOM_SHOW_PRIVILEGES, SQLCOM_SHOW_PROC_CODE, SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_SCHEDULER_STATUS, SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_SHOW_SLAVE_STAT, SQLCOM_SHOW_STATUS, SQLCOM_SHOW_STATUS_FUNC, SQLCOM_SHOW_STATUS_PROC, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_TABLE_STATUS, SQLCOM_SHOW_TABLES, SQLCOM_SHOW_TRIGGERS, SQLCOM_SHOW_VARIABLES, SQLCOM_SHOW_WARNS, SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, SQLCOM_TRUNCATE, SQLCOM_UNINSTALL_PLUGIN, SQLCOM_UNLOCK_TABLES, SQLCOM_UPDATE, SQLCOM_UPDATE_MULTI, SQLCOM_XA_COMMIT, SQLCOM_XA_END, SQLCOM_XA_PREPARE, SQLCOM_XA_RECOVER, SQLCOM_XA_ROLLBACK, SQLCOM_XA_START, start_waiting_global_read_lock(), statistic_increment, LEX_STRING::str, strcmp(), STRING_WITH_LEN, strip_sp(), strlen(), strmake_root(), SUPER_ACL, system_charset_info, st_table_list::table, st_table_list::table_name, st_table_list::table_name_length, test, test_all_bits, TL_WRITE, TL_WRITE_CONCURRENT_INSERT, TL_WRITE_DELAYED, TRUE, trust_function_creators, TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE, unique_table(), unlikely, unlock_global_read_lock(), unlock_locked_tables(), UPDATE_ACL, Events::update_event(), update_non_unique_table_error(), update_precheck(), st_lex_user::user, user, Item::val_int(), st_table_list::view, view_store_options(), wait_if_global_read_lock(), MYSQL_ERROR::WARN_LEVEL_ERROR, MYSQL_ERROR::WARN_LEVEL_NOTE, MYSQL_ERROR::WARN_LEVEL_WARN, where, st_table_list::where, write_to_binlog(), xa_state_names, xid_cache_delete(), xid_cache_insert(), and xid_cache_search().
Referenced by sp_instr_stmt::exec_core(), Prepared_statement::execute(), mysql_open_cursor(), and mysql_parse().
02473 { 02474 bool res= FALSE; 02475 bool need_start_waiting= FALSE; // have protection against global read lock 02476 int result= 0; 02477 LEX *lex= thd->lex; 02478 /* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */ 02479 SELECT_LEX *select_lex= &lex->select_lex; 02480 /* first table of first SELECT_LEX */ 02481 TABLE_LIST *first_table= (TABLE_LIST*) select_lex->table_list.first; 02482 /* list of all tables in query */ 02483 TABLE_LIST *all_tables; 02484 /* most outer SELECT_LEX_UNIT of query */ 02485 SELECT_LEX_UNIT *unit= &lex->unit; 02486 /* Saved variable value */ 02487 DBUG_ENTER("mysql_execute_command"); 02488 thd->net.no_send_error= 0; 02489 #ifdef WITH_PARTITION_STORAGE_ENGINE 02490 thd->work_part_info= 0; 02491 #endif 02492 02493 /* 02494 In many cases first table of main SELECT_LEX have special meaning => 02495 check that it is first table in global list and relink it first in 02496 queries_tables list if it is necessary (we need such relinking only 02497 for queries with subqueries in select list, in this case tables of 02498 subqueries will go to global list first) 02499 02500 all_tables will differ from first_table only if most upper SELECT_LEX 02501 do not contain tables. 02502 02503 Because of above in place where should be at least one table in most 02504 outer SELECT_LEX we have following check: 02505 DBUG_ASSERT(first_table == all_tables); 02506 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02507 */ 02508 lex->first_lists_tables_same(); 02509 /* should be assigned after making first tables same */ 02510 all_tables= lex->query_tables; 02511 /* set context for commands which do not use setup_tables */ 02512 select_lex-> 02513 context.resolve_in_table_list_only((TABLE_LIST*)select_lex-> 02514 table_list.first); 02515 02516 /* 02517 Reset warning count for each query that uses tables 02518 A better approach would be to reset this for any commands 02519 that is not a SHOW command or a select that only access local 02520 variables, but for now this is probably good enough. 02521 Don't reset warnings when executing a stored routine. 02522 */ 02523 if ((all_tables || &lex->select_lex != lex->all_selects_list || 02524 lex->sroutines.records) && !thd->spcont || 02525 lex->time_zone_tables_used) 02526 mysql_reset_errors(thd, 0); 02527 02528 #ifdef HAVE_REPLICATION 02529 if (unlikely(thd->slave_thread)) 02530 { 02531 /* 02532 Check if statment should be skipped because of slave filtering 02533 rules 02534 02535 Exceptions are: 02536 - UPDATE MULTI: For this statement, we want to check the filtering 02537 rules later in the code 02538 - SET: we always execute it (Not that many SET commands exists in 02539 the binary log anyway -- only 4.1 masters write SET statements, 02540 in 5.0 there are no SET statements in the binary log) 02541 - DROP TEMPORARY TABLE IF EXISTS: we always execute it (otherwise we 02542 have stale files on slave caused by exclusion of one tmp table). 02543 */ 02544 if (!(lex->sql_command == SQLCOM_UPDATE_MULTI) && 02545 !(lex->sql_command == SQLCOM_SET_OPTION) && 02546 !(lex->sql_command == SQLCOM_DROP_TABLE && 02547 lex->drop_temporary && lex->drop_if_exists) && 02548 all_tables_not_ok(thd, all_tables)) 02549 { 02550 /* we warn the slave SQL thread */ 02551 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 02552 reset_one_shot_variables(thd); 02553 DBUG_RETURN(0); 02554 } 02555 } 02556 else 02557 { 02558 #endif /* HAVE_REPLICATION */ 02559 /* 02560 When option readonly is set deny operations which change non-temporary 02561 tables. Except for the replication thread and the 'super' users. 02562 */ 02563 if (opt_readonly && 02564 !(thd->security_ctx->master_access & SUPER_ACL) && 02565 (sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) && 02566 !((lex->sql_command == SQLCOM_CREATE_TABLE) && 02567 (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) && 02568 ((lex->sql_command != SQLCOM_UPDATE_MULTI) && 02569 some_non_temp_table_to_be_updated(thd, all_tables))) 02570 { 02571 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); 02572 DBUG_RETURN(-1); 02573 } 02574 #ifdef HAVE_REPLICATION 02575 } /* endif unlikely slave */ 02576 #endif 02577 statistic_increment(thd->status_var.com_stat[lex->sql_command], 02578 &LOCK_status); 02579 02580 switch (lex->sql_command) { 02581 case SQLCOM_SHOW_EVENTS: 02582 if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0, 02583 is_schema_db(thd->lex->select_lex.db)))) 02584 break; 02585 /* fall through */ 02586 case SQLCOM_SHOW_STATUS_PROC: 02587 case SQLCOM_SHOW_STATUS_FUNC: 02588 res= execute_sqlcom_select(thd, all_tables); 02589 break; 02590 case SQLCOM_SHOW_STATUS: 02591 { 02592 system_status_var old_status_var= thd->status_var; 02593 thd->initial_status_var= &old_status_var; 02594 res= execute_sqlcom_select(thd, all_tables); 02595 /* Don't log SHOW STATUS commands to slow query log */ 02596 thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED | 02597 SERVER_QUERY_NO_GOOD_INDEX_USED); 02598 /* 02599 restore status variables, as we don't want 'show status' to cause 02600 changes 02601 */ 02602 pthread_mutex_lock(&LOCK_status); 02603 add_diff_to_status(&global_status_var, &thd->status_var, 02604 &old_status_var); 02605 thd->status_var= old_status_var; 02606 pthread_mutex_unlock(&LOCK_status); 02607 break; 02608 } 02609 case SQLCOM_SHOW_DATABASES: 02610 case SQLCOM_SHOW_TABLES: 02611 case SQLCOM_SHOW_TRIGGERS: 02612 case SQLCOM_SHOW_TABLE_STATUS: 02613 case SQLCOM_SHOW_OPEN_TABLES: 02614 case SQLCOM_SHOW_PLUGINS: 02615 case SQLCOM_SHOW_FIELDS: 02616 case SQLCOM_SHOW_KEYS: 02617 case SQLCOM_SHOW_VARIABLES: 02618 case SQLCOM_SHOW_CHARSETS: 02619 case SQLCOM_SHOW_COLLATIONS: 02620 case SQLCOM_SELECT: 02621 thd->status_var.last_query_cost= 0.0; 02622 if (all_tables) 02623 { 02624 res= check_table_access(thd, 02625 lex->exchange ? SELECT_ACL | FILE_ACL : 02626 SELECT_ACL, 02627 all_tables, 0); 02628 } 02629 else 02630 res= check_access(thd, 02631 lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, 02632 any_db, 0, 0, 0, 0); 02633 if (!res) 02634 res= execute_sqlcom_select(thd, all_tables); 02635 break; 02636 case SQLCOM_PREPARE: 02637 { 02638 mysql_sql_stmt_prepare(thd); 02639 break; 02640 } 02641 case SQLCOM_EXECUTE: 02642 { 02643 mysql_sql_stmt_execute(thd); 02644 break; 02645 } 02646 case SQLCOM_DEALLOCATE_PREPARE: 02647 { 02648 mysql_sql_stmt_close(thd); 02649 break; 02650 } 02651 case SQLCOM_DO: 02652 if (check_table_access(thd, SELECT_ACL, all_tables, 0) || 02653 open_and_lock_tables(thd, all_tables)) 02654 goto error; 02655 02656 res= mysql_do(thd, *lex->insert_list); 02657 break; 02658 02659 case SQLCOM_EMPTY_QUERY: 02660 send_ok(thd); 02661 break; 02662 02663 case SQLCOM_HELP: 02664 res= mysqld_help(thd,lex->help_arg); 02665 break; 02666 02667 #ifndef EMBEDDED_LIBRARY 02668 case SQLCOM_PURGE: 02669 { 02670 if (check_global_access(thd, SUPER_ACL)) 02671 goto error; 02672 /* PURGE MASTER LOGS TO 'file' */ 02673 res = purge_master_logs(thd, lex->to_log); 02674 break; 02675 } 02676 case SQLCOM_PURGE_BEFORE: 02677 { 02678 Item *it; 02679 02680 if (check_global_access(thd, SUPER_ACL)) 02681 goto error; 02682 /* PURGE MASTER LOGS BEFORE 'data' */ 02683 it= (Item *)lex->value_list.head(); 02684 if ((!it->fixed && it->fix_fields(lex->thd, &it)) || 02685 it->check_cols(1)) 02686 { 02687 my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE"); 02688 goto error; 02689 } 02690 it= new Item_func_unix_timestamp(it); 02691 /* 02692 it is OK only emulate fix_fieds, because we need only 02693 value of constant 02694 */ 02695 it->quick_fix_field(); 02696 res = purge_master_logs_before_date(thd, (ulong)it->val_int()); 02697 break; 02698 } 02699 #endif 02700 case SQLCOM_SHOW_WARNS: 02701 { 02702 res= mysqld_show_warnings(thd, (ulong) 02703 ((1L << (uint) MYSQL_ERROR::WARN_LEVEL_NOTE) | 02704 (1L << (uint) MYSQL_ERROR::WARN_LEVEL_WARN) | 02705 (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR) 02706 )); 02707 break; 02708 } 02709 case SQLCOM_SHOW_ERRORS: 02710 { 02711 res= mysqld_show_warnings(thd, (ulong) 02712 (1L << (uint) MYSQL_ERROR::WARN_LEVEL_ERROR)); 02713 break; 02714 } 02715 case SQLCOM_SHOW_NEW_MASTER: 02716 { 02717 if (check_global_access(thd, REPL_SLAVE_ACL)) 02718 goto error; 02719 /* This query don't work now. See comment in repl_failsafe.cc */ 02720 #ifndef WORKING_NEW_MASTER 02721 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "SHOW NEW MASTER"); 02722 goto error; 02723 #else 02724 res = show_new_master(thd); 02725 break; 02726 #endif 02727 } 02728 02729 #ifdef HAVE_REPLICATION 02730 case SQLCOM_SHOW_SLAVE_HOSTS: 02731 { 02732 if (check_global_access(thd, REPL_SLAVE_ACL)) 02733 goto error; 02734 res = show_slave_hosts(thd); 02735 break; 02736 } 02737 case SQLCOM_SHOW_BINLOG_EVENTS: 02738 { 02739 if (check_global_access(thd, REPL_SLAVE_ACL)) 02740 goto error; 02741 res = mysql_show_binlog_events(thd); 02742 break; 02743 } 02744 #endif 02745 02746 case SQLCOM_BACKUP_TABLE: 02747 { 02748 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02749 if (check_table_access(thd, SELECT_ACL, all_tables, 0) || 02750 check_global_access(thd, FILE_ACL)) 02751 goto error; /* purecov: inspected */ 02752 thd->enable_slow_log= opt_log_slow_admin_statements; 02753 res = mysql_backup_table(thd, first_table); 02754 select_lex->table_list.first= (byte*) first_table; 02755 lex->query_tables=all_tables; 02756 break; 02757 } 02758 case SQLCOM_RESTORE_TABLE: 02759 { 02760 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02761 if (check_table_access(thd, INSERT_ACL, all_tables, 0) || 02762 check_global_access(thd, FILE_ACL)) 02763 goto error; /* purecov: inspected */ 02764 thd->enable_slow_log= opt_log_slow_admin_statements; 02765 res = mysql_restore_table(thd, first_table); 02766 select_lex->table_list.first= (byte*) first_table; 02767 lex->query_tables=all_tables; 02768 break; 02769 } 02770 case SQLCOM_ASSIGN_TO_KEYCACHE: 02771 { 02772 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02773 if (check_access(thd, INDEX_ACL, first_table->db, 02774 &first_table->grant.privilege, 0, 0, 02775 test(first_table->schema_table))) 02776 goto error; 02777 res= mysql_assign_to_keycache(thd, first_table, &lex->ident); 02778 break; 02779 } 02780 case SQLCOM_PRELOAD_KEYS: 02781 { 02782 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02783 if (check_access(thd, INDEX_ACL, first_table->db, 02784 &first_table->grant.privilege, 0, 0, 02785 test(first_table->schema_table))) 02786 goto error; 02787 res = mysql_preload_keys(thd, first_table); 02788 break; 02789 } 02790 #ifdef HAVE_REPLICATION 02791 case SQLCOM_CHANGE_MASTER: 02792 { 02793 if (check_global_access(thd, SUPER_ACL)) 02794 goto error; 02795 pthread_mutex_lock(&LOCK_active_mi); 02796 res = change_master(thd,active_mi); 02797 pthread_mutex_unlock(&LOCK_active_mi); 02798 break; 02799 } 02800 case SQLCOM_SHOW_SLAVE_STAT: 02801 { 02802 /* Accept one of two privileges */ 02803 if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) 02804 goto error; 02805 pthread_mutex_lock(&LOCK_active_mi); 02806 res = show_master_info(thd,active_mi); 02807 pthread_mutex_unlock(&LOCK_active_mi); 02808 break; 02809 } 02810 case SQLCOM_SHOW_MASTER_STAT: 02811 { 02812 /* Accept one of two privileges */ 02813 if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL)) 02814 goto error; 02815 res = show_binlog_info(thd); 02816 break; 02817 } 02818 02819 case SQLCOM_LOAD_MASTER_DATA: // sync with master 02820 if (check_global_access(thd, SUPER_ACL)) 02821 goto error; 02822 if (end_active_trans(thd)) 02823 goto error; 02824 res = load_master_data(thd); 02825 break; 02826 #endif /* HAVE_REPLICATION */ 02827 case SQLCOM_SHOW_ENGINE_STATUS: 02828 { 02829 if (check_global_access(thd, SUPER_ACL)) 02830 goto error; 02831 res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_STATUS); 02832 break; 02833 } 02834 case SQLCOM_SHOW_ENGINE_MUTEX: 02835 { 02836 if (check_global_access(thd, SUPER_ACL)) 02837 goto error; 02838 res = ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_MUTEX); 02839 break; 02840 } 02841 #ifdef HAVE_REPLICATION 02842 case SQLCOM_LOAD_MASTER_TABLE: 02843 { 02844 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02845 DBUG_ASSERT(first_table->db); /* Must be set in the parser */ 02846 02847 if (check_access(thd, CREATE_ACL, first_table->db, 02848 &first_table->grant.privilege, 0, 0, 02849 test(first_table->schema_table))) 02850 goto error; /* purecov: inspected */ 02851 if (grant_option) 02852 { 02853 /* Check that the first table has CREATE privilege */ 02854 if (check_grant(thd, CREATE_ACL, all_tables, 0, 1, 0)) 02855 goto error; 02856 } 02857 if (strlen(first_table->table_name) > NAME_LEN) 02858 { 02859 my_error(ER_WRONG_TABLE_NAME, MYF(0), first_table->table_name); 02860 break; 02861 } 02862 pthread_mutex_lock(&LOCK_active_mi); 02863 /* 02864 fetch_master_table will send the error to the client on failure. 02865 Give error if the table already exists. 02866 */ 02867 if (!fetch_master_table(thd, first_table->db, first_table->table_name, 02868 active_mi, 0, 0)) 02869 { 02870 send_ok(thd); 02871 } 02872 pthread_mutex_unlock(&LOCK_active_mi); 02873 break; 02874 } 02875 #endif /* HAVE_REPLICATION */ 02876 02877 case SQLCOM_CREATE_TABLE: 02878 { 02879 /* If CREATE TABLE of non-temporary table, do implicit commit */ 02880 if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) 02881 { 02882 if (end_active_trans(thd)) 02883 { 02884 res= -1; 02885 break; 02886 } 02887 } 02888 DBUG_ASSERT(first_table == all_tables && first_table != 0); 02889 bool link_to_local; 02890 // Skip first table, which is the table we are creating 02891 TABLE_LIST *create_table= lex->unlink_first_table(&link_to_local); 02892 TABLE_LIST *select_tables= lex->query_tables; 02893 02894 if ((res= create_table_precheck(thd, select_tables, create_table))) 02895 goto end_with_restore_list; 02896 02897 #ifndef HAVE_READLINK 02898 lex->create_info.data_file_name=lex->create_info.index_file_name=0; 02899 #else 02900 /* Fix names if symlinked tables */ 02901 if (append_file_to_dir(thd, &lex->create_info.data_file_name, 02902 create_table->table_name) || 02903 append_file_to_dir(thd, &lex->create_info.index_file_name, 02904 create_table->table_name)) 02905 goto end_with_restore_list; 02906 #endif 02907 /* 02908 If we are using SET CHARSET without DEFAULT, add an implicit 02909 DEFAULT to not confuse old users. (This may change). 02910 */ 02911 if ((lex->create_info.used_fields & 02912 (HA_CREATE_USED_DEFAULT_CHARSET | HA_CREATE_USED_CHARSET)) == 02913 HA_CREATE_USED_CHARSET) 02914 { 02915 lex->create_info.used_fields&= ~HA_CREATE_USED_CHARSET; 02916 lex->create_info.used_fields|= HA_CREATE_USED_DEFAULT_CHARSET; 02917 lex->create_info.default_table_charset= lex->create_info.table_charset; 02918 lex->create_info.table_charset= 0; 02919 } 02920 /* 02921 The create-select command will open and read-lock the select table 02922 and then create, open and write-lock the new table. If a global 02923 read lock steps in, we get a deadlock. The write lock waits for 02924 the global read lock, while the global read lock waits for the 02925 select table to be closed. So we wait until the global readlock is 02926 gone before starting both steps. Note that 02927 wait_if_global_read_lock() sets a protection against a new global 02928 read lock when it succeeds. This needs to be released by 02929 start_waiting_global_read_lock(). We protect the normal CREATE 02930 TABLE in the same way. That way we avoid that a new table is 02931 created during a gobal read lock. 02932 */ 02933 if (!thd->locked_tables && 02934 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 02935 { 02936 res= 1; 02937 goto end_with_restore_list; 02938 } 02939 #ifdef WITH_PARTITION_STORAGE_ENGINE 02940 { 02941 partition_info *part_info= thd->lex->part_info; 02942 if (part_info && !(part_info= thd->lex->part_info->get_clone())) 02943 { 02944 res= -1; 02945 goto end_with_restore_list; 02946 } 02947 thd->work_part_info= part_info; 02948 } 02949 #endif 02950 if (select_lex->item_list.elements) // With select 02951 { 02952 select_result *result; 02953 02954 select_lex->options|= SELECT_NO_UNLOCK; 02955 unit->set_limit(select_lex); 02956 02957 if (!(res= open_and_lock_tables(thd, select_tables))) 02958 { 02959 /* 02960 Is table which we are changing used somewhere in other parts 02961 of query 02962 */ 02963 if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) 02964 { 02965 TABLE_LIST *duplicate; 02966 if ((duplicate= unique_table(thd, create_table, select_tables))) 02967 { 02968 update_non_unique_table_error(create_table, "CREATE", duplicate); 02969 res= 1; 02970 goto end_with_restore_list; 02971 } 02972 } 02973 /* If we create merge table, we have to test tables in merge, too */ 02974 if (lex->create_info.used_fields & HA_CREATE_USED_UNION) 02975 { 02976 TABLE_LIST *tab; 02977 for (tab= (TABLE_LIST*) lex->create_info.merge_list.first; 02978 tab; 02979 tab= tab->next_local) 02980 { 02981 TABLE_LIST *duplicate; 02982 if ((duplicate= unique_table(thd, tab, select_tables))) 02983 { 02984 update_non_unique_table_error(tab, "CREATE", duplicate); 02985 res= 1; 02986 goto end_with_restore_list; 02987 } 02988 } 02989 } 02990 02991 if ((result= new select_create(create_table, 02992 &lex->create_info, 02993 lex->create_list, 02994 lex->key_list, 02995 select_lex->item_list, 02996 lex->duplicates, 02997 lex->ignore))) 02998 { 02999 /* 03000 CREATE from SELECT give its SELECT_LEX for SELECT, 03001 and item_list belong to SELECT 03002 */ 03003 res= handle_select(thd, lex, result, 0); 03004 delete result; 03005 } 03006 /* reset for PS */ 03007 lex->create_list.empty(); 03008 lex->key_list.empty(); 03009 } 03010 } 03011 else 03012 { 03013 /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */ 03014 if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) 03015 thd->options|= OPTION_KEEP_LOG; 03016 /* regular create */ 03017 if (lex->like_name) 03018 res= mysql_create_like_table(thd, create_table, &lex->create_info, 03019 lex->like_name); 03020 else 03021 { 03022 res= mysql_create_table(thd, create_table->db, 03023 create_table->table_name, &lex->create_info, 03024 lex->create_list, 03025 lex->key_list, 0, 0, 1); 03026 } 03027 if (!res) 03028 send_ok(thd); 03029 } 03030 03031 /* put tables back for PS rexecuting */ 03032 end_with_restore_list: 03033 lex->link_first_table_back(create_table, link_to_local); 03034 break; 03035 } 03036 case SQLCOM_CREATE_INDEX: 03037 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03038 if (check_one_table_access(thd, INDEX_ACL, all_tables)) 03039 goto error; /* purecov: inspected */ 03040 thd->enable_slow_log= opt_log_slow_admin_statements; 03041 if (end_active_trans(thd)) 03042 goto error; 03043 res= mysql_create_index(thd, first_table, lex->key_list); 03044 break; 03045 03046 #ifdef HAVE_REPLICATION 03047 case SQLCOM_SLAVE_START: 03048 { 03049 pthread_mutex_lock(&LOCK_active_mi); 03050 start_slave(thd,active_mi,1 /* net report*/); 03051 pthread_mutex_unlock(&LOCK_active_mi); 03052 break; 03053 } 03054 case SQLCOM_SLAVE_STOP: 03055 /* 03056 If the client thread has locked tables, a deadlock is possible. 03057 Assume that 03058 - the client thread does LOCK TABLE t READ. 03059 - then the master updates t. 03060 - then the SQL slave thread wants to update t, 03061 so it waits for the client thread because t is locked by it. 03062 - then the client thread does SLAVE STOP. 03063 SLAVE STOP waits for the SQL slave thread to terminate its 03064 update t, which waits for the client thread because t is locked by it. 03065 To prevent that, refuse SLAVE STOP if the 03066 client thread has locked tables 03067 */ 03068 if (thd->locked_tables || thd->active_transaction() || thd->global_read_lock) 03069 { 03070 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03071 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03072 goto error; 03073 } 03074 { 03075 pthread_mutex_lock(&LOCK_active_mi); 03076 stop_slave(thd,active_mi,1/* net report*/); 03077 pthread_mutex_unlock(&LOCK_active_mi); 03078 break; 03079 } 03080 #endif /* HAVE_REPLICATION */ 03081 03082 case SQLCOM_ALTER_TABLE: 03083 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03084 #if defined(DONT_ALLOW_SHOW_COMMANDS) 03085 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 03086 MYF(0)); /* purecov: inspected */ 03087 goto error; 03088 #else 03089 { 03090 ulong priv=0; 03091 ulong priv_needed= ALTER_ACL; 03092 /* We also require DROP priv for ALTER TABLE ... DROP PARTITION */ 03093 if (lex->alter_info.flags & ALTER_DROP_PARTITION) 03094 priv_needed|= DROP_ACL; 03095 03096 if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN)) 03097 { 03098 my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name); 03099 goto error; 03100 } 03101 /* Must be set in the parser */ 03102 DBUG_ASSERT(select_lex->db); 03103 if (check_access(thd, priv_needed, first_table->db, 03104 &first_table->grant.privilege, 0, 0, 03105 test(first_table->schema_table)) || 03106 check_access(thd,INSERT_ACL | CREATE_ACL,select_lex->db,&priv,0,0, 03107 is_schema_db(select_lex->db))|| 03108 check_merge_table_access(thd, first_table->db, 03109 (TABLE_LIST *) 03110 lex->create_info.merge_list.first)) 03111 goto error; /* purecov: inspected */ 03112 if (grant_option) 03113 { 03114 if (check_grant(thd, priv_needed, all_tables, 0, UINT_MAX, 0)) 03115 goto error; 03116 if (lex->name && !test_all_bits(priv,INSERT_ACL | CREATE_ACL)) 03117 { // Rename of table 03118 TABLE_LIST tmp_table; 03119 bzero((char*) &tmp_table,sizeof(tmp_table)); 03120 tmp_table.table_name=lex->name; 03121 tmp_table.db=select_lex->db; 03122 tmp_table.grant.privilege=priv; 03123 if (check_grant(thd, INSERT_ACL | CREATE_ACL, &tmp_table, 0, 03124 UINT_MAX, 0)) 03125 goto error; 03126 } 03127 } 03128 /* Don't yet allow changing of symlinks with ALTER TABLE */ 03129 if (lex->create_info.data_file_name) 03130 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, 03131 "DATA DIRECTORY option ignored"); 03132 if (lex->create_info.index_file_name) 03133 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, 03134 "INDEX DIRECTORY option ignored"); 03135 lex->create_info.data_file_name=lex->create_info.index_file_name=0; 03136 /* ALTER TABLE ends previous transaction */ 03137 if (end_active_trans(thd)) 03138 goto error; 03139 03140 if (!thd->locked_tables && 03141 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 03142 { 03143 res= 1; 03144 break; 03145 } 03146 03147 thd->enable_slow_log= opt_log_slow_admin_statements; 03148 res= mysql_alter_table(thd, select_lex->db, lex->name, 03149 &lex->create_info, 03150 first_table, lex->create_list, 03151 lex->key_list, 03152 select_lex->order_list.elements, 03153 (ORDER *) select_lex->order_list.first, 03154 lex->ignore, &lex->alter_info, 1); 03155 break; 03156 } 03157 #endif /*DONT_ALLOW_SHOW_COMMANDS*/ 03158 case SQLCOM_RENAME_TABLE: 03159 { 03160 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03161 TABLE_LIST *table; 03162 for (table= first_table; table; table= table->next_local->next_local) 03163 { 03164 if (check_access(thd, ALTER_ACL | DROP_ACL, table->db, 03165 &table->grant.privilege,0,0, test(table->schema_table)) || 03166 check_access(thd, INSERT_ACL | CREATE_ACL, table->next_local->db, 03167 &table->next_local->grant.privilege, 0, 0, 03168 test(table->next_local->schema_table))) 03169 goto error; 03170 if (grant_option) 03171 { 03172 TABLE_LIST old_list, new_list; 03173 /* 03174 we do not need initialize old_list and new_list because we will 03175 come table[0] and table->next[0] there 03176 */ 03177 old_list= table[0]; 03178 new_list= table->next_local[0]; 03179 if (check_grant(thd, ALTER_ACL, &old_list, 0, 1, 0) || 03180 (!test_all_bits(table->next_local->grant.privilege, 03181 INSERT_ACL | CREATE_ACL) && 03182 check_grant(thd, INSERT_ACL | CREATE_ACL, &new_list, 0, 1, 0))) 03183 goto error; 03184 } 03185 } 03186 query_cache_invalidate3(thd, first_table, 0); 03187 if (end_active_trans(thd) || mysql_rename_tables(thd, first_table, 0)) 03188 goto error; 03189 break; 03190 } 03191 #ifndef EMBEDDED_LIBRARY 03192 case SQLCOM_SHOW_BINLOGS: 03193 #ifdef DONT_ALLOW_SHOW_COMMANDS 03194 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 03195 MYF(0)); /* purecov: inspected */ 03196 goto error; 03197 #else 03198 { 03199 if (check_global_access(thd, SUPER_ACL)) 03200 goto error; 03201 res = show_binlogs(thd); 03202 break; 03203 } 03204 #endif 03205 #endif /* EMBEDDED_LIBRARY */ 03206 case SQLCOM_SHOW_CREATE: 03207 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03208 #ifdef DONT_ALLOW_SHOW_COMMANDS 03209 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 03210 MYF(0)); /* purecov: inspected */ 03211 goto error; 03212 #else 03213 { 03214 /* Ignore temporary tables if this is "SHOW CREATE VIEW" */ 03215 if (lex->only_view) 03216 first_table->skip_temporary= 1; 03217 03218 if (check_access(thd, SELECT_ACL | EXTRA_ACL, first_table->db, 03219 &first_table->grant.privilege, 0, 0, 03220 test(first_table->schema_table))) 03221 goto error; 03222 if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0)) 03223 goto error; 03224 res= mysqld_show_create(thd, first_table); 03225 break; 03226 } 03227 #endif 03228 case SQLCOM_CHECKSUM: 03229 { 03230 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03231 if (check_table_access(thd, SELECT_ACL | EXTRA_ACL, all_tables, 0)) 03232 goto error; /* purecov: inspected */ 03233 res = mysql_checksum_table(thd, first_table, &lex->check_opt); 03234 break; 03235 } 03236 case SQLCOM_REPAIR: 03237 { 03238 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03239 if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) 03240 goto error; /* purecov: inspected */ 03241 thd->enable_slow_log= opt_log_slow_admin_statements; 03242 res= mysql_repair_table(thd, first_table, &lex->check_opt); 03243 /* ! we write after unlocking the table */ 03244 if (!res && !lex->no_write_to_binlog) 03245 { 03246 if (mysql_bin_log.is_open()) 03247 { 03248 thd->clear_error(); // No binlog error generated 03249 thd->binlog_query(THD::STMT_QUERY_TYPE, 03250 thd->query, thd->query_length, 0, FALSE); 03251 } 03252 } 03253 select_lex->table_list.first= (byte*) first_table; 03254 lex->query_tables=all_tables; 03255 break; 03256 } 03257 case SQLCOM_CHECK: 03258 { 03259 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03260 if (check_table_access(thd, SELECT_ACL | EXTRA_ACL , all_tables, 0)) 03261 goto error; /* purecov: inspected */ 03262 thd->enable_slow_log= opt_log_slow_admin_statements; 03263 res = mysql_check_table(thd, first_table, &lex->check_opt); 03264 select_lex->table_list.first= (byte*) first_table; 03265 lex->query_tables=all_tables; 03266 break; 03267 } 03268 case SQLCOM_ANALYZE: 03269 { 03270 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03271 if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) 03272 goto error; /* purecov: inspected */ 03273 thd->enable_slow_log= opt_log_slow_admin_statements; 03274 res= mysql_analyze_table(thd, first_table, &lex->check_opt); 03275 /* ! we write after unlocking the table */ 03276 if (!res && !lex->no_write_to_binlog) 03277 { 03278 if (mysql_bin_log.is_open()) 03279 { 03280 thd->clear_error(); // No binlog error generated 03281 thd->binlog_query(THD::STMT_QUERY_TYPE, 03282 thd->query, thd->query_length, 0, FALSE); 03283 } 03284 } 03285 select_lex->table_list.first= (byte*) first_table; 03286 lex->query_tables=all_tables; 03287 break; 03288 } 03289 03290 case SQLCOM_OPTIMIZE: 03291 { 03292 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03293 if (check_table_access(thd, SELECT_ACL | INSERT_ACL, all_tables, 0)) 03294 goto error; /* purecov: inspected */ 03295 thd->enable_slow_log= opt_log_slow_admin_statements; 03296 res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? 03297 mysql_recreate_table(thd, first_table, 1) : 03298 mysql_optimize_table(thd, first_table, &lex->check_opt); 03299 /* ! we write after unlocking the table */ 03300 if (!res && !lex->no_write_to_binlog) 03301 { 03302 if (mysql_bin_log.is_open()) 03303 { 03304 thd->clear_error(); // No binlog error generated 03305 thd->binlog_query(THD::STMT_QUERY_TYPE, 03306 thd->query, thd->query_length, 0, FALSE); 03307 } 03308 } 03309 select_lex->table_list.first= (byte*) first_table; 03310 lex->query_tables=all_tables; 03311 break; 03312 } 03313 case SQLCOM_UPDATE: 03314 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03315 if (update_precheck(thd, all_tables)) 03316 break; 03317 DBUG_ASSERT(select_lex->offset_limit == 0); 03318 unit->set_limit(select_lex); 03319 res= (result= mysql_update(thd, all_tables, 03320 select_lex->item_list, 03321 lex->value_list, 03322 select_lex->where, 03323 select_lex->order_list.elements, 03324 (ORDER *) select_lex->order_list.first, 03325 unit->select_limit_cnt, 03326 lex->duplicates, lex->ignore)); 03327 /* mysql_update return 2 if we need to switch to multi-update */ 03328 if (result != 2) 03329 break; 03330 case SQLCOM_UPDATE_MULTI: 03331 { 03332 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03333 /* if we switched from normal update, rights are checked */ 03334 if (result != 2) 03335 { 03336 if ((res= multi_update_precheck(thd, all_tables))) 03337 break; 03338 } 03339 else 03340 res= 0; 03341 03342 res= mysql_multi_update_prepare(thd); 03343 03344 #ifdef HAVE_REPLICATION 03345 /* Check slave filtering rules */ 03346 if (unlikely(thd->slave_thread)) 03347 { 03348 if (all_tables_not_ok(thd, all_tables)) 03349 { 03350 if (res!= 0) 03351 { 03352 res= 0; /* don't care of prev failure */ 03353 thd->clear_error(); /* filters are of highest prior */ 03354 } 03355 /* we warn the slave SQL thread */ 03356 my_error(ER_SLAVE_IGNORED_TABLE, MYF(0)); 03357 break; 03358 } 03359 if (res) 03360 break; 03361 } 03362 else 03363 { 03364 #endif /* HAVE_REPLICATION */ 03365 if (res) 03366 break; 03367 if (opt_readonly && 03368 !(thd->security_ctx->master_access & SUPER_ACL) && 03369 some_non_temp_table_to_be_updated(thd, all_tables)) 03370 { 03371 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); 03372 break; 03373 } 03374 #ifdef HAVE_REPLICATION 03375 } /* unlikely */ 03376 #endif 03377 03378 res= mysql_multi_update(thd, all_tables, 03379 &select_lex->item_list, 03380 &lex->value_list, 03381 select_lex->where, 03382 select_lex->options, 03383 lex->duplicates, lex->ignore, unit, select_lex); 03384 break; 03385 } 03386 case SQLCOM_REPLACE: 03387 case SQLCOM_INSERT: 03388 { 03389 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03390 if ((res= insert_precheck(thd, all_tables))) 03391 break; 03392 /* Skip first table, which is the table we are inserting in */ 03393 select_lex->context.table_list= first_table->next_local; 03394 03395 if (!thd->locked_tables && 03396 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 03397 { 03398 res= 1; 03399 break; 03400 } 03401 03402 res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, 03403 lex->update_list, lex->value_list, 03404 lex->duplicates, lex->ignore); 03405 /* do not show last insert ID if VIEW does not have auto_inc */ 03406 if (first_table->view && !first_table->contain_auto_increment) 03407 thd->first_successful_insert_id_in_cur_stmt= 0; 03408 break; 03409 } 03410 case SQLCOM_REPLACE_SELECT: 03411 case SQLCOM_INSERT_SELECT: 03412 { 03413 select_result *result; 03414 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03415 if ((res= insert_precheck(thd, all_tables))) 03416 break; 03417 03418 /* Fix lock for first table */ 03419 if (first_table->lock_type == TL_WRITE_DELAYED) 03420 first_table->lock_type= TL_WRITE; 03421 03422 /* Don't unlock tables until command is written to binary log */ 03423 select_lex->options|= SELECT_NO_UNLOCK; 03424 03425 unit->set_limit(select_lex); 03426 03427 if (! thd->locked_tables && 03428 ! (need_start_waiting= ! wait_if_global_read_lock(thd, 0, 1))) 03429 { 03430 res= 1; 03431 break; 03432 } 03433 03434 if (!(res= open_and_lock_tables(thd, all_tables))) 03435 { 03436 /* Skip first table, which is the table we are inserting in */ 03437 TABLE_LIST *second_table= first_table->next_local; 03438 select_lex->table_list.first= (byte*) second_table; 03439 select_lex->context.table_list= 03440 select_lex->context.first_name_resolution_table= second_table; 03441 res= mysql_insert_select_prepare(thd); 03442 if (!res && (result= new select_insert(first_table, first_table->table, 03443 &lex->field_list, 03444 &lex->update_list, 03445 &lex->value_list, 03446 lex->duplicates, lex->ignore))) 03447 { 03448 res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE); 03449 /* 03450 Invalidate the table in the query cache if something changed 03451 after unlocking when changes become visible. 03452 TODO: this is workaround. right way will be move invalidating in 03453 the unlock procedure. 03454 */ 03455 if (first_table->lock_type == TL_WRITE_CONCURRENT_INSERT && 03456 thd->lock) 03457 { 03458 mysql_unlock_tables(thd, thd->lock); 03459 query_cache_invalidate3(thd, first_table, 1); 03460 thd->lock=0; 03461 } 03462 delete result; 03463 } 03464 /* revert changes for SP */ 03465 select_lex->table_list.first= (byte*) first_table; 03466 } 03467 /* do not show last insert ID if VIEW does not have auto_inc */ 03468 if (first_table->view && !first_table->contain_auto_increment) 03469 thd->first_successful_insert_id_in_cur_stmt= 0; 03470 break; 03471 } 03472 case SQLCOM_TRUNCATE: 03473 if (end_active_trans(thd)) 03474 { 03475 res= -1; 03476 break; 03477 } 03478 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03479 if (check_one_table_access(thd, DELETE_ACL, all_tables)) 03480 goto error; 03481 /* 03482 Don't allow this within a transaction because we want to use 03483 re-generate table 03484 */ 03485 if (thd->locked_tables || thd->active_transaction()) 03486 { 03487 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03488 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03489 goto error; 03490 } 03491 03492 res= mysql_truncate(thd, first_table, 0); 03493 break; 03494 case SQLCOM_DELETE: 03495 { 03496 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03497 if ((res= delete_precheck(thd, all_tables))) 03498 break; 03499 DBUG_ASSERT(select_lex->offset_limit == 0); 03500 unit->set_limit(select_lex); 03501 03502 if (!thd->locked_tables && 03503 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 03504 { 03505 res= 1; 03506 break; 03507 } 03508 03509 res = mysql_delete(thd, all_tables, select_lex->where, 03510 &select_lex->order_list, 03511 unit->select_limit_cnt, select_lex->options, 03512 FALSE); 03513 break; 03514 } 03515 case SQLCOM_DELETE_MULTI: 03516 { 03517 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03518 TABLE_LIST *aux_tables= 03519 (TABLE_LIST *)thd->lex->auxiliary_table_list.first; 03520 multi_delete *result; 03521 03522 if (!thd->locked_tables && 03523 !(need_start_waiting= !wait_if_global_read_lock(thd, 0, 1))) 03524 { 03525 res= 1; 03526 break; 03527 } 03528 03529 if ((res= multi_delete_precheck(thd, all_tables))) 03530 break; 03531 03532 /* condition will be TRUE on SP re-excuting */ 03533 if (select_lex->item_list.elements != 0) 03534 select_lex->item_list.empty(); 03535 if (add_item_to_list(thd, new Item_null())) 03536 goto error; 03537 03538 thd->proc_info="init"; 03539 if ((res= open_and_lock_tables(thd, all_tables))) 03540 break; 03541 03542 if ((res= mysql_multi_delete_prepare(thd))) 03543 goto error; 03544 03545 if (!thd->is_fatal_error && (result= new multi_delete(aux_tables, 03546 lex->table_count))) 03547 { 03548 res= mysql_select(thd, &select_lex->ref_pointer_array, 03549 select_lex->get_table_list(), 03550 select_lex->with_wild, 03551 select_lex->item_list, 03552 select_lex->where, 03553 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL, 03554 (ORDER *)NULL, 03555 select_lex->options | thd->options | 03556 SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | 03557 OPTION_SETUP_TABLES_DONE, 03558 result, unit, select_lex); 03559 delete result; 03560 } 03561 else 03562 res= TRUE; // Error 03563 break; 03564 } 03565 case SQLCOM_DROP_TABLE: 03566 { 03567 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03568 if (!lex->drop_temporary) 03569 { 03570 if (check_table_access(thd, DROP_ACL, all_tables, 0)) 03571 goto error; /* purecov: inspected */ 03572 if (end_active_trans(thd)) 03573 goto error; 03574 } 03575 else 03576 { 03577 /* 03578 If this is a slave thread, we may sometimes execute some 03579 DROP / * 40005 TEMPORARY * / TABLE 03580 that come from parts of binlogs (likely if we use RESET SLAVE or CHANGE 03581 MASTER TO), while the temporary table has already been dropped. 03582 To not generate such irrelevant "table does not exist errors", 03583 we silently add IF EXISTS if TEMPORARY was used. 03584 */ 03585 if (thd->slave_thread) 03586 lex->drop_if_exists= 1; 03587 03588 /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ 03589 thd->options|= OPTION_KEEP_LOG; 03590 } 03591 res= mysql_rm_table(thd, first_table, lex->drop_if_exists, 03592 lex->drop_temporary); 03593 } 03594 break; 03595 case SQLCOM_DROP_INDEX: 03596 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03597 if (check_one_table_access(thd, INDEX_ACL, all_tables)) 03598 goto error; /* purecov: inspected */ 03599 if (end_active_trans(thd)) 03600 goto error; 03601 res= mysql_drop_index(thd, first_table, &lex->alter_info); 03602 break; 03603 case SQLCOM_SHOW_PROCESSLIST: 03604 if (!thd->security_ctx->priv_user[0] && 03605 check_global_access(thd,PROCESS_ACL)) 03606 break; 03607 mysqld_list_processes(thd, 03608 (thd->security_ctx->master_access & PROCESS_ACL ? 03609 NullS : 03610 thd->security_ctx->priv_user), 03611 lex->verbose); 03612 break; 03613 case SQLCOM_SHOW_STORAGE_ENGINES: 03614 res= mysqld_show_storage_engines(thd); 03615 break; 03616 case SQLCOM_SHOW_AUTHORS: 03617 res= mysqld_show_authors(thd); 03618 break; 03619 case SQLCOM_SHOW_CONTRIBUTORS: 03620 res= mysqld_show_contributors(thd); 03621 break; 03622 case SQLCOM_SHOW_PRIVILEGES: 03623 res= mysqld_show_privileges(thd); 03624 break; 03625 case SQLCOM_SHOW_COLUMN_TYPES: 03626 res= mysqld_show_column_types(thd); 03627 break; 03628 case SQLCOM_SHOW_ENGINE_LOGS: 03629 #ifdef DONT_ALLOW_SHOW_COMMANDS 03630 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), 03631 MYF(0)); /* purecov: inspected */ 03632 goto error; 03633 #else 03634 { 03635 if (grant_option && check_access(thd, FILE_ACL, any_db,0,0,0,0)) 03636 goto error; 03637 res= ha_show_status(thd, lex->create_info.db_type, HA_ENGINE_LOGS); 03638 break; 03639 } 03640 #endif 03641 case SQLCOM_CHANGE_DB: 03642 if (!mysql_change_db(thd,select_lex->db,FALSE)) 03643 send_ok(thd); 03644 break; 03645 03646 case SQLCOM_LOAD: 03647 { 03648 DBUG_ASSERT(first_table == all_tables && first_table != 0); 03649 uint privilege= (lex->duplicates == DUP_REPLACE ? 03650 INSERT_ACL | DELETE_ACL : INSERT_ACL) | 03651 (lex->local_file ? 0 : FILE_ACL); 03652 03653 if (lex->local_file) 03654 { 03655 if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) || 03656 !opt_local_infile) 03657 { 03658 my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); 03659 goto error; 03660 } 03661 } 03662 03663 if (check_one_table_access(thd, privilege, all_tables)) 03664 goto error; 03665 03666 res= mysql_load(thd, lex->exchange, first_table, lex->field_list, 03667 lex->update_list, lex->value_list, lex->duplicates, 03668 lex->ignore, (bool) lex->local_file); 03669 break; 03670 } 03671 03672 case SQLCOM_SET_OPTION: 03673 { 03674 List<set_var_base> *lex_var_list= &lex->var_list; 03675 if ((check_table_access(thd, SELECT_ACL, all_tables, 0) || 03676 open_and_lock_tables(thd, all_tables))) 03677 goto error; 03678 if (lex->one_shot_set && not_all_support_one_shot(lex_var_list)) 03679 { 03680 my_error(ER_RESERVED_SYNTAX, MYF(0), "SET ONE_SHOT"); 03681 goto error; 03682 } 03683 if (!(res= sql_set_variables(thd, lex_var_list))) 03684 { 03685 /* 03686 If the previous command was a SET ONE_SHOT, we don't want to forget 03687 about the ONE_SHOT property of that SET. So we use a |= instead of = . 03688 */ 03689 thd->one_shot_set|= lex->one_shot_set; 03690 send_ok(thd); 03691 } 03692 break; 03693 } 03694 03695 case SQLCOM_UNLOCK_TABLES: 03696 /* 03697 It is critical for mysqldump --single-transaction --master-data that 03698 UNLOCK TABLES does not implicitely commit a connection which has only 03699 done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes 03700 false, mysqldump will not work. 03701 */ 03702 unlock_locked_tables(thd); 03703 if (thd->options & OPTION_TABLE_LOCK) 03704 { 03705 end_active_trans(thd); 03706 thd->options&= ~(ulong) (OPTION_TABLE_LOCK); 03707 } 03708 if (thd->global_read_lock) 03709 unlock_global_read_lock(thd); 03710 send_ok(thd); 03711 break; 03712 case SQLCOM_LOCK_TABLES: 03713 unlock_locked_tables(thd); 03714 if (end_active_trans(thd)) 03715 goto error; 03716 if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, 0)) 03717 goto error; 03718 thd->in_lock_tables=1; 03719 thd->options|= OPTION_TABLE_LOCK; 03720 03721 if (!(res= simple_open_n_lock_tables(thd, all_tables))) 03722 { 03723 #ifdef HAVE_QUERY_CACHE 03724 if (thd->variables.query_cache_wlock_invalidate) 03725 query_cache.invalidate_locked_for_write(first_table); 03726 #endif /*HAVE_QUERY_CACHE*/ 03727 thd->locked_tables=thd->lock; 03728 thd->lock=0; 03729 send_ok(thd); 03730 } 03731 else 03732 thd->options&= ~(ulong) (OPTION_TABLE_LOCK); 03733 thd->in_lock_tables=0; 03734 break; 03735 case SQLCOM_CREATE_DB: 03736 { 03737 if (end_active_trans(thd)) 03738 { 03739 res= -1; 03740 break; 03741 } 03742 char *alias; 03743 if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name)) 03744 { 03745 my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); 03746 break; 03747 } 03748 /* 03749 If in a slave thread : 03750 CREATE DATABASE DB was certainly not preceded by USE DB. 03751 For that reason, db_ok() in sql/slave.cc did not check the 03752 do_db/ignore_db. And as this query involves no tables, tables_ok() 03753 above was not called. So we have to check rules again here. 03754 */ 03755 #ifdef HAVE_REPLICATION 03756 if (thd->slave_thread && 03757 (!rpl_filter->db_ok(lex->name) || 03758 !rpl_filter->db_ok_with_wild_table(lex->name))) 03759 { 03760 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 03761 break; 03762 } 03763 #endif 03764 if (check_access(thd,CREATE_ACL,lex->name,0,1,0,is_schema_db(lex->name))) 03765 break; 03766 res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name), 03767 &lex->create_info, 0); 03768 break; 03769 } 03770 case SQLCOM_DROP_DB: 03771 { 03772 if (end_active_trans(thd)) 03773 { 03774 res= -1; 03775 break; 03776 } 03777 if (check_db_name(lex->name)) 03778 { 03779 my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); 03780 break; 03781 } 03782 /* 03783 If in a slave thread : 03784 DROP DATABASE DB may not be preceded by USE DB. 03785 For that reason, maybe db_ok() in sql/slave.cc did not check the 03786 do_db/ignore_db. And as this query involves no tables, tables_ok() 03787 above was not called. So we have to check rules again here. 03788 */ 03789 #ifdef HAVE_REPLICATION 03790 if (thd->slave_thread && 03791 (!rpl_filter->db_ok(lex->name) || 03792 !rpl_filter->db_ok_with_wild_table(lex->name))) 03793 { 03794 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 03795 break; 03796 } 03797 #endif 03798 if (check_access(thd,DROP_ACL,lex->name,0,1,0,is_schema_db(lex->name))) 03799 break; 03800 if (thd->locked_tables || thd->active_transaction()) 03801 { 03802 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03803 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03804 goto error; 03805 } 03806 res= mysql_rm_db(thd, lex->name, lex->drop_if_exists, 0); 03807 break; 03808 } 03809 case SQLCOM_RENAME_DB: 03810 { 03811 LEX_STRING *olddb, *newdb; 03812 List_iterator <LEX_STRING> db_list(lex->db_list); 03813 olddb= db_list++; 03814 newdb= db_list++; 03815 if (end_active_trans(thd)) 03816 { 03817 res= 1; 03818 break; 03819 } 03820 #ifdef HAVE_REPLICATION 03821 if (thd->slave_thread && 03822 (!rpl_filter->db_ok(olddb->str) || 03823 !rpl_filter->db_ok(newdb->str) || 03824 !rpl_filter->db_ok_with_wild_table(olddb->str) || 03825 !rpl_filter->db_ok_with_wild_table(newdb->str))) 03826 { 03827 res= 1; 03828 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 03829 break; 03830 } 03831 #endif 03832 if (check_access(thd,ALTER_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || 03833 check_access(thd,DROP_ACL,olddb->str,0,1,0,is_schema_db(olddb->str)) || 03834 check_access(thd,CREATE_ACL,newdb->str,0,1,0,is_schema_db(newdb->str))) 03835 { 03836 res= 1; 03837 break; 03838 } 03839 if (thd->locked_tables || thd->active_transaction()) 03840 { 03841 res= 1; 03842 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03843 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03844 goto error; 03845 } 03846 res= mysql_rename_db(thd, olddb, newdb); 03847 if (!res) 03848 send_ok(thd); 03849 break; 03850 } 03851 case SQLCOM_ALTER_DB: 03852 { 03853 char *db= lex->name; 03854 DBUG_ASSERT(db); /* Must be set in the parser */ 03855 if (!strip_sp(db) || check_db_name(db)) 03856 { 03857 my_error(ER_WRONG_DB_NAME, MYF(0), db); 03858 break; 03859 } 03860 /* 03861 If in a slave thread : 03862 ALTER DATABASE DB may not be preceded by USE DB. 03863 For that reason, maybe db_ok() in sql/slave.cc did not check the 03864 do_db/ignore_db. And as this query involves no tables, tables_ok() 03865 above was not called. So we have to check rules again here. 03866 */ 03867 #ifdef HAVE_REPLICATION 03868 if (thd->slave_thread && 03869 (!rpl_filter->db_ok(db) || 03870 !rpl_filter->db_ok_with_wild_table(db))) 03871 { 03872 my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0)); 03873 break; 03874 } 03875 #endif 03876 if (check_access(thd, ALTER_ACL, db, 0, 1, 0, is_schema_db(db))) 03877 break; 03878 if (thd->locked_tables || thd->active_transaction()) 03879 { 03880 my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, 03881 ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); 03882 goto error; 03883 } 03884 res= mysql_alter_db(thd, db, &lex->create_info); 03885 break; 03886 } 03887 case SQLCOM_SHOW_CREATE_DB: 03888 { 03889 if (!strip_sp(lex->name) || check_db_name(lex->name)) 03890 { 03891 my_error(ER_WRONG_DB_NAME, MYF(0), lex->name); 03892 break; 03893 } 03894 res=mysqld_show_create_db(thd,lex->name,&lex->create_info); 03895 break; 03896 } 03897 case SQLCOM_CREATE_EVENT: 03898 case SQLCOM_ALTER_EVENT: 03899 case SQLCOM_DROP_EVENT: 03900 { 03901 uint rows_affected= 1; 03902 DBUG_ASSERT(lex->et); 03903 do { 03904 if (! lex->et->dbname.str || 03905 (lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && 03906 !lex->spname->m_db.str)) 03907 { 03908 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 03909 res= true; 03910 break; 03911 } 03912 03913 if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0, 03914 is_schema_db(lex->et->dbname.str)) || 03915 (lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && 03916 (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0, 03917 is_schema_db(lex->spname->m_db.str))))) 03918 break; 03919 03920 if (end_active_trans(thd)) 03921 { 03922 res= -1; 03923 break; 03924 } 03925 03926 switch (lex->sql_command) { 03927 case SQLCOM_CREATE_EVENT: 03928 res= Events::create_event(thd, lex->et, 03929 (uint) lex->create_info.options, 03930 &rows_affected); 03931 break; 03932 case SQLCOM_ALTER_EVENT: 03933 res= Events::update_event(thd, lex->et, lex->spname, 03934 &rows_affected); 03935 break; 03936 case SQLCOM_DROP_EVENT: 03937 res= Events::drop_event(thd, lex->et, lex->drop_if_exists, 03938 &rows_affected); 03939 default:; 03940 } 03941 DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d", 03942 res, rows_affected)); 03943 if (!res) 03944 send_ok(thd, rows_affected); 03945 03946 /* lex->unit.cleanup() is called outside, no need to call it here */ 03947 } while (0); 03948 if (!thd->spcont) 03949 { 03950 lex->et->free_sphead_on_delete= true; 03951 lex->et->free_sp(); 03952 lex->et->deinit_mutexes(); 03953 } 03954 03955 break; 03956 } 03957 case SQLCOM_SHOW_CREATE_EVENT: 03958 { 03959 DBUG_ASSERT(lex->spname); 03960 DBUG_ASSERT(lex->et); 03961 if (! lex->spname->m_db.str) 03962 { 03963 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 03964 res= true; 03965 break; 03966 } 03967 if (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0, 03968 is_schema_db(lex->spname->m_db.str))) 03969 break; 03970 03971 if (lex->spname->m_name.length > NAME_LEN) 03972 { 03973 my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); 03974 goto error; 03975 } 03976 res= Events::show_create_event(thd, lex->spname); 03977 break; 03978 } 03979 #ifndef DBUG_OFF 03980 case SQLCOM_SHOW_SCHEDULER_STATUS: 03981 { 03982 res= Events::dump_internal_status(thd); 03983 break; 03984 } 03985 #endif 03986 case SQLCOM_CREATE_FUNCTION: // UDF function 03987 { 03988 if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0)) 03989 break; 03990 #ifdef HAVE_DLOPEN 03991 if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, 03992 &thd->sp_func_cache, FALSE)) 03993 { 03994 my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str); 03995 goto error; 03996 } 03997 if (!(res = mysql_create_function(thd, &lex->udf))) 03998 send_ok(thd); 03999 #else 04000 my_error(ER_CANT_OPEN_LIBRARY, MYF(0), lex->udf.dl, 0, "feature disabled"); 04001 res= TRUE; 04002 #endif 04003 break; 04004 } 04005 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04006 case SQLCOM_CREATE_USER: 04007 { 04008 if (check_access(thd, INSERT_ACL, "mysql", 0, 1, 1, 0) && 04009 check_global_access(thd,CREATE_USER_ACL)) 04010 break; 04011 if (end_active_trans(thd)) 04012 goto error; 04013 if (!(res= mysql_create_user(thd, lex->users_list))) 04014 { 04015 if (mysql_bin_log.is_open()) 04016 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04017 thd->query, thd->query_length, FALSE, FALSE); 04018 send_ok(thd); 04019 } 04020 break; 04021 } 04022 case SQLCOM_DROP_USER: 04023 { 04024 if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 1, 0) && 04025 check_global_access(thd,CREATE_USER_ACL)) 04026 break; 04027 if (end_active_trans(thd)) 04028 goto error; 04029 if (!(res= mysql_drop_user(thd, lex->users_list))) 04030 { 04031 if (mysql_bin_log.is_open()) 04032 { 04033 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04034 thd->query, thd->query_length, FALSE, FALSE); 04035 } 04036 send_ok(thd); 04037 } 04038 break; 04039 } 04040 case SQLCOM_RENAME_USER: 04041 { 04042 if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && 04043 check_global_access(thd,CREATE_USER_ACL)) 04044 break; 04045 if (end_active_trans(thd)) 04046 goto error; 04047 if (!(res= mysql_rename_user(thd, lex->users_list))) 04048 { 04049 if (mysql_bin_log.is_open()) 04050 { 04051 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04052 thd->query, thd->query_length, FALSE, FALSE); 04053 } 04054 send_ok(thd); 04055 } 04056 break; 04057 } 04058 case SQLCOM_REVOKE_ALL: 04059 { 04060 if (check_access(thd, UPDATE_ACL, "mysql", 0, 1, 1, 0) && 04061 check_global_access(thd,CREATE_USER_ACL)) 04062 break; 04063 if (!(res = mysql_revoke_all(thd, lex->users_list))) 04064 { 04065 if (mysql_bin_log.is_open()) 04066 { 04067 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04068 thd->query, thd->query_length, FALSE, FALSE); 04069 } 04070 send_ok(thd); 04071 } 04072 break; 04073 } 04074 case SQLCOM_REVOKE: 04075 case SQLCOM_GRANT: 04076 { 04077 if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, 04078 first_table ? first_table->db : select_lex->db, 04079 first_table ? &first_table->grant.privilege : 0, 04080 first_table ? 0 : 1, 0, 04081 first_table ? (bool) first_table->schema_table : 04082 select_lex->db ? is_schema_db(select_lex->db) : 0)) 04083 goto error; 04084 04085 if (thd->security_ctx->user) // If not replication 04086 { 04087 LEX_USER *user, *tmp_user; 04088 04089 List_iterator <LEX_USER> user_list(lex->users_list); 04090 while ((tmp_user= user_list++)) 04091 { 04092 if (!(user= get_current_user(thd, tmp_user))) 04093 goto error; 04094 if (specialflag & SPECIAL_NO_RESOLVE && 04095 hostname_requires_resolving(user->host.str)) 04096 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04097 ER_WARN_HOSTNAME_WONT_WORK, 04098 ER(ER_WARN_HOSTNAME_WONT_WORK), 04099 user->host.str); 04100 // Are we trying to change a password of another user 04101 DBUG_ASSERT(user->host.str != 0); 04102 if (strcmp(thd->security_ctx->user, user->user.str) || 04103 my_strcasecmp(system_charset_info, 04104 user->host.str, thd->security_ctx->host_or_ip)) 04105 { 04106 // TODO: use check_change_password() 04107 if (is_acl_user(user->host.str, user->user.str) && 04108 user->password.str && 04109 check_access(thd, UPDATE_ACL,"mysql",0,1,1,0)) 04110 { 04111 my_message(ER_PASSWORD_NOT_ALLOWED, 04112 ER(ER_PASSWORD_NOT_ALLOWED), MYF(0)); 04113 goto error; 04114 } 04115 } 04116 } 04117 } 04118 if (first_table) 04119 { 04120 if (lex->type == TYPE_ENUM_PROCEDURE || 04121 lex->type == TYPE_ENUM_FUNCTION) 04122 { 04123 uint grants= lex->all_privileges 04124 ? (PROC_ACLS & ~GRANT_ACL) | (lex->grant & GRANT_ACL) 04125 : lex->grant; 04126 if (grant_option && 04127 check_grant_routine(thd, grants | GRANT_ACL, all_tables, 04128 lex->type == TYPE_ENUM_PROCEDURE, 0)) 04129 goto error; 04130 res= mysql_routine_grant(thd, all_tables, 04131 lex->type == TYPE_ENUM_PROCEDURE, 04132 lex->users_list, grants, 04133 lex->sql_command == SQLCOM_REVOKE, 0); 04134 } 04135 else 04136 { 04137 if (grant_option && check_grant(thd, 04138 (lex->grant | lex->grant_tot_col | 04139 GRANT_ACL), 04140 all_tables, 0, UINT_MAX, 0)) 04141 goto error; 04142 res= mysql_table_grant(thd, all_tables, lex->users_list, 04143 lex->columns, lex->grant, 04144 lex->sql_command == SQLCOM_REVOKE); 04145 } 04146 if (!res && mysql_bin_log.is_open()) 04147 { 04148 thd->clear_error(); 04149 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04150 thd->query, thd->query_length, FALSE, FALSE); 04151 } 04152 } 04153 else 04154 { 04155 if (lex->columns.elements || lex->type) 04156 { 04157 my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE), 04158 MYF(0)); 04159 goto error; 04160 } 04161 else 04162 res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, 04163 lex->sql_command == SQLCOM_REVOKE); 04164 if (!res) 04165 { 04166 if (mysql_bin_log.is_open()) 04167 { 04168 thd->clear_error(); 04169 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04170 thd->query, thd->query_length, FALSE, FALSE); 04171 } 04172 if (lex->sql_command == SQLCOM_GRANT) 04173 { 04174 List_iterator <LEX_USER> str_list(lex->users_list); 04175 LEX_USER *user, *tmp_user; 04176 while ((tmp_user=str_list++)) 04177 { 04178 if (!(user= get_current_user(thd, tmp_user))) 04179 goto error; 04180 reset_mqh(user); 04181 } 04182 } 04183 } 04184 } 04185 break; 04186 } 04187 #endif 04188 case SQLCOM_RESET: 04189 /* 04190 RESET commands are never written to the binary log, so we have to 04191 initialize this variable because RESET shares the same code as FLUSH 04192 */ 04193 lex->no_write_to_binlog= 1; 04194 case SQLCOM_FLUSH: 04195 { 04196 bool write_to_binlog; 04197 if (check_global_access(thd,RELOAD_ACL)) 04198 goto error; 04199 /* 04200 reload_acl_and_cache() will tell us if we are allowed to write to the 04201 binlog or not. 04202 */ 04203 if (!reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog)) 04204 { 04205 /* 04206 We WANT to write and we CAN write. 04207 ! we write after unlocking the table. 04208 */ 04209 if (!lex->no_write_to_binlog && write_to_binlog) 04210 { 04211 if (mysql_bin_log.is_open()) 04212 { 04213 thd->binlog_query(THD::STMT_QUERY_TYPE, 04214 thd->query, thd->query_length, 0, FALSE); 04215 } 04216 } 04217 send_ok(thd); 04218 } 04219 break; 04220 } 04221 case SQLCOM_KILL: 04222 { 04223 Item *it= (Item *)lex->value_list.head(); 04224 04225 if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1)) 04226 { 04227 my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), 04228 MYF(0)); 04229 goto error; 04230 } 04231 sql_kill(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY); 04232 break; 04233 } 04234 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04235 case SQLCOM_SHOW_GRANTS: 04236 { 04237 LEX_USER *grant_user= get_current_user(thd, lex->grant_user); 04238 if (!grant_user) 04239 goto error; 04240 if ((thd->security_ctx->priv_user && 04241 !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) || 04242 !check_access(thd, SELECT_ACL, "mysql",0,1,0,0)) 04243 { 04244 res = mysql_show_grants(thd, grant_user); 04245 } 04246 break; 04247 } 04248 #endif 04249 case SQLCOM_HA_OPEN: 04250 DBUG_ASSERT(first_table == all_tables && first_table != 0); 04251 if (check_table_access(thd, SELECT_ACL, all_tables, 0)) 04252 goto error; 04253 res= mysql_ha_open(thd, first_table, 0); 04254 break; 04255 case SQLCOM_HA_CLOSE: 04256 DBUG_ASSERT(first_table == all_tables && first_table != 0); 04257 res= mysql_ha_close(thd, first_table); 04258 break; 04259 case SQLCOM_HA_READ: 04260 DBUG_ASSERT(first_table == all_tables && first_table != 0); 04261 /* 04262 There is no need to check for table permissions here, because 04263 if a user has no permissions to read a table, he won't be 04264 able to open it (with SQLCOM_HA_OPEN) in the first place. 04265 */ 04266 unit->set_limit(select_lex); 04267 res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str, 04268 lex->insert_list, lex->ha_rkey_mode, select_lex->where, 04269 unit->select_limit_cnt, unit->offset_limit_cnt); 04270 break; 04271 04272 case SQLCOM_BEGIN: 04273 if (thd->transaction.xid_state.xa_state != XA_NOTR) 04274 { 04275 my_error(ER_XAER_RMFAIL, MYF(0), 04276 xa_state_names[thd->transaction.xid_state.xa_state]); 04277 break; 04278 } 04279 if (begin_trans(thd)) 04280 goto error; 04281 send_ok(thd); 04282 break; 04283 case SQLCOM_COMMIT: 04284 if (end_trans(thd, lex->tx_release ? COMMIT_RELEASE : 04285 lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT)) 04286 goto error; 04287 send_ok(thd); 04288 break; 04289 case SQLCOM_ROLLBACK: 04290 if (end_trans(thd, lex->tx_release ? ROLLBACK_RELEASE : 04291 lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK)) 04292 goto error; 04293 send_ok(thd); 04294 break; 04295 case SQLCOM_RELEASE_SAVEPOINT: 04296 { 04297 SAVEPOINT *sv; 04298 for (sv=thd->transaction.savepoints; sv; sv=sv->prev) 04299 { 04300 if (my_strnncoll(system_charset_info, 04301 (uchar *)lex->ident.str, lex->ident.length, 04302 (uchar *)sv->name, sv->length) == 0) 04303 break; 04304 } 04305 if (sv) 04306 { 04307 if (ha_release_savepoint(thd, sv)) 04308 res= TRUE; // cannot happen 04309 else 04310 send_ok(thd); 04311 thd->transaction.savepoints=sv->prev; 04312 } 04313 else 04314 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str); 04315 break; 04316 } 04317 case SQLCOM_ROLLBACK_TO_SAVEPOINT: 04318 { 04319 SAVEPOINT *sv; 04320 for (sv=thd->transaction.savepoints; sv; sv=sv->prev) 04321 { 04322 if (my_strnncoll(system_charset_info, 04323 (uchar *)lex->ident.str, lex->ident.length, 04324 (uchar *)sv->name, sv->length) == 0) 04325 break; 04326 } 04327 if (sv) 04328 { 04329 if (ha_rollback_to_savepoint(thd, sv)) 04330 res= TRUE; // cannot happen 04331 else 04332 { 04333 if ((thd->options & 04334 (OPTION_STATUS_NO_TRANS_UPDATE | OPTION_KEEP_LOG)) && 04335 !thd->slave_thread) 04336 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04337 ER_WARNING_NOT_COMPLETE_ROLLBACK, 04338 ER(ER_WARNING_NOT_COMPLETE_ROLLBACK)); 04339 send_ok(thd); 04340 } 04341 thd->transaction.savepoints=sv; 04342 } 04343 else 04344 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str); 04345 break; 04346 } 04347 case SQLCOM_SAVEPOINT: 04348 if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) || 04349 thd->in_sub_stmt) || !opt_using_transactions) 04350 send_ok(thd); 04351 else 04352 { 04353 SAVEPOINT **sv, *newsv; 04354 for (sv=&thd->transaction.savepoints; *sv; sv=&(*sv)->prev) 04355 { 04356 if (my_strnncoll(system_charset_info, 04357 (uchar *)lex->ident.str, lex->ident.length, 04358 (uchar *)(*sv)->name, (*sv)->length) == 0) 04359 break; 04360 } 04361 if (*sv) /* old savepoint of the same name exists */ 04362 { 04363 newsv=*sv; 04364 ha_release_savepoint(thd, *sv); // it cannot fail 04365 *sv=(*sv)->prev; 04366 } 04367 else if ((newsv=(SAVEPOINT *) alloc_root(&thd->transaction.mem_root, 04368 savepoint_alloc_size)) == 0) 04369 { 04370 my_error(ER_OUT_OF_RESOURCES, MYF(0)); 04371 break; 04372 } 04373 newsv->name=strmake_root(&thd->transaction.mem_root, 04374 lex->ident.str, lex->ident.length); 04375 newsv->length=lex->ident.length; 04376 /* 04377 if we'll get an error here, don't add new savepoint to the list. 04378 we'll lose a little bit of memory in transaction mem_root, but it'll 04379 be free'd when transaction ends anyway 04380 */ 04381 if (ha_savepoint(thd, newsv)) 04382 res= TRUE; 04383 else 04384 { 04385 newsv->prev=thd->transaction.savepoints; 04386 thd->transaction.savepoints=newsv; 04387 send_ok(thd); 04388 } 04389 } 04390 break; 04391 case SQLCOM_CREATE_PROCEDURE: 04392 case SQLCOM_CREATE_SPFUNCTION: 04393 { 04394 uint namelen; 04395 char *name; 04396 int result; 04397 04398 DBUG_ASSERT(lex->sphead != 0); 04399 DBUG_ASSERT(lex->sphead->m_db.str); /* Must be initialized in the parser */ 04400 04401 if (check_access(thd, CREATE_PROC_ACL, lex->sphead->m_db.str, 0, 0, 0, 04402 is_schema_db(lex->sphead->m_db.str))) 04403 { 04404 delete lex->sphead; 04405 lex->sphead= 0; 04406 goto error; 04407 } 04408 04409 if (end_active_trans(thd)) 04410 { 04411 delete lex->sphead; 04412 lex->sphead= 0; 04413 goto error; 04414 } 04415 04416 name= lex->sphead->name(&namelen); 04417 #ifdef HAVE_DLOPEN 04418 if (lex->sphead->m_type == TYPE_ENUM_FUNCTION) 04419 { 04420 udf_func *udf = find_udf(name, namelen); 04421 04422 if (udf) 04423 { 04424 my_error(ER_UDF_EXISTS, MYF(0), name); 04425 delete lex->sphead; 04426 lex->sphead= 0; 04427 goto error; 04428 } 04429 } 04430 #endif 04431 04432 /* 04433 If the definer is not specified, this means that CREATE-statement missed 04434 DEFINER-clause. DEFINER-clause can be missed in two cases: 04435 04436 - The user submitted a statement w/o the clause. This is a normal 04437 case, we should assign CURRENT_USER as definer. 04438 04439 - Our slave received an updated from the master, that does not 04440 replicate definer for stored rountines. We should also assign 04441 CURRENT_USER as definer here, but also we should mark this routine 04442 as NON-SUID. This is essential for the sake of backward 04443 compatibility. 04444 04445 The problem is the slave thread is running under "special" user (@), 04446 that actually does not exist. In the older versions we do not fail 04447 execution of a stored routine if its definer does not exist and 04448 continue the execution under the authorization of the invoker 04449 (BUG#13198). And now if we try to switch to slave-current-user (@), 04450 we will fail. 04451 04452 Actually, this leads to the inconsistent state of master and 04453 slave (different definers, different SUID behaviour), but it seems, 04454 this is the best we can do. 04455 */ 04456 04457 if (!lex->definer) 04458 { 04459 bool res= FALSE; 04460 Query_arena original_arena; 04461 Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); 04462 04463 if (!(lex->definer= create_default_definer(thd))) 04464 res= TRUE; 04465 04466 if (ps_arena) 04467 thd->restore_active_arena(ps_arena, &original_arena); 04468 04469 if (res) 04470 { 04471 /* Error has been already reported. */ 04472 delete lex->sphead; 04473 lex->sphead= 0; 04474 goto error; 04475 } 04476 04477 if (thd->slave_thread) 04478 lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; 04479 } 04480 04481 /* 04482 If the specified definer differs from the current user, we should check 04483 that the current user has SUPER privilege (in order to create a stored 04484 routine under another user one must have SUPER privilege). 04485 */ 04486 04487 else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || 04488 my_strcasecmp(system_charset_info, 04489 lex->definer->host.str, 04490 thd->security_ctx->priv_host)) 04491 { 04492 if (check_global_access(thd, SUPER_ACL)) 04493 { 04494 my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); 04495 delete lex->sphead; 04496 lex->sphead= 0; 04497 goto error; 04498 } 04499 } 04500 04501 /* Check that the specified definer exists. Emit a warning if not. */ 04502 04503 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04504 if (!is_acl_user(lex->definer->host.str, 04505 lex->definer->user.str)) 04506 { 04507 push_warning_printf(thd, 04508 MYSQL_ERROR::WARN_LEVEL_NOTE, 04509 ER_NO_SUCH_USER, 04510 ER(ER_NO_SUCH_USER), 04511 lex->definer->user.str, 04512 lex->definer->host.str); 04513 } 04514 #endif /* NO_EMBEDDED_ACCESS_CHECKS */ 04515 04516 res= (result= lex->sphead->create(thd)); 04517 if (result == SP_OK) 04518 { 04519 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04520 /* only add privileges if really neccessary */ 04521 if (sp_automatic_privileges && !opt_noacl && 04522 check_routine_access(thd, DEFAULT_CREATE_PROC_ACLS, 04523 lex->sphead->m_db.str, name, 04524 lex->sql_command == SQLCOM_CREATE_PROCEDURE, 1)) 04525 { 04526 if (sp_grant_privileges(thd, lex->sphead->m_db.str, name, 04527 lex->sql_command == SQLCOM_CREATE_PROCEDURE)) 04528 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04529 ER_PROC_AUTO_GRANT_FAIL, 04530 ER(ER_PROC_AUTO_GRANT_FAIL)); 04531 close_thread_tables(thd); 04532 } 04533 #endif 04534 lex->unit.cleanup(); 04535 delete lex->sphead; 04536 lex->sphead= 0; 04537 send_ok(thd); 04538 } 04539 else 04540 { 04541 switch (result) { 04542 case SP_WRITE_ROW_FAILED: 04543 my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name); 04544 break; 04545 case SP_NO_DB_ERROR: 04546 my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str); 04547 break; 04548 case SP_BAD_IDENTIFIER: 04549 my_error(ER_TOO_LONG_IDENT, MYF(0), name); 04550 break; 04551 case SP_BODY_TOO_LONG: 04552 my_error(ER_TOO_LONG_BODY, MYF(0), name); 04553 break; 04554 default: 04555 my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name); 04556 break; 04557 } 04558 lex->unit.cleanup(); 04559 delete lex->sphead; 04560 lex->sphead= 0; 04561 goto error; 04562 } 04563 break; 04564 } 04565 case SQLCOM_CALL: 04566 { 04567 sp_head *sp; 04568 04569 /* 04570 This will cache all SP and SF and open and lock all tables 04571 required for execution. 04572 */ 04573 if (check_table_access(thd, SELECT_ACL, all_tables, 0) || 04574 open_and_lock_tables(thd, all_tables)) 04575 goto error; 04576 04577 /* 04578 By this moment all needed SPs should be in cache so no need to look 04579 into DB. 04580 */ 04581 if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, 04582 &thd->sp_proc_cache, TRUE))) 04583 { 04584 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE", 04585 lex->spname->m_qname.str); 04586 goto error; 04587 } 04588 else 04589 { 04590 ha_rows select_limit; 04591 /* bits that should be cleared in thd->server_status */ 04592 uint bits_to_be_cleared= 0; 04593 /* 04594 Check that the stored procedure doesn't contain Dynamic SQL 04595 and doesn't return result sets: such stored procedures can't 04596 be called from a function or trigger. 04597 */ 04598 if (thd->in_sub_stmt) 04599 { 04600 const char *where= (thd->in_sub_stmt & SUB_STMT_TRIGGER ? 04601 "trigger" : "function"); 04602 if (sp->is_not_allowed_in_function(where)) 04603 goto error; 04604 } 04605 04606 my_bool nsok= thd->net.no_send_ok; 04607 thd->net.no_send_ok= TRUE; 04608 if (sp->m_flags & sp_head::MULTI_RESULTS) 04609 { 04610 if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS)) 04611 { 04612 /* 04613 The client does not support multiple result sets being sent 04614 back 04615 */ 04616 my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str); 04617 thd->net.no_send_ok= nsok; 04618 goto error; 04619 } 04620 /* 04621 If SERVER_MORE_RESULTS_EXISTS is not set, 04622 then remember that it should be cleared 04623 */ 04624 bits_to_be_cleared= (~thd->server_status & 04625 SERVER_MORE_RESULTS_EXISTS); 04626 thd->server_status|= SERVER_MORE_RESULTS_EXISTS; 04627 } 04628 04629 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04630 if (check_routine_access(thd, EXECUTE_ACL, 04631 sp->m_db.str, sp->m_name.str, TRUE, FALSE)) 04632 { 04633 thd->net.no_send_ok= nsok; 04634 goto error; 04635 } 04636 #endif 04637 select_limit= thd->variables.select_limit; 04638 thd->variables.select_limit= HA_POS_ERROR; 04639 04640 thd->row_count_func= 0; 04641 04642 /* 04643 We never write CALL statements into binlog: 04644 - If the mode is non-prelocked, each statement will be logged 04645 separately. 04646 - If the mode is prelocked, the invoking statement will care 04647 about writing into binlog. 04648 So just execute the statement. 04649 */ 04650 res= sp->execute_procedure(thd, &lex->value_list); 04651 /* 04652 If warnings have been cleared, we have to clear total_warn_count 04653 too, otherwise the clients get confused. 04654 */ 04655 if (thd->warn_list.is_empty()) 04656 thd->total_warn_count= 0; 04657 04658 thd->variables.select_limit= select_limit; 04659 04660 thd->net.no_send_ok= nsok; 04661 thd->server_status&= ~bits_to_be_cleared; 04662 04663 if (!res) 04664 send_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 : 04665 thd->row_count_func)); 04666 else 04667 goto error; // Substatement should already have sent error 04668 } 04669 break; 04670 } 04671 case SQLCOM_ALTER_PROCEDURE: 04672 case SQLCOM_ALTER_FUNCTION: 04673 { 04674 int result; 04675 sp_head *sp; 04676 st_sp_chistics chistics; 04677 04678 memcpy(&chistics, &lex->sp_chistics, sizeof(chistics)); 04679 if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) 04680 sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, 04681 &thd->sp_proc_cache, FALSE); 04682 else 04683 sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, 04684 &thd->sp_func_cache, FALSE); 04685 mysql_reset_errors(thd, 0); 04686 if (! sp) 04687 { 04688 if (lex->spname->m_db.str) 04689 result= SP_KEY_NOT_FOUND; 04690 else 04691 { 04692 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 04693 goto error; 04694 } 04695 } 04696 else 04697 { 04698 if (check_routine_access(thd, ALTER_PROC_ACL, sp->m_db.str, 04699 sp->m_name.str, 04700 lex->sql_command == SQLCOM_ALTER_PROCEDURE, 0)) 04701 goto error; 04702 04703 if (end_active_trans(thd)) 04704 goto error; 04705 memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics)); 04706 if ((sp->m_type == TYPE_ENUM_FUNCTION) && 04707 !trust_function_creators && mysql_bin_log.is_open() && 04708 !sp->m_chistics->detistic && 04709 (chistics.daccess == SP_CONTAINS_SQL || 04710 chistics.daccess == SP_MODIFIES_SQL_DATA)) 04711 { 04712 my_message(ER_BINLOG_UNSAFE_ROUTINE, 04713 ER(ER_BINLOG_UNSAFE_ROUTINE), MYF(0)); 04714 result= SP_INTERNAL_ERROR; 04715 } 04716 else 04717 { 04718 /* 04719 Note that if you implement the capability of ALTER FUNCTION to 04720 alter the body of the function, this command should be made to 04721 follow the restrictions that log-bin-trust-function-creators=0 04722 already puts on CREATE FUNCTION. 04723 */ 04724 if (lex->sql_command == SQLCOM_ALTER_PROCEDURE) 04725 result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics); 04726 else 04727 result= sp_update_function(thd, lex->spname, &lex->sp_chistics); 04728 } 04729 } 04730 switch (result) 04731 { 04732 case SP_OK: 04733 if (mysql_bin_log.is_open()) 04734 { 04735 thd->clear_error(); 04736 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04737 thd->query, thd->query_length, FALSE, FALSE); 04738 } 04739 send_ok(thd); 04740 break; 04741 case SP_KEY_NOT_FOUND: 04742 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04743 SP_COM_STRING(lex), lex->spname->m_qname.str); 04744 goto error; 04745 default: 04746 my_error(ER_SP_CANT_ALTER, MYF(0), 04747 SP_COM_STRING(lex), lex->spname->m_qname.str); 04748 goto error; 04749 } 04750 break; 04751 } 04752 case SQLCOM_DROP_PROCEDURE: 04753 case SQLCOM_DROP_FUNCTION: 04754 { 04755 int result; 04756 int type= (lex->sql_command == SQLCOM_DROP_PROCEDURE ? 04757 TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION); 04758 04759 result= sp_routine_exists_in_table(thd, type, lex->spname); 04760 mysql_reset_errors(thd, 0); 04761 if (result == SP_OK) 04762 { 04763 char *db= lex->spname->m_db.str; 04764 char *name= lex->spname->m_name.str; 04765 04766 if (check_routine_access(thd, ALTER_PROC_ACL, db, name, 04767 lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) 04768 goto error; 04769 04770 if (end_active_trans(thd)) 04771 goto error; 04772 #ifndef NO_EMBEDDED_ACCESS_CHECKS 04773 if (sp_automatic_privileges && !opt_noacl && 04774 sp_revoke_privileges(thd, db, name, 04775 lex->sql_command == SQLCOM_DROP_PROCEDURE)) 04776 { 04777 push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 04778 ER_PROC_AUTO_REVOKE_FAIL, 04779 ER(ER_PROC_AUTO_REVOKE_FAIL)); 04780 } 04781 #endif 04782 if (lex->sql_command == SQLCOM_DROP_PROCEDURE) 04783 result= sp_drop_procedure(thd, lex->spname); 04784 else 04785 result= sp_drop_function(thd, lex->spname); 04786 } 04787 else 04788 { 04789 #ifdef HAVE_DLOPEN 04790 if (lex->sql_command == SQLCOM_DROP_FUNCTION) 04791 { 04792 udf_func *udf = find_udf(lex->spname->m_name.str, 04793 lex->spname->m_name.length); 04794 if (udf) 04795 { 04796 if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0, 0)) 04797 goto error; 04798 if (!(res = mysql_drop_function(thd, &lex->spname->m_name))) 04799 { 04800 send_ok(thd); 04801 break; 04802 } 04803 } 04804 } 04805 #endif 04806 if (lex->spname->m_db.str) 04807 result= SP_KEY_NOT_FOUND; 04808 else 04809 { 04810 my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); 04811 goto error; 04812 } 04813 } 04814 res= result; 04815 switch (result) 04816 { 04817 case SP_OK: 04818 if (mysql_bin_log.is_open()) 04819 { 04820 thd->clear_error(); 04821 thd->binlog_query(THD::MYSQL_QUERY_TYPE, 04822 thd->query, thd->query_length, FALSE, FALSE); 04823 } 04824 send_ok(thd); 04825 break; 04826 case SP_KEY_NOT_FOUND: 04827 if (lex->drop_if_exists) 04828 { 04829 push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, 04830 ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), 04831 SP_COM_STRING(lex), lex->spname->m_name.str); 04832 res= FALSE; 04833 send_ok(thd); 04834 break; 04835 } 04836 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04837 SP_COM_STRING(lex), lex->spname->m_qname.str); 04838 goto error; 04839 default: 04840 my_error(ER_SP_DROP_FAILED, MYF(0), 04841 SP_COM_STRING(lex), lex->spname->m_qname.str); 04842 goto error; 04843 } 04844 break; 04845 } 04846 case SQLCOM_SHOW_CREATE_PROC: 04847 { 04848 if (lex->spname->m_name.length > NAME_LEN) 04849 { 04850 my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); 04851 goto error; 04852 } 04853 if (sp_show_create_procedure(thd, lex->spname) != SP_OK) 04854 { /* We don't distinguish between errors for now */ 04855 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04856 SP_COM_STRING(lex), lex->spname->m_name.str); 04857 goto error; 04858 } 04859 break; 04860 } 04861 case SQLCOM_SHOW_CREATE_FUNC: 04862 { 04863 if (lex->spname->m_name.length > NAME_LEN) 04864 { 04865 my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); 04866 goto error; 04867 } 04868 if (sp_show_create_function(thd, lex->spname) != SP_OK) 04869 { /* We don't distinguish between errors for now */ 04870 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04871 SP_COM_STRING(lex), lex->spname->m_name.str); 04872 goto error; 04873 } 04874 break; 04875 } 04876 #ifdef NOT_USED 04877 case SQLCOM_SHOW_STATUS_PROC: 04878 { 04879 res= sp_show_status_procedure(thd, (lex->wild ? 04880 lex->wild->ptr() : NullS)); 04881 break; 04882 } 04883 case SQLCOM_SHOW_STATUS_FUNC: 04884 { 04885 res= sp_show_status_function(thd, (lex->wild ? 04886 lex->wild->ptr() : NullS)); 04887 break; 04888 } 04889 #endif 04890 #ifndef DBUG_OFF 04891 case SQLCOM_SHOW_PROC_CODE: 04892 case SQLCOM_SHOW_FUNC_CODE: 04893 { 04894 sp_head *sp; 04895 04896 if (lex->spname->m_name.length > NAME_LEN) 04897 { 04898 my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str); 04899 goto error; 04900 } 04901 if (lex->sql_command == SQLCOM_SHOW_PROC_CODE) 04902 sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname, 04903 &thd->sp_proc_cache, FALSE); 04904 else 04905 sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname, 04906 &thd->sp_func_cache, FALSE); 04907 if (!sp || sp->show_routine_code(thd)) 04908 { 04909 /* We don't distinguish between errors for now */ 04910 my_error(ER_SP_DOES_NOT_EXIST, MYF(0), 04911 SP_COM_STRING(lex), lex->spname->m_name.str); 04912 goto error; 04913 } 04914 break; 04915 } 04916 #endif // ifndef DBUG_OFF 04917 case SQLCOM_CREATE_VIEW: 04918 { 04919 if (end_active_trans(thd)) 04920 goto error; 04921 04922 if (!(res= mysql_create_view(thd, thd->lex->create_view_mode)) && 04923 mysql_bin_log.is_open()) 04924 { 04925 String buff; 04926 const LEX_STRING command[3]= 04927 {{ C_STRING_WITH_LEN("CREATE ") }, 04928 { C_STRING_WITH_LEN("ALTER ") }, 04929 { C_STRING_WITH_LEN("CREATE OR REPLACE ") }}; 04930 thd->clear_error(); 04931 04932 buff.append(command[thd->lex->create_view_mode].str, 04933 command[thd->lex->create_view_mode].length); 04934 view_store_options(thd, first_table, &buff); 04935 buff.append(STRING_WITH_LEN("VIEW ")); 04936 /* Test if user supplied a db (ie: we did not use thd->db) */ 04937 if (first_table->db && first_table->db[0] && 04938 (thd->db == NULL || strcmp(first_table->db, thd->db))) 04939 { 04940 append_identifier(thd, &buff, first_table->db, 04941 first_table->db_length); 04942 buff.append('.'); 04943 } 04944 append_identifier(thd, &buff, first_table->table_name, 04945 first_table->table_name_length); 04946 buff.append(STRING_WITH_LEN(" AS ")); 04947 buff.append(first_table->source.str, first_table->source.length); 04948 04949 thd->binlog_query(THD::STMT_QUERY_TYPE, 04950 buff.ptr(), buff.length(), FALSE, FALSE); 04951 } 04952 break; 04953 } 04954 case SQLCOM_DROP_VIEW: 04955 { 04956 if (check_table_access(thd, DROP_ACL, all_tables, 0) || 04957 end_active_trans(thd)) 04958 goto error; 04959 if (!(res= mysql_drop_view(thd, first_table, thd->lex->drop_mode)) && 04960 mysql_bin_log.is_open()) 04961 { 04962 thd->clear_error(); 04963 thd->binlog_query(THD::STMT_QUERY_TYPE, 04964 thd->query, thd->query_length, FALSE, FALSE); 04965 } 04966 break; 04967 } 04968 case SQLCOM_CREATE_TRIGGER: 04969 { 04970 if (end_active_trans(thd)) 04971 goto error; 04972 04973 res= mysql_create_or_drop_trigger(thd, all_tables, 1); 04974 04975 /* We don't care about trigger body after this point */ 04976 delete lex->sphead; 04977 lex->sphead= 0; 04978 break; 04979 } 04980 case SQLCOM_DROP_TRIGGER: 04981 { 04982 if (end_active_trans(thd)) 04983 goto error; 04984 04985 res= mysql_create_or_drop_trigger(thd, all_tables, 0); 04986 break; 04987 } 04988 case SQLCOM_XA_START: 04989 if (thd->transaction.xid_state.xa_state == XA_IDLE && 04990 thd->lex->xa_opt == XA_RESUME) 04991 { 04992 if (! thd->transaction.xid_state.xid.eq(thd->lex->xid)) 04993 { 04994 my_error(ER_XAER_NOTA, MYF(0)); 04995 break; 04996 } 04997 thd->transaction.xid_state.xa_state=XA_ACTIVE; 04998 send_ok(thd); 04999 break; 05000 } 05001 if (thd->lex->xa_opt != XA_NONE) 05002 { // JOIN is not supported yet. TODO 05003 my_error(ER_XAER_INVAL, MYF(0)); 05004 break; 05005 } 05006 if (thd->transaction.xid_state.xa_state != XA_NOTR) 05007 { 05008 my_error(ER_XAER_RMFAIL, MYF(0), 05009 xa_state_names[thd->transaction.xid_state.xa_state]); 05010 break; 05011 } 05012 if (thd->active_transaction() || thd->locked_tables) 05013 { 05014 my_error(ER_XAER_OUTSIDE, MYF(0)); 05015 break; 05016 } 05017 if (xid_cache_search(thd->lex->xid)) 05018 { 05019 my_error(ER_XAER_DUPID, MYF(0)); 05020 break; 05021 } 05022 DBUG_ASSERT(thd->transaction.xid_state.xid.is_null()); 05023 thd->transaction.xid_state.xa_state=XA_ACTIVE; 05024 thd->transaction.xid_state.xid.set(thd->lex->xid); 05025 xid_cache_insert(&thd->transaction.xid_state); 05026 thd->options= ((thd->options & ~(OPTION_STATUS_NO_TRANS_UPDATE | 05027 OPTION_KEEP_LOG)) | 05028 OPTION_BEGIN); 05029 thd->server_status|= SERVER_STATUS_IN_TRANS; 05030 send_ok(thd); 05031 break; 05032 case SQLCOM_XA_END: 05033 /* fake it */ 05034 if (thd->lex->xa_opt != XA_NONE) 05035 { // SUSPEND and FOR MIGRATE are not supported yet. TODO 05036 my_error(ER_XAER_INVAL, MYF(0)); 05037 break; 05038 } 05039 if (thd->transaction.xid_state.xa_state != XA_ACTIVE) 05040 { 05041 my_error(ER_XAER_RMFAIL, MYF(0), 05042 xa_state_names[thd->transaction.xid_state.xa_state]); 05043 break; 05044 } 05045 if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) 05046 { 05047 my_error(ER_XAER_NOTA, MYF(0)); 05048 break; 05049 } 05050 thd->transaction.xid_state.xa_state=XA_IDLE; 05051 send_ok(thd); 05052 break; 05053 case SQLCOM_XA_PREPARE: 05054 if (thd->transaction.xid_state.xa_state != XA_IDLE) 05055 { 05056 my_error(ER_XAER_RMFAIL, MYF(0), 05057 xa_state_names[thd->transaction.xid_state.xa_state]); 05058 break; 05059 } 05060 if (!thd->transaction.xid_state.xid.eq(thd->lex->xid)) 05061 { 05062 my_error(ER_XAER_NOTA, MYF(0)); 05063 break; 05064 } 05065 if (ha_prepare(thd)) 05066 { 05067 my_error(ER_XA_RBROLLBACK, MYF(0)); 05068 xid_cache_delete(&thd->transaction.xid_state); 05069 thd->transaction.xid_state.xa_state=XA_NOTR; 05070 break; 05071 } 05072 thd->transaction.xid_state.xa_state=XA_PREPARED; 05073 send_ok(thd); 05074

