summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-08-10 21:38:55 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-08-10 21:38:55 +0300
commit1c587481966abc7a9ad5309d0a91ca920f7a5657 (patch)
tree28b936bd807cab0ba7b82e4cc9ec963fa6de6307 /sql
parent17be2b47ba32535e69e28da9a444e528ba8ab155 (diff)
parenteae968f62d285de97ed607c87bc131cd863d5d03 (diff)
downloadmariadb-git-1c587481966abc7a9ad5309d0a91ca920f7a5657.tar.gz
Merge 10.4 into 10.5
Diffstat (limited to 'sql')
-rw-r--r--sql/item_func.cc55
-rw-r--r--sql/item_func.h3
-rw-r--r--sql/item_strfunc.cc32
-rw-r--r--sql/item_subselect.h4
-rw-r--r--sql/records.cc20
-rw-r--r--sql/records.h1
-rw-r--r--sql/share/errmsg-utf8.txt38
-rw-r--r--sql/sql_lex.cc11
-rw-r--r--sql/sql_select.cc53
-rw-r--r--sql/sql_select.h2
-rw-r--r--sql/sql_show.cc6
-rw-r--r--sql/sql_string.cc11
-rw-r--r--sql/sql_string.h6
-rw-r--r--sql/sql_type.cc29
-rw-r--r--sql/sql_type.h7
-rw-r--r--sql/sql_union.cc22
-rw-r--r--sql/table.h13
-rw-r--r--sql/tztime.cc19
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");