Skip to content

Commit

Permalink
BUG#22202665 - ADDING A TRIGGER TO A TABLE CHANGES THE BEHAVIOUR OF N…
Browse files Browse the repository at this point in the history
…ULL DETECTION

For non-strict mode attempt to implicitly insert NULL value into NOT NULL
column led to a different results depending on whether trigger is set
or not. Implicit insert means here the following use case:
  CREATE TABLE t1 (a INT, b INT NOT NULL);
  SET sql_mode= '';
  INSERT INTO t1 (a) VALUES (1);
For such use case for mysql server before 5.7 the warning 1364
"Field 'b' doesn't have a default value" was issued.
In 5.7 the error 1048  "Column 'b' cannot be null" is issued.
Such behaviour broke backward compatibility with 5.6.

The reason for different behaviour in error handling of implicit NOT NULL
constraint violation was that prior 5.7 checking for presense of all
non-default values in INSERT statement was done before filling record
by column values. So any attempt to INSERT a record without specifying all
columns that doesn't have default values led to warning 1364. As of 5.7
checking for presence of non-default values is done after record is filled and
NOT NULL constraints has been already checked for ever table's field.
This leads to the fact that error 1048 is issued instead of warning 1364.

To fix the bug that broke backward compatibility checking for NOT NULL
violation is done only for fields set during handling INSERT statement.
In other words, for only those fields that is set in
field->table->fields_set_during_insert checking for NOT NULL is done.
  • Loading branch information
Dmitry Shulga committed Dec 17, 2015
1 parent b06546e commit 8f1be5b
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 4 deletions.
20 changes: 18 additions & 2 deletions mysql-test/r/trigger_wl6030.result
Original file line number Diff line number Diff line change
Expand Up @@ -875,12 +875,10 @@ END|

INSERT INTO t1(a) VALUES (1), (2), (3), (4), (5), (6);
Warnings:
Warning 1048 Column 'b' cannot be null
Warning 1364 Field 'b' doesn't have a default value

REPLACE INTO t1(a) VALUES (1), (2), (3), (4), (5), (6);
Warnings:
Warning 1048 Column 'b' cannot be null
Warning 1364 Field 'b' doesn't have a default value

SELECT * FROM t1;
Expand Down Expand Up @@ -2221,3 +2219,21 @@ SET sql_mode = @sql_mode_saved;
Warnings:
Warning 3090 Changing sql mode 'NO_AUTO_CREATE_USER' is deprecated. It will be removed in a future release.
DROP TABLE t1;
SET @sql_mode_saved = @@sql_mode;
SET sql_mode='';
CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL);
INSERT INTO t1(a) VALUES (1);
Warnings:
Warning 1364 Field 'b' doesn't have a default value
SHOW WARNINGS;
Level Code Message
Warning 1364 Field 'b' doesn't have a default value
CREATE TRIGGER t1_trg_before_ins BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=2;
INSERT INTO t1(a) VALUES (1);
Warnings:
Warning 1364 Field 'b' doesn't have a default value
SHOW WARNINGS;
Level Code Message
Warning 1364 Field 'b' doesn't have a default value
SET sql_mode = @sql_mode_saved;
DROP TABLE t1;
19 changes: 19 additions & 0 deletions mysql-test/t/trigger_wl6030.test
Original file line number Diff line number Diff line change
Expand Up @@ -1814,3 +1814,22 @@ SHOW WARNINGS;
SET sql_mode = @sql_mode_saved;
DROP TABLE t1;

#
# BUG#22202665 - ADDING A TRIGGER TO A TABLE CHANGES THE BEHAVIOUR OF NULL DETECTION
#

--disable_warnings
SET @sql_mode_saved = @@sql_mode;
SET sql_mode='';
--enable_warnings
CREATE TABLE t1(a INT NOT NULL, b INT NOT NULL);
INSERT INTO t1(a) VALUES (1);
SHOW WARNINGS;
CREATE TRIGGER t1_trg_before_ins BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a=2;
INSERT INTO t1(a) VALUES (1);
SHOW WARNINGS;

--disable_warnings
SET sql_mode = @sql_mode_saved;
--enable_warnings
DROP TABLE t1;
30 changes: 28 additions & 2 deletions sql/sql_base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9245,6 +9245,32 @@ bool check_record(THD *thd, Field **ptr)
}


/**
Check the NOT NULL constraint on all the fields explicitly set
in INSERT INTO statement or implicitly set in BEFORE trigger.
@param thd Thread context.
@param ptr Fields.
@return Error status.
*/

static bool check_inserting_record(THD *thd, Field **ptr)
{
Field *field;

while ((field = *ptr++) && !thd->is_error())
{
if (bitmap_is_set(field->table->fields_set_during_insert,
field->field_index) &&
field->check_constraints(ER_BAD_NULL_ERROR) != TYPE_OK)
return true;
}

return thd->is_error();
}


/**
Check if SQL-statement is INSERT/INSERT SELECT/REPLACE/REPLACE SELECT
and trigger event is ON INSERT. When this condition is true that means
Expand Down Expand Up @@ -9380,7 +9406,7 @@ fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,

table->triggers->disable_fields_temporary_nullability();

return rc || check_record(thd, table->field);
return rc || check_inserting_record(thd, table->field);
}
else
{
Expand Down Expand Up @@ -9535,7 +9561,7 @@ fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
if (rc)
return true;

return check_record(thd, ptr);
return check_inserting_record(thd, ptr);
}


Expand Down
1 change: 1 addition & 0 deletions sql/sql_insert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1945,6 +1945,7 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
err= 1;
}
}
bitmap_clear_all(write_set);
return (!thd->lex->is_ignore() && thd->is_strict_mode()) ? err : 0;
}

Expand Down

0 comments on commit 8f1be5b

Please sign in to comment.