[Commits] 212b8407074: MDEV-16517: Server crash in Item_func_in::val_int() when
by Galina 19 Jun '18
by Galina 19 Jun '18
19 Jun '18
revision-id: 212b8407074564c349e6bc61c7ca4554ad60ed79 (mariadb-10.2.15-67-g212b8407074)
parent(s): 10d09a57f88cafaabcb6ba8475c1951fe329756e
author: Galina Shalygina
committer: Galina Shalygina
timestamp: 2018-06-19 19:19:40 +0200
message:
MDEV-16517: Server crash in Item_func_in::val_int() when
IN predicate defined with non-constant values is pushed down
The problem appears because of wrong changes made in MDEV-16090 in the
Item_func_in::build_clone() method.
For the clone of the IN predicate it copied 'cmp_fields' array values
that become dirty after Item::cleanup_excluding_const_fields_processor
work in pushdown. That causes crash.
There is no need to copy 'cmp_fields' field, the array values should be
NULL so in fix_fields() for the cloned IN predicate they can be set correctly.
---
mysql-test/r/derived_cond_pushdown.result | 34 +++++++++++++++++++++++++++++++
mysql-test/t/derived_cond_pushdown.test | 33 ++++++++++++++++++++++++++++++
sql/item_cmpfunc.cc | 2 +-
3 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/mysql-test/r/derived_cond_pushdown.result b/mysql-test/r/derived_cond_pushdown.result
index 83e70dd634c..2fb0d471c71 100644
--- a/mysql-test/r/derived_cond_pushdown.result
+++ b/mysql-test/r/derived_cond_pushdown.result
@@ -9669,3 +9669,37 @@ EXPLAIN
}
}
DROP TABLE t1;
+#
+# MDEV-16517: pushdown condition with the IN predicate defined
+# with non-constant values
+#
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2),(1,3);
+SELECT * FROM
+(
+SELECT t1.a
+FROM t1
+WHERE 1 IN (0,t1.a)
+GROUP BY t1.a
+) AS dt1
+JOIN
+(
+SELECT t1.a
+FROM t1
+WHERE 1 IN (0,t1.a)
+) AS dt2
+ON dt1.a = dt2.a;
+a a
+1 1
+1 1
+SELECT * FROM
+(
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+) AS dt, t1
+WHERE dt.a=t1.a AND dt.a IN (1,t1.a);
+a MAX(t1.b) a b
+1 3 1 2
+1 3 1 3
+DROP TABLE t1;
diff --git a/mysql-test/t/derived_cond_pushdown.test b/mysql-test/t/derived_cond_pushdown.test
index 718140d3a77..275eb9cca6e 100644
--- a/mysql-test/t/derived_cond_pushdown.test
+++ b/mysql-test/t/derived_cond_pushdown.test
@@ -1801,3 +1801,36 @@ EVAL $query;
EVAL EXPLAIN FORMAT=JSON $query;
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-16517: pushdown condition with the IN predicate defined
+--echo # with non-constant values
+--echo #
+
+CREATE TABLE t1 (a INT, b INT);
+INSERT INTO t1 VALUES (1,2),(1,3);
+
+SELECT * FROM
+(
+ SELECT t1.a
+ FROM t1
+ WHERE 1 IN (0,t1.a)
+ GROUP BY t1.a
+) AS dt1
+JOIN
+(
+ SELECT t1.a
+ FROM t1
+ WHERE 1 IN (0,t1.a)
+) AS dt2
+ON dt1.a = dt2.a;
+
+SELECT * FROM
+(
+ SELECT t1.a,MAX(t1.b)
+ FROM t1
+ GROUP BY t1.a
+) AS dt, t1
+WHERE dt.a=t1.a AND dt.a IN (1,t1.a);
+
+DROP TABLE t1;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index b86c0079bce..f176a0a8193 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -4438,7 +4438,7 @@ Item *Item_func_in::build_clone(THD *thd, MEM_ROOT *mem_root)
{
if (array && clone->create_array(thd))
return NULL;
- memcpy(&clone->cmp_items, &cmp_items, sizeof(cmp_items));
+ bzero(&clone->cmp_items, sizeof(cmp_items));
}
return clone;
}
1
0
revision-id: 07ed346ebdad6c661682d46ec21f2f09d439573d (mariadb-10.2.15-70-g07ed346ebda)
parent(s): 943e0b77d567141963b17d1c83b4e5692c46ebc4
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-06-19 18:27:26 +0200
message:
Optimize charset tracking a bit.
---
sql/set_var.cc | 24 ++++++------------------
sql/set_var.h | 4 +++-
sql/sys_vars.cc | 6 ++++++
3 files changed, 15 insertions(+), 19 deletions(-)
diff --git a/sql/set_var.cc b/sql/set_var.cc
index e96e636e3d3..d27751b8ab7 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1004,24 +1004,12 @@ int set_var_collation_client::update(THD *thd)
#ifndef EMBEDDED_LIBRARY
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
{
- sys_var *svar;
- mysql_mutex_lock(&LOCK_plugin);
- if ((svar= find_sys_var_ex(thd, "character_set_client",
- sizeof("character_set_client") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- if ((svar= find_sys_var_ex(thd, "character_set_results",
- sizeof("character_set_results") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- if ((svar= find_sys_var_ex(thd, "character_set_connection",
- sizeof("character_set_connection") - 1,
- false, true)))
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)svar);
- mysql_mutex_unlock(&LOCK_plugin);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_client_ptr);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_results_ptr);
+ thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_connection_ptr);
}
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
#endif //EMBEDDED_LIBRARY
diff --git a/sql/set_var.h b/sql/set_var.h
index 24e25af2245..1023bd18078 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -424,7 +424,9 @@ sql_mode_t expand_sql_mode(sql_mode_t sql_mode);
bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode, LEX_STRING *ls);
int default_regex_flags_pcre(const THD *thd);
-extern sys_var *Sys_autocommit_ptr, *Sys_last_gtid_ptr;
+extern sys_var *Sys_autocommit_ptr, *Sys_last_gtid_ptr,
+ *Sys_character_set_client_ptr, *Sys_character_set_connection_ptr,
+ *Sys_character_set_results_ptr;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 1fd75cb5040..2af4a0922be 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -673,6 +673,8 @@ static Sys_var_struct Sys_character_set_client(
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_cs_client),
ON_UPDATE(fix_thd_charset));
+// for check changing
+export sys_var *Sys_character_set_client_ptr= &Sys_character_set_client;
static Sys_var_struct Sys_character_set_connection(
"character_set_connection", "The character set used for "
@@ -682,6 +684,8 @@ static Sys_var_struct Sys_character_set_connection(
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, IN_BINLOG, ON_CHECK(check_charset_not_null),
ON_UPDATE(fix_thd_charset));
+// for check changing
+export sys_var *Sys_character_set_connection_ptr= &Sys_character_set_connection;
static Sys_var_struct Sys_character_set_results(
"character_set_results", "The character set used for returning "
@@ -689,6 +693,8 @@ static Sys_var_struct Sys_character_set_results(
SESSION_VAR(character_set_results), NO_CMD_LINE,
offsetof(CHARSET_INFO, csname), DEFAULT(&default_charset_info),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_charset));
+// for check changing
+export sys_var *Sys_character_set_results_ptr= &Sys_character_set_results;
static Sys_var_struct Sys_character_set_filesystem(
"character_set_filesystem", "The filesystem character set",
1
0
[Commits] 943e0b77d56: MDEV-15477: SESSION_SYSVARS_TRACKER does not track last_gtid
by Oleksandr Byelkin 19 Jun '18
by Oleksandr Byelkin 19 Jun '18
19 Jun '18
revision-id: 943e0b77d567141963b17d1c83b4e5692c46ebc4 (mariadb-10.2.15-69-g943e0b77d56)
parent(s): a7068c05c3d6c4b268f63ae6add9a7d8168fdb8b
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-06-19 18:25:10 +0200
message:
MDEV-15477: SESSION_SYSVARS_TRACKER does not track last_gtid
register changes of last_gtid
---
mysql-test/r/session_tracker_last_gtid.result | 33 +++++++++++++++++++++++++++
mysql-test/t/session_tracker_last_gtid.test | 18 +++++++++++++++
sql/log.cc | 5 +++-
sql/set_var.h | 2 +-
sql/sql_class.cc | 13 ++++++++++-
sql/sql_class.h | 8 ++++++-
sql/sys_vars.cc | 7 ++++--
7 files changed, 80 insertions(+), 6 deletions(-)
diff --git a/mysql-test/r/session_tracker_last_gtid.result b/mysql-test/r/session_tracker_last_gtid.result
new file mode 100644
index 00000000000..6ed850d4ff5
--- /dev/null
+++ b/mysql-test/r/session_tracker_last_gtid.result
@@ -0,0 +1,33 @@
+#
+# MDEV-15477: SESSION_SYSVARS_TRACKER does not track last_gtid
+#
+SET @@session.session_track_system_variables='last_gtid';
+create table t1 (a int) engine=innodb;
+-- Tracker : SESSION_TRACK_SYSTEM_VARIABLES
+-- last_gtid
+-- 0-1-1
+
+select @@last_gtid;
+@@last_gtid
+0-1-1
+-- Tracker : SESSION_TRACK_SYSTEM_VARIABLES
+-- last_gtid
+-- 0-1-1
+
+insert into t1 values (1);
+-- Tracker : SESSION_TRACK_SYSTEM_VARIABLES
+-- last_gtid
+-- 0-1-2
+
+select @@last_gtid;
+@@last_gtid
+0-1-2
+-- Tracker : SESSION_TRACK_SYSTEM_VARIABLES
+-- last_gtid
+-- 0-1-2
+
+drop table t1;
+-- Tracker : SESSION_TRACK_SYSTEM_VARIABLES
+-- last_gtid
+-- 0-1-3
+
diff --git a/mysql-test/t/session_tracker_last_gtid.test b/mysql-test/t/session_tracker_last_gtid.test
new file mode 100644
index 00000000000..ccd2c25b31f
--- /dev/null
+++ b/mysql-test/t/session_tracker_last_gtid.test
@@ -0,0 +1,18 @@
+
+--source include/have_innodb.inc
+--source include/have_binlog_format_statement.inc
+
+--enable_session_track_info
+
+--echo #
+--echo # MDEV-15477: SESSION_SYSVARS_TRACKER does not track last_gtid
+--echo #
+
+SET @@session.session_track_system_variables='last_gtid';
+create table t1 (a int) engine=innodb;
+select @@last_gtid;
+insert into t1 values (1);
+select @@last_gtid;
+drop table t1;
+
+--disable_session_track_info
diff --git a/sql/log.cc b/sql/log.cc
index 973aecb16e8..d83f2e1930c 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -46,6 +46,8 @@
#include <stdarg.h>
#include <m_ctype.h> // For test_if_number
+#include <set_var.h> // for Sys_last_gtid_ptr
+
#ifdef _WIN32
#include "message.h"
#endif
@@ -5945,7 +5947,8 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
}
if (err)
DBUG_RETURN(true);
- thd->last_commit_gtid= gtid;
+
+ thd->set_last_commit_gtid(gtid);
Gtid_log_event gtid_event(thd, seq_no, domain_id, standalone,
LOG_EVENT_SUPPRESS_USE_F, is_transactional,
diff --git a/sql/set_var.h b/sql/set_var.h
index 7a48e319466..24e25af2245 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -424,7 +424,7 @@ sql_mode_t expand_sql_mode(sql_mode_t sql_mode);
bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode, LEX_STRING *ls);
int default_regex_flags_pcre(const THD *thd);
-extern sys_var *Sys_autocommit_ptr;
+extern sys_var *Sys_autocommit_ptr, *Sys_last_gtid_ptr;
CHARSET_INFO *get_old_charset_by_name(const char *old_name);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 7e15eff4dd4..d2959b0dac5 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1287,7 +1287,7 @@ void THD::init(void)
bzero((char *) &org_status_var, sizeof(org_status_var));
status_in_global= 0;
start_bytes_received= 0;
- last_commit_gtid.seq_no= 0;
+ m_last_commit_gtid.seq_no= 0;
last_stmt= NULL;
/* Reset status of last insert id */
arg_of_last_insert_id_function= FALSE;
@@ -7069,6 +7069,17 @@ THD::signal_wakeup_ready()
mysql_cond_signal(&COND_wakeup_ready);
}
+void THD::set_last_commit_gtid(rpl_gtid >id)
+{
+ bool changed_gtid= (m_last_commit_gtid.seq_no != gtid.seq_no);
+ m_last_commit_gtid= gtid;
+ if (changed_gtid &&
+ session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
+ {
+ session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(this, (LEX_CSTRING*)Sys_last_gtid_ptr);
+ }
+}
void
wait_for_commit::reinit()
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a12015ecfe4..024ec3b4017 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4254,7 +4254,13 @@ class THD :public Statement,
The GTID assigned to the last commit. If no GTID was assigned to any commit
so far, this is indicated by last_commit_gtid.seq_no == 0.
*/
- rpl_gtid last_commit_gtid;
+private:
+ rpl_gtid m_last_commit_gtid;
+
+public:
+ rpl_gtid get_last_commit_gtid() { return m_last_commit_gtid; }
+ void set_last_commit_gtid(rpl_gtid >id);
+
LF_PINS *tdc_hash_pins;
LF_PINS *xid_hash_pins;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index c3d786af945..1fd75cb5040 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1828,6 +1828,8 @@ static Sys_var_last_gtid Sys_last_gtid(
"or the empty string if none.",
READ_ONLY sys_var::ONLY_SESSION, NO_CMD_LINE);
+export sys_var *Sys_last_gtid_ptr= &Sys_last_gtid; // for check changing
+
uchar *
Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_STRING *base)
@@ -1838,8 +1840,9 @@ Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_STRING *base)
bool first= true;
str.length(0);
- if ((thd->last_commit_gtid.seq_no > 0 &&
- rpl_slave_state_tostring_helper(&str, &thd->last_commit_gtid, &first)) ||
+ rpl_gtid gtid= thd->get_last_commit_gtid();
+ if ((gtid.seq_no > 0 &&
+ rpl_slave_state_tostring_helper(&str, >id, &first)) ||
!(p= thd->strmake(str.ptr(), str.length())))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
1
0
revision-id: 860366b459390b76002324f20ce4b81c1577cf47 (mariadb-10.2.15-71-g860366b4593)
parent(s): 01e25bfbbcdcdb2f6fe16b800ec0f740c67fc4d3
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-06-19 18:27:15 +0200
message:
postreview fix
---
sql/set_var.cc | 2 --
1 file changed, 2 deletions(-)
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 62f815d961a..d27751b8ab7 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -1004,14 +1004,12 @@ int set_var_collation_client::update(THD *thd)
#ifndef EMBEDDED_LIBRARY
if (thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
{
- mysql_mutex_lock(&LOCK_plugin);
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_client_ptr);
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_results_ptr);
thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
mark_as_changed(thd, (LEX_CSTRING*)Sys_character_set_connection_ptr);
- mysql_mutex_unlock(&LOCK_plugin);
}
thd->session_tracker.mark_as_changed(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
#endif //EMBEDDED_LIBRARY
1
0
revision-id: 1ce8a497c5c0c1d30a6602c8650bc604d8074baa (mariadb-10.2.15-71-g1ce8a497c5c)
parent(s): 36f7324255f03bd812444016acb418d6a0abec74
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-06-19 18:24:22 +0200
message:
postreview change
---
sql/log.cc | 12 ++----------
sql/sql_class.cc | 13 ++++++++++++-
sql/sql_class.h | 8 +++++++-
sql/sys_vars.cc | 5 +++--
4 files changed, 24 insertions(+), 14 deletions(-)
diff --git a/sql/log.cc b/sql/log.cc
index d0e1c8ca523..d83f2e1930c 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -5947,16 +5947,8 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
}
if (err)
DBUG_RETURN(true);
- bool changed_gtid= (thd->last_commit_gtid.seq_no != gtid.seq_no);
- thd->last_commit_gtid= gtid;
- if (changed_gtid &&
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
- {
- mysql_mutex_lock(&LOCK_plugin);
- thd->session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
- mark_as_changed(thd, (LEX_CSTRING*)Sys_last_gtid_ptr);
- mysql_mutex_unlock(&LOCK_plugin);
- }
+
+ thd->set_last_commit_gtid(gtid);
Gtid_log_event gtid_event(thd, seq_no, domain_id, standalone,
LOG_EVENT_SUPPRESS_USE_F, is_transactional,
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 7e15eff4dd4..d2959b0dac5 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1287,7 +1287,7 @@ void THD::init(void)
bzero((char *) &org_status_var, sizeof(org_status_var));
status_in_global= 0;
start_bytes_received= 0;
- last_commit_gtid.seq_no= 0;
+ m_last_commit_gtid.seq_no= 0;
last_stmt= NULL;
/* Reset status of last insert id */
arg_of_last_insert_id_function= FALSE;
@@ -7069,6 +7069,17 @@ THD::signal_wakeup_ready()
mysql_cond_signal(&COND_wakeup_ready);
}
+void THD::set_last_commit_gtid(rpl_gtid >id)
+{
+ bool changed_gtid= (m_last_commit_gtid.seq_no != gtid.seq_no);
+ m_last_commit_gtid= gtid;
+ if (changed_gtid &&
+ session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->is_enabled())
+ {
+ session_tracker.get_tracker(SESSION_SYSVARS_TRACKER)->
+ mark_as_changed(this, (LEX_CSTRING*)Sys_last_gtid_ptr);
+ }
+}
void
wait_for_commit::reinit()
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a12015ecfe4..024ec3b4017 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4254,7 +4254,13 @@ class THD :public Statement,
The GTID assigned to the last commit. If no GTID was assigned to any commit
so far, this is indicated by last_commit_gtid.seq_no == 0.
*/
- rpl_gtid last_commit_gtid;
+private:
+ rpl_gtid m_last_commit_gtid;
+
+public:
+ rpl_gtid get_last_commit_gtid() { return m_last_commit_gtid; }
+ void set_last_commit_gtid(rpl_gtid >id);
+
LF_PINS *tdc_hash_pins;
LF_PINS *xid_hash_pins;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index f2665b01dd6..2af4a0922be 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -1846,8 +1846,9 @@ Sys_var_last_gtid::session_value_ptr(THD *thd, const LEX_STRING *base)
bool first= true;
str.length(0);
- if ((thd->last_commit_gtid.seq_no > 0 &&
- rpl_slave_state_tostring_helper(&str, &thd->last_commit_gtid, &first)) ||
+ rpl_gtid gtid= thd->get_last_commit_gtid();
+ if ((gtid.seq_no > 0 &&
+ rpl_slave_state_tostring_helper(&str, >id, &first)) ||
!(p= thd->strmake(str.ptr(), str.length())))
{
my_error(ER_OUT_OF_RESOURCES, MYF(0));
1
0
[Commits] 37b432c1d59: MDEV-15242 Poor RBR update performance with partitioned tables
by andrei.elkinīŧ pp.inet.fi 19 Jun '18
by andrei.elkinīŧ pp.inet.fi 19 Jun '18
19 Jun '18
revision-id: 37b432c1d59e66b742f97a280cae7784d85e62ec (mariadb-10.0.35-41-g37b432c1d59)
parent(s): d2e1ed8b936a78ceeec0e64231997d7ed18a4daf
author: Andrei Elkin
committer: Andrei Elkin
timestamp: 2018-06-19 18:14:47 +0300
message:
MDEV-15242 Poor RBR update performance with partitioned tables
Observed and described
partitioned engine execution time difference
between master and slave was caused by excessive invocation
of base_engine::rnd_init which was done also for partitions
uninvolved into Rows-event operation.
The bug's slave slowdown therefore scales with the number of partitions.
Fixed with applying an upstream patch.
References:
----------
https://bugs.mysql.com/bug.php?id=73648
Bug#25687813 REPLICATION REGRESSION WITH RBR AND PARTITIONED TABLES
---
sql/ha_partition.cc | 3 ++-
sql/handler.h | 10 +++++++++-
sql/log_event.cc | 4 ----
3 files changed, 11 insertions(+), 6 deletions(-)
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 6a6627f9276..0488ebfb60f 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5090,7 +5090,8 @@ int ha_partition::rnd_pos_by_record(uchar *record)
if (unlikely(get_part_for_delete(record, m_rec0, m_part_info, &m_last_part)))
DBUG_RETURN(1);
- DBUG_RETURN(handler::rnd_pos_by_record(record));
+ int err= m_file[m_last_part]->rnd_pos_by_record(record);
+ DBUG_RETURN(err);
}
diff --git a/sql/handler.h b/sql/handler.h
index 74d50536ec4..52396b84c0d 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -3042,9 +3042,17 @@ class handler :public Sql_alloc
*/
virtual int rnd_pos_by_record(uchar *record)
{
+ int error;
DBUG_ASSERT(table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION);
+
+ error = ha_rnd_init(false);
+ if (error != 0)
+ return error;
+
position(record);
- return rnd_pos(record, ref);
+ error = ha_rnd_pos(record, ref);
+ ha_rnd_end();
+ return error;
}
virtual int read_first_row(uchar *buf, uint primary_key);
public:
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 7989db9c687..3638269cbf5 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -12135,10 +12135,6 @@ int Rows_log_event::find_row(rpl_group_info *rgi)
int error;
DBUG_PRINT("info",("locating record using primary key (position)"));
- if (!table->file->inited &&
- (error= table->file->ha_rnd_init_with_error(0)))
- DBUG_RETURN(error);
-
error= table->file->ha_rnd_pos_by_record(table->record[0]);
if (error)
{
1
0
[Commits] 083279f7838: Merge commit '6b8802e8dd5467556a024d807a1df23940b00895' into bb-10.3-fix_len_dec
by Oleksandr Byelkin 19 Jun '18
by Oleksandr Byelkin 19 Jun '18
19 Jun '18
revision-id: 083279f7838d45c475344d20585ead72a147a21d (mariadb-10.3.7-52-g083279f7838)
parent(s): 0121d5a790983c08dabedc66e70f862e47f7c8c7 6b8802e8dd5467556a024d807a1df23940b00895
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-06-19 14:51:50 +0200
message:
Merge commit '6b8802e8dd5467556a024d807a1df23940b00895' into bb-10.3-fix_len_dec
mysql-test/main/alter_table.result | 11 +++
mysql-test/main/alter_table.test | 16 ++++
sql/item.h | 2 +-
sql/item_cmpfunc.cc | 98 +++++++++++--------
sql/item_cmpfunc.h | 82 +++++++++-------
sql/item_func.cc | 143 ++++++++++++++-------------
sql/item_func.h | 159 +++++++++++++++++-------------
sql/item_geofunc.cc | 9 +-
sql/item_geofunc.h | 77 ++++++++-------
sql/item_inetfunc.h | 12 ++-
sql/item_jsonfunc.cc | 57 +++++++----
sql/item_jsonfunc.h | 40 ++++----
sql/item_strfunc.cc | 164 +++++++++++++++++++------------
sql/item_strfunc.h | 192 ++++++++++++++++++++++---------------
sql/item_subselect.cc | 71 +++++++++-----
sql/item_subselect.h | 22 ++---
sql/item_sum.cc | 50 +++++-----
sql/item_sum.h | 34 ++++---
sql/item_timefunc.cc | 38 +++++---
sql/item_timefunc.h | 146 ++++++++++++++++------------
sql/item_vers.h | 8 +-
sql/item_windowfunc.cc | 6 +-
sql/item_windowfunc.h | 15 ++-
sql/item_xmlfunc.cc | 13 +--
sql/item_xmlfunc.h | 2 +-
sql/sql_select.cc | 3 +-
sql/sql_table.cc | 14 ++-
27 files changed, 892 insertions(+), 592 deletions(-)
diff --cc mysql-test/main/alter_table.result
index cb5553a086c,00000000000..ac6f9aba17b
mode 100644,000000..100644
--- a/mysql-test/main/alter_table.result
+++ b/mysql-test/main/alter_table.result
@@@ -1,2384 -1,0 +1,2395 @@@
+drop table if exists t1,t2;
+drop database if exists mysqltest;
+create table t1 (
+col1 int not null auto_increment primary key,
+col2 varchar(30) not null,
+col3 varchar (20) not null,
+col4 varchar(4) not null,
+col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null,
+col6 int not null, to_be_deleted int);
+insert into t1 values (2,4,3,5,"PENDING",1,7);
+alter table t1
+add column col4_5 varchar(20) not null after col4,
+add column col7 varchar(30) not null after col5,
+add column col8 datetime not null, drop column to_be_deleted,
+change column col2 fourth varchar(30) not null after col3,
+modify column col6 int not null first;
+select * from t1;
+col6 col1 col3 fourth col4 col4_5 col5 col7 col8
+1 2 3 4 5 PENDING 0000-00-00 00:00:00
+drop table t1;
+create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL);
+insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12);
+alter table t1 add column new_col int, order by payoutid,bandid;
+select * from t1;
+bandID payoutID new_col
+6 1 NULL
+3 4 NULL
+1 6 NULL
+2 6 NULL
+4 9 NULL
+5 10 NULL
+7 12 NULL
+8 12 NULL
+alter table t1 order by bandid,payoutid;
+select * from t1;
+bandID payoutID new_col
+1 6 NULL
+2 6 NULL
+3 4 NULL
+4 9 NULL
+5 10 NULL
+6 1 NULL
+7 12 NULL
+8 12 NULL
+drop table t1;
+CREATE TABLE t1 (
+GROUP_ID int(10) unsigned DEFAULT '0' NOT NULL,
+LANG_ID smallint(5) unsigned DEFAULT '0' NOT NULL,
+NAME varchar(80) DEFAULT '' NOT NULL,
+PRIMARY KEY (GROUP_ID,LANG_ID),
+KEY NAME (NAME));
+ALTER TABLE t1 CHANGE NAME NAME CHAR(80) not null;
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+GROUP_ID int(10) unsigned NULL NO PRI 0 #
+LANG_ID smallint(5) unsigned NULL NO PRI 0 #
+NAME char(80) latin1_swedish_ci NO MUL NULL #
+DROP TABLE t1;
+create table t1 (n int);
+insert into t1 values(9),(3),(12),(10);
+alter table t1 order by n;
+select * from t1;
+n
+3
+9
+10
+12
+drop table t1;
+CREATE TABLE t1 (
+id int(11) unsigned NOT NULL default '0',
+category_id tinyint(4) unsigned NOT NULL default '0',
+type_id tinyint(4) unsigned NOT NULL default '0',
+body text NOT NULL,
+user_id int(11) unsigned NOT NULL default '0',
+status enum('new','old') NOT NULL default 'new',
+PRIMARY KEY (id)
+) ENGINE=MyISAM;
+ALTER TABLE t1 ORDER BY t1.id, t1.status, t1.type_id, t1.user_id, t1.body;
+DROP TABLE t1;
+CREATE TABLE t1 (AnamneseId int(10) unsigned NOT NULL auto_increment,B BLOB,PRIMARY KEY (AnamneseId)) engine=myisam;
+insert into t1 values (null,"hello");
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1 ADD Column new_col int not null;
+UNLOCK TABLES;
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+DROP TABLE t1;
+create table t1 (i int unsigned not null auto_increment primary key);
+insert into t1 values (null),(null),(null),(null);
+alter table t1 drop i,add i int unsigned not null auto_increment, drop primary key, add primary key (i);
+select * from t1;
+i
+1
+2
+3
+4
+drop table t1;
+create table t1 (name char(15));
+insert into t1 (name) values ("current");
+create database mysqltest;
+create table mysqltest.t1 (name char(15));
+insert into mysqltest.t1 (name) values ("mysqltest");
+select * from t1;
+name
+current
+select * from mysqltest.t1;
+name
+mysqltest
+alter table t1 rename mysqltest.t1;
+ERROR 42S01: Table 't1' already exists
+select * from t1;
+name
+current
+select * from mysqltest.t1;
+name
+mysqltest
+drop table t1;
+drop database mysqltest;
+create table t1 (n1 int not null, n2 int, n3 int, n4 float,
+unique(n1),
+key (n1, n2, n3, n4),
+key (n2, n3, n4, n1),
+key (n3, n4, n1, n2),
+key (n4, n1, n2, n3) );
+alter table t1 disable keys;
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 n1 1 n1 A 0 NULL NULL BTREE
+t1 1 n1_2 1 n1 A NULL NULL NULL BTREE disabled
+t1 1 n1_2 2 n2 A NULL NULL NULL YES BTREE disabled
+t1 1 n1_2 3 n3 A NULL NULL NULL YES BTREE disabled
+t1 1 n1_2 4 n4 A NULL NULL NULL YES BTREE disabled
+t1 1 n2 1 n2 A NULL NULL NULL YES BTREE disabled
+t1 1 n2 2 n3 A NULL NULL NULL YES BTREE disabled
+t1 1 n2 3 n4 A NULL NULL NULL YES BTREE disabled
+t1 1 n2 4 n1 A NULL NULL NULL BTREE disabled
+t1 1 n3 1 n3 A NULL NULL NULL YES BTREE disabled
+t1 1 n3 2 n4 A NULL NULL NULL YES BTREE disabled
+t1 1 n3 3 n1 A NULL NULL NULL BTREE disabled
+t1 1 n3 4 n2 A NULL NULL NULL YES BTREE disabled
+t1 1 n4 1 n4 A NULL NULL NULL YES BTREE disabled
+t1 1 n4 2 n1 A NULL NULL NULL BTREE disabled
+t1 1 n4 3 n2 A NULL NULL NULL YES BTREE disabled
+t1 1 n4 4 n3 A NULL NULL NULL YES BTREE disabled
+alter table t1 enable keys;
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 n1 1 n1 A 10 NULL NULL BTREE
+t1 1 n1_2 1 n1 A 10 NULL NULL BTREE
+t1 1 n1_2 2 n2 A 10 NULL NULL YES BTREE
+t1 1 n1_2 3 n3 A 10 NULL NULL YES BTREE
+t1 1 n1_2 4 n4 A 10 NULL NULL YES BTREE
+t1 1 n2 1 n2 A 10 NULL NULL YES BTREE
+t1 1 n2 2 n3 A 10 NULL NULL YES BTREE
+t1 1 n2 3 n4 A 10 NULL NULL YES BTREE
+t1 1 n2 4 n1 A 10 NULL NULL BTREE
+t1 1 n3 1 n3 A 10 NULL NULL YES BTREE
+t1 1 n3 2 n4 A 10 NULL NULL YES BTREE
+t1 1 n3 3 n1 A 10 NULL NULL BTREE
+t1 1 n3 4 n2 A 10 NULL NULL YES BTREE
+t1 1 n4 1 n4 A 10 NULL NULL YES BTREE
+t1 1 n4 2 n1 A 10 NULL NULL BTREE
+t1 1 n4 3 n2 A 10 NULL NULL YES BTREE
+t1 1 n4 4 n3 A 10 NULL NULL YES BTREE
+drop table t1;
+create table t1 (i int unsigned not null auto_increment primary key);
+alter table t1 rename t2;
+alter table t2 rename t1, add c char(10) comment "no comment";
+show columns from t1;
+Field Type Null Key Default Extra
+i int(10) unsigned NO PRI NULL auto_increment
+c char(10) YES NULL
+drop table t1;
+create table t1 (a int, b int);
+alter table t1 add unique (a,b), add key (b);
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A 3 NULL NULL YES BTREE
+t1 0 a 2 b A 300 NULL NULL YES BTREE
+t1 1 b 1 b A 100 NULL NULL YES BTREE
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Table is already up to date
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A 3 NULL NULL YES BTREE
+t1 0 a 2 b A 300 NULL NULL YES BTREE
+t1 1 b 1 b A 100 NULL NULL YES BTREE
+drop table t1;
+CREATE TABLE t1 (i int(10), index(i) ) ENGINE=MyISAM;
+ALTER TABLE t1 DISABLE KEYS;
+INSERT DELAYED INTO t1 VALUES(1),(2),(3);
+ALTER TABLE t1 ENABLE KEYS;
+drop table t1;
+CREATE TABLE t1 (
+Host varchar(16) binary NOT NULL default '',
+User varchar(16) binary NOT NULL default '',
+PRIMARY KEY (Host,User)
+) ENGINE=MyISAM;
+ALTER TABLE t1 DISABLE KEYS;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 VALUES ('localhost','root'),('localhost',''),('games','monty');
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE
+t1 0 PRIMARY 2 User A 0 NULL NULL BTREE
+ALTER TABLE t1 ENABLE KEYS;
+UNLOCK TABLES;
+CHECK TABLES t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+DROP TABLE t1;
+CREATE TABLE t1 (
+Host varchar(16) binary NOT NULL default '',
+User varchar(16) binary NOT NULL default '',
+PRIMARY KEY (Host,User),
+KEY (Host)
+) ENGINE=MyISAM;
+ALTER TABLE t1 DISABLE KEYS;
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE
+t1 0 PRIMARY 2 User A 0 NULL NULL BTREE
+t1 1 Host 1 Host A NULL NULL NULL BTREE disabled
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 VALUES ('localhost','root'),('localhost','');
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE
+t1 0 PRIMARY 2 User A 0 NULL NULL BTREE
+t1 1 Host 1 Host A NULL NULL NULL BTREE disabled
+ALTER TABLE t1 ENABLE KEYS;
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE
+t1 0 PRIMARY 2 User A 2 NULL NULL BTREE
+t1 1 Host 1 Host A 1 NULL NULL BTREE
+UNLOCK TABLES;
+CHECK TABLES t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1 RENAME t2;
+UNLOCK TABLES;
+select * from t2;
+Host User
+localhost
+localhost root
+DROP TABLE t2;
+CREATE TABLE t1 (
+Host varchar(16) binary NOT NULL default '',
+User varchar(16) binary NOT NULL default '',
+PRIMARY KEY (Host,User),
+KEY (Host)
+) ENGINE=MyISAM;
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1 DISABLE KEYS;
+SHOW INDEX FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 PRIMARY 1 Host A NULL NULL NULL BTREE
+t1 0 PRIMARY 2 User A 0 NULL NULL BTREE
+t1 1 Host 1 Host A NULL NULL NULL BTREE disabled
+DROP TABLE t1;
+create table t1 (a int);
+alter table t1 rename to ``;
+ERROR 42000: Incorrect table name ''
+rename table t1 to ``;
+ERROR 42000: Incorrect table name ''
+drop table t1;
+drop table if exists t1, t2;
+Warnings:
+Note 1051 Unknown table 'test.t1'
+Note 1051 Unknown table 'test.t2'
+create table t1 ( a varchar(10) not null primary key ) engine=myisam;
+create table t2 ( a varchar(10) not null primary key ) engine=merge union=(t1);
+flush tables;
+alter table t1 modify a varchar(10);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(10) NOT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`)
+flush tables;
+alter table t1 modify a varchar(10) not null;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` varchar(10) NOT NULL,
+ PRIMARY KEY (`a`)
+) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 UNION=(`t1`)
+drop table if exists t1, t2;
+create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM;
+insert ignore into t1 (a) values(1);
+Warnings:
+Warning 1364 Field 'b' doesn't have a default value
+Warning 1364 Field 'c' doesn't have a default value
+Warning 1364 Field 'd' doesn't have a default value
+Warning 1364 Field 'e' doesn't have a default value
+Warning 1364 Field 'f' doesn't have a default value
+Warning 1364 Field 'g' doesn't have a default value
+Warning 1364 Field 'h' doesn't have a default value
+Warning 1364 Field 'i' doesn't have a default value
+show table status like 't1';
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
+t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL X N
+alter table t1 modify a int;
+show table status like 't1';
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
+t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL X N
+drop table t1;
+create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM;
+insert ignore into t1 (a) values(1);
+Warnings:
+Warning 1364 Field 'b' doesn't have a default value
+Warning 1364 Field 'c' doesn't have a default value
+Warning 1364 Field 'd' doesn't have a default value
+Warning 1364 Field 'e' doesn't have a default value
+Warning 1364 Field 'f' doesn't have a default value
+Warning 1364 Field 'g' doesn't have a default value
+Warning 1364 Field 'h' doesn't have a default value
+Warning 1364 Field 'i' doesn't have a default value
+show table status like 't1';
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
+t1 MyISAM 10 Fixed 1 37 X X X X X X X X latin1_swedish_ci NULL X N
+drop table t1;
+set names koi8r;
+create table t1 (a char(10) character set koi8r);
+insert into t1 values ('īŋŊīŋŊīŋŊīŋŊ');
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ D4C5D3D4
+alter table t1 change a a char(10) character set cp1251;
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ F2E5F1F2
+alter table t1 change a a binary(4);
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ F2E5F1F2
+alter table t1 change a a char(10) character set cp1251;
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ F2E5F1F2
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ D4C5D3D4
+alter table t1 change a a varchar(10) character set cp1251;
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ F2E5F1F2
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ D4C5D3D4
+alter table t1 change a a text character set cp1251;
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ F2E5F1F2
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+a hex(a)
+īŋŊīŋŊīŋŊīŋŊ D4C5D3D4
+delete from t1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) CHARACTER SET koi8r DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 DEFAULT CHARACTER SET latin1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) CHARACTER SET koi8r DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 CONVERT TO CHARACTER SET latin1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 DEFAULT CHARACTER SET cp1251;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) CHARACTER SET latin1 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=cp1251
+drop table t1;
+create table t1 (myblob longblob,mytext longtext)
+default charset latin1 collate latin1_general_cs;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `myblob` longblob DEFAULT NULL,
+ `mytext` longtext COLLATE latin1_general_cs DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_cs
+alter table t1 character set latin2;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `myblob` longblob DEFAULT NULL,
+ `mytext` longtext CHARACTER SET latin1 COLLATE latin1_general_cs DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin2
+drop table t1;
+CREATE TABLE t1 (a int PRIMARY KEY, b INT UNIQUE);
+ALTER TABLE t1 DROP PRIMARY KEY;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ UNIQUE KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 DROP PRIMARY KEY;
+ERROR 42000: Can't DROP INDEX `PRIMARY`; check that it exists
+DROP TABLE t1;
+create table t1 (a int, b int, key(a));
+insert into t1 values (1,1), (2,2);
+alter table t1 drop key no_such_key;
+ERROR 42000: Can't DROP INDEX `no_such_key`; check that it exists
+alter table t1 drop key a;
+drop table t1;
+CREATE TABLE T12207(a int) ENGINE=MYISAM;
+ALTER TABLE T12207 DISCARD TABLESPACE;
+ERROR HY000: Storage engine MyISAM of the table `test`.`T12207` doesn't have this option
+DROP TABLE T12207;
+create table t1 (a text) character set koi8r;
+insert into t1 values (_koi8r'īŋŊīŋŊīŋŊīŋŊ');
+select hex(a) from t1;
+hex(a)
+D4C5D3D4
+alter table t1 convert to character set cp1251;
+select hex(a) from t1;
+hex(a)
+F2E5F1F2
+drop table t1;
+create table t1 ( a timestamp );
+alter table t1 add unique ( a(1) );
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+drop table t1;
+drop table if exists t1;
+create table t1 (a int, key(a));
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE
+"this used not to disable the index"
+alter table t1 modify a int, disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE disabled
+alter table t1 enable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE
+alter table t1 modify a bigint, disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE disabled
+alter table t1 enable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE
+alter table t1 add b char(10), disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE disabled
+alter table t1 add c decimal(10,2), enable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE
+"this however did"
+alter table t1 disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE disabled
+desc t1;
+Field Type Null Key Default Extra
+a bigint(20) YES MUL NULL
+b char(10) YES NULL
+c decimal(10,2) YES NULL
+alter table t1 add d decimal(15,5);
+"The key should still be disabled"
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 a 1 a A NULL NULL NULL YES BTREE disabled
+drop table t1;
+"Now will test with one unique index"
+create table t1(a int, b char(10), unique(a));
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+alter table t1 disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+alter table t1 enable keys;
+"If no copy on noop change, this won't touch the data file"
+"Unique index, no change"
+alter table t1 modify a int, disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+"Change the type implying data copy"
+"Unique index, no change"
+alter table t1 modify a bigint, disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+alter table t1 modify a bigint;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+alter table t1 modify a int;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+drop table t1;
+"Now will test with one unique and one non-unique index"
+create table t1(a int, b char(10), unique(a), key(b));
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+t1 1 b 1 b A NULL NULL NULL YES BTREE
+alter table t1 disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+t1 1 b 1 b A NULL NULL NULL YES BTREE disabled
+alter table t1 enable keys;
+"If no copy on noop change, this won't touch the data file"
+"The non-unique index will be disabled"
+alter table t1 modify a int, disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+t1 1 b 1 b A NULL NULL NULL YES BTREE disabled
+alter table t1 enable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+t1 1 b 1 b A NULL NULL NULL YES BTREE
+"Change the type implying data copy"
+"The non-unique index will be disabled"
+alter table t1 modify a bigint, disable keys;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+t1 1 b 1 b A NULL NULL NULL YES BTREE disabled
+"Change again the type, but leave the indexes as_is"
+alter table t1 modify a int;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+t1 1 b 1 b A NULL NULL NULL YES BTREE disabled
+"Try the same. When data is no copied on similar tables, this is noop"
+alter table t1 modify a int;
+show indexes from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 0 a 1 a A NULL NULL NULL YES BTREE
+t1 1 b 1 b A NULL NULL NULL YES BTREE disabled
+drop table t1;
+create database mysqltest;
+create table t1 (c1 int);
+alter table t1 rename mysqltest.t1;
+drop table t1;
+ERROR 42S02: Unknown table 'test.t1'
+alter table mysqltest.t1 rename t1;
+drop table t1;
+create table t1 (c1 int);
+use mysqltest;
+drop database mysqltest;
+alter table test.t1 rename t1;
+ERROR 3D000: No database selected
+alter table test.t1 rename test.t1;
+use test;
+drop table t1;
+CREATE TABLE t1(a INT) ROW_FORMAT=FIXED;
+CREATE INDEX i1 ON t1(a);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ KEY `i1` (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+DROP INDEX i1 ON t1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+DROP TABLE t1;
+DROP TABLE IF EXISTS bug24219;
+DROP TABLE IF EXISTS bug24219_2;
+CREATE TABLE bug24219 (a INT, INDEX(a));
+SHOW INDEX FROM bug24219;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+bug24219 1 a 1 a A NULL NULL NULL YES BTREE
+ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS;
+SHOW INDEX FROM bug24219_2;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+bug24219_2 1 a 1 a A NULL NULL NULL YES BTREE disabled
+DROP TABLE bug24219_2;
+drop table if exists table_24562;
+create table table_24562(
+section int,
+subsection int,
+title varchar(50));
+insert into table_24562 values
+(1, 0, "Introduction"),
+(1, 1, "Authors"),
+(1, 2, "Acknowledgements"),
+(2, 0, "Basics"),
+(2, 1, "Syntax"),
+(2, 2, "Client"),
+(2, 3, "Server"),
+(3, 0, "Intermediate"),
+(3, 1, "Complex queries"),
+(3, 2, "Stored Procedures"),
+(3, 3, "Stored Functions"),
+(4, 0, "Advanced"),
+(4, 1, "Replication"),
+(4, 2, "Load balancing"),
+(4, 3, "High availability"),
+(5, 0, "Conclusion");
+select * from table_24562;
+section subsection title
+1 0 Introduction
+1 1 Authors
+1 2 Acknowledgements
+2 0 Basics
+2 1 Syntax
+2 2 Client
+2 3 Server
+3 0 Intermediate
+3 1 Complex queries
+3 2 Stored Procedures
+3 3 Stored Functions
+4 0 Advanced
+4 1 Replication
+4 2 Load balancing
+4 3 High availability
+5 0 Conclusion
+alter table table_24562 add column reviewer varchar(20),
+order by title;
+select * from table_24562;
+section subsection title reviewer
+1 2 Acknowledgements NULL
+4 0 Advanced NULL
+1 1 Authors NULL
+2 0 Basics NULL
+2 2 Client NULL
+3 1 Complex queries NULL
+5 0 Conclusion NULL
+4 3 High availability NULL
+3 0 Intermediate NULL
+1 0 Introduction NULL
+4 2 Load balancing NULL
+4 1 Replication NULL
+2 3 Server NULL
+3 3 Stored Functions NULL
+3 2 Stored Procedures NULL
+2 1 Syntax NULL
+update table_24562 set reviewer="Me" where section=2;
+update table_24562 set reviewer="You" where section=3;
+alter table table_24562
+order by section ASC, subsection DESC;
+select * from table_24562;
+section subsection title reviewer
+1 2 Acknowledgements NULL
+1 1 Authors NULL
+1 0 Introduction NULL
+2 3 Server Me
+2 2 Client Me
+2 1 Syntax Me
+2 0 Basics Me
+3 3 Stored Functions You
+3 2 Stored Procedures You
+3 1 Complex queries You
+3 0 Intermediate You
+4 3 High availability NULL
+4 2 Load balancing NULL
+4 1 Replication NULL
+4 0 Advanced NULL
+5 0 Conclusion NULL
+alter table table_24562
+order by table_24562.subsection ASC, table_24562.section DESC;
+select * from table_24562;
+section subsection title reviewer
+5 0 Conclusion NULL
+4 0 Advanced NULL
+3 0 Intermediate You
+2 0 Basics Me
+1 0 Introduction NULL
+4 1 Replication NULL
+3 1 Complex queries You
+2 1 Syntax Me
+1 1 Authors NULL
+4 2 Load balancing NULL
+3 2 Stored Procedures You
+2 2 Client Me
+1 2 Acknowledgements NULL
+4 3 High availability NULL
+3 3 Stored Functions You
+2 3 Server Me
+alter table table_24562 order by 12;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '12' at line 1
+alter table table_24562 order by (section + 12);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(section + 12)' at line 1
+alter table table_24562 order by length(title);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(title)' at line 1
+alter table table_24562 order by (select 12 from dual);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '(select 12 from dual)' at line 1
+alter table table_24562 order by no_such_col;
+ERROR 42S22: Unknown column 'no_such_col' in 'order clause'
+drop table table_24562;
+create table t1 (mycol int(10) not null);
+alter table t1 alter column mycol set default 0;
+desc t1;
+Field Type Null Key Default Extra
+mycol int(10) NO 0
+drop table t1;
+create table t1(id int(8) primary key auto_increment) engine=heap;
+insert into t1 values (null);
+insert into t1 values (null);
+select * from t1;
+id
+1
+2
+alter table t1 auto_increment = 50;
+alter table t1 engine = myisam;
+insert into t1 values (null);
+select * from t1;
+id
+1
+2
+50
+alter table t1 engine = heap;
+insert into t1 values (null);
+select * from t1;
+id
+1
+2
+50
+51
+drop table t1;
+set @orig_sql_mode = @@sql_mode;
+set sql_mode="no_zero_date";
+create table t1(f1 int);
+alter table t1 add column f2 datetime not null, add column f21 date not null;
+insert into t1 values(1,'2000-01-01','2000-01-01');
+alter table t1 add column f3 datetime not null;
+ERROR 22007: Incorrect datetime value: '0000-00-00 00:00:00' for column 'f3' at row 1
+alter table t1 add column f3 date not null;
+ERROR 22007: Incorrect date value: '0000-00-00' for column 'f3' at row 1
+alter table t1 add column f4 datetime not null default '2002-02-02',
+add column f41 date not null;
+ERROR 22007: Incorrect date value: '0000-00-00' for column 'f41' at row 1
+alter table t1 add column f4 datetime not null default '2002-02-02',
+add column f41 date not null default '2002-02-02';
+select * from t1;
+f1 f2 f21 f4 f41
+1 2000-01-01 00:00:00 2000-01-01 2002-02-02 00:00:00 2002-02-02
+drop table t1;
+set sql_mode= @orig_sql_mode;
+create table t1 (v varchar(32));
+insert into t1 values ('def'),('abc'),('hij'),('3r4f');
+select * from t1;
+v
+def
+abc
+hij
+3r4f
+alter table t1 change v v2 varchar(32);
+select * from t1;
+v2
+def
+abc
+hij
+3r4f
+alter table t1 change v2 v varchar(64);
+select * from t1;
+v
+def
+abc
+hij
+3r4f
+update t1 set v = 'lmn' where v = 'hij';
+select * from t1;
+v
+def
+abc
+lmn
+3r4f
+alter table t1 add i int auto_increment not null primary key first;
+select * from t1;
+i v
+1 def
+2 abc
+3 lmn
+4 3r4f
+update t1 set i=5 where i=3;
+select * from t1;
+i v
+1 def
+2 abc
+5 lmn
+4 3r4f
+alter table t1 change i i bigint;
+select * from t1;
+i v
+1 def
+2 abc
+5 lmn
+4 3r4f
+alter table t1 add unique key (i, v);
+select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn');
+i v
+4 3r4f
+drop table t1;
+create table t1 (t varchar(255) default null, key t (t(80)))
+engine=myisam default charset=latin1;
+alter table t1 change t t text;
+drop table t1;
+CREATE TABLE t1 (a varchar(500));
+ALTER TABLE t1 ADD b GEOMETRY NOT NULL, ADD SPATIAL INDEX(b);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(500) DEFAULT NULL,
+ `b` geometry NOT NULL,
+ SPATIAL KEY `b` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 ADD KEY(b(50));
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(500) DEFAULT NULL,
+ `b` geometry NOT NULL,
+ SPATIAL KEY `b` (`b`),
+ KEY `b_2` (`b`(50))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 ADD c POINT;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(500) DEFAULT NULL,
+ `b` geometry NOT NULL,
+ `c` point DEFAULT NULL,
+ SPATIAL KEY `b` (`b`),
+ KEY `b_2` (`b`(50))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+CREATE TABLE t2 (a INT, KEY (a(20)));
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+ALTER TABLE t1 ADD d INT;
+ALTER TABLE t1 ADD KEY (d(20));
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+ALTER TABLE t1 ADD e GEOMETRY NOT NULL, ADD SPATIAL KEY (e(30));
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+DROP TABLE t1;
+CREATE TABLE t1 (s CHAR(8) BINARY);
+INSERT INTO t1 VALUES ('test');
+SELECT LENGTH(s) FROM t1;
+LENGTH(s)
+4
+ALTER TABLE t1 MODIFY s CHAR(10) BINARY;
+SELECT LENGTH(s) FROM t1;
+LENGTH(s)
+4
+DROP TABLE t1;
+CREATE TABLE t1 (s BINARY(8));
+INSERT INTO t1 VALUES ('test');
+SELECT LENGTH(s) FROM t1;
+LENGTH(s)
+8
+SELECT HEX(s) FROM t1;
+HEX(s)
+7465737400000000
+ALTER TABLE t1 MODIFY s BINARY(10);
+SELECT HEX(s) FROM t1;
+HEX(s)
+74657374000000000000
+SELECT LENGTH(s) FROM t1;
+LENGTH(s)
+10
+DROP TABLE t1;
+CREATE TABLE t1 (v VARCHAR(3), b INT);
+INSERT INTO t1 VALUES ('abc', 5);
+SELECT * FROM t1;
+v b
+abc 5
+ALTER TABLE t1 MODIFY COLUMN v VARCHAR(4);
+SELECT * FROM t1;
+v b
+abc 5
+DROP TABLE t1;
+create table t1 (a tinytext character set latin1);
+alter table t1 convert to character set utf8;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` text DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+drop table t1;
+create table t1 (a mediumtext character set latin1);
+alter table t1 convert to character set utf8;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` longtext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+drop table t1;
+End of 5.0 tests
+drop table if exists t1, t2, t3;
+create table t1 (i int);
+create table t3 (j int);
+insert into t1 values ();
+insert into t3 values ();
+lock table t1 write, t3 read;
+alter table t1 modify i int default 1;
+insert into t1 values ();
+select * from t1;
+i
+NULL
+1
+alter table t1 change i c char(10) default "Two";
+insert into t1 values ();
+select * from t1;
+c
+NULL
+1
+Two
+alter table t1 modify c char(10) default "Three", rename to t2;
+select * from t1;
+ERROR HY000: Table 't1' was not locked with LOCK TABLES
+select * from t2;
+ERROR HY000: Table 't2' was not locked with LOCK TABLES
+select * from t3;
+j
+NULL
+unlock tables;
+insert into t2 values ();
+select * from t2;
+c
+NULL
+1
+Two
+Three
+lock table t2 write, t3 read;
+alter table t2 change c vc varchar(100) default "Four", rename to t1;
+select * from t1;
+ERROR HY000: Table 't1' was not locked with LOCK TABLES
+select * from t2;
+ERROR HY000: Table 't2' was not locked with LOCK TABLES
+select * from t3;
+j
+NULL
+unlock tables;
+insert into t1 values ();
+select * from t1;
+vc
+NULL
+1
+Two
+Three
+Four
+drop tables t1, t3;
+DROP TABLE IF EXISTS `t+1`, `t+2`;
+CREATE TABLE `t+1` (c1 INT);
+ALTER TABLE `t+1` RENAME `t+2`;
+CREATE TABLE `t+1` (c1 INT);
+ALTER TABLE `t+1` RENAME `t+2`;
+ERROR 42S01: Table 't+2' already exists
+DROP TABLE `t+1`, `t+2`;
+CREATE TEMPORARY TABLE `tt+1` (c1 INT);
+ALTER TABLE `tt+1` RENAME `tt+2`;
+CREATE TEMPORARY TABLE `tt+1` (c1 INT);
+ALTER TABLE `tt+1` RENAME `tt+2`;
+ERROR 42S01: Table 'tt+2' already exists
+SHOW CREATE TABLE `tt+1`;
+Table Create Table
+tt+1 CREATE TEMPORARY TABLE `tt+1` (
+ `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SHOW CREATE TABLE `tt+2`;
+Table Create Table
+tt+2 CREATE TEMPORARY TABLE `tt+2` (
+ `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE `tt+1`, `tt+2`;
+CREATE TABLE `#sql1` (c1 INT);
+CREATE TABLE `@0023sql2` (c1 INT);
+SHOW TABLES;
+Tables_in_test
+#sql1
+@0023sql2
+RENAME TABLE `#sql1` TO `@0023sql1`;
+RENAME TABLE `@0023sql2` TO `#sql2`;
+SHOW TABLES;
+Tables_in_test
+#sql2
+@0023sql1
+ALTER TABLE `@0023sql1` RENAME `#sql-1`;
+ALTER TABLE `#sql2` RENAME `@0023sql-2`;
+SHOW TABLES;
+Tables_in_test
+#sql-1
+@0023sql-2
+INSERT INTO `#sql-1` VALUES (1);
+INSERT INTO `@0023sql-2` VALUES (2);
+DROP TABLE `#sql-1`, `@0023sql-2`;
+CREATE TEMPORARY TABLE `#sql1` (c1 INT);
+CREATE TEMPORARY TABLE `@0023sql2` (c1 INT);
+SHOW TABLES;
+Tables_in_test
+ALTER TABLE `#sql1` RENAME `@0023sql1`;
+ALTER TABLE `@0023sql2` RENAME `#sql2`;
+SHOW TABLES;
+Tables_in_test
+INSERT INTO `#sql2` VALUES (1);
+INSERT INTO `@0023sql1` VALUES (2);
+SHOW CREATE TABLE `#sql2`;
+Table Create Table
+#sql2 CREATE TEMPORARY TABLE `#sql2` (
+ `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SHOW CREATE TABLE `@0023sql1`;
+Table Create Table
+@0023sql1 CREATE TEMPORARY TABLE `@0023sql1` (
+ `c1` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE `#sql2`, `@0023sql1`;
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+CREATE TABLE t1 (
+int_field INTEGER UNSIGNED NOT NULL,
+char_field CHAR(10),
+INDEX(`int_field`)
+);
+DESCRIBE t1;
+Field Type Null Key Default Extra
+int_field int(10) unsigned NO MUL NULL
+char_field char(10) YES NULL
+SHOW INDEXES FROM t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
+t1 1 int_field 1 int_field A NULL NULL NULL BTREE
+INSERT INTO t1 VALUES (1, "edno"), (1, "edno"), (2, "dve"), (3, "tri"), (5, "pet");
+"Non-copy data change - new frm, but old data and index files"
+ALTER TABLE t1
+CHANGE int_field unsigned_int_field INTEGER UNSIGNED NOT NULL,
+RENAME t2;
+SELECT * FROM t1 ORDER BY int_field;
+ERROR 42S02: Table 'test.t1' doesn't exist
+SELECT * FROM t2 ORDER BY unsigned_int_field;
+unsigned_int_field char_field
+1 edno
+1 edno
+2 dve
+3 tri
+5 pet
+DESCRIBE t2;
+Field Type Null Key Default Extra
+unsigned_int_field int(10) unsigned NO MUL NULL
+char_field char(10) YES NULL
+DESCRIBE t2;
+Field Type Null Key Default Extra
+unsigned_int_field int(10) unsigned NO MUL NULL
+char_field char(10) YES NULL
+ALTER TABLE t2 MODIFY unsigned_int_field BIGINT UNSIGNED NOT NULL;
+DESCRIBE t2;
+Field Type Null Key Default Extra
+unsigned_int_field bigint(20) unsigned NO MUL NULL
+char_field char(10) YES NULL
+DROP TABLE t2;
+CREATE TABLE t1 (f1 INT, f2 INT, f3 INT);
+INSERT INTO t1 VALUES (1, 2, NULL);
+SELECT * FROM t1;
+f1 f2 f3
+1 2 NULL
+ALTER TABLE t1 MODIFY COLUMN f3 INT AFTER f1;
+SELECT * FROM t1;
+f1 f3 f2
+1 NULL 2
+ALTER TABLE t1 MODIFY COLUMN f3 INT AFTER f2;
+SELECT * FROM t1;
+f1 f2 f3
+1 2 NULL
+DROP TABLE t1;
+create table t1 (c char(10) default "Two");
+lock table t1 write;
+insert into t1 values ();
+alter table t1 modify c char(10) default "Three";
+unlock tables;
+select * from t1;
+c
+Two
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (id int, c int) character set latin1;
+INSERT INTO t1 VALUES (1,1);
+ALTER TABLE t1 CHANGE c d int;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 CHANGE d c int;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 MODIFY c VARCHAR(10);
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 CHANGE c d varchar(10);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 CHANGE d c varchar(10);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (id int, c int) character set utf8;
+INSERT INTO t1 VALUES (1,1);
+ALTER TABLE t1 CHANGE c d int;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 CHANGE d c int;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 MODIFY c VARCHAR(10);
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 CHANGE c d varchar(10);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 CHANGE d c varchar(10);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+DROP TABLE t1;
+create table t1(f1 int not null, f2 int not null, key (f1), key (f2));
+select index_length into @unpaked_keys_size from
+information_schema.tables where table_name='t1';
+alter table t1 pack_keys=1;
+select index_length into @paked_keys_size from
+information_schema.tables where table_name='t1';
+select (@unpaked_keys_size > @paked_keys_size);
+(@unpaked_keys_size > @paked_keys_size)
+1
+select max_data_length into @orig_max_data_length from
+information_schema.tables where table_name='t1';
+alter table t1 max_rows=100;
+select max_data_length into @changed_max_data_length from
+information_schema.tables where table_name='t1';
+select (@orig_max_data_length > @changed_max_data_length);
+(@orig_max_data_length > @changed_max_data_length)
+1
+drop table t1;
+CREATE TABLE t1(a INT AUTO_INCREMENT PRIMARY KEY,
+b ENUM('a', 'b', 'c') NOT NULL);
+INSERT INTO t1 (b) VALUES ('a'), ('c'), ('b'), ('b'), ('a');
+ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL;
+SELECT * FROM t1;
+a b
+1 a
+2 c
+3 b
+4 b
+5 a
+DROP TABLE t1;
+SET @save_sql_mode=@@sql_mode;
+SET sql_mode=strict_all_tables;
+CREATE TABLE t1 (a int NOT NULL default 42);
+INSERT INTO t1 values ();
+SELECT * FROM t1;
+a
+42
+ALTER TABLE t1 ALTER COLUMN a DROP DEFAULT;
+INSERT INTO t1 values ();
+ERROR HY000: Field 'a' doesn't have a default value
+INSERT INTO t1 (a) VALUES (11);
+SELECT * FROM t1 ORDER BY a;
+a
+11
+42
+DROP TABLE t1;
+SET @@sql_mode=@save_sql_mode;
+#
+# Bug#45567: Fast ALTER TABLE broken for enum and set
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a ENUM('a1','a2'));
+INSERT INTO t1 VALUES ('a1'),('a2');
+# No copy: No modification
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2');
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+# No copy: Add new enumeration to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a3');
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+# Copy: Modify and add new to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx','a5');
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+# Copy: Remove from the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx');
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+# Copy: Add new enumeration
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx');
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+# No copy: Add new enumerations to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx','a5','a6');
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+DROP TABLE t1;
+CREATE TABLE t1 (a SET('a1','a2'));
+INSERT INTO t1 VALUES ('a1'),('a2');
+# No copy: No modification
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2');
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+# No copy: Add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a3');
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+# Copy: Modify and add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx','a5');
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+# Copy: Remove from the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx');
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+# Copy: Add new member
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx');
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+# No copy: Add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6');
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+# Copy: Numerical incrase (pack lenght)
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9','a10');
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+DROP TABLE t1;
+CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL,
+f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2);
+this should affect no rows as there is no real change
+ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+DROP TABLE t1;
+#
+# Bug #31145: ALTER TABLE DROP COLUMN, ADD COLUMN crashes (linux)
+# or freezes (win) the server
+#
+CREATE TABLE t1 (a TEXT, id INT, b INT);
+ALTER TABLE t1 DROP COLUMN a, ADD COLUMN c TEXT FIRST;
+DROP TABLE t1;
+#
+# Test for bug #12652385 - "61493: REORDERING COLUMNS TO POSITION
+# FIRST CAN CAUSE DATA TO BE CORRUPTED".
+#
+drop table if exists t1;
+# Use MyISAM engine as the fact that InnoDB doesn't support
+# in-place ALTER TABLE in cases when columns are being renamed
+# hides some bugs.
+create table t1 (i int, j int) engine=myisam;
+insert into t1 value (1, 2);
+# First, test for original problem described in the bug report.
+select * from t1;
+i j
+1 2
+# Change of column order by the below ALTER TABLE statement should
+# affect both column names and column contents.
+alter table t1 modify column j int first;
+select * from t1;
+j i
+2 1
+# Now test for similar problem with the same root.
+# The below ALTER TABLE should change not only the name but
+# also the value for the last column of the table.
+alter table t1 drop column i, add column k int default 0;
+select * from t1;
+j k
+2 0
+# Clean-up.
+drop table t1;
+End of 5.1 tests
+CREATE TABLE t1(c CHAR(10),
+i INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY);
+INSERT INTO t1 VALUES('a',2),('b',4),('c',6);
+ALTER TABLE t1
+DROP i,
+ADD i INT UNSIGNED NOT NULL AUTO_INCREMENT,
+AUTO_INCREMENT = 1;
+DROP TABLE t1;
+CREATE TABLE t1 (a CHAR(1), PRIMARY KEY (a(255)));
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+CREATE TABLE t1 (a CHAR(1));
+ALTER TABLE t1 ADD PRIMARY KEY (a(20));
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+ALTER TABLE t1 ADD KEY (a(20));
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+CREATE UNIQUE INDEX i1 ON t1 (a(20));
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+CREATE INDEX i2 ON t1 (a(20));
+ERROR HY000: Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys
+DROP TABLE t1;
+CREATE TABLE t1 (id int);
+INSERT INTO t1 VALUES (1), (2);
+ALTER TABLE t1 ADD COLUMN (f1 INT), ADD COLUMN (f2 INT), ADD KEY f2k(f2);
+DROP TABLE t1;
+#
+# Test for bug #53820 "ALTER a MEDIUMINT column table causes full
+# table copy".
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a INT, b MEDIUMINT);
+INSERT INTO t1 VALUES (1, 1), (2, 2);
+# The below ALTER should not copy table and so no rows should
+# be shown as affected.
+ALTER TABLE t1 CHANGE a id INT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+DROP TABLE t1;
+#
+# Bug#11754461 CANNOT ALTER TABLE WHEN KEY PREFIX TOO LONG
+#
+DROP DATABASE IF EXISTS db1;
+CREATE DATABASE db1 CHARACTER SET utf8;
+CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
+ALTER TABLE db1.t1 ADD baz INT;
+DROP DATABASE db1;
+# Additional coverage for refactoring which is made as part
+# of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+# to allow temp table operations".
+#
+# At some point the below test case failed on assertion.
+DROP TABLE IF EXISTS t1;
+CREATE TEMPORARY TABLE t1 (i int) ENGINE=MyISAM;
+ALTER TABLE t1 DISCARD TABLESPACE;
+ERROR HY000: Storage engine MyISAM of the table `test`.`t1` doesn't have this option
+DROP TABLE t1;
+#
+# Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
+# CLAUSE FAILS OR ABORTS SERVER.
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2';
+execute stmt1;
+rename table t2 to t1;
+# The below statement should succeed and not emit error or abort server.
+execute stmt1;
+deallocate prepare stmt1;
+drop table t2;
+#
+# MDEV-8960 Can't refer the same column twice in one ALTER TABLE
+#
+CREATE TABLE t1 (
+`a` int(11) DEFAULT NULL
+) DEFAULT CHARSET=utf8;
+ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL,
+ALTER COLUMN `consultant_id` DROP DEFAULT;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `consultant_id` int(11) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+DROP TABLE t1;
+CREATE TABLE t1 (
+`a` int(11) DEFAULT NULL
+) DEFAULT CHARSET=utf8;
+ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL,
+ALTER COLUMN `consultant_id` SET DEFAULT 2;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `consultant_id` int(11) NOT NULL DEFAULT 2
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+DROP TABLE t1;
+CREATE TABLE t1 (
+`a` int(11) DEFAULT NULL
+) DEFAULT CHARSET=utf8;
+ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL DEFAULT 2,
+ALTER COLUMN `consultant_id` DROP DEFAULT;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `consultant_id` int(11) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+DROP TABLE t1;
+CREATE TABLE t1 (
+`a` int(11) DEFAULT NULL
+) DEFAULT CHARSET=utf8;
+ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL DEFAULT 2,
+ALTER COLUMN `consultant_id` DROP DEFAULT,
+MODIFY COLUMN `consultant_id` BIGINT;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `consultant_id` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+DROP TABLE t1;
+CREATE TABLE t1 (
+id INT(11) NOT NULL,
+x_param INT(11) DEFAULT NULL,
+PRIMARY KEY (id)
+) ENGINE=MYISAM;
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS id INT,
+ADD COLUMN IF NOT EXISTS lol INT AFTER id;
+Warnings:
+Note 1060 Duplicate column name 'id'
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS lol INT AFTER id;
+Warnings:
+Note 1060 Duplicate column name 'lol'
+ALTER TABLE t1 DROP COLUMN IF EXISTS lol;
+ALTER TABLE t1 DROP COLUMN IF EXISTS lol;
+Warnings:
+Note 1091 Can't DROP COLUMN `lol`; check that it exists
+ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param);
+ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param);
+Warnings:
+Note 1061 Duplicate key name 'x_param'
+ALTER TABLE t1 MODIFY IF EXISTS lol INT;
+Warnings:
+Note 1054 Unknown column 'lol' in 't1'
+DROP INDEX IF EXISTS x_param ON t1;
+DROP INDEX IF EXISTS x_param ON t1;
+Warnings:
+Note 1091 Can't DROP INDEX `x_param`; check that it exists
+CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param);
+CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param);
+Warnings:
+Note 1061 Duplicate key name 'x_param1'
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) NOT NULL,
+ `x_param` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `x_param1` (`x_param`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (
+id INT(11) NOT NULL,
+x_param INT(11) DEFAULT NULL,
+PRIMARY KEY (id)
+) ENGINE=INNODB;
+CREATE TABLE t2 (
+id INT(11) NOT NULL) ENGINE=INNODB;
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS id INT,
+ADD COLUMN IF NOT EXISTS lol INT AFTER id;
+Warnings:
+Note 1060 Duplicate column name 'id'
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS lol INT AFTER id;
+Warnings:
+Note 1060 Duplicate column name 'lol'
+ALTER TABLE t1 DROP COLUMN IF EXISTS lol;
+ALTER TABLE t1 DROP COLUMN IF EXISTS lol;
+Warnings:
+Note 1091 Can't DROP COLUMN `lol`; check that it exists
+ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param);
+ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param);
+Warnings:
+Note 1061 Duplicate key name 'x_param'
+ALTER TABLE t1 MODIFY IF EXISTS lol INT;
+Warnings:
+Note 1054 Unknown column 'lol' in 't1'
+DROP INDEX IF EXISTS x_param ON t1;
+DROP INDEX IF EXISTS x_param ON t1;
+Warnings:
+Note 1091 Can't DROP INDEX `x_param`; check that it exists
+CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param);
+CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param);
+Warnings:
+Note 1061 Duplicate key name 'x_param1'
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) NOT NULL,
+ `x_param` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `x_param1` (`x_param`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS fk(id) REFERENCES t1(id);
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS fk(id) REFERENCES t1(id);
+Warnings:
+Note 1061 Duplicate key name 'fk'
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk;
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk;
+Warnings:
+Note 1091 Can't DROP FOREIGN KEY `fk`; check that it exists
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL,
+ KEY `fk` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+ALTER TABLE t2 ADD FOREIGN KEY (id) REFERENCES t1(id);
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS t2_ibfk_1(id) REFERENCES t1(id);
+Warnings:
+Note 1061 Duplicate key name 't2_ibfk_1'
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
+Warnings:
+Note 1091 Can't DROP FOREIGN KEY `t2_ibfk_1`; check that it exists
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL,
+ KEY `id` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t2;
+CREATE TABLE t2 (
+id INT(11) NOT NULL);
+ALTER TABLE t2 ADD COLUMN a INT, ADD COLUMN IF NOT EXISTS a INT;
+Warnings:
+Note 1060 Duplicate column name 'a'
+ALTER TABLE t2 ADD KEY k_id(id), ADD KEY IF NOT EXISTS k_id(id);
+Warnings:
+Note 1061 Duplicate key name 'k_id'
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL,
+ `a` int(11) DEFAULT NULL,
+ KEY `k_id` (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t2 DROP KEY k_id, DROP KEY IF EXISTS k_id;
+Warnings:
+Note 1091 Can't DROP INDEX `k_id`; check that it exists
+ALTER TABLE t2 DROP COLUMN a, DROP COLUMN IF EXISTS a;
+Warnings:
+Note 1091 Can't DROP COLUMN `a`; check that it exists
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t2;
+DROP TABLE t1;
+CREATE TABLE t1 (
+`transaction_id` int(11) NOT NULL DEFAULT '0',
+KEY `transaction_id` (`transaction_id`));
+ALTER TABLE t1 DROP KEY IF EXISTS transaction_id, ADD PRIMARY KEY IF NOT EXISTS (transaction_id);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `transaction_id` int(11) NOT NULL DEFAULT 0,
+ PRIMARY KEY (`transaction_id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+# Bug#11748057 (formerly known as 34972): ALTER TABLE statement doesn't
+# identify correct column name.
+#
+CREATE TABLE t1 (c1 int unsigned , c2 char(100) not null default '');
+ALTER TABLE t1 ADD c3 char(16) NOT NULL DEFAULT '' AFTER c2,
+MODIFY c2 char(100) NOT NULL DEFAULT '' AFTER c1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c1` int(10) unsigned DEFAULT NULL,
+ `c2` char(100) NOT NULL DEFAULT '',
+ `c3` char(16) NOT NULL DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# WL#5534 Online ALTER, Phase 1
+#
+# Single thread tests.
+# See innodb_mysql_sync.test for multi thread tests.
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a INT PRIMARY KEY, b INT) engine=InnoDB;
+CREATE TABLE m1(a INT PRIMARY KEY, b INT) engine=MyISAM;
+INSERT INTO t1 VALUES (1,1), (2,2);
+INSERT INTO m1 VALUES (1,1), (2,2);
+#
+# 1: Test ALGORITHM keyword
+#
+# --enable_info allows us to see how many rows were updated
+# by ALTER TABLE. in-place will show 0 rows, while copy > 0.
+ALTER TABLE t1 ADD INDEX i1(b);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= DEFAULT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i2`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= COPY;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i3`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= INPLACE;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i4`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i5(b), ALGORITHM= INVALID;
+ERROR HY000: Unknown ALGORITHM 'INVALID'
+ALTER TABLE m1 ENABLE KEYS;
+affected rows: 0
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= DEFAULT;
+affected rows: 0
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE;
+affected rows: 0
+ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4;
+#
+# 2: Test ALGORITHM + old_alter_table
+#
+SET SESSION old_alter_table= 1;
+affected rows: 0
+ALTER TABLE t1 ADD INDEX i1(b);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= DEFAULT;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i2`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= COPY;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i3`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= INPLACE;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i4`. This is deprecated and will be disallowed in a future release
+SET SESSION old_alter_table= 0;
+affected rows: 0
+ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4;
+#
+# 3: Test unsupported in-place operation
+#
+ALTER TABLE t1 ADD COLUMN (c1 INT);
+ALTER TABLE t1 ADD COLUMN (c2 INT), ALGORITHM= DEFAULT;
+ALTER TABLE t1 ADD COLUMN (c3 INT), ALGORITHM= COPY;
+ALTER TABLE t1 ADD COLUMN (c4 INT), ALGORITHM= INPLACE;
+ALTER TABLE t1 DROP COLUMN c1, DROP COLUMN c2, DROP COLUMN c3, DROP COLUMN c4;
+#
+# 4: Test LOCK keyword
+#
+ALTER TABLE t1 ADD INDEX i1(b), LOCK= DEFAULT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 ADD INDEX i2(b), LOCK= NONE;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i2`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i3(b), LOCK= SHARED;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i3`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i4(b), LOCK= EXCLUSIVE;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i4`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i5(b), LOCK= INVALID;
+ERROR HY000: Unknown LOCK type 'INVALID'
+ALTER TABLE m1 ENABLE KEYS, LOCK= DEFAULT;
+ALTER TABLE m1 ENABLE KEYS, LOCK= NONE;
+ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE
+ALTER TABLE m1 ENABLE KEYS, LOCK= SHARED;
+ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE
+ALTER TABLE m1 ENABLE KEYS, LOCK= EXCLUSIVE;
+ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4;
+#
+# 5: Test ALGORITHM + LOCK
+#
+ALTER TABLE t1 ADD INDEX i1(b), ALGORITHM= INPLACE, LOCK= NONE;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= INPLACE, LOCK= SHARED;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i2`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= INPLACE, LOCK= EXCLUSIVE;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i3`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= COPY, LOCK= NONE;
+ERROR 0A000: LOCK=NONE is not supported. Reason: COPY algorithm requires a lock. Try LOCK=SHARED
+ALTER TABLE t1 ADD INDEX i5(b), ALGORITHM= COPY, LOCK= SHARED;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i5`. This is deprecated and will be disallowed in a future release
+ALTER TABLE t1 ADD INDEX i6(b), ALGORITHM= COPY, LOCK= EXCLUSIVE;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1831 Duplicate index `i6`. This is deprecated and will be disallowed in a future release
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= NONE;
+ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= SHARED;
+ERROR 0A000: LOCK=NONE/SHARED is not supported for this operation. Try LOCK=EXCLUSIVE
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= EXCLUSIVE;
+affected rows: 0
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= NONE;
+ERROR 0A000: LOCK=NONE is not supported. Reason: COPY algorithm requires a lock. Try LOCK=SHARED
+ALTER ONLINE TABLE m1 ADD COLUMN c int;
+ERROR 0A000: LOCK=NONE is not supported for this operation. Try LOCK=SHARED
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= SHARED;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= EXCLUSIVE;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+DROP TABLE t1, m1;
+#
+# 6: Possible deadlock involving thr_lock.c
+#
+CREATE TABLE t1(a INT PRIMARY KEY, b INT);
+INSERT INTO t1 VALUES (1,1), (2,2);
+START TRANSACTION;
+INSERT INTO t1 VALUES (3,3);
+connect con1, localhost, root;
+# Sending:
+ALTER TABLE t1 DISABLE KEYS;
+connection default;
+# Waiting until ALTER TABLE is blocked.
+UPDATE t1 SET b = 4;
+COMMIT;
+connection con1;
+# Reaping: ALTER TABLE t1 DISABLE KEYS
+disconnect con1;
+connection default;
+DROP TABLE t1;
+#
+# 7: Which operations require copy and which can be done in-place?
+#
+# Test which ALTER TABLE operations are done in-place and
+# which operations are done using temporary table copy.
+#
+# --enable_info allows us to see how many rows were updated
+# by ALTER TABLE. in-place will show 0 rows, while copy > 0.
+#
+DROP TABLE IF EXISTS ti1, ti2, ti3, tm1, tm2, tm3;
+# Single operation tests
+CREATE TABLE ti1(a INT NOT NULL, b INT, c INT) engine=InnoDB;
+CREATE TABLE tm1(a INT NOT NULL, b INT, c INT) engine=MyISAM;
+CREATE TABLE ti2(a INT PRIMARY KEY AUTO_INCREMENT, b INT, c INT) engine=InnoDB;
+CREATE TABLE tm2(a INT PRIMARY KEY AUTO_INCREMENT, b INT, c INT) engine=MyISAM;
+INSERT INTO ti1 VALUES (1,1,1), (2,2,2);
+INSERT INTO ti2 VALUES (1,1,1), (2,2,2);
+INSERT INTO tm1 VALUES (1,1,1), (2,2,2);
+INSERT INTO tm2 VALUES (1,1,1), (2,2,2);
+ALTER TABLE ti1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD COLUMN d VARCHAR(200);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD COLUMN d VARCHAR(200);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD COLUMN d2 VARCHAR(200);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD COLUMN d2 VARCHAR(200);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD COLUMN e ENUM('a', 'b') FIRST;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD COLUMN e ENUM('a', 'b') FIRST;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD COLUMN f INT AFTER a;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD COLUMN f INT AFTER a;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD INDEX ii1(b);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD INDEX im1(b);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD UNIQUE INDEX ii2 (c);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD UNIQUE INDEX im2 (c);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD FULLTEXT INDEX ii3 (d);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD FULLTEXT INDEX im3 (d);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD FULLTEXT INDEX ii4 (d2);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD FULLTEXT INDEX im4 (d2);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD PRIMARY KEY(a), ALGORITHM=INPLACE;
+ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try ALGORITHM=COPY
+ALTER TABLE ti1 ADD PRIMARY KEY(a);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD PRIMARY KEY(a);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 DROP INDEX ii3;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 DROP INDEX im3;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 DROP COLUMN d2;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 DROP COLUMN d2;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ADD CONSTRAINT fi1 FOREIGN KEY (b) REFERENCES ti2(a);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ADD CONSTRAINT fm1 FOREIGN KEY (b) REFERENCES tm2(a);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ALTER COLUMN b SET DEFAULT 1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ALTER COLUMN b SET DEFAULT 1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 ALTER COLUMN b DROP DEFAULT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ALTER COLUMN b DROP DEFAULT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 CHANGE COLUMN f g INT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 CHANGE COLUMN f g INT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 CHANGE COLUMN g h VARCHAR(20);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 CHANGE COLUMN g h VARCHAR(20);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MODIFY COLUMN e ENUM('a', 'b', 'c');
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MODIFY COLUMN e ENUM('a', 'b', 'c');
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MODIFY COLUMN e INT;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MODIFY COLUMN e INT;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MODIFY COLUMN e INT AFTER h;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MODIFY COLUMN e INT AFTER h;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MODIFY COLUMN e INT FIRST;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MODIFY COLUMN e INT FIRST;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+SET @orig_sql_mode = @@sql_mode;
+SET @@sql_mode = 'STRICT_TRANS_TABLES';
+ALTER TABLE ti1 MODIFY COLUMN c INT NOT NULL;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SET @@sql_mode = @orig_sql_mode;
+ALTER TABLE tm1 MODIFY COLUMN c INT NOT NULL;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MODIFY COLUMN c INT NULL;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MODIFY COLUMN c INT NULL;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MODIFY COLUMN h VARCHAR(30);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MODIFY COLUMN h VARCHAR(30);
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MODIFY COLUMN h VARCHAR(30) AFTER d;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MODIFY COLUMN h VARCHAR(30) AFTER d;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 DROP COLUMN h;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 DROP COLUMN h;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 DROP INDEX ii2;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 DROP INDEX im2;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 DROP PRIMARY KEY;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 DROP PRIMARY KEY;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 DROP FOREIGN KEY fi1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 DROP FOREIGN KEY fm1;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 RENAME TO ti3;
+affected rows: 0
+ALTER TABLE tm1 RENAME TO tm3;
+affected rows: 0
+ALTER TABLE ti3 RENAME TO ti1;
+affected rows: 0
+ALTER TABLE tm3 RENAME TO tm1;
+affected rows: 0
+ALTER TABLE ti1 ORDER BY b;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 ORDER BY b;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 CONVERT TO CHARACTER SET utf16;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 CONVERT TO CHARACTER SET utf16;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 DEFAULT CHARACTER SET utf8;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 DEFAULT CHARACTER SET utf8;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 FORCE;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 FORCE;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 AUTO_INCREMENT 3;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 AUTO_INCREMENT 3;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 AVG_ROW_LENGTH 10;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 AVG_ROW_LENGTH 10;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 CHECKSUM 1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 CHECKSUM 1;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 COMMENT 'test';
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 COMMENT 'test';
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MAX_ROWS 100;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MAX_ROWS 100;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 MIN_ROWS 1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 MIN_ROWS 1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti1 PACK_KEYS 1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE tm1 PACK_KEYS 1;
+affected rows: 2
+info: Records: 2 Duplicates: 0 Warnings: 0
+DROP TABLE ti1, ti2, tm1, tm2;
+# Tests of >1 operation (InnoDB)
+CREATE TABLE ti1(a INT PRIMARY KEY AUTO_INCREMENT, b INT) engine=InnoDB;
+INSERT INTO ti1(b) VALUES (1), (2);
+ALTER TABLE ti1 RENAME TO ti3, ADD INDEX ii1(b);
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE ti3 DROP INDEX ii1, AUTO_INCREMENT 5;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+INSERT INTO ti3(b) VALUES (5);
+ALTER TABLE ti3 ADD INDEX ii1(b), AUTO_INCREMENT 7;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+INSERT INTO ti3(b) VALUES (7);
+SELECT * FROM ti3;
+a b
+1 1
+2 2
+5 5
+7 7
+DROP TABLE ti3;
+#
+# 8: Scenario in which ALTER TABLE was returning an unwarranted
+# ER_ILLEGAL_HA error at some point during work on this WL.
+#
+CREATE TABLE tm1(i INT DEFAULT 1) engine=MyISAM;
+ALTER TABLE tm1 ADD INDEX ii1(i), ALTER COLUMN i DROP DEFAULT;
+DROP TABLE tm1;
+create table if not exists t1 (i int);
+alter table t1 add key (i);
+alter table t1 add key if not exists (i);
+Warnings:
+Note 1061 Duplicate key name 'i'
+DROP TABLE t1;
+create table t1 (a int);
+alter table t1 change column if exists a b bigint;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+create table t1 (i int);
+alter table t1 add unique index if not exists idx(i);
+alter table t1 add unique index if not exists idx(i);
+Warnings:
+Note 1061 Duplicate key name 'idx'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL,
+ UNIQUE KEY `idx` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (
+`event_id` bigint(20) unsigned NOT NULL DEFAULT '0',
+`market_id` bigint(20) unsigned NOT NULL DEFAULT '0',
+PRIMARY KEY (`event_id`,`market_id`)
+);
+ALTER TABLE t1 ADD PRIMARY KEY IF NOT EXISTS event_id (event_id,market_id);
+Warnings:
+Note 1061 Multiple primary key defined
+DROP TABLE t1;
+#
+# MDEV-11126 Crash while altering persistent virtual column
+#
+CREATE TABLE `tab1` (
+`id` bigint(20) NOT NULL AUTO_INCREMENT,
+`field2` set('option1','option2','option3','option4') NOT NULL,
+`field3` set('option1','option2','option3','option4','option5') NOT NULL,
+`field4` set('option1','option2','option3','option4') NOT NULL,
+`field5` varchar(32) NOT NULL,
+`field6` varchar(32) NOT NULL,
+`field7` varchar(32) NOT NULL,
+`field8` varchar(32) NOT NULL,
+`field9` int(11) NOT NULL DEFAULT '1',
+`field10` varchar(16) NOT NULL,
+`field11` enum('option1','option2','option3') NOT NULL DEFAULT 'option1',
+`v_col` varchar(128) AS (IF(field11='option1',CONCAT_WS(":","field1",field2,field3,field4,field5,field6,field7,field8,field9,field10), CONCAT_WS(":","field1",field11,field2,field3,field4,field5,field6,field7,field8,field9,field10))) PERSISTENT,
+PRIMARY KEY (`id`)
+) DEFAULT CHARSET=latin1;
+ALTER TABLE `tab1` CHANGE COLUMN v_col `v_col` varchar(128);
+SHOW CREATE TABLE `tab1`;
+Table Create Table
+tab1 CREATE TABLE `tab1` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `field2` set('option1','option2','option3','option4') NOT NULL,
+ `field3` set('option1','option2','option3','option4','option5') NOT NULL,
+ `field4` set('option1','option2','option3','option4') NOT NULL,
+ `field5` varchar(32) NOT NULL,
+ `field6` varchar(32) NOT NULL,
+ `field7` varchar(32) NOT NULL,
+ `field8` varchar(32) NOT NULL,
+ `field9` int(11) NOT NULL DEFAULT 1,
+ `field10` varchar(16) NOT NULL,
+ `field11` enum('option1','option2','option3') NOT NULL DEFAULT 'option1',
+ `v_col` varchar(128) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE `tab1` CHANGE COLUMN v_col `v_col` varchar(128) AS (IF(field11='option1',CONCAT_WS(":","field1",field2,field3,field4,field5,field6,field7,field8,field9,field10), CONCAT_WS(":","field1",field11,field2,field3,field4,field5,field6,field7,field8,field9,field10))) PERSISTENT;
+SHOW CREATE TABLE `tab1`;
+Table Create Table
+tab1 CREATE TABLE `tab1` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `field2` set('option1','option2','option3','option4') NOT NULL,
+ `field3` set('option1','option2','option3','option4','option5') NOT NULL,
+ `field4` set('option1','option2','option3','option4') NOT NULL,
+ `field5` varchar(32) NOT NULL,
+ `field6` varchar(32) NOT NULL,
+ `field7` varchar(32) NOT NULL,
+ `field8` varchar(32) NOT NULL,
+ `field9` int(11) NOT NULL DEFAULT 1,
+ `field10` varchar(16) NOT NULL,
+ `field11` enum('option1','option2','option3') NOT NULL DEFAULT 'option1',
+ `v_col` varchar(128) GENERATED ALWAYS AS (if(`field11` = 'option1',concat_ws(':','field1',`field2`,`field3`,`field4`,`field5`,`field6`,`field7`,`field8`,`field9`,`field10`),concat_ws(':','field1',`field11`,`field2`,`field3`,`field4`,`field5`,`field6`,`field7`,`field8`,`field9`,`field10`))) STORED,
+ PRIMARY KEY (`id`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE `tab1`;
+#
+# MDEV-11548 Reproducible server crash after the 2nd ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS
+#
+CREATE TABLE t1 (id INT UNSIGNED NOT NULL PRIMARY KEY);
+CREATE TABLE t2 (id1 INT UNSIGNED NOT NULL);
+ALTER TABLE t2
+ADD FOREIGN KEY IF NOT EXISTS (id1)
+REFERENCES t1 (id);
+ALTER TABLE t2
+ADD FOREIGN KEY IF NOT EXISTS (id1)
+REFERENCES t1 (id);
+Warnings:
+Note 1061 Duplicate key name 'id1'
+DROP TABLE t2;
+DROP TABLE t1;
+#
+# MDEV-6390 CONVERT TO CHARACTER SET utf8 doesn't change DEFAULT CHARSET.
+#
+CREATE TABLE t1 (id int(11) NOT NULL, a int(11) NOT NULL, b int(11))
+ENGINE=InnoDB DEFAULT CHARSET=latin1;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) NOT NULL,
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+ALTER TABLE t1 CONVERT TO CHARACTER SET utf8;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) NOT NULL,
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
+DROP TABLE t1;
+#
+# MDEV-15308
+# Assertion `ha_alter_info->alter_info->drop_list.elements > 0' failed
+# in ha_innodb::prepare_inplace_alter_table
+#
+CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB;
+ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP COLUMN b;
+Warnings:
+Note 1091 Can't DROP FOREIGN KEY `fk`; check that it exists
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB;
+ALTER TABLE t1 DROP INDEX IF EXISTS fk, DROP COLUMN b;
+Warnings:
+Note 1091 Can't DROP INDEX `fk`; check that it exists
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT, c INT, KEY(c)) ENGINE=InnoDB;
+ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP COLUMN c;
+Warnings:
+Note 1091 Can't DROP FOREIGN KEY `fk`; check that it exists
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT, c INT, KEY c1(c)) ENGINE=InnoDB;
+ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP INDEX c1;
+Warnings:
+Note 1091 Can't DROP FOREIGN KEY `fk`; check that it exists
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB;
+ALTER TABLE t1 DROP INDEX IF EXISTS fk, DROP COLUMN IF EXISTS c;
+Warnings:
+Note 1091 Can't DROP INDEX `fk`; check that it exists
+Note 1091 Can't DROP COLUMN `c`; check that it exists
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# End of 10.0 tests
+#
+#
+# MDEV-7374 : Losing connection to MySQL while running ALTER TABLE
+#
+CREATE TABLE t1(i INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
+INSERT INTO t1 SELECT a.* FROM t1 a, t1 b, t1 c, t1 d, t1 e;
+ALTER TABLE t1 MODIFY i FLOAT;
+DROP TABLE t1;
+#
+# MDEV-7816 ALTER with DROP INDEX and ADD INDEX .. COMMENT='comment2' ignores the new comment
+#
+CREATE TABLE t1(a INT);
+CREATE INDEX i1 ON t1(a) COMMENT 'comment1';
+ALTER TABLE t1 DROP INDEX i1, ADD INDEX i1(a) COMMENT 'comment2';
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ KEY `i1` (`a`) COMMENT 'comment2'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+#
+# End of 10.1 tests
+#
+#
+# MDEV-10421 duplicate CHECK CONSTRAINTs
+#
+CREATE TABLE t1 (a INT, b INT) engine=myisam;
+ALTER TABLE t1 ADD CONSTRAINT IF NOT EXISTS `min` CHECK (a+b > 100);
+ALTER TABLE t1 ADD CONSTRAINT `min` CHECK (a+b > 100);
+ERROR HY000: Duplicate CHECK constraint name 'min'
+ALTER TABLE t1 ADD CONSTRAINT IF NOT EXISTS `min` CHECK (a+b > 100);
+Warnings:
+Note 1826 Duplicate CHECK constraint name 'min'
+ALTER TABLE t1 ADD CONSTRAINT `mini` CHECK (a+b > 100);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ CONSTRAINT `min` CHECK (`a` + `b` > 100),
+ CONSTRAINT `mini` CHECK (`a` + `b` > 100)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1(a INT, b INT, CONSTRAINT min check (a>5),
+CONSTRAINT min check (b>5));
+ERROR HY000: Duplicate CHECK constraint name 'min'
+create table t1 (a int, b int, check(a>b));
+alter table t1 drop column a;
+ERROR 42S22: Unknown column 'a' in 'CHECK'
+alter table t1 drop column b, add column b bigint first;
+ERROR 42S22: Unknown column 'b' in 'CHECK'
+alter table t1 drop column a, drop constraint constraint_1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int, check(a>0));
+alter table t1 drop column a;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int, check(a>0));
+alter table t1 drop column a, add column a bigint first;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` bigint(20) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int, c int, unique(a));
+alter table t1 drop column a;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int, b int, c int, unique(a,b));
+alter table t1 drop column a;
+ERROR 42000: Key column 'a' doesn't exist in table
+alter table t1 drop column a, drop index a;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (i int);
+alter table t1 alter column if exists a set default 1;
+Warnings:
+Note 1054 Unknown column 'a' in 't1'
+alter table t1 alter column if exists a drop default;
+Warnings:
+Note 1054 Unknown column 'a' in 't1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+#
+# MDEV-13508 Check that rename of columns changes defaults, virtual
+# columns and constraints
+#
+create table t1 (a int, b int, check(a>b));
+alter table t1 change column a b int, change column b a int;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `b` int(11) DEFAULT NULL,
+ `a` int(11) DEFAULT NULL,
+ CONSTRAINT `CONSTRAINT_1` CHECK (`b` > `a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (a int primary key, b int, c int default (a+b) check (a+b>0),
+d int as (a+b),
+key (b),
+constraint test check (a+b > 1));
+alter table t1 change b new_b int not null, add column b char(1), add constraint new check (length(b) > 0);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `new_b` int(11) NOT NULL,
+ `c` int(11) DEFAULT (`a` + `new_b`) CHECK (`a` + `new_b` > 0),
+ `d` int(11) GENERATED ALWAYS AS (`a` + `new_b`) VIRTUAL,
+ `b` char(1) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `b` (`new_b`),
+ CONSTRAINT `test` CHECK (`a` + `new_b` > 1),
+ CONSTRAINT `new` CHECK (octet_length(`b`) > 0)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+#
++# MDEV-11071: Assertion `thd->transaction.stmt.is_empty()' failed
++# in Locked_tables_list::unlock_locked_tables
++#
++CREATE TABLE t1 (d DATETIME DEFAULT CURRENT_TIMESTAMP, i INT) ENGINE=InnoDB;
++INSERT INTO t1 (i) VALUES (1),(1);
++LOCK TABLE t1 WRITE;
++ALTER TABLE t1 ADD UNIQUE(i);
++ERROR 23000: Duplicate entry '1' for key 'i'
++UNLOCK TABLES;
++DROP TABLE t1;
++#
+# End of 10.2 tests
+#
diff --cc mysql-test/main/alter_table.test
index aa9faf710f5,00000000000..c9302d588da
mode 100644,000000..100644
--- a/mysql-test/main/alter_table.test
+++ b/mysql-test/main/alter_table.test
@@@ -1,1942 -1,0 +1,1958 @@@
+--source include/have_innodb.inc
+#
+# Test of alter table
+#
+--disable_warnings
+drop table if exists t1,t2;
+drop database if exists mysqltest;
+--enable_warnings
+
+create table t1 (
+col1 int not null auto_increment primary key,
+col2 varchar(30) not null,
+col3 varchar (20) not null,
+col4 varchar(4) not null,
+col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null,
+col6 int not null, to_be_deleted int);
+insert into t1 values (2,4,3,5,"PENDING",1,7);
+alter table t1
+add column col4_5 varchar(20) not null after col4,
+add column col7 varchar(30) not null after col5,
+add column col8 datetime not null, drop column to_be_deleted,
+change column col2 fourth varchar(30) not null after col3,
+modify column col6 int not null first;
+select * from t1;
+drop table t1;
+
+create table t1 (bandID MEDIUMINT UNSIGNED NOT NULL PRIMARY KEY, payoutID SMALLINT UNSIGNED NOT NULL);
+insert into t1 (bandID,payoutID) VALUES (1,6),(2,6),(3,4),(4,9),(5,10),(6,1),(7,12),(8,12);
+alter table t1 add column new_col int, order by payoutid,bandid;
+select * from t1;
+alter table t1 order by bandid,payoutid;
+select * from t1;
+drop table t1;
+
+# Check that pack_keys and dynamic length rows are not forced.
+
+CREATE TABLE t1 (
+GROUP_ID int(10) unsigned DEFAULT '0' NOT NULL,
+LANG_ID smallint(5) unsigned DEFAULT '0' NOT NULL,
+NAME varchar(80) DEFAULT '' NOT NULL,
+PRIMARY KEY (GROUP_ID,LANG_ID),
+KEY NAME (NAME));
+#show table status like "t1";
+ALTER TABLE t1 CHANGE NAME NAME CHAR(80) not null;
+--replace_column 8 #
+SHOW FULL COLUMNS FROM t1;
+DROP TABLE t1;
+
+#
+# Test of ALTER TABLE ... ORDER BY
+#
+
+create table t1 (n int);
+insert into t1 values(9),(3),(12),(10);
+alter table t1 order by n;
+select * from t1;
+drop table t1;
+
+CREATE TABLE t1 (
+ id int(11) unsigned NOT NULL default '0',
+ category_id tinyint(4) unsigned NOT NULL default '0',
+ type_id tinyint(4) unsigned NOT NULL default '0',
+ body text NOT NULL,
+ user_id int(11) unsigned NOT NULL default '0',
+ status enum('new','old') NOT NULL default 'new',
+ PRIMARY KEY (id)
+) ENGINE=MyISAM;
+
+ALTER TABLE t1 ORDER BY t1.id, t1.status, t1.type_id, t1.user_id, t1.body;
+DROP TABLE t1;
+
+#
+# The following combination found a hang-bug in MyISAM
+#
+
+CREATE TABLE t1 (AnamneseId int(10) unsigned NOT NULL auto_increment,B BLOB,PRIMARY KEY (AnamneseId)) engine=myisam;
+insert into t1 values (null,"hello");
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1 ADD Column new_col int not null;
+UNLOCK TABLES;
+OPTIMIZE TABLE t1;
+DROP TABLE t1;
+
+#
+# Drop and add an auto_increment column
+#
+
+create table t1 (i int unsigned not null auto_increment primary key);
+insert into t1 values (null),(null),(null),(null);
+alter table t1 drop i,add i int unsigned not null auto_increment, drop primary key, add primary key (i);
+select * from t1;
+drop table t1;
+
+#
+# Bug #2628: 'alter table t1 rename mysqltest.t1' silently drops mysqltest.t1
+# if it exists
+#
+create table t1 (name char(15));
+insert into t1 (name) values ("current");
+create database mysqltest;
+create table mysqltest.t1 (name char(15));
+insert into mysqltest.t1 (name) values ("mysqltest");
+select * from t1;
+select * from mysqltest.t1;
+--error ER_TABLE_EXISTS_ERROR
+alter table t1 rename mysqltest.t1;
+select * from t1;
+select * from mysqltest.t1;
+drop table t1;
+drop database mysqltest;
+
+#
+# ALTER TABLE ... ENABLE/DISABLE KEYS
+
+create table t1 (n1 int not null, n2 int, n3 int, n4 float,
+ unique(n1),
+ key (n1, n2, n3, n4),
+ key (n2, n3, n4, n1),
+ key (n3, n4, n1, n2),
+ key (n4, n1, n2, n3) );
+alter table t1 disable keys;
+show keys from t1;
+#let $1=10000;
+let $1=10;
+--disable_query_log
+begin;
+while ($1)
+{
+ eval insert into t1 values($1,RAND()*1000,RAND()*1000,RAND());
+ dec $1;
+}
+commit;
+--enable_query_log
+alter table t1 enable keys;
+show keys from t1;
+drop table t1;
+
+#
+# Alter table and rename
+#
+
+create table t1 (i int unsigned not null auto_increment primary key);
+alter table t1 rename t2;
+alter table t2 rename t1, add c char(10) comment "no comment";
+show columns from t1;
+drop table t1;
+
+# implicit analyze
+
+create table t1 (a int, b int);
+let $1=100;
+--disable_query_log
+begin;
+while ($1)
+{
+ eval insert into t1 values(1,$1), (2,$1), (3, $1);
+ dec $1;
+}
+commit;
+--enable_query_log
+alter table t1 add unique (a,b), add key (b);
+show keys from t1;
+analyze table t1;
+show keys from t1;
+drop table t1;
+
+#
+# Test of ALTER TABLE DELAYED
+#
+
+CREATE TABLE t1 (i int(10), index(i) ) ENGINE=MyISAM;
+ALTER TABLE t1 DISABLE KEYS;
+INSERT DELAYED INTO t1 VALUES(1),(2),(3);
+ALTER TABLE t1 ENABLE KEYS;
+drop table t1;
+
+#
+# Test ALTER TABLE ENABLE/DISABLE keys when things are locked
+#
+
+CREATE TABLE t1 (
+ Host varchar(16) binary NOT NULL default '',
+ User varchar(16) binary NOT NULL default '',
+ PRIMARY KEY (Host,User)
+) ENGINE=MyISAM;
+
+ALTER TABLE t1 DISABLE KEYS;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 VALUES ('localhost','root'),('localhost',''),('games','monty');
+SHOW INDEX FROM t1;
+ALTER TABLE t1 ENABLE KEYS;
+UNLOCK TABLES;
+CHECK TABLES t1;
+DROP TABLE t1;
+
+#
+# Test with two keys
+#
+
+CREATE TABLE t1 (
+ Host varchar(16) binary NOT NULL default '',
+ User varchar(16) binary NOT NULL default '',
+ PRIMARY KEY (Host,User),
+ KEY (Host)
+) ENGINE=MyISAM;
+
+ALTER TABLE t1 DISABLE KEYS;
+SHOW INDEX FROM t1;
+LOCK TABLES t1 WRITE;
+INSERT INTO t1 VALUES ('localhost','root'),('localhost','');
+SHOW INDEX FROM t1;
+ALTER TABLE t1 ENABLE KEYS;
+SHOW INDEX FROM t1;
+UNLOCK TABLES;
+CHECK TABLES t1;
+
+# Test RENAME with LOCK TABLES
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1 RENAME t2;
+UNLOCK TABLES;
+select * from t2;
+DROP TABLE t2;
+
+#
+# Test disable keys with locking
+#
+CREATE TABLE t1 (
+ Host varchar(16) binary NOT NULL default '',
+ User varchar(16) binary NOT NULL default '',
+ PRIMARY KEY (Host,User),
+ KEY (Host)
+) ENGINE=MyISAM;
+
+LOCK TABLES t1 WRITE;
+ALTER TABLE t1 DISABLE KEYS;
+SHOW INDEX FROM t1;
+DROP TABLE t1;
+
+#
+# BUG#4717 - check for valid table names
+#
+create table t1 (a int);
+--error ER_WRONG_TABLE_NAME
+alter table t1 rename to ``;
+--error ER_WRONG_TABLE_NAME
+rename table t1 to ``;
+drop table t1;
+
+#
+# BUG#6236 - ALTER TABLE MODIFY should set implicit NOT NULL on PK columns
+#
+drop table if exists t1, t2;
+create table t1 ( a varchar(10) not null primary key ) engine=myisam;
+create table t2 ( a varchar(10) not null primary key ) engine=merge union=(t1);
+flush tables;
+alter table t1 modify a varchar(10);
+show create table t2;
+flush tables;
+alter table t1 modify a varchar(10) not null;
+show create table t2;
+drop table if exists t1, t2;
+
+# The following is also part of bug #6236 (CREATE TABLE didn't properly count
+# not null columns for primary keys)
+
+create table t1 (a int, b int, c int, d int, e int, f int, g int, h int,i int, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM;
+insert ignore into t1 (a) values(1);
+--replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X 19 X
+show table status like 't1';
+alter table t1 modify a int;
+--replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X 19 X
+show table status like 't1';
+drop table t1;
+create table t1 (a int not null, b int not null, c int not null, d int not null, e int not null, f int not null, g int not null, h int not null,i int not null, primary key (a,b,c,d,e,f,g,i,h)) engine=MyISAM;
+insert ignore into t1 (a) values(1);
+--replace_column 7 X 8 X 9 X 10 X 11 X 12 X 13 X 14 X 19 X
+show table status like 't1';
+drop table t1;
+
+#
+# Test that data get converted when character set is changed
+# Test that data doesn't get converted when src or dst is BINARY/BLOB
+#
+set names koi8r;
+create table t1 (a char(10) character set koi8r);
+insert into t1 values ('īŋŊīŋŊīŋŊīŋŊ');
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set cp1251;
+select a,hex(a) from t1;
+alter table t1 change a a binary(4);
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set cp1251;
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+alter table t1 change a a varchar(10) character set cp1251;
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+alter table t1 change a a text character set cp1251;
+select a,hex(a) from t1;
+alter table t1 change a a char(10) character set koi8r;
+select a,hex(a) from t1;
+delete from t1;
+
+#
+# Test ALTER TABLE .. CHARACTER SET ..
+#
+show create table t1;
+alter table t1 DEFAULT CHARACTER SET latin1;
+show create table t1;
+alter table t1 CONVERT TO CHARACTER SET latin1;
+show create table t1;
+alter table t1 DEFAULT CHARACTER SET cp1251;
+show create table t1;
+
+drop table t1;
+
+#
+# Bug#2821
+# Test that table CHARACTER SET does not affect blobs
+#
+create table t1 (myblob longblob,mytext longtext)
+default charset latin1 collate latin1_general_cs;
+show create table t1;
+alter table t1 character set latin2;
+show create table t1;
+drop table t1;
+
+#
+# Bug 2361 (Don't drop UNIQUE with DROP PRIMARY KEY)
+#
+
+CREATE TABLE t1 (a int PRIMARY KEY, b INT UNIQUE);
+ALTER TABLE t1 DROP PRIMARY KEY;
+SHOW CREATE TABLE t1;
+--error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t1 DROP PRIMARY KEY;
+DROP TABLE t1;
+
+# BUG#3899
+create table t1 (a int, b int, key(a));
+insert into t1 values (1,1), (2,2);
+--error ER_CANT_DROP_FIELD_OR_KEY
+alter table t1 drop key no_such_key;
+alter table t1 drop key a;
+drop table t1;
+
+#
+# BUG 12207 alter table ... discard table space on MyISAM table causes ERROR 2013 (HY000)
+#
+# Some platforms (Mac OS X, Windows) will send the error message using small letters.
+CREATE TABLE T12207(a int) ENGINE=MYISAM;
+--replace_result t12207 T12207
+--error ER_ILLEGAL_HA
+ALTER TABLE T12207 DISCARD TABLESPACE;
+DROP TABLE T12207;
+
+#
+# Bug #6479 ALTER TABLE ... changing charset fails for TEXT columns
+#
+# The column's character set was changed but the actual data was not
+# modified. In other words, the values were reinterpreted
+# as UTF8 instead of being converted.
+create table t1 (a text) character set koi8r;
+insert into t1 values (_koi8r'īŋŊīŋŊīŋŊīŋŊ');
+select hex(a) from t1;
+alter table t1 convert to character set cp1251;
+select hex(a) from t1;
+drop table t1;
+
+#
+# Test for bug #7884 "Able to add invalid unique index on TIMESTAMP prefix"
+# MySQL should not think that packed field with non-zero decimals is
+# geometry field and allow to create prefix index which is
+# shorter than packed field length.
+#
+create table t1 ( a timestamp );
+--error ER_WRONG_SUB_KEY
+alter table t1 add unique ( a(1) );
+drop table t1;
+
+#
+# Bug #24395: ALTER TABLE DISABLE KEYS doesn't work when modifying the table
+#
+# This problem happens if the data change is compatible.
+# Changing to the same type is compatible for example.
+#
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int, key(a));
+show indexes from t1;
+--echo "this used not to disable the index"
+alter table t1 modify a int, disable keys;
+show indexes from t1;
+
+alter table t1 enable keys;
+show indexes from t1;
+
+alter table t1 modify a bigint, disable keys;
+show indexes from t1;
+
+alter table t1 enable keys;
+show indexes from t1;
+
+alter table t1 add b char(10), disable keys;
+show indexes from t1;
+
+alter table t1 add c decimal(10,2), enable keys;
+show indexes from t1;
+
+--echo "this however did"
+alter table t1 disable keys;
+show indexes from t1;
+
+desc t1;
+
+alter table t1 add d decimal(15,5);
+--echo "The key should still be disabled"
+show indexes from t1;
+
+drop table t1;
+
+--echo "Now will test with one unique index"
+create table t1(a int, b char(10), unique(a));
+show indexes from t1;
+alter table t1 disable keys;
+show indexes from t1;
+alter table t1 enable keys;
+
+--echo "If no copy on noop change, this won't touch the data file"
+--echo "Unique index, no change"
+alter table t1 modify a int, disable keys;
+show indexes from t1;
+
+--echo "Change the type implying data copy"
+--echo "Unique index, no change"
+alter table t1 modify a bigint, disable keys;
+show indexes from t1;
+
+alter table t1 modify a bigint;
+show indexes from t1;
+
+alter table t1 modify a int;
+show indexes from t1;
+
+drop table t1;
+
+--echo "Now will test with one unique and one non-unique index"
+create table t1(a int, b char(10), unique(a), key(b));
+show indexes from t1;
+alter table t1 disable keys;
+show indexes from t1;
+alter table t1 enable keys;
+
+
+--echo "If no copy on noop change, this won't touch the data file"
+--echo "The non-unique index will be disabled"
+alter table t1 modify a int, disable keys;
+show indexes from t1;
+alter table t1 enable keys;
+show indexes from t1;
+
+--echo "Change the type implying data copy"
+--echo "The non-unique index will be disabled"
+alter table t1 modify a bigint, disable keys;
+show indexes from t1;
+
+--echo "Change again the type, but leave the indexes as_is"
+alter table t1 modify a int;
+show indexes from t1;
+--echo "Try the same. When data is no copied on similar tables, this is noop"
+alter table t1 modify a int;
+show indexes from t1;
+
+drop table t1;
+
+
+#
+# Bug#11493 - Alter table rename to default database does not work without
+# db name qualifying
+#
+create database mysqltest;
+create table t1 (c1 int);
+# Move table to other database.
+alter table t1 rename mysqltest.t1;
+# Assure that it has moved.
+--error ER_BAD_TABLE_ERROR
+drop table t1;
+# Move table back.
+alter table mysqltest.t1 rename t1;
+# Assure that it is back.
+drop table t1;
+# Now test for correct message if no database is selected.
+# Create t1 in 'test'.
+create table t1 (c1 int);
+# Change to other db.
+use mysqltest;
+# Drop the current db. This de-selects any db.
+drop database mysqltest;
+# Now test for correct message.
+--error ER_NO_DB_ERROR
+alter table test.t1 rename t1;
+# Check that explicit qualifying works even with no selected db.
+alter table test.t1 rename test.t1;
+# Go back to standard 'test' db.
+use test;
+drop table t1;
+
+#
+# BUG#23404 - ROW_FORMAT=FIXED option is lost is an index is added to the
+# table
+#
+CREATE TABLE t1(a INT) ROW_FORMAT=FIXED;
+CREATE INDEX i1 ON t1(a);
+SHOW CREATE TABLE t1;
+DROP INDEX i1 ON t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+#
+# Bug#24219 - ALTER TABLE ... RENAME TO ... , DISABLE KEYS leads to crash
+#
+--disable_warnings
+DROP TABLE IF EXISTS bug24219;
+DROP TABLE IF EXISTS bug24219_2;
+--enable_warnings
+
+CREATE TABLE bug24219 (a INT, INDEX(a));
+
+SHOW INDEX FROM bug24219;
+
+ALTER TABLE bug24219 RENAME TO bug24219_2, DISABLE KEYS;
+
+SHOW INDEX FROM bug24219_2;
+
+DROP TABLE bug24219_2;
+
+#
+# Bug#24562 (ALTER TABLE ... ORDER BY ... with complex expression asserts)
+#
+
+--disable_warnings
+drop table if exists table_24562;
+--enable_warnings
+
+create table table_24562(
+ section int,
+ subsection int,
+ title varchar(50));
+
+insert into table_24562 values
+(1, 0, "Introduction"),
+(1, 1, "Authors"),
+(1, 2, "Acknowledgements"),
+(2, 0, "Basics"),
+(2, 1, "Syntax"),
+(2, 2, "Client"),
+(2, 3, "Server"),
+(3, 0, "Intermediate"),
+(3, 1, "Complex queries"),
+(3, 2, "Stored Procedures"),
+(3, 3, "Stored Functions"),
+(4, 0, "Advanced"),
+(4, 1, "Replication"),
+(4, 2, "Load balancing"),
+(4, 3, "High availability"),
+(5, 0, "Conclusion");
+
+select * from table_24562;
+
+alter table table_24562 add column reviewer varchar(20),
+order by title;
+
+select * from table_24562;
+
+update table_24562 set reviewer="Me" where section=2;
+update table_24562 set reviewer="You" where section=3;
+
+alter table table_24562
+order by section ASC, subsection DESC;
+
+select * from table_24562;
+
+alter table table_24562
+order by table_24562.subsection ASC, table_24562.section DESC;
+
+select * from table_24562;
+
+--error ER_PARSE_ERROR
+alter table table_24562 order by 12;
+--error ER_PARSE_ERROR
+alter table table_24562 order by (section + 12);
+--error ER_PARSE_ERROR
+alter table table_24562 order by length(title);
+--error ER_PARSE_ERROR
+alter table table_24562 order by (select 12 from dual);
+
+--error ER_BAD_FIELD_ERROR
+alter table table_24562 order by no_such_col;
+
+drop table table_24562;
+
+# End of 4.1 tests
+
+#
+# Bug #14693 (ALTER SET DEFAULT doesn't work)
+#
+
+create table t1 (mycol int(10) not null);
+alter table t1 alter column mycol set default 0;
+desc t1;
+drop table t1;
+
+#
+# Bug#25262 Auto Increment lost when changing Engine type
+#
+
+create table t1(id int(8) primary key auto_increment) engine=heap;
+
+insert into t1 values (null);
+insert into t1 values (null);
+
+select * from t1;
+
+# Set auto increment to 50
+alter table t1 auto_increment = 50;
+
+# Alter to myisam
+alter table t1 engine = myisam;
+
+# This insert should get id 50
+insert into t1 values (null);
+select * from t1;
+
+# Alter to heap again
+alter table t1 engine = heap;
+insert into t1 values (null);
+select * from t1;
+
+drop table t1;
+
+#
+# Bug#27507: Wrong DATETIME value was allowed by ALTER TABLE in the
+# NO_ZERO_DATE mode.
+#
+set @orig_sql_mode = @@sql_mode;
+set sql_mode="no_zero_date";
+create table t1(f1 int);
+alter table t1 add column f2 datetime not null, add column f21 date not null;
+insert into t1 values(1,'2000-01-01','2000-01-01');
+--error 1292
+alter table t1 add column f3 datetime not null;
+--error 1292
+alter table t1 add column f3 date not null;
+--error 1292
+alter table t1 add column f4 datetime not null default '2002-02-02',
+ add column f41 date not null;
+alter table t1 add column f4 datetime not null default '2002-02-02',
+ add column f41 date not null default '2002-02-02';
+select * from t1;
+drop table t1;
+set sql_mode= @orig_sql_mode;
+
+#
+# Some additional tests for new, faster alter table. Note that most of the
+# whole alter table code is being tested all around the test suite already.
+#
+
+create table t1 (v varchar(32));
+insert into t1 values ('def'),('abc'),('hij'),('3r4f');
+select * from t1;
+# Fast alter, no copy performed
+alter table t1 change v v2 varchar(32);
+select * from t1;
+# Fast alter, no copy performed
+alter table t1 change v2 v varchar(64);
+select * from t1;
+update t1 set v = 'lmn' where v = 'hij';
+select * from t1;
+# Regular alter table
+alter table t1 add i int auto_increment not null primary key first;
+select * from t1;
+update t1 set i=5 where i=3;
+select * from t1;
+alter table t1 change i i bigint;
+select * from t1;
+alter table t1 add unique key (i, v);
+select * from t1 where i between 2 and 4 and v in ('def','3r4f','lmn');
+drop table t1;
+
+#
+# Bug#6073 "ALTER table minor glich": ALTER TABLE complains that an index
+# without # prefix is not allowed for TEXT columns, while index
+# is defined with prefix.
+#
+create table t1 (t varchar(255) default null, key t (t(80)))
+engine=myisam default charset=latin1;
+alter table t1 change t t text;
+drop table t1;
+
+#
+# Bug #26794: Adding an index with a prefix on a SPATIAL type breaks ALTER
+# TABLE
+#
+CREATE TABLE t1 (a varchar(500));
+
+ALTER TABLE t1 ADD b GEOMETRY NOT NULL, ADD SPATIAL INDEX(b);
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 ADD KEY(b(50));
+SHOW CREATE TABLE t1;
+
+ALTER TABLE t1 ADD c POINT;
+SHOW CREATE TABLE t1;
+
+--error ER_WRONG_SUB_KEY
+CREATE TABLE t2 (a INT, KEY (a(20)));
+
+ALTER TABLE t1 ADD d INT;
+--error ER_WRONG_SUB_KEY
+ALTER TABLE t1 ADD KEY (d(20));
+
+# the 5.1 part of the test
+--error ER_WRONG_SUB_KEY
+ALTER TABLE t1 ADD e GEOMETRY NOT NULL, ADD SPATIAL KEY (e(30));
+
+DROP TABLE t1;
+
+#
+# Bug#18038 MySQL server corrupts binary columns data
+#
+
+CREATE TABLE t1 (s CHAR(8) BINARY);
+INSERT INTO t1 VALUES ('test');
+SELECT LENGTH(s) FROM t1;
+ALTER TABLE t1 MODIFY s CHAR(10) BINARY;
+SELECT LENGTH(s) FROM t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (s BINARY(8));
+INSERT INTO t1 VALUES ('test');
+SELECT LENGTH(s) FROM t1;
+SELECT HEX(s) FROM t1;
+ALTER TABLE t1 MODIFY s BINARY(10);
+SELECT HEX(s) FROM t1;
+SELECT LENGTH(s) FROM t1;
+DROP TABLE t1;
+
+#
+# Bug#19386: Multiple alter causes crashed table
+# The trailing column would get corrupted data, or server could not even read
+# it.
+#
+
+CREATE TABLE t1 (v VARCHAR(3), b INT);
+INSERT INTO t1 VALUES ('abc', 5);
+SELECT * FROM t1;
+ALTER TABLE t1 MODIFY COLUMN v VARCHAR(4);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+
+#
+# Bug#31291 ALTER TABLE CONVERT TO CHARACTER SET does not change some data types
+#
+create table t1 (a tinytext character set latin1);
+alter table t1 convert to character set utf8;
+show create table t1;
+drop table t1;
+create table t1 (a mediumtext character set latin1);
+alter table t1 convert to character set utf8;
+show create table t1;
+drop table t1;
+
+--echo End of 5.0 tests
+
+#
+# Extended test coverage for ALTER TABLE behaviour under LOCK TABLES
+# It should be consistent across all platforms and for all engines
+# (Before 5.1 this was not true as behavior was different between
+# Unix/Windows and transactional/non-transactional tables).
+# See also innodb_mysql.test
+#
+--disable_warnings
+drop table if exists t1, t2, t3;
+--enable_warnings
+create table t1 (i int);
+create table t3 (j int);
+insert into t1 values ();
+insert into t3 values ();
+# Table which is altered under LOCK TABLES it should stay in list of locked
+# tables and be available after alter takes place unless ALTER contains RENAME
+# clause. We should see the new definition of table, of course.
+lock table t1 write, t3 read;
+# Example of so-called 'fast' ALTER TABLE
+alter table t1 modify i int default 1;
+insert into t1 values ();
+select * from t1;
+# And now full-blown ALTER TABLE
+alter table t1 change i c char(10) default "Two";
+insert into t1 values ();
+select * from t1;
+# If table is renamed then it should be removed from the list
+# of locked tables. 'Fast' ALTER TABLE with RENAME clause:
+alter table t1 modify c char(10) default "Three", rename to t2;
+--error ER_TABLE_NOT_LOCKED
+select * from t1;
+--error ER_TABLE_NOT_LOCKED
+select * from t2;
+select * from t3;
+unlock tables;
+insert into t2 values ();
+select * from t2;
+lock table t2 write, t3 read;
+# Full ALTER TABLE with RENAME
+alter table t2 change c vc varchar(100) default "Four", rename to t1;
+--error ER_TABLE_NOT_LOCKED
+select * from t1;
+--error ER_TABLE_NOT_LOCKED
+select * from t2;
+select * from t3;
+unlock tables;
+insert into t1 values ();
+select * from t1;
+drop tables t1, t3;
+
+
+#
+# Bug#18775 - Temporary table from alter table visible to other threads
+#
+# Check if special characters work and duplicates are detected.
+--disable_warnings
+DROP TABLE IF EXISTS `t+1`, `t+2`;
+--enable_warnings
+CREATE TABLE `t+1` (c1 INT);
+ALTER TABLE `t+1` RENAME `t+2`;
+CREATE TABLE `t+1` (c1 INT);
+--error ER_TABLE_EXISTS_ERROR
+ALTER TABLE `t+1` RENAME `t+2`;
+DROP TABLE `t+1`, `t+2`;
+#
+# Same for temporary tables though these names do not become file names.
+CREATE TEMPORARY TABLE `tt+1` (c1 INT);
+ALTER TABLE `tt+1` RENAME `tt+2`;
+CREATE TEMPORARY TABLE `tt+1` (c1 INT);
+--error ER_TABLE_EXISTS_ERROR
+ALTER TABLE `tt+1` RENAME `tt+2`;
+SHOW CREATE TABLE `tt+1`;
+SHOW CREATE TABLE `tt+2`;
+DROP TABLE `tt+1`, `tt+2`;
+#
+# Check if special characters as in tmp_file_prefix work.
+CREATE TABLE `#sql1` (c1 INT);
+CREATE TABLE `@0023sql2` (c1 INT);
+SHOW TABLES;
+RENAME TABLE `#sql1` TO `@0023sql1`;
+RENAME TABLE `@0023sql2` TO `#sql2`;
+SHOW TABLES;
+ALTER TABLE `@0023sql1` RENAME `#sql-1`;
+ALTER TABLE `#sql2` RENAME `@0023sql-2`;
+SHOW TABLES;
+INSERT INTO `#sql-1` VALUES (1);
+INSERT INTO `@0023sql-2` VALUES (2);
+DROP TABLE `#sql-1`, `@0023sql-2`;
+#
+# Same for temporary tables though these names do not become file names.
+CREATE TEMPORARY TABLE `#sql1` (c1 INT);
+CREATE TEMPORARY TABLE `@0023sql2` (c1 INT);
+SHOW TABLES;
+ALTER TABLE `#sql1` RENAME `@0023sql1`;
+ALTER TABLE `@0023sql2` RENAME `#sql2`;
+SHOW TABLES;
+INSERT INTO `#sql2` VALUES (1);
+INSERT INTO `@0023sql1` VALUES (2);
+SHOW CREATE TABLE `#sql2`;
+SHOW CREATE TABLE `@0023sql1`;
+DROP TABLE `#sql2`, `@0023sql1`;
+
+#
+# Bug #22369: Alter table rename combined with other alterations causes lost tables
+#
+# This problem happens if the data change is compatible.
+# Changing to the same type is compatible for example.
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+--enable_warnings
+CREATE TABLE t1 (
+ int_field INTEGER UNSIGNED NOT NULL,
+ char_field CHAR(10),
+ INDEX(`int_field`)
+);
+
+DESCRIBE t1;
+
+SHOW INDEXES FROM t1;
+
+INSERT INTO t1 VALUES (1, "edno"), (1, "edno"), (2, "dve"), (3, "tri"), (5, "pet");
+--echo "Non-copy data change - new frm, but old data and index files"
+ALTER TABLE t1
+ CHANGE int_field unsigned_int_field INTEGER UNSIGNED NOT NULL,
+ RENAME t2;
+
+--error ER_NO_SUCH_TABLE
+SELECT * FROM t1 ORDER BY int_field;
+SELECT * FROM t2 ORDER BY unsigned_int_field;
+DESCRIBE t2;
+DESCRIBE t2;
+ALTER TABLE t2 MODIFY unsigned_int_field BIGINT UNSIGNED NOT NULL;
+DESCRIBE t2;
+
+DROP TABLE t2;
+
+#
+# Bug#28427: Columns were renamed instead of moving by ALTER TABLE.
+#
+CREATE TABLE t1 (f1 INT, f2 INT, f3 INT);
+INSERT INTO t1 VALUES (1, 2, NULL);
+SELECT * FROM t1;
+ALTER TABLE t1 MODIFY COLUMN f3 INT AFTER f1;
+SELECT * FROM t1;
+ALTER TABLE t1 MODIFY COLUMN f3 INT AFTER f2;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# BUG#29957 - alter_table.test fails
+#
+create table t1 (c char(10) default "Two");
+lock table t1 write;
+insert into t1 values ();
+alter table t1 modify c char(10) default "Three";
+unlock tables;
+select * from t1;
+check table t1;
+drop table t1;
+
+#
+# Bug#33873: Fast ALTER TABLE doesn't work with multibyte character sets
+#
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TABLE t1 (id int, c int) character set latin1;
+INSERT INTO t1 VALUES (1,1);
+--enable_info
+ALTER TABLE t1 CHANGE c d int;
+ALTER TABLE t1 CHANGE d c int;
+ALTER TABLE t1 MODIFY c VARCHAR(10);
+ALTER TABLE t1 CHANGE c d varchar(10);
+ALTER TABLE t1 CHANGE d c varchar(10);
+--disable_info
+DROP TABLE t1;
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TABLE t1 (id int, c int) character set utf8;
+INSERT INTO t1 VALUES (1,1);
+--enable_info
+ALTER TABLE t1 CHANGE c d int;
+ALTER TABLE t1 CHANGE d c int;
+ALTER TABLE t1 MODIFY c VARCHAR(10);
+ALTER TABLE t1 CHANGE c d varchar(10);
+ALTER TABLE t1 CHANGE d c varchar(10);
+--disable_info
+DROP TABLE t1;
+
+#
+# Bug#39372 "Smart" ALTER TABLE not so smart after all.
+#
+create table t1(f1 int not null, f2 int not null, key (f1), key (f2));
+let $count= 50;
+--disable_query_log
+begin;
+while ($count)
+{
+ EVAL insert into t1 values (1,1),(1,1),(1,1),(1,1),(1,1);
+ EVAL insert into t1 values (2,2),(2,2),(2,2),(2,2),(2,2);
+ dec $count ;
+}
+commit;
+--enable_query_log
+
+select index_length into @unpaked_keys_size from
+information_schema.tables where table_name='t1';
+alter table t1 pack_keys=1;
+select index_length into @paked_keys_size from
+information_schema.tables where table_name='t1';
+select (@unpaked_keys_size > @paked_keys_size);
+
+select max_data_length into @orig_max_data_length from
+information_schema.tables where table_name='t1';
+alter table t1 max_rows=100;
+select max_data_length into @changed_max_data_length from
+information_schema.tables where table_name='t1';
+select (@orig_max_data_length > @changed_max_data_length);
+
+drop table t1;
+
+#
+# Bug #23113: Different behavior on altering ENUM fields between 5.0 and 5.1
+#
+CREATE TABLE t1(a INT AUTO_INCREMENT PRIMARY KEY,
+ b ENUM('a', 'b', 'c') NOT NULL);
+INSERT INTO t1 (b) VALUES ('a'), ('c'), ('b'), ('b'), ('a');
+ALTER TABLE t1 MODIFY b ENUM('a', 'z', 'b', 'c') NOT NULL;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Test for ALTER column DROP DEFAULT
+#
+
+SET @save_sql_mode=@@sql_mode;
+SET sql_mode=strict_all_tables;
+
+CREATE TABLE t1 (a int NOT NULL default 42);
+INSERT INTO t1 values ();
+SELECT * FROM t1;
+ALTER TABLE t1 ALTER COLUMN a DROP DEFAULT;
+--error 1364
+INSERT INTO t1 values ();
+INSERT INTO t1 (a) VALUES (11);
+SELECT * FROM t1 ORDER BY a;
+DROP TABLE t1;
+SET @@sql_mode=@save_sql_mode;
+--echo #
+--echo # Bug#45567: Fast ALTER TABLE broken for enum and set
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (a ENUM('a1','a2'));
+INSERT INTO t1 VALUES ('a1'),('a2');
+--enable_info
+--echo # No copy: No modification
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2');
+--echo # No copy: Add new enumeration to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a3');
+--echo # Copy: Modify and add new to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx','a5');
+--echo # Copy: Remove from the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','xx');
+--echo # Copy: Add new enumeration
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx');
+--echo # No copy: Add new enumerations to the end
+ALTER TABLE t1 MODIFY COLUMN a ENUM('a1','a2','a0','xx','a5','a6');
+--disable_info
+DROP TABLE t1;
+
+CREATE TABLE t1 (a SET('a1','a2'));
+INSERT INTO t1 VALUES ('a1'),('a2');
+--enable_info
+--echo # No copy: No modification
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2');
+--echo # No copy: Add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a3');
+--echo # Copy: Modify and add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx','a5');
+--echo # Copy: Remove from the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','xx');
+--echo # Copy: Add new member
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx');
+--echo # No copy: Add new to the end
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6');
+--echo # Copy: Numerical incrase (pack lenght)
+ALTER TABLE t1 MODIFY COLUMN a SET('a1','a2','a0','xx','a5','a6','a7','a8','a9','a10');
+--disable_info
+DROP TABLE t1;
+
+#
+# Bug#43508: Renaming timestamp or date column triggers table copy
+#
+
+CREATE TABLE t1 (f1 TIMESTAMP NULL DEFAULT NULL,
+ f2 INT(11) DEFAULT NULL) ENGINE=MYISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO t1 VALUES (NULL, NULL), ("2009-10-09 11:46:19", 2);
+
+--echo this should affect no rows as there is no real change
+--enable_info
+ALTER TABLE t1 CHANGE COLUMN f1 f1_no_real_change TIMESTAMP NULL DEFAULT NULL;
+--disable_info
+DROP TABLE t1;
+
+
+--echo #
+--echo # Bug #31145: ALTER TABLE DROP COLUMN, ADD COLUMN crashes (linux)
+--echo # or freezes (win) the server
+--echo #
+
+CREATE TABLE t1 (a TEXT, id INT, b INT);
+ALTER TABLE t1 DROP COLUMN a, ADD COLUMN c TEXT FIRST;
+
+DROP TABLE t1;
+
+
+--echo #
+--echo # Test for bug #12652385 - "61493: REORDERING COLUMNS TO POSITION
+--echo # FIRST CAN CAUSE DATA TO BE CORRUPTED".
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+--echo # Use MyISAM engine as the fact that InnoDB doesn't support
+--echo # in-place ALTER TABLE in cases when columns are being renamed
+--echo # hides some bugs.
+create table t1 (i int, j int) engine=myisam;
+insert into t1 value (1, 2);
+--echo # First, test for original problem described in the bug report.
+select * from t1;
+--echo # Change of column order by the below ALTER TABLE statement should
+--echo # affect both column names and column contents.
+alter table t1 modify column j int first;
+select * from t1;
+--echo # Now test for similar problem with the same root.
+--echo # The below ALTER TABLE should change not only the name but
+--echo # also the value for the last column of the table.
+alter table t1 drop column i, add column k int default 0;
+select * from t1;
+--echo # Clean-up.
+drop table t1;
+
+
+--echo End of 5.1 tests
+
+#
+# Bug #31031 ALTER TABLE regression in 5.0
+#
+# The ALTER TABLE operation failed with
+# ERROR 1089 (HY000): Incorrect sub part key; ...
+#
+CREATE TABLE t1(c CHAR(10),
+ i INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY);
+INSERT INTO t1 VALUES('a',2),('b',4),('c',6);
+ALTER TABLE t1
+ DROP i,
+ ADD i INT UNSIGNED NOT NULL AUTO_INCREMENT,
+ AUTO_INCREMENT = 1;
+DROP TABLE t1;
+
+
+#
+# Bug#50542 5.5.x doesn't check length of key prefixes:
+# corruption and crash results
+#
+# This case is related to Bug#31031 (above)
+# A statement where the index key is larger/wider than
+# the column type, should cause an error
+#
+--error ER_WRONG_SUB_KEY
+CREATE TABLE t1 (a CHAR(1), PRIMARY KEY (a(255)));
+
+# Test other variants of creating indices
+CREATE TABLE t1 (a CHAR(1));
+# ALTER TABLE
+--error ER_WRONG_SUB_KEY
+ALTER TABLE t1 ADD PRIMARY KEY (a(20));
+--error ER_WRONG_SUB_KEY
+ALTER TABLE t1 ADD KEY (a(20));
+# CREATE INDEX
+--error ER_WRONG_SUB_KEY
+CREATE UNIQUE INDEX i1 ON t1 (a(20));
+--error ER_WRONG_SUB_KEY
+CREATE INDEX i2 ON t1 (a(20));
+# cleanup
+DROP TABLE t1;
+
+
+#
+# Bug #45052 ALTER TABLE ADD COLUMN crashes server with multiple foreign key columns
+# The alter table fails if 2 or more new fields added and
+# also added a key with these fields
+#
+CREATE TABLE t1 (id int);
+INSERT INTO t1 VALUES (1), (2);
+ALTER TABLE t1 ADD COLUMN (f1 INT), ADD COLUMN (f2 INT), ADD KEY f2k(f2);
+DROP TABLE t1;
+
+
+--echo #
+--echo # Test for bug #53820 "ALTER a MEDIUMINT column table causes full
+--echo # table copy".
+--echo #
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TABLE t1 (a INT, b MEDIUMINT);
+INSERT INTO t1 VALUES (1, 1), (2, 2);
+--echo # The below ALTER should not copy table and so no rows should
+--echo # be shown as affected.
+--enable_info
+ALTER TABLE t1 CHANGE a id INT;
+--disable_info
+DROP TABLE t1;
+
+
+--echo #
+--echo # Bug#11754461 CANNOT ALTER TABLE WHEN KEY PREFIX TOO LONG
+--echo #
+
+--disable_warnings
+DROP DATABASE IF EXISTS db1;
+--enable_warnings
+
+CREATE DATABASE db1 CHARACTER SET utf8;
+CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
+ALTER TABLE db1.t1 ADD baz INT;
+
+DROP DATABASE db1;
+
+
+--echo # Additional coverage for refactoring which is made as part
+--echo # of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+--echo # to allow temp table operations".
+--echo #
+--echo # At some point the below test case failed on assertion.
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TEMPORARY TABLE t1 (i int) ENGINE=MyISAM;
+
+--error ER_ILLEGAL_HA
+ALTER TABLE t1 DISCARD TABLESPACE;
+
+DROP TABLE t1;
+
+
+--echo #
+--echo # Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
+--echo # CLAUSE FAILS OR ABORTS SERVER.
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2';
+execute stmt1;
+rename table t2 to t1;
+--echo # The below statement should succeed and not emit error or abort server.
+execute stmt1;
+deallocate prepare stmt1;
+drop table t2;
+
+--echo #
+--echo # MDEV-8960 Can't refer the same column twice in one ALTER TABLE
+--echo #
+
+CREATE TABLE t1 (
+ `a` int(11) DEFAULT NULL
+) DEFAULT CHARSET=utf8;
+
+ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL,
+ALTER COLUMN `consultant_id` DROP DEFAULT;
+
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ `a` int(11) DEFAULT NULL
+) DEFAULT CHARSET=utf8;
+
+ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL,
+ALTER COLUMN `consultant_id` SET DEFAULT 2;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ `a` int(11) DEFAULT NULL
+) DEFAULT CHARSET=utf8;
+
+ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL DEFAULT 2,
+ALTER COLUMN `consultant_id` DROP DEFAULT;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ `a` int(11) DEFAULT NULL
+) DEFAULT CHARSET=utf8;
+
+ALTER TABLE t1 ADD COLUMN `consultant_id` integer NOT NULL DEFAULT 2,
+ALTER COLUMN `consultant_id` DROP DEFAULT,
+MODIFY COLUMN `consultant_id` BIGINT;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+#
+# Test of ALTER TABLE IF [NOT] EXISTS
+#
+
+CREATE TABLE t1 (
+ id INT(11) NOT NULL,
+ x_param INT(11) DEFAULT NULL,
+ PRIMARY KEY (id)
+) ENGINE=MYISAM;
+
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS id INT,
+ ADD COLUMN IF NOT EXISTS lol INT AFTER id;
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS lol INT AFTER id;
+ALTER TABLE t1 DROP COLUMN IF EXISTS lol;
+ALTER TABLE t1 DROP COLUMN IF EXISTS lol;
+
+ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param);
+ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param);
+ALTER TABLE t1 MODIFY IF EXISTS lol INT;
+
+DROP INDEX IF EXISTS x_param ON t1;
+DROP INDEX IF EXISTS x_param ON t1;
+CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param);
+CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ id INT(11) NOT NULL,
+ x_param INT(11) DEFAULT NULL,
+ PRIMARY KEY (id)
+) ENGINE=INNODB;
+
+CREATE TABLE t2 (
+ id INT(11) NOT NULL) ENGINE=INNODB;
+
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS id INT,
+ ADD COLUMN IF NOT EXISTS lol INT AFTER id;
+ALTER TABLE t1 ADD COLUMN IF NOT EXISTS lol INT AFTER id;
+ALTER TABLE t1 DROP COLUMN IF EXISTS lol;
+ALTER TABLE t1 DROP COLUMN IF EXISTS lol;
+
+ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param);
+ALTER TABLE t1 ADD KEY IF NOT EXISTS x_param(x_param);
+ALTER TABLE t1 MODIFY IF EXISTS lol INT;
+
+DROP INDEX IF EXISTS x_param ON t1;
+DROP INDEX IF EXISTS x_param ON t1;
+CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param);
+CREATE INDEX IF NOT EXISTS x_param1 ON t1(x_param);
+SHOW CREATE TABLE t1;
+
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS fk(id) REFERENCES t1(id);
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS fk(id) REFERENCES t1(id);
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk;
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS fk;
+SHOW CREATE TABLE t2;
+ALTER TABLE t2 ADD FOREIGN KEY (id) REFERENCES t1(id);
+ALTER TABLE t2 ADD FOREIGN KEY IF NOT EXISTS t2_ibfk_1(id) REFERENCES t1(id);
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
+ALTER TABLE t2 DROP FOREIGN KEY IF EXISTS t2_ibfk_1;
+SHOW CREATE TABLE t2;
+
+DROP TABLE t2;
+CREATE TABLE t2 (
+ id INT(11) NOT NULL);
+ALTER TABLE t2 ADD COLUMN a INT, ADD COLUMN IF NOT EXISTS a INT;
+ALTER TABLE t2 ADD KEY k_id(id), ADD KEY IF NOT EXISTS k_id(id);
+SHOW CREATE TABLE t2;
+ALTER TABLE t2 DROP KEY k_id, DROP KEY IF EXISTS k_id;
+ALTER TABLE t2 DROP COLUMN a, DROP COLUMN IF EXISTS a;
+SHOW CREATE TABLE t2;
+
+DROP TABLE t2;
+DROP TABLE t1;
+
+CREATE TABLE t1 (
+ `transaction_id` int(11) NOT NULL DEFAULT '0',
+ KEY `transaction_id` (`transaction_id`));
+ALTER TABLE t1 DROP KEY IF EXISTS transaction_id, ADD PRIMARY KEY IF NOT EXISTS (transaction_id);
+SHOW CREATE TABLE t1;
+
+DROP TABLE t1;
+
+--echo # Bug#11748057 (formerly known as 34972): ALTER TABLE statement doesn't
+--echo # identify correct column name.
+--echo #
+
+CREATE TABLE t1 (c1 int unsigned , c2 char(100) not null default '');
+ALTER TABLE t1 ADD c3 char(16) NOT NULL DEFAULT '' AFTER c2,
+ MODIFY c2 char(100) NOT NULL DEFAULT '' AFTER c1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # WL#5534 Online ALTER, Phase 1
+--echo #
+
+--echo # Single thread tests.
+--echo # See innodb_mysql_sync.test for multi thread tests.
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1(a INT PRIMARY KEY, b INT) engine=InnoDB;
+CREATE TABLE m1(a INT PRIMARY KEY, b INT) engine=MyISAM;
+INSERT INTO t1 VALUES (1,1), (2,2);
+INSERT INTO m1 VALUES (1,1), (2,2);
+
+--echo #
+--echo # 1: Test ALGORITHM keyword
+--echo #
+
+--echo # --enable_info allows us to see how many rows were updated
+--echo # by ALTER TABLE. in-place will show 0 rows, while copy > 0.
+
+--enable_info
+ALTER TABLE t1 ADD INDEX i1(b);
+ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= DEFAULT;
+ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= COPY;
+ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= INPLACE;
+--error ER_UNKNOWN_ALTER_ALGORITHM
+ALTER TABLE t1 ADD INDEX i5(b), ALGORITHM= INVALID;
+
+ALTER TABLE m1 ENABLE KEYS;
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= DEFAULT;
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY;
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE;
+--disable_info
+
+ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4;
+
+--echo #
+--echo # 2: Test ALGORITHM + old_alter_table
+--echo #
+
+--enable_info
+SET SESSION old_alter_table= 1;
+ALTER TABLE t1 ADD INDEX i1(b);
+ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= DEFAULT;
+ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= COPY;
+ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= INPLACE;
+SET SESSION old_alter_table= 0;
+--disable_info
+
+ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4;
+
+--echo #
+--echo # 3: Test unsupported in-place operation
+--echo #
+
+ALTER TABLE t1 ADD COLUMN (c1 INT);
+ALTER TABLE t1 ADD COLUMN (c2 INT), ALGORITHM= DEFAULT;
+ALTER TABLE t1 ADD COLUMN (c3 INT), ALGORITHM= COPY;
+ALTER TABLE t1 ADD COLUMN (c4 INT), ALGORITHM= INPLACE;
+
+ALTER TABLE t1 DROP COLUMN c1, DROP COLUMN c2, DROP COLUMN c3, DROP COLUMN c4;
+
+--echo #
+--echo # 4: Test LOCK keyword
+--echo #
+
+--enable_info
+ALTER TABLE t1 ADD INDEX i1(b), LOCK= DEFAULT;
+ALTER TABLE t1 ADD INDEX i2(b), LOCK= NONE;
+ALTER TABLE t1 ADD INDEX i3(b), LOCK= SHARED;
+ALTER TABLE t1 ADD INDEX i4(b), LOCK= EXCLUSIVE;
+--error ER_UNKNOWN_ALTER_LOCK
+ALTER TABLE t1 ADD INDEX i5(b), LOCK= INVALID;
+--disable_info
+
+ALTER TABLE m1 ENABLE KEYS, LOCK= DEFAULT;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE m1 ENABLE KEYS, LOCK= NONE;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE m1 ENABLE KEYS, LOCK= SHARED;
+ALTER TABLE m1 ENABLE KEYS, LOCK= EXCLUSIVE;
+
+ALTER TABLE t1 DROP INDEX i1, DROP INDEX i2, DROP INDEX i3, DROP INDEX i4;
+
+--echo #
+--echo # 5: Test ALGORITHM + LOCK
+--echo #
+
+--enable_info
+ALTER TABLE t1 ADD INDEX i1(b), ALGORITHM= INPLACE, LOCK= NONE;
+ALTER TABLE t1 ADD INDEX i2(b), ALGORITHM= INPLACE, LOCK= SHARED;
+ALTER TABLE t1 ADD INDEX i3(b), ALGORITHM= INPLACE, LOCK= EXCLUSIVE;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+ALTER TABLE t1 ADD INDEX i4(b), ALGORITHM= COPY, LOCK= NONE;
+ALTER TABLE t1 ADD INDEX i5(b), ALGORITHM= COPY, LOCK= SHARED;
+ALTER TABLE t1 ADD INDEX i6(b), ALGORITHM= COPY, LOCK= EXCLUSIVE;
+
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= NONE;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= SHARED;
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= INPLACE, LOCK= EXCLUSIVE;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= NONE;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+ALTER ONLINE TABLE m1 ADD COLUMN c int;
+# This works because the lock will be SNW for the copy phase.
+# It will still require exclusive lock for actually enabling keys.
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= SHARED;
+ALTER TABLE m1 ENABLE KEYS, ALGORITHM= COPY, LOCK= EXCLUSIVE;
+--disable_info
+
+DROP TABLE t1, m1;
+
+--echo #
+--echo # 6: Possible deadlock involving thr_lock.c
+--echo #
+
+CREATE TABLE t1(a INT PRIMARY KEY, b INT);
+INSERT INTO t1 VALUES (1,1), (2,2);
+
+START TRANSACTION;
+INSERT INTO t1 VALUES (3,3);
+
+connect (con1, localhost, root);
+--echo # Sending:
+--send ALTER TABLE t1 DISABLE KEYS
+
+connection default;
+--echo # Waiting until ALTER TABLE is blocked.
+let $wait_condition=
+ SELECT COUNT(*) = 1 FROM information_schema.processlist
+ WHERE state = "Waiting for table metadata lock" AND
+ info = "ALTER TABLE t1 DISABLE KEYS";
+--source include/wait_condition.inc
+UPDATE t1 SET b = 4;
+COMMIT;
+
+connection con1;
+--echo # Reaping: ALTER TABLE t1 DISABLE KEYS
+--reap
+disconnect con1;
+--source include/wait_until_disconnected.inc
+
+connection default;
+DROP TABLE t1;
+
+--echo #
+--echo # 7: Which operations require copy and which can be done in-place?
+--echo #
+--echo # Test which ALTER TABLE operations are done in-place and
+--echo # which operations are done using temporary table copy.
+--echo #
+--echo # --enable_info allows us to see how many rows were updated
+--echo # by ALTER TABLE. in-place will show 0 rows, while copy > 0.
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS ti1, ti2, ti3, tm1, tm2, tm3;
+--enable_warnings
+
+--echo # Single operation tests
+
+CREATE TABLE ti1(a INT NOT NULL, b INT, c INT) engine=InnoDB;
+CREATE TABLE tm1(a INT NOT NULL, b INT, c INT) engine=MyISAM;
+CREATE TABLE ti2(a INT PRIMARY KEY AUTO_INCREMENT, b INT, c INT) engine=InnoDB;
+CREATE TABLE tm2(a INT PRIMARY KEY AUTO_INCREMENT, b INT, c INT) engine=MyISAM;
+INSERT INTO ti1 VALUES (1,1,1), (2,2,2);
+INSERT INTO ti2 VALUES (1,1,1), (2,2,2);
+INSERT INTO tm1 VALUES (1,1,1), (2,2,2);
+INSERT INTO tm2 VALUES (1,1,1), (2,2,2);
+
+--enable_info
+ALTER TABLE ti1;
+ALTER TABLE tm1;
+
+ALTER TABLE ti1 ADD COLUMN d VARCHAR(200);
+ALTER TABLE tm1 ADD COLUMN d VARCHAR(200);
+ALTER TABLE ti1 ADD COLUMN d2 VARCHAR(200);
+ALTER TABLE tm1 ADD COLUMN d2 VARCHAR(200);
+ALTER TABLE ti1 ADD COLUMN e ENUM('a', 'b') FIRST;
+ALTER TABLE tm1 ADD COLUMN e ENUM('a', 'b') FIRST;
+ALTER TABLE ti1 ADD COLUMN f INT AFTER a;
+ALTER TABLE tm1 ADD COLUMN f INT AFTER a;
+
+ALTER TABLE ti1 ADD INDEX ii1(b);
+ALTER TABLE tm1 ADD INDEX im1(b);
+ALTER TABLE ti1 ADD UNIQUE INDEX ii2 (c);
+ALTER TABLE tm1 ADD UNIQUE INDEX im2 (c);
+ALTER TABLE ti1 ADD FULLTEXT INDEX ii3 (d);
+ALTER TABLE tm1 ADD FULLTEXT INDEX im3 (d);
+ALTER TABLE ti1 ADD FULLTEXT INDEX ii4 (d2);
+ALTER TABLE tm1 ADD FULLTEXT INDEX im4 (d2);
+
+# Bug#14140038 INCONSISTENT HANDLING OF FULLTEXT INDEXES IN ALTER TABLE
+--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
+ALTER TABLE ti1 ADD PRIMARY KEY(a), ALGORITHM=INPLACE;
+ALTER TABLE ti1 ADD PRIMARY KEY(a);
+ALTER TABLE tm1 ADD PRIMARY KEY(a);
+
+ALTER TABLE ti1 DROP INDEX ii3;
+ALTER TABLE tm1 DROP INDEX im3;
+
+ALTER TABLE ti1 DROP COLUMN d2;
+ALTER TABLE tm1 DROP COLUMN d2;
+
+ALTER TABLE ti1 ADD CONSTRAINT fi1 FOREIGN KEY (b) REFERENCES ti2(a);
+ALTER TABLE tm1 ADD CONSTRAINT fm1 FOREIGN KEY (b) REFERENCES tm2(a);
+
+ALTER TABLE ti1 ALTER COLUMN b SET DEFAULT 1;
+ALTER TABLE tm1 ALTER COLUMN b SET DEFAULT 1;
+ALTER TABLE ti1 ALTER COLUMN b DROP DEFAULT;
+ALTER TABLE tm1 ALTER COLUMN b DROP DEFAULT;
+
+# This will set both ALTER_COLUMN_NAME and COLUMN_DEFAULT_VALUE
+ALTER TABLE ti1 CHANGE COLUMN f g INT;
+ALTER TABLE tm1 CHANGE COLUMN f g INT;
+ALTER TABLE ti1 CHANGE COLUMN g h VARCHAR(20);
+ALTER TABLE tm1 CHANGE COLUMN g h VARCHAR(20);
+ALTER TABLE ti1 MODIFY COLUMN e ENUM('a', 'b', 'c');
+ALTER TABLE tm1 MODIFY COLUMN e ENUM('a', 'b', 'c');
+ALTER TABLE ti1 MODIFY COLUMN e INT;
+ALTER TABLE tm1 MODIFY COLUMN e INT;
+# This will set both ALTER_COLUMN_ORDER and COLUMN_DEFAULT_VALUE
+ALTER TABLE ti1 MODIFY COLUMN e INT AFTER h;
+ALTER TABLE tm1 MODIFY COLUMN e INT AFTER h;
+ALTER TABLE ti1 MODIFY COLUMN e INT FIRST;
+ALTER TABLE tm1 MODIFY COLUMN e INT FIRST;
+# This will set both ALTER_COLUMN_NOT_NULLABLE and COLUMN_DEFAULT_VALUE
+--disable_info
+# NULL -> NOT NULL only allowed INPLACE if strict sql_mode is on.
+SET @orig_sql_mode = @@sql_mode;
+SET @@sql_mode = 'STRICT_TRANS_TABLES';
+--enable_info
+ALTER TABLE ti1 MODIFY COLUMN c INT NOT NULL;
+--disable_info
+SET @@sql_mode = @orig_sql_mode;
+--enable_info
+ALTER TABLE tm1 MODIFY COLUMN c INT NOT NULL;
+# This will set both ALTER_COLUMN_NULLABLE and COLUMN_DEFAULT_VALUE
+ALTER TABLE ti1 MODIFY COLUMN c INT NULL;
+ALTER TABLE tm1 MODIFY COLUMN c INT NULL;
+# This will set both ALTER_COLUMN_EQUAL_PACK_LENGTH and COLUMN_DEFAULT_VALUE
+ALTER TABLE ti1 MODIFY COLUMN h VARCHAR(30);
+ALTER TABLE tm1 MODIFY COLUMN h VARCHAR(30);
+ALTER TABLE ti1 MODIFY COLUMN h VARCHAR(30) AFTER d;
+ALTER TABLE tm1 MODIFY COLUMN h VARCHAR(30) AFTER d;
+
+ALTER TABLE ti1 DROP COLUMN h;
+ALTER TABLE tm1 DROP COLUMN h;
+
+ALTER TABLE ti1 DROP INDEX ii2;
+ALTER TABLE tm1 DROP INDEX im2;
+ALTER TABLE ti1 DROP PRIMARY KEY;
+ALTER TABLE tm1 DROP PRIMARY KEY;
+
+ALTER TABLE ti1 DROP FOREIGN KEY fi1;
+ALTER TABLE tm1 DROP FOREIGN KEY fm1;
+
+ALTER TABLE ti1 RENAME TO ti3;
+ALTER TABLE tm1 RENAME TO tm3;
+ALTER TABLE ti3 RENAME TO ti1;
+ALTER TABLE tm3 RENAME TO tm1;
+
+ALTER TABLE ti1 ORDER BY b;
+ALTER TABLE tm1 ORDER BY b;
+
+ALTER TABLE ti1 CONVERT TO CHARACTER SET utf16;
+ALTER TABLE tm1 CONVERT TO CHARACTER SET utf16;
+ALTER TABLE ti1 DEFAULT CHARACTER SET utf8;
+ALTER TABLE tm1 DEFAULT CHARACTER SET utf8;
+
+ALTER TABLE ti1 FORCE;
+ALTER TABLE tm1 FORCE;
+
+ALTER TABLE ti1 AUTO_INCREMENT 3;
+ALTER TABLE tm1 AUTO_INCREMENT 3;
+ALTER TABLE ti1 AVG_ROW_LENGTH 10;
+ALTER TABLE tm1 AVG_ROW_LENGTH 10;
+ALTER TABLE ti1 CHECKSUM 1;
+ALTER TABLE tm1 CHECKSUM 1;
+ALTER TABLE ti1 COMMENT 'test';
+ALTER TABLE tm1 COMMENT 'test';
+ALTER TABLE ti1 MAX_ROWS 100;
+ALTER TABLE tm1 MAX_ROWS 100;
+ALTER TABLE ti1 MIN_ROWS 1;
+ALTER TABLE tm1 MIN_ROWS 1;
+ALTER TABLE ti1 PACK_KEYS 1;
+ALTER TABLE tm1 PACK_KEYS 1;
+
+--disable_info
+DROP TABLE ti1, ti2, tm1, tm2;
+
+--echo # Tests of >1 operation (InnoDB)
+
+CREATE TABLE ti1(a INT PRIMARY KEY AUTO_INCREMENT, b INT) engine=InnoDB;
+INSERT INTO ti1(b) VALUES (1), (2);
+
+--enable_info
+ALTER TABLE ti1 RENAME TO ti3, ADD INDEX ii1(b);
+
+ALTER TABLE ti3 DROP INDEX ii1, AUTO_INCREMENT 5;
+--disable_info
+INSERT INTO ti3(b) VALUES (5);
+--enable_info
+ALTER TABLE ti3 ADD INDEX ii1(b), AUTO_INCREMENT 7;
+--disable_info
+INSERT INTO ti3(b) VALUES (7);
+SELECT * FROM ti3;
+
+DROP TABLE ti3;
+
+--echo #
+--echo # 8: Scenario in which ALTER TABLE was returning an unwarranted
+--echo # ER_ILLEGAL_HA error at some point during work on this WL.
+--echo #
+
+CREATE TABLE tm1(i INT DEFAULT 1) engine=MyISAM;
+ALTER TABLE tm1 ADD INDEX ii1(i), ALTER COLUMN i DROP DEFAULT;
+DROP TABLE tm1;
+
+#
+# MDEV-4435 Server crashes in my_strcasecmp_utf8 on ADD KEY IF NOT EXISTS with implicit name when the key exists.
+#
+create table if not exists t1 (i int);
+alter table t1 add key (i);
+alter table t1 add key if not exists (i);
+DROP TABLE t1;
+
+#
+# MDEV-4436 CHANGE COLUMN IF EXISTS does not work and throws wrong warning.
+#
+create table t1 (a int);
+alter table t1 change column if exists a b bigint;
+show create table t1;
+DROP TABLE t1;
+
+#
+# MDEV-4437 ALTER TABLE .. ADD UNIQUE INDEX IF NOT EXISTS causes syntax error.
+#
+
+create table t1 (i int);
+alter table t1 add unique index if not exists idx(i);
+alter table t1 add unique index if not exists idx(i);
+show create table t1;
+DROP TABLE t1;
+
+#
+# MDEV-8358 ADD PRIMARY KEY IF NOT EXISTS -> ERROR 1068 (42000): Multiple primary key
+#
+
+CREATE TABLE t1 (
+ `event_id` bigint(20) unsigned NOT NULL DEFAULT '0',
+ `market_id` bigint(20) unsigned NOT NULL DEFAULT '0',
+ PRIMARY KEY (`event_id`,`market_id`)
+ );
+ALTER TABLE t1 ADD PRIMARY KEY IF NOT EXISTS event_id (event_id,market_id);
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-11126 Crash while altering persistent virtual column
+--echo #
+
+CREATE TABLE `tab1` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `field2` set('option1','option2','option3','option4') NOT NULL,
+ `field3` set('option1','option2','option3','option4','option5') NOT NULL,
+ `field4` set('option1','option2','option3','option4') NOT NULL,
+ `field5` varchar(32) NOT NULL,
+ `field6` varchar(32) NOT NULL,
+ `field7` varchar(32) NOT NULL,
+ `field8` varchar(32) NOT NULL,
+ `field9` int(11) NOT NULL DEFAULT '1',
+ `field10` varchar(16) NOT NULL,
+ `field11` enum('option1','option2','option3') NOT NULL DEFAULT 'option1',
+ `v_col` varchar(128) AS (IF(field11='option1',CONCAT_WS(":","field1",field2,field3,field4,field5,field6,field7,field8,field9,field10), CONCAT_WS(":","field1",field11,field2,field3,field4,field5,field6,field7,field8,field9,field10))) PERSISTENT,
+ PRIMARY KEY (`id`)
+) DEFAULT CHARSET=latin1;
+
+ALTER TABLE `tab1` CHANGE COLUMN v_col `v_col` varchar(128);
+SHOW CREATE TABLE `tab1`;
+ALTER TABLE `tab1` CHANGE COLUMN v_col `v_col` varchar(128) AS (IF(field11='option1',CONCAT_WS(":","field1",field2,field3,field4,field5,field6,field7,field8,field9,field10), CONCAT_WS(":","field1",field11,field2,field3,field4,field5,field6,field7,field8,field9,field10))) PERSISTENT;
+SHOW CREATE TABLE `tab1`;
+DROP TABLE `tab1`;
+
+--echo #
+--echo # MDEV-11548 Reproducible server crash after the 2nd ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS
+--echo #
+
+CREATE TABLE t1 (id INT UNSIGNED NOT NULL PRIMARY KEY);
+CREATE TABLE t2 (id1 INT UNSIGNED NOT NULL);
+
+ALTER TABLE t2
+ADD FOREIGN KEY IF NOT EXISTS (id1)
+ REFERENCES t1 (id);
+
+ALTER TABLE t2
+ADD FOREIGN KEY IF NOT EXISTS (id1)
+REFERENCES t1 (id);
+
+DROP TABLE t2;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-6390 CONVERT TO CHARACTER SET utf8 doesn't change DEFAULT CHARSET.
+--echo #
+
+CREATE TABLE t1 (id int(11) NOT NULL, a int(11) NOT NULL, b int(11))
+ ENGINE=InnoDB DEFAULT CHARSET=latin1;
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 CONVERT TO CHARACTER SET utf8;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-15308
+--echo # Assertion `ha_alter_info->alter_info->drop_list.elements > 0' failed
+--echo # in ha_innodb::prepare_inplace_alter_table
+--echo #
+
+CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB;
+ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP COLUMN b;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB;
+ALTER TABLE t1 DROP INDEX IF EXISTS fk, DROP COLUMN b;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT, b INT, c INT, KEY(c)) ENGINE=InnoDB;
+ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP COLUMN c;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT, b INT, c INT, KEY c1(c)) ENGINE=InnoDB;
+ALTER TABLE t1 DROP FOREIGN KEY IF EXISTS fk, DROP INDEX c1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT, b INT) ENGINE=InnoDB;
+ALTER TABLE t1 DROP INDEX IF EXISTS fk, DROP COLUMN IF EXISTS c;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of 10.0 tests
+--echo #
+
+--echo #
+--echo # MDEV-7374 : Losing connection to MySQL while running ALTER TABLE
+--echo #
+CREATE TABLE t1(i INT) ENGINE=INNODB;
+INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
+INSERT INTO t1 SELECT a.* FROM t1 a, t1 b, t1 c, t1 d, t1 e;
+ALTER TABLE t1 MODIFY i FLOAT;
+DROP TABLE t1;
+
+--echo #
+--echo # MDEV-7816 ALTER with DROP INDEX and ADD INDEX .. COMMENT='comment2' ignores the new comment
+--echo #
+CREATE TABLE t1(a INT);
+CREATE INDEX i1 ON t1(a) COMMENT 'comment1';
+ALTER TABLE t1 DROP INDEX i1, ADD INDEX i1(a) COMMENT 'comment2';
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+
+--echo #
+--echo # End of 10.1 tests
+--echo #
+
+--echo #
+--echo # MDEV-10421 duplicate CHECK CONSTRAINTs
+--echo #
+CREATE TABLE t1 (a INT, b INT) engine=myisam;
+ALTER TABLE t1 ADD CONSTRAINT IF NOT EXISTS `min` CHECK (a+b > 100);
+--error ER_DUP_CONSTRAINT_NAME
+ALTER TABLE t1 ADD CONSTRAINT `min` CHECK (a+b > 100);
+ALTER TABLE t1 ADD CONSTRAINT IF NOT EXISTS `min` CHECK (a+b > 100);
+ALTER TABLE t1 ADD CONSTRAINT `mini` CHECK (a+b > 100);
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+--error ER_DUP_CONSTRAINT_NAME
+CREATE TABLE t1(a INT, b INT, CONSTRAINT min check (a>5),
+ CONSTRAINT min check (b>5));
+
+#
+# MDEV-11114 Cannot drop column referenced by CHECK constraint
+#
+create table t1 (a int, b int, check(a>b));
+--error ER_BAD_FIELD_ERROR
+alter table t1 drop column a;
+--error ER_BAD_FIELD_ERROR
+alter table t1 drop column b, add column b bigint first;
+alter table t1 drop column a, drop constraint constraint_1;
+show create table t1;
+drop table t1;
+
+create table t1 (a int, b int, check(a>0));
+alter table t1 drop column a;
+show create table t1;
+drop table t1;
+
+create table t1 (a int, b int, check(a>0));
+alter table t1 drop column a, add column a bigint first;
+show create table t1;
+drop table t1;
+
+create table t1 (a int, b int, c int, unique(a));
+alter table t1 drop column a;
+show create table t1;
+drop table t1;
+
+create table t1 (a int, b int, c int, unique(a,b));
+--error ER_KEY_COLUMN_DOES_NOT_EXITS
+alter table t1 drop column a;
+alter table t1 drop column a, drop index a;
+show create table t1;
+drop table t1;
+
+#
+# MDEV-14694 ALTER COLUMN IF EXISTS .. causes syntax error
+#
+
+create table t1 (i int);
+alter table t1 alter column if exists a set default 1;
+alter table t1 alter column if exists a drop default;
+show create table t1;
+drop table t1;
+
+--echo #
+--echo # MDEV-13508 Check that rename of columns changes defaults, virtual
+--echo # columns and constraints
+--echo #
+
+create table t1 (a int, b int, check(a>b));
+alter table t1 change column a b int, change column b a int;
+show create table t1;
+drop table t1;
+
+create table t1 (a int primary key, b int, c int default (a+b) check (a+b>0),
+ d int as (a+b),
+ key (b),
+ constraint test check (a+b > 1));
+alter table t1 change b new_b int not null, add column b char(1), add constraint new check (length(b) > 0);
+show create table t1;
+drop table t1;
+
++--echo #
++--echo # MDEV-11071: Assertion `thd->transaction.stmt.is_empty()' failed
++--echo # in Locked_tables_list::unlock_locked_tables
++--echo #
++
++CREATE TABLE t1 (d DATETIME DEFAULT CURRENT_TIMESTAMP, i INT) ENGINE=InnoDB;
++INSERT INTO t1 (i) VALUES (1),(1);
++LOCK TABLE t1 WRITE;
++--error ER_DUP_ENTRY
++ALTER TABLE t1 ADD UNIQUE(i);
++
++# Cleanup
++UNLOCK TABLES;
++DROP TABLE t1;
++
++
+--echo #
+--echo # End of 10.2 tests
+--echo #
diff --cc sql/item.h
index 10ce987e289,5ed45c69e96..0ee60afb3be
--- a/sql/item.h
+++ b/sql/item.h
@@@ -4674,42 -4211,12 +4674,42 @@@ public
also to make printing of items inherited from Item_sum uniform.
*/
virtual const char *func_name() const= 0;
- virtual void fix_length_and_dec()= 0;
+ virtual bool fix_length_and_dec()= 0;
bool const_item() const { return const_item_cache; }
table_map used_tables() const { return used_tables_cache; }
- Item* build_clone(THD *thd, MEM_ROOT *mem_root);
+ Item* build_clone(THD *thd);
};
+class sp_head;
+class sp_name;
+struct st_sp_security_context;
+
+class Item_sp
+{
+public:
+ Name_resolution_context *context;
+ sp_name *m_name;
+ sp_head *m_sp;
+ TABLE *dummy_table;
+ uchar result_buf[64];
+ sp_rcontext *func_ctx;
+ MEM_ROOT sp_mem_root;
+ Query_arena *sp_query_arena;
+
+ /*
+ The result field of the stored function.
+ */
+ Field *sp_result_field;
+ Item_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name_arg);
+ Item_sp(THD *thd, Item_sp *item);
+ const char *func_name(THD *thd) const;
+ void cleanup();
+ bool sp_check_access(THD *thd);
+ bool execute(THD *thd, bool *null_value, Item **args, uint arg_count);
+ bool execute_impl(THD *thd, Item **args, uint arg_count);
+ bool init_result_field(THD *thd, uint max_length, uint maybe_null,
+ bool *null_value, LEX_CSTRING *name);
+};
class Item_ref :public Item_ident
{
diff --cc sql/item_cmpfunc.cc
index 3034636dca3,b86c0079bce..37ec33c8358
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@@ -2053,30 -2108,35 +2059,31 @@@ void Item_func_between::fix_after_pullo
eval_not_null_tables(NULL);
}
- void Item_func_between::fix_length_and_dec()
+ bool Item_func_between::fix_length_and_dec()
{
- THD *thd= current_thd;
max_length= 1;
- compare_as_dates= 0;
/*
As some compare functions are generated after sql_yacc,
we have to check for out of memory conditions here
*/
if (!args[0] || !args[1] || !args[2])
- return;
+ return TRUE;
- if (agg_cmp_type(&m_compare_type, args, 3))
+ if (m_comparator.aggregate_for_comparison(Item_func_between::func_name(),
+ args, 3, true))
+ {
+ DBUG_ASSERT(current_thd->is_error());
- return;
+ return TRUE;
+ }
- m_comparator.type_handler()->Item_func_between_fix_length_and_dec(this);
- if (m_compare_type == STRING_RESULT &&
- agg_arg_charsets_for_comparison(cmp_collation, args, 3))
- return TRUE;
++ return m_comparator.type_handler()->
++ Item_func_between_fix_length_and_dec(this);
+}
- /*
- When comparing as date/time, we need to convert non-temporal values
- (e.g. strings) to MYSQL_TIME.
- For this to work, we need to know what date/time type we compare
- strings as.
- */
- if (m_compare_type == TIME_RESULT)
- compare_as_dates= find_date_time_item(thd, args, 3, 0, false);
- /* See the comment for Item_func::convert_const_compared_to_int_field */
+bool Item_func_between::fix_length_and_dec_numeric(THD *thd)
+{
+ /* See the comment about the similar block in Item_bool_func2 */
if (args[0]->real_item()->type() == FIELD_ITEM &&
!thd->lex->is_ps_or_view_context_analysis())
{
@@@ -2087,13 -2147,10 +2094,13 @@@
const bool cvt_arg1= convert_const_to_int(thd, field_item, &args[1]);
const bool cvt_arg2= convert_const_to_int(thd, field_item, &args[2]);
if (cvt_arg1 && cvt_arg2)
- m_compare_type= INT_RESULT; // Works for all types.
+ {
+ // Works for all types
+ m_comparator.set_handler(&type_handler_longlong);
+ }
}
}
- return false;
+ return FALSE;
}
@@@ -2604,7 -2730,9 +2611,9 @@@ Item_func_nullif::fix_length_and_dec(
*/
m_cache= args[0]->cmp_type() == STRING_RESULT ?
new (thd->mem_root) Item_cache_str_for_nullif(thd, args[0]) :
- Item_cache::get_cache(thd, args[0]);
+ args[0]->get_cache(thd);
+ if (!m_cache)
+ return TRUE;
m_cache->setup(thd, args[0]);
m_cache->store(args[0]);
m_cache->set_used_tables(args[0]->used_tables());
@@@ -3029,129 -3169,86 +3040,129 @@@ static void propagate_and_change_item_t
}
-bool Item_func_case::fix_length_and_dec()
+bool Item_func_case_simple::prepare_predicant_and_values(THD *thd,
+ uint *found_types,
+ bool nulls_equal)
{
- m_found_types= 0;
- if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
- maybe_null= 1;
-
- /*
- Aggregate all THEN and ELSE expression types
- and collations when string result
- */
- Item **rets= args + first_expr_num + 1 + nwhens;
- uint nrets= nwhens + (else_expr_num != -1);
- set_handler_by_field_type(agg_field_type(rets, nrets, true));
-
- if (Item_func_case::result_type() == STRING_RESULT)
+ bool have_null= false;
+ uint type_cnt;
+ Type_handler_hybrid_field_type tmp;
+ uint ncases= when_count();
+ add_predicant(this, 0);
+ for (uint i= 0 ; i < ncases; i++)
{
- if (count_string_result_length(Item_func_case::field_type(), rets, nrets))
- return TRUE;
+ if (nulls_equal ?
+ add_value("case..when", this, i + 1) :
+ add_value_skip_null("case..when", this, i + 1, &have_null))
+ return true;
}
- else
- fix_attributes(rets, nrets);
+ all_values_added(&tmp, &type_cnt, &m_found_types);
+#ifndef DBUG_OFF
+ Predicant_to_list_comparator::debug_print(thd);
+#endif
+ return false;
+}
+
+
- void Item_func_case_searched::fix_length_and_dec()
++bool Item_func_case_searched::fix_length_and_dec()
+{
+ THD *thd= current_thd;
- aggregate_then_and_else_arguments(thd, when_count());
++ return aggregate_then_and_else_arguments(thd, when_count());
+}
+
+
- void Item_func_case_simple::fix_length_and_dec()
++bool Item_func_case_simple::fix_length_and_dec()
+{
+ THD *thd= current_thd;
- if (!aggregate_then_and_else_arguments(thd, when_count() + 1))
- aggregate_switch_and_when_arguments(thd, false);
++ return (aggregate_then_and_else_arguments(thd, when_count() + 1) ||
++ aggregate_switch_and_when_arguments(thd, false));
+}
+
+
- void Item_func_decode_oracle::fix_length_and_dec()
++bool Item_func_decode_oracle::fix_length_and_dec()
+{
+ THD *thd= current_thd;
- if (!aggregate_then_and_else_arguments(thd, when_count() + 1))
- aggregate_switch_and_when_arguments(thd, true);
++ return (aggregate_then_and_else_arguments(thd, when_count() + 1) ||
++ aggregate_switch_and_when_arguments(thd, true));
+}
+
+
+/*
+ Aggregate all THEN and ELSE expression types
+ and collations when string result
- /*
- Aggregate first expression and all WHEN expression types
- and collations when string comparison
- */
- if (first_expr_num != -1)
- {
- left_cmp_type= args[0]->cmp_type();
+ @param THD - current thd
+ @param start - an element in args to start aggregating from
+*/
+bool Item_func_case::aggregate_then_and_else_arguments(THD *thd, uint start)
+{
+ if (aggregate_for_result(func_name(), args + start, arg_count - start, true))
+ return true;
- if (!(m_found_types= collect_cmp_types(args, nwhens + 1)))
- return TRUE;
+ if (fix_attributes(args + start, arg_count - start))
+ return true;
- Item *date_arg= 0;
- if (m_found_types & (1U << TIME_RESULT))
- date_arg= find_date_time_item(current_thd, args, nwhens + 1, 0, true);
+ return false;
+}
- if (m_found_types & (1U << STRING_RESULT))
- {
- /*
- If we'll do string comparison, we also need to aggregate
- character set and collation for first/WHEN items and
- install converters for some of them to cmp_collation when necessary.
- This is done because cmp_item compatators cannot compare
- strings in two different character sets.
- Some examples when we install converters:
- 1. Converter installed for the first expression:
+/*
+ Aggregate the predicant expression and all WHEN expression types
+ and collations when string comparison
+*/
+bool Item_func_case_simple::aggregate_switch_and_when_arguments(THD *thd,
+ bool nulls_eq)
+{
+ uint ncases= when_count();
+ m_found_types= 0;
+ if (prepare_predicant_and_values(thd, &m_found_types, nulls_eq))
+ {
+ /*
+ If Predicant_to_list_comparator() fails to prepare components,
+ it must put an error into the diagnostics area. This is needed
+ to make fix_fields() catches such errors.
+ */
+ DBUG_ASSERT(thd->is_error());
+ return true;
+ }
+
+ if (!(m_found_types= collect_cmp_types(args, ncases + 1)))
+ return true;
- CASE latin1_item WHEN utf16_item THEN ... END
+ if (m_found_types & (1U << STRING_RESULT))
+ {
+ /*
+ If we'll do string comparison, we also need to aggregate
+ character set and collation for first/WHEN items and
+ install converters for some of them to cmp_collation when necessary.
+ This is done because cmp_item compatators cannot compare
+ strings in two different character sets.
+ Some examples when we install converters:
- is replaced to:
+ 1. Converter installed for the first expression:
- CASE CONVERT(latin1_item USING utf16) WHEN utf16_item THEN ... END
+ CASE latin1_item WHEN utf16_item THEN ... END
- 2. Converter installed for the left WHEN item:
+ is replaced to:
- CASE utf16_item WHEN latin1_item THEN ... END
+ CASE CONVERT(latin1_item USING utf16) WHEN utf16_item THEN ... END
- is replaced to:
+ 2. Converter installed for the left WHEN item:
- CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END
- */
- if (agg_arg_charsets_for_comparison(cmp_collation, args, nwhens + 1))
- return TRUE;
- }
+ CASE utf16_item WHEN latin1_item THEN ... END
- for (uint i= 0; i <= (uint)TIME_RESULT; i++)
- {
- if (m_found_types & (1U << i) && !cmp_items[i])
- {
- DBUG_ASSERT((Item_result)i != ROW_RESULT);
- if (!(cmp_items[i]=
- cmp_item::get_comparator((Item_result)i, date_arg,
- cmp_collation.collation)))
- return TRUE;
- }
- }
+ is replaced to:
+
+ CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END
+ */
+ if (agg_arg_charsets_for_comparison(cmp_collation, args, ncases + 1))
+ return true;
}
- return FALSE;
+
+ if (make_unique_cmp_items(thd, cmp_collation.collation))
+ return true;
+
+ return false;
}
@@@ -4156,71 -4122,52 +4167,74 @@@ void Item_func_in::fix_after_pullout(st
eval_not_null_tables(NULL);
}
-static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
+
+bool Item_func_in::prepare_predicant_and_values(THD *thd, uint *found_types)
{
- return cs->coll->strnncollsp(cs,
- (uchar *) x->ptr(),x->length(),
- (uchar *) y->ptr(),y->length());
+ uint type_cnt;
+ have_null= false;
+
+ add_predicant(this, 0);
+ for (uint i= 1 ; i < arg_count; i++)
+ {
+ if (add_value_skip_null(Item_func_in::func_name(), this, i, &have_null))
+ return true;
+ }
+ all_values_added(&m_comparator, &type_cnt, found_types);
+ arg_types_compatible= type_cnt < 2;
+
+#ifndef DBUG_OFF
+ Predicant_to_list_comparator::debug_print(thd);
+#endif
+ return false;
}
-/*
- Create 'array' for this IN predicate with the respect to its result type
- and put values from <in value list> in 'array'.
-*/
- void Item_func_in::fix_length_and_dec()
-bool Item_func_in::create_array(THD *thd)
++bool Item_func_in::fix_length_and_dec()
{
- Item *date_arg= 0;
+ THD *thd= current_thd;
+ uint found_types;
+ m_comparator.set_handler(type_handler_varchar.type_handler_for_comparison());
+ max_length= 1;
- switch (m_compare_type) {
- case STRING_RESULT:
- array=new (thd->mem_root) in_string(thd, arg_count - 1,
- (qsort2_cmp) srtcmp_in,
- cmp_collation.collation);
- break;
- case INT_RESULT:
- array= new (thd->mem_root) in_longlong(thd, arg_count - 1);
- break;
- case REAL_RESULT:
- array= new (thd->mem_root) in_double(thd, arg_count - 1);
- break;
- case ROW_RESULT:
- /*
- The row comparator was created at the beginning but only DATETIME
- items comparators were initialized. Call store_value() to setup
- others.
- */
- ((in_row*)array)->tmp.store_value(args[0]);
- break;
- case DECIMAL_RESULT:
- array= new (thd->mem_root) in_decimal(thd, arg_count - 1);
- break;
- case TIME_RESULT:
- date_arg= find_date_time_item(thd, args, arg_count, 0, true);
- array= new (thd->mem_root) in_datetime(thd, date_arg, arg_count - 1);
- break;
+ if (prepare_predicant_and_values(thd, &found_types))
+ {
+ DBUG_ASSERT(thd->is_error()); // Must set error
- return;
++ return TRUE;
}
- if (!array || thd->is_fatal_error) // OOM
- return true;
+
+ if (arg_types_compatible) // Bisection condition #1
+ {
- m_comparator.type_handler()->
- Item_func_in_fix_comparator_compatible_types(thd, this);
++ if (m_comparator.type_handler()->
++ Item_func_in_fix_comparator_compatible_types(thd, this))
++ return TRUE;
+ }
+ else
+ {
+ DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT);
- fix_for_scalar_comparison_using_cmp_items(thd, found_types);
++ if ( fix_for_scalar_comparison_using_cmp_items(thd, found_types))
++ return TRUE;
+ }
+
+ DBUG_EXECUTE_IF("Item_func_in",
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
+ ER_UNKNOWN_ERROR, "DBUG: types_compatible=%s bisect=%s",
+ arg_types_compatible ? "yes" : "no",
+ array != NULL ? "yes" : "no"););
++ return FALSE;
+}
+
+
+/**
+ Populate Item_func_in::array with constant not-NULL arguments and sort them.
+
+ Sets "have_null" to true if some of the values appeared to be NULL.
+ Note, explicit NULLs were found during prepare_predicant_and_values().
+ So "have_null" can already be true before the fix_in_vector() call.
+ Here we additionally catch implicit NULLs.
+*/
+void Item_func_in::fix_in_vector()
+{
+ DBUG_ASSERT(array);
uint j=0;
for (uint i=1 ; i < arg_count ; i++)
{
@@@ -5710,7 -5714,7 +5725,8 @@@ Item_func_regexp_instr::fix_length_and_
re.init(cmp_collation.collation, 0);
re.fix_owner(this, args[0], args[1]);
+ max_length= MY_INT32_NUM_DECIMAL_DIGITS; // See also Item_func_locate
+ return FALSE;
}
@@@ -6739,11 -6743,12 +6756,12 @@@ longlong Item_equal::val_int(
}
- void Item_equal::fix_length_and_dec()
+ bool Item_equal::fix_length_and_dec()
{
Item *item= get_first(NO_PARTICULAR_TAB, NULL);
- eval_item= cmp_item::get_comparator(item->cmp_type(), item,
- item->collation.collation);
- return FALSE;
+ const Type_handler *handler= item->type_handler();
+ eval_item= handler->make_cmp_item(current_thd, item->collation.collation);
++ return eval_item == NULL;
}
diff --cc sql/item_cmpfunc.h
index 30d682f05aa,a59432058eb..c321b826ea4
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@@ -215,10 -198,9 +215,10 @@@ public
Item_bool_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
Item_bool_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
Item_bool_func(THD *thd, Item_bool_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_long; }
bool is_bool_type() { return true; }
virtual CHARSET_INFO *compare_collation() const { return NULL; }
- void fix_length_and_dec() { decimals=0; max_length=1; }
+ bool fix_length_and_dec() { decimals=0; max_length=1; return FALSE; }
uint decimal_precision() const { return 1; }
bool need_parentheses_in_default() { return true; }
};
@@@ -903,13 -878,7 +903,13 @@@ public
enum Functype functype() const { return BETWEEN; }
const char *func_name() const { return "between"; }
enum precedence precedence() const { return BETWEEN_PRECEDENCE; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
+ bool fix_length_and_dec_string(THD *)
+ {
+ return agg_arg_charsets_for_comparison(cmp_collation, args, 3);
+ }
+ bool fix_length_and_dec_temporal(THD *);
+ bool fix_length_and_dec_numeric(THD *);
virtual void print(String *str, enum_query_type query_type);
bool eval_not_null_tables(void *opt_arg);
void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge);
@@@ -950,13 -911,15 +950,15 @@@ public
longlong val_int();
uint decimal_precision() const { return 1; }
const char *func_name() const { return "strcmp"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- agg_arg_charsets_for_comparison(cmp_collation, args, 2);
- fix_char_length(2); // returns "1" or "0" or "-1"
+ if (agg_arg_charsets_for_comparison(cmp_collation, args, 2))
+ return TRUE;
+ fix_char_length(2);
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_strcmp>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_strcmp>(thd, this); }
};
@@@ -972,17 -935,15 +974,17 @@@ class Item_func_interval :public Item_l
Item_row *row;
bool use_decimal_comparison;
interval_range *intervals;
-public:
- Item_func_interval(THD *thd, Item_row *a):
- Item_int_func(thd, a), row(a), intervals(0)
+ bool check_arguments() const
{
- allowed_arg_cols= 0; // Fetch this value from first argument
+ return check_argument_types_like_args0();
}
+public:
+ Item_func_interval(THD *thd, Item_row *a):
+ Item_long_func(thd, a), row(a), intervals(0)
+ { }
bool fix_fields(THD *, Item **);
longlong val_int();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "interval"; }
uint decimal_precision() const { return 2; }
void print(String *str, enum_query_type query_type)
@@@ -1006,12 -967,12 +1008,14 @@@ public
longlong int_op();
String *str_op(String *);
my_decimal *decimal_op(my_decimal *);
- bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
+ bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ bool time_op(MYSQL_TIME *ltime);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- if (!aggregate_for_result(func_name(), args, arg_count, true))
- fix_attributes(args, arg_count);
- set_handler_by_field_type(agg_field_type(args, arg_count, true));
++ if (aggregate_for_result(func_name(), args, arg_count, true))
++ return TRUE;
+ fix_attributes(args, arg_count);
+ return FALSE;
}
const char *func_name() const { return "coalesce"; }
table_map not_null_tables() const { return 0; }
@@@ -1024,49 -985,22 +1028,53 @@@
Case abbreviations that aggregate its result field type by two arguments:
IFNULL(arg1, arg2)
IF(switch, arg1, arg2)
+ NVL2(switch, arg1, arg2)
*/
-class Item_func_case_abbreviation2 :public Item_func_hybrid_field_type
+class Item_func_case_abbreviation2 :public Item_func_case_expression
{
protected:
- void fix_length_and_dec2(Item **items)
+ bool fix_length_and_dec2(Item **items)
{
- if (!aggregate_for_result(func_name(), items, 2, true))
- fix_attributes(items, 2);
- set_handler_by_field_type(agg_field_type(items, 2, true));
++ if (aggregate_for_result(func_name(), items, 2, true))
++ return TRUE;
+ fix_attributes(items, 2);
+ return FALSE;
}
- uint decimal_precision2(Item **args) const;
+
+ void cache_type_info(const Item *source, bool maybe_null_arg)
+ {
+ Type_std_attributes::set(source);
+ set_handler(source->type_handler());
+ maybe_null= maybe_null_arg;
+ }
+
- void fix_length_and_dec2_eliminate_null(Item **items)
++ bool fix_length_and_dec2_eliminate_null(Item **items)
+ {
+ // Let IF(cond, expr, NULL) and IF(cond, NULL, expr) inherit type from expr.
+ if (items[0]->type() == NULL_ITEM)
+ {
+ cache_type_info(items[1], true);
+ // If both arguments are NULL, make resulting type BINARY(0).
+ if (items[1]->type() == NULL_ITEM)
+ set_handler(&type_handler_string);
+ }
+ else if (items[1]->type() == NULL_ITEM)
+ {
+ cache_type_info(items[0], true);
+ }
+ else
+ {
- fix_length_and_dec2(items);
++ if (fix_length_and_dec2(items))
++ return TRUE;
+ }
++ return FALSE;
+ }
+
public:
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b):
- Item_func_hybrid_field_type(thd, a, b) { }
+ Item_func_case_expression(thd, a, b) { }
Item_func_case_abbreviation2(THD *thd, Item *a, Item *b, Item *c):
- Item_func_hybrid_field_type(thd, a, b, c) { }
+ Item_func_case_expression(thd, a, b, c) { }
};
@@@ -1079,80 -1013,44 +1087,82 @@@ public
longlong int_op();
String *str_op(String *str);
my_decimal *decimal_op(my_decimal *);
- bool date_op(MYSQL_TIME *ltime,uint fuzzydate);
+ bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate);
+ bool time_op(MYSQL_TIME *ltime);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_func_case_abbreviation2::fix_length_and_dec2(args);
+ if (Item_func_case_abbreviation2::fix_length_and_dec2(args))
+ return TRUE;
maybe_null= args[1]->maybe_null;
+ return FALSE;
}
const char *func_name() const { return "ifnull"; }
- Field *create_field_for_create_select(TABLE *table)
- { return tmp_table_field_from_field_type(table, false, false); }
table_map not_null_tables() const { return 0; }
- uint decimal_precision() const
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_ifnull>(thd, this); }
+};
+
+
+/**
+ Case abbreviations that have a switch argument and
+ two return arguments to choose from. Returns the value
+ of either of the two return arguments depending on the switch argument value.
+
+ IF(switch, arg1, arg2)
+ NVL(switch, arg1, arg2)
+*/
+class Item_func_case_abbreviation2_switch: public Item_func_case_abbreviation2
+{
+protected:
+ virtual Item *find_item() const= 0;
+
+public:
+ Item_func_case_abbreviation2_switch(THD *thd, Item *a, Item *b, Item *c)
+ :Item_func_case_abbreviation2(thd, a, b, c)
+ { }
+
+ bool date_op(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ {
+ Datetime dt(current_thd, find_item(), fuzzydate);
+ return (null_value= dt.copy_to_mysql_time(ltime, mysql_timestamp_type()));
+ }
+ bool time_op(MYSQL_TIME *ltime)
+ {
+ return (null_value= Time(find_item()).copy_to_mysql_time(ltime));
+ }
+ longlong int_op()
{
- return Item_func_case_abbreviation2::decimal_precision2(args);
+ return val_int_from_item(find_item());
+ }
+ double real_op()
+ {
+ return val_real_from_item(find_item());
+ }
+ my_decimal *decimal_op(my_decimal *decimal_value)
+ {
+ return val_decimal_from_item(find_item(), decimal_value);
+ }
+ String *str_op(String *str)
+ {
+ return val_str_from_item(find_item(), str);
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_ifnull>(thd, mem_root, this); }
};
-class Item_func_if :public Item_func_case_abbreviation2
+class Item_func_if :public Item_func_case_abbreviation2_switch
{
+protected:
+ Item *find_item() const { return args[0]->val_bool() ? args[1] : args[2]; }
+
public:
Item_func_if(THD *thd, Item *a, Item *b, Item *c):
- Item_func_case_abbreviation2(thd, a, b, c)
+ Item_func_case_abbreviation2_switch(thd, a, b, c)
{}
- bool date_op(MYSQL_TIME *ltime, uint fuzzydate);
- longlong int_op();
- double real_op();
- my_decimal *decimal_op(my_decimal *);
- String *str_op(String *);
bool fix_fields(THD *, Item **);
- void fix_length_and_dec()
- bool fix_length_and_dec();
- uint decimal_precision() const
++ bool fix_length_and_dec()
{
- fix_length_and_dec2_eliminate_null(args + 1);
- return Item_func_case_abbreviation2::decimal_precision2(args + 1);
++ return fix_length_and_dec2_eliminate_null(args + 1);
}
const char *func_name() const { return "if"; }
bool eval_not_null_tables(void *opt_arg);
@@@ -1164,26 -1062,7 +1174,26 @@@ private
};
-class Item_func_nullif :public Item_func_hybrid_field_type
+class Item_func_nvl2 :public Item_func_case_abbreviation2_switch
+{
+protected:
+ Item *find_item() const { return args[0]->is_null() ? args[2] : args[1]; }
+
+public:
+ Item_func_nvl2(THD *thd, Item *a, Item *b, Item *c):
+ Item_func_case_abbreviation2_switch(thd, a, b, c)
+ {}
+ const char *func_name() const { return "nvl2"; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- fix_length_and_dec2_eliminate_null(args + 1);
++ return fix_length_and_dec2_eliminate_null(args + 1);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_nvl2>(thd, this); }
+};
+
+
+class Item_func_nullif :public Item_func_case_expression
{
Arg_comparator cmp;
/*
@@@ -1236,8 -1114,9 +1246,8 @@@ public
longlong int_op();
String *str_op(String *str);
my_decimal *decimal_op(my_decimal *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool walk(Item_processor processor, bool walk_subquery, void *arg);
- uint decimal_precision() const { return args[2]->decimal_precision(); }
const char *func_name() const { return "nullif"; }
void print(String *str, enum_query_type query_type);
void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array,
@@@ -2120,115 -1579,28 +2130,115 @@@ public
table_map not_null_tables() const { return 0; }
const char *func_name() const { return "case"; }
enum precedence precedence() const { return BETWEEN_PRECEDENCE; }
- virtual void print(String *str, enum_query_type query_type);
- Item *find_item(String *str);
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
- void cleanup();
- Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
bool need_parentheses_in_default() { return true; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_case>(thd, mem_root, this); }
- Item *build_clone(THD *thd, MEM_ROOT *mem_root)
+};
+
+
+/*
+ CASE WHEN cond THEN res [WHEN cond THEN res...] [ELSE res] END
+
+ Searched CASE checks all WHEN expressions one after another.
+ When some WHEN expression evaluated to TRUE then the
+ value of the corresponding THEN expression is returned.
+*/
+class Item_func_case_searched: public Item_func_case
+{
+ uint when_count() const { return arg_count / 2; }
+ bool with_else() const { return arg_count % 2; }
+ Item **else_expr_addr() const { return with_else() ? &args[arg_count - 1] : 0; }
+public:
+ Item_func_case_searched(THD *thd, List<Item> &list)
+ :Item_func_case(thd, list)
{
- Item_func_case *clone= (Item_func_case *) Item_func::build_clone(thd, mem_root);
- if (clone)
- {
- clone->case_item= 0;
- bzero(&clone->cmp_items, sizeof(cmp_items));
- }
+ DBUG_ASSERT(arg_count >= 2);
+ reorder_args(0);
+ }
+ void print(String *str, enum_query_type query_type);
- void fix_length_and_dec();
++ bool fix_length_and_dec();
+ Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
+ {
+ // None of the arguments are in a comparison context
+ Item_args::propagate_equal_fields(thd, Context_identity(), cond);
+ return this;
+ }
+ Item *find_item();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_case_searched>(thd, this); }
+};
+
+
+/*
+ CASE pred WHEN value THEN res [WHEN value THEN res...] [ELSE res] END
+
+ When the predicant expression is specified then it is compared to each WHEN
+ expression individually. When an equal WHEN expression is found
+ the corresponding THEN expression is returned.
+ In order to do correct comparisons several comparators are used. One for
+ each result type. Different result types that are used in particular
+ CASE ... END expression are collected in the fix_length_and_dec() member
+ function and only comparators for there result types are used.
+*/
+class Item_func_case_simple: public Item_func_case,
+ public Predicant_to_list_comparator
+{
+protected:
+ uint m_found_types;
+ uint when_count() const { return (arg_count - 1) / 2; }
+ bool with_else() const { return arg_count % 2 == 0; }
+ Item **else_expr_addr() const { return with_else() ? &args[arg_count - 1] : 0; }
+ bool aggregate_switch_and_when_arguments(THD *thd, bool nulls_equal);
+ bool prepare_predicant_and_values(THD *thd, uint *found_types,
+ bool nulls_equal);
+public:
+ Item_func_case_simple(THD *thd, List<Item> &list)
+ :Item_func_case(thd, list),
+ Predicant_to_list_comparator(thd, arg_count),
+ m_found_types(0)
+ {
+ DBUG_ASSERT(arg_count >= 3);
+ reorder_args(1);
+ }
+ void cleanup()
+ {
+ DBUG_ENTER("Item_func_case_simple::cleanup");
+ Item_func::cleanup();
+ Predicant_to_list_comparator::cleanup();
+ DBUG_VOID_RETURN;
+ }
+ void print(String *str, enum_query_type query_type);
- void fix_length_and_dec();
++ bool fix_length_and_dec();
+ Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
+ Item *find_item();
+ Item *build_clone(THD *thd)
+ {
+ Item_func_case_simple *clone= (Item_func_case_simple *)
+ Item_func_case::build_clone(thd);
+ uint ncases= when_count();
+ if (clone && clone->Predicant_to_list_comparator::init_clone(thd, ncases))
+ return NULL;
return clone;
}
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_case_simple>(thd, this); }
+};
+
+
+class Item_func_decode_oracle: public Item_func_case_simple
+{
+public:
+ Item_func_decode_oracle(THD *thd, List<Item> &list)
+ :Item_func_case_simple(thd, list)
+ { }
+ const char *func_name() const { return "decode_oracle"; }
+ void print(String *str, enum_query_type query_type);
- void fix_length_and_dec();
++ bool fix_length_and_dec();
+ Item *find_item();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_decode_oracle>(thd, this); }
};
+
/*
The Item_func_in class implements
in_expr IN (<in value list>)
@@@ -2298,52 -1642,23 +2308,52 @@@ public
and can be used safely as comparisons for key conditions
*/
bool arg_types_compatible;
- Item_result left_cmp_type;
- cmp_item *cmp_items[6]; /* One cmp_item for each result type */
+
+ TABLE_LIST *emb_on_expr_nest;
Item_func_in(THD *thd, List<Item> &list):
- Item_func_opt_neg(thd, list), array(0), have_null(0),
- arg_types_compatible(FALSE)
- {
- bzero(&cmp_items, sizeof(cmp_items));
- allowed_arg_cols= 0; // Fetch this value from first argument
- }
+ Item_func_opt_neg(thd, list),
+ Predicant_to_list_comparator(thd, arg_count - 1),
+ transform_into_subq(false),
+ array(0), have_null(0),
+ arg_types_compatible(FALSE), emb_on_expr_nest(0)
+ { }
longlong val_int();
bool fix_fields(THD *, Item **);
- void fix_length_and_dec();
- bool create_array(THD *thd);
+ bool fix_length_and_dec();
+ bool compatible_types_scalar_bisection_possible()
+ {
+ DBUG_ASSERT(m_comparator.cmp_type() != ROW_RESULT);
+ return all_items_are_consts(args + 1, arg_count - 1); // Bisection #2
+ }
+ bool compatible_types_row_bisection_possible()
+ {
+ DBUG_ASSERT(m_comparator.cmp_type() == ROW_RESULT);
+ return all_items_are_consts(args + 1, arg_count - 1) && // Bisection #2
+ ((is_top_level_item() && !negated) || // Bisection #3
+ (!list_contains_null() && !args[0]->maybe_null)); // Bisection #4
+ }
+ bool agg_all_arg_charsets_for_comparison()
+ {
+ return agg_arg_charsets_for_comparison(cmp_collation, args, arg_count);
+ }
+ void fix_in_vector();
+ bool value_list_convert_const_to_int(THD *thd);
+ bool fix_for_scalar_comparison_using_bisection(THD *thd)
+ {
+ array= m_comparator.type_handler()->make_in_vector(thd, this, arg_count - 1);
+ if (!array) // OOM
+ return true;
+ fix_in_vector();
+ return false;
+ }
+ bool fix_for_scalar_comparison_using_cmp_items(THD *thd, uint found_types);
+
+ bool fix_for_row_comparison_using_cmp_items(THD *thd);
+ bool fix_for_row_comparison_using_bisection(THD *thd);
+
void cleanup()
{
- uint i;
DBUG_ENTER("Item_func_in::cleanup");
Item_int_func::cleanup();
delete array;
@@@ -2817,14 -2114,14 +2831,14 @@@ public
}
longlong val_int();
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "regexp"; }
enum precedence precedence() const { return CMP_PRECEDENCE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_regex>(thd, mem_root, this); }
- Item *build_clone(THD *thd, MEM_ROOT *mem_root)
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_regex>(thd, this); }
+ Item *build_clone(THD *thd)
{
- Item_func_regex *clone= (Item_func_regex*) Item_bool_func::build_clone(thd, mem_root);
+ Item_func_regex *clone= (Item_func_regex*) Item_bool_func::build_clone(thd);
if (clone)
clone->re.reset();
return clone;
@@@ -2867,10 -2152,10 +2881,10 @@@ public
}
longlong val_int();
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "regexp_instr"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_regexp_instr>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_regexp_instr>(thd, this); }
};
diff --cc sql/item_func.cc
index 567c813de3c,4bdb18ad95a..5693484ad3b
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@@ -372,13 -234,10 +372,12 @@@ Item_func::fix_fields(THD *thd, Item **
with_window_func= with_window_func || item->with_window_func;
with_field= with_field || item->with_field;
used_tables_and_const_cache_join(item);
- with_subselect|= item->has_subquery();
+ m_with_subquery|= item->with_subquery();
}
}
+ if (check_arguments())
+ return true;
- fix_length_and_dec();
- if (unlikely(thd->is_error())) // An error inside fix_length_and_dec occurred
+ if (fix_length_and_dec())
return TRUE;
fixed= 1;
return FALSE;
@@@ -762,10 -732,12 +761,12 @@@ String *Item_int_func::val_str(String *
}
- void Item_func_connection_id::fix_length_and_dec()
+ bool Item_func_connection_id::fix_length_and_dec()
{
- Item_long_func::fix_length_and_dec();
- if (Item_int_func::fix_length_and_dec())
++ if (Item_long_func::fix_length_and_dec())
+ return TRUE;
max_length= 10;
+ return FALSE;
}
@@@ -792,19 -796,44 +793,19 @@@ bool Item_num_op::fix_type_handler(cons
}
- void Item_func_plus::fix_length_and_dec(void)
-/**
- Set result type for a numeric function of one argument
- (can be also used by a numeric function of many arguments, if the result
- type depends only on the first argument)
-*/
-
-bool Item_func_num1::fix_length_and_dec()
++bool Item_func_plus::fix_length_and_dec(void)
{
- DBUG_ENTER("Item_func_num1::fix_length_and_dec");
+ DBUG_ENTER("Item_func_plus::fix_length_and_dec");
DBUG_PRINT("info", ("name %s", func_name()));
- // Note, cast_to_int_type() can return TIME_RESULT
- switch (args[0]->cast_to_int_type()) {
- case INT_RESULT:
- set_handler_by_result_type(INT_RESULT);
- max_length= args[0]->max_length;
- unsigned_flag= args[0]->unsigned_flag;
- break;
- case STRING_RESULT:
- case REAL_RESULT:
- set_handler_by_result_type(REAL_RESULT);
- decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
- max_length= float_length(decimals);
- break;
- case TIME_RESULT:
- case DECIMAL_RESULT:
- set_handler_by_result_type(DECIMAL_RESULT);
- decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
- max_length= args[0]->max_length;
- break;
- case ROW_RESULT:
- DBUG_ASSERT(0);
- }
- DBUG_PRINT("info", ("Type: %s",
- (result_type() == REAL_RESULT ? "REAL_RESULT" :
- result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- result_type() == INT_RESULT ? "INT_RESULT" :
- "--ILLEGAL!!!--")));
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_plus;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_for_result;);
+ DBUG_ASSERT(aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_plus::type_handler()->Item_func_plus_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
++ if (fix_type_handler(aggregator))
++ DBUG_RETURN(TRUE);
++ if (Item_func_plus::type_handler()->Item_func_plus_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
++ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_RETURN(FALSE);
}
@@@ -1316,22 -1423,9 +1317,22 @@@ void Item_func_minus::fix_unsigned_flag
if (unsigned_flag &&
(current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
unsigned_flag=0;
- return FALSE;
+}
+
+
- void Item_func_minus::fix_length_and_dec()
++bool Item_func_minus::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_func_minus::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_minus;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
+ DBUG_ASSERT(!aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_minus::type_handler()->Item_func_minus_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
++ if (fix_type_handler(aggregator))
++ DBUG_RETURN(TRUE);
++ if (Item_func_minus::type_handler()->Item_func_minus_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
++ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
++ DBUG_RETURN(FALSE);
}
@@@ -1551,22 -1650,6 +1552,22 @@@ void Item_func_mul::result_precision(
}
- void Item_func_mul::fix_length_and_dec(void)
++bool Item_func_mul::fix_length_and_dec(void)
+{
+ DBUG_ENTER("Item_func_mul::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_mul;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_for_result;);
+ DBUG_ASSERT(aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_mul::type_handler()->Item_func_mul_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
++ if (fix_type_handler(aggregator))
++ DBUG_RETURN(TRUE);
++ if (Item_func_mul::type_handler()->Item_func_mul_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
++ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
++ DBUG_RETURN(FALSE);
+}
+
+
double Item_func_div::real_op()
{
DBUG_ASSERT(fixed == 1);
@@@ -1634,46 -1723,43 +1635,46 @@@ void Item_func_div::result_precision(
}
+void Item_func_div::fix_length_and_dec_double(void)
+{
+ Item_num_op::fix_length_and_dec_double();
+ decimals= MY_MAX(args[0]->decimals, args[1]->decimals) + prec_increment;
+ set_if_smaller(decimals, NOT_FIXED_DEC);
+ uint tmp= float_length(decimals);
+ if (decimals == NOT_FIXED_DEC)
+ max_length= tmp;
+ else
+ {
+ max_length=args[0]->max_length - args[0]->decimals + decimals;
+ set_if_smaller(max_length, tmp);
+ }
+}
+
+
+void Item_func_div::fix_length_and_dec_int(void)
+{
+ set_handler(&type_handler_newdecimal);
+ DBUG_PRINT("info", ("Type changed: %s", type_handler()->name().ptr()));
+ Item_num_op::fix_length_and_dec_decimal();
+}
+
+
- void Item_func_div::fix_length_and_dec(void)
+ bool Item_func_div::fix_length_and_dec()
{
DBUG_ENTER("Item_func_div::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
prec_increment= current_thd->variables.div_precincrement;
- if (Item_num_op::fix_length_and_dec())
- DBUG_RETURN(TRUE);
- switch (Item_func_div::result_type()) {
- case REAL_RESULT:
- {
- decimals=MY_MAX(args[0]->decimals,args[1]->decimals)+prec_increment;
- set_if_smaller(decimals, NOT_FIXED_DEC);
- uint tmp=float_length(decimals);
- if (decimals == NOT_FIXED_DEC)
- max_length= tmp;
- else
- {
- max_length=args[0]->max_length - args[0]->decimals + decimals;
- set_if_smaller(max_length,tmp);
- }
- break;
- }
- case INT_RESULT:
- set_handler_by_result_type(DECIMAL_RESULT);
- DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
- result_precision();
- break;
- case DECIMAL_RESULT:
- result_precision();
- fix_decimals();
- break;
- case STRING_RESULT:
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- }
maybe_null= 1; // devision by zero
+
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_div;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
+ DBUG_ASSERT(!aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_div::type_handler()->Item_func_div_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
++ if (fix_type_handler(aggregator))
++ DBUG_RETURN(TRUE);
++ if (Item_func_div::type_handler()->Item_func_div_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
++ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
+ DBUG_RETURN(FALSE);
}
@@@ -1843,20 -1930,13 +1845,20 @@@ void Item_func_mod::result_precision(
}
- void Item_func_mod::fix_length_and_dec()
+ bool Item_func_mod::fix_length_and_dec()
{
- if (Item_num_op::fix_length_and_dec())
- return true;
- maybe_null= 1;
- unsigned_flag= args[0]->unsigned_flag;
- return false;
+ DBUG_ENTER("Item_func_mod::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
+ maybe_null= true; // division by zero
+ const Type_aggregator *aggregator= &type_handler_data->m_type_aggregator_for_mod;
+ DBUG_EXECUTE_IF("num_op", aggregator= &type_handler_data->m_type_aggregator_non_commutative_test;);
+ DBUG_ASSERT(!aggregator->is_commutative());
- if (!fix_type_handler(aggregator))
- {
- Item_func_mod::type_handler()->Item_func_mod_fix_length_and_dec(this);
- DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- }
- DBUG_VOID_RETURN;
++ if (fix_type_handler(aggregator))
++ DBUG_RETURN(TRUE);
++ if (Item_func_mod::type_handler()->Item_func_mod_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
++ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
++ DBUG_RETURN(FALSE);
}
@@@ -1929,38 -2012,8 +1931,40 @@@ void Item_func_neg::fix_length_and_dec_
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
}
}
- unsigned_flag= 0;
+ unsigned_flag= false;
+}
+
+
+void Item_func_neg::fix_length_and_dec_double()
+{
+ set_handler(&type_handler_double);
+ decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
+ max_length= args[0]->max_length + 1;
+ // Limit length with something reasonable
+ uint32 mlen= type_handler()->max_display_length(this);
+ set_if_smaller(max_length, mlen);
+ unsigned_flag= false;
+}
+
+
+void Item_func_neg::fix_length_and_dec_decimal()
+{
+ set_handler(&type_handler_newdecimal);
+ decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
+ max_length= args[0]->max_length + 1;
+ unsigned_flag= false;
+}
+
+
- void Item_func_neg::fix_length_and_dec()
++bool Item_func_neg::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_func_neg::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
- args[0]->cast_to_int_type_handler()->Item_func_neg_fix_length_and_dec(this);
++ if (args[0]->cast_to_int_type_handler()->
++ Item_func_neg_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@@ -1999,50 -2052,23 +2003,51 @@@ my_decimal *Item_func_abs::decimal_op(m
return 0;
}
-
+void Item_func_abs::fix_length_and_dec_int()
+{
+ max_length= args[0]->max_length;
+ unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
+}
+
-bool Item_func_abs::fix_length_and_dec()
+void Item_func_abs::fix_length_and_dec_double()
{
- if (Item_func_num1::fix_length_and_dec())
- return TRUE;
+ set_handler(&type_handler_double);
+ decimals= args[0]->decimals; // Preserve NOT_FIXED_DEC
+ max_length= float_length(decimals);
unsigned_flag= args[0]->unsigned_flag;
- return FALSE;
}
-/** Gateway to natural LOG function. */
-double Item_func_ln::val_real()
+void Item_func_abs::fix_length_and_dec_decimal()
{
- DBUG_ASSERT(fixed == 1);
- double value= args[0]->val_real();
- if ((null_value= args[0]->null_value))
- return 0.0;
+ set_handler(&type_handler_newdecimal);
+ decimals= args[0]->decimal_scale(); // Do not preserve NOT_FIXED_DEC
+ max_length= args[0]->max_length;
+ unsigned_flag= args[0]->unsigned_flag;
+}
+
+
- void Item_func_abs::fix_length_and_dec()
++bool Item_func_abs::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_func_abs::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
- args[0]->cast_to_int_type_handler()->Item_func_abs_fix_length_and_dec(this);
++ if (args[0]->cast_to_int_type_handler()->
++ Item_func_abs_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- DBUG_VOID_RETURN;
++ DBUG_RETURN(FALSE);
+}
+
+
+/** Gateway to natural LOG function. */
+double Item_func_ln::val_real()
+{
+ DBUG_ASSERT(fixed == 1);
+ double value= args[0]->val_real();
+ if ((null_value= args[0]->null_value))
+ return 0.0;
if (value <= 0.0)
{
signal_divide_by_null();
@@@ -2274,38 -2303,42 +2279,39 @@@ void Item_func_int_val::fix_length_and_
set_if_smaller(max_length,tmp);
decimals= 0;
- // Note, cast_to_int_type() can return TIME_RESULT
- switch (args[0]->cast_to_int_type())
+ /*
+ -2 because in most high position can't be used any digit for longlong
+ and one position for increasing value during operation
+ */
+ if (args[0]->max_length - args[0]->decimals >= DECIMAL_LONGLONG_DIGITS - 2)
{
- case STRING_RESULT:
- case REAL_RESULT:
- set_handler_by_result_type(REAL_RESULT);
- max_length= float_length(decimals);
- break;
- case INT_RESULT:
- case TIME_RESULT:
- case DECIMAL_RESULT:
- /*
- -2 because in most high position can't be used any digit for longlong
- and one position for increasing value during operation
- */
- if ((args[0]->max_length - args[0]->decimals) >=
- (DECIMAL_LONGLONG_DIGITS - 2))
- {
- set_handler_by_result_type(DECIMAL_RESULT);
- }
- else
- {
- unsigned_flag= args[0]->unsigned_flag;
- set_handler_by_result_type(INT_RESULT);
- }
- break;
- case ROW_RESULT:
- DBUG_ASSERT(0);
+ set_handler(&type_handler_newdecimal);
+ }
+ else
+ {
+ unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
}
- DBUG_PRINT("info", ("Type: %s",
- (result_type() == REAL_RESULT ? "REAL_RESULT" :
- result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- result_type() == INT_RESULT ? "INT_RESULT" :
- "--ILLEGAL!!!--")));
+}
+
+void Item_func_int_val::fix_length_and_dec_double()
+{
+ set_handler(&type_handler_double);
+ max_length= float_length(0);
+ decimals= 0;
+}
+
+
- void Item_func_int_val::fix_length_and_dec()
++bool Item_func_int_val::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_func_int_val::fix_length_and_dec");
+ DBUG_PRINT("info", ("name %s", func_name()));
- args[0]->cast_to_int_type_handler()->
- Item_func_int_val_fix_length_and_dec(this);
++ if (args[0]->cast_to_int_type_handler()->
++ Item_func_int_val_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@@ -2403,92 -2436,86 +2409,91 @@@ my_decimal *Item_func_floor::decimal_op
}
-bool Item_func_round::fix_length_and_dec()
+void Item_func_round::fix_length_and_dec_decimal(uint decimals_to_set)
{
- int decimals_to_set;
- longlong val1;
- bool val1_unsigned;
-
+ int decimals_delta= args[0]->decimals - decimals_to_set;
+ int length_increase= (decimals_delta <= 0 || truncate) ? 0 : 1;
+ int precision= args[0]->decimal_precision() + length_increase -
+ decimals_delta;
+ DBUG_ASSERT(decimals_to_set <= DECIMAL_MAX_SCALE);
+ set_handler(&type_handler_newdecimal);
+ unsigned_flag= args[0]->unsigned_flag;
+ decimals= decimals_to_set;
+ max_length= my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag);
+}
+
+void Item_func_round::fix_length_and_dec_double(uint decimals_to_set)
+{
+ set_handler(&type_handler_double);
unsigned_flag= args[0]->unsigned_flag;
- if (!args[1]->const_item())
+ decimals= decimals_to_set;
+ max_length= float_length(decimals_to_set);
+}
+
+
+void Item_func_round::fix_arg_decimal()
+{
+ if (args[1]->const_item())
{
- decimals= args[0]->decimals;
- max_length= float_length(decimals);
- if (args[0]->result_type() == DECIMAL_RESULT)
- {
- max_length++;
- set_handler_by_result_type(DECIMAL_RESULT);
- }
+ uint dec= (uint) args[1]->val_uint_from_val_int(DECIMAL_MAX_SCALE);
+ if (args[1]->null_value)
+ fix_length_and_dec_double(NOT_FIXED_DEC);
else
- set_handler_by_result_type(REAL_RESULT);
- return FALSE;
+ fix_length_and_dec_decimal(dec);
+ }
+ else
+ {
+ set_handler(&type_handler_newdecimal);
+ unsigned_flag= args[0]->unsigned_flag;
+ decimals= args[0]->decimals;
+ max_length= float_length(args[0]->decimals) + 1;
}
+}
- val1= args[1]->val_int();
- if ((null_value= args[1]->null_value))
- return FALSE;
- val1_unsigned= args[1]->unsigned_flag;
- if (val1 < 0)
- decimals_to_set= val1_unsigned ? INT_MAX : 0;
+void Item_func_round::fix_arg_double()
+{
+ if (args[1]->const_item())
+ {
+ uint dec= (uint) args[1]->val_uint_from_val_int(NOT_FIXED_DEC);
+ fix_length_and_dec_double(args[1]->null_value ? NOT_FIXED_DEC : dec);
+ }
else
- decimals_to_set= (val1 > INT_MAX) ? INT_MAX : (int) val1;
+ fix_length_and_dec_double(args[0]->decimals);
+}
+
- if (args[0]->decimals == NOT_FIXED_DEC)
+void Item_func_round::fix_arg_int()
+{
+ if (args[1]->const_item())
{
- decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
- max_length= float_length(decimals);
- set_handler_by_result_type(REAL_RESULT);
- return FALSE;
- }
-
- switch (args[0]->result_type()) {
- case REAL_RESULT:
- case STRING_RESULT:
- set_handler_by_result_type(REAL_RESULT);
- decimals= MY_MIN(decimals_to_set, NOT_FIXED_DEC);
- max_length= float_length(decimals);
- break;
- case INT_RESULT:
- if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
+ longlong val1= args[1]->val_int();
+ bool val1_is_negative= val1 < 0 && !args[1]->unsigned_flag;
+ uint decimals_to_set= val1_is_negative ?
+ 0 : (uint) MY_MIN(val1, DECIMAL_MAX_SCALE);
+ if (args[1]->null_value)
+ fix_length_and_dec_double(NOT_FIXED_DEC);
+ else if ((!decimals_to_set && truncate) ||
+ args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS)
{
- int length_can_increase= MY_TEST(!truncate && (val1 < 0) &&
- !val1_unsigned);
+ // Length can increase in some cases: ROUND(9,-1) -> 10
+ int length_can_increase= MY_TEST(!truncate && val1_is_negative);
max_length= args[0]->max_length + length_can_increase;
- /* Here we can keep INT_RESULT */
- set_handler_by_result_type(INT_RESULT);
+ // Here we can keep INT_RESULT
+ unsigned_flag= args[0]->unsigned_flag;
decimals= 0;
- break;
+ set_handler(type_handler_long_or_longlong());
}
- /* fall through */
- case DECIMAL_RESULT:
- {
- set_handler_by_result_type(DECIMAL_RESULT);
- decimals_to_set= MY_MIN(DECIMAL_MAX_SCALE, decimals_to_set);
- int decimals_delta= args[0]->decimals - decimals_to_set;
- int precision= args[0]->decimal_precision();
- int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;
-
- precision-= decimals_delta - length_increase;
- decimals= MY_MIN(decimals_to_set, DECIMAL_MAX_SCALE);
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
- break;
- }
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0); /* This result type isn't handled */
+ else
+ fix_length_and_dec_decimal(decimals_to_set);
}
- return FALSE;
+ else
+ fix_length_and_dec_double(args[0]->decimals);
-
}
+
double my_double_round(double value, longlong dec, bool dec_unsigned,
bool truncate)
{
@@@ -5472,9 -5635,10 +5480,10 @@@ bool Item_func_get_user_var::fix_length
{
collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
null_value= 1;
- set_handler_by_field_type(MYSQL_TYPE_LONG_BLOB);
+ set_handler(&type_handler_long_blob);
max_length= MAX_BLOB_WIDTH;
}
+ return false;
}
@@@ -6367,12 -6639,10 +6377,12 @@@ bool Item_func_sp::fix_length_and_dec(
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
DBUG_ASSERT(sp_result_field);
- Type_std_attributes::set(sp_result_field);
+ Type_std_attributes::set(sp_result_field->type_std_attributes());
+ // There is a bug in the line below. See MDEV-11292 for details.
+ collation.derivation= DERIVATION_COERCIBLE;
maybe_null= 1;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
@@@ -6678,308 -6981,10 +6688,309 @@@ my_decimal *Item_func_last_value::val_d
}
+bool Item_func_last_value::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+{
+ evaluate_sideeffects();
+ bool tmp= last_value->get_date(ltime, fuzzydate);
+ null_value= last_value->null_value;
+ return tmp;
+}
+
+
- void Item_func_last_value::fix_length_and_dec()
+ bool Item_func_last_value::fix_length_and_dec()
{
last_value= args[arg_count -1];
Type_std_attributes::set(last_value);
maybe_null= last_value->maybe_null;
+ return FALSE;
}
+
+
+void Cursor_ref::print_func(String *str, const char *func_name)
+{
+ append_identifier(current_thd, str, &m_cursor_name);
+ str->append(func_name);
+}
+
+
+sp_cursor *Cursor_ref::get_open_cursor_or_error()
+{
+ THD *thd= current_thd;
+ sp_cursor *c= thd->spcont->get_cursor(m_cursor_offset);
+ DBUG_ASSERT(c);
+ if (!c/*safety*/ || !c->is_open())
+ {
+ my_message(ER_SP_CURSOR_NOT_OPEN, ER_THD(thd, ER_SP_CURSOR_NOT_OPEN),
+ MYF(0));
+ return NULL;
+ }
+ return c;
+}
+
+
+longlong Item_func_cursor_isopen::val_int()
+{
+ sp_cursor *c= current_thd->spcont->get_cursor(m_cursor_offset);
+ DBUG_ASSERT(c != NULL);
+ return c ? c->is_open() : 0;
+}
+
+
+longlong Item_func_cursor_found::val_int()
+{
+ sp_cursor *c= get_open_cursor_or_error();
+ return !(null_value= (!c || c->fetch_count() == 0)) && c->found();
+}
+
+
+longlong Item_func_cursor_notfound::val_int()
+{
+ sp_cursor *c= get_open_cursor_or_error();
+ return !(null_value= (!c || c->fetch_count() == 0)) && !c->found();
+}
+
+
+longlong Item_func_cursor_rowcount::val_int()
+{
+ sp_cursor *c= get_open_cursor_or_error();
+ return !(null_value= !c) ? c->row_count() : 0;
+}
+
+/*****************************************************************************
+ SEQUENCE functions
+*****************************************************************************/
+
+longlong Item_func_nextval::val_int()
+{
+ longlong value;
+ int error;
+ const char *key;
+ uint length= get_table_def_key(table_list, &key);
+ THD *thd;
+ SEQUENCE_LAST_VALUE *entry;
+ char buff[80];
+ String key_buff(buff,sizeof(buff), &my_charset_bin);
+ DBUG_ENTER("Item_func_nextval::val_int");
+ update_table();
+ DBUG_ASSERT(table && table->s->sequence);
+ thd= table->in_use;
+
+ if (thd->count_cuted_fields == CHECK_FIELD_EXPRESSION)
+ {
+ /* Alter table checking if function works */
+ null_value= 0;
+ DBUG_RETURN(0);
+ }
+
+ if (table->s->tmp_table != NO_TMP_TABLE)
+ {
+ /*
+ Temporary tables has an extra \0 at end to distinguish it from
+ normal tables
+ */
+ key_buff.copy(key, length, &my_charset_bin);
+ key_buff.append((char) 0);
+ key= key_buff.ptr();
+ length++;
+ }
+
+ if (!(entry= ((SEQUENCE_LAST_VALUE*)
+ my_hash_search(&thd->sequences, (uchar*) key, length))))
+ {
+ if (!(key= (char*) my_memdup(key, length, MYF(MY_WME))) ||
+ !(entry= new SEQUENCE_LAST_VALUE((uchar*) key, length)))
+ {
+ /* EOM, error given */
+ my_free((char*) key);
+ delete entry;
+ null_value= 1;
+ DBUG_RETURN(0);
+ }
+ if (my_hash_insert(&thd->sequences, (uchar*) entry))
+ {
+ /* EOM, error given */
+ delete entry;
+ null_value= 1;
+ DBUG_RETURN(0);
+ }
+ }
+ entry->null_value= null_value= 0;
+ value= table->s->sequence->next_value(table, 0, &error);
+ entry->value= value;
+ entry->set_version(table);
+
+ if (unlikely(error)) // Warning already printed
+ entry->null_value= null_value= 1; // For not strict mode
+ DBUG_RETURN(value);
+}
+
+
+/* Print for nextval and lastval */
+
+void Item_func_nextval::print(String *str, enum_query_type query_type)
+{
+ char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
+ LEX_CSTRING d_name= table_list->db;
+ LEX_CSTRING t_name= table_list->table_name;
+ bool use_db_name= d_name.str && d_name.str[0];
+ THD *thd= current_thd; // Don't trust 'table'
+
+ str->append(func_name());
+ str->append('(');
+
+ /*
+ for next_val we assume that table_list has been updated to contain
+ the current db.
+ */
+
+ if (lower_case_table_names > 0)
+ {
+ strmake(t_name_buff, t_name.str, MAX_ALIAS_NAME-1);
+ t_name.length= my_casedn_str(files_charset_info, t_name_buff);
+ t_name.str= t_name_buff;
+ if (use_db_name)
+ {
+ strmake(d_name_buff, d_name.str, MAX_ALIAS_NAME-1);
+ d_name.length= my_casedn_str(files_charset_info, d_name_buff);
+ d_name.str= d_name_buff;
+ }
+ }
+
+ if (use_db_name)
+ {
+ append_identifier(thd, str, &d_name);
+ str->append('.');
+ }
+ append_identifier(thd, str, &t_name);
+ str->append(')');
+}
+
+
+/* Return last used value for sequence or NULL if sequence hasn't been used */
+
+longlong Item_func_lastval::val_int()
+{
+ const char *key;
+ SEQUENCE_LAST_VALUE *entry;
+ uint length= get_table_def_key(table_list, &key);
+ THD *thd;
+ char buff[80];
+ String key_buff(buff,sizeof(buff), &my_charset_bin);
+ DBUG_ENTER("Item_func_lastval::val_int");
+ update_table();
+ thd= table->in_use;
+
+ if (table->s->tmp_table != NO_TMP_TABLE)
+ {
+ /*
+ Temporary tables has an extra \0 at end to distinguish it from
+ normal tables
+ */
+ key_buff.copy(key, length, &my_charset_bin);
+ key_buff.append((char) 0);
+ key= key_buff.ptr();
+ length++;
+ }
+
+ if (!(entry= ((SEQUENCE_LAST_VALUE*)
+ my_hash_search(&thd->sequences, (uchar*) key, length))))
+ {
+ /* Sequence not used */
+ null_value= 1;
+ DBUG_RETURN(0);
+ }
+ if (entry->check_version(table))
+ {
+ /* Table droped and re-created, remove current version */
+ my_hash_delete(&thd->sequences, (uchar*) entry);
+ null_value= 1;
+ DBUG_RETURN(0);
+ }
+
+ null_value= entry->null_value;
+ DBUG_RETURN(entry->value);
+}
+
+
+/*
+ Sets next value to be returned from sequences
+
+ SELECT setval('foo', 42, 0); Next nextval will return 43
+ SELECT setval('foo', 42, 0, true); Same as above
+ SELECT setval('foo', 42, 0, false); Next nextval will return 42
+*/
+
+longlong Item_func_setval::val_int()
+{
+ longlong value;
+ int error;
+ THD *thd;
+ DBUG_ENTER("Item_func_setval::val_int");
+
+ update_table();
+ DBUG_ASSERT(table && table->s->sequence);
+ thd= table->in_use;
+
+ if (unlikely(thd->count_cuted_fields == CHECK_FIELD_EXPRESSION))
+ {
+ /* Alter table checking if function works */
+ null_value= 0;
+ DBUG_RETURN(0);
+ }
+
+ value= nextval;
+ error= table->s->sequence->set_value(table, nextval, round, is_used);
+ if (unlikely(error))
+ {
+ null_value= 1;
+ value= 0;
+ }
+ DBUG_RETURN(value);
+}
+
+
+/* Print for setval */
+
+void Item_func_setval::print(String *str, enum_query_type query_type)
+{
+ char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
+ LEX_CSTRING d_name= table_list->db;
+ LEX_CSTRING t_name= table_list->table_name;
+ bool use_db_name= d_name.str && d_name.str[0];
+ THD *thd= current_thd; // Don't trust 'table'
+
+ str->append(func_name());
+ str->append('(');
+
+ /*
+ for next_val we assume that table_list has been updated to contain
+ the current db.
+ */
+
+ if (lower_case_table_names > 0)
+ {
+ strmake(t_name_buff, t_name.str, MAX_ALIAS_NAME-1);
+ t_name.length= my_casedn_str(files_charset_info, t_name_buff);
+ t_name.str= t_name_buff;
+ if (use_db_name)
+ {
+ strmake(d_name_buff, d_name.str, MAX_ALIAS_NAME-1);
+ d_name.length= my_casedn_str(files_charset_info, d_name_buff);
+ d_name.str= d_name_buff;
+ }
+ }
+
+ if (use_db_name)
+ {
+ append_identifier(thd, str, &d_name);
+ str->append('.');
+ }
+ append_identifier(thd, str, &t_name);
+ str->append(',');
+ str->append_longlong(nextval);
+ str->append(',');
+ str->append_longlong(is_used);
+ str->append(',');
+ str->append_ulonglong(round);
+ str->append(')');
+}
diff --cc sql/item_func.h
index 049ef82f71e,0969cf2e3f0..b4f3cce612d
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@@ -394,11 -397,10 +394,15 @@@ public
my_decimal *val_decimal(my_decimal *decimal_value);
longlong val_int()
{ DBUG_ASSERT(fixed == 1); return (longlong) rint(val_real()); }
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ { return get_date_from_real(ltime, fuzzydate); }
+ const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec()
- { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
+ bool fix_length_and_dec()
- { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); return FALSE; }
++ {
++ decimals= NOT_FIXED_DEC;
++ max_length= float_length(decimals);
++ return FALSE;
++ }
};
@@@ -781,86 -617,20 +785,86 @@@ public
{ collation.set_numeric(); }
double val_real();
String *val_str(String*str);
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ { return get_date_from_int(ltime, fuzzydate); }
+ const Type_handler *type_handler() const= 0;
- void fix_length_and_dec() {}
+ bool fix_length_and_dec() { return FALSE; }
};
-class Item_func_connection_id :public Item_int_func
+class Item_long_func: public Item_int_func
+{
+public:
+ Item_long_func(THD *thd): Item_int_func(thd) { }
+ Item_long_func(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_long_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_long_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_long_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
+ Item_long_func(THD *thd, Item_long_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_long; }
- void fix_length_and_dec() { max_length= 11; }
++ bool fix_length_and_dec() { max_length= 11; return FALSE; }
+};
+
+
+class Item_longlong_func: public Item_int_func
+{
+public:
+ Item_longlong_func(THD *thd): Item_int_func(thd) { }
+ Item_longlong_func(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_longlong_func(THD *thd, Item *a, Item *b, Item *c, Item *d):
+ Item_int_func(thd, a, b, c, d) {}
+ Item_longlong_func(THD *thd, List<Item> &list): Item_int_func(thd, list) { }
+ Item_longlong_func(THD *thd, Item_longlong_func *item) :Item_int_func(thd, item) {}
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
+};
+
+
+class Cursor_ref
+{
+protected:
+ LEX_CSTRING m_cursor_name;
+ uint m_cursor_offset;
+ class sp_cursor *get_open_cursor_or_error();
+ Cursor_ref(const LEX_CSTRING *name, uint offset)
+ :m_cursor_name(*name), m_cursor_offset(offset)
+ { }
+ void print_func(String *str, const char *func_name);
+};
+
+
+
+class Item_func_cursor_rowcount: public Item_longlong_func,
+ public Cursor_ref
+{
+public:
+ Item_func_cursor_rowcount(THD *thd, const LEX_CSTRING *name, uint offset)
+ :Item_longlong_func(thd), Cursor_ref(name, offset) { maybe_null= true; }
+ const char *func_name() const { return "%ROWCOUNT"; }
+ longlong val_int();
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), arg, VCOL_SESSION_FUNC);
+ }
+ void print(String *str, enum_query_type query_type)
+ {
+ return Cursor_ref::print_func(str, func_name());
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_cursor_rowcount>(thd, this); }
+};
+
+
+
+class Item_func_connection_id :public Item_long_func
{
longlong value;
public:
- Item_func_connection_id(THD *thd): Item_int_func(thd) {}
+ Item_func_connection_id(THD *thd): Item_long_func(thd) { unsigned_flag=1; }
const char *func_name() const { return "connection_id"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
bool check_vcol_func_processor(void *arg)
@@@ -903,23 -667,7 +907,23 @@@ public
*/
set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1));
fix_char_length(char_length);
- return FALSE;
+ }
+ void fix_length_and_dec_string()
+ {
+ /*
+ For strings, use decimal_int_part() instead of max_char_length().
+ This is important for Item_hex_hybrid:
+ SELECT CAST(0x1FFFFFFFF AS SIGNED);
+ Length is 5, decimal_int_part() is 13.
+ */
+ uint32 char_length= MY_MIN(args[0]->decimal_int_part(),
+ MY_INT64_NUM_DECIMAL_DIGITS);
+ set_if_bigger(char_length, 1U + (unsigned_flag ? 0 : 1));
+ fix_char_length(char_length);
+ }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_func_signed_fix_length_and_dec(this);
++ return args[0]->type_handler()->Item_func_signed_fix_length_and_dec(this);
}
virtual void print(String *str, enum_query_type query_type);
uint decimal_precision() const { return args[0]->decimal_precision(); }
@@@ -949,14 -691,9 +953,14 @@@ public
null_value= args[0]->null_value;
return value;
}
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this);
++ return args[0]->type_handler()->Item_func_unsigned_fix_length_and_dec(this);
+ }
+ uint decimal_precision() const { return max_length; }
virtual void print(String *str, enum_query_type query_type);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_unsigned>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_unsigned>(thd, this); }
};
@@@ -976,14 -712,9 +980,15 @@@ public
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal*);
- enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
- bool fix_length_and_dec() { return FALSE; }
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ { return get_date_from_decimal(ltime, fuzzydate); }
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
+ void fix_length_and_dec_generic() {}
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_decimal_typecast_fix_length_and_dec(this);
++ return
++ args[0]->type_handler()->Item_decimal_typecast_fix_length_and_dec(this);
+ }
const char *func_name() const { return "decimal_typecast"; }
virtual void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
@@@ -1002,11 -733,8 +1007,12 @@@ public
max_length= (uint32) len;
}
double val_real();
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
- bool fix_length_and_dec() { maybe_null= 1; return FALSE; }
+ void fix_length_and_dec_generic() { maybe_null= 1; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this);
++ return
++ args[0]->type_handler()->Item_double_typecast_fix_length_and_dec(this);
+ }
const char *func_name() const { return "double_typecast"; }
virtual void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
@@@ -1032,7 -761,6 +1038,7 @@@ public
Item_func_additive_op(thd, a, b) {}
const char *func_name() const { return "+"; }
enum precedence precedence() const { return ADD_PRECEDENCE; }
- void fix_length_and_dec();
++ bool fix_length_and_dec();
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);
@@@ -1050,25 -778,9 +1056,25 @@@ public
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_minus>(thd, mem_root, this); }
+ void fix_unsigned_flag();
+ void fix_length_and_dec_double()
+ {
+ Item_func_additive_op::fix_length_and_dec_double();
+ fix_unsigned_flag();
+ }
+ void fix_length_and_dec_decimal()
+ {
+ Item_func_additive_op::fix_length_and_dec_decimal();
+ fix_unsigned_flag();
+ }
+ void fix_length_and_dec_int()
+ {
+ Item_func_additive_op::fix_length_and_dec_int();
+ fix_unsigned_flag();
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_minus>(thd, this); }
};
@@@ -1083,11 -795,10 +1089,11 @@@ public
double real_op();
my_decimal *decimal_op(my_decimal *);
void result_precision();
- void fix_length_and_dec();
++ bool fix_length_and_dec();
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_mul>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_mul>(thd, this); }
};
@@@ -1101,12 -812,10 +1107,12 @@@ public
my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "/"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_int();
void result_precision();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_div>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_div>(thd, this); }
};
@@@ -1118,9 -827,7 +1124,9 @@@ public
longlong val_int();
const char *func_name() const { return "DIV"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
+ const Type_handler *type_handler() const
+ { return type_handler_long_or_longlong(); }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void print(String *str, enum_query_type query_type)
{
print_op(str, query_type);
@@@ -1141,31 -848,14 +1147,31 @@@ public
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);
- const char *func_name() const { return "%"; }
+ const char *func_name() const { return "MOD"; }
enum precedence precedence() const { return MUL_PRECEDENCE; }
void result_precision();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
+ void fix_length_and_dec_double()
+ {
+ Item_num_op::fix_length_and_dec_double();
+ unsigned_flag= args[0]->unsigned_flag;
+ }
+ void fix_length_and_dec_decimal()
+ {
+ Item_num_op::fix_length_and_dec_decimal();
+ unsigned_flag= args[0]->unsigned_flag;
+ }
+ void fix_length_and_dec_int()
+ {
+ max_length= MY_MAX(args[0]->max_length, args[1]->max_length);
+ decimals= 0;
+ unsigned_flag= args[0]->unsigned_flag;
+ set_handler(type_handler_long_or_longlong());
+ }
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_mod>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_mod>(thd, this); }
};
@@@ -1184,14 -874,13 +1190,14 @@@ public
str->append(func_name());
args[0]->print_parenthesised(str, query_type, precedence());
}
+ void fix_length_and_dec_int();
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_decimal();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
uint decimal_precision() const { return args[0]->decimal_precision(); }
- bool check_partition_func_processor(void *int_arg) {return FALSE;}
- bool check_vcol_func_processor(void *arg) { return FALSE;}
bool need_parentheses_in_default() { return true; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_neg>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_neg>(thd, this); }
};
@@@ -1203,12 -892,11 +1209,12 @@@ public
longlong int_op();
my_decimal *decimal_op(my_decimal *);
const char *func_name() const { return "abs"; }
+ void fix_length_and_dec_int();
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_decimal();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- bool check_partition_func_processor(void *int_arg) {return FALSE;}
- bool check_vcol_func_processor(void *arg) { return FALSE;}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_abs>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_abs>(thd, this); }
};
// A class to handle logarithmic and trigonometric functions
@@@ -1381,9 -1068,7 +1388,9 @@@ class Item_func_int_val :public Item_fu
{
public:
Item_func_int_val(THD *thd, Item *a): Item_func_num1(thd, a) {}
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_int_or_decimal();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
};
@@@ -1426,15 -1113,9 +1433,15 @@@ public
double real_op();
longlong int_op();
my_decimal *decimal_op(my_decimal *);
- bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_round>(thd, mem_root, this); }
+ void fix_arg_decimal();
+ void fix_arg_int();
+ void fix_arg_double();
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_func_round_fix_length_and_dec(this);
++ return args[0]->type_handler()->Item_func_round_fix_length_and_dec(this);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_round>(thd, this); }
};
@@@ -1465,18 -1144,14 +1472,18 @@@ private
};
-class Item_func_sign :public Item_int_func
+class Item_func_sign :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_real(func_name()); }
public:
- Item_func_sign(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_sign(THD *thd, Item *a): Item_long_func(thd, a) {}
const char *func_name() const { return "sign"; }
+ uint decimal_precision() const { return 1; }
- void fix_length_and_dec() { fix_char_length(2); }
++ bool fix_length_and_dec() { fix_char_length(2); return FALSE; }
longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_sign>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sign>(thd, this); }
};
@@@ -1492,10 -1165,10 +1499,14 @@@ public
Item_real_func(thd, a), name(name_arg), mul(mul_arg), add(add_arg) {}
double val_real();
const char *func_name() const { return name; }
- void fix_length_and_dec()
- { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); }
+ bool fix_length_and_dec()
- { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_units>(thd, mem_root, this); }
++ {
++ decimals= NOT_FIXED_DEC;
++ max_length= float_length(decimals);
++ return FALSE;
++ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_units>(thd, this); }
};
@@@ -1520,69 -1191,12 +1531,70 @@@ public
Item_func_min_max(THD *thd, List<Item> &list, int cmp_sign_arg):
Item_hybrid_func(thd, list), cmp_sign(cmp_sign_arg)
{}
- double val_real();
- longlong val_int();
- String *val_str(String *);
- my_decimal *val_decimal(my_decimal *);
- bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
- bool fix_length_and_dec();
+ String *val_str_native(String *str);
+ double val_real_native();
+ longlong val_int_native();
+ my_decimal *val_decimal_native(my_decimal *);
+ bool get_date_native(MYSQL_TIME *res, ulonglong fuzzydate);
+ bool get_time_native(MYSQL_TIME *res);
+
+ double val_real()
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_val_real(this);
+ }
+ longlong val_int()
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_val_int(this);
+ }
+ String *val_str(String *str)
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_val_str(this, str);
+ }
+ my_decimal *val_decimal(my_decimal *dec)
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_val_decimal(this, dec);
+ }
+ bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date)
+ {
+ DBUG_ASSERT(fixed);
+ return Item_func_min_max::type_handler()->
+ Item_func_min_max_get_date(this, res, fuzzy_date);
+ }
+ void aggregate_attributes_real(Item **items, uint nitems)
+ {
+ /*
+ Aggregating attributes for the double data type for LEAST/GREATEST
+ is almost the same with aggregating for CASE-alike hybrid functions,
+ (CASE..THEN, COALESCE, IF, etc).
+ There is one notable difference though, when a numeric argument is mixed
+ with a string argument:
+ - CASE-alike functions return a string data type in such cases
+ COALESCE(10,'x') -> VARCHAR(2) = '10'
+ - LEAST/GREATEST returns double:
+ GREATEST(10,'10e4') -> DOUBLE = 100000
+ As the string argument can represent a number in the scientific notation,
+ like in the example above, max_length of the result can be longer than
+ max_length of the arguments. To handle this properly, max_length is
+ additionally assigned to the result of float_length(decimals).
+ */
+ Item_func::aggregate_attributes_real(items, nitems);
+ max_length= float_length(decimals);
+ }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ if (aggregate_for_min_max(func_name(), args, arg_count))
- return;
++ return true;
+ fix_attributes(args, arg_count);
++ return false;
+ }
};
class Item_func_min :public Item_func_min_max
@@@ -1615,35 -1229,27 +1627,36 @@@ public
Item_func_rollup_const(THD *thd, Item *a): Item_func(thd, a)
{
name= a->name;
- name_length= a->name_length;
}
- double val_real() { return args[0]->val_real(); }
- longlong val_int() { return args[0]->val_int(); }
- String *val_str(String *str) { return args[0]->val_str(str); }
- my_decimal *val_decimal(my_decimal *dec) { return args[0]->val_decimal(dec); }
+ double val_real() { return val_real_from_item(args[0]); }
+ longlong val_int() { return val_int_from_item(args[0]); }
+ String *val_str(String *str) { return val_str_from_item(args[0], str); }
+ my_decimal *val_decimal(my_decimal *dec)
+ { return val_decimal_from_item(args[0], dec); }
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ { return get_date_from_item(args[0], ltime, fuzzydate); }
const char *func_name() const { return "rollup_const"; }
bool const_item() const { return 0; }
- Item_result result_type() const { return args[0]->result_type(); }
- enum_field_types field_type() const { return args[0]->field_type(); }
+ const Type_handler *type_handler() const { return args[0]->type_handler(); }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
collation= args[0]->collation;
max_length= args[0]->max_length;
- decimals=args[0]->decimals;
- /* The item could be a NULL constant. */
- null_value= args[0]->is_null();
+ decimals=args[0]->decimals;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_rollup_const>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_rollup_const>(thd, this); }
+};
+
+
+class Item_long_func_length: public Item_long_func
+{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_str(func_name()); }
+public:
+ Item_long_func_length(THD *thd, Item *a): Item_long_func(thd, a) {}
- void fix_length_and_dec() { max_length=10; }
++ bool fix_length_and_dec() { max_length=10; return FALSE; }
};
@@@ -1651,48 -1257,44 +1664,49 @@@ class Item_func_octet_length :public It
{
String value;
public:
- Item_func_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_octet_length(THD *thd, Item *a): Item_long_func_length(thd, a) {}
longlong val_int();
- const char *func_name() const { return "length"; }
- bool fix_length_and_dec() { max_length=10; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_length>(thd, mem_root, this); }
+ const char *func_name() const { return "octet_length"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_octet_length>(thd, this); }
};
-class Item_func_bit_length :public Item_func_length
+class Item_func_bit_length :public Item_longlong_func
{
+ String value;
public:
- Item_func_bit_length(THD *thd, Item *a): Item_func_length(thd, a) {}
- longlong val_int()
- { DBUG_ASSERT(fixed == 1); return Item_func_length::val_int()*8; }
+ Item_func_bit_length(THD *thd, Item *a): Item_longlong_func(thd, a) {}
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ max_length= 11; // 0x100000000*8 = 34,359,738,368
++ return FALSE;
+ }
+ longlong val_int();
const char *func_name() const { return "bit_length"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_bit_length>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_bit_length>(thd, this); }
};
-class Item_func_char_length :public Item_int_func
+class Item_func_char_length :public Item_long_func_length
{
String value;
public:
- Item_func_char_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_char_length(THD *thd, Item *a): Item_long_func_length(thd, a) {}
longlong val_int();
const char *func_name() const { return "char_length"; }
- bool fix_length_and_dec() { max_length=10; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_char_length>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_char_length>(thd, this); }
};
-class Item_func_coercibility :public Item_int_func
+class Item_func_coercibility :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_str(func_name()); }
public:
- Item_func_coercibility(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_coercibility(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "coercibility"; }
- void fix_length_and_dec() { max_length=10; maybe_null= 0; }
+ bool fix_length_and_dec() { max_length=10; maybe_null= 0; return FALSE; }
bool eval_not_null_tables(void *)
{
not_null_tables_cache= 0;
@@@ -1722,20 -1312,14 +1736,20 @@@ class Item_func_locate :public Item_lon
String value1,value2;
DTCollation cmp_collation;
public:
- Item_func_locate(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
- Item_func_locate(THD *thd, Item *a, Item *b, Item *c): Item_int_func(thd, a, b, c) {}
+ Item_func_locate(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b) {}
+ Item_func_locate(THD *thd, Item *a, Item *b, Item *c)
+ :Item_long_func(thd, a, b, c) {}
const char *func_name() const { return "locate"; }
longlong val_int();
- void fix_length_and_dec()
- bool fix_length_and_dec();
++ bool fix_length_and_dec()
+ {
+ max_length= MY_INT32_NUM_DECIMAL_DIGITS;
- agg_arg_charsets_for_comparison(cmp_collation, args, 2);
++ return agg_arg_charsets_for_comparison(cmp_collation, args, 2);
+ }
virtual void print(String *str, enum_query_type query_type);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_locate>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_locate>(thd, this); }
};
@@@ -1745,71 -1329,62 +1759,71 @@@ class Item_func_field :public Item_long
Item_result cmp_type;
DTCollation cmp_collation;
public:
- Item_func_field(THD *thd, List<Item> &list): Item_int_func(thd, list) {}
+ Item_func_field(THD *thd, List<Item> &list): Item_long_func(thd, list) {}
longlong val_int();
const char *func_name() const { return "field"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_field>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_field>(thd, this); }
};
-class Item_func_ascii :public Item_int_func
+class Item_func_ascii :public Item_long_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_str(0, arg_count); }
String value;
public:
- Item_func_ascii(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_ascii(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "ascii"; }
- void fix_length_and_dec() { max_length=3; }
+ bool fix_length_and_dec() { max_length=3; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_ascii>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_ascii>(thd, this); }
};
-class Item_func_ord :public Item_int_func
+class Item_func_ord :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_str(func_name()); }
String value;
public:
- Item_func_ord(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_ord(THD *thd, Item *a): Item_long_func(thd, a) {}
- void fix_length_and_dec() { fix_char_length(7); }
++ bool fix_length_and_dec() { fix_char_length(7); return FALSE; }
longlong val_int();
const char *func_name() const { return "ord"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_ord>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_ord>(thd, this); }
};
-class Item_func_find_in_set :public Item_int_func
+class Item_func_find_in_set :public Item_long_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_str(0, 2); }
String value,value2;
uint enum_value;
ulonglong enum_bit;
DTCollation cmp_collation;
public:
Item_func_find_in_set(THD *thd, Item *a, Item *b):
- Item_int_func(thd, a, b), enum_value(0) {}
+ Item_long_func(thd, a, b), enum_value(0) {}
longlong val_int();
const char *func_name() const { return "find_in_set"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_find_in_set>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_find_in_set>(thd, this); }
};
/* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */
-class Item_func_bit: public Item_int_func
+class Item_func_bit: public Item_longlong_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_int(0, arg_count); }
public:
- Item_func_bit(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
- Item_func_bit(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_bit(THD *thd, Item *a, Item *b): Item_longlong_func(thd, a, b) {}
+ Item_func_bit(THD *thd, Item *a): Item_longlong_func(thd, a) {}
- void fix_length_and_dec() { unsigned_flag= 1; }
+ bool fix_length_and_dec() { unsigned_flag= 1; return FALSE; }
virtual inline void print(String *str, enum_query_type query_type)
{
@@@ -1836,21 -1411,19 +1850,21 @@@ public
longlong val_int();
const char *func_name() const { return "&"; }
enum precedence precedence() const { return BITAND_PRECEDENCE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_bit_and>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_bit_and>(thd, this); }
};
-class Item_func_bit_count :public Item_int_func
+class Item_func_bit_count :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_int(func_name()); }
public:
- Item_func_bit_count(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_bit_count(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "bit_count"; }
- void fix_length_and_dec() { max_length=2; }
+ bool fix_length_and_dec() { max_length=2; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_bit_count>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_bit_count>(thd, this); }
};
class Item_func_shift_left :public Item_func_bit
@@@ -1892,20 -1465,20 +1906,21 @@@ public
};
-class Item_func_last_insert_id :public Item_int_func
+class Item_func_last_insert_id :public Item_longlong_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_int(0, arg_count); }
public:
- Item_func_last_insert_id(THD *thd): Item_int_func(thd) {}
- Item_func_last_insert_id(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_last_insert_id(THD *thd): Item_longlong_func(thd) {}
+ Item_func_last_insert_id(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "last_insert_id"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- unsigned_flag= TRUE;
+ unsigned_flag= true;
if (arg_count)
max_length= args[0]->max_length;
- unsigned_flag=1;
+ return FALSE;
}
bool fix_fields(THD *thd, Item **ref);
bool check_vcol_func_processor(void *arg)
@@@ -1944,13 -1512,10 +1959,13 @@@ public
void item_func_sleep_init(void);
void item_func_sleep_free(void);
-class Item_func_sleep :public Item_int_func
+class Item_func_sleep :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_real(func_name()); }
public:
- Item_func_sleep(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_sleep(THD *thd, Item *a): Item_long_func(thd, a) {}
- void fix_length_and_dec() { fix_char_length(1); }
++ bool fix_length_and_dec() { fix_char_length(1); return FALSE; }
bool const_item() const { return 0; }
const char *func_name() const { return "sleep"; }
table_map used_tables() const
@@@ -2093,10 -1655,10 +2108,10 @@@ class Item_func_udf_float :public Item_
}
double val_real();
String *val_str(String *str);
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_udf_float>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_udf_float>(thd, this); }
};
@@@ -2111,10 -1673,11 +2126,10 @@@ public
longlong val_int();
double val_real() { return (double) Item_func_udf_int::val_int(); }
String *val_str(String *str);
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
- void fix_length_and_dec() { decimals= 0; max_length= 21; }
+ bool fix_length_and_dec() { decimals= 0; max_length= 21; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_udf_int>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_udf_int>(thd, this); }
};
@@@ -2129,10 -1692,11 +2144,10 @@@ public
double val_real();
my_decimal *val_decimal(my_decimal *);
String *val_str(String *str);
- enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_udf_decimal>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_udf_decimal>(thd, this); }
};
@@@ -2168,10 -1732,11 +2183,10 @@@ public
string2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf);
return dec_buf;
}
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return string_field_type(); }
+ const Type_handler *type_handler() const { return string_type_handler(); }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_udf_str>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_udf_str>(thd, this); }
};
#else /* Dummy functions to get sql_yacc.cc compiled */
@@@ -2222,7 -1785,8 +2237,7 @@@ public
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
double val_real() { DBUG_ASSERT(fixed == 1); null_value= 1; return 0.0; }
longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
- void fix_length_and_dec() { maybe_null=1; max_length=0; }
- enum Item_result result_type () const { return STRING_RESULT; }
+ bool fix_length_and_dec() { maybe_null=1; max_length=0; return FALSE; }
};
#endif /* HAVE_DLOPEN */
@@@ -2230,19 -1794,14 +2245,19 @@@
void mysql_ull_cleanup(THD *thd);
void mysql_ull_set_explicit_lock_duration(THD *thd);
-class Item_func_get_lock :public Item_int_func
+class Item_func_get_lock :public Item_long_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_general_purpose_string(func_name()) ||
+ args[1]->check_type_can_return_real(func_name());
+ }
String value;
public:
- Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_int_func(thd, a, b) {}
+ Item_func_get_lock(THD *thd, Item *a, Item *b) :Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "get_lock"; }
- void fix_length_and_dec() { max_length=1; maybe_null=1;}
+ bool fix_length_and_dec() { max_length=1; maybe_null=1; return FALSE; }
table_map used_tables() const
{
return used_tables_cache | RAND_TABLE_BIT;
@@@ -2253,20 -1812,18 +2268,20 @@@
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_get_lock>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_get_lock>(thd, this); }
};
-class Item_func_release_lock :public Item_int_func
+class Item_func_release_lock :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_general_purpose_string(func_name()); }
String value;
public:
- Item_func_release_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_release_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "release_lock"; }
- void fix_length_and_dec() { max_length= 1; maybe_null= 1;}
+ bool fix_length_and_dec() { max_length= 1; maybe_null= 1; return FALSE; }
table_map used_tables() const
{
return used_tables_cache | RAND_TABLE_BIT;
@@@ -2283,27 -1840,18 +2298,27 @@@
/* replication functions */
-class Item_master_pos_wait :public Item_int_func
+class Item_master_pos_wait :public Item_longlong_func
{
+ bool check_arguments() const
+ {
+ return
+ args[0]->check_type_general_purpose_string(func_name()) ||
+ args[1]->check_type_can_return_int(func_name()) ||
+ (arg_count > 2 && args[2]->check_type_can_return_int(func_name())) ||
+ (arg_count > 3 && args[3]->check_type_general_purpose_string(func_name()));
+ }
String value;
public:
- Item_master_pos_wait(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_master_pos_wait(THD *thd, Item *a, Item *b)
+ :Item_longlong_func(thd, a, b) {}
Item_master_pos_wait(THD *thd, Item *a, Item *b, Item *c):
- Item_int_func(thd, a, b, c) {}
+ Item_longlong_func(thd, a, b, c) {}
Item_master_pos_wait(THD *thd, Item *a, Item *b, Item *c, Item *d):
- Item_int_func(thd, a, b, c, d) {}
+ Item_longlong_func(thd, a, b, c, d) {}
longlong val_int();
const char *func_name() const { return "master_pos_wait"; }
- void fix_length_and_dec() { max_length=21; maybe_null=1;}
+ bool fix_length_and_dec() { max_length=21; maybe_null=1; return FALSE; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@@ -2313,22 -1861,15 +2328,22 @@@
};
-class Item_master_gtid_wait :public Item_int_func
+class Item_master_gtid_wait :public Item_long_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_general_purpose_string(func_name()) ||
+ (arg_count > 1 && args[1]->check_type_can_return_real(func_name()));
+ }
String value;
public:
- Item_master_gtid_wait(THD *thd, Item *a): Item_int_func(thd, a) {}
- Item_master_gtid_wait(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_master_gtid_wait(THD *thd, Item *a)
+ :Item_long_func(thd, a) {}
+ Item_master_gtid_wait(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "master_gtid_wait"; }
- void fix_length_and_dec() { max_length=2; }
+ bool fix_length_and_dec() { max_length=2; return FALSE; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@@ -2425,7 -1960,13 +2440,7 @@@ public
void save_item_result(Item *item);
bool update();
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Field *create_field_for_create_select(TABLE *table)
- {
- return result_type() != STRING_RESULT ?
- create_tmp_field(false, table, MY_INT32_NUM_DECIMAL_DIGITS) :
- tmp_table_field_from_field_type(table, false, true);
- }
void print(String *str, enum_query_type query_type);
enum precedence precedence() const { return ASSIGN_PRECEDENCE; }
void print_as_stmt(String *str, enum_query_type query_type);
@@@ -2708,38 -2211,42 +2723,46 @@@ public
longlong val_int();
const char *func_name() const { return "^"; }
enum precedence precedence() const { return BITXOR_PRECEDENCE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_bit_xor>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_bit_xor>(thd, this); }
};
-class Item_func_is_free_lock :public Item_int_func
+class Item_func_is_free_lock :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_general_purpose_string(func_name()); }
String value;
public:
- Item_func_is_free_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_is_free_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "is_free_lock"; }
- void fix_length_and_dec() { decimals=0; max_length=1; maybe_null=1;}
+ bool fix_length_and_dec()
+ {
+ decimals=0; max_length=1; maybe_null=1;
+ return FALSE;
+ }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_is_free_lock>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_is_free_lock>(thd, this); }
};
-class Item_func_is_used_lock :public Item_int_func
+class Item_func_is_used_lock :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_general_purpose_string(func_name()); }
String value;
public:
- Item_func_is_used_lock(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_is_used_lock(THD *thd, Item *a): Item_long_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "is_used_lock"; }
- void fix_length_and_dec() { decimals=0; max_length=10; maybe_null=1;}
+ bool fix_length_and_dec()
+ {
+ decimals=0; max_length=10; maybe_null=1;
+ return FALSE;
+ }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@@ -2782,13 -2291,14 +2805,13 @@@ public
};
-class Item_func_row_count :public Item_int_func
+class Item_func_row_count :public Item_longlong_func
{
public:
- Item_func_row_count(THD *thd): Item_int_func(thd) {}
+ Item_func_row_count(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "row_count"; }
- void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool fix_length_and_dec() { decimals= 0; maybe_null=0; return FALSE; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
@@@ -2940,62 -2456,19 +2963,63 @@@ public
};
-class Item_func_found_rows :public Item_int_func
+class Item_func_found_rows :public Item_longlong_func
{
public:
- Item_func_found_rows(THD *thd): Item_int_func(thd) {}
+ Item_func_found_rows(THD *thd): Item_longlong_func(thd) {}
longlong val_int();
const char *func_name() const { return "found_rows"; }
- void fix_length_and_dec() { decimals= 0; maybe_null=0; }
+ bool fix_length_and_dec() { decimals= 0; maybe_null=0; return FALSE; }
bool check_vcol_func_processor(void *arg)
{
return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_found_rows>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_found_rows>(thd, this); }
+};
+
+
+class Item_func_oracle_sql_rowcount :public Item_longlong_func
+{
+public:
+ Item_func_oracle_sql_rowcount(THD *thd): Item_longlong_func(thd) {}
+ longlong val_int();
+ const char *func_name() const { return "SQL%ROWCOUNT"; }
+ void print(String *str, enum_query_type query_type)
+ {
+ str->append(func_name());
+ }
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_oracle_sql_rowcount>(thd, this); }
+};
+
+
+class Item_func_sqlcode: public Item_long_func
+{
+public:
+ Item_func_sqlcode(THD *thd): Item_long_func(thd) { }
+ longlong val_int();
+ const char *func_name() const { return "SQLCODE"; }
+ void print(String *str, enum_query_type query_type)
+ {
+ str->append(func_name());
+ }
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg, VCOL_IMPOSSIBLE);
+ }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ maybe_null= null_value= false;
+ max_length= 11;
++ return FALSE;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sqlcode>(thd, this); }
};
@@@ -3030,10 -2503,9 +3054,10 @@@ public
longlong val_int();
String *val_str(String *);
my_decimal *val_decimal(my_decimal *);
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- enum Item_result result_type () const { return last_value->result_type(); }
const char *func_name() const { return "last_value"; }
+ const Type_handler *type_handler() const { return last_value->type_handler(); }
bool eval_not_null_tables(void *)
{
not_null_tables_cache= 0;
@@@ -3046,90 -2519,8 +3070,91 @@@
Item_func::update_used_tables();
maybe_null= last_value->maybe_null;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_last_value>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_last_value>(thd, this); }
+};
+
+
+/* Implementation for sequences: NEXT VALUE FOR sequence and NEXTVAL() */
+
+class Item_func_nextval :public Item_longlong_func
+{
+protected:
+ TABLE_LIST *table_list;
+ TABLE *table;
+public:
+ Item_func_nextval(THD *thd, TABLE_LIST *table_list_arg):
+ Item_longlong_func(thd), table_list(table_list_arg) {}
+ longlong val_int();
+ const char *func_name() const { return "nextval"; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ unsigned_flag= 0;
+ max_length= MAX_BIGINT_WIDTH;
+ maybe_null= 1; /* In case of errors */
++ return FALSE;
+ }
+ /*
+ update_table() function must be called during the value function
+ as in case of DEFAULT the sequence table may not yet be open
+ while fix_fields() are called
+ */
+ void update_table()
+ {
+ if (!(table= table_list->table))
+ {
+ /*
+ If nextval was used in DEFAULT then next_local points to
+ the table_list used by to open the sequence table
+ */
+ table= table_list->next_local->table;
+ }
+ }
+ bool const_item() const { return 0; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_nextval>(thd, this); }
+ void print(String *str, enum_query_type query_type);
+ bool check_vcol_func_processor(void *arg)
+ {
+ return mark_unsupported_function(func_name(), "()", arg,
+ (VCOL_NON_DETERMINISTIC |
+ VCOL_NOT_VIRTUAL));
+ }
+};
+
+
+/* Implementation for sequences: LASTVAL(sequence), PostgreSQL style */
+
+class Item_func_lastval :public Item_func_nextval
+{
+public:
+ Item_func_lastval(THD *thd, TABLE_LIST *table_list_arg):
+ Item_func_nextval(thd, table_list_arg) {}
+ longlong val_int();
+ const char *func_name() const { return "lastval"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_lastval>(thd, this); }
+};
+
+
+/* Implementation for sequences: SETVAL(sequence), PostgreSQL style */
+
+class Item_func_setval :public Item_func_nextval
+{
+ longlong nextval;
+ ulonglong round;
+ bool is_used;
+public:
+ Item_func_setval(THD *thd, TABLE_LIST *table_list_arg, longlong nextval_arg,
+ ulonglong round_arg, bool is_used_arg)
+ : Item_func_nextval(thd, table_list_arg),
+ nextval(nextval_arg), round(round_arg), is_used(is_used_arg)
+ {}
+ longlong val_int();
+ const char *func_name() const { return "setval"; }
+ void print(String *str, enum_query_type query_type);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_setval>(thd, this); }
};
diff --cc sql/item_geofunc.cc
index aee44a7a01f,246be438e36..4c2a2fa8b11
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@@ -40,12 -40,22 +40,13 @@@
#include "opt_range.h"
- void Item_geometry_func::fix_length_and_dec()
-Field *Item_geometry_func::create_field_for_create_select(TABLE *t_arg)
-{
- Field *result;
- if ((result= new Field_geom(max_length, maybe_null, name, t_arg->s,
- get_geometry_type())))
- result->init(t_arg);
- return result;
-}
-
+ bool Item_geometry_func::fix_length_and_dec()
{
collation.set(&my_charset_bin);
decimals=0;
- max_length= (uint32) 4294967295U;
+ max_length= (uint32) UINT_MAX32;
maybe_null= 1;
+ return FALSE;
}
@@@ -214,11 -224,12 +215,12 @@@ String *Item_func_as_wkt::val_str_ascii
}
- void Item_func_as_wkt::fix_length_and_dec()
+ bool Item_func_as_wkt::fix_length_and_dec()
{
collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
- max_length=MAX_BLOB_WIDTH;
+ max_length= (uint32) UINT_MAX32;
maybe_null= 1;
+ return FALSE;
}
diff --cc sql/item_geofunc.h
index 8101433abb5,acc94183d47..0e727829ce7
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@@ -38,164 -38,13 +38,164 @@@ public
Item_geometry_func(THD *thd, Item *a, Item *b, Item *c):
Item_str_func(thd, a, b, c) {}
Item_geometry_func(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
- Field *create_field_for_create_select(TABLE *table);
+ const Type_handler *type_handler() const { return &type_handler_geometry; }
};
+
+/*
+ Functions returning REAL measurements of a single GEOMETRY argument
+*/
+class Item_real_func_args_geometry: public Item_real_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_real_func_args_geometry(THD *thd, Item *a)
+ :Item_real_func(thd, a) {}
+};
+
+
+/*
+ Functions returning INT measurements of a single GEOMETRY argument
+*/
+class Item_long_func_args_geometry: public Item_long_func
+{
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+protected:
+ String value;
+public:
+ Item_long_func_args_geometry(THD *thd, Item *a)
+ :Item_long_func(thd, a) {}
+};
+
+
+/*
+ Functions returning BOOL measurements of a single GEOMETRY argument
+*/
+class Item_bool_func_args_geometry: public Item_bool_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count == 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_bool_func_args_geometry(THD *thd, Item *a)
+ :Item_bool_func(thd, a) {}
+};
+
+
+/*
+ Functions returning ASCII string measurements of a single GEOMETRY argument
+*/
+class Item_str_ascii_func_args_geometry: public Item_str_ascii_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a)
+ :Item_str_ascii_func(thd, a) {}
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b)
+ :Item_str_ascii_func(thd, a, b) {}
+ Item_str_ascii_func_args_geometry(THD *thd, Item *a, Item *b, Item *c)
+ :Item_str_ascii_func(thd, a, b, c) {}
+};
+
+
+/*
+ Functions returning binary string measurements of a single GEOMETRY argument
+*/
+class Item_binary_func_args_geometry: public Item_str_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_binary_func_args_geometry(THD *thd, Item *a)
+ :Item_str_func(thd, a) {}
+};
+
+
+/*
+ Functions returning GEOMETRY measurements of a single GEOEMETRY argument
+*/
+class Item_geometry_func_args_geometry: public Item_geometry_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 1);
+ return args[0]->check_type_or_binary(func_name(), &type_handler_geometry);
+ }
+public:
+ Item_geometry_func_args_geometry(THD *thd, Item *a)
+ :Item_geometry_func(thd, a) {}
+ Item_geometry_func_args_geometry(THD *thd, Item *a, Item *b)
+ :Item_geometry_func(thd, a, b) {}
+};
+
+
+/*
+ Functions returning REAL result relationships between two GEOMETRY arguments
+*/
+class Item_real_func_args_geometry_geometry: public Item_real_func
+{
+protected:
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
+public:
+ Item_real_func_args_geometry_geometry(THD *thd, Item *a, Item *b)
+ :Item_real_func(thd, a, b) {}
+};
+
+
+/*
+ Functions returning BOOL result relationships between two GEOMETRY arguments
+*/
+class Item_bool_func_args_geometry_geometry: public Item_bool_func
+{
+protected:
+ String value;
+ bool check_arguments() const
+ {
+ DBUG_ASSERT(arg_count >= 2);
+ return check_argument_types_or_binary(&type_handler_geometry, 0, 2);
+ }
+public:
+ Item_bool_func_args_geometry_geometry(THD *thd, Item *a, Item *b, Item *c)
+ :Item_bool_func(thd, a, b, c) {}
+};
+
+
class Item_func_geometry_from_text: public Item_geometry_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_general_purpose_string(func_name()) ||
+ check_argument_types_can_return_int(1, MY_MIN(2, arg_count));
+ }
public:
Item_func_geometry_from_text(THD *thd, Item *a): Item_geometry_func(thd, a) {}
Item_func_geometry_from_text(THD *thd, Item *a, Item *srid):
@@@ -246,76 -84,60 +246,78 @@@ public
};
-class Item_func_as_wkt: public Item_str_ascii_func
+class Item_func_as_wkt: public Item_str_ascii_func_args_geometry
{
public:
- Item_func_as_wkt(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
+ Item_func_as_wkt(THD *thd, Item *a)
+ :Item_str_ascii_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_astext"; }
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_as_wkt>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_as_wkt>(thd, this); }
};
-class Item_func_as_wkb: public Item_geometry_func
+class Item_func_as_wkb: public Item_binary_func_args_geometry
{
public:
- Item_func_as_wkb(THD *thd, Item *a): Item_geometry_func(thd, a) {}
+ Item_func_as_wkb(THD *thd, Item *a)
+ :Item_binary_func_args_geometry(thd, a) {}
const char *func_name() const { return "st_aswkb"; }
String *val_str(String *);
- enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_as_wkb>(thd, mem_root, this); }
+ const Type_handler *type_handler() const { return &type_handler_long_blob; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ collation.set(&my_charset_bin);
+ decimals=0;
+ max_length= (uint32) UINT_MAX32;
+ maybe_null= 1;
++ return FALSE;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_as_wkb>(thd, this); }
};
-class Item_func_as_geojson: public Item_str_ascii_func
+class Item_func_as_geojson: public Item_str_ascii_func_args_geometry
{
+ bool check_arguments() const
+ {
+ // TODO: check with Alexey, for better args[1] and args[2] type control
+ return Item_str_ascii_func_args_geometry::check_arguments() ||
+ check_argument_types_traditional_scalar(1, MY_MIN(3, arg_count));
+ }
public:
- Item_func_as_geojson(THD *thd, Item *js): Item_str_ascii_func(thd, js) {}
- Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits):
- Item_str_ascii_func(thd, js, max_dec_digits) {}
- Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt):
- Item_str_ascii_func(thd, js, max_dec_digits, opt) {}
+ Item_func_as_geojson(THD *thd, Item *js)
+ :Item_str_ascii_func_args_geometry(thd, js) {}
+ Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits)
+ :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits) {}
+ Item_func_as_geojson(THD *thd, Item *js, Item *max_dec_digits, Item *opt)
+ :Item_str_ascii_func_args_geometry(thd, js, max_dec_digits, opt) {}
const char *func_name() const { return "st_asgeojson"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str_ascii(String *);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_as_geojson>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_as_geojson>(thd, this); }
};
-class Item_func_geometry_type: public Item_str_ascii_func
+class Item_func_geometry_type: public Item_str_ascii_func_args_geometry
{
public:
- Item_func_geometry_type(THD *thd, Item *a): Item_str_ascii_func(thd, a) {}
+ Item_func_geometry_type(THD *thd, Item *a)
+ :Item_str_ascii_func_args_geometry(thd, a) {}
String *val_str_ascii(String *);
const char *func_name() const { return "st_geometrytype"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
// "GeometryCollection" is the longest
fix_length_and_charset(20, default_charset());
maybe_null= 1;
+ return FALSE;
};
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_geometry_type>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_geometry_type>(thd, this); }
};
@@@ -720,47 -508,44 +725,47 @@@ public
};
-class Item_func_isempty: public Item_bool_func
+class Item_func_isempty: public Item_bool_func_args_geometry
{
public:
- Item_func_isempty(THD *thd, Item *a): Item_bool_func(thd, a) {}
+ Item_func_isempty(THD *thd, Item *a)
+ :Item_bool_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isempty"; }
- void fix_length_and_dec() { maybe_null= 1; }
+ bool fix_length_and_dec() { maybe_null= 1; return FALSE; }
bool need_parentheses_in_default() { return false; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_isempty>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_isempty>(thd, this); }
};
-class Item_func_issimple: public Item_int_func
+class Item_func_issimple: public Item_long_func_args_geometry
{
Gcalc_heap collector;
Gcalc_function func;
Gcalc_scan_iterator scan_it;
String tmp;
public:
- Item_func_issimple(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_issimple(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_issimple"; }
- void fix_length_and_dec() { decimals=0; max_length=2; }
+ bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; }
uint decimal_precision() const { return 1; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_issimple>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_issimple>(thd, this); }
};
-class Item_func_isclosed: public Item_int_func
+class Item_func_isclosed: public Item_long_func_args_geometry
{
public:
- Item_func_isclosed(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_isclosed(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isclosed"; }
- void fix_length_and_dec() { decimals=0; max_length=2; }
+ bool fix_length_and_dec() { decimals=0; max_length=2; return FALSE; }
uint decimal_precision() const { return 1; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_isclosed>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_isclosed>(thd, this); }
};
class Item_func_isring: public Item_func_issimple
@@@ -769,107 -554,115 +774,113 @@@ public
Item_func_isring(THD *thd, Item *a): Item_func_issimple(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_isring"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_isring>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_isring>(thd, this); }
};
-class Item_func_dimension: public Item_int_func
+class Item_func_dimension: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_dimension(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dimension(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_dimension"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_dimension>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_dimension>(thd, this); }
};
-class Item_func_x: public Item_real_func
+
+class Item_func_x: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_x(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_x(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_x"; }
- void fix_length_and_dec()
- {
- Item_real_func::fix_length_and_dec();
- maybe_null= 1;
+ bool fix_length_and_dec()
+ {
+ if (Item_real_func::fix_length_and_dec())
+ return TRUE;
+ maybe_null= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_x>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_x>(thd, this); }
};
-class Item_func_y: public Item_real_func
+class Item_func_y: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_y(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_y(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_y"; }
- void fix_length_and_dec()
- {
- Item_real_func::fix_length_and_dec();
- maybe_null= 1;
+ bool fix_length_and_dec()
+ {
+ if (Item_real_func::fix_length_and_dec())
+ return TRUE;
+ maybe_null= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_y>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_y>(thd, this); }
};
-class Item_func_numgeometries: public Item_int_func
+class Item_func_numgeometries: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numgeometries(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numgeometries(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numgeometries"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_numgeometries>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_numgeometries>(thd, this); }
};
-class Item_func_numinteriorring: public Item_int_func
+class Item_func_numinteriorring: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numinteriorring(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numinteriorring(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numinteriorrings"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_numinteriorring>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_numinteriorring>(thd, this); }
};
-class Item_func_numpoints: public Item_int_func
+class Item_func_numpoints: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_numpoints(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_numpoints(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "st_numpoints"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_numpoints>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_numpoints>(thd, this); }
};
-class Item_func_area: public Item_real_func
+class Item_func_area: public Item_real_func_args_geometry
{
- String value;
public:
- Item_func_area(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_area(THD *thd, Item *a): Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_area"; }
- void fix_length_and_dec()
- {
- Item_real_func::fix_length_and_dec();
- maybe_null= 1;
+ bool fix_length_and_dec()
+ {
+ if (Item_real_func::fix_length_and_dec())
+ return TRUE;
+ maybe_null= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_area>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_area>(thd, this); }
};
@@@ -877,30 -670,31 +888,32 @@@ class Item_func_glength: public Item_re
{
String value;
public:
- Item_func_glength(THD *thd, Item *a): Item_real_func(thd, a) {}
+ Item_func_glength(THD *thd, Item *a)
+ :Item_real_func_args_geometry(thd, a) {}
double val_real();
const char *func_name() const { return "st_length"; }
- void fix_length_and_dec()
- {
- Item_real_func::fix_length_and_dec();
- maybe_null= 1;
+ bool fix_length_and_dec()
+ {
+ if (Item_real_func::fix_length_and_dec())
+ return TRUE;
+ maybe_null= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_glength>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_glength>(thd, this); }
};
-class Item_func_srid: public Item_int_func
+class Item_func_srid: public Item_long_func_args_geometry
{
- String value;
public:
- Item_func_srid(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_srid(THD *thd, Item *a)
+ :Item_long_func_args_geometry(thd, a) {}
longlong val_int();
const char *func_name() const { return "srid"; }
- void fix_length_and_dec() { max_length= 10; maybe_null= 1; }
+ bool fix_length_and_dec() { max_length= 10; maybe_null= 1; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_srid>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_srid>(thd, this); }
};
@@@ -939,12 -731,11 +952,12 @@@ public
#ifndef DBUG_OFF
-class Item_func_gis_debug: public Item_int_func
+class Item_func_gis_debug: public Item_long_func
{
public:
- Item_func_gis_debug(THD *thd, Item *a): Item_int_func(thd, a)
+ Item_func_gis_debug(THD *thd, Item *a): Item_long_func(thd, a)
{ null_value= false; }
- void fix_length_and_dec() { fix_char_length(10); }
++ bool fix_length_and_dec() { fix_char_length(10); return FALSE; }
const char *func_name() const { return "st_gis_debug"; }
longlong val_int();
bool check_vcol_func_processor(void *arg)
diff --cc sql/item_inetfunc.h
index d934cef43dd,670dce3da9f..024ff8ce4f0
--- a/sql/item_inetfunc.h
+++ b/sql/item_inetfunc.h
@@@ -24,23 -24,22 +24,24 @@@
Item_func_inet_aton implements INET_ATON() SQL-function.
*************************************************************************/
-class Item_func_inet_aton : public Item_int_func
+class Item_func_inet_aton : public Item_longlong_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_text(0, arg_count); }
public:
- Item_func_inet_aton(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_inet_aton(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "inet_aton"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals= 0;
max_length= 21;
maybe_null= 1;
unsigned_flag= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_inet_aton>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_inet_aton>(thd, this); }
};
@@@ -60,9 -59,10 +61,10 @@@ public
decimals= 0;
fix_length_and_charset(3 * 8 + 7, default_charset());
maybe_null= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_inet_ntoa>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_inet_ntoa>(thd, this); }
};
@@@ -129,9 -129,10 +131,10 @@@ public
decimals= 0;
fix_length_and_charset(16, &my_charset_bin);
maybe_null= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_inet6_aton>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_inet6_aton>(thd, this); }
protected:
virtual bool calc_value(const String *arg, String *buffer);
@@@ -163,9 -164,10 +166,10 @@@ public
fix_length_and_charset(8 * 4 + 7, default_charset());
maybe_null= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_inet6_ntoa>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_inet6_ntoa>(thd, this); }
protected:
virtual bool calc_value(const String *arg, String *buffer);
diff --cc sql/item_jsonfunc.cc
index e67357000da,72aeac5b930..52042c56fcc
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@@ -388,11 -388,13 +388,13 @@@ longlong Item_func_json_valid::val_int(
}
- void Item_func_json_exists::fix_length_and_dec()
+ bool Item_func_json_exists::fix_length_and_dec()
{
- Item_bool_func::fix_length_and_dec();
- if (Item_int_func::fix_length_and_dec())
++ if (Item_bool_func::fix_length_and_dec())
+ return TRUE;
maybe_null= 1;
path.set_constant_flag(args[1]->const_item());
+ return FALSE;
}
@@@ -944,7 -950,7 +950,7 @@@ bool Item_func_json_contains::fix_lengt
maybe_null= 1;
if (arg_count > 2)
path.set_constant_flag(args[2]->const_item());
- Item_bool_func::fix_length_and_dec();
- return Item_int_func::fix_length_and_dec();
++ return Item_bool_func::fix_length_and_dec();
}
@@@ -1196,7 -1202,7 +1202,7 @@@ bool Item_func_json_contains_path::fix_
ooa_parsed= FALSE;
maybe_null= 1;
mark_constant_paths(paths, args+2, arg_count-2);
- Item_bool_func::fix_length_and_dec();
- return Item_int_func::fix_length_and_dec();
++ return Item_bool_func::fix_length_and_dec();
}
@@@ -2129,7 -2135,7 +2137,8 @@@ bool Item_func_json_length::fix_length_
if (arg_count > 1)
path.set_constant_flag(args[1]->const_item());
maybe_null= 1;
+ max_length= 10;
+ return FALSE;
}
diff --cc sql/item_jsonfunc.h
index 354de69eee4,f331ee3b582..af0995b9605
--- a/sql/item_jsonfunc.h
+++ b/sql/item_jsonfunc.h
@@@ -46,16 -46,19 +46,18 @@@ protected
String tmp_value;
public:
- Item_func_json_valid(THD *thd, Item *json) : Item_int_func(thd, json) {}
+ Item_func_json_valid(THD *thd, Item *json) : Item_bool_func(thd, json) {}
longlong val_int();
const char *func_name() const { return "json_valid"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- Item_bool_func::fix_length_and_dec();
- if (Item_int_func::fix_length_and_dec())
++ if (Item_bool_func::fix_length_and_dec())
+ return TRUE;
maybe_null= 1;
+ return FALSE;
}
- bool is_bool_type() { return true; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_valid>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_valid>(thd, this); }
};
@@@ -67,11 -70,12 +69,11 @@@ protected
public:
Item_func_json_exists(THD *thd, Item *js, Item *i_path):
- Item_int_func(thd, js, i_path) {}
+ Item_bool_func(thd, js, i_path) {}
const char *func_name() const { return "json_exists"; }
- void fix_length_and_dec();
- bool is_bool_type() { return true; }
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_exists>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_exists>(thd, this); }
longlong val_int();
};
@@@ -86,11 -90,11 +88,11 @@@ public
Item_func_json_value(THD *thd, Item *js, Item *i_path):
Item_str_func(thd, js, i_path) {}
const char *func_name() const { return "json_value"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
virtual bool check_and_get_value(json_engine_t *je, String *res, int *error);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_value>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_value>(thd, this); }
};
@@@ -115,10 -119,10 +117,10 @@@ protected
public:
Item_func_json_quote(THD *thd, Item *s): Item_str_func(thd, s) {}
const char *func_name() const { return "json_quote"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_quote>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_quote>(thd, this); }
};
@@@ -130,10 -134,10 +132,10 @@@ protected
public:
Item_func_json_unquote(THD *thd, Item *s): Item_str_func(thd, s) {}
const char *func_name() const { return "json_unquote"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_unquote>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_unquote>(thd, this); }
};
@@@ -183,12 -187,12 +185,12 @@@ protected
String tmp_val, *val;
public:
Item_func_json_contains(THD *thd, List<Item> &list):
- Item_int_func(thd, list) {}
+ Item_bool_func(thd, list) {}
const char *func_name() const { return "json_contains"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_contains>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_contains>(thd, this); }
};
@@@ -204,14 -208,14 +206,14 @@@ protected
public:
Item_func_json_contains_path(THD *thd, List<Item> &list):
- Item_int_func(thd, list), tmp_paths(0) {}
+ Item_bool_func(thd, list), tmp_paths(0) {}
const char *func_name() const { return "json_contains_path"; }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void cleanup();
longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_contains_path>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_contains_path>(thd, this); }
};
@@@ -227,10 -231,10 +229,10 @@@ public
Item_str_func(thd, list) {}
String *val_str(String *);
bool is_json_type() { return true; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "json_array"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_array>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_array>(thd, this); }
};
@@@ -307,12 -305,12 +309,12 @@@ protected
String tmp_path;
public:
Item_func_json_length(THD *thd, List<Item> &list):
- Item_int_func(thd, list) {}
+ Item_long_func(thd, list) {}
const char *func_name() const { return "json_length"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_length>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_length>(thd, this); }
};
@@@ -323,12 -319,11 +325,12 @@@ class Item_func_json_depth: public Item
protected:
String tmp_js;
public:
- Item_func_json_depth(THD *thd, Item *js): Item_int_func(thd, js) {}
+ Item_func_json_depth(THD *thd, Item *js): Item_long_func(thd, js) {}
const char *func_name() const { return "json_depth"; }
- void fix_length_and_dec() { max_length= 10; }
++ bool fix_length_and_dec() { max_length= 10; return FALSE; }
longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_depth>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_depth>(thd, this); }
};
@@@ -339,10 -334,10 +341,10 @@@ protected
public:
Item_func_json_type(THD *thd, Item *js): Item_str_func(thd, js) {}
const char *func_name() const { return "json_type"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_type>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_type>(thd, this); }
};
@@@ -395,10 -390,10 +397,10 @@@ public
Item_func_json_keys(THD *thd, List<Item> &list):
Item_str_func(thd, list) {}
const char *func_name() const { return "json_keys"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_keys>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_keys>(thd, this); }
};
@@@ -419,11 -414,11 +421,11 @@@ public
Item_json_str_multipath(thd, list) {}
const char *func_name() const { return "json_search"; }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
String *val_str(String *);
uint get_n_paths() const { return arg_count > 4 ? arg_count - 4 : 0; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_json_search>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_json_search>(thd, this); }
};
diff --cc sql/item_strfunc.cc
index 6af49d494d4,87c766340c7..c914c6cbdf8
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@@ -652,25 -636,7 +658,25 @@@ null
}
+bool Item_func_concat::append_value(THD *thd, String *res, const String *app)
+{
+ uint concat_len;
+ if ((concat_len= res->length() + app->length()) >
+ thd->variables.max_allowed_packet)
+ {
+ push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(),
+ thd->variables.max_allowed_packet);
+ return true;
+ }
+ DBUG_ASSERT(!res->uses_buffer_owned_by(app));
+ DBUG_ASSERT(!app->uses_buffer_owned_by(res));
+ return realloc_result(res, concat_len) || res->append(*app);
+}
+
+
- void Item_func_concat::fix_length_and_dec()
+ bool Item_func_concat::fix_length_and_dec()
{
ulonglong char_length= 0;
@@@ -1102,11 -1070,12 +1110,13 @@@ String *Item_func_reverse::val_str(Stri
}
- void Item_func_reverse::fix_length_and_dec()
+ bool Item_func_reverse::fix_length_and_dec()
{
-- agg_arg_charsets_for_string_result(collation, args, 1);
++ if (agg_arg_charsets_for_string_result(collation, args, 1))
++ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
fix_char_length(args[0]->max_char_length());
+ return FALSE;
}
/**
@@@ -2417,10 -2374,10 +2445,11 @@@ bool Item_func_current_role::fix_fields
return 0;
}
- void Item_func_soundex::fix_length_and_dec()
+ bool Item_func_soundex::fix_length_and_dec()
{
uint32 char_length= args[0]->max_char_length();
-- agg_arg_charsets_for_string_result(collation, args, 1);
++ if (agg_arg_charsets_for_string_result(collation, args, 1))
++ return TRUE;
DBUG_ASSERT(collation.collation != NULL);
set_if_bigger(char_length, 4);
fix_char_length(char_length);
@@@ -2581,16 -2539,35 +2611,17 @@@ String *Item_func_soundex::val_str(Stri
const int FORMAT_MAX_DECIMALS= 30;
- void Item_func_format::fix_length_and_dec()
-MY_LOCALE *Item_func_format::get_locale(Item *item)
-{
- DBUG_ASSERT(arg_count == 3);
- String tmp, *locale_name= args[2]->val_str_ascii(&tmp);
- MY_LOCALE *lc;
- if (!locale_name ||
- !(lc= my_locale_by_name(locale_name->c_ptr_safe())))
- {
- THD *thd= current_thd;
- push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
- ER_UNKNOWN_LOCALE,
- ER_THD(thd, ER_UNKNOWN_LOCALE),
- locale_name ? locale_name->c_ptr_safe() : "NULL");
- lc= &my_locale_en_US;
- }
- return lc;
-}
-
+ bool Item_func_format::fix_length_and_dec()
{
uint32 char_length= args[0]->max_char_length();
uint32 max_sep_count= (char_length / 3) + (decimals ? 1 : 0) + /*sign*/1;
collation.set(default_charset());
fix_char_length(char_length + max_sep_count + decimals);
if (arg_count == 3)
- locale= args[2]->basic_const_item() ? get_locale(args[2]) : NULL;
+ locale= args[2]->basic_const_item() ? args[2]->locale_from_val_str() : NULL;
else
locale= &my_locale_en_US; /* Two arguments */
+ return FALSE;
}
@@@ -3123,23 -3084,11 +3160,23 @@@ err
}
- void Item_func_pad::fix_length_and_dec()
-bool Item_func_rpad::fix_length_and_dec()
++bool Item_func_pad::fix_length_and_dec()
{
- // Handle character set for args[0] and args[2].
- if (agg_arg_charsets_for_string_result(collation, &args[0], 2, 2))
- return TRUE;
+ if (arg_count == 3)
+ {
+ // Handle character set for args[0] and args[2].
+ if (agg_arg_charsets_for_string_result(collation, &args[0], 2, 2))
- return;
++ return TRUE;
+ }
+ else
+ {
+ if (agg_arg_charsets_for_string_result(collation, &args[0], 1, 1))
- return;
++ return TRUE;
+ pad_str.set_charset(collation.collation);
+ pad_str.length(0);
+ pad_str.append(" ", 1);
+ }
+
if (args[1]->const_item())
{
ulonglong char_length= (ulonglong) args[1]->val_int();
@@@ -3436,17 -3392,32 +3475,18 @@@ String *Item_func_set_collation::val_st
return str;
}
- void Item_func_set_collation::fix_length_and_dec()
+ bool Item_func_set_collation::fix_length_and_dec()
{
- CHARSET_INFO *set_collation;
- const char *colname;
- String tmp, *str= args[1]->val_str(&tmp);
- colname= str->c_ptr();
- if (colname == binary_keyword)
- set_collation= get_charset_by_csname(args[0]->collation.collation->csname,
- MY_CS_BINSORT,MYF(0));
- else
- {
- if (!(set_collation= mysqld_collation_get_by_name(colname)))
- return TRUE;
- }
-
- if (!set_collation ||
- !my_charset_same(args[0]->collation.collation,set_collation))
+ if (!my_charset_same(args[0]->collation.collation, m_set_collation))
{
my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- colname, args[0]->collation.collation->csname);
+ m_set_collation->name, args[0]->collation.collation->csname);
- return;
+ return TRUE;
}
- collation.set(set_collation, DERIVATION_EXPLICIT,
+ collation.set(m_set_collation, DERIVATION_EXPLICIT,
args[0]->collation.repertoire);
max_length= args[0]->max_length;
+ return FALSE;
}
@@@ -3501,12 -3488,13 +3541,13 @@@ bool Item_func_weight_string::fix_lengt
*/
if (!(max_length= result_length))
{
- uint char_length;
+ size_t char_length;
char_length= ((cs->state & MY_CS_STRNXFRM_BAD_NWEIGHTS) || !nweights) ?
args[0]->max_char_length() : nweights * cs->levels_for_order;
- max_length= cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen);
+ max_length= (uint32)cs->coll->strnxfrmlen(cs, char_length * cs->mbmaxlen);
}
maybe_null= 1;
+ return FALSE;
}
@@@ -5204,23 -5203,3 +5247,24 @@@ null
my_free(names);
return NULL;
}
+
+Item_temptable_rowid::Item_temptable_rowid(TABLE *table_arg)
+ : Item_str_func(table_arg->in_use), table(table_arg)
+{
+ max_length= table->file->ref_length;
+}
+
- void Item_temptable_rowid::fix_length_and_dec()
++bool Item_temptable_rowid::fix_length_and_dec()
+{
+ used_tables_cache= table->map;
+ const_item_cache= false;
++ return FALSE;
+}
+
+String *Item_temptable_rowid::val_str(String *str)
+{
+ if (!((null_value= table->null_row)))
+ table->file->position(table->record[0]);
+ str_value.set((char*)(table->file->ref), max_length, &my_charset_bin);
+ return &str_value;
+}
diff --cc sql/item_strfunc.h
index eb084c3f58d,a908aba2d2f..29af0b43d9d
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@@ -144,13 -145,14 +144,14 @@@ class Item_func_md5 :public Item_str_as
public:
Item_func_md5(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a) {}
String *val_str_ascii(String *);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
fix_length_and_charset(32, default_charset());
+ return FALSE;
}
const char *func_name() const { return "md5"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_md5>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_md5>(thd, this); }
};
@@@ -159,10 -161,10 +160,10 @@@ class Item_func_sha :public Item_str_as
public:
Item_func_sha(THD *thd, Item *a): Item_str_ascii_checksum_func(thd, a) {}
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "sha"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_sha>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sha>(thd, this); }
};
class Item_func_sha2 :public Item_str_ascii_checksum_func
@@@ -171,10 -173,10 +172,10 @@@ public
Item_func_sha2(THD *thd, Item *a, Item *b)
:Item_str_ascii_checksum_func(thd, a, b) {}
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "sha2"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_sha2>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sha2>(thd, this); }
};
class Item_func_to_base64 :public Item_str_ascii_checksum_func
@@@ -184,10 -186,10 +185,10 @@@ public
Item_func_to_base64(THD *thd, Item *a)
:Item_str_ascii_checksum_func(thd, a) {}
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "to_base64"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_to_base64>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_to_base64>(thd, this); }
};
class Item_func_from_base64 :public Item_str_binary_checksum_func
@@@ -197,10 -199,10 +198,10 @@@ public
Item_func_from_base64(THD *thd, Item *a)
:Item_str_binary_checksum_func(thd, a) { }
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "from_base64"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_from_base64>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_from_base64>(thd, this); }
};
#include <my_crypt.h>
@@@ -224,10 -226,10 +225,10 @@@ class Item_func_aes_encrypt :public Ite
public:
Item_func_aes_encrypt(THD *thd, Item *a, Item *b)
:Item_aes_crypt(thd, a, b) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "aes_encrypt"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_aes_encrypt>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_aes_encrypt>(thd, this); }
};
class Item_func_aes_decrypt :public Item_aes_crypt
@@@ -235,10 -237,10 +236,10 @@@
public:
Item_func_aes_decrypt(THD *thd, Item *a, Item *b):
Item_aes_crypt(thd, a, b) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "aes_decrypt"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_aes_decrypt>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_aes_decrypt>(thd, this); }
};
@@@ -259,35 -252,12 +260,35 @@@ public
Item_func_concat(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
Item_func_concat(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "concat"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_concat>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_concat>(thd, this); }
+};
+
+
+/*
+ This class handles the || operator in sql_mode=ORACLE.
+ Unlike the traditional MariaDB concat(), it treats NULL arguments as ''.
+*/
+class Item_func_concat_operator_oracle :public Item_func_concat
+{
+public:
+ Item_func_concat_operator_oracle(THD *thd, List<Item> &list)
+ :Item_func_concat(thd, list)
+ { }
+ Item_func_concat_operator_oracle(THD *thd, Item *a, Item *b)
+ :Item_func_concat(thd, a, b)
+ { }
+ String *val_str(String *);
+ const char *func_name() const { return "concat_operator_oracle"; }
+ Item *get_copy(THD *thd)
+ {
+ return get_item_copy<Item_func_concat_operator_oracle>(thd, this);
+ }
};
+
class Item_func_decode_histogram :public Item_str_func
{
public:
@@@ -299,10 -269,11 +300,11 @@@
collation.set(system_charset_info);
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
+ return FALSE;
}
const char *func_name() const { return "decode_histogram"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_decode_histogram>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_decode_histogram>(thd, this); }
};
class Item_func_concat_ws :public Item_str_func
@@@ -311,11 -282,11 +313,11 @@@
public:
Item_func_concat_ws(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "concat_ws"; }
table_map not_null_tables() const { return 0; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_concat_ws>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_concat_ws>(thd, this); }
};
class Item_func_reverse :public Item_str_func
@@@ -324,10 -295,10 +326,10 @@@
public:
Item_func_reverse(THD *thd, Item *a): Item_str_func(thd, a) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "reverse"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_reverse>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_reverse>(thd, this); }
};
@@@ -337,25 -308,11 +339,25 @@@ class Item_func_replace :public Item_st
public:
Item_func_replace(THD *thd, Item *org, Item *find, Item *replace):
Item_str_func(thd, org, find, replace) {}
- String *val_str(String *);
+ String *val_str(String *to) { return val_str_internal(to, NULL); };
- void fix_length_and_dec();
+ bool fix_length_and_dec();
+ String *val_str_internal(String *str, String *empty_string_for_null);
const char *func_name() const { return "replace"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_replace>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_replace>(thd, this); }
+};
+
+
+class Item_func_replace_oracle :public Item_func_replace
+{
+ String tmp_emtpystr;
+public:
+ Item_func_replace_oracle(THD *thd, Item *org, Item *find, Item *replace):
+ Item_func_replace(thd, org, find, replace) {}
+ String *val_str(String *to) { return val_str_internal(to, &tmp_emtpystr); };
+ const char *func_name() const { return "replace_oracle"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_replace_oracle>(thd, this); }
};
@@@ -378,9 -335,9 +380,9 @@@ public
}
String *val_str(String *str);
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "regexp_replace"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0;}
+ Item *get_copy(THD *thd) { return 0;}
};
@@@ -400,9 -357,9 +402,9 @@@ public
}
String *val_str(String *str);
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "regexp_substr"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return 0; }
+ Item *get_copy(THD *thd) { return 0; }
};
@@@ -414,10 -371,10 +416,10 @@@ public
Item *new_str):
Item_str_func(thd, org, start, length, new_str) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "insert"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_insert>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_insert>(thd, this); }
};
@@@ -438,9 -395,9 +440,9 @@@ class Item_func_lcase :public Item_str_
public:
Item_func_lcase(THD *thd, Item *item): Item_str_conv(thd, item) {}
const char *func_name() const { return "lcase"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_lcase>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_lcase>(thd, this); }
};
class Item_func_ucase :public Item_str_conv
@@@ -448,9 -405,9 +450,9 @@@
public:
Item_func_ucase(THD *thd, Item *item): Item_str_conv(thd, item) {}
const char *func_name() const { return "ucase"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_ucase>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_ucase>(thd, this); }
};
@@@ -460,10 -417,10 +462,10 @@@ class Item_func_left :public Item_str_f
public:
Item_func_left(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "left"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_left>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_left>(thd, this); }
};
@@@ -473,50 -430,26 +475,51 @@@ class Item_func_right :public Item_str_
public:
Item_func_right(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "right"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_right>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_right>(thd, this); }
};
class Item_func_substr :public Item_str_func
{
String tmp_value;
+protected:
+ virtual longlong get_position() { return args[1]->val_int(); }
public:
Item_func_substr(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
- Item_func_substr(THD *thd, Item *a, Item *b, Item *c): Item_str_func(thd, a, b, c) {}
+ Item_func_substr(THD *thd, Item *a, Item *b, Item *c):
+ Item_str_func(thd, a, b, c) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "substr"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_substr>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_substr>(thd, this); }
};
+class Item_func_substr_oracle :public Item_func_substr
+{
+protected:
+ longlong get_position()
+ { longlong pos= args[1]->val_int(); return pos == 0 ? 1 : pos; }
+ String *make_empty_result()
+ { null_value= 1; return NULL; }
+public:
+ Item_func_substr_oracle(THD *thd, Item *a, Item *b):
+ Item_func_substr(thd, a, b) {}
+ Item_func_substr_oracle(THD *thd, Item *a, Item *b, Item *c):
+ Item_func_substr(thd, a, b, c) {}
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- Item_func_substr::fix_length_and_dec();
++ bool res= Item_func_substr::fix_length_and_dec();
+ maybe_null= true;
++ return res;
+ }
+ const char *func_name() const { return "substr_oracle"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_substr_oracle>(thd, this); }
+};
class Item_func_substr_index :public Item_str_func
{
@@@ -525,10 -458,10 +528,10 @@@ public
Item_func_substr_index(THD *thd, Item *a,Item *b,Item *c):
Item_str_func(thd, a, b, c) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "substring_index"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_substr_index>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_substr_index>(thd, this); }
};
@@@ -565,29 -494,8 +568,30 @@@ public
const char *func_name() const { return "trim"; }
void print(String *str, enum_query_type query_type);
virtual const char *mode_name() const { return "both"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_trim>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_trim>(thd, this); }
+};
+
+
+class Item_func_trim_oracle :public Item_func_trim
+{
+protected:
+ String *make_empty_result()
+ { null_value= 1; return NULL; }
+ const char *func_name_ext() const { return "_oracle"; }
+public:
+ Item_func_trim_oracle(THD *thd, Item *a, Item *b):
+ Item_func_trim(thd, a, b) {}
+ Item_func_trim_oracle(THD *thd, Item *a): Item_func_trim(thd, a) {}
+ const char *func_name() const { return "trim_oracle"; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- Item_func_trim::fix_length_and_dec();
++ bool res= Item_func_trim::fix_length_and_dec();
+ maybe_null= true;
++ return res;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_trim_oracle>(thd, this); }
};
@@@ -599,29 -507,8 +603,30 @@@ public
String *val_str(String *);
const char *func_name() const { return "ltrim"; }
const char *mode_name() const { return "leading"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_ltrim>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_ltrim>(thd, this); }
+};
+
+
+class Item_func_ltrim_oracle :public Item_func_ltrim
+{
+protected:
+ String *make_empty_result()
+ { null_value= 1; return NULL; }
+ const char *func_name_ext() const { return "_oracle"; }
+public:
+ Item_func_ltrim_oracle(THD *thd, Item *a, Item *b):
+ Item_func_ltrim(thd, a, b) {}
+ Item_func_ltrim_oracle(THD *thd, Item *a): Item_func_ltrim(thd, a) {}
+ const char *func_name() const { return "ltrim_oracle"; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- Item_func_ltrim::fix_length_and_dec();
++ bool res= Item_func_ltrim::fix_length_and_dec();
+ maybe_null= true;
++ return res;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_ltrim_oracle>(thd, this); }
};
@@@ -638,26 -525,6 +643,27 @@@ public
};
+class Item_func_rtrim_oracle :public Item_func_rtrim
+{
+protected:
+ String *make_empty_result()
+ { null_value= 1; return NULL; }
+ const char *func_name_ext() const { return "_oracle"; }
+public:
+ Item_func_rtrim_oracle(THD *thd, Item *a, Item *b):
+ Item_func_rtrim(thd, a, b) {}
+ Item_func_rtrim_oracle(THD *thd, Item *a): Item_func_rtrim(thd, a) {}
+ const char *func_name() const { return "rtrim_oracle"; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- Item_func_rtrim::fix_length_and_dec();
++ bool res= Item_func_rtrim::fix_length_and_dec();
+ maybe_null= true;
++ return res;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_rtrim_oracle>(thd, this); }
+};
+
/*
Item_func_password -- new (4.1.1) PASSWORD() function implementation.
Returns strcat('*', octet2hex(sha1(sha1(password)))). '*' stands for new
@@@ -712,10 -580,11 +719,11 @@@ public
maybe_null=1;
/* 9 = MAX ((8- (arg_len % 8)) + 1) */
max_length = args[0]->max_length + 9;
+ return FALSE;
}
const char *func_name() const { return "des_encrypt"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_des_encrypt>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_des_encrypt>(thd, this); }
};
class Item_func_des_decrypt :public Item_str_binary_checksum_func
@@@ -734,10 -603,11 +742,11 @@@ public
max_length= args[0]->max_length;
if (max_length >= 9U)
max_length-= 9U;
+ return FALSE;
}
const char *func_name() const { return "des_decrypt"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_des_decrypt>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_des_decrypt>(thd, this); }
};
@@@ -790,10 -660,10 +799,10 @@@ public
Item_func_encode(THD *thd, Item *a, Item *seed_arg):
Item_str_binary_checksum_func(thd, a, seed_arg) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "encode"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_encode>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_encode>(thd, this); }
protected:
virtual void crypto_transform(String *);
private:
@@@ -847,29 -718,8 +857,30 @@@ public
}
const char *func_name() const { return "database"; }
const char *fully_qualified_func_name() const { return "database()"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_database>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_database>(thd, this); }
+};
+
+
+class Item_func_sqlerrm :public Item_func_sysconst
+{
+public:
+ Item_func_sqlerrm(THD *thd): Item_func_sysconst(thd) {}
+ String *val_str(String *);
+ const char *func_name() const { return "SQLERRM"; }
+ const char *fully_qualified_func_name() const { return "SQLERRM"; }
+ void print(String *str, enum_query_type query_type)
+ {
+ str->append(func_name());
+ }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ max_length= 512 * system_charset_info->mbmaxlen;
+ null_value= maybe_null= false;
++ return FALSE;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sqlerrm>(thd, this); }
};
@@@ -961,10 -815,10 +976,10 @@@ class Item_func_soundex :public Item_st
public:
Item_func_soundex(THD *thd, Item *a): Item_str_func(thd, a) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "soundex"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_soundex>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_soundex>(thd, this); }
};
@@@ -975,10 -829,10 +990,10 @@@ public
double val_real();
longlong val_int();
String *val_str(String *str);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "elt"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_elt>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_elt>(thd, this); }
};
@@@ -989,10 -843,10 +1004,10 @@@ class Item_func_make_set :public Item_s
public:
Item_func_make_set(THD *thd, List<Item> &list): Item_str_func(thd, list) {}
String *val_str(String *str);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "make_set"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_make_set>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_make_set>(thd, this); }
};
@@@ -1005,11 -859,12 +1020,11 @@@ public
Item_func_format(THD *thd, Item *org, Item *dec, Item *lang):
Item_str_ascii_func(thd, org, dec, lang) {}
- MY_LOCALE *get_locale(Item *item);
String *val_str_ascii(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "format"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_format>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_format>(thd, this); }
};
@@@ -1021,35 -876,18 +1036,37 @@@ public
Item_func_char(THD *thd, List<Item> &list, CHARSET_INFO *cs):
Item_str_func(thd, list)
{ collation.set(cs); }
+ Item_func_char(THD *thd, Item *arg1, CHARSET_INFO *cs):
+ Item_str_func(thd, arg1)
+ { collation.set(cs); }
String *val_str(String *);
+ void append_char(String * str, int32 num);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
max_length= arg_count * 4;
+ return FALSE;
}
const char *func_name() const { return "char"; }
void print(String *str, enum_query_type query_type);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_char>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_char>(thd, this); }
};
+class Item_func_chr :public Item_func_char
+{
+public:
+ Item_func_chr(THD *thd, Item *arg1, CHARSET_INFO *cs):
+ Item_func_char(thd, arg1, cs) {}
+ String *val_str(String *);
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ max_length= 4;
++ return FALSE;
+ }
+ const char *func_name() const { return "chr"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_chr>(thd, this); }
+};
class Item_func_repeat :public Item_str_func
{
@@@ -1058,10 -896,10 +1075,10 @@@ public
Item_func_repeat(THD *thd, Item *arg1, Item *arg2):
Item_str_func(thd, arg1, arg2) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "repeat"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_repeat>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_repeat>(thd, this); }
};
@@@ -1070,10 -908,10 +1087,10 @@@ class Item_func_space :public Item_str_
public:
Item_func_space(THD *thd, Item *arg1): Item_str_func(thd, arg1) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "space"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_space>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_space>(thd, this); }
};
@@@ -1094,84 -932,31 +1111,86 @@@ public
};
-class Item_func_rpad :public Item_str_func
+class Item_func_pad: public Item_str_func
{
- String tmp_value, rpad_str;
+protected:
+ String tmp_value, pad_str;
public:
- Item_func_rpad(THD *thd, Item *arg1, Item *arg2, Item *arg3):
+ Item_func_pad(THD *thd, Item *arg1, Item *arg2, Item *arg3):
Item_str_func(thd, arg1, arg2, arg3) {}
- String *val_str(String *);
+ Item_func_pad(THD *thd, Item *arg1, Item *arg2):
+ Item_str_func(thd, arg1, arg2) {}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
+};
+
+
+class Item_func_rpad :public Item_func_pad
+{
+public:
+ Item_func_rpad(THD *thd, Item *arg1, Item *arg2, Item *arg3):
+ Item_func_pad(thd, arg1, arg2, arg3) {}
+ Item_func_rpad(THD *thd, Item *arg1, Item *arg2):
+ Item_func_pad(thd, arg1, arg2) {}
+ String *val_str(String *);
const char *func_name() const { return "rpad"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_rpad>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_rpad>(thd, this); }
};
-class Item_func_lpad :public Item_str_func
+class Item_func_rpad_oracle :public Item_func_rpad
+{
+ String *make_empty_result()
+ { null_value= 1; return NULL; }
+public:
+ Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2, Item *arg3):
+ Item_func_rpad(thd, arg1, arg2, arg3) {}
+ Item_func_rpad_oracle(THD *thd, Item *arg1, Item *arg2):
+ Item_func_rpad(thd, arg1, arg2) {}
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- Item_func_rpad::fix_length_and_dec();
++ bool res= Item_func_rpad::fix_length_and_dec();
+ maybe_null= true;
++ return res;
+ }
+ const char *func_name() const { return "rpad_oracle"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_rpad_oracle>(thd, this); }
+};
+
+
+class Item_func_lpad :public Item_func_pad
{
- String tmp_value, lpad_str;
public:
Item_func_lpad(THD *thd, Item *arg1, Item *arg2, Item *arg3):
- Item_str_func(thd, arg1, arg2, arg3) {}
+ Item_func_pad(thd, arg1, arg2, arg3) {}
+ Item_func_lpad(THD *thd, Item *arg1, Item *arg2):
+ Item_func_pad(thd, arg1, arg2) {}
String *val_str(String *);
- bool fix_length_and_dec();
const char *func_name() const { return "lpad"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_lpad>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_lpad>(thd, this); }
+};
+
+
+class Item_func_lpad_oracle :public Item_func_lpad
+{
+ String *make_empty_result()
+ { null_value= 1; return NULL; }
+public:
+ Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2, Item *arg3):
+ Item_func_lpad(thd, arg1, arg2, arg3) {}
+ Item_func_lpad_oracle(THD *thd, Item *arg1, Item *arg2):
+ Item_func_lpad(thd, arg1, arg2) {}
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- Item_func_lpad::fix_length_and_dec();
++ bool res= Item_func_lpad::fix_length_and_dec();
+ maybe_null= true;
++ return res;
+ }
+ const char *func_name() const { return "lpad_oracle"; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_lpad_oracle>(thd, this); }
};
@@@ -1187,44 -972,30 +1206,46 @@@ public
collation.set(default_charset());
max_length=64;
maybe_null= 1;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_conv>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_conv>(thd, this); }
};
class Item_func_hex :public Item_str_ascii_checksum_func
{
+protected:
String tmp_value;
+ /*
+ Calling arg[0]->type_handler() can be expensive on every row.
+ It's a virtual method, and in case if args[0] is a complex Item,
+ its type_handler() can call more virtual methods.
+ So let's cache it during fix_length_and_dec().
+ */
+ const Type_handler *m_arg0_type_handler;
public:
Item_func_hex(THD *thd, Item *a):
- Item_str_ascii_checksum_func(thd, a) {}
+ Item_str_ascii_checksum_func(thd, a), m_arg0_type_handler(NULL) {}
const char *func_name() const { return "hex"; }
- String *val_str_ascii(String *);
+ String *val_str_ascii_from_val_int(String *str);
+ String *val_str_ascii_from_val_real(String *str);
+ String *val_str_ascii_from_val_str(String *str);
+ String *val_str_ascii(String *str)
+ {
+ DBUG_ASSERT(fixed);
+ return m_arg0_type_handler->Item_func_hex_val_str_ascii(this, str);
+ }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- collation.set(default_charset());
+ collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
decimals=0;
fix_char_length(args[0]->max_length * 2);
+ m_arg0_type_handler= args[0]->type_handler();
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_hex>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_hex>(thd, this); }
};
class Item_func_unhex :public Item_str_func
@@@ -1243,9 -1014,10 +1264,10 @@@ public
collation.set(&my_charset_bin);
decimals=0;
max_length=(1+args[0]->max_length)/2;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_unhex>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_unhex>(thd, this); }
};
@@@ -1351,10 -1126,10 +1376,10 @@@ class Item_func_export_set: public Item
Item_func_export_set(THD *thd, Item *a, Item *b, Item* c, Item* d, Item* e):
Item_str_func(thd, a, b, c, d, e) {}
String *val_str(String *str);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "export_set"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_export_set>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_export_set>(thd, this); }
};
@@@ -1371,9 -1146,10 +1396,10 @@@ public
ulonglong max_result_length= (ulonglong) args[0]->max_length * 2 +
2 * collation.collation->mbmaxlen;
max_length= (uint32) MY_MIN(max_result_length, MAX_BLOB_WIDTH);
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_quote>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_quote>(thd, this); }
};
class Item_func_conv_charset :public Item_str_func
@@@ -1453,21 -1229,20 +1479,21 @@@ public
return 1;
return res;
}
- void fix_length_and_dec();
+ bool fix_length_and_dec();
const char *func_name() const { return "convert"; }
void print(String *str, enum_query_type query_type);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_conv_charset>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_conv_charset>(thd, this); }
};
class Item_func_set_collation :public Item_str_func
{
+ CHARSET_INFO *m_set_collation;
public:
- Item_func_set_collation(THD *thd, Item *a, Item *b):
- Item_str_func(thd, a, b) {}
+ Item_func_set_collation(THD *thd, Item *a, CHARSET_INFO *set_collation):
+ Item_str_func(thd, a), m_set_collation(set_collation) {}
String *val_str(String *);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "collate"; }
enum precedence precedence() const { return COLLATE_PRECEDENCE; }
@@@ -1555,36 -1331,33 +1582,36 @@@ public
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{ return this; }
void print(String *str, enum_query_type query_type);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_weight_string>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_weight_string>(thd, this); }
};
-class Item_func_crc32 :public Item_int_func
+class Item_func_crc32 :public Item_long_func
{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_str(func_name()); }
String value;
public:
- Item_func_crc32(THD *thd, Item *a): Item_int_func(thd, a)
+ Item_func_crc32(THD *thd, Item *a): Item_long_func(thd, a)
{ unsigned_flag= 1; }
const char *func_name() const { return "crc32"; }
- void fix_length_and_dec() { max_length=10; }
+ bool fix_length_and_dec() { max_length=10; return FALSE; }
longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_crc32>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_crc32>(thd, this); }
};
-class Item_func_uncompressed_length : public Item_int_func
+class Item_func_uncompressed_length : public Item_long_func_length
{
String value;
public:
- Item_func_uncompressed_length(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_uncompressed_length(THD *thd, Item *a)
+ :Item_long_func_length(thd, a) {}
const char *func_name() const{return "uncompressed_length";}
- void fix_length_and_dec() { max_length=10; maybe_null= true; }
+ bool fix_length_and_dec() { max_length=10; maybe_null= true; return FALSE; }
longlong val_int();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_uncompressed_length>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_uncompressed_length>(thd, this); }
};
#ifdef HAVE_COMPRESS
@@@ -1599,11 -1372,15 +1626,15 @@@ class Item_func_compress: public Item_s
public:
Item_func_compress(THD *thd, Item *a)
:Item_str_binary_checksum_func(thd, a) {}
- void fix_length_and_dec(){max_length= (args[0]->max_length*120)/100+12;}
+ bool fix_length_and_dec()
+ {
+ max_length= (args[0]->max_length * 120) / 100 + 12;
+ return FALSE;
+ }
const char *func_name() const{return "compress";}
String *val_str(String *) ZLIB_DEPENDED_FUNCTION
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_compress>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_compress>(thd, this); }
};
class Item_func_uncompress: public Item_str_binary_checksum_func
@@@ -1612,11 -1389,15 +1643,15 @@@
public:
Item_func_uncompress(THD *thd, Item *a)
:Item_str_binary_checksum_func(thd, a) {}
- void fix_length_and_dec(){ maybe_null= 1; max_length= MAX_BLOB_WIDTH; }
+ bool fix_length_and_dec()
+ {
+ maybe_null= 1; max_length= MAX_BLOB_WIDTH;
+ return FALSE;
+ }
const char *func_name() const{return "uncompress";}
String *val_str(String *) ZLIB_DEPENDED_FUNCTION
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_uncompress>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_uncompress>(thd, this); }
};
@@@ -1691,9 -1473,10 +1727,10 @@@ public
max_length= MAX_BLOB_WIDTH;
maybe_null= 1;
decimals= 0;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_dyncol_json>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_dyncol_json>(thd, this); }
};
/*
@@@ -1744,32 -1527,13 +1781,33 @@@ class Item_func_dyncol_list: public Ite
public:
Item_func_dyncol_list(THD *thd, Item *str): Item_str_func(thd, str)
{collation.set(DYNCOL_UTF);}
- void fix_length_and_dec() { maybe_null= 1; max_length= MAX_BLOB_WIDTH; };
+ bool fix_length_and_dec()
+ { maybe_null= 1; max_length= MAX_BLOB_WIDTH; return FALSE; };
const char *func_name() const{ return "column_list"; }
String *val_str(String *);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_dyncol_list>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_dyncol_list>(thd, this); }
};
-#endif /* ITEM_STRFUNC_INCLUDED */
+/*
+ this is used by JOIN_TAB::keep_current_rowid
+ and stores handler::position().
+ It has nothing to do with _rowid pseudo-column, that the parser supports.
+*/
+class Item_temptable_rowid :public Item_str_func
+{
+public:
+ TABLE *table;
+ Item_temptable_rowid(TABLE *table_arg);
+ const Type_handler *type_handler() const { return &type_handler_string; }
+ Field *create_tmp_field(bool group, TABLE *table)
+ { return create_table_field_from_handler(table); }
+ String *val_str(String *str);
+ enum Functype functype() const { return TEMPTABLE_ROWID; }
+ const char *func_name() const { return "<rowid>"; }
- void fix_length_and_dec();
++ bool fix_length_and_dec();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_temptable_rowid>(thd, this); }
+};
+#endif /* ITEM_STRFUNC_INCLUDED */
diff --cc sql/item_subselect.cc
index 4280a67e356,8a9dd083911..1947a45186a
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@@ -1181,12 -1182,26 +1187,12 @@@ void Item_singlerow_subselect::store(ui
row[i]->cache_value();
}
-enum Item_result Item_singlerow_subselect::result_type() const
-{
- return engine->type();
-}
-
-enum Item_result Item_singlerow_subselect::cmp_type() const
-{
- return engine->cmptype();
-}
-
-/*
- Don't rely on the result type to calculate field type.
- Ask the engine instead.
-*/
-enum_field_types Item_singlerow_subselect::field_type() const
+const Type_handler *Item_singlerow_subselect::type_handler() const
{
- return engine->field_type();
+ return engine->type_handler();
}
- void Item_singlerow_subselect::fix_length_and_dec()
+ bool Item_singlerow_subselect::fix_length_and_dec()
{
if ((max_columns= engine->cols()) == 1)
{
@@@ -3721,19 -3742,21 +3732,21 @@@ bool subselect_engine::set_row(List<Ite
item->decimals= sel_item->decimals;
item->unsigned_flag= sel_item->unsigned_flag;
maybe_null= sel_item->maybe_null;
- if (!(row[i]= Item_cache::get_cache(thd, sel_item, sel_item->cmp_type())))
+ if (!(row[i]= sel_item->get_cache(thd)))
- return;
+ return TRUE;
row[i]->setup(thd, sel_item);
//psergey-backport-timours: row[i]->store(sel_item);
}
if (item_list.elements > 1)
- cmp_type= res_type= ROW_RESULT;
+ set_handler(&type_handler_row);
+ return FALSE;
}
- void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
+ bool subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{
DBUG_ASSERT(row || select_lex->item_list.elements==1);
- set_row(select_lex->item_list, row);
+ if (set_row(select_lex->item_list, row))
+ return TRUE;
item->collation.set(row[0]->collation);
if (cols() != 1)
maybe_null= 0;
diff --cc sql/item_subselect.h
index dfe3287615b,bd6a1bdc498..363dbba4ddd
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@@ -305,10 -303,12 +305,10 @@@ public
my_decimal *val_decimal(my_decimal *);
bool val_bool();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
- enum Item_result result_type() const;
- enum Item_result cmp_type() const;
- enum_field_types field_type() const;
+ const Type_handler *type_handler() const;
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- uint cols();
+ uint cols() const;
Item* element_index(uint i) { return reinterpret_cast<Item*>(row[i]); }
Item** addr(uint i) { return (Item**)row + i; }
bool check_cols(uint c);
@@@ -401,10 -402,8 +401,10 @@@ public
String *val_str(String*);
my_decimal *val_decimal(my_decimal *);
bool val_bool();
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ { return get_date_from_int(ltime, fuzzydate); }
bool fix_fields(THD *thd, Item **ref);
- void fix_length_and_dec();
+ bool fix_length_and_dec();
void print(String *str, enum_query_type query_type);
bool select_transformer(JOIN *join);
void top_level_item() { abort_on_null=1; }
@@@ -865,9 -870,9 +865,9 @@@ public
Item_subselect *item);
void cleanup();
int prepare(THD *thd);
- void fix_length_and_dec(Item_cache** row);
+ bool fix_length_and_dec(Item_cache** row);
int exec();
- uint cols();
+ uint cols() const;
uint8 uncacheable();
void exclude();
table_map upper_select_const_tables();
@@@ -901,9 -905,9 +901,9 @@@ public
Item_subselect *item);
void cleanup();
int prepare(THD *);
- void fix_length_and_dec(Item_cache** row);
+ bool fix_length_and_dec(Item_cache** row);
int exec();
- uint cols();
+ uint cols() const;
uint8 uncacheable();
void exclude();
table_map upper_select_const_tables();
@@@ -959,9 -963,9 +959,9 @@@ public
~subselect_uniquesubquery_engine();
void cleanup();
int prepare(THD *);
- void fix_length_and_dec(Item_cache** row);
+ bool fix_length_and_dec(Item_cache** row);
int exec();
- uint cols() { return 1; }
+ uint cols() const { return 1; }
uint8 uncacheable() { return UNCACHEABLE_DEPENDENT_INJECTED; }
void exclude();
table_map upper_select_const_tables() { return 0; }
@@@ -1381,8 -1385,8 +1381,8 @@@ public
uint count_columns_with_nulls_arg);
int prepare(THD *thd_arg) { set_thd(thd_arg); return 0; }
int exec();
- void fix_length_and_dec(Item_cache**) {}
+ bool fix_length_and_dec(Item_cache**) { return FALSE; }
- uint cols() { /* TODO: what is the correct value? */ return 1; }
+ uint cols() const { /* TODO: what is the correct value? */ return 1; }
uint8 uncacheable() { return UNCACHEABLE_DEPENDENT; }
void exclude() {}
table_map upper_select_const_tables() { return 0; }
diff --cc sql/item_sum.cc
index 0e506cc26f2,9e59ec4e373..3163fb9ea2e
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@@ -1167,25 -1161,40 +1166,27 @@@ Item_sum_hybrid::fix_fields(THD *thd, I
with_param= args[0]->with_param;
with_window_func|= args[0]->with_window_func;
- fix_length_and_dec();
- Item *item2= item->real_item();
- if (item2->type() == Item::FIELD_ITEM)
- set_handler_by_field_type(((Item_field*) item2)->field->type());
- else if (item->cmp_type() == TIME_RESULT)
- set_handler_by_field_type(item2->field_type());
- else
- set_handler_by_result_type(item2->result_type(),
- max_length, collation.collation);
++ if (fix_length_and_dec())
++ DBUG_RETURN(TRUE);
+
- switch (Item_sum_hybrid::result_type()) {
- case INT_RESULT:
- case DECIMAL_RESULT:
- case STRING_RESULT:
- break;
- case REAL_RESULT:
- max_length= float_length(decimals);
- break;
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- };
if (!is_window_func_sum_expr())
setup_hybrid(thd, args[0], NULL);
- /* MIN/MAX can return NULL for empty set indepedent of the used column */
- maybe_null= 1;
result_field=0;
- null_value=1;
- if (fix_length_and_dec() ||
- check_sum_func(thd, ref))
- return TRUE;
+
+ if (check_sum_func(thd, ref))
+ DBUG_RETURN(TRUE);
orig_args[0]= args[0];
fixed= 1;
- return FALSE;
+ DBUG_RETURN(FALSE);
+}
+
+
- void Item_sum_hybrid::fix_length_and_dec()
++bool Item_sum_hybrid::fix_length_and_dec()
+{
+ DBUG_ASSERT(args[0]->field_type() == args[0]->real_item()->field_type());
+ DBUG_ASSERT(args[0]->result_type() == args[0]->real_item()->result_type());
- (void) args[0]->type_handler()->Item_sum_hybrid_fix_length_and_dec(this);
++ return args[0]->type_handler()->Item_sum_hybrid_fix_length_and_dec(this);
}
@@@ -1235,181 -1244,42 +1236,182 @@@ Field *Item_sum_hybrid::create_tmp_fiel
if (args[0]->type() == Item::FIELD_ITEM)
{
- field= ((Item_field*) args[0])->field;
-
- if ((field= create_tmp_field_from_field(table->in_use, field, name, table,
- NULL)))
+ Field *field= ((Item_field*) args[0])->field;
+ if ((field= create_tmp_field_from_field(table->in_use, field, &name,
+ table, NULL)))
field->flags&= ~NOT_NULL_FLAG;
- return field;
+ DBUG_RETURN(field);
}
+ DBUG_RETURN(tmp_table_field_from_field_type(table));
+}
- /*
- DATE/TIME fields have STRING_RESULT result types.
- In order to preserve field type, it's needed to handle DATE/TIME
- fields creations separately.
- */
- mem_root= table->in_use->mem_root;
- switch (args[0]->field_type()) {
- case MYSQL_TYPE_DATE:
- field= new (mem_root)
- Field_newdate(0, maybe_null ? (uchar*)"" : 0, 0, Field::NONE, name);
- break;
- case MYSQL_TYPE_TIME:
- field= new_Field_time(mem_root, 0, maybe_null ? (uchar*)"" : 0, 0,
- Field::NONE, name, decimals);
- break;
- case MYSQL_TYPE_TIMESTAMP:
- case MYSQL_TYPE_DATETIME:
- field= new_Field_datetime(mem_root, 0, maybe_null ? (uchar*)"" : 0, 0,
- Field::NONE, name, decimals);
- break;
- default:
- return Item_sum::create_tmp_field(group, table);
+/***********************************************************************
+** Item_sum_sp class
+***********************************************************************/
+
+Item_sum_sp::Item_sum_sp(THD *thd, Name_resolution_context *context_arg,
+ sp_name *name_arg, sp_head *sp, List<Item> &list)
+ :Item_sum(thd, list), Item_sp(thd, context_arg, name_arg)
+{
+ maybe_null= 1;
+ quick_group= 0;
+ m_sp= sp;
+}
+
+Item_sum_sp::Item_sum_sp(THD *thd, Name_resolution_context *context_arg,
+ sp_name *name_arg, sp_head *sp)
+ :Item_sum(thd), Item_sp(thd, context_arg, name_arg)
+{
+ maybe_null= 1;
+ quick_group= 0;
+ m_sp= sp;
+}
+
+Item_sum_sp::Item_sum_sp(THD *thd, Item_sum_sp *item):
+ Item_sum(thd, item), Item_sp(thd, item)
+{
+ maybe_null= item->maybe_null;
+ quick_group= item->quick_group;
+}
+
+bool
+Item_sum_sp::fix_fields(THD *thd, Item **ref)
+{
+ DBUG_ASSERT(fixed == 0);
+ if (init_sum_func_check(thd))
+ return TRUE;
+ decimals= 0;
+
+ m_sp= m_sp ? m_sp : sp_handler_function.sp_find_routine(thd, m_name, true);
+
+ if (!m_sp)
+ {
+ my_missing_function_error(m_name->m_name, ErrConvDQName(m_name).ptr());
+ context->process_error(thd);
+ return TRUE;
}
- if (field)
- field->init(table);
- return field;
+
+ if (init_result_field(thd, max_length, maybe_null, &null_value, &name))
+ return TRUE;
+
+ for (uint i= 0 ; i < arg_count ; i++)
+ {
+ if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i]))
+ return TRUE;
+ set_if_bigger(decimals, args[i]->decimals);
+ m_with_subquery|= args[i]->with_subquery();
+ with_window_func|= args[i]->with_window_func;
+ }
+ result_field= NULL;
+ max_length= float_length(decimals);
+ null_value= 1;
- fix_length_and_dec();
++ if (fix_length_and_dec())
++ return TRUE;
+
+ if (check_sum_func(thd, ref))
+ return TRUE;
+
+ memcpy(orig_args, args, sizeof(Item *) * arg_count);
+ fixed= 1;
+ return FALSE;
+}
+
+/**
+ Execute function to store value in result field.
+ This is called when we need the value to be returned for the function.
+ Here we send a signal in form of the server status that all rows have been
+ fetched and now we have to exit from the function with the return value.
+ @return Function returns error status.
+ @retval FALSE on success.
+ @retval TRUE if an error occurred.
+*/
+
+bool
+Item_sum_sp::execute()
+{
+ THD *thd= current_thd;
+ bool res;
+ uint old_server_status= thd->server_status;
+
+ /* We set server status so we can send a signal to exit from the
+ function with the return value. */
+
+ thd->server_status= SERVER_STATUS_LAST_ROW_SENT;
+ res= Item_sp::execute(thd, &null_value, args, arg_count);
+ thd->server_status= old_server_status;
+ return res;
+}
+
+/**
+ Handles the aggregation of the values.
+ @note: See class description for more details on how and why this is done.
+ @return The error state.
+ @retval FALSE on success.
+ @retval TRUE if an error occurred.
+*/
+
+bool
+Item_sum_sp::add()
+{
+ return execute_impl(current_thd, args, arg_count);
+}
+
+
+void
+Item_sum_sp::clear()
+{
+ delete func_ctx;
+ func_ctx= NULL;
+ sp_query_arena->free_items();
+ free_root(&sp_mem_root, MYF(0));
+}
+
+const Type_handler *Item_sum_sp::type_handler() const
+{
+ DBUG_ENTER("Item_sum_sp::type_handler");
+ DBUG_PRINT("info", ("m_sp = %p", (void *) m_sp));
+ DBUG_ASSERT(sp_result_field);
+ // This converts ENUM/SET to STRING
+ const Type_handler *handler= sp_result_field->type_handler();
+ DBUG_RETURN(handler->type_handler_for_item_field());
+}
+
+void
+Item_sum_sp::cleanup()
+{
+ Item_sp::cleanup();
+ Item_sum::cleanup();
}
+/**
+ Initialize local members with values from the Field interface.
+ @note called from Item::fix_fields.
+*/
+
- void
++bool
+Item_sum_sp::fix_length_and_dec()
+{
+ DBUG_ENTER("Item_sum_sp::fix_length_and_dec");
+ DBUG_ASSERT(sp_result_field);
+ Type_std_attributes::set(sp_result_field->type_std_attributes());
- Item_sum::fix_length_and_dec();
- DBUG_VOID_RETURN;
++ bool res= Item_sum::fix_length_and_dec();
++ DBUG_RETURN(res);
+}
+
+const char *
+Item_sum_sp::func_name() const
+{
+ THD *thd= current_thd;
+ return Item_sp::func_name(thd);
+}
+
+Item* Item_sum_sp::copy_or_same(THD *thd)
+{
+ Item_sum_sp *copy_item= new (thd->mem_root) Item_sum_sp(thd, this);
+ copy_item->init_result_field(thd, max_length, maybe_null,
+ ©_item->null_value, ©_item->name);
+ return copy_item;
+}
/***********************************************************************
** reset and add of sum_func
@@@ -1467,68 -1327,42 +1469,70 @@@ void Item_sum_sum::clear(
}
+void Item_sum_sum::fix_length_and_dec_double()
+{
+ set_handler(&type_handler_double); // Change FLOAT to DOUBLE
+ decimals= args[0]->decimals;
+ sum= 0.0;
+}
+
+
+void Item_sum_sum::fix_length_and_dec_decimal()
+{
+ set_handler(&type_handler_newdecimal); // Change temporal to new DECIMAL
+ decimals= args[0]->decimals;
+ /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
+ int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
+ max_length= my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag);
+ curr_dec_buff= 0;
+ my_decimal_set_zero(dec_buffs);
+}
+
+
- void Item_sum_sum::fix_length_and_dec()
+ bool Item_sum_sum::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_sum::fix_length_and_dec");
maybe_null=null_value=1;
- args[0]->cast_to_int_type_handler()->Item_sum_sum_fix_length_and_dec(this);
- decimals= args[0]->decimals;
- switch (args[0]->cast_to_int_type()) {
- case REAL_RESULT:
- case STRING_RESULT:
- set_handler_by_field_type(MYSQL_TYPE_DOUBLE);
- sum= 0.0;
- break;
- case INT_RESULT:
- case TIME_RESULT:
- case DECIMAL_RESULT:
++ if (args[0]->cast_to_int_type_handler()->
++ Item_sum_sum_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
+ max_length, (int) decimals));
- DBUG_VOID_RETURN;
++ DBUG_RETURN(FALSE);
+}
+
+
+void Item_sum_sum::direct_add(my_decimal *add_sum_decimal)
+{
+ DBUG_ENTER("Item_sum_sum::direct_add");
+ DBUG_PRINT("info", ("add_sum_decimal: %p", add_sum_decimal));
+ direct_added= TRUE;
+ direct_reseted_field= FALSE;
+ if (add_sum_decimal)
{
- /* SUM result can't be longer than length(arg) + length(MAX_ROWS) */
- int precision= args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS;
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
- curr_dec_buff= 0;
- set_handler_by_field_type(MYSQL_TYPE_NEWDECIMAL);
- my_decimal_set_zero(dec_buffs);
- break;
+ direct_sum_is_null= FALSE;
+ direct_sum_decimal= *add_sum_decimal;
}
- case ROW_RESULT:
- DBUG_ASSERT(0);
+ else
+ {
+ direct_sum_is_null= TRUE;
+ direct_sum_decimal= decimal_zero;
}
- DBUG_PRINT("info", ("Type: %s (%d, %d)",
- (result_type() == REAL_RESULT ? "REAL_RESULT" :
- result_type() == DECIMAL_RESULT ? "DECIMAL_RESULT" :
- result_type() == INT_RESULT ? "INT_RESULT" :
- "--ILLEGAL!!!--"),
- max_length,
- (int)decimals));
- DBUG_RETURN(FALSE);
+ DBUG_VOID_RETURN;
+}
+
+
+void Item_sum_sum::direct_add(double add_sum_real, bool add_sum_is_null)
+{
+ DBUG_ENTER("Item_sum_sum::direct_add");
+ DBUG_PRINT("info", ("add_sum_real: %f", add_sum_real));
+ direct_added= TRUE;
+ direct_reseted_field= FALSE;
+ direct_sum_is_null= add_sum_is_null;
+ direct_sum_real= add_sum_real;
+ DBUG_VOID_RETURN;
}
@@@ -1889,39 -1662,30 +1893,41 @@@ void Item_sum_count::cleanup(
/*
Avgerage
*/
+
+void Item_sum_avg::fix_length_and_dec_decimal()
+{
+ Item_sum_sum::fix_length_and_dec_decimal();
+ int precision= args[0]->decimal_precision() + prec_increment;
+ decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
+ max_length= my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag);
+ f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
+ f_scale= args[0]->decimals;
+ dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
+}
+
+
+void Item_sum_avg::fix_length_and_dec_double()
+{
+ Item_sum_sum::fix_length_and_dec_double();
+ decimals= MY_MIN(args[0]->decimals + prec_increment,
+ FLOATING_POINT_DECIMALS);
+ max_length= MY_MIN(args[0]->max_length + prec_increment, float_length(decimals));
+}
+
+
- void Item_sum_avg::fix_length_and_dec()
+ bool Item_sum_avg::fix_length_and_dec()
{
- if (Item_sum_sum::fix_length_and_dec())
- return TRUE;
- maybe_null=null_value=1;
+ DBUG_ENTER("Item_sum_avg::fix_length_and_dec");
prec_increment= current_thd->variables.div_precincrement;
- if (Item_sum_avg::result_type() == DECIMAL_RESULT)
- {
- int precision= args[0]->decimal_precision() + prec_increment;
- decimals= MY_MIN(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
- f_precision= MY_MIN(precision+DECIMAL_LONGLONG_DIGITS, DECIMAL_MAX_PRECISION);
- f_scale= args[0]->decimals;
- dec_bin_size= my_decimal_get_binary_size(f_precision, f_scale);
- }
- else
- {
- decimals= MY_MIN(args[0]->decimals + prec_increment,
- FLOATING_POINT_DECIMALS);
- max_length= MY_MIN(args[0]->max_length + prec_increment, float_length(decimals));
- }
- return FALSE;
+ maybe_null=null_value=1;
- args[0]->cast_to_int_type_handler()->Item_sum_avg_fix_length_and_dec(this);
++ if (args[0]->cast_to_int_type_handler()->
++ Item_sum_avg_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
+ max_length, (int) decimals));
- DBUG_VOID_RETURN;
++ DBUG_RETURN(FALSE);
}
@@@ -2114,26 -1884,7 +2120,26 @@@ Item_sum_variance::Item_sum_variance(TH
}
+void Item_sum_variance::fix_length_and_dec_double()
+{
+ DBUG_ASSERT(Item_sum_variance::type_handler() == &type_handler_double);
+ decimals= MY_MIN(args[0]->decimals + 4, FLOATING_POINT_DECIMALS);
+}
+
+
+void Item_sum_variance::fix_length_and_dec_decimal()
+{
+ DBUG_ASSERT(Item_sum_variance::type_handler() == &type_handler_double);
+ int precision= args[0]->decimal_precision() * 2 + prec_increment;
+ decimals= MY_MIN(args[0]->decimals + prec_increment,
+ FLOATING_POINT_DECIMALS - 1);
+ max_length= my_decimal_precision_to_length_no_truncation(precision,
+ decimals,
+ unsigned_flag);
+}
+
+
- void Item_sum_variance::fix_length_and_dec()
+ bool Item_sum_variance::fix_length_and_dec()
{
DBUG_ENTER("Item_sum_variance::fix_length_and_dec");
maybe_null= null_value= 1;
@@@ -2145,11 -1896,30 +2151,11 @@@
type of the result is an implementation-defined aproximate numeric
type.
*/
--
- args[0]->type_handler()->Item_sum_variance_fix_length_and_dec(this);
- switch (args[0]->result_type()) {
- case REAL_RESULT:
- case STRING_RESULT:
- decimals= MY_MIN(args[0]->decimals + 4, FLOATING_POINT_DECIMALS);
- break;
- case INT_RESULT:
- case DECIMAL_RESULT:
- {
- int precision= args[0]->decimal_precision()*2 + prec_increment;
- decimals= MY_MIN(args[0]->decimals + prec_increment,
- FLOATING_POINT_DECIMALS-1);
- max_length= my_decimal_precision_to_length_no_truncation(precision,
- decimals,
- unsigned_flag);
-
- break;
- }
- case ROW_RESULT:
- case TIME_RESULT:
- DBUG_ASSERT(0);
- }
- DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals));
++ if (args[0]->type_handler()->Item_sum_variance_fix_length_and_dec(this))
++ DBUG_RETURN(TRUE);
+ DBUG_PRINT("info", ("Type: %s (%d, %d)", type_handler()->name().ptr(),
+ max_length, (int)decimals));
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
}
diff --cc sql/item_sum.h
index b66f6ab6143,5c8ff520259..b400ebd5f80
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@@ -457,7 -456,9 +457,8 @@@ public
Updated value is then saved in the field.
*/
virtual void update_field()=0;
- virtual void fix_length_and_dec() { maybe_null=1; null_value=1; }
- virtual bool keep_field_type(void) const { return 0; }
+ virtual bool fix_length_and_dec()
+ { maybe_null=1; null_value=1; return FALSE; }
virtual Item *result_item(THD *thd, Field *field);
void update_used_tables ();
@@@ -752,9 -751,10 +753,9 @@@ public
double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
- void fix_length_and_dec()
- { decimals=0; max_length=21; maybe_null=null_value=0; }
+ bool fix_length_and_dec()
+ { decimals=0; max_length=21; maybe_null=null_value=0; return FALSE; }
};
@@@ -762,15 -762,10 +763,15 @@@ class Item_sum_sum :public Item_sum_num
public Type_handler_hybrid_field_type
{
protected:
+ bool direct_added;
+ bool direct_reseted_field;
+ bool direct_sum_is_null;
+ double direct_sum_real;
double sum;
+ my_decimal direct_sum_decimal;
my_decimal dec_buffs[2];
uint curr_dec_buff;
- void fix_length_and_dec();
+ bool fix_length_and_dec();
public:
Item_sum_sum(THD *thd, Item *item_par, bool distinct):
@@@ -903,9 -889,7 +904,9 @@@ public
:Item_sum_sum(thd, item), count(item->count),
prec_increment(item->prec_increment) {}
+ void fix_length_and_dec_double();
+ void fix_length_and_dec_decimal();
- void fix_length_and_dec();
+ bool fix_length_and_dec();
enum Sumfunctype sum_func () const
{
return has_with_distinct() ? AVG_DISTINCT_FUNC : AVG_FUNC;
@@@ -1052,10 -1033,8 +1053,10 @@@ protected
cmp_sign(item->cmp_sign), was_values(item->was_values)
{ }
bool fix_fields(THD *, Item **);
- void fix_length_and_dec();
++ bool fix_length_and_dec();
void setup_hybrid(THD *thd, Item *item, Item *value_arg);
void clear();
+ void direct_add(Item *item);
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
@@@ -1228,142 -1210,6 +1232,142 @@@ private
void set_bits_from_counters();
};
+class sp_head;
+class sp_name;
+class Query_arena;
+struct st_sp_security_context;
+
+/*
+ Item_sum_sp handles STORED AGGREGATE FUNCTIONS
+
+ Each Item_sum_sp represents a custom aggregate function. Inside the
+ function's body, we require at least one occurence of FETCH GROUP NEXT ROW
+ instruction. This cursor is what makes custom stored aggregates possible.
+
+ During computation the function's add method is called. This in turn performs
+ an execution of the function. The function will execute from the current
+ function context (and instruction), if one exists, or from the start if not.
+ See Item_sp for more details.
+
+ Upon encounter of FETCH GROUP NEXT ROW instruction, the function will pause
+ execution. We assume that the user has performed the necessary additions for
+ a row, between two encounters of FETCH GROUP NEXT ROW.
+
+ Example:
+ create aggregate function f1(x INT) returns int
+ begin
+ declare continue handler for not found return s;
+ declare s int default 0
+ loop
+ fetch group next row;
+ set s = s + x;
+ end loop;
+ end
+
+ The function will always stop after an encounter of FETCH GROUP NEXT ROW,
+ except (!) on first encounter, as the value for the first row in the
+ group is already set in the argument x. This behaviour is done so when
+ a user writes a function, he should "logically" include FETCH GROUP NEXT ROW
+ before any "add" instructions in the stored function. This means however that
+ internally, the first occurence doesn't stop the function. See the
+ implementation of FETCH GROUP NEXT ROW for details as to how it happens.
+
+ Either way, one should assume that after calling "Item_sum_sp::add()" that
+ the values for that particular row have been added to the aggregation.
+
+ To produce values for val_xxx methods we need an extra syntactic construct.
+ We require a continue handler when "no more rows are available". val_xxx
+ methods force a function return by executing the function again, while
+ setting a server flag that no more rows have been found. This implies
+ that val_xxx methods should only be called once per group however.
+
+ Example:
+ DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN ret_val;
+*/
+class Item_sum_sp :public Item_sum,
+ public Item_sp
+{
+ private:
+ bool execute();
+
+public:
+ Item_sum_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name,
+ sp_head *sp);
+
+ Item_sum_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name,
+ sp_head *sp, List<Item> &list);
+ Item_sum_sp(THD *thd, Item_sum_sp *item);
+
+ enum Sumfunctype sum_func () const
+ {
+ return SP_AGGREGATE_FUNC;
+ }
+ Field *create_field_for_create_select(TABLE *table)
+ {
+ return create_table_field_from_handler(table);
+ }
- void fix_length_and_dec();
++ bool fix_length_and_dec();
+ bool fix_fields(THD *thd, Item **ref);
+ const char *func_name() const;
+ const Type_handler *type_handler() const;
+ bool add();
+
+ /* val_xx functions */
+ longlong val_int()
+ {
+ if(execute())
+ return 0;
+ return sp_result_field->val_int();
+ }
+
+ double val_real()
+ {
+ if(execute())
+ return 0.0;
+ return sp_result_field->val_real();
+ }
+
+ my_decimal *val_decimal(my_decimal *dec_buf)
+ {
+ if(execute())
+ return NULL;
+ return sp_result_field->val_decimal(dec_buf);
+ }
+
+ String *val_str(String *str)
+ {
+ String buf;
+ char buff[20];
+ buf.set(buff, 20, str->charset());
+ buf.length(0);
+ if (execute())
+ return NULL;
+ /*
+ result_field will set buf pointing to internal buffer
+ of the resul_field. Due to this it will change any time
+ when SP is executed. In order to prevent occasional
+ corruption of returned value, we make here a copy.
+ */
+ sp_result_field->val_str(&buf);
+ str->copy(buf);
+ return str;
+ }
+ void reset_field(){DBUG_ASSERT(0);}
+ void update_field(){DBUG_ASSERT(0);}
+ void clear();
+ void cleanup();
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ {
+ return execute() || sp_result_field->get_date(ltime, fuzzydate);
+ }
+ inline Field *get_sp_result_field()
+ {
+ return sp_result_field;
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_sum_sp>(thd, this); }
+ Item *copy_or_same(THD *thd);
+};
/* Items to get the value of a stored sum function */
@@@ -1561,11 -1402,13 +1565,11 @@@ class Item_sum_udf_float :public Item_u
double val_real();
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return REAL_RESULT; }
- enum Item_result cmp_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; }
Item *copy_or_same(THD* thd);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_sum_udf_float>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_sum_udf_float>(thd, this); }
};
@@@ -1583,11 -1426,12 +1587,11 @@@ public
{ DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str);
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_longlong; }
- void fix_length_and_dec() { decimals=0; max_length=21; }
+ bool fix_length_and_dec() { decimals=0; max_length=21; return FALSE; }
Item *copy_or_same(THD* thd);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_sum_udf_int>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_sum_udf_int>(thd, this); }
};
@@@ -1624,11 -1468,12 +1628,11 @@@ public
return cs->cset->strtoll10(cs, res->ptr(), &end, &err_not_used);
}
my_decimal *val_decimal(my_decimal *dec);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return string_field_type(); }
+ const Type_handler *type_handler() const { return string_type_handler(); }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
Item *copy_or_same(THD* thd);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_sum_udf_str>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_sum_udf_str>(thd, this); }
};
@@@ -1645,11 -1490,12 +1649,11 @@@ public
double val_real();
longlong val_int();
my_decimal *val_decimal(my_decimal *);
- enum Item_result result_type () const { return DECIMAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
+ const Type_handler *type_handler() const { return &type_handler_newdecimal; }
- void fix_length_and_dec() { fix_num_length_and_dec(); }
+ bool fix_length_and_dec() { fix_num_length_and_dec(); return FALSE; }
Item *copy_or_same(THD* thd);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_sum_udf_decimal>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_sum_udf_decimal>(thd, this); }
};
#else /* Dummy functions to get sql_yacc.cc compiled */
@@@ -1720,7 -1566,8 +1724,7 @@@ public
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
double val_real() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.0; }
longlong val_int() { DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
- void fix_length_and_dec() { maybe_null=1; max_length=0; }
- enum Item_result result_type () const { return STRING_RESULT; }
+ bool fix_length_and_dec() { maybe_null=1; max_length=0; return FALSE; }
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
void clear() {}
bool add() { return 0; }
diff --cc sql/item_timefunc.cc
index e01114fb0ad,bb75ad7c28c..b4d929e0f70
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@@ -1842,17 -1876,10 +1844,17 @@@ overflow
return 0;
}
- void Item_func_date_format::fix_length_and_dec()
+ bool Item_func_date_format::fix_length_and_dec()
{
THD* thd= current_thd;
- locale= thd->variables.lc_time_names;
+ if (!is_time_format)
+ {
+ if (arg_count < 3)
+ locale= thd->variables.lc_time_names;
+ else
+ if (args[2]->basic_const_item())
+ locale= args[2]->locale_from_val_str();
+ }
/*
Must use this_item() in case it's a local SP variable
@@@ -2039,8 -2059,8 +2042,9 @@@ bool Item_func_from_unixtime::fix_lengt
THD *thd= current_thd;
thd->time_zone_used= 1;
tz= thd->variables.time_zone;
- decimals= args[0]->decimals;
- return Item_temporal_func::fix_length_and_dec();
+ fix_attributes_datetime_not_fixed_dec(args[0]->decimals);
+ maybe_null= true;
++ return FALSE;
}
@@@ -2116,13 -2143,6 +2120,13 @@@ bool Item_date_add_interval::fix_length
{
enum_field_types arg0_field_type;
+ if (!args[0]->type_handler()->is_traditional_type())
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ args[0]->type_handler()->name().ptr(),
+ "interval", func_name());
- return;
++ return TRUE;
+ }
/*
The field type for the result of an Item_datefunc is defined as
follows:
@@@ -2169,26 -2186,15 +2173,27 @@@
}
else if (arg0_field_type == MYSQL_TYPE_TIME)
{
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME), interval_dec);
+ uint dec= MY_MAX(args[0]->time_precision(), interval_dec);
if (int_type >= INTERVAL_DAY && int_type != INTERVAL_YEAR_MONTH)
- set_handler_by_field_type(arg0_field_type);
+ {
+ set_handler(&type_handler_time2);
+ fix_attributes_time(dec);
+ }
else
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
+ {
+ set_handler(&type_handler_datetime2);
+ fix_attributes_datetime(dec);
+ }
}
else
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_DATETIME), interval_dec);
- return Item_temporal_func::fix_length_and_dec();
+ {
+ uint dec= MY_MAX(args[0]->datetime_precision(), interval_dec);
+ set_handler(&type_handler_string);
+ collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
+ fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
+ }
+ maybe_null= true;
++ return FALSE;
}
@@@ -2688,18 -2688,11 +2694,18 @@@ err
}
- void Item_func_add_time::fix_length_and_dec()
+ bool Item_func_add_time::fix_length_and_dec()
{
enum_field_types arg0_field_type;
- decimals= MY_MAX(args[0]->decimals, args[1]->decimals);
+ if (!args[0]->type_handler()->is_traditional_type() ||
+ !args[1]->type_handler()->is_traditional_type())
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ args[0]->type_handler()->name().ptr(),
+ args[1]->type_handler()->name().ptr(), func_name());
- return;
++ return TRUE;
+ }
/*
The field type for the result of an Item_func_add_time function is defined
as follows:
@@@ -2722,18 -2716,11 +2728,19 @@@
}
else if (arg0_field_type == MYSQL_TYPE_TIME)
{
- set_handler_by_field_type(MYSQL_TYPE_TIME);
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
- args[1]->temporal_precision(MYSQL_TYPE_TIME));
+ uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
+ set_handler(&type_handler_time2);
+ fix_attributes_time(dec);
}
- return Item_temporal_func::fix_length_and_dec();
+ else
+ {
+ uint dec= MY_MAX(args[0]->decimals, args[1]->decimals);
+ set_handler(&type_handler_string);
+ collation.set(default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_ASCII);
+ fix_char_length_temporal_not_fixed_dec(MAX_DATETIME_WIDTH, dec);
+ }
+ maybe_null= true;
++ return FALSE;
}
/**
@@@ -3220,25 -3209,21 +3227,25 @@@ get_date_time_result_type(const char *f
}
- void Item_func_str_to_date::fix_length_and_dec()
+ bool Item_func_str_to_date::fix_length_and_dec()
{
+ if (!args[0]->type_handler()->is_traditional_type() ||
+ !args[1]->type_handler()->is_traditional_type())
+ {
+ my_error(ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION, MYF(0),
+ args[0]->type_handler()->name().ptr(),
+ args[1]->type_handler()->name().ptr(), func_name());
- return;
++ return TRUE;
+ }
if (agg_arg_charsets(collation, args, 2, MY_COLL_ALLOW_CONV, 1))
- return;
+ return TRUE;
if (collation.collation->mbminlen > 1)
- {
-#if MYSQL_VERSION_ID > 50500
internal_charset= &my_charset_utf8mb4_general_ci;
-#else
- internal_charset= &my_charset_utf8_general_ci;
-#endif
- }
- set_handler_by_field_type(MYSQL_TYPE_DATETIME);
- decimals= TIME_SECOND_PART_DIGITS;
+ maybe_null= true;
+ set_handler(&type_handler_datetime2);
+ fix_attributes_datetime(TIME_SECOND_PART_DIGITS);
+
if ((const_item= args[1]->const_item()))
{
char format_buff[64];
@@@ -3274,7 -3254,8 +3281,8 @@@
}
}
}
- cached_timestamp_type= mysql_type_to_time_type(field_type());
- return Item_temporal_func::fix_length_and_dec();
+ cached_timestamp_type= mysql_timestamp_type();
++ return FALSE;
}
diff --cc sql/item_timefunc.h
index 30d5018ff36,c983e1a6f8a..51ce3bf2988
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@@ -31,75 -31,63 +31,78 @@@ enum date_time_format_type
};
-static inline uint
-mysql_temporal_int_part_length(enum enum_field_types mysql_type)
+bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
+
+
+class Item_long_func_date_field: public Item_long_func
{
- static uint max_time_type_width[5]=
- { MAX_DATETIME_WIDTH, MAX_DATETIME_WIDTH, MAX_DATE_WIDTH,
- MAX_DATETIME_WIDTH, MIN_TIME_WIDTH };
- return max_time_type_width[mysql_type_to_time_type(mysql_type)+2];
-}
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_date(func_name()); }
+public:
+ Item_long_func_date_field(THD *thd, Item *a)
+ :Item_long_func(thd, a) { }
+};
-bool get_interval_value(Item *args,interval_type int_type, INTERVAL *interval);
+class Item_long_func_time_field: public Item_long_func
+{
+ bool check_arguments() const
+ { return args[0]->check_type_can_return_time(func_name()); }
+public:
+ Item_long_func_time_field(THD *thd, Item *a)
+ :Item_long_func(thd, a) { }
+};
+
-class Item_func_period_add :public Item_int_func
+class Item_func_period_add :public Item_long_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_int(0, 2); }
public:
- Item_func_period_add(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_period_add(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "period_add"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_period_add>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_period_add>(thd, this); }
};
-class Item_func_period_diff :public Item_int_func
+class Item_func_period_diff :public Item_long_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_int(0, 2); }
public:
- Item_func_period_diff(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_period_diff(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "period_diff"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_period_diff>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_period_diff>(thd, this); }
};
-class Item_func_to_days :public Item_int_func
+class Item_func_to_days :public Item_long_func_date_field
{
public:
- Item_func_to_days(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_to_days(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "to_days"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
- maybe_null=1;
+ maybe_null=1;
+ return FALSE;
}
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
@@@ -114,19 -102,18 +117,20 @@@
};
-class Item_func_to_seconds :public Item_int_func
+class Item_func_to_seconds :public Item_longlong_func
{
+ bool check_arguments() const
+ { return check_argument_types_can_return_date(0, arg_count); }
public:
- Item_func_to_seconds(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_to_seconds(THD *thd, Item *a): Item_longlong_func(thd, a) {}
longlong val_int();
const char *func_name() const { return "to_seconds"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
- max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
+ fix_char_length(12);
maybe_null= 1;
+ return FALSE;
}
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
@@@ -142,17 -129,18 +146,18 @@@
};
-class Item_func_dayofmonth :public Item_int_func
+class Item_func_dayofmonth :public Item_long_func_date_field
{
public:
- Item_func_dayofmonth(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dayofmonth(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "dayofmonth"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
- maybe_null=1;
+ maybe_null=1;
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@@ -181,14 -169,11 +186,14 @@@ public
str->set(nr, collation.collation);
return str;
}
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ {
+ return get_date_from_int(ltime, fuzzydate);
+ }
const char *func_name() const { return "month"; }
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ const Type_handler *type_handler() const { return &type_handler_long; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals= 0;
fix_char_length(2);
maybe_null=1;
@@@ -226,14 -212,14 +232,14 @@@ public
};
-class Item_func_dayofyear :public Item_int_func
+class Item_func_dayofyear :public Item_long_func_date_field
{
public:
- Item_func_dayofyear(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_dayofyear(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "dayofyear"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals= 0;
fix_char_length(3);
maybe_null=1;
@@@ -249,13 -236,13 +256,13 @@@
};
-class Item_func_hour :public Item_int_func
+class Item_func_hour :public Item_long_func_time_field
{
public:
- Item_func_hour(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_hour(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "hour"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
@@@ -272,13 -260,13 +280,13 @@@
};
-class Item_func_minute :public Item_int_func
+class Item_func_minute :public Item_long_func_time_field
{
public:
- Item_func_minute(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_minute(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "minute"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
@@@ -295,14 -284,14 +304,14 @@@
};
-class Item_func_quarter :public Item_int_func
+class Item_func_quarter :public Item_long_func_date_field
{
public:
- Item_func_quarter(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_quarter(THD *thd, Item *a): Item_long_func_date_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "quarter"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=1*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
@@@ -318,14 -308,14 +328,14 @@@
};
-class Item_func_second :public Item_int_func
+class Item_func_second :public Item_long_func_time_field
{
public:
- Item_func_second(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_second(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "second"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
@@@ -341,20 -332,15 +352,20 @@@
};
-class Item_func_week :public Item_int_func
+class Item_func_week :public Item_long_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ (arg_count > 1 && args[1]->check_type_can_return_int(func_name()));
+ }
public:
- Item_func_week(THD *thd, Item *a): Item_int_func(thd, a) {}
- Item_func_week(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_week(THD *thd, Item *a): Item_long_func(thd, a) {}
+ Item_func_week(THD *thd, Item *a, Item *b): Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "week"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=2*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
@@@ -369,24 -356,18 +381,24 @@@
{
return arg_count == 2;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_week>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_week>(thd, this); }
};
-class Item_func_yearweek :public Item_int_func
+class Item_func_yearweek :public Item_long_func
{
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ args[1]->check_type_can_return_int(func_name());
+ }
public:
- Item_func_yearweek(THD *thd, Item *a, Item *b): Item_int_func(thd, a, b) {}
+ Item_func_yearweek(THD *thd, Item *a, Item *b)
+ :Item_long_func(thd, a, b) {}
longlong val_int();
const char *func_name() const { return "yearweek"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
@@@ -445,12 -428,9 +459,12 @@@ public
{
return (odbc_type ? "dayofweek" : "weekday");
}
- enum Item_result result_type () const { return INT_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
+ bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
+ {
+ return type_handler()->Item_get_date(this, ltime, fuzzydate);
+ }
+ const Type_handler *type_handler() const { return &type_handler_long; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals= 0;
fix_char_length(1);
@@@ -473,8 -454,9 +488,8 @@@ class Item_func_dayname :public Item_fu
Item_func_dayname(THD *thd, Item *a): Item_func_weekday(thd, a, 0) {}
const char *func_name() const { return "dayname"; }
String *val_str(String *str);
- enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
+ const Type_handler *type_handler() const { return &type_handler_varchar; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool check_partition_func_processor(void *int_arg) {return TRUE;}
bool check_vcol_func_processor(void *arg)
{
@@@ -535,14 -516,10 +550,15 @@@ public
return FALSE;
return mark_unsupported_function(func_name(), "()", arg, VCOL_TIME_FUNC);
}
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- fix_length_and_dec_generic(arg_count ? args[0]->datetime_precision() : 0);
++ fix_length_and_dec_generic(arg_count ? args[0]->datetime_precision() : 0);
++ return FALSE;
+ }
longlong int_op();
my_decimal *decimal_op(my_decimal* buf);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_unix_timestamp>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_unix_timestamp>(thd, this); }
};
@@@ -558,14 -537,10 +574,15 @@@ public
{
return !has_time_args();
}
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ fix_length_and_dec_generic(args[0]->time_precision());
++ return FALSE;
+ }
longlong int_op();
my_decimal *decimal_op(my_decimal* buf);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_time_to_sec>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_time_to_sec>(thd, this); }
};
@@@ -627,13 -630,7 +644,14 @@@ class Item_datefunc :public Item_tempor
public:
Item_datefunc(THD *thd): Item_temporal_func(thd) { }
Item_datefunc(THD *thd, Item *a): Item_temporal_func(thd, a) { }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
+ Item_datefunc(THD *thd, Item *a, Item *b): Item_temporal_func(thd, a, b) { }
+ const Type_handler *type_handler() const { return &type_handler_newdate; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ fix_attributes_date();
+ maybe_null= (arg_count > 0);
++ return FALSE;
+ }
};
@@@ -670,7 -667,6 +688,7 @@@ public
Item_func_curtime(THD *thd, uint dec): Item_timefunc(thd), last_query_id(0)
{ decimals= dec; }
bool fix_fields(THD *, Item **);
- void fix_length_and_dec() { fix_attributes_time(decimals); }
++ bool fix_length_and_dec() { fix_attributes_time(decimals); return FALSE; }
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
/*
Abstract method that defines which time zone is used for conversion.
@@@ -757,7 -753,6 +775,8 @@@ public
Item_func_now(THD *thd, uint dec): Item_datetimefunc(thd), last_query_id(0)
{ decimals= dec; }
bool fix_fields(THD *, Item **);
- void fix_length_and_dec() { fix_attributes_datetime(decimals); }
++ bool fix_length_and_dec()
++ { fix_attributes_datetime(decimals); return FALSE;}
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
virtual void store_now_in_TIME(THD *thd, MYSQL_TIME *now_time)=0;
bool check_vcol_func_processor(void *arg)
@@@ -847,24 -840,17 +866,24 @@@ public
class Item_func_date_format :public Item_str_func
{
- MY_LOCALE *locale;
+ bool check_arguments() const
+ {
+ return args[0]->check_type_can_return_date(func_name()) ||
+ check_argument_types_can_return_text(1, arg_count);
+ }
+ const MY_LOCALE *locale;
int fixed_length;
- const bool is_time_format;
String value;
+protected:
+ bool is_time_format;
public:
- Item_func_date_format(THD *thd, Item *a, Item *b, bool is_time_format_arg):
- Item_str_func(thd, a, b), is_time_format(is_time_format_arg) {}
+ Item_func_date_format(THD *thd, Item *a, Item *b):
+ Item_str_func(thd, a, b), locale(0), is_time_format(false) {}
+ Item_func_date_format(THD *thd, Item *a, Item *b, Item *c):
+ Item_str_func(thd, a, b, c), locale(0), is_time_format(false) {}
String *val_str(String *str);
- const char *func_name() const
- { return is_time_format ? "time_format" : "date_format"; }
+ const char *func_name() const { return "date_format"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
uint format_length(const String *format);
bool eq(const Item *item, bool binary_cmp) const;
bool check_vcol_func_processor(void *arg)
@@@ -897,10 -870,10 +916,10 @@@ class Item_func_from_unixtime :public I
public:
Item_func_from_unixtime(THD *thd, Item *a): Item_datetimefunc(thd, a) {}
const char *func_name() const { return "from_unixtime"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_from_unixtime>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_from_unixtime>(thd, this); }
};
@@@ -937,15 -905,11 +956,16 @@@ class Item_func_convert_tz :public Item
Item_func_convert_tz(THD *thd, Item *a, Item *b, Item *c):
Item_datetimefunc(thd, a, b, c), from_tz_cached(0), to_tz_cached(0) {}
const char *func_name() const { return "convert_tz"; }
- void fix_length_and_dec()
- bool fix_length_and_dec();
++ bool fix_length_and_dec()
+ {
+ fix_attributes_datetime(args[0]->datetime_precision());
+ maybe_null= true;
++ return FALSE;
+ }
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
void cleanup();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_convert_tz>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_convert_tz>(thd, this); }
};
@@@ -956,14 -918,14 +976,15 @@@ class Item_func_sec_to_time :public Ite
public:
Item_func_sec_to_time(THD *thd, Item *item): Item_timefunc(thd, item) {}
bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- decimals= MY_MIN(args[0]->decimals, TIME_SECOND_PART_DIGITS);
- return Item_timefunc::fix_length_and_dec();
+ fix_attributes_time(args[0]->decimals);
+ maybe_null= true;
++ return FALSE;
}
const char *func_name() const { return "sec_to_time"; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_sec_to_time>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_sec_to_time>(thd, this); }
};
@@@ -1116,23 -1078,12 +1137,23 @@@ public
enum Functype functype() const { return CHAR_TYPECAST_FUNC; }
bool eq(const Item *item, bool binary_cmp) const;
const char *func_name() const { return "cast_as_char"; }
+ CHARSET_INFO *cast_charset() const { return cast_cs; }
String *val_str(String *a);
- bool fix_length_and_dec();
+ void fix_length_and_dec_generic();
+ void fix_length_and_dec_numeric();
+ void fix_length_and_dec_str()
+ {
+ fix_length_and_dec_generic();
+ m_suppress_warning_to_error_escalation= true;
+ }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this);
++ return args[0]->type_handler()->Item_char_typecast_fix_length_and_dec(this);
+ }
void print(String *str, enum_query_type query_type);
bool need_parentheses_in_default() { return true; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_char_typecast>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_char_typecast>(thd, this); }
};
@@@ -1151,13 -1108,9 +1172,13 @@@ public
const char *func_name() const { return "cast_as_date"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *cast_type() const { return "date"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_date_typecast>(thd, mem_root, this); }
+ const Type_handler *type_handler() const { return &type_handler_newdate; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this);
++ return args[0]->type_handler()->Item_date_typecast_fix_length_and_dec(this);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_date_typecast>(thd, this); }
};
@@@ -1169,13 -1122,9 +1190,14 @@@ public
const char *func_name() const { return "cast_as_time"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *cast_type() const { return "time"; }
- enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_time_typecast>(thd, mem_root, this); }
+ const Type_handler *type_handler() const { return &type_handler_time2; }
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_time_typecast_fix_length_and_dec(this);
++ return args[0]->type_handler()->
++ Item_time_typecast_fix_length_and_dec(this);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_time_typecast>(thd, this); }
};
@@@ -1186,14 -1135,10 +1208,15 @@@ public
Item_temporal_typecast(thd, a) { decimals= dec_arg; }
const char *func_name() const { return "cast_as_datetime"; }
const char *cast_type() const { return "datetime"; }
- enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
+ const Type_handler *type_handler() const { return &type_handler_datetime2; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
- void fix_length_and_dec()
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_datetime_typecast>(thd, mem_root, this); }
++ bool fix_length_and_dec()
+ {
- args[0]->type_handler()->Item_datetime_typecast_fix_length_and_dec(this);
++ return args[0]->type_handler()->
++ Item_datetime_typecast_fix_length_and_dec(this);
+ }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_datetime_typecast>(thd, this); }
};
@@@ -1235,15 -1177,15 +1258,16 @@@ class Item_func_timediff :public Item_t
public:
Item_func_timediff(THD *thd, Item *a, Item *b): Item_timefunc(thd, a, b) {}
const char *func_name() const { return "timediff"; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- decimals= MY_MAX(args[0]->temporal_precision(MYSQL_TYPE_TIME),
- args[1]->temporal_precision(MYSQL_TYPE_TIME));
- return Item_timefunc::fix_length_and_dec();
+ uint dec= MY_MAX(args[0]->time_precision(), args[1]->time_precision());
+ fix_attributes_time(dec);
+ maybe_null= true;
++ return FALSE;
}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_timediff>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_timediff>(thd, this); }
};
class Item_func_maketime :public Item_timefunc
@@@ -1257,10 -1194,10 +1281,11 @@@ public
Item_func_maketime(THD *thd, Item *a, Item *b, Item *c):
Item_timefunc(thd, a, b, c)
{}
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
- decimals= MY_MIN(args[2]->decimals, TIME_SECOND_PART_DIGITS);
- return Item_timefunc::fix_length_and_dec();
+ fix_attributes_time(args[2]->decimals);
+ maybe_null= true;
++ return FALSE;
}
const char *func_name() const { return "maketime"; }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
@@@ -1269,17 -1206,17 +1294,18 @@@
};
-class Item_func_microsecond :public Item_int_func
+class Item_func_microsecond :public Item_long_func_time_field
{
public:
- Item_func_microsecond(THD *thd, Item *a): Item_int_func(thd, a) {}
+ Item_func_microsecond(THD *thd, Item *a): Item_long_func_time_field(thd, a) {}
longlong val_int();
const char *func_name() const { return "microsecond"; }
- void fix_length_and_dec()
- {
+ bool fix_length_and_dec()
+ {
decimals=0;
maybe_null=1;
+ fix_char_length(6);
+ return FALSE;
}
bool check_partition_func_processor(void *int_arg) {return FALSE;}
bool check_vcol_func_processor(void *arg) { return FALSE;}
@@@ -1299,17 -1234,18 +1325,18 @@@ class Item_func_timestamp_diff :public
const interval_type int_type;
public:
Item_func_timestamp_diff(THD *thd, Item *a, Item *b, interval_type type_arg):
- Item_int_func(thd, a, b), int_type(type_arg) {}
+ Item_longlong_func(thd, a, b), int_type(type_arg) {}
const char *func_name() const { return "timestampdiff"; }
longlong val_int();
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals=0;
maybe_null=1;
+ return FALSE;
}
virtual void print(String *str, enum_query_type query_type);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_timestamp_diff>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_timestamp_diff>(thd, this); }
};
@@@ -1332,10 -1268,11 +1359,11 @@@ public
maybe_null= 1;
decimals=0;
fix_length_and_charset(17, default_charset());
+ return FALSE;
}
virtual void print(String *str, enum_query_type query_type);
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_get_format>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_get_format>(thd, this); }
};
@@@ -1353,9 -1290,9 +1381,9 @@@ public
{}
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date);
const char *func_name() const { return "str_to_date"; }
- void fix_length_and_dec();
+ bool fix_length_and_dec();
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_func_str_to_date>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_str_to_date>(thd, this); }
};
diff --cc sql/item_vers.h
index 17ad3daa73c,00000000000..8b9c0e6056c
mode 100644,000000..100644
--- a/sql/item_vers.h
+++ b/sql/item_vers.h
@@@ -1,114 -1,0 +1,116 @@@
+#ifndef ITEM_VERS_INCLUDED
+#define ITEM_VERS_INCLUDED
+/* Copyright (c) 2017, 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
+
+
+/* System Versioning items */
+
+#ifdef USE_PRAGMA_INTERFACE
+#pragma interface /* gcc class implementation */
+#endif
+
+class Item_func_trt_ts: public Item_datetimefunc
+{
+ TR_table::field_id_t trt_field;
+public:
+ Item_func_trt_ts(THD *thd, Item* a, TR_table::field_id_t _trt_field);
+ const char *func_name() const
+ {
+ if (trt_field == TR_table::FLD_BEGIN_TS)
+ {
+ return "trt_begin_ts";
+ }
+ return "trt_commit_ts";
+ }
+ bool get_date(MYSQL_TIME *res, ulonglong fuzzy_date);
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_trt_ts>(thd, this); }
- void fix_length_and_dec() { fix_attributes_datetime(decimals); }
++ bool fix_length_and_dec()
++ { fix_attributes_datetime(decimals); return FALSE; }
+};
+
+class Item_func_trt_id : public Item_longlong_func
+{
+ TR_table::field_id_t trt_field;
+ bool backwards;
+
+ longlong get_by_trx_id(ulonglong trx_id);
+ longlong get_by_commit_ts(MYSQL_TIME &commit_ts, bool backwards);
+
+public:
+ Item_func_trt_id(THD *thd, Item* a, TR_table::field_id_t _trt_field, bool _backwards= false);
+ Item_func_trt_id(THD *thd, Item* a, Item* b, TR_table::field_id_t _trt_field);
+
+ const char *func_name() const
+ {
+ switch (trt_field)
+ {
+ case TR_table::FLD_TRX_ID:
+ return "trt_trx_id";
+ case TR_table::FLD_COMMIT_ID:
+ return "trt_commit_id";
+ case TR_table::FLD_ISO_LEVEL:
+ return "trt_iso_level";
+ default:
+ DBUG_ASSERT(0);
+ }
+ return NULL;
+ }
+
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
- Item_int_func::fix_length_and_dec();
++ bool res= Item_int_func::fix_length_and_dec();
+ max_length= 20;
++ return res;
+ }
+
+ longlong val_int();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_trt_id>(thd, this); }
+};
+
+class Item_func_trt_trx_sees : public Item_bool_func
+{
+protected:
+ bool accept_eq;
+
+public:
+ Item_func_trt_trx_sees(THD *thd, Item* a, Item* b);
+ const char *func_name() const
+ {
+ return "trt_trx_sees";
+ }
+ longlong val_int();
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_func_trt_trx_sees>(thd, this); }
+};
+
+class Item_func_trt_trx_sees_eq :
+ public Item_func_trt_trx_sees
+{
+public:
+ Item_func_trt_trx_sees_eq(THD *thd, Item* a, Item* b) :
+ Item_func_trt_trx_sees(thd, a, b)
+ {
+ accept_eq= true;
+ }
+ const char *func_name() const
+ {
+ return "trt_trx_sees_eq";
+ }
+};
+
+#endif /* ITEM_VERS_INCLUDED */
diff --cc sql/item_windowfunc.h
index cb85a2c06d1,e5afb9e1555..48851da7d96
--- a/sql/item_windowfunc.h
+++ b/sql/item_windowfunc.h
@@@ -524,9 -513,10 +524,9 @@@ class Item_sum_percent_rank: public Ite
row_number= 0;
}
bool add();
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals = 10; // TODO-cvicentiu find out how many decimals the standard
// requires.
@@@ -612,21 -600,18 +613,22 @@@ class Item_sum_cume_dist: public Item_s
}
void update_field() {}
- enum Item_result result_type () const { return REAL_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ const Type_handler *type_handler() const { return &type_handler_double; }
- void fix_length_and_dec()
+ bool fix_length_and_dec()
{
decimals = 10; // TODO-cvicentiu find out how many decimals the standard
// requires.
+ return FALSE;
}
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_sum_cume_dist>(thd, mem_root, this); }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_sum_cume_dist>(thd, this); }
+
+ ulonglong get_row_number()
+ {
+ return current_row_count_ ;
+ }
private:
ulonglong current_row_count_;
@@@ -703,277 -689,6 +705,279 @@@ class Item_sum_ntile : public Item_sum_
ulong current_row_count_;
};
+class Item_sum_percentile_disc : public Item_sum_cume_dist,
+ public Type_handler_hybrid_field_type
+{
+public:
+ Item_sum_percentile_disc(THD *thd, Item* arg) : Item_sum_cume_dist(thd, arg),
+ Type_handler_hybrid_field_type(&type_handler_longlong),
+ value(NULL), val_calculated(FALSE), first_call(TRUE),
+ prev_value(0), order_item(NULL){}
+
+ double val_real()
+ {
+ if (get_row_count() == 0 || get_arg(0)->is_null())
+ {
+ null_value= true;
+ return 0;
+ }
+ null_value= false;
+ return value->val_real();
+ }
+
+ longlong val_int()
+ {
+ if (get_row_count() == 0 || get_arg(0)->is_null())
+ {
+ null_value= true;
+ return 0;
+ }
+ null_value= false;
+ return value->val_int();
+ }
+
+ my_decimal* val_decimal(my_decimal* dec)
+ {
+ if (get_row_count() == 0 || get_arg(0)->is_null())
+ {
+ null_value= true;
+ return 0;
+ }
+ null_value= false;
+ return value->val_decimal(dec);
+ }
+
+ String* val_str(String *str)
+ {
+ if (get_row_count() == 0 || get_arg(0)->is_null())
+ {
+ null_value= true;
+ return 0;
+ }
+ null_value= false;
+ return value->val_str(str);
+ }
+
+ bool add()
+ {
+ Item *arg= get_arg(0);
+ if (arg->is_null())
+ return false;
+
+ if (first_call)
+ {
+ prev_value= arg->val_real();
+ if (prev_value > 1 || prev_value < 0)
+ {
+ my_error(ER_ARGUMENT_OUT_OF_RANGE, MYF(0), func_name());
+ return true;
+ }
+ first_call= false;
+ }
+
+ double arg_val= arg->val_real();
+
+ if (prev_value != arg_val)
+ {
+ my_error(ER_ARGUMENT_NOT_CONSTANT, MYF(0), func_name());
+ return true;
+ }
+
+ if (val_calculated)
+ return false;
+
+ value->store(order_item);
+ value->cache_value();
+ if (value->null_value)
+ return false;
+
+ Item_sum_cume_dist::add();
+ double val= Item_sum_cume_dist::val_real();
+
+ if (val >= prev_value && !val_calculated)
+ val_calculated= true;
+ return false;
+ }
+
+ enum Sumfunctype sum_func() const
+ {
+ return PERCENTILE_DISC_FUNC;
+ }
+
+ void clear()
+ {
+ val_calculated= false;
+ first_call= true;
+ value->clear();
+ Item_sum_cume_dist::clear();
+ }
+
+ const char*func_name() const
+ {
+ return "percentile_disc";
+ }
+
+ void update_field() {}
+ void set_type_handler(Window_spec *window_spec);
+ const Type_handler *type_handler() const
+ {return Type_handler_hybrid_field_type::type_handler();}
+
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ decimals = 10; // TODO-cvicentiu find out how many decimals the standard
+ // requires.
++ return FALSE;
+ }
+
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_sum_percentile_disc>(thd, this); }
+ void setup_window_func(THD *thd, Window_spec *window_spec);
+ void setup_hybrid(THD *thd, Item *item);
+ bool fix_fields(THD *thd, Item **ref);
+
+private:
+ Item_cache *value;
+ bool val_calculated;
+ bool first_call;
+ double prev_value;
+ Item *order_item;
+};
+
+class Item_sum_percentile_cont : public Item_sum_cume_dist,
+ public Type_handler_hybrid_field_type
+{
+public:
+ Item_sum_percentile_cont(THD *thd, Item* arg) : Item_sum_cume_dist(thd, arg),
+ Type_handler_hybrid_field_type(&type_handler_double),
+ floor_value(NULL), ceil_value(NULL), first_call(TRUE),prev_value(0),
+ ceil_val_calculated(FALSE), floor_val_calculated(FALSE), order_item(NULL){}
+
+ double val_real()
+ {
+ if (get_row_count() == 0 || get_arg(0)->is_null())
+ {
+ null_value= true;
+ return 0;
+ }
+ null_value= false;
+ double val= 1 + prev_value * (get_row_count()-1);
+
+ /*
+ Applying the formula to get the value
+ If (CRN = FRN = RN) then the result is (value of expression from row at RN)
+ Otherwise the result is
+ (CRN - RN) * (value of expression for row at FRN) +
+ (RN - FRN) * (value of expression for row at CRN)
+ */
+
+ if(ceil(val) == floor(val))
+ return floor_value->val_real();
+
+ double ret_val= ((val - floor(val)) * ceil_value->val_real()) +
+ ((ceil(val) - val) * floor_value->val_real());
+
+ return ret_val;
+ }
+
+ bool add()
+ {
+ Item *arg= get_arg(0);
+ if (arg->is_null())
+ return false;
+
+ if (first_call)
+ {
+ first_call= false;
+ prev_value= arg->val_real();
+ if (prev_value > 1 || prev_value < 0)
+ {
+ my_error(ER_ARGUMENT_OUT_OF_RANGE, MYF(0), func_name());
+ return true;
+ }
+ }
+
+ double arg_val= arg->val_real();
+ if (prev_value != arg_val)
+ {
+ my_error(ER_ARGUMENT_NOT_CONSTANT, MYF(0), func_name());
+ return true;
+ }
+
+ if (!floor_val_calculated)
+ {
+ floor_value->store(order_item);
+ floor_value->cache_value();
+ if (floor_value->null_value)
+ return false;
+ }
+ if (floor_val_calculated && !ceil_val_calculated)
+ {
+ ceil_value->store(order_item);
+ ceil_value->cache_value();
+ if (ceil_value->null_value)
+ return false;
+ }
+
+ Item_sum_cume_dist::add();
+ double val= 1 + prev_value * (get_row_count()-1);
+
+ if (!floor_val_calculated && get_row_number() == floor(val))
+ floor_val_calculated= true;
+
+ if (!ceil_val_calculated && get_row_number() == ceil(val))
+ ceil_val_calculated= true;
+ return false;
+ }
+
+ enum Sumfunctype sum_func() const
+ {
+ return PERCENTILE_CONT_FUNC;
+ }
+
+ void clear()
+ {
+ first_call= true;
+ floor_value->clear();
+ ceil_value->clear();
+ floor_val_calculated= false;
+ ceil_val_calculated= false;
+ Item_sum_cume_dist::clear();
+ }
+
+ const char*func_name() const
+ {
+ return "percentile_cont";
+ }
+ void update_field() {}
+ void set_type_handler(Window_spec *window_spec);
+ const Type_handler *type_handler() const
+ {return Type_handler_hybrid_field_type::type_handler();}
+
- void fix_length_and_dec()
++ bool fix_length_and_dec()
+ {
+ decimals = 10; // TODO-cvicentiu find out how many decimals the standard
+ // requires.
++ return FALSE;
+ }
+
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_sum_percentile_cont>(thd, this); }
+ void setup_window_func(THD *thd, Window_spec *window_spec);
+ void setup_hybrid(THD *thd, Item *item);
+ bool fix_fields(THD *thd, Item **ref);
+
+private:
+ Item_cache *floor_value;
+ Item_cache *ceil_value;
+ bool first_call;
+ double prev_value;
+ bool ceil_val_calculated;
+ bool floor_val_calculated;
+ Item *order_item;
+};
+
+
+
class Item_window_func : public Item_func_or_sum
{
diff --cc sql/item_xmlfunc.cc
index 63cc07fa34c,738047fea9b..63734ecf9ac
--- a/sql/item_xmlfunc.cc
+++ b/sql/item_xmlfunc.cc
@@@ -456,9 -457,9 +457,9 @@@ public
Item_nodeset_func(thd, pxml), string_cache(str_arg) { }
String *val_nodeset(String *res)
{ return string_cache; }
- void fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; }
- bool fix_length_and_dec() { max_length= MAX_BLOB_WIDTH; return FALSE; }
- Item *get_copy(THD *thd, MEM_ROOT *mem_root)
- { return get_item_copy<Item_nodeset_context_cache>(thd, mem_root, this); }
++ bool fix_length_and_dec() { max_length= MAX_BLOB_WIDTH;; return FALSE; }
+ Item *get_copy(THD *thd)
+ { return get_item_copy<Item_nodeset_context_cache>(thd, this); }
};
@@@ -468,9 -469,9 +469,9 @@@ class Item_func_xpath_position :public
String tmp_value;
public:
Item_func_xpath_position(THD *thd, Item *a, String *p):
- Item_int_func(thd, a), pxml(p) {}
+ Item_long_func(thd, a), pxml(p) {}
const char *func_name() const { return "xpath_position"; }
- void fix_length_and_dec() { max_length=10; }
+ bool fix_length_and_dec() { max_length=10; return FALSE; }
longlong val_int()
{
String *flt= args[0]->val_nodeset(&tmp_value);
@@@ -489,9 -490,9 +490,9 @@@ class Item_func_xpath_count :public Ite
String tmp_value;
public:
Item_func_xpath_count(THD *thd, Item *a, String *p):
- Item_int_func(thd, a), pxml(p) {}
+ Item_long_func(thd, a), pxml(p) {}
const char *func_name() const { return "xpath_count"; }
- void fix_length_and_dec() { max_length=10; }
+ bool fix_length_and_dec() { max_length=10; return FALSE; }
longlong val_int()
{
uint predicate_supplied_context_size;
diff --cc sql/sql_table.cc
index 6835d92773c,9a87b0e7461..2b0c4439146
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@@ -4961,9 -4896,14 +4961,14 @@@ int create_table_impl(THD *thd
file= mysql_create_frm_image(thd, orig_db, orig_table_name, create_info,
alter_info, create_table_mode, key_info,
key_count, frm);
- if (!file)
+ /*
+ TODO: remove this check of thd->is_error() (now it intercept
+ errors in some val_*() methoids and bring some single place to
+ such error interception).
+ */
+ if (!file || thd->is_error())
goto err;
- if (rea_create_table(thd, frm, path, db, table_name, create_info,
+ if (rea_create_table(thd, frm, path, db->str, table_name->str, create_info,
file, frm_only))
goto err;
}
@@@ -7621,10 -7401,17 +7626,15 @@@ static bool mysql_inplace_alter_table(T
/*
Replace the old .FRM with the new .FRM, but keep the old name for now.
Rename to the new name (if needed) will be handled separately below.
+
+ TODO: remove this check of thd->is_error() (now it intercept
+ errors in some val_*() methoids and bring some single place to
+ such error interception).
*/
- if (mysql_rename_table(db_type, alter_ctx->new_db, alter_ctx->tmp_name,
- alter_ctx->db, alter_ctx->alias,
+ if (mysql_rename_table(db_type, &alter_ctx->new_db, &alter_ctx->tmp_name,
+ &alter_ctx->db, &alter_ctx->alias,
- FN_FROM_IS_TMP | NO_HA_TABLE))
+ FN_FROM_IS_TMP | NO_HA_TABLE) ||
+ thd->is_error())
{
// Since changes were done in-place, we can't revert them.
(void) quick_rm_table(thd, db_type,
1
0
[Commits] 5ba6cee: MDEV-16209 JSON_EXTRACT in query crashes server.
by holyfootīŧ askmonty.org 18 Jun '18
by holyfootīŧ askmonty.org 18 Jun '18
18 Jun '18
revision-id: 5ba6cee01255186ea77a69f122d3a15c07f44f6d (mariadb-10.2.15-63-g5ba6cee)
parent(s): eb77f8cf8de44ecaa7155afa7f55ece73b2b0497
committer: Alexey Botchkov
timestamp: 2018-06-18 23:00:34 +0400
message:
MDEV-16209 JSON_EXTRACT in query crashes server.
The optimizer can create various item's over the original one,
so we can't count on the exact item's type inside the comparison.
---
mysql-test/r/func_json.result | 5 ++++
mysql-test/t/func_json.test | 8 ++++++
sql/item_jsonfunc.cc | 62 +++++++++++++++++++++++++------------------
3 files changed, 49 insertions(+), 26 deletions(-)
diff --git a/mysql-test/r/func_json.result b/mysql-test/r/func_json.result
index 77a4241..564442a 100644
--- a/mysql-test/r/func_json.result
+++ b/mysql-test/r/func_json.result
@@ -742,3 +742,8 @@ json_extract('{"test":8.437e-5}','$.test')
select json_value('{"b":true}','$.b')=1;
json_value('{"b":true}','$.b')=1
1
+CREATE TABLE t1 (c VARCHAR(8));
+INSERT INTO t1 VALUES ('foo'),('bar');
+SELECT * FROM t1 WHERE c IN (JSON_EXTRACT('{"a":"b"}', '$.*'));
+c
+DROP TABLE t1;
diff --git a/mysql-test/t/func_json.test b/mysql-test/t/func_json.test
index b74915c..1b91061 100644
--- a/mysql-test/t/func_json.test
+++ b/mysql-test/t/func_json.test
@@ -404,4 +404,12 @@ select json_extract('{"test":8.437e-5}','$.test');
#
select json_value('{"b":true}','$.b')=1;
+#
+# MDEV-16209 JSON_EXTRACT in query crashes server.
+#
+
+CREATE TABLE t1 (c VARCHAR(8));
+INSERT INTO t1 VALUES ('foo'),('bar');
+SELECT * FROM t1 WHERE c IN (JSON_EXTRACT('{"a":"b"}', '$.*'));
+DROP TABLE t1;
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index c8cda66..8103aa9 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -3229,34 +3229,44 @@ String *Item_func_json_format::val_json(String *str)
int Arg_comparator::compare_json_str_basic(Item *j, Item *s)
{
- String *res1,*res2;
- json_value_types type;
- char *value;
- int value_len, c_len;
- Item_func_json_extract *e= (Item_func_json_extract *) j;
-
- if ((res1= e->read_json(&value1, &type, &value, &value_len)))
- {
- if ((res2= s->val_str(&value2)))
- {
- if (type == JSON_VALUE_STRING)
- {
- if (value1.realloc_with_extra_if_needed(value_len) ||
- (c_len= json_unescape(value1.charset(), (uchar *) value,
- (uchar *) value+value_len,
- &my_charset_utf8_general_ci,
- (uchar *) value1.ptr(),
- (uchar *) (value1.ptr() + value_len))) < 0)
- goto error;
- value1.length(c_len);
- res1= &value1;
- }
+ String *js,*str;
+ int c_len;
+ json_engine_t je;
- if (set_null)
- owner->null_value= 0;
- return sortcmp(res1, res2, compare_collation());
- }
+ if ((js= j->val_str(&value1)))
+ {
+ json_scan_start(&je, js->charset(), (const uchar *) js->ptr(),
+ (const uchar *) js->ptr()+js->length());
+ if (json_read_value(&je))
+ goto error;
+ if (je.value_type == JSON_VALUE_STRING)
+ {
+ if (value2.realloc_with_extra_if_needed(je.value_len) ||
+ (c_len= json_unescape(js->charset(), je.value,
+ je.value + je.value_len,
+ &my_charset_utf8_general_ci,
+ (uchar *) value2.ptr(),
+ (uchar *) (value2.ptr() + je.value_len))) < 0)
+ goto error;
+
+ value2.length(c_len);
+ js= &value2;
+ str= &value1;
+ }
+ else
+ {
+ str= &value2;
+ }
+
+
+ if ((str= s->val_str(str)))
+ {
+ if (set_null)
+ owner->null_value= 0;
+ return sortcmp(js, str, compare_collation());
+ }
}
+
error:
if (set_null)
owner->null_value= 1;
1
0
18 Jun '18
revision-id: 636b4e0dfc1f57a055532f0717e43849e751588f (mariadb-10.3.6-13-g636b4e0dfc1)
parent(s): ffe83e8e7bef32eb2a80aad2d382f0b023dd3a44
author: Galina Shalygina
committer: Galina Shalygina
timestamp: 2018-06-18 20:15:39 +0200
message:
MDEV-7486: Condition pushdown from HAVING into WHERE
Condition can be pushed from the HAVING clause into the WHERE clause
if it depends only on the fields that are used in the GROUP BY 'grouping_fields'
or depends on the fields that are equal to 'grouping_fields'.
Aggregate functions can't be pushed down.
How the pushdown is made on the example:
SELECT t1.a,MAX(t1.b)
FROM t1
GROUP BY t1.a
HAVING (t1.a>2) AND (MAX(c)>12);
=>
SELECT t1.a,MAX(t1.b)
FROM t1
WHERE (t1.a>2)
GROUP BY t1.a
HAVING (MAX(c)>12);
The implementation scheme:
1. Search for the condition cond in the HAVING clause of the select that
depends only on the fields that are used in the GROUP BY of the select
2. Save it as a condition that can be pushed into the WHERE clause
of the select
3. Remove cond from the HAVING clause
The optimization is made in the
st_select_lex::pushdown_from_having_into_where() and is controlled by the
variable 'condition_pushdown_from_having_into_where'.
New test file having_cond_pushdown.test is created.
optimize_cond() for the HAVING clause was moved so now it is called before
optimize_cond() call for the WHERE clause in JOIN::optimize_inner().
check_simple_equality() was also changed in the way that after the work of
optimize_cond() for the HAVING clause all equalities there are transformed into
the multiple equalities.
---
mysql-test/main/derived_cond_pushdown.result | 12 +-
mysql-test/main/func_debug.result | 10 +
mysql-test/main/group_min_max.result | 16 +-
mysql-test/main/having.result | 10 +-
mysql-test/main/having_cond_pushdown.result | 1631 ++++++++++++++++++++
mysql-test/main/having_cond_pushdown.test | 402 +++++
mysql-test/main/key.result | 2 +-
mysql-test/main/mysqld--help.result | 5 +-
mysql-test/main/select.result | 2 +
mysql-test/main/select_jcl6.result | 2 +
mysql-test/main/select_pkeycache.result | 2 +
mysql-test/main/subselect.result | 4 +-
mysql-test/main/subselect_innodb.result | 2 +-
mysql-test/main/subselect_mat.result | 2 +-
mysql-test/main/subselect_no_exists_to_in.result | 4 +-
mysql-test/main/subselect_no_mat.result | 4 +-
mysql-test/main/subselect_no_opts.result | 4 +-
mysql-test/main/subselect_no_scache.result | 4 +-
mysql-test/main/subselect_no_semijoin.result | 4 +-
mysql-test/main/subselect_sj_jcl6.result | 4 +-
mysql-test/main/subselect_sj_mat.result | 2 +-
mysql-test/main/tmp_table_count-7586.result | 2 +-
mysql-test/main/union.result | 4 +-
mysql-test/suite/gcol/r/gcol_select_innodb.result | 1 +
.../suite/sys_vars/r/optimizer_switch_basic.result | 36 +-
.../sys_vars/r/sysvars_server_notembedded.result | 8 +-
sql/item.cc | 79 +-
sql/item.h | 17 +-
sql/item_cmpfunc.cc | 2 +
sql/item_cmpfunc.h | 11 +-
sql/item_func.cc | 16 +
sql/item_func.h | 10 +
sql/opt_subselect.cc | 81 +-
sql/sql_class.cc | 1 +
sql/sql_class.h | 2 +
sql/sql_derived.cc | 8 +-
sql/sql_lex.cc | 368 ++++-
sql/sql_lex.h | 8 +-
sql/sql_priv.h | 4 +-
sql/sql_select.cc | 91 +-
sql/sys_vars.cc | 1 +
.../mysql-test/tokudb/r/ext_key_1_innodb.result | 2 +-
.../mysql-test/tokudb/r/ext_key_2_innodb.result | 2 +-
43 files changed, 2686 insertions(+), 196 deletions(-)
diff --git a/mysql-test/main/derived_cond_pushdown.result b/mysql-test/main/derived_cond_pushdown.result
index 6887ad11284..d9f51a5c41a 100644
--- a/mysql-test/main/derived_cond_pushdown.result
+++ b/mysql-test/main/derived_cond_pushdown.result
@@ -7738,7 +7738,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
- "having_condition": "c < 300 and (t1.a > 3 and c > 110 or c < 110 and t1.a = 1)",
+ "having_condition": "c < 300 and (t1.a > 3 and c > 110 or t1.a = 1 and c < 110)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -7757,7 +7757,7 @@ EXPLAIN
"query_block": {
"select_id": 3,
"operation": "INTERSECT",
- "having_condition": "c > 100 and (t1.a > 3 and c > 110 or c < 110 and t1.a = 1)",
+ "having_condition": "c > 100 and (t1.a > 3 and c > 110 or t1.a = 1 and c < 110)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -8663,7 +8663,7 @@ EXPLAIN
{
"query_block": {
"select_id": 2,
- "having_condition": "c > 200 and (t1.a > 1 and c < 500 or c > 500 and t1.a = 1)",
+ "having_condition": "c > 200 and (t1.a > 1 and c < 500 or t1.a = 1 and c > 500)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -8682,7 +8682,7 @@ EXPLAIN
"query_block": {
"select_id": 3,
"operation": "EXCEPT",
- "having_condition": "c < 300 and (t1.a > 1 and c < 500 or c > 500 and t1.a = 1)",
+ "having_condition": "c < 300 and (t1.a > 1 and c < 500 or t1.a = 1 and c > 500)",
"filesort": {
"sort_key": "t1.a, t1.b",
"temporary_table": {
@@ -12673,7 +12673,7 @@ EXPLAIN
"materialized": {
"query_block": {
"select_id": 2,
- "having_condition": "max_c > 37 and max_c > 30 and t1.b = 1",
+ "having_condition": "t1.b = 1 and max_c > 37 and max_c > 30",
"table": {
"table_name": "t1",
"access_type": "ALL",
@@ -12748,7 +12748,7 @@ EXPLAIN
"materialized": {
"query_block": {
"select_id": 2,
- "having_condition": "max_c > 37 and max_c > 30 and t1.b = 1",
+ "having_condition": "t1.b = 1 and max_c > 37 and max_c > 30",
"table": {
"table_name": "t1",
"access_type": "ALL",
diff --git a/mysql-test/main/func_debug.result b/mysql-test/main/func_debug.result
index 7fcf522abba..a87bcdb2750 100644
--- a/mysql-test/main/func_debug.result
+++ b/mysql-test/main/func_debug.result
@@ -1565,12 +1565,16 @@ A NULL
Warnings:
Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
Note 1105 DBUG: types_compatible=yes bisect=no
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b);
a b
A NULL
Warnings:
Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
Note 1105 DBUG: types_compatible=yes bisect=no
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: types_compatible=yes bisect=no
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A',10);
a b
A NULL
@@ -1594,6 +1598,9 @@ Warnings:
Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
Note 1105 DBUG: [1] arg=3 handler=1 (double)
Note 1105 DBUG: types_compatible=no bisect=no
+Note 1105 DBUG: [0] arg=2 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
Warning 1292 Truncated incorrect DOUBLE value: 'A'
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b,10);
a b
@@ -1602,6 +1609,9 @@ Warnings:
Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
Note 1105 DBUG: [1] arg=3 handler=1 (double)
Note 1105 DBUG: types_compatible=no bisect=no
+Note 1105 DBUG: [0] arg=1 handler=0 (longblob)
+Note 1105 DBUG: [1] arg=3 handler=1 (double)
+Note 1105 DBUG: types_compatible=no bisect=no
Warning 1292 Truncated incorrect DOUBLE value: 'A'
DROP TABLE t1;
#
diff --git a/mysql-test/main/group_min_max.result b/mysql-test/main/group_min_max.result
index 36a44b05817..2f08a81acaa 100644
--- a/mysql-test/main/group_min_max.result
+++ b/mysql-test/main/group_min_max.result
@@ -2424,41 +2424,41 @@ EXPLAIN SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
-2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE EXISTS
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer index NULL a 10 NULL 15 Using index
-2 SUBQUERY t1 index NULL a 10 NULL 15 Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
a IN (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 8
+1 PRIMARY <subquery2> ALL distinct_key NULL NULL NULL 3
1 PRIMARY t1_outer ref a a 5 <subquery2>.max(b) 2 Using index
-2 MATERIALIZED t1 range NULL a 5 NULL 8 Using index for group-by
+2 MATERIALIZED t1 range a a 5 NULL 3 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer GROUP BY a HAVING
a > (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer range NULL a 5 NULL 8 Using index for group-by
-2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index for group-by
EXPLAIN SELECT 1 FROM t1 AS t1_outer1 JOIN t1 AS t1_outer2
ON t1_outer1.a = (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2)
AND t1_outer1.b = t1_outer2.b;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer1 ref a a 5 const 1 Using where; Using index
1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using where; Using index; Using join buffer (flat, BNL join)
-2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index for group-by
EXPLAIN SELECT (SELECT (SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) x
FROM t1 AS t1_outer) x2 FROM t1 AS t1_outer2;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1_outer2 index NULL a 10 NULL 15 Using index
2 SUBQUERY t1_outer index NULL a 10 NULL 15 Using index
-3 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+3 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index for group-by
CREATE TABLE t3 LIKE t1;
FLUSH STATUS;
INSERT INTO t3 SELECT a,MAX(b) FROM t1 GROUP BY a;
diff --git a/mysql-test/main/having.result b/mysql-test/main/having.result
index 6c206a1699d..291130d28d1 100644
--- a/mysql-test/main/having.result
+++ b/mysql-test/main/having.result
@@ -470,9 +470,9 @@ WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8 AND table1.f1 >= 6);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where `test`.`table1`.`f3` = 9 group by `test`.`table1`.`f1`,7 having 0
+Note 1003 select 0 AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where 0 group by 0,7 having 1
EXPLAIN EXTENDED
SELECT table1.f1, table2.f2
FROM t1 AS table1
@@ -481,9 +481,9 @@ WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
-1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where `test`.`table1`.`f3` = 9 group by `test`.`table1`.`f1`,7 having 0
+Note 1003 select `test`.`table1`.`f1` AS `f1`,7 AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where 0 group by `test`.`table1`.`f1`,7 having 1
DROP TABLE t1;
#
# Bug#52336 Segfault / crash in 5.1 copy_fields (param=0x9872980) at sql_select.cc:15355
@@ -631,7 +631,7 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 index NULL f10 4 NULL 2 100.00 Using index
2 DEPENDENT SUBQUERY t3 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
-Note 1003 /* select#1 */ select min(`test`.`t1`.`f10`) AS `field1` from `test`.`t1` where <expr_cache><7>(<in_optimizer>(7,<exists>(/* select#2 */ select `test`.`t3`.`f3` from `test`.`t3` where <cache>(7) = `test`.`t3`.`f3`))) having <cache>(`field1`) < 's'
+Note 1003 /* select#1 */ select min(`test`.`t1`.`f10`) AS `field1` from `test`.`t1` where <expr_cache><7>(<in_optimizer>(7,<exists>(/* select#2 */ select `test`.`t3`.`f3` from `test`.`t3` where <cache>(7) = `test`.`t3`.`f3`))) having `field1` < 's'
set optimizer_switch=@save_optimizer_switch;
drop table t1,t2,t3;
End of 5.2 tests
diff --git a/mysql-test/main/having_cond_pushdown.result b/mysql-test/main/having_cond_pushdown.result
new file mode 100644
index 00000000000..b7148a890ed
--- /dev/null
+++ b/mysql-test/main/having_cond_pushdown.result
@@ -0,0 +1,1631 @@
+CREATE TABLE t1(a INT, b INT, c INT);
+CREATE TABLE t2(x INT, y INT);
+INSERT INTO t1 VALUES (1,14,3), (2,13,2), (1,22,1), (3,13,4), (3,14,2);
+INSERT INTO t2 VALUES (2,13),(5,22),(3,14),(1,22);
+CREATE VIEW v1
+AS SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a;
+CREATE FUNCTION f1() RETURNS INT RETURN 3;
+# conjunctive subformula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : using equality
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+# extracted AND formula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+a MAX(t1.b)
+2 13
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+a MAX(t1.b)
+2 13
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a < 4"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) AND (t1.a<4)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a < 4"
+ }
+ }
+ }
+ }
+}
+# extracted OR formula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+a MAX(t1.b)
+2 13
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+a MAX(t1.b)
+2 13
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+Warnings:
+Note 1249 Select 2 was reduced during optimization
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 or t1.a = 3"
+ }
+ }
+ }
+ }
+}
+Warnings:
+Note 1249 Select 2 was reduced during optimization
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) OR (a IN (SELECT 3))
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 or t1.a = 3"
+ }
+ }
+ }
+ }
+}
+Warnings:
+Note 1249 Select 2 was reduced during optimization
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+3 14 2
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+3 14 2
+explain SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 2 and max(t1.b) > 13 or t1.a < 3 and min(t1.c) > 1",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2 or t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a>2) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a > 2 and max(t1.b) > 13 or t1.a < 3 and min(t1.c) > 1",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 2 or t1.a < 3"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : no aggregation formula pushdown
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.a)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) = 3",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 3"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=3)
+GROUP BY t1.a
+HAVING (MAX(t1.a)=3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.a) = 3",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 3"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 12",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>12);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) > 12",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+a MAX(t1.b)
+2 13
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+a MAX(t1.b)
+2 13
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+a MIN(t1.c)
+2 2
+3 2
+SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+a MIN(t1.c)
+2 2
+3 2
+explain SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "min(t1.c) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MIN(t1.c)<3);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "min(t1.c) < 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+a MAX(t1.b) MIN(t1.c)
+2 13 2
+explain SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13 and min(t1.c) = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "max(t1.b) = 13 and min(t1.c) = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2"
+ }
+ }
+}
+# conjunctive subformula : no stored function pushdown
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+a MAX(t1.b)
+3 14
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+a MAX(t1.b)
+3 14
+explain SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = test.f1()",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (a=test.f1());
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = test.f1()",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into derived table WHERE clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+a
+2
+3
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+a
+2
+3
+explain SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary; Using filesort
+1 PRIMARY <derived2> ref key0 key0 5 test.t2.x 2
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x > 1 and t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.a>1)
+GROUP BY v1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x > 1 and t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into derived table HAVING clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+a c
+1 3
+3 4
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+a c
+1 3
+3 4
+explain SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary; Using filesort
+1 PRIMARY <derived2> ref key0 key0 5 test.t2.x 2 Using where
+2 DERIVED t1 ALL NULL NULL NULL NULL 5 Using temporary; Using filesort
+explain format=json SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.c",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "attached_condition": "v1.c > 2",
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "t1.c > 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.c>2)
+GROUP BY v1.c;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "v1.c",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x is not null"
+ },
+ "table": {
+ "table_name": "<derived2>",
+ "access_type": "ref",
+ "possible_keys": ["key0"],
+ "key": "key0",
+ "key_length": "5",
+ "used_key_parts": ["a"],
+ "ref": ["test.t2.x"],
+ "rows": 2,
+ "filtered": 100,
+ "attached_condition": "v1.c > 2",
+ "materialized": {
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "t1.c > 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into materialized IN subquery
+# WHERE clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+a b c
+2 13 2
+3 14 2
+SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+a b c
+2 13 2
+3 14 2
+explain SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+explain format=json SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5 and t2.x > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT * FROM t1
+WHERE
+(t1.a>1) AND
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5 and t2.x > 1"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# conjunctive subformula : pushdown into materialized IN subquery
+# HAVING clause
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+a b c
+2 13 2
+SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+a b c
+2 13 2
+explain SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 8 test.t1.a,test.t1.b 1
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 4 Using where; Using temporary
+explain format=json SELECT * FROM t1
+WHERE
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b < 14 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "`MAX(t2.y)` < 14",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT * FROM t1
+WHERE
+(t1.b<14) AND
+(t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.b",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b < 14 and t1.a is not null and t1.b is not null"
+ },
+ "table": {
+ "table_name": "<subquery2>",
+ "access_type": "eq_ref",
+ "possible_keys": ["distinct_key"],
+ "key": "distinct_key",
+ "key_length": "8",
+ "used_key_parts": ["x", "MAX(t2.y)"],
+ "ref": ["test.t1.a", "test.t1.b"],
+ "rows": 1,
+ "filtered": 100,
+ "materialized": {
+ "unique": 1,
+ "query_block": {
+ "select_id": 2,
+ "having_condition": "`MAX(t2.y)` < 14",
+ "temporary_table": {
+ "table": {
+ "table_name": "t2",
+ "access_type": "ALL",
+ "rows": 4,
+ "filtered": 100,
+ "attached_condition": "t2.x < 5"
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+# non-standard allowed queries
+# conjunctive subformula
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = 2",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+MAX(t1.a) a b c
+3 2 13 2
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+MAX(t1.a) a b c
+3 2 13 2
+explain SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = 2 and t1.c = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b = 13"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+WHERE (t1.b=13)
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.a = 2 and t1.c = 2",
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.b = 13"
+ }
+ }
+}
+# extracted AND formula : using equalities
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b) FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2 and t1.c = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a=2)
+GROUP BY t1.a;
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.a = 2 and t1.c = 2"
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+a MAX(t1.b) c
+2 13 2
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+a MAX(t1.b) c
+2 13 2
+explain SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 5 Using where; Using temporary; Using filesort
+explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3 and t1.c > 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3"
+ }
+ }
+ }
+ }
+}
+set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for explain format=json SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE ((t1.a=t1.c) AND (t1.a>1)) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+EXPLAIN
+{
+ "query_block": {
+ "select_id": 1,
+ "having_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3 and t1.c > 3",
+ "filesort": {
+ "sort_key": "t1.a",
+ "temporary_table": {
+ "table": {
+ "table_name": "t1",
+ "access_type": "ALL",
+ "rows": 5,
+ "filtered": 100,
+ "attached_condition": "t1.c = t1.a and t1.a > 1 or t1.a < 3"
+ }
+ }
+ }
+ }
+}
+DROP TABLE t1,t2;
+DROP VIEW v1;
+DROP FUNCTION f1;
diff --git a/mysql-test/main/having_cond_pushdown.test b/mysql-test/main/having_cond_pushdown.test
new file mode 100644
index 00000000000..a0ce2923e55
--- /dev/null
+++ b/mysql-test/main/having_cond_pushdown.test
@@ -0,0 +1,402 @@
+let $no_pushdown=
+ set statement optimizer_switch='condition_pushdown_from_having_into_where=off' for;
+
+CREATE TABLE t1(a INT, b INT, c INT);
+CREATE TABLE t2(x INT, y INT);
+
+INSERT INTO t1 VALUES (1,14,3), (2,13,2), (1,22,1), (3,13,4), (3,14,2);
+INSERT INTO t2 VALUES (2,13),(5,22),(3,14),(1,22);
+
+CREATE VIEW v1
+AS SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a;
+
+CREATE FUNCTION f1() RETURNS INT RETURN 3;
+
+--echo # conjunctive subformula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : using equality
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted AND formula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (t1.a<4);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) AND (t1.a<4)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted OR formula
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) OR (a IN (SELECT 3));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1) OR (a IN (SELECT 3))
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a>2) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a>2) AND (MAX(t1.b)>13)) OR ((t1.a<3) AND (MIN(t1.c)>1));
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : no aggregation formula pushdown
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.a)<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.a)<3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)>13);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>13);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=3) AND (MAX(t1.a)=3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=3)
+GROUP BY t1.a
+HAVING (MAX(t1.a)=3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)>12);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)>12);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MAX(t1.b)=13);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (MIN(t1.c)<3);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (MIN(t1.c)<3);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),MIN(t1.c)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=2) AND (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MIN(t1.c)
+FROM t1
+WHERE (t1.a=2)
+GROUP BY t1.a
+HAVING (MAX(t1.b)=13) AND (MIN(t1.c)=2);
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : no stored function pushdown
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a>1) AND (a=test.f1());
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b)
+FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (a=test.f1());
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into derived table WHERE clause
+let $query=
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.a
+HAVING (v1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT v1.a
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.a>1)
+GROUP BY v1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into derived table HAVING clause
+let $query=
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a)
+GROUP BY v1.c
+HAVING (v1.c>2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT v1.a,v1.c
+FROM t2,v1
+WHERE (t2.x=v1.a) AND (v1.c>2)
+GROUP BY v1.c;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into materialized IN subquery
+--echo # WHERE clause
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a
+HAVING (t1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a>1) AND
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+--echo # conjunctive subformula : pushdown into materialized IN subquery
+--echo # HAVING clause
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b
+HAVING (t1.b<14);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT * FROM t1
+WHERE
+ (t1.b<14) AND
+ (t1.a,t1.b) IN (SELECT t2.x,MAX(t2.y) FROM t2 WHERE t2.x<5 GROUP BY t2.x)
+GROUP BY t1.b;
+eval $no_pushdown explain format=json $query;
+
+--echo # non-standard allowed queries
+--echo # conjunctive subformula
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.c=2) AND (t1.a>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c FROM t1
+WHERE (t1.a>1)
+GROUP BY t1.a
+HAVING (t1.c=2);
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.b=13) AND (t1.c=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT MAX(t1.a),t1.a,t1.b,t1.c
+FROM t1
+WHERE (t1.b=13)
+GROUP BY t1.b
+HAVING (t1.a=2) AND (t1.c=2);
+eval $no_pushdown explain format=json $query;
+
+--echo # extracted AND formula : using equalities
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c>1);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b) FROM t1
+WHERE (t1.a=t1.c) AND (t1.a>1)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING (t1.a=t1.c) AND (t1.c=2);
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE (t1.a=t1.c) AND (t1.a=2)
+GROUP BY t1.a;
+eval $no_pushdown explain format=json $query;
+
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+eval $no_pushdown $query;
+eval $query;
+eval explain $query;
+eval explain format=json $query;
+let $query=
+SELECT t1.a,MAX(t1.b),t1.c
+FROM t1
+WHERE ((t1.a=t1.c) AND (t1.a>1)) OR (t1.a<3)
+GROUP BY t1.a
+HAVING ((t1.a=t1.c) AND (t1.a>1)) OR ((t1.a<3) AND (t1.c>3));
+eval $no_pushdown explain format=json $query;
+
+DROP TABLE t1,t2;
+DROP VIEW v1;
+DROP FUNCTION f1;
diff --git a/mysql-test/main/key.result b/mysql-test/main/key.result
index ba1124aaa14..a6a51b7f990 100644
--- a/mysql-test/main/key.result
+++ b/mysql-test/main/key.result
@@ -607,7 +607,7 @@ EXPLAIN SELECT 1 FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range NULL a 5 NULL 8 Using index for group-by
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index for group-by
SELECT 1 as RES FROM t1 AS t1_outer WHERE
(SELECT max(b) FROM t1 GROUP BY a HAVING a < 2) > 12;
RES
diff --git a/mysql-test/main/mysqld--help.result b/mysql-test/main/mysqld--help.result
index 3ab9b5a04e8..22d84f2ce58 100644
--- a/mysql-test/main/mysqld--help.result
+++ b/mysql-test/main/mysqld--help.result
@@ -666,7 +666,8 @@ The following options may be given as the first argument:
optimize_join_buffer_size, table_elimination,
extended_keys, exists_to_in, orderby_uses_equalities,
condition_pushdown_for_derived, split_materialized,
- condition_pushdown_for_subquery
+ condition_pushdown_for_subquery,
+ condition_pushdown_from_having_into_where
--optimizer-use-condition-selectivity=#
Controls selectivity of which conditions the optimizer
takes into account to calculate cardinality of a partial
@@ -1515,7 +1516,7 @@ old-style-user-limits FALSE
optimizer-prune-level 1
optimizer-search-depth 62
optimizer-selectivity-sampling-limit 100
-optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+optimizer-switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
optimizer-use-condition-selectivity 1
performance-schema FALSE
performance-schema-accounts-size -1
diff --git a/mysql-test/main/select.result b/mysql-test/main/select.result
index 9b6a570717b..631fca85294 100644
--- a/mysql-test/main/select.result
+++ b/mysql-test/main/select.result
@@ -4645,6 +4645,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/select_jcl6.result b/mysql-test/main/select_jcl6.result
index d78fad15da1..b36a0e0f95a 100644
--- a/mysql-test/main/select_jcl6.result
+++ b/mysql-test/main/select_jcl6.result
@@ -4656,6 +4656,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/select_pkeycache.result b/mysql-test/main/select_pkeycache.result
index 9b6a570717b..631fca85294 100644
--- a/mysql-test/main/select_pkeycache.result
+++ b/mysql-test/main/select_pkeycache.result
@@ -4645,6 +4645,8 @@ WHERE int_key IN (SELECT 1 FROM t1)
HAVING date_nokey = '10:41:7'
ORDER BY date_key;
date_nokey
+Warnings:
+Warning 1292 Incorrect datetime value: '10:41:7'
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT NOT NULL, b INT);
INSERT INTO t1 VALUES (1, 1);
diff --git a/mysql-test/main/subselect.result b/mysql-test/main/subselect.result
index 1c087a3199c..9ec950dba05 100644
--- a/mysql-test/main/subselect.result
+++ b/mysql-test/main/subselect.result
@@ -7004,7 +7004,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -7038,7 +7038,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect_innodb.result b/mysql-test/main/subselect_innodb.result
index ec7f2c0a3d5..04bf3c2c599 100644
--- a/mysql-test/main/subselect_innodb.result
+++ b/mysql-test/main/subselect_innodb.result
@@ -458,7 +458,7 @@ EXPLAIN
SELECT * FROM t1 WHERE EXISTS ( SELECT b FROM t2, t3 GROUP BY b HAVING b != 3 );
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t2 index NULL PRIMARY 4 NULL 1 Using index; Using temporary; Using filesort
+2 SUBQUERY t2 index PRIMARY PRIMARY 4 NULL 1 Using where; Using index; Using temporary; Using filesort
2 SUBQUERY t3 ALL NULL NULL NULL NULL 1 Using join buffer (flat, BNL join)
SELECT * FROM t1 WHERE EXISTS ( SELECT b FROM t2, t3 GROUP BY b HAVING b != 3 );
a
diff --git a/mysql-test/main/subselect_mat.result b/mysql-test/main/subselect_mat.result
index 463ec53e7bb..e415737c987 100644
--- a/mysql-test/main/subselect_mat.result
+++ b/mysql-test/main/subselect_mat.result
@@ -1901,7 +1901,7 @@ INSERT INTO t2 values(1),(2);
EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
SHOW STATUS LIKE 'Created_tmp_tables';
diff --git a/mysql-test/main/subselect_no_exists_to_in.result b/mysql-test/main/subselect_no_exists_to_in.result
index eb912d9e331..e118389f222 100644
--- a/mysql-test/main/subselect_no_exists_to_in.result
+++ b/mysql-test/main/subselect_no_exists_to_in.result
@@ -7004,7 +7004,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -7038,7 +7038,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect_no_mat.result b/mysql-test/main/subselect_no_mat.result
index 72f30bbd21f..c13d5bcca33 100644
--- a/mysql-test/main/subselect_no_mat.result
+++ b/mysql-test/main/subselect_no_mat.result
@@ -6998,7 +6998,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -7031,7 +7031,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect_no_opts.result b/mysql-test/main/subselect_no_opts.result
index de075d3245f..e997c323167 100644
--- a/mysql-test/main/subselect_no_opts.result
+++ b/mysql-test/main/subselect_no_opts.result
@@ -6995,7 +6995,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -7029,7 +7029,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect_no_scache.result b/mysql-test/main/subselect_no_scache.result
index a594f5f85b9..7bfbd95ad0b 100644
--- a/mysql-test/main/subselect_no_scache.result
+++ b/mysql-test/main/subselect_no_scache.result
@@ -7010,7 +7010,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -7044,7 +7044,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect_no_semijoin.result b/mysql-test/main/subselect_no_semijoin.result
index e068b28b017..e7c13ed5a03 100644
--- a/mysql-test/main/subselect_no_semijoin.result
+++ b/mysql-test/main/subselect_no_semijoin.result
@@ -6995,7 +6995,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
@@ -7029,7 +7029,7 @@ INSERT INTO t2 VALUES (45),(17),(20);
EXPLAIN SELECT * FROM t1 WHERE EXISTS ( SELECT a FROM t1, t2 WHERE b = a GROUP BY a HAVING a <> 1 ) ;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
-2 SUBQUERY t1 range a a 5 NULL 2 Using where; Using index
+2 SUBQUERY t1 range a a 5 NULL 3 Using where; Using index
2 SUBQUERY t2 ref b b 5 test.t1.a 2 Using index
DROP TABLE t1,t2;
#
diff --git a/mysql-test/main/subselect_sj_jcl6.result b/mysql-test/main/subselect_sj_jcl6.result
index 77a073ea2d3..4edb2285573 100644
--- a/mysql-test/main/subselect_sj_jcl6.result
+++ b/mysql-test/main/subselect_sj_jcl6.result
@@ -3386,7 +3386,7 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index
+1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
@@ -3400,7 +3400,7 @@ EXPLAIN
SELECT a FROM t1 t WHERE a IN (SELECT b FROM t1, t2 WHERE b = a)
GROUP BY a HAVING a != 'z';
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t index idx_a idx_a 4 NULL 3 Using index
+1 PRIMARY t range idx_a idx_a 4 NULL 3 Using where; Using index
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1
2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where
2 MATERIALIZED t1 ref idx_a idx_a 4 test.t2.b 2 Using index
diff --git a/mysql-test/main/subselect_sj_mat.result b/mysql-test/main/subselect_sj_mat.result
index 6a4a1a4ad5b..e8164a2fd1d 100644
--- a/mysql-test/main/subselect_sj_mat.result
+++ b/mysql-test/main/subselect_sj_mat.result
@@ -1939,7 +1939,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.a 1
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
SHOW STATUS LIKE 'Created_tmp_tables';
diff --git a/mysql-test/main/tmp_table_count-7586.result b/mysql-test/main/tmp_table_count-7586.result
index 0c526e0d4a3..637e7385685 100644
--- a/mysql-test/main/tmp_table_count-7586.result
+++ b/mysql-test/main/tmp_table_count-7586.result
@@ -38,7 +38,7 @@ EXPLAIN SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2 Using where
1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 test.t1.a 1
-2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using temporary
+2 MATERIALIZED t2 ALL NULL NULL NULL NULL 2 Using where; Using temporary
truncate table performance_schema.events_statements_history_long;
flush status;
CREATE TABLE t3 SELECT * FROM t1 WHERE a IN (SELECT * FROM t2 GROUP BY a HAVING a > 1);
diff --git a/mysql-test/main/union.result b/mysql-test/main/union.result
index 4e5f9312e03..4ae49971980 100644
--- a/mysql-test/main/union.result
+++ b/mysql-test/main/union.result
@@ -2261,9 +2261,9 @@ GROUP BY i
HAVING i = 10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL No tables used
-2 UNION NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
+2 UNION NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
-Note 1003 /* select#1 */ select 1 AS `1`,2 AS `2` union all /* select#2 */ select 1 AS `i`,count(0) AS `COUNT(*)` from `test`.`t2` where 1 group by 1 having 0
+Note 1003 /* select#1 */ select 1 AS `1`,2 AS `2` union all /* select#2 */ select 1 AS `i`,count(0) AS `COUNT(*)` from `test`.`t2` where 0 group by 1 having 1
DROP TABLE t1,t2;
#
# Start of 10.3 tests
diff --git a/mysql-test/suite/gcol/r/gcol_select_innodb.result b/mysql-test/suite/gcol/r/gcol_select_innodb.result
index bc9bddad690..c04aff7662b 100644
--- a/mysql-test/suite/gcol/r/gcol_select_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_select_innodb.result
@@ -493,6 +493,7 @@ Warning 1292 Truncated incorrect DOUBLE value: 'c'
Warning 1292 Truncated incorrect DOUBLE value: 't'
Warning 1292 Truncated incorrect DOUBLE value: 'm'
Warning 1292 Truncated incorrect DOUBLE value: 'd'
+Warning 1292 Truncated incorrect DOUBLE value: 'd'
DROP TABLE cc;
SET sql_mode=@save_old_sql_mode;
#
diff --git a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
index bc22fe198a1..1f0692a7d83 100644
--- a/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
+++ b/mysql-test/suite/sys_vars/r/optimizer_switch_basic.result
@@ -1,63 +1,63 @@
SET @start_global_value = @@global.optimizer_switch;
SELECT @start_global_value;
@start_global_value
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+optimizer_switch index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+OPTIMIZER_SWITCH index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
set global optimizer_switch=10;
set session optimizer_switch=5;
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=off,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+index_merge=on,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
set global optimizer_switch="index_merge_sort_union=on";
set session optimizer_switch="index_merge=off";
select @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
show global variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+optimizer_switch index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
show session variables like 'optimizer_switch';
Variable_name Value
-optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+optimizer_switch index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
select * from information_schema.global_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
select * from information_schema.session_variables where variable_name='optimizer_switch';
VARIABLE_NAME VARIABLE_VALUE
-OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+OPTIMIZER_SWITCH index_merge=off,index_merge_union=off,index_merge_sort_union=on,index_merge_intersection=off,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
set session optimizer_switch="default";
select @@session.optimizer_switch;
@@session.optimizer_switch
-index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off
+index_merge=off,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=off,derived_merge=off,derived_with_keys=off,firstmatch=off,loosescan=off,materialization=off,in_to_exists=off,semijoin=off,partial_match_rowid_merge=off,partial_match_table_scan=off,subquery_cache=off,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=off,semijoin_with_cache=off,join_cache_incremental=off,join_cache_hashed=off,join_cache_bka=off,optimize_join_buffer_size=off,table_elimination=off,extended_keys=off,exists_to_in=off,orderby_uses_equalities=off,condition_pushdown_for_derived=off,split_materialized=off,condition_pushdown_for_subquery=off,condition_pushdown_from_having_into_where=off
set optimizer_switch = replace(@@optimizer_switch, '=off', '=on');
Warnings:
Warning 1681 'engine_condition_pushdown=on' is deprecated and will be removed in a future release
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=on,engine_condition_pushdown=on,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=on,mrr_cost_based=on,mrr_sort_keys=on,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
set global optimizer_switch=1.1;
ERROR 42000: Incorrect argument type to variable 'optimizer_switch'
set global optimizer_switch=1e1;
@@ -69,4 +69,4 @@ ERROR 42000: Variable 'optimizer_switch' can't be set to the value of 'foobar'
SET @@global.optimizer_switch = @start_global_value;
SELECT @@global.optimizer_switch;
@@global.optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
index f6f88692ff2..1469cb4214a 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result
@@ -2883,17 +2883,17 @@ ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_SWITCH
-SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
-GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+SESSION_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
+GLOBAL_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
GLOBAL_VALUE_ORIGIN COMPILE-TIME
-DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+DEFAULT_VALUE index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
VARIABLE_SCOPE SESSION
VARIABLE_TYPE FLAGSET
VARIABLE_COMMENT Fine-tune the optimizer behavior
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
-ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,default
+ENUM_VALUE_LIST index_merge,index_merge_union,index_merge_sort_union,index_merge_intersection,index_merge_sort_intersection,engine_condition_pushdown,index_condition_pushdown,derived_merge,derived_with_keys,firstmatch,loosescan,materialization,in_to_exists,semijoin,partial_match_rowid_merge,partial_match_table_scan,subquery_cache,mrr,mrr_cost_based,mrr_sort_keys,outer_join_with_cache,semijoin_with_cache,join_cache_incremental,join_cache_hashed,join_cache_bka,optimize_join_buffer_size,table_elimination,extended_keys,exists_to_in,orderby_uses_equalities,condition_pushdown_for_derived,split_materialized,condition_pushdown_for_subquery,condition_pushdown_from_having_into_where,default
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME OPTIMIZER_USE_CONDITION_SELECTIVITY
diff --git a/sql/item.cc b/sql/item.cc
index c19ad32f6ce..897be581256 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -3048,6 +3048,8 @@ Item_sp::init_result_field(THD *thd, uint max_length, uint maybe_null,
Item* Item_ref::build_clone(THD *thd)
{
+ if (thd->having_pushdown)
+ return real_item()->build_clone(thd);
Item_ref *copy= (Item_ref *) get_copy(thd);
if (!copy ||
!(copy->ref= (Item**) alloc_root(thd->mem_root, sizeof(Item*))) ||
@@ -7978,45 +7980,14 @@ Item *Item_direct_view_ref::derived_field_transformer_for_where(THD *thd,
return this;
}
-static
-Field_pair *find_matching_grouping_field(Item *item,
- st_select_lex *sel)
-{
- DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
- (item->type() == Item::REF_ITEM &&
- ((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
- List_iterator<Field_pair> li(sel->grouping_tmp_fields);
- Field_pair *gr_field;
- Item_field *field_item= (Item_field *) (item->real_item());
- while ((gr_field= li++))
- {
- if (field_item->field == gr_field->field)
- return gr_field;
- }
- Item_equal *item_equal= item->get_item_equal();
- if (item_equal)
- {
- Item_equal_fields_iterator it(*item_equal);
- Item *equal_item;
- while ((equal_item= it++))
- {
- field_item= (Item_field *) (equal_item->real_item());
- li.rewind();
- while ((gr_field= li++))
- {
- if (field_item->field == gr_field->field)
- return gr_field;
- }
- }
- }
- return NULL;
-}
+Field_pair *find_matching_field_pair(Item *item, List<Field_pair> pair_list);
+
Item *Item_field::grouping_field_transformer_for_where(THD *thd, uchar *arg)
{
st_select_lex *sel= (st_select_lex *)arg;
- Field_pair *gr_field= find_matching_grouping_field(this, sel);
+ Field_pair *gr_field= find_matching_field_pair(this, sel->grouping_tmp_fields);
if (gr_field)
return gr_field->corresponding_item->build_clone(thd);
return this;
@@ -8030,7 +8001,8 @@ Item_direct_view_ref::grouping_field_transformer_for_where(THD *thd,
if (!item_equal)
return this;
st_select_lex *sel= (st_select_lex *)arg;
- Field_pair *gr_field= find_matching_grouping_field(this, sel);
+ Field_pair *gr_field= find_matching_field_pair(this,
+ sel->grouping_tmp_fields);
return gr_field->corresponding_item->build_clone(thd);
}
@@ -9462,6 +9434,19 @@ Item *Item_direct_view_ref::propagate_equal_fields(THD *thd,
}
+Item *Item_ref::propagate_equal_fields(THD *thd, const Context &ctx,
+ COND_EQUAL *cond)
+{
+ Item *field_item= real_item();
+ if (field_item->type() != FIELD_ITEM)
+ return this;
+ Item *item= field_item->propagate_equal_fields(thd, ctx, cond);
+ if (item != field_item)
+ return item;
+ return this;
+}
+
+
/**
Replace an Item_direct_view_ref for an equal Item_field evaluated earlier
(if any).
@@ -9503,6 +9488,17 @@ Item *Item_direct_view_ref::replace_equal_field(THD *thd, uchar *arg)
return item != field_item ? item : this;
}
+bool Item_field::excl_dep_on_table(table_map tab_map)
+{
+ return used_tables() == tab_map ||
+ (item_equal && (item_equal->used_tables() & tab_map));
+}
+
+bool
+Item_field::excl_dep_on_grouping_fields(st_select_lex *sel)
+{
+ return find_matching_field_pair(this, sel->grouping_tmp_fields) != NULL;
+}
bool Item_direct_view_ref::excl_dep_on_table(table_map tab_map)
{
@@ -9524,7 +9520,7 @@ bool Item_direct_view_ref::excl_dep_on_grouping_fields(st_select_lex *sel)
if (item_equal)
{
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
- return find_matching_grouping_field(this, sel) != NULL;
+ return (find_matching_field_pair(this, sel->grouping_tmp_fields) != NULL);
}
return (*ref)->excl_dep_on_grouping_fields(sel);
}
@@ -10968,17 +10964,6 @@ const char *dbug_print_unit(SELECT_LEX_UNIT *un)
#endif /*DBUG_OFF*/
-bool Item_field::excl_dep_on_table(table_map tab_map)
-{
- return used_tables() == tab_map ||
- (item_equal && (item_equal->used_tables() & tab_map));
-}
-
-bool
-Item_field::excl_dep_on_grouping_fields(st_select_lex *sel)
-{
- return find_matching_grouping_field(this, sel) != NULL;
-}
bool Item_field::vers_trx_id() const
{
diff --git a/sql/item.h b/sql/item.h
index 117c6b5c6d5..4af59eb4aea 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2158,7 +2158,6 @@ class Item: public Value_source,
{
return excl_dep_on_in_subq_left_part((Item_in_subselect *)arg);
}
- Item *get_corresponding_field_in_insubq(Item_in_subselect *subq_pred);
Item *build_pushable_cond(THD *thd,
Pushdown_checker checker,
uchar *arg);
@@ -2172,10 +2171,17 @@ class Item: public Value_source,
/*
Checks if this item consists in the left part of arg IN subquery predicate
*/
- bool pushable_equality_checker_for_subquery(uchar *arg)
- {
- return get_corresponding_field_in_insubq((Item_in_subselect *)arg);
- }
+ bool pushable_equality_checker_for_subquery(uchar *arg);
+ /*
+ Always returns true.
+ For the pushdown from the HAVING clause into the WHERE clause equality
+ can be pushed down if it contains the field that is equal to the field
+ from the GROUP BY of the select.
+ Equalities that can't be pushed are eliminated before this procedure call
+ so will never be handled by it.
+ */
+ bool pushable_equality_checker_for_having_pushdown(uchar *arg)
+ { return true; }
};
MEM_ROOT *get_thd_memroot(THD *thd);
@@ -4974,6 +4980,7 @@ class Item_ref :public Item_ident
Item *get_tmp_table_item(THD *thd);
Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src,
const Tmp_field_param *param);
+ Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *);
table_map used_tables() const;
void update_used_tables();
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ba503f18855..7865f2668bf 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -6219,6 +6219,8 @@ Item_equal::Item_equal(THD *thd, Item_equal *item_equal):
with_const= item_equal->with_const;
cond_false= item_equal->cond_false;
upper_levels= item_equal->upper_levels;
+ if (item_equal->upper_levels)
+ item_equal->upper_levels->references++;
}
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 1cdc48c8962..32e4b9fce08 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -3139,6 +3139,7 @@ class Item_equal: public Item_bool_func
{
return used_tables() & tab_map;
}
+ bool excl_dep_on_grouping_fields(st_select_lex *sel);
bool excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred);
friend class Item_equal_fields_iterator;
@@ -3160,12 +3161,15 @@ class COND_EQUAL: public Sql_alloc
COND_EQUAL *upper_levels; /* multiple equalities of upper and levels */
List<Item_equal> current_level; /* list of multiple equalities of
the current and level */
+ uint references; /* number of conditions that contain
+ reference on this COND_EQUAL */
COND_EQUAL()
{
upper_levels= 0;
+ references= 0;
}
COND_EQUAL(Item_equal *item, MEM_ROOT *mem_root)
- :upper_levels(0)
+ :upper_levels(0), references(0)
{
current_level.push_back(item, mem_root);
}
@@ -3173,11 +3177,16 @@ class COND_EQUAL: public Sql_alloc
{
max_members= cond_equal.max_members;
upper_levels= cond_equal.upper_levels;
+ references= cond_equal.references;
if (cond_equal.current_level.is_empty())
current_level.empty();
else
current_level= cond_equal.current_level;
}
+ bool is_empty()
+ {
+ return (current_level.elements == 0);
+ }
};
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e2740272385..48df4b55d2c 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -6405,6 +6405,22 @@ const Type_handler *Item_func_sp::type_handler() const
}
+bool Item_func_sp::excl_dep_on_grouping_fields(st_select_lex *sel)
+{
+ if (sel->join->thd->having_pushdown)
+ return false;
+ return Item_args::excl_dep_on_grouping_fields(sel);
+}
+
+
+bool Item_udf_func::excl_dep_on_grouping_fields(st_select_lex *sel)
+{
+ if (sel->join->thd->having_pushdown)
+ return false;
+ return Item_args::excl_dep_on_grouping_fields(sel);
+}
+
+
longlong Item_func_found_rows::val_int()
{
DBUG_ASSERT(fixed == 1);
diff --git a/sql/item_func.h b/sql/item_func.h
index 59fc49ead39..d6e08b9331a 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -313,6 +313,11 @@ class Item_func :public Item_func_or_sum
return this;
}
+ bool has_rand_bit()
+ {
+ return used_tables() & RAND_TABLE_BIT;
+ }
+
bool excl_dep_on_table(table_map tab_map)
{
if (used_tables() & OUTER_REF_TABLE_BIT)
@@ -323,6 +328,8 @@ class Item_func :public Item_func_or_sum
bool excl_dep_on_grouping_fields(st_select_lex *sel)
{
+ if (has_rand_bit())
+ return false;
return Item_args::excl_dep_on_grouping_fields(sel);
}
@@ -2066,6 +2073,7 @@ class Item_udf_func :public Item_func
{
return type_handler()->Item_get_date(this, ltime, fuzzydate);
}
+ bool excl_dep_on_grouping_fields(st_select_lex *sel);
};
@@ -2944,6 +2952,8 @@ class Item_func_sp :public Item_func,
not_null_tables_cache= 0;
return 0;
}
+ bool pushdown_into_where_checker(uchar *arg) { return true; }
+ bool excl_dep_on_grouping_fields(st_select_lex *sel);
};
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index a55ce2d163c..01956934375 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -5653,6 +5653,7 @@ Item *and_new_conditions_to_optimized_cond(THD *thd, Item *cond,
*/
if (is_simplified_cond)
cond= cond->remove_eq_conds(thd, cond_value, true);
+
return cond;
}
@@ -6320,33 +6321,31 @@ bool JOIN::choose_tableless_subquery_plan()
}
-/*
- Check if the item exists in the fields list of the left part of
- the IN subquery predicate subq_pred and returns its corresponding
- item from the select of the right part of subq_pred.
-*/
-Item *Item::get_corresponding_field_in_insubq(Item_in_subselect *subq_pred)
-{
- DBUG_ASSERT(type() == Item::FIELD_ITEM ||
- (type() == Item::REF_ITEM &&
- ((Item_ref *) this)->ref_type() == Item_ref::VIEW_REF));
+Field_pair *get_corresponding_field_pair(Item *item,
+ List<Field_pair> pair_list);
- List_iterator<Field_pair> it(subq_pred->corresponding_fields);
- Field_pair *ret;
- Item_field *field_item= (Item_field *) (real_item());
- while ((ret= it++))
- {
- if (field_item->field == ret->field)
- return ret->corresponding_item;
- }
- return NULL;
+
+bool Item::pushable_equality_checker_for_subquery(uchar *arg)
+{
+ return
+ get_corresponding_field_pair(this,
+ ((Item_in_subselect *)arg)->corresponding_fields);
}
-bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+/*
+ Checks if 'item' or some item equal to it is equal to the field from
+ some Field_pair of 'pair_list' and returns matching Field_pair or
+ NULL if the matching Field_pair wasn't found.
+*/
+
+Field_pair *find_matching_field_pair(Item *item, List<Field_pair> pair_list)
{
- if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
- return true;
+ Field_pair *field_pair= get_corresponding_field_pair(item, pair_list);
+ if (field_pair)
+ return field_pair;
+
+ Item_equal *item_equal= item->get_item_equal();
if (item_equal)
{
Item_equal_fields_iterator it(*item_equal);
@@ -6355,10 +6354,19 @@ bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
{
if (equal_item->const_item())
continue;
- if (equal_item->get_corresponding_field_in_insubq(subq_pred))
- return true;
+ field_pair= get_corresponding_field_pair(equal_item, pair_list);
+ if (field_pair)
+ return field_pair;
}
}
+ return NULL;
+}
+
+
+bool Item_field::excl_dep_on_in_subq_left_part(Item_in_subselect *subq_pred)
+{
+ if (find_matching_field_pair(((Item *) this), subq_pred->corresponding_fields))
+ return true;
return false;
}
@@ -6368,7 +6376,7 @@ bool Item_direct_view_ref::excl_dep_on_in_subq_left_part(Item_in_subselect *subq
if (item_equal)
{
DBUG_ASSERT(real_item()->type() == Item::FIELD_ITEM);
- if (((Item *)this)->get_corresponding_field_in_insubq(subq_pred))
+ if (get_corresponding_field_pair(((Item *)this), subq_pred->corresponding_fields))
return true;
}
return (*ref)->excl_dep_on_in_subq_left_part(subq_pred);
@@ -6432,7 +6440,7 @@ Item *get_corresponding_item(THD *thd, Item *item,
(item->type() == Item::REF_ITEM &&
((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF));
- Item *corresonding_item;
+ Field_pair *field_pair;
Item_equal *item_equal= item->get_item_equal();
if (item_equal)
@@ -6441,15 +6449,20 @@ Item *get_corresponding_item(THD *thd, Item *item,
Item *equal_item;
while ((equal_item= it++))
{
- corresonding_item=
- equal_item->get_corresponding_field_in_insubq(subq_pred);
- if (corresonding_item)
- return corresonding_item;
+ field_pair=
+ get_corresponding_field_pair(equal_item, subq_pred->corresponding_fields);
+ if (field_pair)
+ return field_pair->corresponding_item;
}
- return NULL;
}
else
- return item->get_corresponding_field_in_insubq(subq_pred);
+ {
+ field_pair=
+ get_corresponding_field_pair(item, subq_pred->corresponding_fields);
+ if (field_pair)
+ return field_pair->corresponding_item;
+ }
+ return NULL;
}
@@ -6725,9 +6738,7 @@ bool Item_in_subselect::pushdown_cond_for_in_subquery(THD *thd, Item *cond)
if (!remaining_cond)
goto exit;
- remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
- 0, 0);
- sel->cond_pushed_into_having= remaining_cond;
+ sel->mark_or_conds_to_avoid_pushdown(remaining_cond);
exit:
thd->lex->current_select= save_curr_select;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 7b7d34c6bc0..6f08095c4d3 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -960,6 +960,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier, bool skip_global_sys_var_lock)
/* Restore THR_THD */
set_current_thd(old_THR_THD);
inc_thread_count();
+ having_pushdown= FALSE;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index a7c33cbc504..2c8b0c49634 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4755,6 +4755,8 @@ class THD :public Statement,
LOG_SLOW_DISABLE_ADMIN);
query_plan_flags|= QPLAN_ADMIN;
}
+
+ bool having_pushdown;
};
inline void add_to_active_threads(THD *thd)
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 2df740b6811..728814d6ca8 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -1374,10 +1374,10 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
sl->find_common_window_func_partition_fields(thd);
if (!common_partition_fields)
continue;
- sl->collect_grouping_fields(thd, common_partition_fields);
+ sl->collect_grouping_fields_for_derived(thd, common_partition_fields);
}
else
- sl->collect_grouping_fields(thd, sl->group_list.first);
+ sl->collect_grouping_fields_for_derived(thd, sl->group_list.first);
Item *remaining_cond= NULL;
/* Do 4-6 */
@@ -1399,9 +1399,7 @@ bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived)
if (!remaining_cond)
continue;
- remaining_cond->walk(&Item::cleanup_excluding_const_fields_processor,
- 0, 0);
- sl->cond_pushed_into_having= remaining_cond;
+ sl->mark_or_conds_to_avoid_pushdown(remaining_cond);
}
thd->lex->current_select= save_curr_select;
DBUG_RETURN(false);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 93810d2041c..2824e9d9d17 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -7227,13 +7227,14 @@ void binlog_unsafe_map_init()
st_select_lex and saves this fields.
*/
-void st_select_lex::collect_grouping_fields(THD *thd,
- ORDER *grouping_list)
+void st_select_lex::collect_grouping_fields_for_derived(THD *thd,
+ ORDER *grouping_list)
{
grouping_tmp_fields.empty();
List_iterator<Item> li(join->fields_list);
Item *item= li++;
- for (uint i= 0; i < master_unit()->derived->table->s->fields; i++, (item=li++))
+ for (uint i= 0; i < master_unit()->derived->table->s->fields;
+ i++, (item=li++))
{
for (ORDER *ord= grouping_list; ord; ord= ord->next)
{
@@ -7247,6 +7248,47 @@ void st_select_lex::collect_grouping_fields(THD *thd,
}
}
+
+bool st_select_lex::collect_grouping_fields(THD *thd)
+{
+ grouping_tmp_fields.empty();
+
+ for (ORDER *ord= group_list.first; ord; ord= ord->next)
+ {
+ Item *item= *ord->item;
+ if (item->type() != Item::FIELD_ITEM &&
+ item->type() != Item::REF_ITEM)
+ continue;
+
+ Field_pair *grouping_tmp_field=
+ new Field_pair(((Item_field *)item->real_item())->field, item);
+ grouping_tmp_fields.push_back(grouping_tmp_field);
+ }
+ if (grouping_tmp_fields.elements)
+ return false;
+ return true;
+}
+
+
+bool Item_equal::excl_dep_on_grouping_fields(st_select_lex *sel)
+{
+ Item_equal_fields_iterator it(*this);
+ Item *item;
+
+ while ((item=it++))
+ {
+ if (item->excl_dep_on_grouping_fields(sel))
+ {
+ if (upper_levels)
+ upper_levels->references--;
+ set_extraction_flag(FULL_EXTRACTION_FL);
+ return true;
+ }
+ }
+ return false;
+}
+
+
/**
@brief
For a condition check possibility of exraction a formula over grouping fields
@@ -7271,12 +7313,18 @@ void st_select_lex::collect_grouping_fields(THD *thd,
*/
void
-st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
+st_select_lex::check_cond_extraction_for_grouping_fields(THD *thd, Item *cond)
{
+ if (thd->having_pushdown &&
+ cond->get_extraction_flag() == NO_EXTRACTION_FL)
+ return;
cond->clear_extraction_flag();
if (cond->type() == Item::COND_ITEM)
{
- bool and_cond= ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC;
+ Item_cond_and *and_cond=
+ (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC) ?
+ ((Item_cond_and*) cond) : 0;
+ uint mult_equal_count= and_cond ? and_cond->m_cond_equal.references : 0;
List<Item> *arg_list= ((Item_cond*) cond)->argument_list();
List_iterator<Item> li(*arg_list);
uint count= 0; // to count items not containing NO_EXTRACTION_FL
@@ -7284,7 +7332,7 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
Item *item;
while ((item=li++))
{
- check_cond_extraction_for_grouping_fields(item);
+ check_cond_extraction_for_grouping_fields(thd, item);
if (item->get_extraction_flag() != NO_EXTRACTION_FL)
{
count++;
@@ -7294,10 +7342,23 @@ st_select_lex::check_cond_extraction_for_grouping_fields(Item *cond)
else if (!and_cond)
break;
}
- if ((and_cond && count == 0) || item)
+ if (item)
cond->set_extraction_flag(NO_EXTRACTION_FL);
- if (count_full == arg_list->elements)
+ if (and_cond && ((count == 0) ||
+ (mult_equal_count != 0 &&
+ and_cond->m_cond_equal.references != 0)))
+ {
+ cond->set_extraction_flag(NO_EXTRACTION_FL);
+ if (!and_cond->m_cond_equal.is_empty())
+ and_cond->m_cond_equal.references= mult_equal_count;
+ }
+ else if (count_full == arg_list->elements)
+ {
+ if (and_cond != 0 && !and_cond->m_cond_equal.is_empty() &&
+ and_cond->m_cond_equal.upper_levels)
+ and_cond->m_cond_equal.upper_levels->references--;
cond->set_extraction_flag(FULL_EXTRACTION_FL);
+ }
if (cond->get_extraction_flag() != 0)
{
li.rewind();
@@ -7350,6 +7411,8 @@ Item *st_select_lex::build_cond_for_grouping_fields(THD *thd, Item *cond,
{
if (cond->get_extraction_flag() == FULL_EXTRACTION_FL)
{
+ if (thd->having_pushdown)
+ return cond->build_clone(thd);
if (no_top_clones)
return cond;
cond->clear_extraction_flag();
@@ -7809,7 +7872,7 @@ void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
if (have_window_funcs())
{
Item *cond_over_partition_fields;
- check_cond_extraction_for_grouping_fields(cond);
+ check_cond_extraction_for_grouping_fields(thd, cond);
cond_over_partition_fields=
build_cond_for_grouping_fields(thd, cond, true);
if (cond_over_partition_fields)
@@ -7845,7 +7908,7 @@ void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
that could be pushed into the WHERE clause of this select
*/
Item *cond_over_grouping_fields;
- check_cond_extraction_for_grouping_fields(cond);
+ check_cond_extraction_for_grouping_fields(thd, cond);
cond_over_grouping_fields=
build_cond_for_grouping_fields(thd, cond, true);
@@ -7875,3 +7938,288 @@ void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond,
*remaining_cond= cond;
}
+
+
+/**
+ @brief
+ Mark OR-conditions as non-pushable to avoid repeatable pushdown
+
+ @param cond The condition that should be marked (or its subformulas)
+
+ @details
+ In the case when OR-condition can be pushed into the HAVING clause
+ of the materialized derived table/view/IN subquery and some of
+ its parts can be pushed into the WHERE clause it can cause
+ repeatable pushdown in the pushdown from HAVING into WHERE clause.
+ Example:
+
+ SELECT *
+ FROM t1,
+ (
+ SELECT a,MAX(c) AS m_c
+ GROUP BY a
+ ) AS dt
+ WHERE ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3)) AND
+ (t1.a=v1.a);
+
+ after the pushdown into the materialized views/derived tables optimization
+ is done:
+
+ SELECT *
+ FROM t1,
+ (
+ SELECT a,MAX(c) AS m_c
+ WHERE (dt.a>2) OR (dt.a<3)
+ GROUP BY a
+ HAVING ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3))
+ ) AS dt
+ WHERE ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3)) AND
+ (t1.a=v1.a);
+
+ In the optimization stage for the select that defines derived table
+ in the pushdown from HAVING into WHERE optimization
+ (dt.a>2) OR (dt.a<3) will be again extracted from
+ ((dt.m_c>10) AND (dt.a>2)) OR ((dt.m_c<7) and (dt.a<3))
+ and pushed into the WHERE clause of the select that defines derived table.
+
+ To avoid it after conditions are pushed into the materialized derived
+ tables/views or IN subqueries OR-conditions that were pushed are marked
+ with NO_EXTRACTION_FL flag to avoid repeatable pushdown.
+*/
+
+void st_select_lex::mark_or_conds_to_avoid_pushdown(Item *cond)
+{
+ cond->walk(&Item::cleanup_excluding_const_fields_processor, 0, 0);
+
+ if (cond->type() == Item::COND_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ if (item->type() == Item::COND_ITEM &&
+ ((Item_cond*) item)->functype() == Item_func::COND_OR_FUNC)
+ item->set_extraction_flag(NO_EXTRACTION_FL);
+ }
+ }
+ else if (cond->type() == Item::COND_ITEM &&
+ ((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
+ cond->set_extraction_flag(NO_EXTRACTION_FL);
+
+ cond_pushed_into_having= cond;
+}
+
+
+/**
+ @brief
+ Remove marked top conjuncts of condition for pushdown from HAVING into WHERE
+
+ @param thd The thread handle
+ @param cond The condition which subformulas are to be removed
+
+ @details
+ The function behavior is similar to remove_pushed_top_conjuncts()
+ except the case when 'cond' is the AND-condition.
+ As in the pushdown from HAVING into WHERE conditions are not just cloned
+ so they can be later pushed down as it is for pushdown into materialized
+ derived tables/views or IN subqueries, but also should be removed from
+ the HAVING clause there comes a problem with multiple equalities removal.
+ It is solved with the removal from multiple equalities list 'm_cond_equal'
+ of 'cond' conditions that are marked with the FULL_EXTRACTION_FLAG flag.
+ @retval
+ condition without removed subformulas
+ 0 if the whole 'cond' is removed
+*/
+
+Item *remove_pushed_top_conjuncts_for_having(THD *thd, Item *cond)
+{
+ if (cond->get_extraction_flag() == FULL_EXTRACTION_FL)
+ {
+ cond->clear_extraction_flag();
+ return 0;
+ }
+ if (cond->type() == Item::COND_ITEM)
+ {
+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ List<Item> *cond_arg_list= ((Item_cond_and *)cond)->argument_list();
+ List<Item_equal> *cond_equalities=
+ &((Item_cond_and*) cond)->m_cond_equal.current_level;
+ cond_arg_list->disjoin((List<Item> *) cond_equalities);
+ List_iterator<Item_equal> it(*cond_equalities);
+ Item_equal *eq_item;
+ while ((eq_item= it++))
+ {
+ if (eq_item->get_extraction_flag() == FULL_EXTRACTION_FL)
+ it.remove();
+ }
+ cond_arg_list->append((List<Item> *) cond_equalities);
+
+ List_iterator<Item> li(*cond_arg_list);
+ Item *item;
+ while ((item= li++))
+ {
+ if (item->get_extraction_flag() == FULL_EXTRACTION_FL)
+ {
+ item->clear_extraction_flag();
+ li.remove();
+ }
+ }
+ switch (cond_arg_list->elements)
+ {
+ case 0:
+ return 0;
+ case 1:
+ return (cond_arg_list->head());
+ default:
+ return cond;
+ }
+ }
+ }
+ return cond;
+}
+
+
+/**
+ Check if the item is equal to some field in Field_pair 'field_pair'
+ from 'pair_list' and return found 'field_pair' if it exists.
+*/
+
+Field_pair *get_corresponding_field_pair(Item *item,
+ List<Field_pair> pair_list)
+{
+ DBUG_ASSERT(item->type() == Item::FIELD_ITEM ||
+ (item->type() == Item::REF_ITEM &&
+ ((((Item_ref *) item)->ref_type() == Item_ref::VIEW_REF) ||
+ (((Item_ref *) item)->ref_type() == Item_ref::REF))));
+
+ List_iterator<Field_pair> it(pair_list);
+ Field_pair *field_pair;
+ Item_field *field_item= (Item_field *) (item->real_item());
+ while ((field_pair= it++))
+ {
+ if (field_item->field == field_pair->field)
+ return field_pair;
+ }
+ return NULL;
+}
+
+
+/**
+ @brief
+ Extract condition that can be pushed from HAVING clause into WHERE clause
+
+ @param thd the thread handle
+ @param having the HAVING clause of this select
+ @param having_equal multiple equalities of HAVING
+
+ @details
+ This function builds the most restrictive condition depending only on
+ the fields used in the GROUP BY of this select (directly or indirectly
+ through equality) that can be extracted from the HAVING clause of this
+ select having and pushes it into the WHERE clause of this select.
+
+ Example of the transformation:
+
+ SELECT t1.a,MAX(t1.b)
+ FROM t1
+ GROUP BY t1.a
+ HAVING (t1.a>2) AND (MAX(c)>12);
+
+ =>
+
+ SELECT t1.a,MAX(t1.b)
+ FROM t1
+ WHERE (t1.a>2)
+ GROUP BY t1.a
+ HAVING (MAX(c)>12);
+
+ In details:
+ 1. Search for the condition cond_over_grouping_fields in
+ the HAVING clause of this select having that depends only on the
+ fields that are used in the GROUP BY of this select.
+ 2. Remove cond_over_grouping_fields from the HAVING clause having.
+ 3. Save cond_over_grouping_fields as a condition that can be pushed
+ into the WHERE clause of this select.
+
+ @note
+ This method is similar to st_select_lex::pushdown_cond_into_where_clause().
+
+ @retval TRUE if an error occurs
+ @retval FALSE otherwise
+*/
+
+Item *st_select_lex::pushdown_from_having_into_where(THD *thd, Item *having,
+ COND_EQUAL **having_equal)
+{
+ if (!having || !group_list.first)
+ return having;
+ if (!cond_pushdown_is_allowed())
+ return having;
+
+ st_select_lex *save_curr_select= thd->lex->current_select;
+ thd->lex->current_select= this;
+
+ /* Collect fields that are used in the GROUP BY of sl */
+ if (have_window_funcs())
+ {
+ if (group_list.first || join->implicit_grouping)
+ return having;
+ ORDER *common_partition_fields=
+ find_common_window_func_partition_fields(thd);
+ if (!common_partition_fields || collect_grouping_fields(thd))
+ return having;
+ }
+ else if (collect_grouping_fields(thd))
+ return having;
+
+ /*
+ 1. Search for the condition cond_over_grouping_fields in
+ the HAVING clause of this select having that depends only on the
+ fields that are used in the GROUP BY of this select.
+ */
+ thd->having_pushdown= true;
+ check_cond_extraction_for_grouping_fields(thd, having);
+ Item *cond_over_grouping_fields=
+ having->build_pushable_cond(thd,
+ &Item::pushable_equality_checker_for_having_pushdown,
+ (uchar *)this);
+
+ if (cond_over_grouping_fields)
+ {
+ /*
+ 2. Remove cond_over_grouping_fields from the HAVING clause having.
+ */
+ having= remove_pushed_top_conjuncts_for_having(thd, having);
+ cond_over_grouping_fields->walk(
+ &Item::cleanup_excluding_const_fields_processor, 0, 0);
+ /*
+ 3. Save cond_over_grouping_fields as a condition that can be pushed
+ into the WHERE clause of this select.
+ */
+ cond_pushed_into_where= cond_over_grouping_fields;
+
+ /*
+ Refresh having_equal as some of the multiple equalities of
+ having can be removed after pushdown.
+ */
+ *having_equal= 0;
+ if (having)
+ {
+ if (having->type() == Item::COND_ITEM &&
+ ((Item_cond*) having)->functype() == Item_func::COND_AND_FUNC)
+ {
+ Item_cond_and *and_having= (Item_cond_and *)having;
+ *having_equal= &and_having->m_cond_equal;
+ }
+ if (having->type() == Item::FUNC_ITEM &&
+ ((Item_func*) having)->functype() == Item_func::MULT_EQUAL_FUNC)
+ *having_equal= new (thd->mem_root) COND_EQUAL((Item_equal *)having,
+ thd->mem_root);
+ }
+ }
+ thd->lex->current_select= save_curr_select;
+ thd->having_pushdown= false;
+ return having;
+}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 89e3abe284f..0039248367a 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -1239,8 +1239,9 @@ class st_select_lex: public st_select_lex_node
With_element *find_table_def_in_with_clauses(TABLE_LIST *table);
bool check_unrestricted_recursive(bool only_standard_compliant);
bool check_subqueries_with_recursive_references();
- void collect_grouping_fields(THD *thd, ORDER *grouping_list);
- void check_cond_extraction_for_grouping_fields(Item *cond);
+ void collect_grouping_fields_for_derived(THD *thd, ORDER *grouping_list);
+ bool collect_grouping_fields(THD *thd);
+ void check_cond_extraction_for_grouping_fields(THD *thd, Item *cond);
Item *build_cond_for_grouping_fields(THD *thd, Item *cond,
bool no_to_clones);
@@ -1270,6 +1271,9 @@ class st_select_lex: public st_select_lex_node
Item **remaining_cond,
Item_transformer transformer,
uchar *arg);
+ void mark_or_conds_to_avoid_pushdown(Item *cond);
+ Item *pushdown_from_having_into_where(THD *thd, Item *having,
+ COND_EQUAL **having_equal);
private:
bool m_non_agg_field_used;
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 7d2e1bae741..61fda7345a9 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -229,6 +229,7 @@
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED (1ULL << 30)
#define OPTIMIZER_SWITCH_SPLIT_MATERIALIZED (1ULL << 31)
#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY (1ULL << 32)
+#define OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE (1ULL << 33)
#define OPTIMIZER_SWITCH_DEFAULT (OPTIMIZER_SWITCH_INDEX_MERGE | \
OPTIMIZER_SWITCH_INDEX_MERGE_UNION | \
@@ -256,7 +257,8 @@
OPTIMIZER_SWITCH_ORDERBY_EQ_PROP | \
OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_DERIVED | \
OPTIMIZER_SWITCH_SPLIT_MATERIALIZED | \
- OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY)
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FOR_SUBQUERY | \
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE)
/*
Replication uses 8 bytes to store SQL_MODE in the binary log. The day you
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 958ab0201e0..9a315020fc3 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1639,12 +1639,6 @@ JOIN::optimize_inner()
}
eq_list.empty();
- if (select_lex->cond_pushed_into_where)
- {
- conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
- if (conds && conds->fix_fields(thd, &conds))
- DBUG_RETURN(1);
- }
if (select_lex->cond_pushed_into_having)
{
having= and_conds(thd, having, select_lex->cond_pushed_into_having);
@@ -1656,7 +1650,39 @@ JOIN::optimize_inner()
select_lex->having_fix_field= 0;
}
}
-
+
+ having= optimize_cond(this, having, join_list, TRUE,
+ &having_value, &having_equal);
+ if (thd->is_error())
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from optimize_cond"));
+ DBUG_RETURN(1);
+ }
+
+ if (select_lex->cond_pushed_into_where)
+ {
+ conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
+ if (conds && conds->fix_fields(thd, &conds))
+ DBUG_RETURN(1);
+ select_lex->cond_pushed_into_where= 0;
+ }
+
+ if (thd->lex->sql_command == SQLCOM_SELECT &&
+ optimizer_flag(thd,
+ OPTIMIZER_SWITCH_COND_PUSHDOWN_FROM_HAVING_INTO_WHERE))
+ {
+ having=
+ select_lex->pushdown_from_having_into_where(thd, having, &having_equal);
+ if (select_lex->cond_pushed_into_where)
+ {
+ conds= and_conds(thd, conds, select_lex->cond_pushed_into_where);
+ if (conds && conds->fix_fields(thd, &conds))
+ DBUG_RETURN(1);
+ select_lex->cond_pushed_into_where= 0;
+ }
+ }
+
conds= optimize_cond(this, conds, join_list, FALSE,
&cond_value, &cond_equal, OPT_LINK_EQUAL_FIELDS);
@@ -1732,15 +1758,6 @@ JOIN::optimize_inner()
}
{
- having= optimize_cond(this, having, join_list, TRUE,
- &having_value, &having_equal);
-
- if (thd->is_error())
- {
- error= 1;
- DBUG_PRINT("error",("Error from optimize_cond"));
- DBUG_RETURN(1);
- }
if (select_lex->where)
{
select_lex->cond_value= cond_value;
@@ -1755,7 +1772,7 @@ JOIN::optimize_inner()
}
if (cond_value == Item::COND_FALSE || having_value == Item::COND_FALSE ||
(!unit->select_limit_cnt && !(select_options & OPTION_FOUND_ROWS)))
- { /* Impossible cond */
+ { /* Impossible cond */
DBUG_PRINT("info", (having_value == Item::COND_FALSE ?
"Impossible HAVING" : "Impossible WHERE"));
zero_result_cause= having_value == Item::COND_FALSE ?
@@ -1767,6 +1784,7 @@ JOIN::optimize_inner()
}
}
+
#ifdef WITH_PARTITION_STORAGE_ENGINE
{
TABLE_LIST *tbl;
@@ -2028,6 +2046,22 @@ int JOIN::optimize_stage2()
"after substitute_best_equal",
QT_ORDINARY););
}
+ if (having)
+ {
+ having= substitute_for_best_equal_field(thd, NO_PARTICULAR_TAB, having,
+ having_equal, map2table);
+ if (thd->is_error())
+ {
+ error= 1;
+ DBUG_PRINT("error",("Error from substitute_for_best_equal"));
+ DBUG_RETURN(1);
+ }
+ having->update_used_tables();
+ DBUG_EXECUTE("having",
+ print_where(having,
+ "after substitute_best_equal",
+ QT_ORDINARY););
+ }
/*
Perform the optimization on fields evaluation mentioned above
@@ -4776,7 +4810,11 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
{
if (*s->on_expr_ref && s->cond_equal &&
s->cond_equal->upper_levels == orig_cond_equal)
+ {
s->cond_equal->upper_levels= join->cond_equal;
+ if (s->cond_equal->upper_levels)
+ s->cond_equal->upper_levels->references++;
+ }
}
}
}
@@ -13433,14 +13471,16 @@ bool check_simple_equality(THD *thd, const Item::Context &ctx,
Item *orig_left_item= left_item;
Item *orig_right_item= right_item;
if (left_item->type() == Item::REF_ITEM &&
- ((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
+ (((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF ||
+ ((Item_ref*)left_item)->ref_type() == Item_ref::REF))
{
if (((Item_ref*)left_item)->get_depended_from())
return FALSE;
left_item= left_item->real_item();
}
if (right_item->type() == Item::REF_ITEM &&
- ((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF)
+ (((Item_ref*)right_item)->ref_type() == Item_ref::VIEW_REF ||
+ ((Item_ref*)right_item)->ref_type() == Item_ref::REF))
{
if (((Item_ref*)right_item)->get_depended_from())
return FALSE;
@@ -13998,6 +14038,8 @@ COND *Item_func_eq::build_equal_items(THD *thd,
set_if_bigger(thd->lex->current_select->max_equal_elems,
item_equal->n_field_items());
item_equal->upper_levels= inherited;
+ if (inherited)
+ inherited->references++;
if (cond_equal_ref)
*cond_equal_ref= new (thd->mem_root) COND_EQUAL(item_equal,
thd->mem_root);
@@ -14031,6 +14073,8 @@ COND *Item_func_eq::build_equal_items(THD *thd,
and_cond->update_used_tables();
if (cond_equal_ref)
*cond_equal_ref= &and_cond->m_cond_equal;
+ if (inherited)
+ inherited->references++;
return and_cond;
}
}
@@ -14156,6 +14200,8 @@ static COND *build_equal_items(JOIN *join, COND *cond,
if (*cond_equal_ref)
{
(*cond_equal_ref)->upper_levels= inherited;
+ if (inherited)
+ inherited->references++;
inherited= *cond_equal_ref;
}
}
@@ -14488,11 +14534,8 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels,
*/
Item *head_item= (!item_const && current_sjm &&
current_sjm_head != field_item) ? current_sjm_head: head;
- Item *head_real_item= head_item->real_item();
- if (head_real_item->type() == Item::FIELD_ITEM)
- head_item= head_real_item;
-
- eq_item= new (thd->mem_root) Item_func_eq(thd, field_item->real_item(), head_item);
+
+ eq_item= new (thd->mem_root) Item_func_eq(thd, field_item, head_item);
if (!eq_item || eq_item->set_cmp_func())
return 0;
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 0331343ccef..0f50de4fc29 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -2473,6 +2473,7 @@ export const char *optimizer_switch_names[]=
"condition_pushdown_for_derived",
"split_materialized",
"condition_pushdown_for_subquery",
+ "condition_pushdown_from_having_into_where",
"default",
NullS
};
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
index 2a0ee4fa3e1..1378dccab5e 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_1_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
create table t (id int not null, x int not null, y int not null, primary key(id), key(x)) engine=innodb;
insert into t values (0,0,0),(1,1,1),(2,2,2),(3,2,3),(4,2,4);
explain select x,id from t force index (x) where x=0 and id=0;
diff --git a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
index fb998e3a6ad..336cde11382 100644
--- a/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
+++ b/storage/tokudb/mysql-test/tokudb/r/ext_key_2_innodb.result
@@ -1,7 +1,7 @@
drop table if exists t;
select @@optimizer_switch;
@@optimizer_switch
-index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on
+index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=off,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,condition_pushdown_from_having_into_where=on
create table t (a int not null, b int not null, c int not null, d int not null, primary key(a,b), key(c,a)) engine=innodb;
insert into t values (0,0,0,0),(0,1,0,1);
explain select c,a,b from t where c=0 and a=0 and b=1;
1
0
revision-id: 95486e132c38d20d6666a7d783d67d86bdb67e87 (mariadb-10.0.35-43-g95486e132c3)
parent(s): 3661d9882224dd485556ce937c1294eaeda02ef8
author: Oleksandr Byelkin
committer: Oleksandr Byelkin
timestamp: 2018-06-18 15:19:06 +0200
message:
ccc
---
mysql-test/t/test.test | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++
sql/item_subselect.cc | 2 +-
sql/sql_select.cc | 3 +++
sql/sql_update.cc | 18 ++++++++++++++--
4 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/mysql-test/t/test.test b/mysql-test/t/test.test
new file mode 100644
index 00000000000..ac16d08c167
--- /dev/null
+++ b/mysql-test/t/test.test
@@ -0,0 +1,57 @@
+--source include/have_innodb.inc
+
+--connect (con2,localhost,root,,test)
+CREATE TABLE t1 (
+ f1_1 DATE,
+ f1_2 DATE NOT NULL,
+ f1_3 VARCHAR(10),
+ f1_4 INT UNSIGNED,
+ f_ind DATE NOT NULL,
+ KEY(f_ind)
+) ENGINE=InnoDB;
+CREATE OR REPLACE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1;
+INSERT INTO t1 VALUES (NULL, '0000-00-00', 'z', 2, '2001-03-01'), ('0000-00-00', '2001-08-25', 'p', 2, '2006-03-03');
+
+CREATE TABLE t2 (f2 INT UNSIGNED) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (1),(2);
+
+CREATE TABLE t3 (
+ pk INT,
+ f3_1 VARCHAR(10),
+ f3_2 INT UNSIGNED,
+primary key (pk)
+) ENGINE=innodb;
+CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3;
+INSERT INTO t3 VALUES (1, NULL, 9), (2, 'v', 0);
+
+--connect (con1,localhost,root,,test)
+SET DEBUG_SYNC= 'multi_update_before_loop1 SIGNAL update1 WAIT_FOR continue1';
+SET DEBUG_SYNC= 'multi_update_after_loop SIGNAL update3 WAIT_FOR continue3';
+--send
+UPDATE t1, t2, t3 SET pk = -1;
+
+--connection con2
+SET DEBUG_SYNC= 'now WAIT_FOR update1';
+SET DEBUG_SYNC= 'multi_update_before_loop2 SIGNAL update2 WAIT_FOR continue2';
+--send
+UPDATE v1 LEFT JOIN t1 ON (v1.f1_2 = t1.f1_1) SET v1.f1_4 = 1 WHERE EXISTS ( SELECT * FROM t2 INNER JOIN v3 ON (f3_2 = f2) WHERE f3_1 = t1.f1_3 OR f3_2 > f2 );
+
+--connection default
+SET DEBUG_SYNC= 'now WAIT_FOR update2';
+SET DEBUG_SYNC= 'now SIGNAL continue1';
+SET DEBUG_SYNC= 'now WAIT_FOR update3';
+SET DEBUG_SYNC= 'now SIGNAL continue3';
+--connection con1
+--error ER_DUP_ENTRY
+--reap
+
+SET DEBUG_SYNC= 'now SIGNAL continue2';
+
+
+--connection con2
+--reap
+
+--connection default
+SET DEBUG_SYNC= 'reset';
+drop view v1,v3;
+drop table t1,t2,t3;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index a8dfdff9809..808cbf4a103 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -3781,7 +3781,7 @@ int subselect_single_select_engine::exec()
}
thd->where= save_where;
thd->lex->current_select= save_select;
- DBUG_RETURN(0);
+ DBUG_RETURN(join->error);
}
int subselect_union_engine::exec()
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index f7f6287c3fd..8d6927cfac8 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -18155,6 +18155,9 @@ evaluate_join_record(JOIN *join, JOIN_TAB *join_tab,
DBUG_RETURN(NESTED_LOOP_OK);
}
}
+ /* check for errors evaluating the condition */
+ if (join->thd->is_error())
+ DBUG_RETURN(NESTED_LOOP_ERROR);
}
/*
Check whether join_tab is not the last inner table
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 94fbe0924b6..b72ea886a0f 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -527,7 +527,7 @@ int mysql_update(THD *thd,
DBUG_EXECUTE_IF("show_explain_probe_update_exec_start",
dbug_serve_apcs(thd, 1););
-
+
if (!(select && select->quick))
status_var_increment(thd->status_var.update_scan_count);
@@ -1589,6 +1589,8 @@ bool mysql_multi_update(THD *thd,
thd->abort_on_warning= !ignore && thd->is_strict_mode();
List<Item> total_list;
+ DEBUG_SYNC(thd, "multi_update_before_loop1");
+ DEBUG_SYNC(thd, "multi_update_before_loop2");
res= mysql_select(thd, &select_lex->ref_pointer_array,
table_list, select_lex->with_wild,
total_list,
@@ -1597,6 +1599,7 @@ bool mysql_multi_update(THD *thd,
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
OPTION_SETUP_TABLES_DONE,
*result, unit, select_lex);
+ DEBUG_SYNC(thd, "multi_update_after_loop");
DBUG_PRINT("info",("res: %d report_error: %d", res, (int) thd->is_error()));
res|= thd->is_error();
@@ -2151,11 +2154,22 @@ int multi_update::send_data(List<Item> ¬_used_values)
}
else
{
- if (error == HA_ERR_RECORD_IS_THE_SAME)
+ if (error == HA_ERR_RECORD_IS_THE_SAME ||
+ (error && ignore &&
+ !table->file->is_fatal_error(error, HA_CHECK_ALL)))
{
error= 0;
updated--;
}
+ else
+ {
+ if (error)
+ {
+ table->file->print_error(error, MYF(0));
+ DBUG_RETURN(1);
+ }
+ }
+
/* non-transactional or transactional table got modified */
/* either multi_update class' flag is raised in its branch */
if (table->file->has_transactions())
1
0