diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/log_event.cc | 23 | ||||
-rw-r--r-- | sql/log_event.h | 16 | ||||
-rw-r--r-- | sql/sp_head.cc | 3 | ||||
-rw-r--r-- | sql/sql_acl.cc | 6 | ||||
-rw-r--r-- | sql/sql_base.cc | 32 | ||||
-rw-r--r-- | sql/sql_base.h | 4 | ||||
-rw-r--r-- | sql/sql_lex.cc | 7 | ||||
-rw-r--r-- | sql/sql_lex.h | 54 | ||||
-rw-r--r-- | sql/sql_load.cc | 10 | ||||
-rw-r--r-- | sql/sql_parse.cc | 1 | ||||
-rw-r--r-- | sql/sql_priv.h | 6 | ||||
-rw-r--r-- | sql/sql_select.cc | 3 | ||||
-rw-r--r-- | sql/sql_show.cc | 10 | ||||
-rw-r--r-- | sql/sql_table.cc | 6 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 7 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 52 |
17 files changed, 165 insertions, 77 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index 3a52b72909a..3a3d6c74e8e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -4226,7 +4226,7 @@ void Load_log_event::print_query(bool need_db, const char *cs, char *buf, pos= strmov(pos, "LOAD DATA "); - if (thd->lex->lock_option == TL_WRITE_CONCURRENT_INSERT) + if (is_concurrent) pos= strmov(pos, "CONCURRENT "); if (fn_start) @@ -4368,6 +4368,7 @@ bool Load_log_event::write_data_body(IO_CACHE* file) Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, const char *db_arg, const char *table_name_arg, List<Item> &fields_arg, + bool is_concurrent_arg, enum enum_duplicates handle_dup, bool ignore, bool using_trans) :Log_event(thd_arg, @@ -4378,7 +4379,8 @@ Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex, num_fields(0),fields(0), field_lens(0),field_block_len(0), table_name(table_name_arg ? table_name_arg : ""), - db(db_arg), fname(ex->file_name), local_fname(FALSE) + db(db_arg), fname(ex->file_name), local_fname(FALSE), + is_concurrent(is_concurrent_arg) { time_t end_time; time(&end_time); @@ -4459,7 +4461,13 @@ Load_log_event::Load_log_event(const char *buf, uint event_len, const Format_description_log_event *description_event) :Log_event(buf, description_event), num_fields(0), fields(0), field_lens(0),field_block_len(0), - table_name(0), db(0), fname(0), local_fname(FALSE) + table_name(0), db(0), fname(0), local_fname(FALSE), + /* + Load_log_event which comes from the binary log does not contain + information about the type of insert which was used on the master. + Assume that it was an ordinary, non-concurrent LOAD DATA. + */ + is_concurrent(FALSE) { DBUG_ENTER("Load_log_event"); /* @@ -6149,11 +6157,14 @@ int Stop_log_event::do_update_pos(Relay_log_info *rli) Create_file_log_event:: Create_file_log_event(THD* thd_arg, sql_exchange* ex, const char* db_arg, const char* table_name_arg, - List<Item>& fields_arg, enum enum_duplicates handle_dup, + List<Item>& fields_arg, + bool is_concurrent_arg, + enum enum_duplicates handle_dup, bool ignore, uchar* block_arg, uint block_len_arg, bool using_trans) - :Load_log_event(thd_arg,ex,db_arg,table_name_arg,fields_arg,handle_dup, ignore, - using_trans), + :Load_log_event(thd_arg, ex, db_arg, table_name_arg, fields_arg, + is_concurrent_arg, + handle_dup, ignore, using_trans), fake_base(0), block(block_arg), event_buf(0), block_len(block_len_arg), file_id(thd_arg->file_id = mysql_bin_log.next_file_id()) { diff --git a/sql/log_event.h b/sql/log_event.h index 36397c427e5..e281fd6e206 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -2069,6 +2069,17 @@ public: uint32 skip_lines; sql_ex_info sql_ex; bool local_fname; + /** + Indicates that this event corresponds to LOAD DATA CONCURRENT, + + @note Since Load_log_event event coming from the binary log + lacks information whether LOAD DATA on master was concurrent + or not, this flag is only set to TRUE for an auxiliary + Load_log_event object which is used in mysql_load() to + re-construct LOAD DATA statement from function parameters, + for logging. + */ + bool is_concurrent; /* fname doesn't point to memory inside Log_event::temp_buf */ void set_fname_outside_temp_buf(const char *afname, uint alen) @@ -2089,7 +2100,9 @@ public: Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg, const char* table_name_arg, - List<Item>& fields_arg, enum enum_duplicates handle_dup, bool ignore, + List<Item>& fields_arg, + bool is_concurrent_arg, + enum enum_duplicates handle_dup, bool ignore, bool using_trans); void set_fields(const char* db, List<Item> &fields_arg, Name_resolution_context *context); @@ -2708,6 +2721,7 @@ public: Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg, const char* table_name_arg, List<Item>& fields_arg, + bool is_concurrent_arg, enum enum_duplicates handle_dup, bool ignore, uchar* block_arg, uint block_len_arg, bool using_trans); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index c91ba2a68b4..2e66aec91e5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2127,6 +2127,9 @@ sp_head::reset_lex(THD *thd) sublex->interval_list.empty(); sublex->type= 0; + /* Reset part of parser state which needs this. */ + thd->m_parser_state->m_yacc.reset_before_substatement(); + DBUG_RETURN(FALSE); } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index f8be3ff6d4a..55d83f49245 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3159,6 +3159,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, */ Query_tables_list backup; thd->lex->reset_n_backup_query_tables_list(&backup); + /* + Restore Query_tables_list::sql_command value, which was reset + above, as the code writing query to the binary log assumes that + this value corresponds to the statement being executed. + */ + thd->lex->sql_command= backup.sql_command; if (open_and_lock_tables(thd, tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT)) { // Should never happen close_thread_tables(thd); /* purecov: deadcode */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index baf13431d77..1d7ad87eae0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -3963,7 +3963,8 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request, Return a appropriate read lock type given a table object. @param thd Thread context - @param table TABLE object for table to be locked + @param prelocking_ctx Prelocking context. + @param table_list Table list element for table to be locked. @remark Due to a statement-based replication limitation, statements such as INSERT INTO .. SELECT FROM .. and CREATE TABLE .. SELECT FROM need @@ -3972,20 +3973,31 @@ recover_from_failed_open(THD *thd, MDL_request *mdl_request, source table. If such a statement gets applied on the slave before the INSERT .. SELECT statement finishes, data on the master could differ from data on the slave and end-up with a discrepancy between - the binary log and table state. Furthermore, this does not apply to - I_S and log tables as it's always unsafe to replicate such tables - under statement-based replication as the table on the slave might - contain other data (ie: general_log is enabled on the slave). The - statement will be marked as unsafe for SBR in decide_logging_format(). + the binary log and table state. + This also applies to SELECT/SET/DO statements which use stored + functions. Calls to such functions are going to be logged as a + whole and thus should be serialized against concurrent changes + to tables used by those functions. This can be avoided if functions + only read data but doing so requires more complex analysis than it + is done now. + Furthermore, this does not apply to I_S and log tables as it's + always unsafe to replicate such tables under statement-based + replication as the table on the slave might contain other data + (ie: general_log is enabled on the slave). The statement will + be marked as unsafe for SBR in decide_logging_format(). */ -thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table) +thr_lock_type read_lock_type_for_table(THD *thd, + Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list) { bool log_on= mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG); ulong binlog_format= thd->variables.binlog_format; if ((log_on == FALSE) || (binlog_format == BINLOG_FORMAT_ROW) || - (table->s->table_category == TABLE_CATEGORY_LOG) || - (table->s->table_category == TABLE_CATEGORY_PERFORMANCE)) + (table_list->table->s->table_category == TABLE_CATEGORY_LOG) || + (table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) || + !(is_update_query(prelocking_ctx->sql_command) || + table_list->prelocking_placeholder)) return TL_READ; else return TL_READ_NO_INSERT; @@ -4336,7 +4348,7 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables, tables->table->reginfo.lock_type= thd->update_lock_default; else if (tables->lock_type == TL_READ_DEFAULT) tables->table->reginfo.lock_type= - read_lock_type_for_table(thd, tables->table); + read_lock_type_for_table(thd, lex, tables); else tables->table->reginfo.lock_type= tables->lock_type; } diff --git a/sql/sql_base.h b/sql/sql_base.h index a57666afe49..77fbc7458ca 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -123,7 +123,9 @@ TABLE *open_temporary_table(THD *thd, const char *path, const char *db, TABLE *find_locked_table(TABLE *list, const char *db, const char *table_name); TABLE *find_write_locked_table(TABLE *list, const char *db, const char *table_name); -thr_lock_type read_lock_type_for_table(THD *thd, TABLE *table); +thr_lock_type read_lock_type_for_table(THD *thd, + Query_tables_list *prelocking_ctx, + TABLE_LIST *table_list); my_bool mysql_rm_tmp_tables(void); bool rm_temporary_table(handlerton *base, char *path); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 13f85b24299..6bd6a374883 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -350,7 +350,6 @@ void lex_start(THD *thd) lex->subqueries= FALSE; lex->view_prepare_mode= FALSE; lex->derived_tables= 0; - lex->lock_option= TL_READ; lex->safe_to_cache_query= 1; lex->leaf_tables_insert= 0; lex->parsing_options.reset(); @@ -363,7 +362,6 @@ void lex_start(THD *thd) lex->select_lex.ftfunc_list= &lex->select_lex.ftfunc_list_alloc; lex->select_lex.group_list.empty(); lex->select_lex.order_list.empty(); - lex->sql_command= SQLCOM_END; lex->duplicates= DUP_ERROR; lex->ignore= 0; lex->spname= NULL; @@ -1708,7 +1706,6 @@ void st_select_lex::init_query() exclude_from_table_unique_test= no_wrap_view_item= FALSE; nest_level= 0; link_next= 0; - lock_option= TL_READ_DEFAULT; } void st_select_lex::init_select() @@ -2219,6 +2216,7 @@ void LEX::cleanup_lex_after_parse_error(THD *thd) void Query_tables_list::reset_query_tables_list(bool init) { + sql_command= SQLCOM_END; if (!init && query_tables) { TABLE_LIST *table= query_tables; @@ -2281,8 +2279,7 @@ void Query_tables_list::destroy_query_tables_list() */ LEX::LEX() - :result(0), - sql_command(SQLCOM_END), option_type(OPT_DEFAULT), is_lex_started(0) + :result(0), option_type(OPT_DEFAULT), is_lex_started(0) { my_init_dynamic_array2(&plugins, sizeof(plugin_ref), diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 85ae2697f21..6f7acc4a609 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -739,14 +739,6 @@ public: List<udf_func> udf_list; /* udf function calls stack */ - /** - Per sub-query locking strategy. - Note: This variable might interfer with the corresponding statement-level - variable Lex::lock_option because on how different parser rules depend - on eachother. - */ - thr_lock_type lock_option; - /* This is a copy of the original JOIN USING list that comes from the parser. The parser : @@ -1005,8 +997,11 @@ extern const LEX_STRING empty_lex_str; /* - Class representing list of all tables used by statement. - It also contains information about stored functions used by statement + Class representing list of all tables used by statement and other + information which is necessary for opening and locking its tables, + like SQL command for this statement. + + Also contains information about stored functions used by statement since during its execution we may have to add all tables used by its stored functions/triggers to this list in order to pre-open and lock them. @@ -1018,6 +1013,13 @@ extern const LEX_STRING empty_lex_str; class Query_tables_list { public: + /** + SQL command for this statement. Part of this class since the + process of opening and locking tables for the statement needs + this information to determine correct type of lock for some of + the tables. + */ + enum_sql_command sql_command; /* Global list of all tables used by this statement */ TABLE_LIST *query_tables; /* Pointer to next_global member of last element in the previous list. */ @@ -1918,7 +1920,6 @@ struct LEX: public Query_tables_list the variable can contain 0 or 1 for each nest level. */ nesting_map allow_sum_func; - enum_sql_command sql_command; Sql_statement *m_stmt; @@ -1930,7 +1931,6 @@ struct LEX: public Query_tables_list */ bool expr_allows_subselect; - thr_lock_type lock_option; enum SSL_type ssl_type; /* defined in violite.h */ enum enum_duplicates duplicates; enum enum_tx_isolation tx_isolation; @@ -2237,12 +2237,21 @@ class Yacc_state { public: Yacc_state() - : yacc_yyss(NULL), yacc_yyvs(NULL) + : yacc_yyss(NULL), yacc_yyvs(NULL), m_lock_type(TL_READ_DEFAULT) {} ~Yacc_state(); /** + Reset part of the state which needs resetting before parsing + substatement. + */ + void reset_before_substatement() + { + m_lock_type= TL_READ_DEFAULT; + } + + /** Bison internal state stack, yyss, when dynamically allocated using my_yyoverflow(). */ @@ -2260,6 +2269,25 @@ public: */ Set_signal_information m_set_signal_info; + /** + Type of lock to be used for tables being added to the statement's + table list in table_factor, table_alias_ref, single_multi and + table_wild_one rules. + Statements which use these rules but require lock type different + from one specified by this member have to override it by using + st_select_lex::set_lock_for_tables() method. + + The default value of this member is TL_READ_DEFAULT. The only two + cases in which we change it are: + - When parsing SELECT HIGH_PRIORITY. + - Rule for DELETE. In which we use this member to pass information + about type of lock from delete to single_multi part of rule. + + We should try to avoid introducing new use cases as we would like + to get rid of this member eventually. + */ + thr_lock_type m_lock_type; + /* TODO: move more attributes from the LEX structure here. */ diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 87a347b9f98..be047a8711f 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -132,6 +132,7 @@ static int read_xml_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list, static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, const char* db_arg, /* table's database */ const char* table_name_arg, + bool is_concurrent, enum enum_duplicates duplicates, bool ignore, bool transactional_table, @@ -184,6 +185,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, char *tdb= thd->db ? thd->db : db; // Result is never null ulong skip_lines= ex->skip_lines; bool transactional_table; + bool is_concurrent; THD::killed_state killed_status= THD::NOT_KILLED; DBUG_ENTER("mysql_load"); @@ -245,6 +247,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, table= table_list->table; transactional_table= table->file->has_transactions(); + is_concurrent= (table_list->lock_type == TL_WRITE_CONCURRENT_INSERT); if (!fields_vars.elements) { @@ -562,6 +565,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, (void) write_execute_load_query_log_event(thd, ex, table_list->db, table_list->table_name, + is_concurrent, handle_duplicates, ignore, transactional_table, errcode); @@ -610,6 +614,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, int errcode= query_error_code(thd, killed_status == THD::NOT_KILLED); error= write_execute_load_query_log_event(thd, ex, table_list->db, table_list->table_name, + is_concurrent, handle_duplicates, ignore, transactional_table, errcode); @@ -638,6 +643,7 @@ err: static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, const char* db_arg, /* table's database */ const char* table_name_arg, + bool is_concurrent, enum enum_duplicates duplicates, bool ignore, bool transactional_table, @@ -673,8 +679,8 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex, tbl= string_buf.c_ptr_safe(); } - Load_log_event lle(thd, ex, tdb, tbl, fv, duplicates, - ignore, transactional_table); + Load_log_event lle(thd, ex, tdb, tbl, fv, is_concurrent, + duplicates, ignore, transactional_table); /* force in a LOCAL if there was one in the original. diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 85e6866f3db..42777dbc837 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5710,7 +5710,6 @@ void mysql_init_multi_delete(LEX *lex) lex->select_lex.select_limit= 0; lex->unit.select_limit_cnt= HA_POS_ERROR; lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list); - lex->lock_option= TL_READ_DEFAULT; lex->query_tables= 0; lex->query_tables_last= &lex->query_tables; } diff --git a/sql/sql_priv.h b/sql/sql_priv.h index eeefd3cac04..20893e0caa8 100644 --- a/sql/sql_priv.h +++ b/sql/sql_priv.h @@ -129,6 +129,12 @@ extern char err_shared_dir[]; */ #define TMP_TABLE_FORCE_MYISAM (1ULL << 32) #define OPTION_PROFILING (1ULL << 33) +/** + Indicates that this is a HIGH_PRIORITY SELECT. + Currently used only for printing of such selects. + Type of locks to be acquired is specified directly. +*/ +#define SELECT_HIGH_PRIORITY (1ULL << 34) // SELECT, user /* The rest of the file is included in the server only */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 62a51a32ca2..d126d0e4ec6 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -17179,8 +17179,7 @@ void st_select_lex::print(THD *thd, String *str, enum_query_type query_type) /* First add options */ if (options & SELECT_STRAIGHT_JOIN) str->append(STRING_WITH_LEN("straight_join ")); - if ((thd->lex->lock_option == TL_READ_HIGH_PRIORITY) && - (this == &thd->lex->select_lex)) + if (options & SELECT_HIGH_PRIORITY) str->append(STRING_WITH_LEN("high_priority ")); if (options & SELECT_DISTINCT) str->append(STRING_WITH_LEN("distinct ")); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 41117650e4a..f1db513d0e2 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -3341,7 +3341,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) LEX *lex= thd->lex; TABLE *table= tables->table; SELECT_LEX *old_all_select_lex= lex->all_selects_list; - enum_sql_command save_sql_command= lex->sql_command; SELECT_LEX *lsel= tables->schema_select_lex; ST_SCHEMA_TABLE *schema_table= tables->schema_table; SELECT_LEX sel; @@ -3377,6 +3376,12 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) lex->view_prepare_mode= TRUE; lex->reset_n_backup_query_tables_list(&query_tables_list_backup); + /* + Restore Query_tables_list::sql_command value, which was reset + above, as ST_SCHEMA_TABLE::process_table() functions often rely + that this value reflects which SHOW statement is executed. + */ + lex->sql_command= query_tables_list_backup.sql_command; /* We should not introduce deadlocks even if we already have some @@ -3539,7 +3544,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) (MYSQL_OPEN_IGNORE_FLUSH | MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL | (can_deadlock ? MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0))); - lex->sql_command= save_sql_command; + lex->sql_command= query_tables_list_backup.sql_command; /* XXX: show_table_list has a flag i_is_requested, and when it's set, open_normal_and_derived_tables() @@ -3598,7 +3603,6 @@ err: lex->derived_tables= derived_tables; lex->all_selects_list= old_all_select_lex; lex->view_prepare_mode= save_view_prepare_mode; - lex->sql_command= save_sql_command; DBUG_RETURN(error); } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index c752905d14c..b688d706762 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4808,6 +4808,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, /* purecov: begin inspected */ char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE]; size_t length; + enum_sql_command save_sql_command= lex->sql_command; DBUG_PRINT("admin", ("sending error message")); protocol->prepare_for_resend(); protocol->store(table_name, system_charset_info); @@ -4821,6 +4822,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, close_thread_tables(thd); thd->mdl_context.release_transactional_locks(); lex->reset_query_tables_list(FALSE); + /* + Restore Query_tables_list::sql_command value to make statement + safe for re-execution. + */ + lex->sql_command= save_sql_command; table->table=0; // For query cache if (protocol->write()) goto err; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 701a2ec93c2..9ce62d9f2a4 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -411,6 +411,13 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) destructive changes necessary to open the trigger's table. */ thd->lex->reset_n_backup_query_tables_list(&backup); + /* + Restore Query_tables_list::sql_command, which was + reset above, as the code that writes the query to the + binary log assumes that this value corresponds to the + statement that is being executed. + */ + thd->lex->sql_command= backup.sql_command; if (add_table_for_trigger(thd, thd->lex->spname, if_exists, & tables)) goto end; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 41737b33fb6..412a053014f 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1054,7 +1054,7 @@ int mysql_multi_update_prepare(THD *thd) be write-locked (for example, trigger to be invoked might try to update this table). */ - tl->lock_type= read_lock_type_for_table(thd, table); + tl->lock_type= read_lock_type_for_table(thd, lex, tl); tl->updating= 0; /* Update TABLE::lock_type accordingly. */ if (!tl->placeholder() && !using_lock_tables) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a0d64e6a378..aa336f3c072 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -29,6 +29,7 @@ #define YYLEX_PARAM yythd #define YYTHD ((THD *)yythd) #define YYLIP (& YYTHD->m_parser_state->m_lip) +#define YYPS (& YYTHD->m_parser_state->m_yacc) #define MYSQL_YACC #define YYINITDEPTH 100 @@ -4937,7 +4938,6 @@ create_select: SELECT_SYM { LEX *lex=Lex; - lex->lock_option= TL_READ_DEFAULT; if (lex->sql_command == SQLCOM_INSERT) lex->sql_command= SQLCOM_INSERT_SELECT; else if (lex->sql_command == SQLCOM_REPLACE) @@ -7302,7 +7302,6 @@ select_lock_type: { LEX *lex=Lex; lex->current_select->set_lock_for_tables(TL_WRITE); - lex->current_select->lock_option= TL_WRITE; lex->safe_to_cache_query=0; lex->protect_against_global_read_lock= TRUE; } @@ -7311,7 +7310,6 @@ select_lock_type: LEX *lex=Lex; lex->current_select-> set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS); - lex->current_select->lock_option= TL_READ_WITH_SHARED_LOCKS; lex->safe_to_cache_query=0; } ; @@ -9221,7 +9219,7 @@ table_factor: { if (!($$= Select->add_table_to_list(YYTHD, $2, $3, Select->get_table_join_options(), - Lex->lock_option, + YYPS->m_lock_type, Select->pop_index_hints()))) MYSQL_YYABORT; Select->add_joined_table($$); @@ -10278,7 +10276,7 @@ table_alias_ref: { if (!Select->add_table_to_list(YYTHD, $1, NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, - Lex->lock_option )) + YYPS->m_lock_type)) MYSQL_YYABORT; } ; @@ -10303,8 +10301,6 @@ insert: lex->sql_command= SQLCOM_INSERT; lex->duplicates= DUP_ERROR; mysql_init_select(lex); - /* for subselects */ - lex->lock_option= TL_READ_DEFAULT; } insert_lock_option opt_ignore insert2 @@ -10495,7 +10491,6 @@ update: LEX *lex= Lex; mysql_init_select(lex); lex->sql_command= SQLCOM_UPDATE; - lex->lock_option= TL_UNLOCK; /* Will be set later */ lex->duplicates= DUP_ERROR; } opt_low_priority opt_ignore join_table_list @@ -10562,7 +10557,7 @@ delete: LEX *lex= Lex; lex->sql_command= SQLCOM_DELETE; mysql_init_select(lex); - lex->lock_option= TL_WRITE_DEFAULT; + YYPS->m_lock_type= TL_WRITE_DEFAULT; lex->ignore= 0; lex->select_lex.init_order(); } @@ -10573,20 +10568,27 @@ single_multi: FROM table_ident { if (!Select->add_table_to_list(YYTHD, $2, NULL, TL_OPTION_UPDATING, - Lex->lock_option)) + YYPS->m_lock_type)) MYSQL_YYABORT; + YYPS->m_lock_type= TL_READ_DEFAULT; } where_clause opt_order_clause delete_limit_clause {} | table_wild_list - { mysql_init_multi_delete(Lex); } + { + mysql_init_multi_delete(Lex); + YYPS->m_lock_type= TL_READ_DEFAULT; + } FROM join_table_list where_clause { if (multi_delete_set_locks_and_link_aux_tables(Lex)) MYSQL_YYABORT; } | FROM table_alias_ref_list - { mysql_init_multi_delete(Lex); } + { + mysql_init_multi_delete(Lex); + YYPS->m_lock_type= TL_READ_DEFAULT; + } USING join_table_list where_clause { if (multi_delete_set_locks_and_link_aux_tables(Lex)) @@ -10609,7 +10611,7 @@ table_wild_one: ti, NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, - Lex->lock_option)) + YYPS->m_lock_type)) MYSQL_YYABORT; } | ident '.' ident opt_wild @@ -10621,7 +10623,7 @@ table_wild_one: ti, NULL, TL_OPTION_UPDATING | TL_OPTION_ALIAS, - Lex->lock_option)) + YYPS->m_lock_type)) MYSQL_YYABORT; } ; @@ -10638,7 +10640,7 @@ opt_delete_options: opt_delete_option: QUICK { Select->options|= OPTION_QUICK; } - | LOW_PRIORITY { Lex->lock_option= TL_WRITE_LOW_PRIORITY; } + | LOW_PRIORITY { YYPS->m_lock_type= TL_WRITE_LOW_PRIORITY; } | IGNORE_SYM { Lex->ignore= 1; } ; @@ -10724,7 +10726,6 @@ show: { LEX *lex=Lex; lex->wild=0; - lex->lock_option= TL_READ; mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; bzero((char*) &lex->create_info,sizeof(lex->create_info)); @@ -11077,7 +11078,6 @@ describe: describe_command table_ident { LEX *lex= Lex; - lex->lock_option= TL_READ; mysql_init_select(lex); lex->current_select->parsing_place= SELECT_LIST; lex->sql_command= SQLCOM_SHOW_FIELDS; @@ -11291,7 +11291,6 @@ load: { LEX *lex=Lex; lex->sql_command= SQLCOM_LOAD; - lex->lock_option= $4; lex->local_file= $5; lex->duplicates= DUP_ERROR; lex->ignore= 0; @@ -11302,7 +11301,7 @@ load: { LEX *lex=Lex; if (!Select->add_table_to_list(YYTHD, $12, NULL, TL_OPTION_UPDATING, - lex->lock_option)) + $4)) MYSQL_YYABORT; lex->field_list.empty(); lex->update_list.empty(); @@ -13734,17 +13733,6 @@ subselect_start: subselect_end: { LEX *lex=Lex; - /* - Set the required lock level for the tables associated with the - current sub-select. This will overwrite previous lock options set - using st_select_lex::add_table_to_list in any of the following - rules: single_multi, table_wild_one, load_data, table_alias_ref, - table_factor. - The default lock level is TL_READ_DEFAULT but it can be modified - with query options specific for a certain (sub-)SELECT. - */ - lex->current_select-> - set_lock_for_tables(lex->current_select->lock_option); lex->pop_context(); SELECT_LEX *child= lex->current_select; @@ -13776,8 +13764,8 @@ query_expression_option: { if (check_simple_select()) MYSQL_YYABORT; - Lex->lock_option= TL_READ_HIGH_PRIORITY; - Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY; + YYPS->m_lock_type= TL_READ_HIGH_PRIORITY; + Select->options|= SELECT_HIGH_PRIORITY; } | DISTINCT { Select->options|= SELECT_DISTINCT; } | SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; } |