summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorOleksandr Byelkin <sanja@mariadb.com>2020-12-25 09:13:28 +0100
committerOleksandr Byelkin <sanja@mariadb.com>2020-12-25 09:13:28 +0100
commit478b83032b170b2ae030fa77fe4bed60a7910472 (patch)
treea3893bb725e227dc15c6997731cdeba622ae1744 /sql
parent0aa02567dd62d96467f84ba96cc67b103f63c9e0 (diff)
parent043bd85a574a88856ab9c6d497e682ed06fe45e9 (diff)
downloadmariadb-git-478b83032b170b2ae030fa77fe4bed60a7910472.tar.gz
Merge branch '10.3' into 10.4bb-10.4-MDEV-23468
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc2
-rw-r--r--sql/field.h3
-rw-r--r--sql/filesort.cc14
-rw-r--r--sql/handler.cc7
-rw-r--r--sql/item_cmpfunc.cc19
-rw-r--r--sql/item_cmpfunc.h7
-rw-r--r--sql/item_sum.cc14
-rw-r--r--sql/opt_range.cc4
-rw-r--r--sql/sql_base.cc36
-rw-r--r--sql/sql_cache.cc4
-rw-r--r--sql/sql_cache.h2
-rw-r--r--sql/sql_class.h17
-rw-r--r--sql/sql_cte.cc27
-rw-r--r--sql/sql_derived.cc11
-rw-r--r--sql/sql_help.cc3
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/sql_show.cc2
-rw-r--r--sql/sql_type.h4
-rw-r--r--sql/sql_union.cc68
-rw-r--r--sql/sql_update.cc7
-rw-r--r--sql/sql_view.cc2
-rw-r--r--sql/sql_yacc.yy14
-rw-r--r--sql/sql_yacc_ora.yy14
-rw-r--r--sql/sys_vars.cc6
25 files changed, 167 insertions, 127 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 5a694b50fe0..70598619acd 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -8494,7 +8494,7 @@ int Field_blob::store(const char *from,size_t length,CHARSET_INFO *cs)
DBUG_ASSERT(length <= max_data_length());
new_length= length;
- copy_length= (size_t)MY_MIN(UINT_MAX,table->in_use->variables.group_concat_max_len);
+ copy_length= table->in_use->variables.group_concat_max_len;
if (new_length > copy_length)
{
new_length= Well_formed_prefix(cs,
diff --git a/sql/field.h b/sql/field.h
index a512d74b444..b3bc2d4dbea 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1394,8 +1394,6 @@ public:
virtual uint max_packed_col_length(uint max_length)
{ return max_length;}
- virtual bool is_packable() const { return false; }
-
uint offset(const uchar *record) const
{
return (uint) (ptr - record);
@@ -1988,7 +1986,6 @@ public:
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const;
- bool is_packable() const { return true; }
};
/* base class for float and double and decimal (old one) */
diff --git a/sql/filesort.cc b/sql/filesort.cc
index ad4cb2b6e6b..aa25474be1a 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -1978,14 +1978,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
if (sortorder->field)
{
CHARSET_INFO *cs= sortorder->field->sort_charset();
- sortorder->type= sortorder->field->is_packable() ?
- SORT_FIELD_ATTR::VARIABLE_SIZE :
- SORT_FIELD_ATTR::FIXED_SIZE;
-
sortorder->length= sortorder->field->sort_length();
- if (sortorder->is_variable_sized())
- set_if_smaller(sortorder->length, thd->variables.max_sort_length);
-
if (use_strnxfrm((cs=sortorder->field->sort_charset())))
{
*multi_byte_charset= true;
@@ -1996,10 +1989,6 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
}
else
{
- sortorder->type= sortorder->item->type_handler()->is_packable() ?
- SORT_FIELD_ATTR::VARIABLE_SIZE :
- SORT_FIELD_ATTR::FIXED_SIZE;
-
sortorder->item->type_handler()->sortlength(thd, sortorder->item,
sortorder);
if (use_strnxfrm(sortorder->item->collation.collation))
@@ -2009,8 +1998,7 @@ sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
if (sortorder->item->maybe_null)
length++; // Place for NULL marker
}
- if (sortorder->is_variable_sized())
- set_if_smaller(sortorder->length, thd->variables.max_sort_length);
+ set_if_smaller(sortorder->length, thd->variables.max_sort_length);
length+=sortorder->length;
}
sortorder->field= (Field*) 0; // end marker
diff --git a/sql/handler.cc b/sql/handler.cc
index ed12830ce20..34fc2ad7e67 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3322,6 +3322,13 @@ int handler::update_auto_increment()
(table->auto_increment_field_not_null &&
thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO))
{
+
+ /*
+ There could be an error reported because value was truncated
+ when strict mode is enabled.
+ */
+ if (thd->is_error())
+ DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
/*
Update next_insert_id if we had already generated a value in this
statement (case of INSERT VALUES(null),(3763),(null):
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index c43dbcaab78..4f878d8437c 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -5473,6 +5473,7 @@ void Item_func_like::print(String *str, enum_query_type query_type)
longlong Item_func_like::val_int()
{
DBUG_ASSERT(fixed == 1);
+ DBUG_ASSERT(escape != -1);
String* res= args[0]->val_str(&cmp_value1);
if (args[0]->null_value)
{
@@ -5559,15 +5560,29 @@ bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str,
bool escape_used_in_parsing, CHARSET_INFO *cmp_cs,
int *escape)
{
- if (!escape_item->const_during_execution())
+ /*
+ ESCAPE clause accepts only constant arguments and Item_param.
+
+ Subqueries during context_analysis_only might decide they're
+ const_during_execution, but not quite const yet, not evaluate-able.
+ This is fine, as most of context_analysis_only modes will never
+ reach val_int(), so we won't need the value.
+ CONTEXT_ANALYSIS_ONLY_DERIVED being a notable exception here.
+ */
+ if (!escape_item->const_during_execution() ||
+ (!escape_item->const_item() &&
+ !(thd->lex->context_analysis_only & ~CONTEXT_ANALYSIS_ONLY_DERIVED)))
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
return TRUE;
}
-
+
+ IF_DBUG(*escape= -1,);
+
if (escape_item->const_item())
{
/* If we are on execution stage */
+ /* XXX is it safe to evaluate is_expensive() items here? */
String *escape_str= escape_item->val_str(tmp_str);
if (escape_str)
{
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index ab8e15372ad..8160557e006 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -2787,6 +2787,13 @@ public:
return this;
}
+ bool walk(Item_processor processor, bool walk_subquery, void *arg)
+ {
+ return walk_args(processor, walk_subquery, arg)
+ || escape_item->walk(processor, walk_subquery, arg)
+ || (this->*processor)(arg);
+ }
+
bool find_selective_predicates_list_processor(void *arg);
Item *get_copy(THD *thd)
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index e00fc2fd3ab..c97220fd686 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3619,7 +3619,7 @@ int dump_leaf_key(void* key_arg, element_count count __attribute__((unused)),
{
Item_func_group_concat *item= (Item_func_group_concat *) item_arg;
TABLE *table= item->table;
- uint max_length= (uint)table->in_use->variables.group_concat_max_len;
+ uint max_length= table->in_use->variables.group_concat_max_len;
String tmp((char *)table->record[1], table->s->reclength,
default_charset_info);
String tmp2;
@@ -3960,7 +3960,7 @@ bool Item_func_group_concat::repack_tree(THD *thd)
DBUG_ASSERT(tree->size_of_element == st.tree.size_of_element);
st.table= table;
st.len= 0;
- st.maxlen= (size_t)thd->variables.group_concat_max_len;
+ st.maxlen= thd->variables.group_concat_max_len;
tree_walk(tree, &copy_to_tree, &st, left_root_right);
if (st.len <= st.maxlen) // Copying aborted. Must be OOM
{
@@ -3981,7 +3981,7 @@ bool Item_func_group_concat::repack_tree(THD *thd)
decreases up to N=10 (that is, factor=1024) and then starts to increase,
again, very slowly.
*/
-#define GCONCAT_REPACK_FACTOR (1 << 10)
+#define GCONCAT_REPACK_FACTOR 10
bool Item_func_group_concat::add()
{
@@ -4027,7 +4027,7 @@ bool Item_func_group_concat::add()
{
THD *thd= table->in_use;
table->field[0]->store(row_str_len, FALSE);
- if (tree_len > thd->variables.group_concat_max_len * GCONCAT_REPACK_FACTOR
+ if ((tree_len >> GCONCAT_REPACK_FACTOR) > thd->variables.group_concat_max_len
&& tree->elements_in_tree > 1)
if (repack_tree(thd))
return 1;
@@ -4082,9 +4082,9 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
result.set_charset(collation.collation);
result_field= 0;
null_value= 1;
- max_length= (uint32)(thd->variables.group_concat_max_len
- / collation.collation->mbminlen
- * collation.collation->mbmaxlen);
+ max_length= (uint32)MY_MIN(thd->variables.group_concat_max_len
+ / collation.collation->mbminlen
+ * collation.collation->mbmaxlen, UINT_MAX32);
uint32 offset;
if (separator->needs_conversion(separator->length(), separator->charset(),
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 1a7ac1044c3..97ebbdbe8a7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -7800,9 +7800,9 @@ SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param,
{
key_map::Iterator it(field->key_start);
uint key_no;
- while ((key_no= it.next_bit()) != key_map::Iterator::BITMAP_END)
+ while ((key_no= it++) != key_map::Iterator::BITMAP_END)
{
- KEY *key_info= &param->table->key_info[key_no];
+ KEY *key_info= &field->table->key_info[key_no];
if (key_info->user_defined_key_parts == 1 &&
(key_info->flags & HA_NOSAME))
{
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 868d76572e3..8bb601160d6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -6231,6 +6231,7 @@ find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check if there are sufficient access rights to the found field. */
if (check_privileges &&
+ !table_list->is_derived() &&
check_column_grant_in_table_ref(thd, *actual_table, name, length, fld))
fld= WRONG_GRANT;
else
@@ -8092,36 +8093,23 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
- Ensure that we have access rights to all fields to be inserted. Under
- some circumstances, this check may be skipped.
+ Ensure that we have access rights to all fields to be inserted
+ the table 'tables'. Under some circumstances, this check may be skipped.
- - If any_privileges is true, skip the check.
+ The check is skipped in the following cases:
- - If the SELECT privilege has been found as fulfilled already for both
- the TABLE and TABLE_LIST objects (and both of these exist, of
- course), the check is skipped.
+ - any_privileges is true
- - If the SELECT privilege has been found fulfilled for the TABLE object
- and the TABLE_LIST represents a derived table other than a view (see
- below), the check is skipped.
+ - the table is a derived table
- - If the TABLE_LIST object represents a view, we may skip checking if
- the SELECT privilege has been found fulfilled for it, regardless of
- the TABLE object.
+ - the table is a view with SELECT privilege
- - If there is no TABLE object, the test is skipped if either
- * the TABLE_LIST does not represent a view, or
- * the SELECT privilege has been found fulfilled.
-
- A TABLE_LIST that is not a view may be a subquery, an
- information_schema table, or a nested table reference. See the comment
- for TABLE_LIST.
+ - the table is a base table with SELECT privilege
*/
- if (!((table && tables->is_non_derived() &&
- (table->grant.privilege & SELECT_ACL)) ||
- ((!tables->is_non_derived() &&
- (tables->grant.privilege & SELECT_ACL)))) &&
- !any_privileges)
+ if (!any_privileges &&
+ !tables->is_derived() &&
+ !(tables->is_view() && (tables->grant.privilege & SELECT_ACL)) &&
+ !(table && (table->grant.privilege & SELECT_ACL)))
{
field_iterator.set(tables);
if (check_grant_all_columns(thd, SELECT_ACL, &field_iterator))
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 0ba4732b6cd..bef3318f974 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1449,7 +1449,7 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used)
DBUG_PRINT("qcache", ("\
long %d, 4.1: %d, eof: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %llu, TZ: %p, \
-sql mode: 0x%llx, sort len: %llu, conncat len: %llu, div_precision: %zu, \
+sql mode: 0x%llx, sort len: %llu, concat len: %u, div_precision: %zu, \
def_week_frmt: %zu, in_trans: %d, autocommit: %d",
(int)flags.client_long_flag,
(int)flags.client_protocol_41,
@@ -1949,7 +1949,7 @@ Query_cache::send_result_to_client(THD *thd, char *org_sql, uint query_length)
DBUG_PRINT("qcache", ("\
long %d, 4.1: %d, eof: %d, bin_proto: %d, more results %d, pkt_nr: %d, \
CS client: %u, CS result: %u, CS conn: %u, limit: %llu, TZ: %p, \
-sql mode: 0x%llx, sort len: %llu, conncat len: %llu, div_precision: %zu, \
+sql mode: 0x%llx, sort len: %llu, concat len: %u, div_precision: %zu, \
def_week_frmt: %zu, in_trans: %d, autocommit: %d",
(int)flags.client_long_flag,
(int)flags.client_protocol_41,
diff --git a/sql/sql_cache.h b/sql/sql_cache.h
index 92635ecacc7..d59bc37b7a3 100644
--- a/sql/sql_cache.h
+++ b/sql/sql_cache.h
@@ -558,11 +558,11 @@ struct Query_cache_query_flags
uint character_set_client_num;
uint character_set_results_num;
uint collation_connection_num;
+ uint group_concat_max_len;
ha_rows limit;
Time_zone *time_zone;
sql_mode_t sql_mode;
ulonglong max_sort_length;
- ulonglong group_concat_max_len;
size_t default_week_format;
size_t div_precision_increment;
MY_LOCALE *lc_time_names;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 6b3c1594e60..936437fac17 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -592,7 +592,6 @@ typedef struct system_variables
ulonglong bulk_insert_buff_size;
ulonglong join_buff_size;
ulonglong sortbuff_size;
- ulonglong group_concat_max_len;
ulonglong default_regex_flags;
ulonglong max_mem_used;
@@ -685,6 +684,8 @@ typedef struct system_variables
uint32 gtid_domain_id;
uint64 gtid_seq_no;
+ uint group_concat_max_len;
+
/**
Default transaction access mode. READ ONLY (true) or READ WRITE (false).
*/
@@ -5787,10 +5788,15 @@ class select_union_recursive :public select_unit
public:
/* The temporary table with the new records generated by one iterative step */
TABLE *incr_table;
+ /* The TMP_TABLE_PARAM structure used to create incr_table */
+ TMP_TABLE_PARAM incr_table_param;
/* One of tables from the list rec_tables (determined dynamically) */
TABLE *first_rec_table_to_update;
- /* The temporary tables used for recursive table references */
- List<TABLE> rec_tables;
+ /*
+ The list of all recursive table references to the CTE for whose
+ specification this select_union_recursive was created
+ */
+ List<TABLE_LIST> rec_table_refs;
/*
The count of how many times cleanup() was called with cleaned==false
for the unit specifying the recursive CTE for which this object was created
@@ -5800,7 +5806,8 @@ class select_union_recursive :public select_unit
select_union_recursive(THD *thd_arg):
select_unit(thd_arg),
- incr_table(0), first_rec_table_to_update(0), cleanup_count(0) {};
+ incr_table(0), first_rec_table_to_update(0), cleanup_count(0)
+ { incr_table_param.init(); };
int send_data(List<Item> &items);
bool create_result_table(THD *thd, List<Item> *column_types,
@@ -6095,8 +6102,6 @@ struct SORT_FIELD_ATTR
{
uint length; /* Length of sort field */
uint suffix_length; /* Length suffix (0-4) */
- enum Type { FIXED_SIZE, VARIABLE_SIZE } type;
- bool is_variable_sized() { return type == VARIABLE_SIZE; }
};
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index d4b6d815118..a9f5443e36d 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -252,6 +252,8 @@ With_element *With_clause::find_table_def(TABLE_LIST *table,
!table->is_fqtn)
{
table->set_derived();
+ table->db.str= empty_c_string;
+ table->db.length= 0;
return with_elem;
}
}
@@ -887,8 +889,6 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
goto err;
spec_tables_tail= tbl;
}
- if (check_table_access(thd, SELECT_ACL, spec_tables, FALSE, UINT_MAX, FALSE))
- goto err;
if (spec_tables)
{
if (with_table->next_global)
@@ -914,6 +914,22 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd,
with_select));
if (check_dependencies_in_with_clauses(lex->with_clauses_list))
res= NULL;
+ /*
+ Resolve references to CTE from the spec_tables list that has not
+ been resolved yet.
+ */
+ for (TABLE_LIST *tbl= spec_tables;
+ tbl;
+ tbl= tbl->next_global)
+ {
+ if (!tbl->with)
+ tbl->with= with_select->find_table_def_in_with_clauses(tbl);
+ if (tbl == spec_tables_tail)
+ break;
+ }
+ if (check_table_access(thd, SELECT_ACL, spec_tables, FALSE, UINT_MAX, FALSE))
+ goto err;
+
lex->sphead= NULL; // in order not to delete lex->sphead
lex_end(lex);
err:
@@ -1466,10 +1482,11 @@ void With_element::print(String *str, enum_query_type query_type)
bool With_element::instantiate_tmp_tables()
{
- List_iterator_fast<TABLE> li(rec_result->rec_tables);
- TABLE *rec_table;
- while ((rec_table= li++))
+ List_iterator_fast<TABLE_LIST> li(rec_result->rec_table_refs);
+ TABLE_LIST *rec_tbl;
+ while ((rec_tbl= li++))
{
+ TABLE *rec_table= rec_tbl->table;
if (!rec_table->is_created() &&
instantiate_tmp_table(rec_table,
rec_table->s->key_info,
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 1e416c307cf..dc079ba6f16 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -710,7 +710,7 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
if (derived->is_with_table_recursive_reference())
{
/* Here 'derived" is a secondary recursive table reference */
- unit->with_element->rec_result->rec_tables.push_back(derived->table);
+ unit->with_element->rec_result->rec_table_refs.push_back(derived);
}
}
DBUG_ASSERT(derived->table || res);
@@ -808,17 +808,17 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
derived->fill_me= FALSE;
- if (!(derived->derived_result= new (thd->mem_root) select_unit(thd)))
+ if ((!derived->is_with_table_recursive_reference() ||
+ !derived->derived_result) &&
+ !(derived->derived_result= new (thd->mem_root) select_unit(thd)))
DBUG_RETURN(TRUE); // out of memory
- lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
// st_select_lex_unit::prepare correctly work for single select
if ((res= unit->prepare(derived, derived->derived_result, 0)))
goto exit;
if (derived->with &&
(res= derived->with->rename_columns_of_derived_unit(thd, unit)))
goto exit;
- lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
if ((res= check_duplicate_names(thd, unit->types, 0)))
goto exit;
@@ -827,7 +827,8 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
Depending on the result field translation will or will not
be created.
*/
- if (derived->init_derived(thd, FALSE))
+ if (!derived->is_with_table_recursive_reference() &&
+ derived->init_derived(thd, FALSE))
goto exit;
/*
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index e5f1e958d99..81e5ad48e7e 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -742,6 +742,9 @@ static bool mysqld_help_internal(THD *thd, const char *mask)
&name, &description, &example);
delete select;
+ if (thd->is_error())
+ goto error;
+
if (count_topics == 0)
{
int UNINIT_VAR(key_id);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 472dc3b386a..e03b98177d0 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -6805,6 +6805,9 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
bool check_single_table_access(THD *thd, ulong privilege, TABLE_LIST *tables,
bool no_errors)
{
+ if (tables->derived)
+ return 0;
+
Switch_to_definer_security_ctx backup_sctx(thd, tables);
const char *db_name;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9671880f1e0..a6aee4db341 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -13363,10 +13363,6 @@ void JOIN_TAB::cleanup()
{
DBUG_ENTER("JOIN_TAB::cleanup");
- if (tab_list && tab_list->is_with_table_recursive_reference() &&
- tab_list->with->is_cleaned())
- DBUG_VOID_RETURN;
-
DBUG_PRINT("enter", ("tab: %p table %s.%s",
this,
(table ? table->s->db.str : "?"),
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 1fdd2d7c8d0..09d8b6b81a1 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -9861,7 +9861,7 @@ ST_FIELD_INFO check_constraints_fields_info[]=
{"TABLE_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0, OPEN_FULL_TABLE},
{"CONSTRAINT_NAME", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
OPEN_FULL_TABLE},
- {"CHECK_CLAUSE", NAME_CHAR_LEN, MYSQL_TYPE_STRING, 0, 0, 0,
+ {"CHECK_CLAUSE", MAX_FIELD_VARCHARLENGTH , MYSQL_TYPE_STRING, 0, 0, 0,
OPEN_FULL_TABLE},
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
diff --git a/sql/sql_type.h b/sql/sql_type.h
index f8ebc269788..6958d4f970f 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -3655,8 +3655,6 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const= 0;
- virtual bool is_packable() const { return false; }
-
virtual uint32 max_display_length(const Item *item) const= 0;
virtual uint32 Item_decimal_notation_int_digits(const Item *item) const { return 0; }
virtual uint32 calc_pack_length(uint32 length) const= 0;
@@ -4816,8 +4814,6 @@ public:
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
- bool is_packable()const { return true; }
-
bool union_element_finalize(const Item * item) const;
bool Column_definition_prepare_stage1(THD *thd,
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 027d5882722..b295112b70d 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -405,7 +405,10 @@ select_union_recursive::create_result_table(THD *thd_arg,
hidden))
return true;
- if (! (incr_table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
+ incr_table_param.init();
+ incr_table_param.field_count= column_types->elements;
+ incr_table_param.bit_fields_as_long= bit_fields_as_long;
+ if (! (incr_table= create_tmp_table(thd_arg, &incr_table_param, *column_types,
(ORDER*) 0, false, 1,
options, HA_POS_ERROR, &empty_clex_str,
true, keep_row_order)))
@@ -415,20 +418,6 @@ select_union_recursive::create_result_table(THD *thd_arg,
for (uint i=0; i < table->s->fields; i++)
incr_table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
- TABLE *rec_table= 0;
- if (! (rec_table= create_tmp_table(thd_arg, &tmp_table_param, *column_types,
- (ORDER*) 0, false, 1,
- options, HA_POS_ERROR, alias,
- true, keep_row_order)))
- return true;
-
- rec_table->keys_in_use_for_query.clear_all();
- for (uint i=0; i < table->s->fields; i++)
- rec_table->field[i]->flags &= ~(PART_KEY_FLAG | PART_INDIRECT_KEY_FLAG);
-
- if (rec_tables.push_back(rec_table))
- return true;
-
return false;
}
@@ -466,23 +455,25 @@ void select_union_recursive::cleanup()
free_tmp_table(thd, incr_table);
}
- List_iterator<TABLE> it(rec_tables);
- TABLE *tab;
- while ((tab= it++))
+ List_iterator<TABLE_LIST> it(rec_table_refs);
+ TABLE_LIST *tbl;
+ while ((tbl= it++))
{
+ TABLE *tab= tbl->table;
if (tab->is_created())
{
tab->file->extra(HA_EXTRA_RESET_STATE);
tab->file->ha_delete_all_rows();
}
- /*
+ /*
The table will be closed later in close_thread_tables(),
because it might be used in the statements like
ANALYZE WITH r AS (...) SELECT * from r
- where r is defined through recursion.
+ where r is defined through recursion.
*/
tab->next= thd->rec_tables;
thd->rec_tables= tab;
+ tbl->derived_result= 0;
}
}
@@ -1138,9 +1129,33 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
goto err;
if (!derived_arg->table)
{
- derived_arg->table= with_element->rec_result->rec_tables.head();
- if (derived_arg->derived_result)
- derived_arg->derived_result->table= derived_arg->table;
+ bool res= false;
+
+ if ((!derived_arg->is_with_table_recursive_reference() ||
+ !derived_arg->derived_result) &&
+ !(derived_arg->derived_result=
+ new (thd->mem_root) select_unit(thd)))
+ goto err; // out of memory
+ thd->create_tmp_table_for_derived= TRUE;
+
+ res= derived_arg->derived_result->create_result_table(thd,
+ &types,
+ FALSE,
+ create_options,
+ &derived_arg->alias,
+ FALSE, FALSE,
+ FALSE, 0);
+ thd->create_tmp_table_for_derived= FALSE;
+ if (res)
+ goto err;
+ derived_arg->derived_result->set_unit(this);
+ derived_arg->table= derived_arg->derived_result->table;
+ if (derived_arg->is_with_table_recursive_reference())
+ {
+ /* Here 'derived_arg' is the primary recursive table reference */
+ derived_arg->with->rec_result->
+ rec_table_refs.push_back(derived_arg);
+ }
}
with_element->mark_as_with_prepared_anchor();
is_rec_result_table_created= true;
@@ -1783,11 +1798,11 @@ bool st_select_lex_unit::exec_recursive()
TABLE *incr_table= with_element->rec_result->incr_table;
st_select_lex *end= NULL;
bool is_unrestricted= with_element->is_unrestricted();
- List_iterator_fast<TABLE> li(with_element->rec_result->rec_tables);
+ List_iterator_fast<TABLE_LIST> li(with_element->rec_result->rec_table_refs);
TMP_TABLE_PARAM *tmp_table_param= &with_element->rec_result->tmp_table_param;
ha_rows examined_rows= 0;
bool was_executed= executed;
- TABLE *rec_table;
+ TABLE_LIST *rec_tbl;
DBUG_ENTER("st_select_lex_unit::exec_recursive");
@@ -1865,8 +1880,9 @@ bool st_select_lex_unit::exec_recursive()
else
with_element->level++;
- while ((rec_table= li++))
+ while ((rec_tbl= li++))
{
+ TABLE *rec_table= rec_tbl->table;
saved_error=
incr_table->insert_all_rows_into_tmp_table(thd, rec_table,
tmp_table_param,
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 367682c74e9..eac8d91b3f5 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -1852,7 +1852,11 @@ int mysql_multi_update_prepare(THD *thd)
During prepare phase acquire only S metadata locks instead of SW locks to
keep prepare of multi-UPDATE compatible with concurrent LOCK TABLES WRITE
and global read lock.
+
+ Don't evaluate any subqueries even if constant, because
+ tables aren't locked yet.
*/
+ lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI)
{
if (open_tables(thd, &table_list, &table_count,
@@ -1875,6 +1879,9 @@ int mysql_multi_update_prepare(THD *thd)
{
DBUG_RETURN(TRUE);
}
+
+ lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_DERIVED;
+
(void) read_statistics_for_tables_if_needed(thd, table_list);
/* @todo: downgrade the metadata locks here. */
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 0a18a852832..126db90656c 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -292,6 +292,8 @@ bool create_view_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *view,
{
for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local)
{
+ if (!tbl->with && tbl->select_lex)
+ tbl->with= tbl->select_lex->find_table_def_in_with_clauses(tbl);
/*
Ensure that we have some privileges on this table, more strict check
will be done on column level after preparation,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 47102c3c6aa..2548dc28731 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -829,7 +829,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
/*
We should not introduce any further shift/reduce conflicts.
*/
-%expect 54
+%expect 47
/*
Comments for TOKENS.
@@ -1879,7 +1879,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <item>
literal insert_ident order_ident temporal_literal
simple_ident expr sum_expr in_sum_expr
- variable variable_aux bool_pri
+ variable variable_aux
predicate bit_expr parenthesized_expr
table_wild simple_expr column_default_non_parenthesized_expr udf_expr
primary_expr string_factor_expr mysql_concatenation_expr
@@ -10064,23 +10064,19 @@ expr:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bool_pri
- ;
-
-bool_pri:
- bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
+ | expr EQUAL_SYM predicate %prec EQUAL_SYM
{
$$= new (thd->mem_root) Item_func_equal(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bool_pri comp_op predicate %prec '='
+ | expr comp_op predicate %prec '='
{
$$= (*$2)(0)->create(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bool_pri comp_op all_or_any '(' subselect ')' %prec '='
+ | expr comp_op all_or_any '(' subselect ')' %prec '='
{
$$= all_any_subquery_creator(thd, $1, $2, $3, $5);
if (unlikely($$ == NULL))
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index ac4929468b1..30727a8ffc4 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -305,7 +305,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
/*
We should not introduce any further shift/reduce conflicts.
*/
-%expect 57
+%expect 50
/*
Comments for TOKENS.
@@ -1362,7 +1362,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <item>
literal insert_ident order_ident temporal_literal
simple_ident expr sum_expr in_sum_expr
- variable variable_aux bool_pri
+ variable variable_aux
predicate bit_expr parenthesized_expr
table_wild simple_expr column_default_non_parenthesized_expr udf_expr
primary_expr string_factor_expr mysql_concatenation_expr
@@ -10168,23 +10168,19 @@ expr:
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bool_pri
- ;
-
-bool_pri:
- bool_pri EQUAL_SYM predicate %prec EQUAL_SYM
+ | expr EQUAL_SYM predicate %prec EQUAL_SYM
{
$$= new (thd->mem_root) Item_func_equal(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bool_pri comp_op predicate %prec '='
+ | expr comp_op predicate %prec '='
{
$$= (*$2)(0)->create(thd, $1, $3);
if (unlikely($$ == NULL))
MYSQL_YYABORT;
}
- | bool_pri comp_op all_or_any '(' subselect ')' %prec '='
+ | expr comp_op all_or_any '(' subselect ')' %prec '='
{
$$= all_any_subquery_creator(thd, $1, $2, $3, $5);
if (unlikely($$ == NULL))
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 4c3028b0a00..5f5f9b5daf8 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2352,7 +2352,7 @@ static Sys_var_ulong Sys_max_sort_length(
"the first max_sort_length bytes of each value are used; the rest "
"are ignored)",
SESSION_VAR(max_sort_length), CMD_LINE(REQUIRED_ARG),
- VALID_RANGE(8, 8192*1024L), DEFAULT(1024), BLOCK_SIZE(1));
+ VALID_RANGE(64, 8192*1024L), DEFAULT(1024), BLOCK_SIZE(1));
static Sys_var_ulong Sys_max_sp_recursion_depth(
"max_sp_recursion_depth",
@@ -4570,11 +4570,11 @@ static Sys_var_ulong Sys_default_week_format(
SESSION_VAR(default_week_format), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, 7), DEFAULT(0), BLOCK_SIZE(1));
-static Sys_var_ulonglong Sys_group_concat_max_len(
+static Sys_var_uint Sys_group_concat_max_len(
"group_concat_max_len",
"The maximum length of the result of function GROUP_CONCAT()",
SESSION_VAR(group_concat_max_len), CMD_LINE(REQUIRED_ARG),
- VALID_RANGE(4, SIZE_T_MAX), DEFAULT(1024*1024), BLOCK_SIZE(1));
+ VALID_RANGE(4, UINT_MAX32), DEFAULT(1024*1024), BLOCK_SIZE(1));
static char *glob_hostname_ptr;
static Sys_var_charptr Sys_hostname(