Commit 428a6731 authored by Dmitry Shulga's avatar Dmitry Shulga

MDEV-33549: Incorrect handling of UPDATE in PS mode in case a table's colum declared as NOT NULL

UPDATE statement that is run in PS mode and uses positional parameter
handles columns declared with the clause DEFAULT NULL incorrectly in
case the clause DEFAULT is passed as actual value for the positional
parameter of the prepared statement. Similar issue happens in case
an expression specified in the DEFAULT clause of table's column definition.

The reason for incorrect processing of columns declared as DEFAULT NULL
is that setting of null flag for a field being updated was missed
in implementation of the method Item_param::assign_default().
The reason for incorrect handling of an expression in DEFAULT clause is
also missed saving of a field inside implementation of the method
Item_param::assign_default().
parent 0a9cec22
......@@ -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
#
......@@ -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 #
......@@ -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);
}
}
......
......@@ -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.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment