diff options
author | Oleksandr Byelkin <sanja@mariadb.com> | 2020-12-25 09:13:28 +0100 |
---|---|---|
committer | Oleksandr Byelkin <sanja@mariadb.com> | 2020-12-25 09:13:28 +0100 |
commit | 478b83032b170b2ae030fa77fe4bed60a7910472 (patch) | |
tree | a3893bb725e227dc15c6997731cdeba622ae1744 /sql | |
parent | 0aa02567dd62d96467f84ba96cc67b103f63c9e0 (diff) | |
parent | 043bd85a574a88856ab9c6d497e682ed06fe45e9 (diff) | |
download | mariadb-git-478b83032b170b2ae030fa77fe4bed60a7910472.tar.gz |
Merge branch '10.3' into 10.4bb-10.4-MDEV-23468
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field.h | 3 | ||||
-rw-r--r-- | sql/filesort.cc | 14 | ||||
-rw-r--r-- | sql/handler.cc | 7 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 19 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 7 | ||||
-rw-r--r-- | sql/item_sum.cc | 14 | ||||
-rw-r--r-- | sql/opt_range.cc | 4 | ||||
-rw-r--r-- | sql/sql_base.cc | 36 | ||||
-rw-r--r-- | sql/sql_cache.cc | 4 | ||||
-rw-r--r-- | sql/sql_cache.h | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 17 | ||||
-rw-r--r-- | sql/sql_cte.cc | 27 | ||||
-rw-r--r-- | sql/sql_derived.cc | 11 | ||||
-rw-r--r-- | sql/sql_help.cc | 3 | ||||
-rw-r--r-- | sql/sql_parse.cc | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 4 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 | ||||
-rw-r--r-- | sql/sql_type.h | 4 | ||||
-rw-r--r-- | sql/sql_union.cc | 68 | ||||
-rw-r--r-- | sql/sql_update.cc | 7 | ||||
-rw-r--r-- | sql/sql_view.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 14 | ||||
-rw-r--r-- | sql/sql_yacc_ora.yy | 14 | ||||
-rw-r--r-- | sql/sys_vars.cc | 6 |
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, ©_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= ¶m->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( |