From 14ddcb1ff27dbb7248c63a01756852404b6d5209 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 2 Aug 2018 22:28:04 +0200 Subject: [PATCH 01/14] Bug#27407480: AUTOMATIC_SP_PRIVILEGES REQUIRES NEED THE INSERT PRIVILEGES FOR MYSQL.USER TABLE A test case and a followup fix --- mysql-test/r/sp-security.result | 21 +++++++++++++++++++++ mysql-test/t/sp-security.test | 19 ++++++++++++++++++- sql/sql_acl.cc | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index 88908b05f46..39237b7f322 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -617,3 +617,24 @@ SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci # Connection default DROP USER user2@localhost; DROP DATABASE db1; +create user foo@local_ost; +create user foo@`local\_ost` identified by 'nevermore'; +create database foodb; +grant create routine on foodb.* to foo@local_ost; +select user(), current_user(); +user() current_user() +foo@localhost foo@local_ost +show grants; +Grants for foo@local_ost +GRANT USAGE ON *.* TO 'foo'@'local_ost' +GRANT CREATE ROUTINE ON `foodb`.* TO 'foo'@'local_ost' +create procedure fooproc() select 'i am fooproc'; +show grants; +Grants for foo@local_ost +GRANT USAGE ON *.* TO 'foo'@'local_ost' +GRANT CREATE ROUTINE ON `foodb`.* TO 'foo'@'local_ost' +GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `test`.`fooproc` TO 'foo'@'local_ost' +drop user foo@local_ost; +drop user foo@`local\_ost`; +drop procedure fooproc; +drop database foodb; diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index ca4e6b04f13..3769bb3b4bf 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -995,7 +995,24 @@ disconnect con2; DROP USER user2@localhost; DROP DATABASE db1; +# +# Bug#27407480: AUTOMATIC_SP_PRIVILEGES REQUIRES NEED THE INSERT PRIVILEGES FOR MYSQL.USER TABLE +# +create user foo@local_ost; +create user foo@`local\_ost` identified by 'nevermore'; +create database foodb; +grant create routine on foodb.* to foo@local_ost; +connect con1,localhost,foo; +select user(), current_user(); +show grants; +create procedure fooproc() select 'i am fooproc'; +show grants; +disconnect con1; +connection default; +drop user foo@local_ost; +drop user foo@`local\_ost`; +drop procedure fooproc; +drop database foodb; # Wait till all disconnects are completed --source include/wait_until_count_sessions.inc - diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 24740a0695a..066e7e4c7f4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -7190,7 +7190,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, mysql_mutex_lock(&acl_cache->lock); if ((au= find_acl_user(combo->host.str= (char *) sctx->priv_host, - combo->user.str, FALSE))) + combo->user.str, TRUE))) goto found_acl; mysql_mutex_unlock(&acl_cache->lock); From ff34436a2ecc30a177cb304fd1dce928d8709f45 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 3 Aug 2018 13:04:43 +0200 Subject: [PATCH 02/14] Bug#27230925: HANDLE_FATAL_SIGNAL (SIG=11) IN SHOW_ROUTINE_GRANTS test case --- mysql-test/r/grant.result | 21 +++++++++++++++++++++ mysql-test/t/grant.test | 21 +++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index 85e42ea96ee..60f2eb90e2d 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -2581,3 +2581,24 @@ foo@localhost foo@127.0.0.1 # Clean-up DROP USER foo@'127.0.0.1'; # End of Bug#12766319 +create user foo@localhost; +create database foodb; +grant create routine on foodb.* to foo@localhost; +create procedure fooproc() select 'i am fooproc'; +show grants; +Grants for foo@localhost +GRANT USAGE ON *.* TO 'foo'@'localhost' +GRANT CREATE ROUTINE ON `foodb`.* TO 'foo'@'localhost' +GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `test`.`fooproc` TO 'foo'@'localhost' +rename table mysql.procs_priv to mysql.procs_priv1; +flush privileges; +ERROR 42S02: Table 'mysql.procs_priv' doesn't exist +show grants for foo@localhost; +Grants for foo@localhost +GRANT USAGE ON *.* TO 'foo'@'localhost' +GRANT CREATE ROUTINE ON `foodb`.* TO 'foo'@'localhost' +GRANT EXECUTE, ALTER ROUTINE ON PROCEDURE `test`.`fooproc` TO 'foo'@'localhost' +rename table mysql.procs_priv1 to mysql.procs_priv; +drop user foo@localhost; +drop procedure fooproc; +drop database foodb; diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 5de3328944a..220cc0a248c 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -2244,5 +2244,26 @@ DROP USER foo@'127.0.0.1'; --echo # End of Bug#12766319 +# +# Bug#27230925: HANDLE_FATAL_SIGNAL (SIG=11) IN SHOW_ROUTINE_GRANTS +# +create user foo@localhost; +create database foodb; +grant create routine on foodb.* to foo@localhost; +connect con1,localhost,foo; +create procedure fooproc() select 'i am fooproc'; +show grants; +disconnect con1; +connection default; +rename table mysql.procs_priv to mysql.procs_priv1; +error ER_NO_SUCH_TABLE; +flush privileges; +show grants for foo@localhost; +rename table mysql.procs_priv1 to mysql.procs_priv; +drop user foo@localhost; +drop procedure fooproc; +drop database foodb; + + # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc From b7944343dd3f0bfd16023604611f7be811b994b6 Mon Sep 17 00:00:00 2001 From: Ian Gilfillan Date: Mon, 10 Sep 2018 14:26:11 +0200 Subject: [PATCH 03/14] Update contributors --- CREDITS | 4 +++- mysql-test/r/contributors.result | 4 +++- sql/contributors.h | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CREDITS b/CREDITS index 1788b6304fe..9f03f7fc24e 100644 --- a/CREDITS +++ b/CREDITS @@ -10,9 +10,11 @@ Microsoft https://microsoft.com/ (2017) Tencent Cloud https://cloud.tencent.com (2017) Development Bank of Singapore https://dbs.com (2016) IBM https://www.ibm.com (2017) +Tencent Games http://game.qq.com/ (2018) Visma https://visma.com (2015) -Acronis http://acronis.com (2016) +Acronis https://acronis.com (2016) Nexedi https://www.nexedi.com (2016) +Percona https://www.percona.com (2018) Tencent Game DBA http://tencentdba.com/about (2016) Tencent TDSQL http://tdsql.org (2016) Verkkokauppa.com https://www.verkkokauppa.com (2015) diff --git a/mysql-test/r/contributors.result b/mysql-test/r/contributors.result index 36d033f4cb3..3e4bf5f0d43 100644 --- a/mysql-test/r/contributors.result +++ b/mysql-test/r/contributors.result @@ -8,12 +8,14 @@ MariaDB Corporation https://mariadb.com Founding member, Platinum Sponsor of the Visma https://visma.com Gold Sponsor of the MariaDB Foundation DBS https://dbs.com Gold Sponsor of the MariaDB Foundation IBM https://www.ibm.com Gold Sponsor of the MariaDB Foundation +Tencent Games http://game.qq.com/ Gold Sponsor of the MariaDB Foundation Nexedi https://www.nexedi.com Silver Sponsor of the MariaDB Foundation -Acronis http://www.acronis.com Silver Sponsor of the MariaDB Foundation +Acronis https://www.acronis.com Silver Sponsor of the MariaDB Foundation Verkkokauppa.com https://www.verkkokauppa.com Bronze Sponsor of the MariaDB Foundation Virtuozzo https://virtuozzo.com Bronze Sponsor of the MariaDB Foundation Tencent Game DBA http://tencentdba.com/about Bronze Sponsor of the MariaDB Foundation Tencent TDSQL http://tdsql.org Bronze Sponsor of the MariaDB Foundation +Percona https://www.percona.com/ Bronze Sponsor of the MariaDB Foundation Google USA Sponsoring encryption, parallel replication and GTID Facebook USA Sponsoring non-blocking API, LIMIT ROWS EXAMINED etc Ronald Bradford Brisbane, Australia EFF contribution for UC2006 Auction diff --git a/sql/contributors.h b/sql/contributors.h index a0d05af3fa6..69f8fa6bd4c 100644 --- a/sql/contributors.h +++ b/sql/contributors.h @@ -45,12 +45,14 @@ struct show_table_contributors_st show_table_contributors[]= { {"Visma", "https://visma.com", "Gold Sponsor of the MariaDB Foundation"}, {"DBS", "https://dbs.com", "Gold Sponsor of the MariaDB Foundation"}, {"IBM", "https://www.ibm.com", "Gold Sponsor of the MariaDB Foundation"}, + {"Tencent Games", "http://game.qq.com/", "Gold Sponsor of the MariaDB Foundation"}, {"Nexedi", "https://www.nexedi.com", "Silver Sponsor of the MariaDB Foundation"}, - {"Acronis", "http://www.acronis.com", "Silver Sponsor of the MariaDB Foundation"}, + {"Acronis", "https://www.acronis.com", "Silver Sponsor of the MariaDB Foundation"}, {"Verkkokauppa.com", "https://www.verkkokauppa.com", "Bronze Sponsor of the MariaDB Foundation"}, {"Virtuozzo", "https://virtuozzo.com", "Bronze Sponsor of the MariaDB Foundation"}, {"Tencent Game DBA", "http://tencentdba.com/about", "Bronze Sponsor of the MariaDB Foundation"}, {"Tencent TDSQL", "http://tdsql.org", "Bronze Sponsor of the MariaDB Foundation"}, + {"Percona", "https://www.percona.com/", "Bronze Sponsor of the MariaDB Foundation"}, /* Sponsors of important features */ {"Google", "USA", "Sponsoring encryption, parallel replication and GTID"}, From e43bc02e7b2752f0deb88cd1edc24d827e01dca9 Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Mon, 16 Jul 2018 15:35:16 +0300 Subject: [PATCH 04/14] MDEV-16741 Assertion `m_extra_cache' failed in ha_partition::late_extra_cache multi_delete sets TABLE::no_cache=1 and should set it to 0 when DELETE is done. --- mysql-test/suite/parts/r/update_and_cache.result | 7 +++++++ mysql-test/suite/parts/t/update_and_cache.test | 12 ++++++++++++ sql/sql_delete.cc | 1 + sql/sql_update.cc | 2 +- 4 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 mysql-test/suite/parts/r/update_and_cache.result create mode 100644 mysql-test/suite/parts/t/update_and_cache.test diff --git a/mysql-test/suite/parts/r/update_and_cache.result b/mysql-test/suite/parts/r/update_and_cache.result new file mode 100644 index 00000000000..52f13e66702 --- /dev/null +++ b/mysql-test/suite/parts/r/update_and_cache.result @@ -0,0 +1,7 @@ +CREATE TABLE t1 (pk INT PRIMARY KEY, a INT); +INSERT INTO t1 VALUES (1,10),(2,20); +CREATE TABLE t2 (b INT) PARTITION BY KEY (b) PARTITIONS 2; +INSERT INTO t2 VALUES (1),(2); +DELETE t2 FROM t2 WHERE b BETWEEN 5 AND 9; +UPDATE t2 JOIN t1 SET b = 5; +DROP TABLE t1, t2; diff --git a/mysql-test/suite/parts/t/update_and_cache.test b/mysql-test/suite/parts/t/update_and_cache.test new file mode 100644 index 00000000000..08ade807422 --- /dev/null +++ b/mysql-test/suite/parts/t/update_and_cache.test @@ -0,0 +1,12 @@ +--source include/have_partition.inc + +CREATE TABLE t1 (pk INT PRIMARY KEY, a INT); +INSERT INTO t1 VALUES (1,10),(2,20); + +CREATE TABLE t2 (b INT) PARTITION BY KEY (b) PARTITIONS 2; +INSERT INTO t2 VALUES (1),(2); + +DELETE t2 FROM t2 WHERE b BETWEEN 5 AND 9; +UPDATE t2 JOIN t1 SET b = 5; + +DROP TABLE t1, t2; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 8aca415a9d0..cdd7350cb0c 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -744,6 +744,7 @@ multi_delete::~multi_delete() { TABLE *table= table_being_deleted->table; table->no_keyread=0; + table->no_cache= 0; } for (uint counter= 0; counter < num_of_tables; counter++) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index e42f6a4ff76..fe007d5823d 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1868,7 +1868,7 @@ multi_update::~multi_update() TABLE_LIST *table; for (table= update_tables ; table; table= table->next_local) { - table->table->no_keyread= table->table->no_cache= 0; + table->table->no_keyread= 0; if (ignore) table->table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); } From 327b2717219aaa8f9033895a2351a6ccd4655116 Mon Sep 17 00:00:00 2001 From: Sergey Vojtovich Date: Fri, 7 Sep 2018 14:50:10 +0400 Subject: [PATCH 05/14] MDEV-14410 - Assertion `table->pos_in_locked_tables == __null || table->pos_in_locked_tables->table == table' failed in mark_used_tables_as_free_for_reuse Assertion failure can be triggered by some DDL executed under LOCK TABLES that holds lock for DDL target table multiple times (either explicitly or implcitly). When closing all table instances for given table (e.g. when preparing for table removal during CREATE OR REPLACE), only one instance was removed from m_locked_tables list. Later we attempt to re-insert one of the instances in mysql_create_table()/ add_back_last_deleted_lock(), which wasn't actually removed. This leads to m_locks_tables corruption, specifically loss of all following elements. Then UNLOCK TABLE won't reset some table instances properly (specifically pos_in_locked_tables), since they're not present in m_locked_tables. Eventually such table instance gets released to table cache and then re-used by subsequent statement, which triggers this assertion failure. --- mysql-test/r/create_or_replace.result | 15 +++++++++++++++ mysql-test/t/create_or_replace.test | 21 +++++++++++++++++++++ sql/sql_base.cc | 3 ++- sql/table_cache.cc | 1 + 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/create_or_replace.result b/mysql-test/r/create_or_replace.result index 0d171f9f87a..646183ebcb1 100644 --- a/mysql-test/r/create_or_replace.result +++ b/mysql-test/r/create_or_replace.result @@ -473,3 +473,18 @@ ERROR HY000: Table 't1' was not locked with LOCK TABLES UNLOCK TABLES; DROP FUNCTION f1; DROP TABLE t1; +# +# MDEV-14410 - Assertion `table->pos_in_locked_tables == __null || +# table->pos_in_locked_tables->table == table' failed in +# mark_used_tables_as_free_for_reuse +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT); +CREATE TABLE t3 (c INT); +CREATE TRIGGER tr1 BEFORE INSERT ON t3 FOR EACH ROW INSERT INTO t1 VALUES (); +CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW INSERT INTO t3 SELECT * FROM t1; +LOCK TABLE t1 WRITE, t2 WRITE; +CREATE OR REPLACE TABLE t1 (i INT); +UNLOCK TABLES; +INSERT INTO t2 VALUES (1); +DROP TABLE t1, t2, t3; diff --git a/mysql-test/t/create_or_replace.test b/mysql-test/t/create_or_replace.test index 5ebb3031be3..8c8ed1c9886 100644 --- a/mysql-test/t/create_or_replace.test +++ b/mysql-test/t/create_or_replace.test @@ -423,3 +423,24 @@ UNLOCK TABLES; DROP FUNCTION f1; DROP TABLE t1; + + +--echo # +--echo # MDEV-14410 - Assertion `table->pos_in_locked_tables == __null || +--echo # table->pos_in_locked_tables->table == table' failed in +--echo # mark_used_tables_as_free_for_reuse +--echo # +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT); +CREATE TABLE t3 (c INT); + +CREATE TRIGGER tr1 BEFORE INSERT ON t3 FOR EACH ROW INSERT INTO t1 VALUES (); +CREATE TRIGGER tr2 BEFORE INSERT ON t2 FOR EACH ROW INSERT INTO t3 SELECT * FROM t1; + +LOCK TABLE t1 WRITE, t2 WRITE; +CREATE OR REPLACE TABLE t1 (i INT); +UNLOCK TABLES; +INSERT INTO t2 VALUES (1); + +# Cleanup +DROP TABLE t1, t2, t3; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 32ce3c3a793..1a17c8e39d5 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -806,6 +806,7 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, uint key_length= share->table_cache_key.length; const char *db= key; const char *table_name= db + share->db.length + 1; + bool remove_from_locked_tables= extra != HA_EXTRA_NOT_USED; memcpy(key, share->table_cache_key.str, key_length); @@ -819,7 +820,7 @@ close_all_tables_for_name(THD *thd, TABLE_SHARE *share, { thd->locked_tables_list.unlink_from_list(thd, table->pos_in_locked_tables, - extra != HA_EXTRA_NOT_USED); + remove_from_locked_tables); /* Inform handler that there is a drop table or a rename going on */ if (extra != HA_EXTRA_NOT_USED && table->db_stat) { diff --git a/sql/table_cache.cc b/sql/table_cache.cc index bdb7914c32b..f13d7183a99 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -376,6 +376,7 @@ bool tc_release_table(TABLE *table) { DBUG_ASSERT(table->in_use); DBUG_ASSERT(table->file); + DBUG_ASSERT(!table->pos_in_locked_tables); if (table->needs_reopen() || tc_records() > tc_size) { From 0c6455aa4658790439a58956f05df200a5e380b8 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 20 Sep 2018 16:02:58 +0400 Subject: [PATCH 06/14] MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result --- mysql-test/r/func_time.result | 45 ++++++++++++++++++++++++++++++++++ mysql-test/r/type_float.result | 36 +++++++++++++++++++++++++++ mysql-test/t/func_time.test | 21 ++++++++++++++++ mysql-test/t/type_float.test | 29 ++++++++++++++++++++++ sql/field.cc | 3 ++- sql/item.cc | 8 ++++-- sql/item_func.cc | 5 +++- sql/item_func.h | 10 ++++++-- sql/item_sum.cc | 6 +++-- sql/item_sum.h | 19 +++++++++++--- sql/item_timefunc.cc | 22 +++++------------ sql/sql_error.h | 7 +++--- sql/sql_type_int.h | 40 ++++++++++++++++++++++++++++++ 13 files changed, 219 insertions(+), 32 deletions(-) create mode 100644 sql/sql_type_int.h diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 3f0d99e1315..1db897d4ec0 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -2661,5 +2661,50 @@ SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')); PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')) 24257 # +# MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result +# +SELECT +MAKETIME(1e10,0,0), +MAKETIME(-1e10,0,0), +MAKETIME(1e50,0,0), +MAKETIME(-1e50,0,0), +MAKETIME(COALESCE(1e50),0,0), +MAKETIME(COALESCE(-1e50),0,0); +MAKETIME(1e10,0,0) 838:59:59 +MAKETIME(-1e10,0,0) -838:59:59 +MAKETIME(1e50,0,0) 838:59:59 +MAKETIME(-1e50,0,0) -838:59:59 +MAKETIME(COALESCE(1e50),0,0) 838:59:59 +MAKETIME(COALESCE(-1e50),0,0) -838:59:59 +Warnings: +Level Warning +Code 1292 +Message Truncated incorrect time value: '10000000000:00:00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '-10000000000:00:00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '9223372036854775807:00:00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '-9223372036854775808:00:00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '9223372036854775807:00:00' +Level Warning +Code 1292 +Message Truncated incorrect time value: '-9223372036854775808:00:00' +CREATE TABLE t1 (a FLOAT); +INSERT INTO t1 VALUES (1e30),(-1e30); +SELECT MAKETIME(a,0,0) FROM t1; +MAKETIME(a,0,0) +838:59:59 +-838:59:59 +Warnings: +Warning 1292 Truncated incorrect time value: '9223372036854775807:00:00' +Warning 1292 Truncated incorrect time value: '-9223372036854775808:00:00' +DROP TABLE t1; +# # End of 5.5 tests # diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index f41c2e7688b..f8574167de3 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -447,3 +447,39 @@ End of 5.0 tests select format(truncate('1.7976931348623157E+308',-12),1,'fr_BE') as foo; foo 0 +# +# MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result +# +SELECT LEFT('a',EXP(50)); +LEFT('a',EXP(50)) +a +SELECT LEFT('a', COALESCE(1e30)); +LEFT('a', COALESCE(1e30)) +a +CREATE TABLE t1 (a FLOAT); +INSERT INTO t1 VALUES (1e30); +SELECT LEFT('a',a), LEFT('a',1e30) FROM t1; +LEFT('a',a) LEFT('a',1e30) +a a +DROP TABLE t1; +PREPARE stmt FROM 'SELECT LEFT(111,?)'; +SET @a=1e30; +EXECUTE stmt USING @a; +LEFT(111,?) +111 +DEALLOCATE PREPARE stmt; +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT LEFT('a',(SELECT 1e30 FROM t1 LIMIT 1)); +LEFT('a',(SELECT 1e30 FROM t1 LIMIT 1)) +a +DROP TABLE t1; +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES (1e30),(0); +SELECT LEFT('a', SUM(a)) FROM t1; +LEFT('a', SUM(a)) +a +SELECT LEFT('a', AVG(a)) FROM t1; +LEFT('a', AVG(a)) +a +DROP TABLE t1; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 361eff170fb..10b2b2958c2 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -1634,6 +1634,27 @@ SELECT SEC_TO_TIME(MAKEDATE(0,RAND(~0))); # SELECT PERIOD_DIFF(2018, AES_ENCRYPT('Rae Bareli', 'Rae Bareli')); + +--echo # +--echo # MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result +--echo # + +--vertical_results +SELECT + MAKETIME(1e10,0,0), + MAKETIME(-1e10,0,0), + MAKETIME(1e50,0,0), + MAKETIME(-1e50,0,0), + MAKETIME(COALESCE(1e50),0,0), + MAKETIME(COALESCE(-1e50),0,0); +--horizontal_results + +CREATE TABLE t1 (a FLOAT); +INSERT INTO t1 VALUES (1e30),(-1e30); +SELECT MAKETIME(a,0,0) FROM t1; +DROP TABLE t1; + + --echo # --echo # End of 5.5 tests --echo # diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index b33c51566a0..fa45b1041d8 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -331,3 +331,32 @@ eval select concat((truncate((-1.7976931348623157E+307),(0x1e))), --echo # select format(truncate('1.7976931348623157E+308',-12),1,'fr_BE') as foo; + + +--echo # +--echo # MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result +--echo # + +SELECT LEFT('a',EXP(50)); +SELECT LEFT('a', COALESCE(1e30)); + +CREATE TABLE t1 (a FLOAT); +INSERT INTO t1 VALUES (1e30); +SELECT LEFT('a',a), LEFT('a',1e30) FROM t1; +DROP TABLE t1; + +PREPARE stmt FROM 'SELECT LEFT(111,?)'; +SET @a=1e30; +EXECUTE stmt USING @a; +DEALLOCATE PREPARE stmt; + +CREATE TABLE t1 (a INT); +INSERT INTO t1 VALUES (1),(2),(3); +SELECT LEFT('a',(SELECT 1e30 FROM t1 LIMIT 1)); +DROP TABLE t1; + +CREATE TABLE t1 (a DOUBLE); +INSERT INTO t1 VALUES (1e30),(0); +SELECT LEFT('a', SUM(a)) FROM t1; +SELECT LEFT('a', AVG(a)) FROM t1; +DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 5b111ab5e03..28b3d743ed8 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3948,7 +3948,8 @@ longlong Field_float::val_int(void) { float j; float4get(j,ptr); - return (longlong) rint(j); + bool error; + return double_to_longlong(j, false, &error); } diff --git a/sql/item.cc b/sql/item.cc index 745cbf31f0c..e1afc339cc2 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3692,7 +3692,10 @@ longlong Item_param::val_int() { switch (state) { case REAL_VALUE: - return (longlong) rint(value.real); + { + bool error; + return double_to_longlong(value.real, unsigned_flag, &error); + } case INT_VALUE: return value.integer; case DECIMAL_VALUE: @@ -9231,7 +9234,8 @@ longlong Item_cache_real::val_int() DBUG_ASSERT(fixed == 1); if (!has_value()) return 0; - return (longlong) rint(value); + bool error; + return double_to_longlong(value, unsigned_flag, &error); } diff --git a/sql/item_func.cc b/sql/item_func.cc index 8b3c72dd328..73fc099252b 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -999,7 +999,10 @@ longlong Item_func_hybrid_result_type::val_int() case INT_RESULT: return int_op(); case REAL_RESULT: - return (longlong) rint(real_op()); + { + bool error; + return double_to_longlong(real_op(), unsigned_flag, &error); + } case STRING_RESULT: { if (is_temporal_type(field_type())) diff --git a/sql/item_func.h b/sql/item_func.h index 3a609fc0fe0..64b3b5cfb75 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -411,7 +411,11 @@ public: String *val_str(String*str); my_decimal *val_decimal(my_decimal *decimal_value); longlong val_int() - { DBUG_ASSERT(fixed == 1); return (longlong) rint(val_real()); } + { + DBUG_ASSERT(fixed == 1); + bool error; + return double_to_longlong(val_real(), unsigned_flag, &error); + } enum Item_result result_type () const { return REAL_RESULT; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } @@ -1465,7 +1469,9 @@ class Item_func_udf_float :public Item_udf_func longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) rint(Item_func_udf_float::val_real()); + bool error; + return double_to_longlong(Item_func_udf_float::val_real(), + unsigned_flag, &error); } my_decimal *val_decimal(my_decimal *dec_buf) { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 16334cd7b30..22fbe2bacfe 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1434,7 +1434,8 @@ longlong Item_sum_sum::val_int() &result); return result; } - return (longlong) rint(val_real()); + bool error; + return double_to_longlong(val_real(), unsigned_flag, &error); } @@ -2648,7 +2649,8 @@ double Item_avg_field::val_real() longlong Item_avg_field::val_int() { - return (longlong) rint(val_real()); + bool error; + return double_to_longlong(val_real(), unsigned_flag, &error); } diff --git a/sql/item_sum.h b/sql/item_sum.h index dcc3e494f82..b0bca5e7ad2 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -699,7 +699,9 @@ public: longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) rint(val_real()); /* Real as default */ + // Real as default + bool error; + return double_to_longlong(val_real(), unsigned_flag, &error); } String *val_str(String*str); my_decimal *val_decimal(my_decimal *); @@ -867,7 +869,11 @@ public: bool add(); double val_real(); // In SPs we might force the "wrong" type with select into a declare variable - longlong val_int() { return (longlong) rint(val_real()); } + longlong val_int() + { + bool error; + return double_to_longlong(val_real(), unsigned_flag, &error); + } my_decimal *val_decimal(my_decimal *); String *val_str(String *str); void reset_field(); @@ -904,7 +910,10 @@ public: enum Type type() const {return FIELD_VARIANCE_ITEM; } double val_real(); longlong val_int() - { /* can't be fix_fields()ed */ return (longlong) rint(val_real()); } + { /* can't be fix_fields()ed */ + bool error; + return double_to_longlong(val_real(), unsigned_flag, &error); + } String *val_str(String *str) { return val_string_from_real(str); } my_decimal *val_decimal(my_decimal *dec_buf) @@ -1215,7 +1224,9 @@ class Item_sum_udf_float :public Item_udf_sum longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) rint(Item_sum_udf_float::val_real()); + bool error; + return double_to_longlong(Item_sum_udf_float::val_real(), + unsigned_flag, &error); } double val_real(); String *val_str(String*str); diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index eeb373a75ee..cc03cc004bd 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -40,6 +40,7 @@ #include "set_var.h" #include "sql_locale.h" // MY_LOCALE my_locale_en_US #include "strfunc.h" // check_word +#include "sql_type_int.h" // Longlong_hybrid #include "sql_time.h" // make_truncated_value_warning, // get_date_from_daynr, // calc_weekday, calc_week, @@ -2741,8 +2742,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) { DBUG_ASSERT(fixed == 1); - bool overflow= 0; - longlong hour= args[0]->val_int(); + Longlong_hybrid hour(args[0]->val_int(), args[0]->unsigned_flag); longlong minute= args[1]->val_int(); ulonglong second; ulong microsecond; @@ -2754,21 +2754,11 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) bzero(ltime, sizeof(*ltime)); ltime->time_type= MYSQL_TIMESTAMP_TIME; + ltime->neg= hour.neg(); - /* Check for integer overflows */ - if (hour < 0) + if (hour.abs() <= TIME_MAX_HOUR) { - if (args[0]->unsigned_flag) - overflow= 1; - else - ltime->neg= 1; - } - if (-hour > TIME_MAX_HOUR || hour > TIME_MAX_HOUR) - overflow= 1; - - if (!overflow) - { - ltime->hour= (uint) ((hour < 0 ? -hour : hour)); + ltime->hour= (uint) hour.abs(); ltime->minute= (uint) minute; ltime->second= (uint) second; ltime->second_part= microsecond; @@ -2779,7 +2769,7 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) ltime->minute= TIME_MAX_MINUTE; ltime->second= TIME_MAX_SECOND; char buf[28]; - char *ptr= longlong10_to_str(hour, buf, args[0]->unsigned_flag ? 10 : -10); + char *ptr= longlong10_to_str(hour.value(), buf, hour.is_unsigned() ? 10 : -10); int len = (int)(ptr - buf) + sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second); make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, buf, len, MYSQL_TIMESTAMP_TIME, diff --git a/sql/sql_error.h b/sql/sql_error.h index 5f912ad8102..903ad65521d 100644 --- a/sql/sql_error.h +++ b/sql/sql_error.h @@ -18,6 +18,7 @@ #include "sql_list.h" /* Sql_alloc, MEM_ROOT */ #include "m_string.h" /* LEX_STRING */ +#include "sql_type_int.h" // Longlong_hybrid #include "sql_string.h" /* String */ #include "mysql_com.h" /* MYSQL_ERRMSG_SIZE */ @@ -542,13 +543,11 @@ public: { return err_conv(err_buffer, sizeof(err_buffer), str, len, cs); } }; -class ErrConvInteger : public ErrConv +class ErrConvInteger : public ErrConv, public Longlong_hybrid { - longlong m_value; - bool m_unsigned; public: ErrConvInteger(longlong num_arg, bool unsigned_flag= false) : - ErrConv(), m_value(num_arg), m_unsigned(unsigned_flag) {} + ErrConv(), Longlong_hybrid(num_arg, unsigned_flag) {} const char *ptr() const { return m_unsigned ? ullstr(m_value, err_buffer) : diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h new file mode 100644 index 00000000000..055790ba431 --- /dev/null +++ b/sql/sql_type_int.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2006, 2010, Oracle and/or its affiliates. + Copyright (c) 2011, 2016, MariaDB + + 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 St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef SQL_TYPE_INT_INCLUDED +#define SQL_TYPE_INT_INCLUDED + + +// A longlong/ulonglong hybrid. Good to store results of val_int(). +class Longlong_hybrid +{ +protected: + longlong m_value; + bool m_unsigned; +public: + Longlong_hybrid(longlong nr, bool unsigned_flag) + :m_value(nr), m_unsigned(unsigned_flag) + { } + longlong value() const { return m_value; } + bool is_unsigned() const { return m_unsigned; } + bool neg() const { return m_value < 0 && !m_unsigned; } + ulonglong abs() const + { + return neg() ? (ulonglong) -m_value : (ulonglong) m_value; + } +}; + +#endif // SQL_TYPE_INT_INCLUDED From 935a163dd9242457fe56e73b2c2932230579aef5 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 20 Sep 2018 16:51:56 +0400 Subject: [PATCH 07/14] MDEV-17244 MAKETIME(900,0,0.111) returns a wrong result --- mysql-test/r/func_time.result | 113 ++++++++++++++++++++++++++++++++++ mysql-test/t/func_time.test | 28 +++++++++ sql/item_timefunc.cc | 7 ++- 3 files changed, 145 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 1db897d4ec0..9d478b10d8a 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -2706,5 +2706,118 @@ Warning 1292 Truncated incorrect time value: '9223372036854775807:00:00' Warning 1292 Truncated incorrect time value: '-9223372036854775808:00:00' DROP TABLE t1; # +# MDEV-17244 MAKETIME(900,0,0.111) returns a wrong result +# +SELECT MAKETIME(900,0,0); +MAKETIME(900,0,0) +838:59:59 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.1); +MAKETIME(900,0,0.1) +838:59:59.9 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.11); +MAKETIME(900,0,0.11) +838:59:59.99 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.111); +MAKETIME(900,0,0.111) +838:59:59.999 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.1111); +MAKETIME(900,0,0.1111) +838:59:59.9999 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.11111); +MAKETIME(900,0,0.11111) +838:59:59.99999 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.111111); +MAKETIME(900,0,0.111111) +838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.1111111); +MAKETIME(900,0,0.1111111) +838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.11111111); +MAKETIME(900,0,0.11111111) +838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,0.111111111); +MAKETIME(900,0,0.111111111) +838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:00' +SELECT MAKETIME(900,0,EXP(1)); +MAKETIME(900,0,EXP(1)) +838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '900:00:02' +SELECT MAKETIME(-900,0,0); +MAKETIME(-900,0,0) +-838:59:59 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.1); +MAKETIME(-900,0,0.1) +-838:59:59.9 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.11); +MAKETIME(-900,0,0.11) +-838:59:59.99 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.111); +MAKETIME(-900,0,0.111) +-838:59:59.999 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.1111); +MAKETIME(-900,0,0.1111) +-838:59:59.9999 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.11111); +MAKETIME(-900,0,0.11111) +-838:59:59.99999 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.111111); +MAKETIME(-900,0,0.111111) +-838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.1111111); +MAKETIME(-900,0,0.1111111) +-838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.11111111); +MAKETIME(-900,0,0.11111111) +-838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,0.111111111); +MAKETIME(-900,0,0.111111111) +-838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:00' +SELECT MAKETIME(-900,0,EXP(1)); +MAKETIME(-900,0,EXP(1)) +-838:59:59.999999 +Warnings: +Warning 1292 Truncated incorrect time value: '-900:00:02' +# # End of 5.5 tests # diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index 10b2b2958c2..4497a4d9668 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -1654,6 +1654,34 @@ INSERT INTO t1 VALUES (1e30),(-1e30); SELECT MAKETIME(a,0,0) FROM t1; DROP TABLE t1; +--echo # +--echo # MDEV-17244 MAKETIME(900,0,0.111) returns a wrong result +--echo # + +SELECT MAKETIME(900,0,0); +SELECT MAKETIME(900,0,0.1); +SELECT MAKETIME(900,0,0.11); +SELECT MAKETIME(900,0,0.111); +SELECT MAKETIME(900,0,0.1111); +SELECT MAKETIME(900,0,0.11111); +SELECT MAKETIME(900,0,0.111111); +SELECT MAKETIME(900,0,0.1111111); +SELECT MAKETIME(900,0,0.11111111); +SELECT MAKETIME(900,0,0.111111111); +SELECT MAKETIME(900,0,EXP(1)); + +SELECT MAKETIME(-900,0,0); +SELECT MAKETIME(-900,0,0.1); +SELECT MAKETIME(-900,0,0.11); +SELECT MAKETIME(-900,0,0.111); +SELECT MAKETIME(-900,0,0.1111); +SELECT MAKETIME(-900,0,0.11111); +SELECT MAKETIME(-900,0,0.111111); +SELECT MAKETIME(-900,0,0.1111111); +SELECT MAKETIME(-900,0,0.11111111); +SELECT MAKETIME(-900,0,0.111111111); +SELECT MAKETIME(-900,0,EXP(1)); + --echo # --echo # End of 5.5 tests diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index cc03cc004bd..2dc704f6873 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2765,9 +2765,10 @@ bool Item_func_maketime::get_date(MYSQL_TIME *ltime, ulonglong fuzzy_date) } else { - ltime->hour= TIME_MAX_HOUR; - ltime->minute= TIME_MAX_MINUTE; - ltime->second= TIME_MAX_SECOND; + // use check_time_range() to set ltime to the max value depending on dec + int unused; + ltime->hour= TIME_MAX_HOUR + 1; + check_time_range(ltime, decimals, &unused); char buf[28]; char *ptr= longlong10_to_str(hour.value(), buf, hour.is_unsigned() ? 10 : -10); int len = (int)(ptr - buf) + sprintf(ptr, ":%02u:%02u", (uint)minute, (uint)second); From e07118946a82af60c7cc3804c321d3fd9a49f128 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 20 Sep 2018 17:11:36 +0400 Subject: [PATCH 08/14] MDEV-17250 Remove unused Item_copy_xxx --- sql/item.cc | 175 ---------------------------------------------------- sql/item.h | 90 --------------------------- 2 files changed, 265 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index e1afc339cc2..d2e3b847f5c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4169,31 +4169,6 @@ void Item_param::make_field(Send_field *field) field->type= m_out_param_info->type; } -/**************************************************************************** - Item_copy -****************************************************************************/ - -Item_copy *Item_copy::create (Item *item) -{ - switch (item->result_type()) - { - case STRING_RESULT: - return new Item_copy_string (item); - case REAL_RESULT: - return new Item_copy_float (item); - case INT_RESULT: - return item->unsigned_flag ? - new Item_copy_uint (item) : new Item_copy_int (item); - case DECIMAL_RESULT: - return new Item_copy_decimal (item); - case TIME_RESULT: - case ROW_RESULT: - case IMPOSSIBLE_RESULT: - DBUG_ASSERT (0); - } - /* should not happen */ - return NULL; -} /**************************************************************************** Item_copy_string @@ -4251,156 +4226,6 @@ my_decimal *Item_copy_string::val_decimal(my_decimal *decimal_value) } -/**************************************************************************** - Item_copy_int -****************************************************************************/ - -void Item_copy_int::copy() -{ - cached_value= item->val_int(); - null_value=item->null_value; -} - -static int save_int_value_in_field (Field *, longlong, bool, bool); - -int Item_copy_int::save_in_field(Field *field, bool no_conversions) -{ - return save_int_value_in_field(field, cached_value, - null_value, unsigned_flag); -} - - -String *Item_copy_int::val_str(String *str) -{ - if (null_value) - return (String *) 0; - - str->set(cached_value, &my_charset_bin); - return str; -} - - -my_decimal *Item_copy_int::val_decimal(my_decimal *decimal_value) -{ - if (null_value) - return (my_decimal *) 0; - - int2my_decimal(E_DEC_FATAL_ERROR, cached_value, unsigned_flag, decimal_value); - return decimal_value; -} - - -/**************************************************************************** - Item_copy_uint -****************************************************************************/ - -String *Item_copy_uint::val_str(String *str) -{ - if (null_value) - return (String *) 0; - - str->set((ulonglong) cached_value, &my_charset_bin); - return str; -} - - -/**************************************************************************** - Item_copy_float -****************************************************************************/ - -String *Item_copy_float::val_str(String *str) -{ - if (null_value) - return (String *) 0; - else - { - double nr= val_real(); - str->set_real(nr,decimals, &my_charset_bin); - return str; - } -} - - -my_decimal *Item_copy_float::val_decimal(my_decimal *decimal_value) -{ - if (null_value) - return (my_decimal *) 0; - else - { - double nr= val_real(); - double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value); - return decimal_value; - } -} - - -int Item_copy_float::save_in_field(Field *field, bool no_conversions) -{ - if (null_value) - return set_field_to_null(field); - field->set_notnull(); - return field->store(cached_value); -} - - -/**************************************************************************** - Item_copy_decimal -****************************************************************************/ - -int Item_copy_decimal::save_in_field(Field *field, bool no_conversions) -{ - if (null_value) - return set_field_to_null(field); - field->set_notnull(); - return field->store_decimal(&cached_value); -} - - -String *Item_copy_decimal::val_str(String *result) -{ - if (null_value) - return (String *) 0; - result->set_charset(&my_charset_bin); - my_decimal2string(E_DEC_FATAL_ERROR, &cached_value, 0, 0, 0, result); - return result; -} - - -double Item_copy_decimal::val_real() -{ - if (null_value) - return 0.0; - else - { - double result; - my_decimal2double(E_DEC_FATAL_ERROR, &cached_value, &result); - return result; - } -} - - -longlong Item_copy_decimal::val_int() -{ - if (null_value) - return LL(0); - else - { - longlong result; - my_decimal2int(E_DEC_FATAL_ERROR, &cached_value, unsigned_flag, &result); - return result; - } -} - - -void Item_copy_decimal::copy() -{ - my_decimal *nr= item->val_decimal(&cached_value); - if (nr && nr != &cached_value) - my_decimal2decimal (nr, &cached_value); - null_value= item->null_value; -} - - /* Functions to convert item to field (for send_result_set_metadata) */ diff --git a/sql/item.h b/sql/item.h index 1bded7377ee..dbcf6bc6d08 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3664,13 +3664,6 @@ protected: } public: - /** - Factory method to create the appropriate subclass dependent on the type of - the original item. - - @param item the original item. - */ - static Item_copy *create (Item *item); /** Update the cache with the value of the original item @@ -3732,89 +3725,6 @@ public: }; -class Item_copy_int : public Item_copy -{ -protected: - longlong cached_value; -public: - Item_copy_int (Item *i) : Item_copy(i) {} - int save_in_field(Field *field, bool no_conversions); - - virtual String *val_str(String*); - virtual my_decimal *val_decimal(my_decimal *); - virtual double val_real() - { - return null_value ? 0.0 : (double) cached_value; - } - virtual longlong val_int() - { - return null_value ? LL(0) : cached_value; - } - virtual void copy(); -}; - - -class Item_copy_uint : public Item_copy_int -{ -public: - Item_copy_uint (Item *item) : Item_copy_int(item) - { - unsigned_flag= 1; - } - - String *val_str(String*); - double val_real() - { - return null_value ? 0.0 : (double) (ulonglong) cached_value; - } -}; - - -class Item_copy_float : public Item_copy -{ -protected: - double cached_value; -public: - Item_copy_float (Item *i) : Item_copy(i) {} - int save_in_field(Field *field, bool no_conversions); - - String *val_str(String*); - my_decimal *val_decimal(my_decimal *); - double val_real() - { - return null_value ? 0.0 : cached_value; - } - longlong val_int() - { - return (longlong) rint(val_real()); - } - void copy() - { - cached_value= item->val_real(); - null_value= item->null_value; - } -}; - - -class Item_copy_decimal : public Item_copy -{ -protected: - my_decimal cached_value; -public: - Item_copy_decimal (Item *i) : Item_copy(i) {} - int save_in_field(Field *field, bool no_conversions); - - String *val_str(String*); - my_decimal *val_decimal(my_decimal *) - { - return null_value ? NULL: &cached_value; - } - double val_real(); - longlong val_int(); - void copy(); -}; - - /* Cached_item_XXX objects are not exactly caches. They do the following: From d533f6d58b0e4e4dace14227c6eb53e3c0b3232d Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 21 Sep 2018 09:32:17 +0400 Subject: [PATCH 09/14] After-merge cleanup: adjust the test to work in 10.0 For the original test in 10.0 it was not really important if find_user_wild() or find_user_exact() is used in sp_grant_privileges(). sp-security.test passed with either of them. Fixing the test so it reliably fails with find_user_wild() and pass with find_user_exact(). --- mysql-test/r/sp-security.result | 4 +++- mysql-test/t/sp-security.test | 11 ++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result index a4e3505cf0f..4125762e622 100644 --- a/mysql-test/r/sp-security.result +++ b/mysql-test/r/sp-security.result @@ -618,7 +618,9 @@ SELECT 1 latin1 latin1_swedish_ci latin1_swedish_ci DROP USER user2@localhost; DROP DATABASE db1; create user foo@local_ost; -create user foo@`local\_ost` identified by 'nevermore'; +create user foo@`local\_ost`; +update mysql.user set plugin='foobar' where host='local\\_ost'; +flush privileges; create database foodb; grant create routine on foodb.* to foo@local_ost; select user(), current_user(); diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test index 0f9243f30bb..53dc4f8c7ac 100644 --- a/mysql-test/t/sp-security.test +++ b/mysql-test/t/sp-security.test @@ -999,7 +999,16 @@ DROP DATABASE db1; # Bug#27407480: AUTOMATIC_SP_PRIVILEGES REQUIRES NEED THE INSERT PRIVILEGES FOR MYSQL.USER TABLE # create user foo@local_ost; -create user foo@`local\_ost` identified by 'nevermore'; +# +# Create a user with an authentification plugin 'foobar'. +# Instead of using a normal "CREATE USER IDENTIFIED VIA " +# we do CREATE (without VIA) followed by UPDATE and FLUSH. +# This is to avoid installing a real plugin and thus avoid the test dependency. +# We won't login under this user in the below test, so this is fine. +# +create user foo@`local\_ost`; +update mysql.user set plugin='foobar' where host='local\\_ost'; +flush privileges; create database foodb; grant create routine on foodb.* to foo@local_ost; connect con1,localhost,foo; From 5b25dc6fa4bf63d783e8f8db73abc22ab111143b Mon Sep 17 00:00:00 2001 From: Eugene Kosov Date: Wed, 19 Sep 2018 22:01:00 +0300 Subject: [PATCH 10/14] MDEV-17248 Improve ASAN memory pool instrumentation alloc_root(): unpoison only requested amount of bytes instead of a possible bigger aligned-sized buffer. --- include/my_valgrind.h | 4 ++-- mysys/my_alloc.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/my_valgrind.h b/include/my_valgrind.h index 8dde079b976..5d08a271d4a 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -49,9 +49,9 @@ https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */ #endif /* HAVE_VALGRIND */ #ifndef DBUG_OFF -#define TRASH_FILL(A,B,C) do { MEM_UNDEFINED(A,B); memset(A,C,B); } while(0) +#define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_UNDEFINED(A, trash_tmp); memset(A, C, trash_tmp); } while (0) #else -#define TRASH_FILL(A,B,C) do { MEM_UNDEFINED(A,B); } while(0) +#define TRASH_FILL(A,B,C) do { const size_t trash_tmp __attribute__((unused))= (B); MEM_UNDEFINED(A,trash_tmp); } while (0) #endif #define TRASH_ALLOC(A,B) do { TRASH_FILL(A,B,0xA5); MEM_UNDEFINED(A,B); } while(0) #define TRASH_FREE(A,B) do { TRASH_FILL(A,B,0x8F); MEM_NOACCESS(A,B); } while(0) diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 24e95d2c69c..e727f46be6d 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -184,6 +184,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) uchar* point; reg1 USED_MEM *next= 0; reg2 USED_MEM **prev; + size_t original_length = length; DBUG_ENTER("alloc_root"); DBUG_PRINT("enter",("root: 0x%lx", (long) mem_root)); DBUG_ASSERT(alloc_root_inited(mem_root)); @@ -241,7 +242,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) mem_root->used= next; mem_root->first_block_usage= 0; } - TRASH_ALLOC(point, length); + TRASH_ALLOC(point, original_length); DBUG_PRINT("exit",("ptr: 0x%lx", (ulong) point)); DBUG_RETURN((void*) point); #endif From b514a5f9e887911d5d5b46c91f4cfbe87c346289 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 21 Sep 2018 18:03:23 +0400 Subject: [PATCH 11/14] A cleanup for MDEV-17249 MAKETIME(-1e50,0,0) returns a wrong result Unary minus operation for the smallest possible signed long long value (LONLONG_MIN) is undefined in C++. Because of this, func_time.test failed on ppc64 buildbot machines. Fixing the code to avod using undefined operations. This is fix is similar to "MDEV-7973 bigint fail with gcc 5.0" --- sql/sql_type_int.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sql/sql_type_int.h b/sql/sql_type_int.h index 055790ba431..1eda5651df5 100644 --- a/sql/sql_type_int.h +++ b/sql/sql_type_int.h @@ -33,7 +33,11 @@ public: bool neg() const { return m_value < 0 && !m_unsigned; } ulonglong abs() const { - return neg() ? (ulonglong) -m_value : (ulonglong) m_value; + if (m_unsigned) + return (ulonglong) m_value; + if (m_value == LONGLONG_MIN) // avoid undefined behavior + return ((ulonglong) LONGLONG_MAX) + 1; + return m_value < 0 ? -m_value : m_value; } }; From fc70f21e0a874a535cd640695a60ecc76fb9aef2 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 21 Sep 2018 18:04:56 +0400 Subject: [PATCH 12/14] Fixing the comment not to mention the removed class Item_copy_int. --- sql/item.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item.h b/sql/item.h index dbcf6bc6d08..dacac2d725e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -3608,7 +3608,7 @@ public: Base class to implement typed value caching Item classes Item_copy_ classes are very similar to the corresponding Item_ - classes (e.g. Item_copy_int is similar to Item_int) but they add + classes (e.g. Item_copy_string is similar to Item_string) but they add the following additional functionality to Item_ : 1. Nullability 2. Possibility to store the value not only on instantiation time, From 3a9276bad31810a87133dd003bbe345602627ecc Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 22 Sep 2018 15:19:40 +0200 Subject: [PATCH 13/14] sanitize tokudb locking macros --- storage/tokudb/hatoku_defines.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/storage/tokudb/hatoku_defines.h b/storage/tokudb/hatoku_defines.h index 66a8fa5d982..2fd149d120d 100644 --- a/storage/tokudb/hatoku_defines.h +++ b/storage/tokudb/hatoku_defines.h @@ -290,23 +290,23 @@ inline uint tokudb_uint3korr(const uchar *a) { typedef unsigned int pfs_key_t; #if defined(SAFE_MUTEX) || defined(HAVE_PSI_MUTEX_INTERFACE) -#define mutex_t_lock(M) M.lock(__FILE__, __LINE__) +#define mutex_t_lock(M) (M).lock(__FILE__, __LINE__) #else // SAFE_MUTEX || HAVE_PSI_MUTEX_INTERFACE -#define mutex_t_lock(M) M.lock() +#define mutex_t_lock(M) (M).lock() #endif // SAFE_MUTEX || HAVE_PSI_MUTEX_INTERFACE #if defined(SAFE_MUTEX) -#define mutex_t_unlock(M) M.unlock(__FILE__, __LINE__) +#define mutex_t_unlock(M) (M).unlock(__FILE__, __LINE__) #else // SAFE_MUTEX -#define mutex_t_unlock(M) M.unlock() +#define mutex_t_unlock(M) (M).unlock() #endif // SAFE_MUTEX #if defined(HAVE_PSI_RWLOCK_INTERFACE) -#define rwlock_t_lock_read(M) M.lock_read(__FILE__, __LINE__) -#define rwlock_t_lock_write(M) M.lock_write(__FILE__, __LINE__) +#define rwlock_t_lock_read(M) (M).lock_read(__FILE__, __LINE__) +#define rwlock_t_lock_write(M) (M).lock_write(__FILE__, __LINE__) #else // HAVE_PSI_RWLOCK_INTERFACE -#define rwlock_t_lock_read(M) M.lock_read() -#define rwlock_t_lock_write(M) M.lock_write() +#define rwlock_t_lock_read(M) (M).lock_read() +#define rwlock_t_lock_write(M) (M).lock_write() #endif // HAVE_PSI_RWLOCK_INTERFACE #endif // _HATOKU_DEFINES_H From 1144acbcbdf9b7bdf18c31f88cbe859d99658b53 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 22 Sep 2018 15:21:20 +0200 Subject: [PATCH 14/14] tokudb: create and destroy TOKUDB_SHARE::_open_tables_mutex dynamically to guarantee that it's destroyed when plugin deinit is called, not after --- storage/tokudb/ha_tokudb.cc | 12 +++++++----- storage/tokudb/ha_tokudb.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc index 4637ac1bf5f..34a7fefde30 100644 --- a/storage/tokudb/ha_tokudb.cc +++ b/storage/tokudb/ha_tokudb.cc @@ -48,7 +48,7 @@ static inline uint get_ext_key_parts(const KEY *key) { #endif // defined(TOKU_INCLUDE_EXTENDED_KEYS) && TOKU_INCLUDE_EXTENDED_KEYS std::unordered_map TOKUDB_SHARE::_open_tables; -tokudb::thread::mutex_t TOKUDB_SHARE::_open_tables_mutex; +tokudb::thread::mutex_t* TOKUDB_SHARE::_open_tables_mutex; static const char* ha_tokudb_exts[] = { ha_tokudb_ext, @@ -154,6 +154,7 @@ static void free_key_and_col_info (KEY_AND_COL_INFO* kc_info) { void TOKUDB_SHARE::static_init() { assert_always(_open_tables.size() == 0); + _open_tables_mutex = new tokudb::thread::mutex_t(); } void TOKUDB_SHARE::static_destroy() { for (auto it = _open_tables.cbegin(); it != _open_tables.cend(); it++) { @@ -164,6 +165,7 @@ void TOKUDB_SHARE::static_destroy() { } _open_tables.clear(); assert_always(_open_tables.size() == 0); + delete _open_tables_mutex; } const char* TOKUDB_SHARE::get_state_string(share_state_t state) { static const char* state_string[] = { @@ -218,7 +220,7 @@ TOKUDB_SHARE* TOKUDB_SHARE::get_share(const char* table_name, THR_LOCK_DATA* data, bool create_new) { std::string find_table_name(table_name); - mutex_t_lock(_open_tables_mutex); + mutex_t_lock(*_open_tables_mutex); auto it = _open_tables.find(find_table_name); TOKUDB_SHARE *share = nullptr; if (it != _open_tables.end()) { @@ -251,7 +253,7 @@ TOKUDB_SHARE* TOKUDB_SHARE::get_share(const char* table_name, thr_lock_data_init(&(share->_thr_lock), data, NULL); exit: - mutex_t_unlock(_open_tables_mutex); + mutex_t_unlock(*_open_tables_mutex); return share; } void TOKUDB_SHARE::drop_share(TOKUDB_SHARE* share) { @@ -262,12 +264,12 @@ void TOKUDB_SHARE::drop_share(TOKUDB_SHARE* share) { get_state_string(share->_state), share->_use_count); - mutex_t_lock(_open_tables_mutex); + mutex_t_lock(*_open_tables_mutex); size_t n = _open_tables.erase(std::string(share->full_table_name())); assert_always(n == 1); share->destroy(); delete share; - mutex_t_unlock(_open_tables_mutex); + mutex_t_unlock(*_open_tables_mutex); } TOKUDB_SHARE::share_state_t TOKUDB_SHARE::addref() { TOKUDB_SHARE_TRACE_FOR_FLAGS((TOKUDB_DEBUG_ENTER & TOKUDB_DEBUG_SHARE), diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h index 6f592617b76..e322c3de18e 100644 --- a/storage/tokudb/ha_tokudb.h +++ b/storage/tokudb/ha_tokudb.h @@ -274,7 +274,7 @@ public: private: static std::unordered_map _open_tables; - static tokudb::thread::mutex_t _open_tables_mutex; + static tokudb::thread::mutex_t* _open_tables_mutex; //********************************* // Spans open-close-open