From 50d7eddc3d21b9bad66db6961900e3222a6fa356 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 4 Dec 2020 08:50:20 -0800 Subject: MDEV-24314 Unexpected error message when selecting from view that uses mergeable derived table Do not check privileges for derived tables/CTEs and their fields. Approved by Oleksandr Byelkin --- sql/sql_base.cc | 1 + sql/sql_parse.cc | 3 +++ 2 files changed, 4 insertions(+) (limited to 'sql') diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 590073bbed7..622273648a1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5795,6 +5795,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= WRONG_GRANT; else diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0166c4554e7..6e1d36b79a4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6639,6 +6639,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->is_derived()) + return 0; + Switch_to_definer_security_ctx backup_sctx(thd, tables); const char *db_name; -- cgit v1.2.1 From f924a3bd6cd70c140f00d162ad18da003cc87a89 Mon Sep 17 00:00:00 2001 From: Anel Husakovic Date: Tue, 1 Dec 2020 15:40:44 +0100 Subject: MDEV-24139: CHECK_CLAUSE field in INFORMATION_SCHEMA.CHECK_CONSTRAINTS truncate check constraints expressions - Reviewed by: daniel@mariadb.org --- sql/sql_show.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 5544c765775..3babaabb37d 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -9410,7 +9410,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} }; -- cgit v1.2.1 From 2db6eb142956cd1744cf5c452bca66b20067d73e Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Fri, 4 Dec 2020 14:20:52 -0800 Subject: MDEV-22781 CREATE VIEW containing WITH clause Signal 11 For table references to CTEs the field TABLE_LIST::db must be set to an empty string as it's done for table references to derived tables in order CTEs to be processed similar to how derived tables are processed. Approved by Oleksandr Byelkin --- sql/sql_cte.cc | 1 + sql/sql_view.cc | 2 ++ 2 files changed, 3 insertions(+) (limited to 'sql') diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index fe8e0de71b4..a8bccf0c1dd 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -227,6 +227,7 @@ With_element *With_clause::find_table_def(TABLE_LIST *table, !table->is_fqtn) { table->set_derived(); + table->db= empty_c_string; return with_elem; } } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 8bfe6896ea2..0701c5233ac 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -291,6 +291,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, -- cgit v1.2.1 From a3f7f2334a267ec4e120f70e84a8551fb502860f Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Tue, 8 Dec 2020 11:13:36 -0800 Subject: MDEV-24019 Assertion is hit for query using recursive CTE with no default DB When the query using a recursive CTE whose definition contained wildcard symbols in the recursive part was processed at the prepare stage an assertion was hit if the query was executed without any default database set. The failure happened when the function insert_fields() tried to check column privileges for the temporary table created for a recursive reference to the CTE. No acl checks are needed for any CTE. That's why this check should be blocked as well. The patch formulates a stricter condition at which this check is to be blocked that covers the case when a query using recursive CTEs is executed with no default database set. Approved by Oleksandr Byelkin --- sql/sql_base.cc | 35 +++++++++++------------------------ 1 file changed, 11 insertions(+), 24 deletions(-) (limited to 'sql') diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 622273648a1..8e57ea437b6 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7648,36 +7648,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)) -- cgit v1.2.1 From 59bbe873d48b13eb3b8a912c2187ea94ee165ae9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 3 Nov 2020 19:07:16 +0100 Subject: Revert "MDEV-24033: SIGSEGV in __memcmp_avx2_movbe from queue_insert | SIGSEGV in __memcmp_avx2_movbe from native_compare" This reverts commit 5a0c34e4c2fd951119efb432eedcaa65a1d36606. but keeps the test case --- sql/field.h | 3 --- sql/filesort.cc | 14 +------------- sql/sql_class.h | 2 -- sql/sql_type.h | 2 -- 4 files changed, 1 insertion(+), 20 deletions(-) (limited to 'sql') diff --git a/sql/field.h b/sql/field.h index fea40251587..18e44f1d9d4 100644 --- a/sql/field.h +++ b/sql/field.h @@ -1339,8 +1339,6 @@ public: virtual uint max_packed_col_length(uint max_length) { return max_length;} - virtual bool is_packable() const { return false; } - uint offset(uchar *record) const { return (uint) (ptr - record); @@ -1829,7 +1827,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 96f9aa874da..d76c39c3bd4 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1971,14 +1971,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; @@ -1989,10 +1982,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->sortlength(thd, sortorder->item, sortorder); if (use_strnxfrm(sortorder->item->collation.collation)) { @@ -2001,8 +1990,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/sql_class.h b/sql/sql_class.h index 84f188b7803..d2b0b40846b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5456,8 +5456,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_type.h b/sql/sql_type.h index 046b42e4a83..42090037ead 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -92,7 +92,6 @@ public: virtual void sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const= 0; - virtual bool is_packable() const { return false; } }; @@ -170,7 +169,6 @@ public: void sortlength(THD *thd, const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const; - bool is_packable()const { return true; } }; -- cgit v1.2.1 From b31912fd3525be526cd2852e376bd7d1e7ec4d31 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 3 Nov 2020 23:38:31 +0100 Subject: MDEV-24033: SIGSEGV in __memcmp_avx2_movbe from queue_insert | SIGSEGV in __memcmp_avx2_movbe from native_compare don't allow too small max_sort_length values --- sql/sys_vars.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 7b74689a7f0..e1252acefcc 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2224,7 +2224,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", -- cgit v1.2.1 From f6e91552f00daf7f87bffd3a64082dc5673af95c Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 11 Nov 2020 15:51:18 +0100 Subject: MDEV-4677 GROUP_CONCAT not showing any output with group_concat_max_len >= 4Gb don't allow group_concat_max_len values >= 4Gb (they never worked anyway) --- sql/field.cc | 2 +- sql/item_sum.cc | 14 +++++++------- sql/sql_cache.cc | 4 ++-- sql/sql_cache.h | 2 +- sql/sql_class.h | 3 ++- sql/sys_vars.cc | 4 ++-- 6 files changed, 15 insertions(+), 14 deletions(-) (limited to 'sql') diff --git a/sql/field.cc b/sql/field.cc index fbce8b9041d..9ea1eac9db9 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -8255,7 +8255,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) DBUG_ASSERT(length <= max_data_length()); new_length= length; - copy_length= (uint)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/item_sum.cc b/sql/item_sum.cc index 9490c71c19e..dd65f04a652 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -3171,7 +3171,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; @@ -3499,7 +3499,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 { @@ -3520,7 +3520,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() { @@ -3566,7 +3566,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; @@ -3624,9 +3624,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/sql_cache.cc b/sql/sql_cache.cc index 8555ae6ee3e..0de153a5e7d 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1451,7 +1451,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: %lu, \ +sql mode: 0x%llx, sort len: %llu, concat len: %u, div_precision: %lu, \ def_week_frmt: %lu, in_trans: %d, autocommit: %d", (int)flags.client_long_flag, (int)flags.client_protocol_41, @@ -1951,7 +1951,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: %lu, \ +sql mode: 0x%llx, sort len: %llu, concat len: %u, div_precision: %lu, \ def_week_frmt: %lu, 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 6ad73bbb0a2..d428c7fdb80 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -554,11 +554,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; ulong default_week_format; ulong div_precision_increment; MY_LOCALE *lc_time_names; diff --git a/sql/sql_class.h b/sql/sql_class.h index d2b0b40846b..35068245830 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -555,7 +555,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; @@ -645,6 +644,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). */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index e1252acefcc..baf27a7d0af 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4157,11 +4157,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( -- cgit v1.2.1 From 493c7d34cb2c5c0bc8c495d1dd7b2394c62036ad Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 23 Nov 2020 14:10:44 +0100 Subject: MDEV-24194 View definition corruption fix parsing of "1 IS NULL = 2" --- sql/sql_yacc.yy | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'sql') diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2eabc4f0a6d..1f37296842c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1030,10 +1030,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %parse-param { THD *thd } %lex-param { THD *thd } /* - Currently there are 105 shift/reduce conflicts. + Currently there are 98 shift/reduce conflicts. We should not introduce new conflicts any more. */ -%expect 105 +%expect 98 /* Comments for TOKENS. @@ -1836,7 +1836,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %type literal text_literal insert_ident order_ident temporal_literal simple_ident expr opt_expr opt_else 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 expr_or_default set_expr_or_default @@ -8972,23 +8972,19 @@ expr: if ($$ == 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 ($$ == NULL) MYSQL_YYABORT; } - | bool_pri comp_op predicate %prec '=' + | expr comp_op predicate %prec '=' { $$= (*$2)(0)->create(thd, $1, $3); if ($$ == 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 ($$ == NULL) -- cgit v1.2.1 From 4fa44c584cf14c72fdbb15b88d406fd4e9e42c18 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 11 Dec 2020 19:35:38 +0100 Subject: MDEV-24331 mysqldump fails with "Got error: 1356" if the database contains a view with a subquery detect derived tables differently. TABLE_LIST::is_derived() only works after mysql_derived_init() --- sql/sql_parse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 6e1d36b79a4..54937116383 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -6639,7 +6639,7 @@ 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->is_derived()) + if (tables->derived) return 0; Switch_to_definer_security_ctx backup_sctx(thd, tables); -- cgit v1.2.1 From 5f4d351d7fe3dcae9f5d76d8027d54fa8392e66a Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Thu, 17 Sep 2020 19:05:08 +0530 Subject: MDEV-22422: Assertion `! is_set()' failed in Diagnostics_area::set_eof_status Analysis: The error is not returned when the statement can't be used. And so we still go on to search for keywords. Fix: Return the error state. --- sql/sql_help.cc | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sql') diff --git a/sql/sql_help.cc b/sql/sql_help.cc index c05c9a7d229..5ae9d3beb8b 100644 --- a/sql/sql_help.cc +++ b/sql/sql_help.cc @@ -741,6 +741,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); -- cgit v1.2.1 From 74223c33d1aeffac28b155c59646dc3df58e33fb Mon Sep 17 00:00:00 2001 From: Rucha Deodhar Date: Tue, 4 Aug 2020 13:21:54 +0530 Subject: MDEV-23209: Assertion `!is_set() || (m_status == DA_OK_BULK && is_bulk_op())' failed in Diagnostics_area::set_ok_status on INSERT Analysis: Error is not returned when strict mode is enabled and value is truncated because double is outside range. Fix: Return HA_ERR_AUTOINC_ERANGE if the error was reported when double is outside range. --- sql/handler.cc | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sql') diff --git a/sql/handler.cc b/sql/handler.cc index d2408767530..c38c604347a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3118,6 +3118,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): -- cgit v1.2.1 From 066212d16cc2b3995e2c53de9e2f799fdab557bd Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 15 Dec 2020 14:38:30 +0300 Subject: MDEV-21958: Query having many NOT-IN clauses running forever Basic variant of the fix: do not consider conditions in form unique_key NOT IN (c1,c2...) to be sargable. If there are only a few constants, the condition is not selective. If there are a lot constants, the overhead of processing such a huge range list is not worth it. (Backport to 10.2) --- sql/opt_range.cc | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index cbf82a20f4a..3a6579b0471 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7158,6 +7158,30 @@ SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param, if (array->count > NOT_IN_IGNORE_THRESHOLD || !value_item) DBUG_RETURN(0); + /* + If this is "unique_key NOT IN (...)", do not consider it sargable (for + any index, not just the unique one). The logic is as follows: + - if there are only a few constants, this condition is not selective + (unless the table is also very small in which case we won't gain + anything) + - If there are a lot of constants, the overhead of building and + processing enormous range list is not worth it. + */ + if (param->using_real_indexes) + { + key_map::Iterator it(field->key_start); + uint key_no; + while ((key_no= it.next_bit()) != key_map::Iterator::BITMAP_END) + { + KEY *key_info= ¶m->table->key_info[key_no]; + if (key_info->user_defined_key_parts == 1 && + (key_info->flags & HA_NOSAME)) + { + DBUG_RETURN(0); + } + } + } + /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */ uint i=0; do -- cgit v1.2.1 From a244be7044534a59199a0f11e856be37ba6f02c8 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 16 Dec 2020 09:11:11 -0800 Subject: MDEV-23406 Signal 8 in maria_create after recursive cte query This bug could cause a crash when executing queries that used mutually recursive CTEs with system variable big_tables set to 1. It happened due to several bugs in the code that handled recursive table references referred mutually recursive CTEs. For each recursive table reference a temporary table is created that contains all rows generated for the corresponding recursive CTE table on the previous step of recursion. This temporary table should be created in the same way as the temporary table created for a regular materialized derived table using the method select_union::create_result_table(). In this case when the temporary table is created it uses the select_union::TMP_TABLE_PARAM structure as the parameter for the table construction. However the code created the temporary table using just the function create_tmp_table() and passed pointers to certain fields of the TMP_TABLE_PARAM structure used for accumulation of rows of the recursive CTE table as parameters for update. This was a mistake because now different temporary tables cannot share some TMP_TABLE_PARAM fields in a general case. Besides, depending on how mutually recursive CTE tables were defined and which of them were referred in the executed query the select_union object allocated for a recursive table reference could be allocated again after the the temporary table had been created. In this case the TMP_TABLE_PARAM object associated with the temporary table created for the recursive table reference contained unassigned fields needed for execution when Aria engine is employed as the engine for temporary tables. This patch ensures that - select_union object is created only once for any recursive table reference - any temporary table created for recursive CTEs uses its own TMP_TABLE_PARAM structure The patch also fixes a problem caused by incomplete cleanup of join tables associated with recursive table references. Approved by Oleksandr Byelkin --- sql/sql_class.h | 12 +++++++--- sql/sql_cte.cc | 7 +++--- sql/sql_derived.cc | 9 +++++--- sql/sql_select.cc | 4 ---- sql/sql_union.cc | 64 ++++++++++++++++++++++++++++++++---------------------- 5 files changed, 57 insertions(+), 39 deletions(-) (limited to 'sql') diff --git a/sql/sql_class.h b/sql/sql_class.h index 35068245830..b68e3553a2d 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5152,10 +5152,15 @@ class select_union_recursive :public select_union 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 rec_tables; + /* + The list of all recursive table references to the CTE for whose + specification this select_union_recursive was created + */ + 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 @@ -5165,7 +5170,8 @@ class select_union_recursive :public select_union select_union_recursive(THD *thd_arg): select_union(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 &items); bool create_result_table(THD *thd, List *column_types, diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index a8bccf0c1dd..dd764dad7cf 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -1429,10 +1429,11 @@ void With_element::print(String *str, enum_query_type query_type) bool With_element::instantiate_tmp_tables() { - List_iterator_fast
li(rec_result->rec_tables); - TABLE *rec_table; - while ((rec_table= li++)) + List_iterator_fast 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 5379dd45bfb..33f323b86a0 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -677,7 +677,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); @@ -733,7 +733,9 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) derived->fill_me= FALSE; - if (!(derived->derived_result= new (thd->mem_root) select_union(thd))) + if ((!derived->is_with_table_recursive_reference() || + !derived->derived_result) && + !(derived->derived_result= new (thd->mem_root) select_union(thd))) DBUG_RETURN(TRUE); // out of memory lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED; @@ -752,7 +754,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_select.cc b/sql/sql_select.cc index 8b4401b1009..d5e5a79eba2 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11929,10 +11929,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_union.cc b/sql/sql_union.cc index 7716f792fdc..7baedfb259c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -211,7 +211,10 @@ select_union_recursive::create_result_table(THD *thd_arg, create_table, keep_row_order)) 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, "", true, keep_row_order))) @@ -221,20 +224,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; } @@ -272,23 +261,25 @@ void select_union_recursive::cleanup() free_tmp_table(thd, incr_table); } - List_iterator
it(rec_tables); - TABLE *tab; - while ((tab= it++)) + List_iterator 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; } } @@ -715,9 +706,29 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, goto err; if (!derived->table) { - derived->table= with_element->rec_result->rec_tables.head(); - if (derived->derived_result) - derived->derived_result->table= derived->table; + bool res= false; + + if ((!derived->is_with_table_recursive_reference() || + !derived->derived_result) && + !(derived->derived_result= new (thd->mem_root) select_union(thd))) + goto err; // out of memory + thd->create_tmp_table_for_derived= TRUE; + res= derived->derived_result->create_result_table(thd, + &types, + FALSE, + create_options, + derived->alias, + FALSE, FALSE); + thd->create_tmp_table_for_derived= FALSE; + if (res) + goto err; + derived->derived_result->set_unit(this); + derived->table= derived->derived_result->table; + if (derived->is_with_table_recursive_reference()) + { + /* Here 'derived" is the primary recursive table reference */ + derived->with->rec_result->rec_table_refs.push_back(derived); + } } with_element->mark_as_with_prepared_anchor(); is_rec_result_table_created= true; @@ -1272,11 +1283,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
li(with_element->rec_result->rec_tables); + List_iterator_fast 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"); @@ -1335,8 +1346,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, -- cgit v1.2.1 From 2cb5fb6019f4ea10106d9059307b2dbf9b9605e8 Mon Sep 17 00:00:00 2001 From: sjaakola Date: Wed, 2 Dec 2020 17:28:49 +0200 Subject: MDEV-24327 wsrep XID checkpointing order with log_slave_updates=OFF MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If log_slave_updates==OFF, wsrep applier threads used to be configured with option: thd->variables.option_bits&= ~(OPTION_BIN_LOG); (i.e. like sql_log_bin=ON). And this was regardless of log-bin configuration. With this, having configuration of: --log-bin && --log-slave-updates=OFF, local threads used binlogging, but applier threads did not. And further: local threads went through binlog group commit, while applier threads did direct commits. This resulted in situation, where applier threads entered earlier in wsrep XID checkpointing, and could sync their wsrep XID out of order. Later local thread commit would see that higher seqno was already checkpointed, and fire an assert because of this. As a fix, applier threads are now forced to enable binlogging regardless of log-slave-updates configuration. This PR comes with new mtr test: galera.MDEV-24327, which causes a scenario where applier transaction is applied and committed while earlier local transaction is parked before commit order monitor enter. A buggy mariadb versoin would fail for assertion because of wsrep XID checkpoint order violation. Reviewed-by: Jan Lindström --- sql/wsrep_thd.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'sql') diff --git a/sql/wsrep_thd.cc b/sql/wsrep_thd.cc index 2396b8663df..1c43aeaaead 100644 --- a/sql/wsrep_thd.cc +++ b/sql/wsrep_thd.cc @@ -146,11 +146,12 @@ static void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) // Disable general logging on applier threads thd->variables.option_bits |= OPTION_LOG_OFF; - // Enable binlogging if opt_log_slave_updates is set - if (opt_log_slave_updates) - thd->variables.option_bits|= OPTION_BIN_LOG; - else - thd->variables.option_bits&= ~(OPTION_BIN_LOG); + + /* enable binlogging regardless of log_slave_updates setting + this is for ensuring that both local and applier transaction go through + same commit ordering algorithm in group commit control + */ + thd->variables.option_bits|= OPTION_BIN_LOG; if (!thd->wsrep_rgi) thd->wsrep_rgi= wsrep_relay_group_init(thd, "wsrep_relay"); -- cgit v1.2.1 From 25d6f634b89c4b1ad8ae721921b5ccf595073270 Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Thu, 17 Dec 2020 10:09:16 -0800 Subject: MDEV-20751 Permission Issue With Nested CTEs Due to this bug the server reported bogus messages about lack of SELECT privileges for base tables used in the specifications of CTE tables. It happened only if such a CTE were referred to at least twice. For any non-recursive reference to CTE that is not primary the specification of the CTE is cloned. The function check_table_access() is called for such reference. The function checks privileges of the tables referenced in the specification. As no name resolution was performed for CTE references whose definitions occurred outside the specification before the call of check_table_access() that was supposed to check the access rights of the underlying tables these references were considered as references to base tables rather than references to CTEs. Yet for CTEs as well as for derived tables no privileges are needed and thus cannot be granted. The patch ensures proper name resolution of all references to CTEs before any acl checks. Approved by Oleksandr Byelkin --- sql/sql_cte.cc | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'sql') diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index dd764dad7cf..e07a525f691 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -864,8 +864,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) @@ -891,6 +889,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: -- cgit v1.2.1 From d1e9a4c15c7ea4121408c21e02a0006a19689508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Lindstr=C3=B6m?= Date: Sat, 19 Dec 2020 09:41:14 +0200 Subject: MDEV-23065 : Crash after setting wsrep_on to ON dynamically and reconnect At end_connection make sure we have wsrep before trying to free connection assigned to it. --- sql/sql_connect.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index b2900a20b28..aa7a877ed20 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -1112,7 +1112,7 @@ void end_connection(THD *thd) { NET *net= &thd->net; #ifdef WITH_WSREP - if (WSREP(thd)) + if (WSREP(thd) && wsrep) { wsrep_status_t rcode= wsrep->free_connection(wsrep, thd->thread_id); if (rcode) { -- cgit v1.2.1 From 5785de72ac85ba37eda837c691aaf9a9195ba45d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 16 Dec 2020 19:35:24 +0100 Subject: Item_func_like calls escape_item->fix_fields() twice this happens if Item_func_like is copied (get_copy()). after one copy gets fixed, the other tries to fix escape item again. --- sql/item_cmpfunc.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2a0972216f8..d0941ef58c2 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5413,7 +5413,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref) { DBUG_ASSERT(fixed == 0); if (Item_bool_func2::fix_fields(thd, ref) || - escape_item->fix_fields(thd, &escape_item) || + (!escape_item->fixed && escape_item->fix_fields(thd, &escape_item)) || fix_escape_item(thd, escape_item, &cmp_value1, escape_used_in_parsing, cmp_collation.collation, &escape)) return TRUE; -- cgit v1.2.1 From a587ded283d8abd1f20258b283911abe759f5f64 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 14 Dec 2020 18:25:08 +0100 Subject: MDEV-24346 valgrind error in main.precedence in queries like create view v1 as select 2 like 1 escape (3 in (select 0 union select 1)); select 2 union select * from v1; Item_func_like::escape was left uninitialized, because Item_in_optimizer is const_during_execution() but not actually const_item() during execution. It's not, because const subquery evaluation was disabled for derived. Practically it only needs to be disabled for multi-update that runs fix_fields() before all tables are locked. --- sql/item_cmpfunc.cc | 6 +++++- sql/sql_derived.cc | 2 -- sql/sql_update.cc | 7 +++++++ 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index d0941ef58c2..e0dad886a06 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5261,6 +5261,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) { @@ -5352,10 +5353,13 @@ bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str, 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/sql_derived.cc b/sql/sql_derived.cc index 33f323b86a0..be5905da683 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -738,14 +738,12 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) !(derived->derived_result= new (thd->mem_root) select_union(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(thd, 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; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 5e40cd242a4..7454d16d55d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1534,7 +1534,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, @@ -1557,6 +1561,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. */ -- cgit v1.2.1 From 59211ab7b9fb3c106e805bebd393731f42f95abe Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 15 Dec 2020 00:16:21 +0100 Subject: MDEV-24346 valgrind error in main.precedence Part II. It's still possible to bypass Item_func_like::escape initialization in Item_func_like::fix_fields(). This requires ESCAPE argument being a cacheable subquery that uses tables and is inside a derived table which is used in multi-update. Instead of implementing a complex or expensive fix for this particular ridiculously artificial case, let's simply disallow it. --- sql/item_cmpfunc.cc | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index e0dad886a06..bfd7f3dbd1b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -5348,7 +5348,18 @@ 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; -- cgit v1.2.1 From 6f40d5c8d6bf8742b2450410fc024caf3ac114b4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 16 Dec 2020 20:12:04 +0100 Subject: Item_func_like::walk() was ignoring escape_item in particular, it caused escape_item->is_expensive() property to be lost instead of being properly propagated up. --- sql/item_cmpfunc.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'sql') diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 22736339bf6..26469d88929 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2013,6 +2013,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, MEM_ROOT *mem_root) -- cgit v1.2.1 From df4f4bd84acce75150caff95b08c9b82d61e45db Mon Sep 17 00:00:00 2001 From: Sergei Petrunia Date: Tue, 22 Dec 2020 19:17:20 +0300 Subject: MDEV-24444: ASAN use-after-poison in Item_func_in::get_func_mm_tree with NOT IN Fix a trivial error in the fix for MDEV-21958: check the key in the right table. --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 3a6579b0471..27ea4a83714 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7173,7 +7173,7 @@ SEL_TREE *Item_func_in::get_func_mm_tree(RANGE_OPT_PARAM *param, uint key_no; while ((key_no= it.next_bit()) != 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)) { -- cgit v1.2.1 From f87737db0424a981926868b50b383ad741b40803 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 24 Dec 2020 15:47:01 +0100 Subject: Bring changes to oracle parser --- sql/sql_yacc_ora.yy | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'sql') diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 735d5ad59a2..503cb7dcf1b 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -288,7 +288,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); /* We should not introduce any further shift/reduce conflicts. */ -%expect 70 +%expect 63 /* Comments for TOKENS. @@ -1332,7 +1332,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); %type 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 @@ -9781,23 +9781,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)) -- cgit v1.2.1 From 1e9af7996e7f84934da8241b61f349b2626f7cf5 Mon Sep 17 00:00:00 2001 From: Oleksandr Byelkin Date: Thu, 24 Dec 2020 22:15:40 +0100 Subject: Fix MDEV-21958 code to be working with not 64 MAX_INDEXES --- sql/opt_range.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sql') diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 27ea4a83714..1b4f20bc39c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7171,7 +7171,7 @@ 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= &field->table->key_info[key_no]; if (key_info->user_defined_key_parts == 1 && -- cgit v1.2.1