summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/gen_win_tzname_data.ps11
-rw-r--r--sql/item.h36
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_class.h4
-rw-r--r--sql/sql_delete.cc19
-rw-r--r--sql/sql_derived.cc5
-rw-r--r--sql/sql_lex.cc21
-rw-r--r--sql/sql_lex.h30
-rw-r--r--sql/sql_table.cc55
-rw-r--r--sql/sql_update.cc38
-rw-r--r--sql/win_tzname_data.h1
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> &not_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"},