diff --git a/mysql-test/main/func_str.result b/mysql-test/main/func_str.result index 0e9cebd0cb4..d354bdf1220 100644 --- a/mysql-test/main/func_str.result +++ b/mysql-test/main/func_str.result @@ -211,6 +211,11 @@ this is test select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c'); replace('aaaa','a','b') replace('aaaa','aa','b') replace('aaaa','a','bb') replace('aaaa','','b') replace('bbbb','a','c') bbbb bb bbbbbbbb aaaa bbbb +select replace('aaaa','a','bbbb'); +Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr +def replace('aaaa','a','bbbb') 253 16 16 Y 0 39 8 +replace('aaaa','a','bbbb') +bbbbbbbbbbbbbbbb select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ; replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') this is a REAL test diff --git a/mysql-test/main/func_str.test b/mysql-test/main/func_str.test index ba5b671ca4f..59ef8b0a805 100644 --- a/mysql-test/main/func_str.test +++ b/mysql-test/main/func_str.test @@ -91,6 +91,9 @@ SELECT CONCAT('"',CONCAT_WS('";"',repeat('a',60),repeat('b',60),repeat('c',60),r select insert('txs',2,1,'hi'),insert('is ',4,0,'a'),insert('txxxxt',2,4,'es'); select replace('aaaa','a','b'),replace('aaaa','aa','b'),replace('aaaa','a','bb'),replace('aaaa','','b'),replace('bbbb','a','c'); +--enable_metadata +select replace('aaaa','a','bbbb'); +--disable_metadata select replace(concat(lcase(concat('THIS',' ','IS',' ','A',' ')),ucase('false'),' ','test'),'FALSE','REAL') ; select soundex(''),soundex('he'),soundex('hello all folks'),soundex('#3556 in bugdb'); select 'mood' sounds like 'mud'; diff --git a/mysql-test/main/null.result b/mysql-test/main/null.result index fc29f68baf0..73ac958cacd 100644 --- a/mysql-test/main/null.result +++ b/mysql-test/main/null.result @@ -267,7 +267,7 @@ t1 CREATE TABLE `t1` ( `c30` varchar(317) CHARACTER SET latin2 DEFAULT NULL, `c31` varchar(192) CHARACTER SET latin2 DEFAULT NULL, `c32` char(0) CHARACTER SET latin2 DEFAULT NULL, - `c33` varchar(3) CHARACTER SET latin2 DEFAULT NULL, + `c33` varchar(6) CHARACTER SET latin2 DEFAULT NULL, `c34` varchar(3) CHARACTER SET latin2 DEFAULT NULL, `c35` varchar(3) CHARACTER SET latin2 DEFAULT NULL, `c36` varchar(3) CHARACTER SET latin2 DEFAULT NULL, diff --git a/mysql-test/main/set_operation.result b/mysql-test/main/set_operation.result index a0210331d93..24d2c7fbdd6 100644 --- a/mysql-test/main/set_operation.result +++ b/mysql-test/main/set_operation.result @@ -1155,3 +1155,37 @@ count(*) 319 drop table t1; drop table t2; +# +# MDEV-24242: set expression with empty intermediate result +# when tmp_memory_table_size is set to 0 +# +create table t1 (a int, b int) engine=MyISAM; +insert into t1 values (1,1), (2,2); +create table t2 (a int, b int) engine=MyISAM; +insert into t2 values (11,11), (12,12), (13,13); +select * from t1 +except all +select * from t1 +except +select * from t1 +union all +select * from t2; +a b +12 12 +11 11 +13 13 +set tmp_memory_table_size=0; +select * from t1 +except all +select * from t1 +except +select * from t1 +union all +select * from t2; +a b +12 12 +11 11 +13 13 +set tmp_memory_table_size=default; +drop table t1,t2; +# End of 10.4 tests diff --git a/mysql-test/main/set_operation.test b/mysql-test/main/set_operation.test index c43725c733e..c422042f371 100644 --- a/mysql-test/main/set_operation.test +++ b/mysql-test/main/set_operation.test @@ -524,3 +524,31 @@ select count(*) from drop table t1; drop table t2; + +--echo # +--echo # MDEV-24242: set expression with empty intermediate result +--echo # when tmp_memory_table_size is set to 0 +--echo # + +create table t1 (a int, b int) engine=MyISAM; +insert into t1 values (1,1), (2,2); +create table t2 (a int, b int) engine=MyISAM; +insert into t2 values (11,11), (12,12), (13,13); + +let $q= +select * from t1 +except all +select * from t1 +except +select * from t1 +union all +select * from t2; + +eval $q; +set tmp_memory_table_size=0; +eval $q; +set tmp_memory_table_size=default; + +drop table t1,t2; + +--echo # End of 10.4 tests diff --git a/mysys/crc32/crc32c.cc b/mysys/crc32/crc32c.cc index 4eaceb8c438..c0f8c518691 100644 --- a/mysys/crc32/crc32c.cc +++ b/mysys/crc32/crc32c.cc @@ -26,11 +26,6 @@ static inline uint32_t DecodeFixed32(const char *ptr) return uint4korr(ptr); } -static inline uint64_t DecodeFixed64(const char *ptr) -{ - return uint8korr(ptr); -} - #include #ifdef _MSC_VER #include @@ -343,6 +338,12 @@ static inline uint32_t LE_LOAD32(const uint8_t *p) { } #if defined(HAVE_SSE42) && (SIZEOF_SIZE_T == 8) + +static inline uint64_t DecodeFixed64(const char *ptr) +{ + return uint8korr(ptr); +} + static inline uint64_t LE_LOAD64(const uint8_t *p) { return DecodeFixed64(reinterpret_cast(p)); } @@ -364,7 +365,7 @@ static inline void Slow_CRC32(uint64_t* l, uint8_t const **p) { table0_[c >> 24]; } -static inline void Fast_CRC32(uint64_t* l, uint8_t const **p) { +__attribute__((unused)) static inline void Fast_CRC32(uint64_t* l, uint8_t const **p) { #ifndef HAVE_SSE42 Slow_CRC32(l, p); #elif (SIZEOF_SIZE_T == 8) diff --git a/sql/field.cc b/sql/field.cc index fe3aebce05d..2173670572d 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1085,7 +1085,7 @@ Field_longstr::make_packed_sort_key_part(uchar *buff, uchar* Field_longstr::pack_sort_string(uchar *to, const SORT_FIELD_ATTR *sort_field) { - StringBuffer buf; + StringBuffer buf; val_str(&buf, &buf); return to + sort_field->pack_sort_string(to, &buf, field_charset()); } diff --git a/sql/item.cc b/sql/item.cc index 52274380cd1..dc90b9fe1b3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3634,7 +3634,7 @@ String *Item_int::val_str(String *str) void Item_int::print(String *str, enum_query_type query_type) { - StringBuffer buf; + StringBuffer buf; // my_charset_bin is good enough for numbers buf.set_int(value, unsigned_flag, &my_charset_bin); str->append(buf); diff --git a/sql/item_func.h b/sql/item_func.h index 6a4a9fa5dae..e774d9c53bd 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1962,6 +1962,7 @@ class Item_func_rand :public Item_real_func bool first_eval; // TRUE if val_real() is called 1st time bool check_arguments() const { return check_argument_types_can_return_int(0, arg_count); } + void seed_random (Item * val); public: Item_func_rand(THD *thd, Item *a): Item_real_func(thd, a), rand(0), first_eval(TRUE) {} @@ -1974,12 +1975,11 @@ public: void cleanup() { first_eval= TRUE; Item_real_func::cleanup(); } bool check_vcol_func_processor(void *arg) { - return mark_unsupported_function(func_name(), "()", arg, VCOL_NON_DETERMINISTIC); + return mark_unsupported_function(func_name(), "()", arg, + VCOL_NON_DETERMINISTIC); } Item *get_copy(THD *thd) { return get_item_copy(thd, this); } -private: - void seed_random (Item * val); }; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index c2de296a109..b4f706984a5 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1286,10 +1286,10 @@ null: bool Item_func_replace::fix_length_and_dec() { ulonglong char_length= (ulonglong) args[0]->max_char_length(); - int diff=(int) (args[2]->max_char_length() - args[1]->max_char_length()); - if (diff > 0 && args[1]->max_char_length()) + int diff=(int) (args[2]->max_char_length() - 1); + if (diff > 0) { // Calculate of maxreplaces - ulonglong max_substrs= char_length / args[1]->max_char_length(); + ulonglong max_substrs= char_length; char_length+= max_substrs * (uint) diff; } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9620b0d0961..ce3bf902931 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -10279,7 +10279,7 @@ bool LEX::sp_proc_stmt_statement_finalize(THD *thd, bool no_lookahead) It is done by transformer. The extracted condition is saved in cond_pushed_into_where of this select. - cond can remain un empty after the extraction of the condition that can be + COND can remain not empty after the extraction of the conditions that can be pushed into WHERE. It is saved in remaining_cond. @note diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 861eb614592..10b71781ce4 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1113,7 +1113,7 @@ public: */ LEX *parent_lex; enum olap_type olap; - /* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */ + /* FROM clause - points to the beginning of the TABLE_LIST::next_local list */ SQL_I_List table_list; /* @@ -1129,8 +1129,8 @@ public: List pre_fix; /* above list before fix_fields */ bool is_item_list_lookup; /* - Usualy it is pointer to ftfunc_list_alloc, but in union used to create fake - select_lex for calling mysql_select under results of union + Usually it is pointer to ftfunc_list_alloc, but in union used to create + fake select_lex for calling mysql_select under results of union */ List *ftfunc_list; List ftfunc_list_alloc; diff --git a/sql/sql_select.cc b/sql/sql_select.cc index ac637931161..73d7a7d25de 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3747,14 +3747,16 @@ JOIN::create_postjoin_aggr_table(JOIN_TAB *tab, List *table_fields, tab->tmp_table_param->skip_create_table= true; TABLE* table= create_tmp_table(thd, tab->tmp_table_param, *table_fields, table_group, distinct, - save_sum_fields, select_options, table_rows_limit, + save_sum_fields, select_options, + table_rows_limit, &empty_clex_str, true, keep_row_order); if (!table) DBUG_RETURN(true); tmp_table_param.using_outer_summary_function= tab->tmp_table_param->using_outer_summary_function; tab->join= this; - DBUG_ASSERT(tab > tab->join->join_tab || !top_join_tab_count || !tables_list); + DBUG_ASSERT(tab > tab->join->join_tab || !top_join_tab_count || + !tables_list); if (tab > join_tab) (tab - 1)->next_select= sub_select_postjoin_aggr; if (!(tab->aggr= new (thd->mem_root) AGGR_OP(tab))) @@ -4270,8 +4272,9 @@ void JOIN::exec_inner() /* Enable LIMIT ROWS EXAMINED during query execution if: (1) This JOIN is the outermost query (not a subquery or derived table) - This ensures that the limit is enabled when actual execution begins, and - not if a subquery is evaluated during optimization of the outer query. + This ensures that the limit is enabled when actual execution begins, + and not if a subquery is evaluated during optimization of the outer + query. (2) This JOIN is not the result of a UNION. In this case do not apply the limit in order to produce the partial query result stored in the UNION temp table. @@ -14101,7 +14104,7 @@ static void update_depend_map_for_order(JOIN *join, ORDER *order) /** - Remove all constants and check if ORDER only contains simple + Remove all constants from ORDER and check if ORDER only contains simple expressions. We also remove all duplicate expressions, keeping only the first one. @@ -16646,13 +16649,13 @@ static uint reset_nj_counters(JOIN *join, List *join_list) @verbatim IMPLEMENTATION LIMITATIONS ON JOIN ORDER - The nested [outer] joins executioner algorithm imposes these limitations - on join order: + The nested [outer] joins executioner algorithm imposes these + limitations on join order: 1. "Outer tables first" - any "outer" table must be before any corresponding "inner" table. - 2. "No interleaving" - tables inside a nested join must form a continuous - sequence in join order (i.e. the sequence must not be interrupted by - tables that are outside of this nested join). + 2. "No interleaving" - tables inside a nested join must form a + continuous sequence in join order (i.e. the sequence must not be + interrupted by tables that are outside of this nested join). #1 is checked elsewhere, this function checks #2 provided that #1 has been already checked. @@ -16664,34 +16667,36 @@ static uint reset_nj_counters(JOIN *join, List *join_list) The join order "t1 t2 t0 t3" is invalid: - table t0 is outside of the nested join, so WHERE condition for t0 is - attached directly to t0 (without triggers, and it may be used to access - t0). Applying WHERE(t0) to (t2,t0,t3) record is invalid as we may miss - combinations of (t1, t2, t3) that satisfy condition cond1, and produce a - null-complemented (t1, t2.NULLs, t3.NULLs) row, which should not have - been produced. + table t0 is outside of the nested join, so WHERE condition + for t0 is attached directly to t0 (without triggers, and it + may be used to access t0). Applying WHERE(t0) to (t2,t0,t3) + record is invalid as we may miss combinations of (t1, t2, t3) + that satisfy condition cond1, and produce a null-complemented + (t1, t2.NULLs, t3.NULLs) row, which should not have been + produced. If table t0 is not between t2 and t3, the problem doesn't exist: - If t0 is located after (t2,t3), WHERE(t0) is applied after nested join - processing has finished. - If t0 is located before (t2,t3), predicates like WHERE_cond(t0, t2) are - wrapped into condition triggers, which takes care of correct nested - join processing. + If t0 is located after (t2,t3), WHERE(t0) is applied after nested + join processing has finished. + If t0 is located before (t2,t3), predicates like WHERE_cond(t0, t2) + are wrapped into condition triggers, which takes care of correct + nested join processing. HOW IT IS IMPLEMENTED The limitations on join order can be rephrased as follows: for valid join order one must be able to: 1. write down the used tables in the join order on one line. - 2. for each nested join, put one '(' and one ')' on the said line + 2. for each nested join, put one '(' and one ')' on the said line 3. write "LEFT JOIN" and "ON (...)" where appropriate 4. get a query equivalent to the query we're trying to execute. Calls to check_interleaving_with_nj() are equivalent to writing the above described line from left to right. - A single check_interleaving_with_nj(A,B) call is equivalent to writing - table B and appropriate brackets on condition that table A and - appropriate brackets is the last what was written. Graphically the - transition is as follows: + + A single check_interleaving_with_nj(A,B) call is equivalent + to writing table B and appropriate brackets on condition that + table A and appropriate brackets is the last what was + written. Graphically the transition is as follows: +---- current position | @@ -21872,8 +21877,8 @@ end_send(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), /* @brief - Perform a GROUP BY operation over a stream of rows ordered by their group. The - result is sent into join->result. + Perform a GROUP BY operation over a stream of rows ordered by their group. + The result is sent into join->result. @detail Also applies HAVING, etc. @@ -22153,7 +22158,9 @@ end: } -/** Like end_update, but this is done with unique constraints instead of keys. */ +/** + Like end_update, but this is done with unique constraints instead of keys. +*/ static enum_nested_loop_state end_unique_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 021720f594e..9e51bb43a74 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -880,6 +880,10 @@ bool select_unit_ext::send_eof() table->file->ha_rnd_end(); } + /* Clean up table buffers for the next set operation from pipeline */ + if (next_sl) + restore_record(table,s->default_values); + if (unlikely(error)) table->file->print_error(error, MYF(0)); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c2961ecc671..fc3d0e6fe22 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6555,6 +6555,11 @@ opt_compressed: | compressed { } ; +opt_enable: + /* empty */ {} + | ENABLE_SYM { } + ; + compressed: COMPRESSED_SYM opt_compression_method { @@ -6581,7 +6586,7 @@ compressed_deprecated_column_attribute: ; asrow_attribute: - not NULL_SYM + not NULL_SYM opt_enable { Lex->last_field->flags|= NOT_NULL_FLAG; } diff --git a/tpool/tpool_generic.cc b/tpool/tpool_generic.cc index 98237063ec2..e508c84f442 100644 --- a/tpool/tpool_generic.cc +++ b/tpool/tpool_generic.cc @@ -305,8 +305,10 @@ public: std::unique_lock lk(m_mtx); if (m_on) { + DBUG_PUSH_EMPTY; thr_timer_end(this); thr_timer_settime(this, 1000ULL * m_period); + DBUG_POP_EMPTY; } } }