Skip to content

Commit

Permalink
MDEV-33549: Incorrect handling of UPDATE in PS mode in case a table's…
Browse files Browse the repository at this point in the history
… 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().
  • Loading branch information
dmitryshulga committed Mar 12, 2024
1 parent 0a9cec2 commit 428a673
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 3 deletions.
50 changes: 50 additions & 0 deletions mysql-test/main/ps.result
Original file line number Diff line number Diff line change
Expand Up @@ -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
#
54 changes: 54 additions & 0 deletions mysql-test/main/ps.test
Original file line number Diff line number Diff line change
Expand Up @@ -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 #
16 changes: 13 additions & 3 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}


Expand Down
6 changes: 6 additions & 0 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 428a673

Please sign in to comment.