summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2021-12-29 14:54:34 +0400
committerAlexander Barkov <bar@mariadb.com>2021-12-29 14:54:34 +0400
commit189bf300cae5bbf147b780d6191f7fef6ad58678 (patch)
tree1e645398a0dab3ebbf6c4da75d5c629d0dfaf294
parentfad1d15326651a92895c799829ff66edc37fc20f (diff)
downloadmariadb-git-189bf300cae5bbf147b780d6191f7fef6ad58678.tar.gz
MDEV-21639 DEFAULT(col) evaluates to a bad value in WHERE clausebb-10.2-bar-MDEV-21639
The problem happened because Item_default_value did not overload properly the val_xxx_result() family methods. This change backports the patch for: MDEV-24958 Server crashes in my_strtod / Value_source::Converter_strntod::Converter_strntod with DEFAULT(blob) which earlier fixed the problem in 10.3.
-rw-r--r--mysql-test/r/func_default.result121
-rw-r--r--mysql-test/t/func_default.test102
-rw-r--r--sql/item.cc42
-rw-r--r--sql/item.h10
4 files changed, 272 insertions, 3 deletions
diff --git a/mysql-test/r/func_default.result b/mysql-test/r/func_default.result
index 9699f0795e3..8721270ca1c 100644
--- a/mysql-test/r/func_default.result
+++ b/mysql-test/r/func_default.result
@@ -29,6 +29,9 @@ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
ERROR HY000: Field 'mi' doesn't have a default value
DROP TABLE t1;
+#
+# Start of 10.2 tests
+#
set timestamp=unix_timestamp('2001-01-01 10:20:30.123456');
create table t1 (a int default 1, b int default (a+1),
c varchar(100) default 'foo', d text default 'bar',
@@ -40,3 +43,121 @@ default(a) default(b) default(c) default(d) default(e) default(f)
1 2 foo bar 2001-01-01 10:20:30 2001-01-01 10:20:30.120000
1 11 foo bar 2001-01-01 10:20:30 2001-01-01 10:20:30.120000
drop table t1;
+#
+# MDEV-21639 DEFAULT(col) evaluates to a bad value in WHERE clause
+#
+CREATE TABLE t1 (a BIGINT NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10)));
+INSERT INTO t1 VALUES (10000);
+SELECT
+a,
+DEFAULT(a),
+CASE WHEN a THEN DEFAULT(a) END AS c,
+CASE WHEN a THEN DEFAULT(a) END = 10 AS ce
+FROM t1;
+a DEFAULT(a) c ce
+10000 10 10 1
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10;
+a
+10000
+DROP TABLE t1;
+CREATE TABLE t1 (a DOUBLE NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10)));
+INSERT INTO t1 VALUES (10000);
+SELECT
+a,
+DEFAULT(a),
+CASE WHEN a THEN DEFAULT(a) END AS c,
+CASE WHEN a THEN DEFAULT(a) END = 10 AS ce
+FROM t1;
+a DEFAULT(a) c ce
+10000 10 10 1
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10;
+a
+10000
+DROP TABLE t1;
+CREATE TABLE t1 (a DECIMAL(10,0) NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10)));
+INSERT INTO t1 VALUES (10000);
+SELECT
+a,
+DEFAULT(a),
+CASE WHEN a THEN DEFAULT(a) END AS c,
+CASE WHEN a THEN DEFAULT(a) END = 10 AS ce
+FROM t1;
+a DEFAULT(a) c ce
+10000 10 10 1
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10;
+a
+10000
+DROP TABLE t1;
+CREATE TABLE t1 (a VARCHAR(32) NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10)));
+INSERT INTO t1 VALUES (10000);
+SELECT
+a,
+DEFAULT(a),
+CASE WHEN a THEN DEFAULT(a) END AS c,
+CASE WHEN a THEN DEFAULT(a) END = '10' AS ce
+FROM t1;
+a DEFAULT(a) c ce
+10000 10 10 1
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='10';
+a
+10000
+DROP TABLE t1;
+CREATE TABLE t1 (a DATE NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP()%10,DATE'2001-01-01')));
+INSERT INTO t1 VALUES ('2000-01-01');
+SELECT
+a,
+DEFAULT(a),
+CASE WHEN a THEN DEFAULT(a) END AS c,
+CASE WHEN a THEN DEFAULT(a) END = '2001-01-01' AS ce
+FROM t1;
+a DEFAULT(a) c ce
+2000-01-01 2001-01-01 2001-01-01 1
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='2001-01-01';
+a
+2000-01-01
+DROP TABLE t1;
+CREATE TABLE t1 (a TIME NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP()%10,TIME'10:20:30')));
+INSERT INTO t1 VALUES ('10:00:00');
+SELECT
+a,
+DEFAULT(a),
+CASE WHEN a THEN DEFAULT(a) END AS c,
+CASE WHEN a THEN DEFAULT(a) END = '10:20:30' AS ce
+FROM t1;
+a DEFAULT(a) c ce
+10:00:00 10:20:30 10:20:30 1
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='10:20:30';
+a
+10:00:00
+DROP TABLE t1;
+CREATE TABLE t1 (a DATETIME NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),TIMESTAMP'2001-01-01 10:20:30')));
+INSERT INTO t1 VALUES ('2000-01-01 10:00:00');
+SELECT
+a,
+DEFAULT(a),
+CASE WHEN a THEN DEFAULT(a) END AS c,
+CASE WHEN a THEN DEFAULT(a) END = '2001-01-01 10:20:30' AS ce
+FROM t1;
+a DEFAULT(a) c ce
+2000-01-01 10:00:00 2001-01-01 10:20:30 2001-01-01 10:20:30 1
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='2001-01-01 10:20:30';
+a
+2000-01-01 10:00:00
+DROP TABLE t1;
+CREATE TABLE t1 (a INT NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),FALSE)));
+INSERT INTO t1 VALUES (10);
+SELECT
+a,
+DEFAULT(a),
+CASE WHEN a THEN DEFAULT(a) END AS c,
+CASE WHEN a THEN DEFAULT(a) END IS FALSE AS ce
+FROM t1;
+a DEFAULT(a) c ce
+10 0 0 1
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END IS FALSE;
+a
+10
+DROP TABLE t1;
+#
+# End of 10.2 tests
+#
diff --git a/mysql-test/t/func_default.test b/mysql-test/t/func_default.test
index 332bfca021f..cba7842c68f 100644
--- a/mysql-test/t/func_default.test
+++ b/mysql-test/t/func_default.test
@@ -34,9 +34,9 @@ INSERT INTO t1 VALUES (1, 'one'), (2, 'two'), (3, 'three');
SELECT s, 32 AS mi FROM t1 GROUP BY s HAVING DEFAULT(mi) IS NULL;
DROP TABLE t1;
-#
-# 10.2 tests
-#
+--echo #
+--echo # Start of 10.2 tests
+--echo #
set timestamp=unix_timestamp('2001-01-01 10:20:30.123456');
create table t1 (a int default 1, b int default (a+1),
@@ -46,3 +46,99 @@ insert t1 () values ();
insert t1 (a) values (10);
select default(a),default(b),default(c),default(d),default(e),default(f) from t1;
drop table t1;
+
+--echo #
+--echo # MDEV-21639 DEFAULT(col) evaluates to a bad value in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a BIGINT NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10)));
+INSERT INTO t1 VALUES (10000);
+SELECT
+ a,
+ DEFAULT(a),
+ CASE WHEN a THEN DEFAULT(a) END AS c,
+ CASE WHEN a THEN DEFAULT(a) END = 10 AS ce
+FROM t1;
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DOUBLE NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10)));
+INSERT INTO t1 VALUES (10000);
+SELECT
+ a,
+ DEFAULT(a),
+ CASE WHEN a THEN DEFAULT(a) END AS c,
+ CASE WHEN a THEN DEFAULT(a) END = 10 AS ce
+FROM t1;
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DECIMAL(10,0) NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10)));
+INSERT INTO t1 VALUES (10000);
+SELECT
+ a,
+ DEFAULT(a),
+ CASE WHEN a THEN DEFAULT(a) END AS c,
+ CASE WHEN a THEN DEFAULT(a) END = 10 AS ce
+FROM t1;
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END=10;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a VARCHAR(32) NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),10)));
+INSERT INTO t1 VALUES (10000);
+SELECT
+ a,
+ DEFAULT(a),
+ CASE WHEN a THEN DEFAULT(a) END AS c,
+ CASE WHEN a THEN DEFAULT(a) END = '10' AS ce
+FROM t1;
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='10';
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DATE NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP()%10,DATE'2001-01-01')));
+INSERT INTO t1 VALUES ('2000-01-01');
+SELECT
+ a,
+ DEFAULT(a),
+ CASE WHEN a THEN DEFAULT(a) END AS c,
+ CASE WHEN a THEN DEFAULT(a) END = '2001-01-01' AS ce
+FROM t1;
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='2001-01-01';
+DROP TABLE t1;
+
+CREATE TABLE t1 (a TIME NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP()%10,TIME'10:20:30')));
+INSERT INTO t1 VALUES ('10:00:00');
+SELECT
+ a,
+ DEFAULT(a),
+ CASE WHEN a THEN DEFAULT(a) END AS c,
+ CASE WHEN a THEN DEFAULT(a) END = '10:20:30' AS ce
+FROM t1;
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='10:20:30';
+DROP TABLE t1;
+
+CREATE TABLE t1 (a DATETIME NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),TIMESTAMP'2001-01-01 10:20:30')));
+INSERT INTO t1 VALUES ('2000-01-01 10:00:00');
+SELECT
+ a,
+ DEFAULT(a),
+ CASE WHEN a THEN DEFAULT(a) END AS c,
+ CASE WHEN a THEN DEFAULT(a) END = '2001-01-01 10:20:30' AS ce
+FROM t1;
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END='2001-01-01 10:20:30';
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT NOT NULL DEFAULT (IF(false,UNIX_TIMESTAMP(),FALSE)));
+INSERT INTO t1 VALUES (10);
+SELECT
+ a,
+ DEFAULT(a),
+ CASE WHEN a THEN DEFAULT(a) END AS c,
+ CASE WHEN a THEN DEFAULT(a) END IS FALSE AS ce
+FROM t1;
+SELECT a FROM t1 WHERE CASE WHEN a THEN DEFAULT(a) END IS FALSE;
+DROP TABLE t1;
+
+--echo #
+--echo # End of 10.2 tests
+--echo #
diff --git a/sql/item.cc b/sql/item.cc
index 3ff0219c3b3..a5b313b786d 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -9165,6 +9165,48 @@ int Item_default_value::save_in_field(Field *field_arg, bool no_conversions)
&view_error_processor);
}
+double Item_default_value::val_result()
+{
+ calculate();
+ return Item_field::val_result();
+}
+
+longlong Item_default_value::val_int_result()
+{
+ calculate();
+ return Item_field::val_int_result();
+}
+
+String *Item_default_value::str_result(String* tmp)
+{
+ calculate();
+ return Item_field::str_result(tmp);
+}
+
+bool Item_default_value::val_bool_result()
+{
+ calculate();
+ return Item_field::val_bool_result();
+}
+
+bool Item_default_value::is_null_result()
+{
+ calculate();
+ return Item_field::is_null_result();
+}
+
+my_decimal *Item_default_value::val_decimal_result(my_decimal *decimal_value)
+{
+ calculate();
+ return Item_field::val_decimal_result(decimal_value);
+}
+
+bool Item_default_value::get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate)
+{
+ calculate();
+ return Item_field::get_date_result(ltime, fuzzydate);
+}
+
table_map Item_default_value::used_tables() const
{
if (!field || !field->default_value)
diff --git a/sql/item.h b/sql/item.h
index 2a904c1691a..997352ef27a 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -5478,6 +5478,16 @@ public:
longlong val_int();
my_decimal *val_decimal(my_decimal *decimal_value);
bool get_date(MYSQL_TIME *ltime,ulonglong fuzzydate);
+
+ /* Result variants */
+ double val_result();
+ longlong val_int_result();
+ String *str_result(String* tmp);
+ my_decimal *val_decimal_result(my_decimal *val);
+ bool val_bool_result();
+ bool is_null_result();
+ bool get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate);
+
bool send(Protocol *protocol, String *buffer);
int save_in_field(Field *field_arg, bool no_conversions);
bool save_in_param(THD *thd, Item_param *param)