diff --git a/mysql-test/main/ps.result b/mysql-test/main/ps.result index 4ed0e71a29a82..aeed24f253b6e 100644 --- a/mysql-test/main/ps.result +++ b/mysql-test/main/ps.result @@ -5933,5 +5933,55 @@ a b 2 30 DROP TABLE t1, t2; # +# MDEV-33549: Incorrect handling of UPDATE in PS mode in case a table's colum declared as NOT NULL +# +CREATE TABLE t1 (a INT, b INT DEFAULT NULL); +INSERT INTO t1 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1 SET b=?' USING DEFAULT; +SELECT * FROM t1; +a b +20 NULL +# Run twice the same update in PS mode to check +# that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1 SET b=?'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; +# Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; +# The same test for multi-table update +CREATE TABLE t1 (a INT, b INT DEFAULT NULL); +CREATE TABLE t2 (a INT, c INT DEFAULT NULL); +INSERT INTO t1 VALUES (20, 30); +INSERT INTO t2 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET b=? WHERE t1.a=t2.a' USING DEFAULT; +SELECT * FROM t1; +a b +20 NULL +# Run twice the same multi-table update in PS mode to check +# that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1,t2 SET b=? WHERE t1.a=t2.a'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; +DEALLOCATE PREPARE stmt; +# Clean up +DROP TABLE t1; +# This time checks that a default value for table's column +# represented by a function call is handled correctly on UPDATE in PS mode +CREATE TABLE t1 (a INT, b INT DEFAULT MOD(a, 3)); +INSERT INTO t1 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1, t2 SET b=? WHERE t1.a=t2.a' USING DEFAULT; +SELECT * FROM t1; +a b +20 2 +# Run twice the same multi-table update in PS mode to check +# that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1, t2 SET b=? WHERE t1.a=t2.a'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; +# Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; +# # End of 10.4 tests # diff --git a/mysql-test/main/ps.test b/mysql-test/main/ps.test index e710050cb48ee..61d1513fa0b20 100644 --- a/mysql-test/main/ps.test +++ b/mysql-test/main/ps.test @@ -5362,6 +5362,60 @@ SELECT * FROM t2; # Cleanup DROP TABLE t1, t2; +--echo # +--echo # MDEV-33549: Incorrect handling of UPDATE in PS mode in case a table's colum declared as NOT NULL +--echo # + +CREATE TABLE t1 (a INT, b INT DEFAULT NULL); +INSERT INTO t1 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1 SET b=?' USING DEFAULT; +SELECT * FROM t1; + +--echo # Run twice the same update in PS mode to check +--echo # that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1 SET b=?'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; + +--echo # Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + +--echo # The same test for multi-table update +CREATE TABLE t1 (a INT, b INT DEFAULT NULL); +CREATE TABLE t2 (a INT, c INT DEFAULT NULL); + +INSERT INTO t1 VALUES (20, 30); +INSERT INTO t2 VALUES (20, 30); + +EXECUTE IMMEDIATE 'UPDATE t1,t2 SET b=? WHERE t1.a=t2.a' USING DEFAULT; +SELECT * FROM t1; +--echo # Run twice the same multi-table update in PS mode to check +--echo # that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1,t2 SET b=? WHERE t1.a=t2.a'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; +DEALLOCATE PREPARE stmt; +--echo # Clean up +DROP TABLE t1; + +--echo # This time checks that a default value for table's column +--echo # represented by a function call is handled correctly on UPDATE in PS mode +CREATE TABLE t1 (a INT, b INT DEFAULT MOD(a, 3)); +INSERT INTO t1 VALUES (20, 30); +EXECUTE IMMEDIATE 'UPDATE t1, t2 SET b=? WHERE t1.a=t2.a' USING DEFAULT; +SELECT * FROM t1; + +--echo # Run twice the same multi-table update in PS mode to check +--echo # that no memory relating issues taken place. +PREPARE stmt FROM 'UPDATE t1, t2 SET b=? WHERE t1.a=t2.a'; +EXECUTE stmt USING DEFAULT; +EXECUTE stmt USING DEFAULT; + +--echo # Clean up +DEALLOCATE PREPARE stmt; +DROP TABLE t1, t2; + --echo # --echo # End of 10.4 tests --echo # diff --git a/sql/item.cc b/sql/item.cc index 07463b202f995..f70775b86e849 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -5064,9 +5064,19 @@ bool Item_param::assign_default(Field *field) } if (m_default_field->default_value) - m_default_field->set_default(); - - return field_conv(field, m_default_field); + { + return m_default_field->default_value->expr->save_in_field(field, 0); + } + else if (m_default_field->is_null()) + { + field->set_null(); + return false; + } + else + { + field->set_notnull(); + return field_conv(field, m_default_field); + } } diff --git a/sql/item.h b/sql/item.h index 9fc5cc4068f73..0e8eeae402a66 100644 --- a/sql/item.h +++ b/sql/item.h @@ -4000,6 +4000,12 @@ class Item_param :public Item_basic_value, Item_param(THD *thd, const LEX_CSTRING *name_arg, uint pos_in_query_arg, uint len_in_query_arg); + void cleanup() override + { + m_default_field= NULL; + Item::cleanup(); + } + enum Type type() const { // Don't pretend to be a constant unless value for this item is set.