diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-08-10 21:38:55 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-08-10 21:38:55 +0300 |
commit | 1c587481966abc7a9ad5309d0a91ca920f7a5657 (patch) | |
tree | 28b936bd807cab0ba7b82e4cc9ec963fa6de6307 /sql | |
parent | 17be2b47ba32535e69e28da9a444e528ba8ab155 (diff) | |
parent | eae968f62d285de97ed607c87bc131cd863d5d03 (diff) | |
download | mariadb-git-1c587481966abc7a9ad5309d0a91ca920f7a5657.tar.gz |
Merge 10.4 into 10.5
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_func.cc | 55 | ||||
-rw-r--r-- | sql/item_func.h | 3 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 32 | ||||
-rw-r--r-- | sql/item_subselect.h | 4 | ||||
-rw-r--r-- | sql/records.cc | 20 | ||||
-rw-r--r-- | sql/records.h | 1 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 38 | ||||
-rw-r--r-- | sql/sql_lex.cc | 11 | ||||
-rw-r--r-- | sql/sql_select.cc | 53 | ||||
-rw-r--r-- | sql/sql_select.h | 2 | ||||
-rw-r--r-- | sql/sql_show.cc | 6 | ||||
-rw-r--r-- | sql/sql_string.cc | 11 | ||||
-rw-r--r-- | sql/sql_string.h | 6 | ||||
-rw-r--r-- | sql/sql_type.cc | 29 | ||||
-rw-r--r-- | sql/sql_type.h | 7 | ||||
-rw-r--r-- | sql/sql_union.cc | 22 | ||||
-rw-r--r-- | sql/table.h | 13 | ||||
-rw-r--r-- | sql/tztime.cc | 19 |
18 files changed, 244 insertions, 88 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc index dc1de8a8e9f..8a75d2c9946 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2245,35 +2245,54 @@ bool Item_func_bit_neg::fix_length_and_dec() void Item_func_int_val::fix_length_and_dec_int_or_decimal() { + DBUG_ASSERT(args[0]->cmp_type() == DECIMAL_RESULT); + DBUG_ASSERT(args[0]->max_length <= DECIMAL_MAX_STR_LENGTH); /* - The INT branch of this code should be revised. - It creates too large data types, e.g. - CREATE OR REPLACE TABLE t2 AS SELECT FLOOR(9999999.999) AS fa; - results in a BININT(10) column, while INT(7) should probably be enough. + FLOOR() for negative numbers can increase length: floor(-9.9) -> -10 + CEILING() for positive numbers can increase length: ceil(9.9) -> 10 */ - ulonglong tmp_max_length= (ulonglong ) args[0]->max_length - - (args[0]->decimals ? args[0]->decimals + 1 : 0) + 2; - max_length= tmp_max_length > (ulonglong) UINT_MAX32 ? - (uint32) UINT_MAX32 : (uint32) tmp_max_length; - uint tmp= float_length(decimals); - set_if_smaller(max_length,tmp); - decimals= 0; + decimal_round_mode mode= round_mode(); + uint length_increase= args[0]->decimals > 0 && + (mode == CEILING || + (mode == FLOOR && !args[0]->unsigned_flag)) ? 1 : 0; + uint precision= args[0]->decimal_int_part() + length_increase; + set_if_bigger(precision, 1); /* - -2 because in most high position can't be used any digit for longlong - and one position for increasing value during operation + The BIGINT data type can store: + UNSIGNED BIGINT: 0..18446744073709551615 - up to 19 digits + SIGNED BIGINT: -9223372036854775808..9223372036854775807 - up to 18 digits + + The INT data type can store: + UNSIGNED INT: 0..4294967295 - up to 9 digits + SIGNED INT: -2147483648..2147483647 - up to 9 digits */ - if (args[0]->max_length - args[0]->decimals >= DECIMAL_LONGLONG_DIGITS - 2) + if (precision > 18) { + unsigned_flag= args[0]->unsigned_flag; fix_char_length( - my_decimal_precision_to_length_no_truncation( - args[0]->decimal_int_part(), 0, false)); + my_decimal_precision_to_length_no_truncation(precision, 0, + unsigned_flag)); set_handler(&type_handler_newdecimal); } else { - unsigned_flag= args[0]->unsigned_flag; - set_handler(type_handler_long_or_longlong()); + uint sign_length= (unsigned_flag= args[0]->unsigned_flag) ? 0 : 1; + fix_char_length(precision + sign_length); + if (precision > 9) + { + if (unsigned_flag) + set_handler(&type_handler_ulonglong); + else + set_handler(&type_handler_slonglong); + } + else + { + if (unsigned_flag) + set_handler(&type_handler_ulong); + else + set_handler(&type_handler_slong); + } } } diff --git a/sql/item_func.h b/sql/item_func.h index f39caa46ffd..5b4acdce1c6 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -1838,6 +1838,7 @@ public: Item_func_int_val(THD *thd, Item *a): Item_func_hybrid_field_type(thd, a) {} bool check_partition_func_processor(void *int_arg) { return FALSE; } bool check_vcol_func_processor(void *arg) { return FALSE; } + virtual decimal_round_mode round_mode() const= 0; void fix_length_and_dec_double(); void fix_length_and_dec_int_or_decimal(); void fix_length_and_dec_time() @@ -1866,6 +1867,7 @@ class Item_func_ceiling :public Item_func_int_val public: Item_func_ceiling(THD *thd, Item *a): Item_func_int_val(thd, a) {} const char *func_name() const { return "ceiling"; } + decimal_round_mode round_mode() const { return CEILING; } longlong int_op(); double real_op(); my_decimal *decimal_op(my_decimal *); @@ -1881,6 +1883,7 @@ class Item_func_floor :public Item_func_int_val public: Item_func_floor(THD *thd, Item *a): Item_func_int_val(thd, a) {} const char *func_name() const { return "floor"; } + decimal_round_mode round_mode() const { return FLOOR; } longlong int_op(); double real_op(); my_decimal *decimal_op(my_decimal *); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 176a6e6efc9..58f41ecfbbc 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2642,18 +2642,42 @@ String *Item_func_soundex::val_str(String *str) This should be 'internationalized' sometimes. */ -const int FORMAT_MAX_DECIMALS= 30; +/* + The maximum supported decimal scale: + 38 - starting from 10.2.1 + 30 - before 10.2.1 +*/ +const int FORMAT_MAX_DECIMALS= 38; bool Item_func_format::fix_length_and_dec() { uint32 char_length= args[0]->type_handler()->Item_decimal_notation_int_digits(args[0]); uint dec= FORMAT_MAX_DECIMALS; - if (args[1]->const_item() && !args[1]->is_expensive() && !args[1]->null_value) + /* + Format can require one more integer digit if rounding happens: + FORMAT(9.9,0) -> '10' + Set need_extra_digit_for_rounding to true by default + if args[0] has some decimals: if args[1] is not + a constant, then format can potentially reduce + the number of decimals and round to the next integer. + */ + bool need_extra_digit_for_rounding= args[0]->decimals > 0; + if (args[1]->const_item() && !args[1]->is_expensive()) { Longlong_hybrid tmp= args[1]->to_longlong_hybrid(); - dec= tmp.to_uint(FORMAT_MAX_DECIMALS); + if (!args[1]->null_value) + { + dec= tmp.to_uint(FORMAT_MAX_DECIMALS); + need_extra_digit_for_rounding= (dec < args[0]->decimals); + } } + /* + In case of a data type with zero integer digits, e.g. DECIMAL(4,4), + we'll print at least one integer digit. + */ + if (need_extra_digit_for_rounding || !char_length) + char_length++; uint32 max_sep_count= (char_length / 3) + (dec ? 1 : 0) + /*sign*/1; collation.set(default_charset()); fix_char_length(char_length + max_sep_count + dec); @@ -2709,7 +2733,7 @@ String *Item_func_format::val_str_ascii(String *str) if ((null_value=args[0]->null_value)) return 0; /* purecov: inspected */ nr= my_double_round(nr, (longlong) dec, FALSE, FALSE); - str->set_real(nr, dec, &my_charset_numeric); + str->set_fcvt(nr, dec); if (!std::isfinite(nr)) return str; str_length=str->length(); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index b5823dfb194..7e504d09565 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -149,6 +149,10 @@ public: Item_subselect(THD *thd); virtual subs_type substype() { return UNKNOWN_SUBS; } + bool is_exists_predicate() + { + return substype() == Item_subselect::EXISTS_SUBS; + } bool is_in_predicate() { return get_IN_subquery() != NULL; diff --git a/sql/records.cc b/sql/records.cc index e1766322e2f..900eacf5943 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -350,12 +350,9 @@ bool init_read_record(READ_RECORD *info,THD *thd, TABLE *table, void end_read_record(READ_RECORD *info) -{ /* free cache if used */ - if (info->cache) - { - my_free_lock(info->cache); - info->cache=0; - } +{ + /* free cache if used */ + free_cache(info); if (info->table) { if (info->table->is_created()) @@ -366,6 +363,17 @@ void end_read_record(READ_RECORD *info) } } + +void free_cache(READ_RECORD *info) +{ + if (info->cache) + { + my_free_lock(info->cache); + info->cache=0; + } +} + + static int rr_handle_error(READ_RECORD *info, int error) { if (info->thd->killed) diff --git a/sql/records.h b/sql/records.h index 04dc06b3c74..272bbd0d9b5 100644 --- a/sql/records.h +++ b/sql/records.h @@ -31,6 +31,7 @@ class SORT_INFO; struct READ_RECORD; void end_read_record(READ_RECORD *info); +void free_cache(READ_RECORD *info); /** A context for reading through a single table using a chosen access method: diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 63df3a6b956..79c27a37e6d 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -3244,25 +3244,25 @@ ER_NONEXISTING_GRANT 42000 swe "Det finns inget privilegium definierat för användare '%-.48s' på '%-.64s'" ukr "Повноважень не визначено для користувача '%-.48s' з хосту '%-.64s'" ER_TABLEACCESS_DENIED_ERROR 42000 - cze "%-.32s příkaz nepřístupný pro uživatele: '%s'@'%s' pro tabulku '%-.192s'" - dan "%-.32s-kommandoen er ikke tilladt for brugeren '%s'@'%s' for tabellen '%-.192s'" - nla "%-.32s commando geweigerd voor gebruiker: '%s'@'%s' voor tabel '%-.192s'" - eng "%-.32s command denied to user '%s'@'%s' for table '%-.192s'" - jps "コマンド %-.32s は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません", - est "%-.32s käsk ei ole lubatud kasutajale '%s'@'%s' tabelis '%-.192s'" - fre "La commande '%-.32s' est interdite à l'utilisateur: '%s'@'%s' sur la table '%-.192s'" - ger "%-.32s Befehl nicht erlaubt für Benutzer '%s'@'%s' auf Tabelle '%-.192s'" - hun "%-.32s parancs a '%s'@'%s' felhasznalo szamara nem engedelyezett a '%-.192s' tablaban" - ita "Comando %-.32s negato per l'utente: '%s'@'%s' sulla tabella '%-.192s'" - jpn "コマンド %-.32s は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません" - kor "'%-.32s' 명령은 다음 사용자에게 거부되었습니다. : '%s'@'%s' for 테이블 '%-.192s'" - por "Comando '%-.32s' negado para o usuário '%s'@'%s' na tabela '%-.192s'" - rum "Comanda %-.32s interzisa utilizatorului: '%s'@'%s' pentru tabela '%-.192s'" - rus "Команда %-.32s запрещена пользователю '%s'@'%s' для таблицы '%-.192s'" - serbian "%-.32s komanda zabranjena za korisnika '%s'@'%s' za tabelu '%-.192s'" - spa "%-.32s comando negado para usuario: '%s'@'%s' para tabla '%-.192s'" - swe "%-.32s ej tillåtet för '%s'@'%s' för tabell '%-.192s'" - ukr "%-.32s команда заборонена користувачу: '%s'@'%s' у таблиці '%-.192s'" + cze "%-.100T příkaz nepřístupný pro uživatele: '%s'@'%s' pro tabulku '%-.192s'" + dan "%-.100T-kommandoen er ikke tilladt for brugeren '%s'@'%s' for tabellen '%-.192s'" + nla "%-.100T commando geweigerd voor gebruiker: '%s'@'%s' voor tabel '%-.192s'" + eng "%-.100T command denied to user '%s'@'%s' for table '%-.192s'" + jps "コマンド %-.100T は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません", + est "%-.100T käsk ei ole lubatud kasutajale '%s'@'%s' tabelis '%-.192s'" + fre "La commande '%-.100T' est interdite à l'utilisateur: '%s'@'%s' sur la table '%-.192s'" + ger "%-.100T Befehl nicht erlaubt für Benutzer '%s'@'%s' auf Tabelle '%-.192s'" + hun "%-.100T parancs a '%s'@'%s' felhasznalo szamara nem engedelyezett a '%-.192s' tablaban" + ita "Comando %-.100T negato per l'utente: '%s'@'%s' sulla tabella '%-.192s'" + jpn "コマンド %-.100T は ユーザー '%s'@'%s' ,テーブル '%-.192s' に対して許可されていません" + kor "'%-.100T' 명령은 다음 사용자에게 거부되었습니다. : '%s'@'%s' for 테이블 '%-.192s'" + por "Comando '%-.100T' negado para o usuário '%s'@'%s' na tabela '%-.192s'" + rum "Comanda %-.100T interzisa utilizatorului: '%s'@'%s' pentru tabela '%-.192s'" + rus "Команда %-.100T запрещена пользователю '%s'@'%s' для таблицы '%-.192s'" + serbian "%-.100T komanda zabranjena za korisnika '%s'@'%s' za tabelu '%-.192s'" + spa "%-.100T comando negado para usuario: '%s'@'%s' para tabla '%-.192s'" + swe "%-.100T ej tillåtet för '%s'@'%s' för tabell '%-.192s'" + ukr "%-.100T команда заборонена користувачу: '%s'@'%s' у таблиці '%-.192s'" ER_COLUMNACCESS_DENIED_ERROR 42000 cze "%-.32s příkaz nepřístupný pro uživatele: '%s'@'%s' pro sloupec '%-.192s' v tabulce '%-.192s'" dan "%-.32s-kommandoen er ikke tilladt for brugeren '%s'@'%s' for kolonne '%-.192s' in tabellen '%-.192s'" diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index a65acc2c87e..37def6df7ed 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2812,8 +2812,17 @@ int Lex_input_stream::scan_ident_delimited(THD *thd, uchar c; DBUG_ASSERT(m_ptr == m_tok_start + 1); - while ((c= yyGet())) + for ( ; ; ) { + if (!(c= yyGet())) + { + /* + End-of-query or straight 0x00 inside a delimited identifier. + Return the quote character, to have the parser fail on syntax error. + */ + m_ptr= (char *) m_tok_start + 1; + return quote_char; + } int var_length= cs->charlen(get_ptr() - 1, get_end_of_query()); if (var_length == 1) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b0c4db47494..5dbe01c5044 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -13885,24 +13885,7 @@ void JOIN::cleanup(bool full) for (tab= first_linear_tab(this, WITH_BUSH_ROOTS, WITH_CONST_TABLES); tab; tab= next_linear_tab(this, tab, WITH_BUSH_ROOTS)) { - if (!tab->table) - continue; - DBUG_PRINT("info", ("close index: %s.%s alias: %s", - tab->table->s->db.str, - tab->table->s->table_name.str, - tab->table->alias.c_ptr())); - if (tab->table->is_created()) - { - tab->table->file->ha_index_or_rnd_end(); - if (tab->aggr) - { - int tmp= 0; - if ((tmp= tab->table->file->extra(HA_EXTRA_NO_CACHE))) - tab->table->file->print_error(tmp, MYF(0)); - } - } - delete tab->filesort_result; - tab->filesort_result= NULL; + tab->partial_cleanup(); } } } @@ -29035,6 +29018,40 @@ void JOIN::handle_implicit_grouping_with_window_funcs() } + +/* + @brief + Perform a partial cleanup for the JOIN_TAB structure + + @note + this is used to cleanup resources for the re-execution of correlated + subqueries. +*/ +void JOIN_TAB::partial_cleanup() +{ + if (!table) + return; + + if (table->is_created()) + { + table->file->ha_index_or_rnd_end(); + DBUG_PRINT("info", ("close index: %s.%s alias: %s", + table->s->db.str, + table->s->table_name.str, + table->alias.c_ptr())); + if (aggr) + { + int tmp= 0; + if ((tmp= table->file->extra(HA_EXTRA_NO_CACHE))) + table->file->print_error(tmp, MYF(0)); + } + } + delete filesort_result; + filesort_result= NULL; + free_cache(&read_record); +} + + /** @brief Look for provision of the select_handler interface by a foreign engine diff --git a/sql/sql_select.h b/sql/sql_select.h index 545db41798c..7c8908302cd 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -673,6 +673,8 @@ typedef struct st_join_table { bool use_order() const; ///< Use ordering provided by chosen index? bool sort_table(); bool remove_duplicates(); + + void partial_cleanup(); void add_keyuses_for_splitting(); SplM_plan_info *choose_best_splitting(double record_count, table_map remaining_tables); diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 6dd013d929e..0d41857aaf5 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -4620,7 +4620,7 @@ fill_schema_table_by_open(THD *thd, MEM_ROOT *mem_root, Again we don't do this for SHOW COLUMNS/KEYS because of backward compatibility. */ - if (!is_show_fields_or_keys && result && + if (!is_show_fields_or_keys && result && thd->is_error() && (thd->get_stmt_da()->sql_errno() == ER_NO_SUCH_TABLE || thd->get_stmt_da()->sql_errno() == ER_WRONG_OBJECT || thd->get_stmt_da()->sql_errno() == ER_NOT_SEQUENCE)) @@ -5932,12 +5932,12 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables, I.e. we are in SELECT FROM INFORMATION_SCHEMA.COLUMS rather than in SHOW COLUMNS */ - convert_error_to_warning(thd); + if (thd->is_error()) + convert_error_to_warning(thd); res= 0; } DBUG_RETURN(res); } - show_table= tables->table; count= 0; ptr= show_table->field; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 030075aa793..e2defba434d 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -183,6 +183,17 @@ bool Binary_string::set_hex(const char *str, uint32 len) } +bool Binary_string::set_fcvt(double num, uint decimals) +{ + // Assert that `decimals` is small enough to fit into FLOATING_POINT_BUFFER + DBUG_ASSERT(decimals < DECIMAL_NOT_SPECIFIED); + if (alloc(FLOATING_POINT_BUFFER)) + return true; + length(my_fcvt(num, decimals, Ptr, NULL)); + return false; +} + + bool String::set_real(double num,uint decimals, CHARSET_INFO *cs) { char buff[FLOATING_POINT_BUFFER]; diff --git a/sql/sql_string.h b/sql/sql_string.h index 37e9c40db61..2ef817ea0ad 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -524,6 +524,7 @@ public: bool set_hex(ulonglong num); bool set_hex(const char *str, uint32 len); + bool set_fcvt(double num, uint decimals); bool copy(); // Alloc string if not alloced bool copy(const Binary_string &s); // Allocate new string @@ -781,6 +782,11 @@ public: bool set(longlong num, CHARSET_INFO *cs) { return set_int(num, false, cs); } bool set(ulonglong num, CHARSET_INFO *cs) { return set_int((longlong)num, true, cs); } bool set_real(double num,uint decimals, CHARSET_INFO *cs); + bool set_fcvt(double num, uint decimals) + { + set_charset(&my_charset_latin1); + return Binary_string::set_fcvt(num, decimals); + } bool set_hex(ulonglong num) { diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 593062646ce..9e0f9b013c0 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -4647,6 +4647,7 @@ bool Type_handler_temporal_result:: Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const { + DBUG_ASSERT(func->field_type() != MYSQL_TYPE_DATE); bool rc= Type_handler::Item_func_min_max_fix_attributes(thd, func, items, nitems); bool is_time= func->field_type() == MYSQL_TYPE_TIME; @@ -4701,7 +4702,6 @@ bool Type_handler_temporal_result:: DATETIME DATETIME no conversion DATETIME TIMESTAMP safe conversion DATETIME DATE safe conversion - DATE DATE no conversion TIME TIME no conversion Note, a function cannot return TIMESTAMP if it has non-TIMESTAMP @@ -4718,9 +4718,6 @@ bool Type_handler_temporal_result:: -------------------- ------------- ------- TIMESTAMP TIME Not possible DATETIME TIME depends on OLD_MODE_ZERO_DATE_TIME_CAST - DATE TIMESTAMP Not possible - DATE DATETIME Not possible - DATE TIME Not possible TIME TIMESTAMP Not possible TIME DATETIME Not possible TIME DATE Not possible @@ -4743,6 +4740,30 @@ bool Type_handler_temporal_result:: } +bool Type_handler_date_common:: + Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, + Item **items, uint nitems) const +{ + func->fix_attributes_date(); + if (func->maybe_null) + return false; + /* + We cannot trust the generic maybe_null value calculated during fix_fields(). + If a conversion from non-temoral types to DATE happens, + then the result can be NULL (even if all arguments are not NULL). + */ + for (uint i= 0; i < nitems; i++) + { + if (items[i]->type_handler()->cmp_type() != TIME_RESULT) + { + func->maybe_null= true; + break; + } + } + return false; +} + + bool Type_handler_real_result:: Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, Item **items, uint nitems) const diff --git a/sql/sql_type.h b/sql/sql_type.h index 02abd55680d..a6d85b5bb47 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -6145,8 +6145,11 @@ public: const char *name, Type_handler_hybrid_field_type *, Type_all_attributes *atrr, - Item **items, uint nitems) - const override; + Item **items, uint nitems) const + override; + bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, + Item **items, uint nitems) const + override; void Item_param_set_param_func(Item_param *param, uchar **pos, ulong len) const override; }; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 3360c3c18cb..f1df76508d7 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2010, 2017, Corporation + Copyright (c) 2010, 2020, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1364,6 +1364,25 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg, found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS; is_union_select= is_unit_op() || fake_select_lex || single_tvc; + /* + If we are reading UNION output and the UNION is in the + IN/ANY/ALL/EXISTS subquery, then ORDER BY is redundant and hence should + be removed. + Example: + select ... col IN (select col2 FROM t1 union select col3 from t2 ORDER BY 1) + + (as for ORDER BY ... LIMIT, it currently not supported inside + IN/ALL/ANY subqueries) + (For non-UNION this removal of ORDER BY clause is done in + check_and_do_in_subquery_rewrites()) + */ + if (item && is_unit_op() && + (item->is_in_predicate() || item->is_exists_predicate())) + { + global_parameters()->order_list.first= NULL; + global_parameters()->order_list.elements= 0; + } + /* will only optimize once */ if (!bag_set_op_optimized && !is_recursive) { @@ -1390,6 +1409,7 @@ bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg, break; } } + /* Global option */ if (is_union_select || is_recursive) diff --git a/sql/table.h b/sql/table.h index 7ce6db5b193..7edf1e68a0b 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1388,9 +1388,16 @@ public: /* number of select if it is derived table */ uint derived_select_number; /* - 0 or JOIN_TYPE_{LEFT|RIGHT}. Currently this is only compared to 0. - If maybe_null !=0, this table is inner w.r.t. some outer join operation, - and null_row may be true. + Possible values: + - 0 by default + - JOIN_TYPE_{LEFT|RIGHT} if the table is inner w.r.t an outer join + operation + - 1 if the SELECT has mixed_implicit_grouping=1. example: + select max(col1), col2 from t1. In this case, the query produces + one row with all columns having NULL values. + + Interpetation: If maybe_null!=0, all fields of the table are considered + NULLable (and have NULL values when null_row=true) */ uint maybe_null; int current_lock; /* Type of lock on table */ diff --git a/sql/tztime.cc b/sql/tztime.cc index b1c0c79d5d7..4546f2291cd 100644 --- a/sql/tztime.cc +++ b/sql/tztime.cc @@ -2719,6 +2719,7 @@ main(int argc, char **argv) } if (opt_skip_write_binlog) + { /* If skip_write_binlog is set and wsrep is compiled in we disable sql_log_bin and wsrep_on to avoid Galera replicating below truncate table clauses. This will allow user to set different @@ -2726,15 +2727,9 @@ main(int argc, char **argv) printf("set @prep1=if((select count(*) from information_schema.global_variables where variable_name='wsrep_on' and variable_value='ON'), 'SET SESSION SQL_LOG_BIN=?, WSREP_ON=OFF;', 'do ?');\n" "prepare set_wsrep_write_binlog from @prep1;\n" "set @toggle=0; execute set_wsrep_write_binlog using @toggle;\n"); - - if (argc == 1 && !opt_leap) + } + else { - /* Argument is timezonedir */ - - root_name_end= strmake_buf(fullname, argv[0]); - - if(!opt_skip_write_binlog) - { // Alter time zone tables to InnoDB if wsrep_on is enabled // to allow changes to them to replicate with Galera printf("\\d |\n" @@ -2746,7 +2741,13 @@ main(int argc, char **argv) "ALTER TABLE time_zone_transition_type ENGINE=InnoDB;\n" "END IF|\n" "\\d ;\n"); - } + } + + if (argc == 1 && !opt_leap) + { + /* Argument is timezonedir */ + + root_name_end= strmake_buf(fullname, argv[0]); printf("TRUNCATE TABLE time_zone;\n"); printf("TRUNCATE TABLE time_zone_name;\n"); |