diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/gen_win_tzname_data.ps1 | 1 | ||||
-rw-r--r-- | sql/item.h | 36 | ||||
-rw-r--r-- | sql/sql_base.cc | 3 | ||||
-rw-r--r-- | sql/sql_class.h | 4 | ||||
-rw-r--r-- | sql/sql_delete.cc | 19 | ||||
-rw-r--r-- | sql/sql_derived.cc | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 21 | ||||
-rw-r--r-- | sql/sql_lex.h | 30 | ||||
-rw-r--r-- | sql/sql_table.cc | 55 | ||||
-rw-r--r-- | sql/sql_update.cc | 38 | ||||
-rw-r--r-- | sql/win_tzname_data.h | 1 |
11 files changed, 179 insertions, 34 deletions
diff --git a/sql/gen_win_tzname_data.ps1 b/sql/gen_win_tzname_data.ps1 index c0a37d21895..474ab889d25 100644 --- a/sql/gen_win_tzname_data.ps1 +++ b/sql/gen_win_tzname_data.ps1 @@ -4,6 +4,7 @@ write-output "/* This file was generated using gen_win_tzname_data.ps1 */" $xdoc = new-object System.Xml.XmlDocument +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $xdoc.load("https://raw.githubusercontent.com/unicode-org/cldr/master/common/supplemental/windowsZones.xml") $nodes = $xdoc.SelectNodes("//mapZone[@territory='001']") # use default territory (001) foreach ($node in $nodes) { diff --git a/sql/item.h b/sql/item.h index 717e49e5b33..dbd2cb0b1df 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1938,6 +1938,15 @@ public: return 0; } + /** + Check db/table_name if they defined in item and match arg values + + @param arg Pointer to Check_table_name_prm structure + + @retval true Match failed + @retval false Match succeeded + */ + virtual bool check_table_name_processor(void *arg) { return false; } /* TRUE if the expression depends only on the table indicated by tab_map or can be converted to such an exression using equalities. @@ -2096,6 +2105,15 @@ public: bool collect; }; + struct Check_table_name_prm + { + LEX_CSTRING db; + LEX_CSTRING table_name; + String field; + Check_table_name_prm(LEX_CSTRING _db, LEX_CSTRING _table_name) : + db(_db), table_name(_table_name) {} + }; + /* For SP local variable returns pointer to Item representing its current value and pointer to current Item otherwise. @@ -3500,6 +3518,24 @@ public: } return 0; } + bool check_table_name_processor(void *arg) + { + Check_table_name_prm &p= *(Check_table_name_prm *) arg; + if (p.table_name.length && table_name) + { + DBUG_ASSERT(p.db.length); + if ((db_name && + my_strcasecmp(table_alias_charset, p.db.str, db_name)) || + my_strcasecmp(table_alias_charset, p.table_name.str, table_name)) + { + print(&p.field, (enum_query_type) (QT_ITEM_ORIGINAL_FUNC_NULLIF | + QT_NO_DATA_EXPANSION | + QT_TO_SYSTEM_CHARSET)); + return true; + } + } + return false; + } void cleanup(); Item_equal *get_item_equal() { return item_equal; } void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a1be9e76fc8..cc6ecda9327 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7952,7 +7952,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context, if (table_list->jtbm_subselect) { Item *item= table_list->jtbm_subselect->optimizer; - if (table_list->jtbm_subselect->optimizer->fix_fields(thd, &item)) + if (!table_list->jtbm_subselect->optimizer->fixed && + table_list->jtbm_subselect->optimizer->fix_fields(thd, &item)) { my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES)); /* psergey-todo: WHY ER_TOO_MANY_TABLES ???*/ DBUG_RETURN(1); diff --git a/sql/sql_class.h b/sql/sql_class.h index 6701c366f0a..d33cd1b35a4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -6267,7 +6267,8 @@ public: class multi_update :public select_result_interceptor { TABLE_LIST *all_tables; /* query/update command tables */ - List<TABLE_LIST> *leaves; /* list of leves of join table tree */ + List<TABLE_LIST> *leaves; /* list of leaves of join table tree */ + List<TABLE_LIST> updated_leaves; /* list of of updated leaves */ TABLE_LIST *update_tables; TABLE **tmp_tables, *main_table, *table_to_update; TMP_TABLE_PARAM *tmp_table_param; @@ -6305,6 +6306,7 @@ public: List<Item> *fields, List<Item> *values, enum_duplicates handle_duplicates, bool ignore); ~multi_update(); + bool init(THD *thd); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int send_data(List<Item> &items); bool initialize_tables (JOIN *join); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index be8767af111..9fa1e015274 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2010, 2019, MariaDB + Copyright (c) 2010, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1128,14 +1128,11 @@ int mysql_multi_delete_prepare(THD *thd) FALSE, DELETE_ACL, SELECT_ACL, FALSE)) DBUG_RETURN(TRUE); - if (lex->first_select_lex()->handle_derived(thd->lex, DT_MERGE)) - DBUG_RETURN(TRUE); - /* Multi-delete can't be constructed over-union => we always have single SELECT on top and have to check underlying SELECTs of it */ - lex->first_select_lex()->exclude_from_table_unique_test= TRUE; + lex->first_select_lex()->set_unique_exclude(); /* Fix tables-to-be-deleted-from list to point at opened tables */ for (target_tbl= (TABLE_LIST*) aux_tables; target_tbl; @@ -1158,6 +1155,12 @@ int mysql_multi_delete_prepare(THD *thd) target_tbl->table_name.str, "DELETE"); DBUG_RETURN(TRUE); } + } + + for (target_tbl= (TABLE_LIST*) aux_tables; + target_tbl; + target_tbl= target_tbl->next_local) + { /* Check that table from which we delete is not used somewhere inside subqueries/view. @@ -1202,12 +1205,6 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u) unit= u; do_delete= 1; THD_STAGE_INFO(thd, stage_deleting_from_main_table); - SELECT_LEX *select_lex= u->first_select(); - if (select_lex->first_cond_optimization) - { - if (select_lex->handle_derived(thd->lex, DT_MERGE)) - DBUG_RETURN(TRUE); - } DBUG_RETURN(0); } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index c5874046224..132872c4a9e 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -382,10 +382,6 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_RETURN(FALSE); } - if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || - thd->lex->sql_command == SQLCOM_DELETE_MULTI) - thd->save_prep_leaf_list= TRUE; - arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test if (!derived->merged_for_insert || @@ -459,6 +455,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) derived->on_expr= expr; derived->prep_on_expr= expr->copy_andor_structure(thd); } + thd->where= "on clause"; if (derived->on_expr && derived->on_expr->fix_fields_if_needed_for_bool(thd, &derived->on_expr)) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c840ae6990c..5937c43c95d 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -5047,6 +5047,27 @@ bool st_select_lex::save_prep_leaf_tables(THD *thd) } +/** + Set exclude_from_table_unique_test for selects of this select and all selects + belonging to the underlying units of derived tables or views +*/ + +void st_select_lex::set_unique_exclude() +{ + exclude_from_table_unique_test= TRUE; + for (SELECT_LEX_UNIT *unit= first_inner_unit(); + unit; + unit= unit->next_unit()) + { + if (unit->derived && unit->derived->is_view_or_derived()) + { + for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) + sl->set_unique_exclude(); + } + } +} + + /* Return true if this select_lex has been converted into a semi-join nest within 'ancestor'. diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 960e36f63b4..466b23b3f94 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2010, 2019, MariaDB Corporation. + Copyright (c) 2010, 2021, MariaDB Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -938,6 +938,10 @@ public: void init_query(); st_select_lex* outer_select(); + const st_select_lex* first_select() const + { + return reinterpret_cast<const st_select_lex*>(slave); + } st_select_lex* first_select() { return reinterpret_cast<st_select_lex*>(slave); @@ -1473,6 +1477,8 @@ public: bool save_leaf_tables(THD *thd); bool save_prep_leaf_tables(THD *thd); + void set_unique_exclude(); + bool is_merged_child_of(st_select_lex *ancestor); /* @@ -3081,7 +3087,8 @@ public: struct LEX: public Query_tables_list { SELECT_LEX_UNIT unit; /* most upper unit */ - inline SELECT_LEX *first_select_lex() {return unit.first_select();} + SELECT_LEX *first_select_lex() { return unit.first_select(); } + const SELECT_LEX *first_select_lex() const { return unit.first_select(); } private: SELECT_LEX builtin_select; @@ -4345,6 +4352,25 @@ public: return false; } + bool create_like() const + { + DBUG_ASSERT(!create_info.like() || + !first_select_lex()->item_list.elements); + return create_info.like(); + } + + bool create_select() const + { + DBUG_ASSERT(!create_info.like() || + !first_select_lex()->item_list.elements); + return first_select_lex()->item_list.elements; + } + + bool create_simple() const + { + return !create_like() && !create_select(); + } + SELECT_LEX *exclude_last_select(); SELECT_LEX *exclude_not_first_select(SELECT_LEX *exclude); void check_automatic_up(enum sub_select_type type); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f66963d7b4f..0249ae68cc3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -74,7 +74,9 @@ static int copy_data_between_tables(THD *, TABLE *,TABLE *, Alter_info::enum_enable_or_disable, Alter_table_ctx *); static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *, - uint *, handler *, KEY **, uint *, int); + uint *, handler *, KEY **, uint *, int, + const LEX_CSTRING db, + const LEX_CSTRING table_name); static uint blob_length_by_type(enum_field_types type); static bool fix_constraints_names(THD *, List<Virtual_column_info> *, const HA_CREATE_INFO *); @@ -1824,7 +1826,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) if (mysql_prepare_create_table(lpt->thd, lpt->create_info, lpt->alter_info, &lpt->db_options, lpt->table->file, &lpt->key_info_buffer, &lpt->key_count, - C_ALTER_TABLE)) + C_ALTER_TABLE, lpt->db, lpt->table_name)) { DBUG_RETURN(TRUE); } @@ -3392,7 +3394,8 @@ static int mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, Alter_info *alter_info, uint *db_options, handler *file, KEY **key_info_buffer, - uint *key_count, int create_table_mode) + uint *key_count, int create_table_mode, + const LEX_CSTRING db, const LEX_CSTRING table_name) { const char *key_name; Create_field *sql_field,*dup_field; @@ -3407,6 +3410,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, uint total_uneven_bit_length= 0; int select_field_count= C_CREATE_SELECT(create_table_mode); bool tmp_table= create_table_mode == C_ALTER_TABLE; + const bool create_simple= thd->lex->create_simple(); bool is_hash_field_needed= false; const Column_derived_attributes dattr(create_info->default_table_charset); const Column_bulk_alter_attributes @@ -4256,6 +4260,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, create_info->null_bits= null_fields; /* Check fields. */ + Item::Check_table_name_prm walk_prm(db, table_name); it.rewind(); while ((sql_field=it++)) { @@ -4310,6 +4315,37 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->field_name.str); DBUG_RETURN(TRUE); } + + if (create_simple) + { + /* + NOTE: we cannot do this in check_vcol_func_processor() as there is already + no table name qualifier in expression. + */ + if (sql_field->vcol_info && sql_field->vcol_info->expr && + sql_field->vcol_info->expr->walk(&Item::check_table_name_processor, + false, (void *) &walk_prm)) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "GENERATED ALWAYS"); + DBUG_RETURN(TRUE); + } + + if (sql_field->default_value && + sql_field->default_value->expr->walk(&Item::check_table_name_processor, + false, (void *) &walk_prm)) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "DEFAULT"); + DBUG_RETURN(TRUE); + } + + if (sql_field->check_constraint && + sql_field->check_constraint->expr->walk(&Item::check_table_name_processor, + false, (void *) &walk_prm)) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK"); + DBUG_RETURN(TRUE); + } + } } /* Check table level constraints */ @@ -4319,6 +4355,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, Virtual_column_info *check; while ((check= c_it++)) { + if (create_simple && check->expr->walk(&Item::check_table_name_processor, false, + (void *) &walk_prm)) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK"); + DBUG_RETURN(TRUE); + } if (!check->name.length || check->automatic_name) continue; @@ -4844,7 +4886,8 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db, } if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options, - file, key_info, key_count, create_table_mode)) + file, key_info, key_count, + create_table_mode, db, table_name)) goto err; create_info->table_options=db_options; @@ -7320,13 +7363,15 @@ bool mysql_compare_tables(TABLE *table, Alter_info tmp_alter_info(*alter_info, thd->mem_root); uint db_options= 0; /* not used */ KEY *key_info_buffer= NULL; + LEX_CSTRING db= { table->s->db.str, table->s->db.length }; + LEX_CSTRING table_name= { table->s->db.str, table->s->table_name.length }; /* Create the prepared information. */ int create_table_mode= table->s->tmp_table == NO_TMP_TABLE ? C_ORDINARY_CREATE : C_ALTER_TABLE; if (mysql_prepare_create_table(thd, create_info, &tmp_alter_info, &db_options, table->file, &key_info_buffer, - &key_count, create_table_mode)) + &key_count, create_table_mode, db, table_name)) DBUG_RETURN(1); /* Some very basic checks. */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 19a9a15921b..41ea52ef3c3 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1710,15 +1710,8 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd) call in setup_tables()). */ - if (setup_tables_and_check_access(thd, &select_lex->context, - &select_lex->top_join_list, table_list, select_lex->leaf_tables, - FALSE, UPDATE_ACL, SELECT_ACL, FALSE)) - DBUG_RETURN(1); - - if (select_lex->handle_derived(thd->lex, DT_MERGE)) - DBUG_RETURN(1); - - if (thd->lex->save_prep_leaf_tables()) + if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, + table_list, select_lex->leaf_tables, FALSE, TRUE)) DBUG_RETURN(1); List<Item> *fields= &lex->first_select_lex()->item_list; @@ -1944,9 +1937,16 @@ bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List<Item> *fields, DBUG_RETURN(TRUE); } + if ((*result)->init(thd)) + DBUG_RETURN(1); + thd->abort_on_warning= !ignore && thd->is_strict_mode(); List<Item> total_list; + if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, + table_list, select_lex->leaf_tables, FALSE, FALSE)) + DBUG_RETURN(1); + if (select_lex->vers_setup_conds(thd, table_list)) DBUG_RETURN(1); @@ -1988,6 +1988,24 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, } +bool multi_update::init(THD *thd) +{ + table_map tables_to_update= get_table_map(fields); + List_iterator_fast<TABLE_LIST> li(*leaves); + TABLE_LIST *tbl; + while ((tbl =li++)) + { + if (tbl->is_jtbm()) + continue; + if (!(tbl->table->map & tables_to_update)) + continue; + if (updated_leaves.push_back(tbl, thd->mem_root)) + return true; + } + return false; +} + + /* Connect fields with tables and create list of tables that are updated */ @@ -2004,7 +2022,7 @@ int multi_update::prepare(List<Item> ¬_used_values, List_iterator_fast<Item> value_it(*values); uint i, max_fields; uint leaf_table_count= 0; - List_iterator<TABLE_LIST> ti(*leaves); + List_iterator<TABLE_LIST> ti(updated_leaves); DBUG_ENTER("multi_update::prepare"); if (prepared) diff --git a/sql/win_tzname_data.h b/sql/win_tzname_data.h index 03197227f8e..792cdbc7a13 100644 --- a/sql/win_tzname_data.h +++ b/sql/win_tzname_data.h @@ -12,6 +12,7 @@ {L"US Mountain Standard Time","America/Phoenix"}, {L"Mountain Standard Time (Mexico)","America/Chihuahua"}, {L"Mountain Standard Time","America/Denver"}, +{L"Yukon Standard Time","America/Whitehorse"}, {L"Central America Standard Time","America/Guatemala"}, {L"Central Standard Time","America/Chicago"}, {L"Easter Island Standard Time","Pacific/Easter"}, |