List:Commits« Previous MessageNext Message »
From:Dmitry Shulga Date:December 11 2012 11:59am
Subject:bzr push into mysql-trunk branch (Dmitry.Shulga:5202 to 5205) WL#6030
View as plain text  
 5205 Dmitry Shulga	2012-12-11
      This is part 2 of core patch for WL#6030.
            
      This patch:
        - introduces the dynamic checking that fields in the result table row
          for INSERT statement don't have default value or
          isn't set inside BEFORE-trigger;
        - adds uniform approach to handling warnings/errors if some fields are missed
          from INSERT statement and these fields doesn't have default values;
        - handles possible missed fields and set error in Diagnostic_area if
          strict_mode is set and IGNORE isn't set in INSERT statement; 
        - modifies guint tests: replaces explicit assignement of pointer value to
          Field::m_null_ptr by call of Field::set_null_ptr();
        - adds tests for wl6030.

    added:
      mysql-test/r/trigger_wl6030.result
      mysql-test/std_data/wl6030.dat
      mysql-test/std_data/wl6030_2.dat
      mysql-test/t/trigger_wl6030.test
    modified:
      mysql-test/r/insert_select.result
      mysql-test/r/key.result
      mysql-test/r/null.result
      mysql-test/r/warnings.result
      sql/field.cc
      sql/field.h
      sql/field_conv.cc
      sql/item.h
      sql/partition_info.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_executor.cc
      sql/sql_insert.cc
      sql/sql_insert.h
      sql/sql_load.cc
      sql/sql_trigger.cc
      sql/sql_union.cc
      sql/sql_update.cc
      sql/table.cc
      sql/table.h
      tests/mysql_client_test.c
      unittest/gunit/field_date-t.cc
      unittest/gunit/field_datetime-t.cc
      unittest/gunit/field_long-t.cc
      unittest/gunit/field_newdecimal-t.cc
      unittest/gunit/mock_field_timestamp.h
      unittest/gunit/mock_field_timestampf.h
 5204 Dmitry Shulga	2012-12-11
      This is core patch for WL#6030.
      
      This patch does the following things:
        - changes Field class so that it is possible to set NOT NULL fields
          temporary to NULL;
        - allows NOT NULL fields to accept NULL values temporarily during
          BEFORE-trigger processing;
        - checks that the NOT NULL constraint is enforced after
          BEFORE-trigger processing.
        - adds support for handling NULL fields in trigger BEFORE-insert
          during execution of statement LOAD DATA INFILE.
      
      Details:
        This patch
          - changes the class Field to allow set the field in
            temporary value NULL;
          - extends interface of class Field by method check_constraints
            in order to check NOT NULL constraint for the field;
          - adds static overloaded functions check_record() into sql_base.cc
            that iterates over table's fields and checks NOT NULL constraint.
            These functions are called after trigger processing has been finished
            as part of execution function fill_records_n_invoke_before_triggers;
          - extends interface of class Table_triggers_list by two additional
            methods enable_fields_temporary_nullability() and
            disable_fields_temporary_nullability(). These methods are used in the
            function fill_record_n_invoke_before_triggers() to enable/disable
            temporary nullability for table's fields during execution of
            BEFORE trigger.
          - adds function check_that_all_fields_are_given_values(). This function
            is called after all fields that are used (explicitly or implicitly
            as part BEFORE INSERT trigger) in the statement INSERT have been
            prepared.
      
            - turns on temporary nullability for table's fields before start loading of
              file records during handling statement LOAD DATA INFILE. After records
              loading has been finished iterates over table's fields and checks
              NOT NULL constraint.

    modified:
      mysql-test/suite/funcs_1/r/innodb_trig_09.result
      mysql-test/suite/funcs_1/r/memory_trig_09.result
      mysql-test/suite/funcs_1/r/myisam_trig_09.result
      sql/field.cc
      sql/field.h
      sql/field_conv.cc
      sql/item.cc
      sql/item_sum.cc
      sql/sql_base.cc
      sql/sql_insert.cc
      sql/sql_load.cc
      sql/sql_trigger.cc
      sql/sql_trigger.h
 5203 Dmitry Shulga	2012-12-11
      This is prerequisite patch for WL#6030.
        
      This patch:
        * introduces the helper TABLE::default_values_offset()
      and uses it everywhere;
        * renames Field::null_ptr to Field::m_null_ptr and makes it
          private
        * introduces protected method Field::get_null_ptr() that encapsulates
          access to Field::m_null_ptr;
        * uses real_maybe_null() instead of Field::m_null_ptr;
        * replaces all occurences of 1 and 0 by true/false in save_in_field()
          calls and replaces all calls of is_null() with argument value 0
          by just is_null() without any argument;
        * uses Field::is_real_null() instead of Field::is_null_in_record();
        * renames Field::copy_from_tmp() to copy_data();
        * uses Field::copy_data() in the implementation of Field::set_default();
        * uses Field::is_real_null() instead of Field::is_null_in_record() in
          item_sum.cc;
        * uses Field::get_null_ptr() in field_conv.cc instead of direct use of
          Field::m_null_ptr.

    modified:
      sql/field.cc
      sql/field.h
      sql/field_conv.cc
      sql/ha_ndbcluster.cc
      sql/ha_ndbcluster_cond.h
      sql/item.cc
      sql/item.h
      sql/item_cmpfunc.cc
      sql/item_func.h
      sql/item_sum.cc
      sql/opt_range.cc
      sql/partition_info.cc
      sql/rpl_record.cc
      sql/rpl_record_old.cc
      sql/sp.cc
      sql/sql_base.cc
      sql/sql_handler.cc
      sql/sql_tmp_table.cc
      sql/table.h
      sql/unireg.cc
 5202 Joerg Bruehe	2012-12-11 [merge]
      Upmerge a merge changeset: empty

=== modified file 'mysql-test/r/insert_select.result'
--- a/mysql-test/r/insert_select.result	2012-02-29 11:17:52 +0000
+++ b/mysql-test/r/insert_select.result	2012-12-11 11:58:31 +0000
@@ -607,7 +607,6 @@ create table t2(No int not null, Field i
 insert into t2 Select null, Field, Count From t1 Where Month=20030901 and Type=2;
 Warnings:
 Warning	1048	Column 'No' cannot be null
-Warning	1048	Column 'No' cannot be null
 select * from t2;
 No	Field	Count
 0	1	100

=== modified file 'mysql-test/r/key.result'
--- a/mysql-test/r/key.result	2012-09-13 08:12:30 +0000
+++ b/mysql-test/r/key.result	2012-12-11 11:58:31 +0000
@@ -160,7 +160,6 @@ UNIQUE (c,i));
 INSERT INTO t1 (c) VALUES (NULL),(NULL);
 Warnings:
 Warning	1048	Column 'c' cannot be null
-Warning	1048	Column 'c' cannot be null
 SELECT * FROM t1;
 c	i
 	1

=== modified file 'mysql-test/r/null.result'
--- a/mysql-test/r/null.result	2011-07-19 15:11:15 +0000
+++ b/mysql-test/r/null.result	2012-12-11 11:58:31 +0000
@@ -105,7 +105,6 @@ ERROR 23000: Column 'a' cannot be null
 INSERT INTO t1 (a) values (null),(null);
 Warnings:
 Warning	1048	Column 'a' cannot be null
-Warning	1048	Column 'a' cannot be null
 INSERT INTO t1 (b) values (null);
 ERROR 23000: Column 'b' cannot be null
 INSERT INTO t1 (b) values (1/null);
@@ -113,7 +112,6 @@ ERROR 23000: Column 'b' cannot be null
 INSERT INTO t1 (b) values (null),(null);
 Warnings:
 Warning	1048	Column 'b' cannot be null
-Warning	1048	Column 'b' cannot be null
 INSERT INTO t1 (c) values (null);
 ERROR 23000: Column 'c' cannot be null
 INSERT INTO t1 (c) values (1/null);
@@ -121,7 +119,6 @@ ERROR 23000: Column 'c' cannot be null
 INSERT INTO t1 (c) values (null),(null);
 Warnings:
 Warning	1048	Column 'c' cannot be null
-Warning	1048	Column 'c' cannot be null
 INSERT INTO t1 (d) values (null);
 ERROR 23000: Column 'd' cannot be null
 INSERT INTO t1 (d) values (1/null);
@@ -129,7 +126,6 @@ ERROR 23000: Column 'd' cannot be null
 INSERT INTO t1 (d) values (null),(null);
 Warnings:
 Warning	1048	Column 'd' cannot be null
-Warning	1048	Column 'd' cannot be null
 select * from t1;
 a	b	c	d
 	0	0000-00-00 00:00:00	0

=== added file 'mysql-test/r/trigger_wl6030.result'
--- a/mysql-test/r/trigger_wl6030.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/trigger_wl6030.result	2012-12-11 11:58:31 +0000
@@ -0,0 +1,2189 @@
+#
+# WL#6030: Triggers are not processed for NOT NULL columns.
+#
+CREATE TABLE t2(a INT, b INT, c INT);
+
+###################################################################
+# Test 1: BEFORE INSERT, NOT NULL.
+#   - Test 1.1: SET to NOT NULL.
+###################################################################
+CREATE TABLE t1(a INT NOT NULL, b INT, c INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a = 1;
+INSERT INTO t2 VALUES (1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+
+# Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (NULL, 2, 3);
+INSERT INTO t1(a, b, c) VALUES (NULL, 20, 30);
+INSERT INTO t1(b, c) VALUES (200, 300);
+INSERT INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+1	20	30
+1	200	300
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (NULL, 2, 3);
+REPLACE INTO t1(a, b, c) VALUES (NULL, 20, 30);
+REPLACE INTO t1(b, c) VALUES (200, 300);
+REPLACE INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+1	20	30
+1	200	300
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+INSERT INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+1	20	30
+1	200	300
+1	2	3
+1	20	30
+1	200	300
+1	2	3
+1	20	30
+1	200	300
+1	NULL	NULL
+1	NULL	NULL
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+REPLACE INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+1	20	30
+1	200	300
+1	2	3
+1	20	30
+1	200	300
+1	2	3
+1	20	30
+1	200	300
+1	NULL	NULL
+1	NULL	NULL
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# INSERT ... SELECT.
+INSERT INTO t1 SELECT * FROM t2;
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+INSERT INTO t1(a) SELECT a FROM t2;
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+1	20	30
+1	200	300
+1	2	3
+1	20	30
+1	200	300
+1	2	3
+1	20	30
+1	200	300
+1	NULL	NULL
+1	NULL	NULL
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# REPLACE ... SELECT.
+REPLACE INTO t1 SELECT * FROM t2;
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+1	20	30
+1	200	300
+1	2	3
+1	20	30
+1	200	300
+1	2	3
+1	20	30
+1	200	300
+1	NULL	NULL
+1	NULL	NULL
+1	NULL	NULL
+
+DELETE FROM t1;
+DELETE FROM t2;
+DROP TRIGGER t1_bi;
+
+###################################################################
+#   - Test 1.2: SET to NULL.
+###################################################################
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a = NULL;
+INSERT INTO t2 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+# Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (1, 2, 3);
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(a, b, c) VALUES (1, 2, 3);
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(b, c) VALUES (2, 3);
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(a) VALUES (1);
+ERROR 23000: Column 'a' cannot be null
+
+SELECT * FROM t1;
+a	b	c
+
+DELETE FROM t1;
+
+# Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (1, 2, 3);
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(a, b, c) VALUES (1, 2, 3);
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(b, c) VALUES (2, 3);
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(a) VALUES (1);
+ERROR 23000: Column 'a' cannot be null
+
+SELECT * FROM t1;
+a	b	c
+
+DELETE FROM t1;
+
+# Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(a, b, c) VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(a) VALUES (1), (10), (100);
+ERROR 23000: Column 'a' cannot be null
+
+SELECT * FROM t1;
+a	b	c
+
+DELETE FROM t1;
+
+# Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(a, b, c) VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(a) VALUES (1), (10), (100);
+ERROR 23000: Column 'a' cannot be null
+
+SELECT * FROM t1;
+a	b	c
+
+DELETE FROM t1;
+
+# INSERT ... SELECT.
+INSERT INTO t1 SELECT * FROM t2;
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+ERROR 23000: Column 'a' cannot be null
+INSERT INTO t1(a) SELECT a FROM t2;
+ERROR 23000: Column 'a' cannot be null
+
+SELECT * FROM t1;
+a	b	c
+
+DELETE FROM t1;
+
+# REPLACE ... SELECT.
+REPLACE INTO t1 SELECT * FROM t2;
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+ERROR 23000: Column 'a' cannot be null
+REPLACE INTO t1(a) SELECT a FROM t2;
+ERROR 23000: Column 'a' cannot be null
+
+SELECT * FROM t1;
+a	b	c
+
+DELETE FROM t1;
+DROP TRIGGER t1_bi;
+
+###################################################################
+# Test 2: BEFORE UPDATE, NOT NULL.
+#   - Test 2.1: SET to NOT NULL.
+###################################################################
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW SET NEW.a = 999;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+# Regular UPDATE.
+UPDATE t1 SET a = NULL WHERE a = 1;
+UPDATE t1 SET a = NULL, c = NULL WHERE a = 100;
+
+SELECT * FROM t1;
+a	b	c
+999	2	3
+10	20	30
+999	200	NULL
+
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+# Multiple UPDATE.
+CREATE TABLE t3(a INT, b INT);
+INSERT INTO t3 VALUES (10, -10);
+UPDATE t1, t3 SET t1.a = NULL, t3.a = -20 WHERE t1.a = t3.a AND t3.a = 10;
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+999	20	30
+100	200	300
+
+SELECT * FROM t3;
+a	b
+-20	-10
+
+DROP TRIGGER t1_bu;
+DROP TABLE t3;
+DELETE FROM t1;
+CREATE TABLE t3(a INT NOT NULL, b INT);
+CREATE TRIGGER t3_bu BEFORE UPDATE ON t3 FOR EACH ROW SET NEW.a = 999;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+INSERT INTO t3 VALUES (10, -10);
+UPDATE t1, t3 SET t1.a = -20, t3.a = NULL WHERE t1.a = t3.a AND t3.a = 10;
+SELECT * FROM t1;
+a	b	c
+1	2	3
+-20	20	30
+100	200	300
+SELECT * FROM t3;
+a	b
+999	-10
+DROP TRIGGER t3_bu;
+DROP TABLE t3;
+
+#   - Test 2.1: SET to NULL.
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW SET NEW.a = NULL;
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+# Regular UPDATE.
+UPDATE t1 SET a = 99 WHERE a = 1;
+ERROR 23000: Column 'a' cannot be null
+UPDATE t1 SET a = 99, b = 99 WHERE a = 1;
+ERROR 23000: Column 'a' cannot be null
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+10	20	30
+100	200	300
+
+# Multiple UPDATE.
+CREATE TABLE t3(a INT, b INT);
+INSERT INTO t3 VALUES (10, -10);
+UPDATE t1, t3 SET t1.a = 99, t3.a = -10 WHERE t1.a = t3.a AND t3.a = 10;
+ERROR 23000: Column 'a' cannot be null
+
+SELECT * FROM t1;
+a	b	c
+1	2	3
+10	20	30
+100	200	300
+
+SELECT * FROM t3;
+a	b
+-10	-10
+
+DELETE FROM t1;
+DELETE FROM t2;
+DROP TABLE t3;
+DROP TRIGGER t1_bu;
+
+###################################################################
+# Test 3: Using illegal NULL-value as r-value.
+#   - Test 3.1: using NULL.
+###################################################################
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+SET NEW.b = NEW.a;
+SET NEW.a = 1;
+END|
+INSERT INTO t2 VALUES (1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+
+# Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (NULL, 2, 3);
+INSERT INTO t1(a, b, c) VALUES (NULL, 20, 30);
+INSERT INTO t1(b, c) VALUES (200, 300);
+INSERT INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b	c
+1	NULL	3
+1	NULL	30
+1	NULL	300
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (NULL, 2, 3);
+REPLACE INTO t1(a, b, c) VALUES (NULL, 20, 30);
+REPLACE INTO t1(b, c) VALUES (200, 300);
+REPLACE INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b	c
+1	NULL	3
+1	NULL	30
+1	NULL	300
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+INSERT INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+SELECT * FROM t1;
+a	b	c
+1	-1	3
+1	NULL	30
+1	NULL	300
+1	-2	3
+1	NULL	30
+1	NULL	300
+1	NULL	3
+1	NULL	30
+1	NULL	300
+1	-3	NULL
+1	NULL	NULL
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+REPLACE INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+SELECT * FROM t1;
+a	b	c
+1	-1	3
+1	NULL	30
+1	NULL	300
+1	-2	3
+1	NULL	30
+1	NULL	300
+1	NULL	3
+1	NULL	30
+1	NULL	300
+1	-3	NULL
+1	NULL	NULL
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# INSERT ... SELECT
+INSERT INTO t1 SELECT * FROM t2;
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+INSERT INTO t1(a) SELECT a FROM t2;
+
+SELECT * FROM t1;
+a	b	c
+1	1	3
+1	NULL	30
+1	NULL	300
+1	1	3
+1	NULL	30
+1	NULL	300
+1	NULL	3
+1	NULL	30
+1	NULL	300
+1	1	NULL
+1	NULL	NULL
+1	NULL	NULL
+
+DELETE FROM t1;
+
+# REPLACE ... SELECT
+REPLACE INTO t1 SELECT * FROM t2;
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+SELECT * FROM t1;
+a	b	c
+1	1	3
+1	NULL	30
+1	NULL	300
+1	1	3
+1	NULL	30
+1	NULL	300
+1	NULL	3
+1	NULL	30
+1	NULL	300
+1	1	NULL
+1	NULL	NULL
+1	NULL	NULL
+
+DELETE FROM t1;
+DROP TRIGGER t1_bi;
+
+###################################################################
+#   - Test 3.2: using NOT NULL.
+###################################################################
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+SET NEW.a = 99;
+SET NEW.b = NEW.a;
+END|
+
+# Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (NULL, 2, 3);
+INSERT INTO t1(a, b, c) VALUES (NULL, 20, 30);
+INSERT INTO t1(b, c) VALUES (200, 300);
+INSERT INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b	c
+99	99	3
+99	99	30
+99	99	300
+99	99	NULL
+
+DELETE FROM t1;
+
+# Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (NULL, 2, 3);
+REPLACE INTO t1(a, b, c) VALUES (NULL, 20, 30);
+REPLACE INTO t1(b, c) VALUES (200, 300);
+REPLACE INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b	c
+99	99	3
+99	99	30
+99	99	300
+99	99	NULL
+
+DELETE FROM t1;
+
+# Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+INSERT INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+SELECT * FROM t1;
+a	b	c
+99	99	3
+99	99	30
+99	99	300
+99	99	3
+99	99	30
+99	99	300
+99	99	3
+99	99	30
+99	99	300
+99	99	NULL
+99	99	NULL
+99	99	NULL
+
+DELETE FROM t1;
+
+# Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+REPLACE INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+SELECT * FROM t1;
+a	b	c
+99	99	3
+99	99	30
+99	99	300
+99	99	3
+99	99	30
+99	99	300
+99	99	3
+99	99	30
+99	99	300
+99	99	NULL
+99	99	NULL
+99	99	NULL
+
+DELETE FROM t1;
+
+# INSERT ... SELECT
+INSERT INTO t1 SELECT * FROM t2;
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+INSERT INTO t1(a) SELECT a FROM t2;
+
+SELECT * FROM t1;
+a	b	c
+99	99	3
+99	99	30
+99	99	300
+99	99	3
+99	99	30
+99	99	300
+99	99	3
+99	99	30
+99	99	300
+99	99	NULL
+99	99	NULL
+99	99	NULL
+
+DELETE FROM t1;
+
+# REPLACE ... SELECT
+REPLACE INTO t1 SELECT * FROM t2;
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+SELECT * FROM t1;
+a	b	c
+99	99	3
+99	99	30
+99	99	300
+99	99	3
+99	99	30
+99	99	300
+99	99	3
+99	99	30
+99	99	300
+99	99	NULL
+99	99	NULL
+99	99	NULL
+
+DELETE FROM t1;
+DELETE FROM t2;
+DROP TRIGGER t1_bi;
+
+###################################################################
+# Test 4: Temporarily setting to illegal NULL-value in trigger
+# (here we only check that it's possible to temporarily assign
+# NULL in triggers).
+###################################################################
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+SET NEW.a = NULL;
+SET NEW.b = NEW.a;
+SET NEW.a = 99;
+END|
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+SET NEW.a = NULL;
+SET NEW.b = NEW.a;
+SET NEW.a = 199;
+END|
+
+# Checking BEFORE INSERT trigger.
+INSERT INTO t1 VALUES (1, 2, 3);
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+SELECT * FROM t1;
+a	b	c
+99	NULL	3
+99	NULL	3
+99	NULL	30
+99	NULL	300
+
+# Checking BEFORE UPDATE trigger.
+UPDATE t1 SET b = 999 WHERE c = 300;
+SELECT * FROM t1;
+a	b	c
+99	NULL	3
+99	NULL	3
+99	NULL	30
+199	NULL	300
+
+DROP TRIGGER t1_bi;
+DROP TRIGGER t1_bu;
+DELETE FROM t1;
+
+###################################################################
+# Test 5: Using IS NULL inside trigger.
+#   - Test 5.1: BEFORE INSERT trigger.
+###################################################################
+ALTER TABLE t1 ADD COLUMN a_new_is_null BOOLEAN DEFAULT NULL;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+SET NEW.a_new_is_null = NEW.a IS NULL;
+SET NEW.a = 99;
+END|
+INSERT INTO t2 VALUES (1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+
+# Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (NULL, 2, 3, NULL);
+INSERT INTO t1(a, b, c) VALUES (NULL, 20, 30);
+INSERT INTO t1(b, c) VALUES (200, 300);
+INSERT INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b	c	a_new_is_null
+99	2	3	1
+99	20	30	1
+99	200	300	1
+99	NULL	NULL	1
+
+DELETE FROM t1;
+
+# Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (NULL, 2, 3, NULL);
+REPLACE INTO t1(a, b, c) VALUES (NULL, 20, 30);
+REPLACE INTO t1(b, c) VALUES (200, 300);
+REPLACE INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b	c	a_new_is_null
+99	2	3	1
+99	20	30	1
+99	200	300	1
+99	NULL	NULL	1
+
+DELETE FROM t1;
+
+# Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES
+(-1, 2, 3, NULL), (NULL, 20, 30, NULL), (NULL, 200, 300, NULL);
+INSERT INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+INSERT INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+SELECT * FROM t1;
+a	b	c	a_new_is_null
+99	2	3	0
+99	20	30	1
+99	200	300	1
+99	2	3	0
+99	20	30	1
+99	200	300	1
+99	2	3	1
+99	20	30	1
+99	200	300	1
+99	NULL	NULL	0
+99	NULL	NULL	1
+99	NULL	NULL	1
+
+DELETE FROM t1;
+
+# Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES
+(-1, 2, 3, NULL), (NULL, 20, 30, NULL), (NULL, 200, 300, NULL);
+REPLACE INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+REPLACE INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+SELECT * FROM t1;
+a	b	c	a_new_is_null
+99	2	3	0
+99	20	30	1
+99	200	300	1
+99	2	3	0
+99	20	30	1
+99	200	300	1
+99	2	3	1
+99	20	30	1
+99	200	300	1
+99	NULL	NULL	0
+99	NULL	NULL	1
+99	NULL	NULL	1
+
+DELETE FROM t1;
+
+# INSERT ... SELECT
+INSERT INTO t1 SELECT t2.*, NULL FROM t2;
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+INSERT INTO t1(a) SELECT a FROM t2;
+
+SELECT * FROM t1;
+a	b	c	a_new_is_null
+99	2	3	0
+99	20	30	1
+99	200	300	1
+99	2	3	0
+99	20	30	1
+99	200	300	1
+99	2	3	1
+99	20	30	1
+99	200	300	1
+99	NULL	NULL	0
+99	NULL	NULL	1
+99	NULL	NULL	1
+
+DELETE FROM t1;
+
+# REPLACE ... SELECT
+REPLACE INTO t1 SELECT t2.*, NULL FROM t2;
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+SELECT * FROM t1;
+a	b	c	a_new_is_null
+99	2	3	0
+99	20	30	1
+99	200	300	1
+99	2	3	0
+99	20	30	1
+99	200	300	1
+99	2	3	1
+99	20	30	1
+99	200	300	1
+99	NULL	NULL	0
+99	NULL	NULL	1
+99	NULL	NULL	1
+
+DELETE FROM t1;
+DROP TRIGGER t1_bi;
+
+###################################################################
+#   - Test 5.2: BEFORE UPDATE trigger.
+###################################################################
+ALTER TABLE t1 ADD COLUMN a_old_is_null BOOLEAN DEFAULT NULL;
+ALTER TABLE t1 ADD COLUMN b_new_is_null BOOLEAN DEFAULT NULL;
+ALTER TABLE t1 ADD COLUMN b_old_is_null BOOLEAN DEFAULT NULL;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+SET NEW.a_new_is_null = NEW.a IS NULL;
+SET NEW.a_old_is_null = OLD.a IS NULL;
+SET NEW.b_new_is_null = NEW.b IS NULL;
+SET NEW.b_old_is_null = OLD.b IS NULL;
+SET NEW.a = 99;
+END|
+INSERT INTO t1(a, b, c) VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+# Regular UPDATE.
+UPDATE t1 SET a = NULL WHERE a = 1;
+UPDATE t1 SET a = NULL, c = NULL WHERE a = 10;
+UPDATE t1 SET b = NULL WHERE a = 100;
+
+SELECT * FROM t1;
+a	b	c	a_new_is_null	a_old_is_null	b_new_is_null	b_old_is_null
+99	2	3	1	0	0	0
+99	20	NULL	1	0	0	0
+99	NULL	300	0	0	1	0
+
+DELETE FROM t1;
+INSERT INTO t1(a, b, c) VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+# Multiple UPDATE.
+CREATE TABLE t3(a INT, b INT);
+INSERT INTO t3 VALUES (10, -10);
+UPDATE t1, t3 SET t1.a = NULL, t3.a = -20 WHERE t1.a = t3.a AND t3.a = 10;
+
+SELECT * FROM t1;
+a	b	c	a_new_is_null	a_old_is_null	b_new_is_null	b_old_is_null
+1	2	3	NULL	NULL	NULL	NULL
+99	20	30	0	0	0	0
+100	200	300	NULL	NULL	NULL	NULL
+
+SELECT * FROM t3;
+a	b
+-20	-10
+
+DROP TABLE t3;
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+DROP TABLE t2;
+
+###################################################################
+# Test 6: Nullability of non-updated columns.
+###################################################################
+CREATE TABLE t1(a INT, b INT NOT NULL);
+
+# - Unconditional SET in a trigger.
+
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+SET NEW.b = NULL;
+
+INSERT INTO t1(a) VALUES (1);
+ERROR 23000: Column 'b' cannot be null
+
+REPLACE INTO t1(a) VALUES (1);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+DELETE FROM t1;
+DROP TRIGGER t1_bi;
+
+# - Conditional SET in a trigger, which is executed for every row.
+
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+SET NEW.b = NEW.a;
+IF NEW.b IS NULL THEN
+SET NEW.b = 1;
+END IF;
+END|
+
+INSERT INTO t1(a) VALUES (NULL);
+
+REPLACE INTO t1(a) VALUES (NULL);
+
+SELECT * FROM t1;
+a	b
+NULL	1
+NULL	1
+DELETE FROM t1;
+DROP TRIGGER t1_bi;
+
+# - Conditional SET in a trigger, which is NOT executed for every row.
+
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+IF (MOD(NEW.a, 2) = 0) THEN
+SET NEW.b = NEW.a - 1;
+END IF;
+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;
+a	b
+1	0
+2	1
+3	0
+4	3
+5	0
+6	5
+1	0
+2	1
+3	0
+4	3
+5	0
+6	5
+DROP TABLE t1;
+
+###################################################################
+# Test 7: Nullability of column being copied as result of INSERT SELECT.
+###################################################################
+CREATE TABLE t1(a INT NOT NULL);
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES (NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+SET NEW.a = 1;
+
+INSERT INTO t1 SELECT * FROM t2;
+REPLACE INTO t1 SELECT * FROM t2;
+
+SELECT * FROM t1;
+a
+1
+1
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1,t2;
+CREATE TABLE t1(a INT NOT NULL);
+INSERT INTO t1 VALUES (1);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+SET NEW.a = 2;
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES (NULL);
+
+UPDATE t1, t2 SET t1.a = t2.a;
+
+SELECT * FROM t1;
+a
+2
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1,t2;
+
+###################################################################
+# Test 8: Nullability of column being copied as result of
+#         LOAD DATA INFILE.
+###################################################################
+CREATE TABLE t1 (a INT NOT NULL, b VARCHAR(10) NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+IF NEW.b IS NULL THEN
+SET NEW.b = '123';
+END IF;
+END |
+LOAD DATA INFILE '../../std_data/wl6030.dat' INTO TABLE t1 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+SELECT * FROM t1;
+a	b
+457	123
+321	text
+579	123
+789	
+
+987	123
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+###################################################################
+# Misc tests.
+###################################################################
+
+CREATE TABLE t1(a INT, b INT NOT NULL);
+CREATE VIEW v1 AS SELECT * FROM t1;
+CREATE TABLE t2(a INT, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL);
+CREATE VIEW v2 AS SELECT * FROM t2;
+CREATE TABLE t1_data(a INT, b INT);
+INSERT INTO t1_data VALUES
+(11, 12),
+(NULL, 22),
+(31, NULL),
+(NULL, NULL);
+CREATE TABLE t2_data(a INT, b INT, c INT, d INT);
+INSERT INTO t2_data VALUES
+(11, 12, 13, 14),
+(NULL, 22, 23, 24),
+(31, NULL, 33, 34),
+(41, 42, NULL, 44),
+(51, 52, 53, NULL),
+(NULL, NULL, NULL, NULL);
+SET @sql_mode_saved = @@sql_mode;
+
+###################################################################
+# Checking permissive SQL_MODE.
+###################################################################
+
+SET sql_mode = '';
+
+#------------------------------------------------------------------
+# Checking INSERT INTO ... VALUES ...
+#------------------------------------------------------------------
+
+#   - No column list (all columns) + NULL-value for NOT NULL column.
+
+INSERT INTO t1 VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+INSERT INTO v1 VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+
+REPLACE INTO t1 VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+REPLACE INTO v1 VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+
+INSERT INTO t2 VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+INSERT INTO v2 VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+
+REPLACE INTO t2 VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+REPLACE INTO v2 VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+
+#   - All columns + NULL-value for NOT NULL column.
+
+INSERT INTO v1(a, b) VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+INSERT INTO t1(a, b) VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+
+REPLACE INTO v1(a, b) VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+REPLACE INTO t1(a, b) VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+
+INSERT INTO t2(a, b, c, d) VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+INSERT INTO v2(a, b, c, d) VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+
+REPLACE INTO t2(a, b, c, d) VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+REPLACE INTO v2(a, b, c, d) VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+
+#   - Single nullable column, no values for NOT NULL columns.
+#     Expect exactly 4 warnings and 8 rows being inserted into t1.
+
+INSERT INTO t1(a) VALUES (1);
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+INSERT INTO t1(a) VALUES (2), (3), (4);
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+INSERT INTO v1(a) VALUES (5);
+Warnings:
+Warning	1423	Field of view 'test.v1' underlying table doesn't have a default value
+INSERT INTO v1(a) VALUES (6), (7), (8);
+Warnings:
+Warning	1423	Field of view 'test.v1' underlying table doesn't have a default value
+
+SELECT * FROM t1;
+a	b
+1	0
+2	0
+3	0
+4	0
+5	0
+6	0
+7	0
+8	0
+DELETE FROM t1;
+
+REPLACE INTO t1(a) VALUES (1);
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+REPLACE INTO t1(a) VALUES (2), (3), (4);
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+REPLACE INTO v1(a) VALUES (5);
+Warnings:
+Warning	1423	Field of view 'test.v1' underlying table doesn't have a default value
+REPLACE INTO v1(a) VALUES (6), (7), (8);
+Warnings:
+Warning	1423	Field of view 'test.v1' underlying table doesn't have a default value
+
+SELECT * FROM t1;
+a	b
+1	0
+2	0
+3	0
+4	0
+5	0
+6	0
+7	0
+8	0
+DELETE FROM t1;
+
+INSERT INTO t2(a) VALUES (1);
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+Warning	1364	Field 'c' doesn't have a default value
+Warning	1364	Field 'd' doesn't have a default value
+INSERT INTO t2(a) VALUES (2), (3), (4);
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+Warning	1364	Field 'c' doesn't have a default value
+Warning	1364	Field 'd' doesn't have a default value
+INSERT INTO v2(a) VALUES (5);
+Warnings:
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+INSERT INTO v2(a) VALUES (6), (7), (8);
+Warnings:
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+
+SELECT * FROM t2;
+a	b	c	d
+1	0	0	0
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+6	0	0	0
+7	0	0	0
+8	0	0	0
+DELETE FROM t2;
+
+REPLACE INTO t2(a) VALUES (1);
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+Warning	1364	Field 'c' doesn't have a default value
+Warning	1364	Field 'd' doesn't have a default value
+REPLACE INTO t2(a) VALUES (2), (3), (4);
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+Warning	1364	Field 'c' doesn't have a default value
+Warning	1364	Field 'd' doesn't have a default value
+REPLACE INTO v2(a) VALUES (5);
+Warnings:
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+REPLACE INTO v2(a) VALUES (6), (7), (8);
+Warnings:
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+
+SELECT * FROM t2;
+a	b	c	d
+1	0	0	0
+2	0	0	0
+3	0	0	0
+4	0	0	0
+5	0	0	0
+6	0	0	0
+7	0	0	0
+8	0	0	0
+DELETE FROM t2;
+
+#------------------------------------------------------------------
+# Checking INSERT INTO ... SELECT ...
+#------------------------------------------------------------------
+
+#   - No column list (all columns) + NULL-value for NOT NULL column.
+#     Expect 4 warnings for each statement.
+
+INSERT INTO t1 SELECT * FROM t1_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+INSERT INTO v1 SELECT a * 10, b * 10 FROM t1_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+11	12
+NULL	22
+31	0
+NULL	0
+110	120
+NULL	220
+310	0
+NULL	0
+DELETE FROM t1;
+
+REPLACE INTO t1 SELECT * FROM t1_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+REPLACE INTO v1 SELECT a * 10, b * 10 FROM t1_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+11	12
+NULL	22
+31	0
+NULL	0
+110	120
+NULL	220
+310	0
+NULL	0
+DELETE FROM t1;
+
+#   - No column list (all columns) + NULL-value for NOT NULL column.
+#     Expect 4 warnings for each statement.
+
+INSERT INTO t2 SELECT * FROM t2_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+Warning	1048	Column 'c' cannot be null
+Warning	1048	Column 'd' cannot be null
+INSERT INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+Warning	1048	Column 'c' cannot be null
+Warning	1048	Column 'd' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+31	0	33	34
+41	42	0	44
+51	52	53	0
+NULL	0	0	0
+110	120	130	140
+NULL	220	230	240
+310	0	330	340
+410	420	0	440
+510	520	530	0
+NULL	0	0	0
+DELETE FROM t2;
+
+REPLACE INTO t2 SELECT * FROM t2_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+Warning	1048	Column 'c' cannot be null
+Warning	1048	Column 'd' cannot be null
+REPLACE INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+Warning	1048	Column 'c' cannot be null
+Warning	1048	Column 'd' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+31	0	33	34
+41	42	0	44
+51	52	53	0
+NULL	0	0	0
+110	120	130	140
+NULL	220	230	240
+310	0	330	340
+410	420	0	440
+510	520	530	0
+NULL	0	0	0
+DELETE FROM t2;
+
+#   - All columns + NULL-value for NOT NULL column.
+#     Expect 4 warnings for each statement.
+
+INSERT INTO t1(a, b) SELECT * FROM t1_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+INSERT INTO v1(a, b) SELECT a * 10, b * 10 FROM t1_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+11	12
+NULL	22
+31	0
+NULL	0
+110	120
+NULL	220
+310	0
+NULL	0
+DELETE FROM t1;
+
+REPLACE INTO t1(a, b) SELECT * FROM t1_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+REPLACE INTO v1(a, b) SELECT a * 10, b * 10 FROM t1_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+11	12
+NULL	22
+31	0
+NULL	0
+110	120
+NULL	220
+310	0
+NULL	0
+DELETE FROM t1;
+
+INSERT INTO t2(a, b, c, d) SELECT * FROM t2_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+Warning	1048	Column 'c' cannot be null
+Warning	1048	Column 'd' cannot be null
+INSERT INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+Warning	1048	Column 'c' cannot be null
+Warning	1048	Column 'd' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+31	0	33	34
+41	42	0	44
+51	52	53	0
+NULL	0	0	0
+110	120	130	140
+NULL	220	230	240
+310	0	330	340
+410	420	0	440
+510	520	530	0
+NULL	0	0	0
+DELETE FROM t2;
+
+REPLACE INTO t2(a, b, c, d) SELECT * FROM t2_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+Warning	1048	Column 'c' cannot be null
+Warning	1048	Column 'd' cannot be null
+REPLACE INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+Warnings:
+Warning	1048	Column 'b' cannot be null
+Warning	1048	Column 'c' cannot be null
+Warning	1048	Column 'd' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+31	0	33	34
+41	42	0	44
+51	52	53	0
+NULL	0	0	0
+110	120	130	140
+NULL	220	230	240
+310	0	330	340
+410	420	0	440
+510	520	530	0
+NULL	0	0	0
+DELETE FROM t2;
+
+#   - Single nullable column, no values for NOT NULL columns.
+#     Expect 4 warnings for each statement.
+
+INSERT INTO t1(a) SELECT a FROM t1_data;
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+INSERT INTO v1(a) SELECT a * 100 FROM t1_data;
+Warnings:
+Warning	1423	Field of view 'test.v1' underlying table doesn't have a default value
+
+SELECT * FROM t1;
+a	b
+11	0
+NULL	0
+31	0
+NULL	0
+1100	0
+NULL	0
+3100	0
+NULL	0
+DELETE FROM t1;
+
+REPLACE INTO t1(a) SELECT a FROM t1_data;
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+REPLACE INTO v1(a) SELECT a * 100 FROM t1_data;
+Warnings:
+Warning	1423	Field of view 'test.v1' underlying table doesn't have a default value
+
+SELECT * FROM t1;
+a	b
+11	0
+NULL	0
+31	0
+NULL	0
+1100	0
+NULL	0
+3100	0
+NULL	0
+DELETE FROM t1;
+
+INSERT INTO t2(a) SELECT a FROM t2_data;
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+Warning	1364	Field 'c' doesn't have a default value
+Warning	1364	Field 'd' doesn't have a default value
+INSERT INTO v2(a) SELECT a * 100 FROM t2_data;
+Warnings:
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+
+SELECT * FROM t2;
+a	b	c	d
+11	0	0	0
+NULL	0	0	0
+31	0	0	0
+41	0	0	0
+51	0	0	0
+NULL	0	0	0
+1100	0	0	0
+NULL	0	0	0
+3100	0	0	0
+4100	0	0	0
+5100	0	0	0
+NULL	0	0	0
+DELETE FROM t2;
+
+REPLACE INTO t2(a) SELECT a FROM t2_data;
+Warnings:
+Warning	1364	Field 'b' doesn't have a default value
+Warning	1364	Field 'c' doesn't have a default value
+Warning	1364	Field 'd' doesn't have a default value
+REPLACE INTO v2(a) SELECT a * 100 FROM t2_data;
+Warnings:
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+Warning	1423	Field of view 'test.v2' underlying table doesn't have a default value
+
+SELECT * FROM t2;
+a	b	c	d
+11	0	0	0
+NULL	0	0	0
+31	0	0	0
+41	0	0	0
+51	0	0	0
+NULL	0	0	0
+1100	0	0	0
+NULL	0	0	0
+3100	0	0	0
+4100	0	0	0
+5100	0	0	0
+NULL	0	0	0
+DELETE FROM t2;
+
+#------------------------------------------------------------------
+# Checking LOAD DATA INFILE ...
+#------------------------------------------------------------------
+
+LOAD DATA INFILE '../../std_data/wl6030_2.dat' INTO TABLE t2 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+Warnings:
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'b' at row 3
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'c' at row 4
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'd' at row 5
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'b' at row 6
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'c' at row 6
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'd' at row 6
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'b' at row 7
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'c' at row 8
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'd' at row 9
+
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+31	0	33	34
+41	42	0	44
+51	52	53	0
+NULL	0	0	0
+NULL	0	73	74
+NULL	82	0	84
+NULL	92	93	0
+
+DELETE FROM t2;
+LOAD DATA INFILE '../../std_data/wl6030_2.dat' INTO TABLE v2 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+Warnings:
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'b' at row 3
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'c' at row 4
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'd' at row 5
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'b' at row 6
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'c' at row 6
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'd' at row 6
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'b' at row 7
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'c' at row 8
+Warning	1263	Column set to default value; NULL supplied to NOT NULL column 'd' at row 9
+
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+31	0	33	34
+41	42	0	44
+51	52	53	0
+NULL	0	0	0
+NULL	0	73	74
+NULL	82	0	84
+NULL	92	93	0
+
+DELETE FROM t2;
+
+###################################################################
+# Checking strict SQL_MODE.
+###################################################################
+
+SET sql_mode = 'traditional';
+
+#------------------------------------------------------------------
+# Checking INSERT INTO ... VALUES ...
+#------------------------------------------------------------------
+
+#   - No column list (all columns) + NULL-value for NOT NULL column.
+
+INSERT INTO t1 VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+INSERT INTO v1 VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+
+REPLACE INTO t1 VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+REPLACE INTO v1 VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+
+INSERT INTO t2 VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+INSERT INTO v2 VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+
+REPLACE INTO t2 VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+REPLACE INTO v2 VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+
+#   - All columns + NULL-value for NOT NULL column.
+
+INSERT INTO v1(a, b) VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+INSERT INTO t1(a, b) VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+
+REPLACE INTO v1(a, b) VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+REPLACE INTO t1(a, b) VALUES (1, NULL);
+ERROR 23000: Column 'b' cannot be null
+
+SELECT * FROM t1;
+a	b
+
+INSERT INTO t2(a, b, c, d) VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+INSERT INTO v2(a, b, c, d) VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+
+REPLACE INTO t2(a, b, c, d) VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+REPLACE INTO v2(a, b, c, d) VALUES (1, 2, NULL, 4);
+ERROR 23000: Column 'c' cannot be null
+
+SELECT * FROM t2;
+a	b	c	d
+
+#   - Single nullable column, no values for NOT NULL columns.
+
+INSERT INTO t1(a) VALUES (1);
+ERROR HY000: Field 'b' doesn't have a default value
+INSERT INTO t1(a) VALUES (2), (3), (4);
+ERROR HY000: Field 'b' doesn't have a default value
+INSERT INTO v1(a) VALUES (5);
+ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
+INSERT INTO v1(a) VALUES (6), (7), (8);
+ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
+
+SELECT * FROM t1;
+a	b
+DELETE FROM t1;
+
+REPLACE INTO t1(a) VALUES (1);
+ERROR HY000: Field 'b' doesn't have a default value
+REPLACE INTO t1(a) VALUES (2), (3), (4);
+ERROR HY000: Field 'b' doesn't have a default value
+REPLACE INTO v1(a) VALUES (5);
+ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
+REPLACE INTO v1(a) VALUES (6), (7), (8);
+ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
+
+SELECT * FROM t1;
+a	b
+DELETE FROM t1;
+
+INSERT INTO t2(a) VALUES (1);
+ERROR HY000: Field 'b' doesn't have a default value
+INSERT INTO t2(a) VALUES (2), (3), (4);
+ERROR HY000: Field 'b' doesn't have a default value
+INSERT INTO v2(a) VALUES (5);
+ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
+INSERT INTO v2(a) VALUES (6), (7), (8);
+ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
+
+SELECT * FROM t2;
+a	b	c	d
+DELETE FROM t2;
+
+REPLACE INTO t2(a) VALUES (1);
+ERROR HY000: Field 'b' doesn't have a default value
+REPLACE INTO t2(a) VALUES (2), (3), (4);
+ERROR HY000: Field 'b' doesn't have a default value
+REPLACE INTO v2(a) VALUES (5);
+ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
+REPLACE INTO v2(a) VALUES (6), (7), (8);
+ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
+
+SELECT * FROM t2;
+a	b	c	d
+DELETE FROM t2;
+
+#------------------------------------------------------------------
+# Checking INSERT INTO ... SELECT ...
+#------------------------------------------------------------------
+
+#   - No column list (all columns) + NULL-value for NOT NULL column.
+
+INSERT INTO t1 SELECT * FROM t1_data;
+ERROR 23000: Column 'b' cannot be null
+INSERT INTO v1 SELECT a * 10, b * 10 FROM t1_data;
+ERROR 23000: Column 'b' cannot be null
+
+# The following SELECT output should have 4 rows.
+# t1's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t1;
+a	b
+11	12
+NULL	22
+110	120
+NULL	220
+DELETE FROM t1;
+
+REPLACE INTO t1 SELECT * FROM t1_data;
+ERROR 23000: Column 'b' cannot be null
+REPLACE INTO v1 SELECT a * 10, b * 10 FROM t1_data;
+ERROR 23000: Column 'b' cannot be null
+
+# The following SELECT output should have 4 rows.
+# t1's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t1;
+a	b
+11	12
+NULL	22
+110	120
+NULL	220
+DELETE FROM t1;
+
+#   - No column list (all columns) + NULL-value for NOT NULL column.
+INSERT INTO t2 SELECT * FROM t2_data;
+ERROR 23000: Column 'b' cannot be null
+INSERT INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+ERROR 23000: Column 'b' cannot be null
+
+# The following SELECT output should have 4 rows.
+# t2's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+110	120	130	140
+NULL	220	230	240
+DELETE FROM t2;
+
+#   - No column list (all columns) + NULL-value for NOT NULL column.
+REPLACE INTO t2 SELECT * FROM t2_data;
+ERROR 23000: Column 'b' cannot be null
+REPLACE INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+ERROR 23000: Column 'b' cannot be null
+
+# The following SELECT output should have 4 rows.
+# t2's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+110	120	130	140
+NULL	220	230	240
+DELETE FROM t2;
+
+#   - All columns + NULL-value for NOT NULL column.
+
+INSERT INTO t1(a, b) SELECT * FROM t1_data;
+ERROR 23000: Column 'b' cannot be null
+INSERT INTO v1(a, b) SELECT a * 10, b * 10 FROM t1_data;
+ERROR 23000: Column 'b' cannot be null
+
+# The following SELECT output should have 4 rows.
+# t1's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t1;
+a	b
+11	12
+NULL	22
+110	120
+NULL	220
+DELETE FROM t1;
+
+REPLACE INTO t1(a, b) SELECT * FROM t1_data;
+ERROR 23000: Column 'b' cannot be null
+REPLACE INTO v1(a, b) SELECT a * 10, b * 10 FROM t1_data;
+ERROR 23000: Column 'b' cannot be null
+
+# The following SELECT output should have 4 rows.
+# t1's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t1;
+a	b
+11	12
+NULL	22
+110	120
+NULL	220
+DELETE FROM t1;
+
+INSERT INTO t2(a, b, c, d) SELECT * FROM t2_data;
+ERROR 23000: Column 'b' cannot be null
+INSERT INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+ERROR 23000: Column 'b' cannot be null
+
+# The following SELECT output should have 4 rows.
+# t2's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+110	120	130	140
+NULL	220	230	240
+DELETE FROM t2;
+
+REPLACE INTO t2(a, b, c, d) SELECT * FROM t2_data;
+ERROR 23000: Column 'b' cannot be null
+REPLACE INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+ERROR 23000: Column 'b' cannot be null
+
+# The following SELECT output should have 4 rows.
+# t2's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+110	120	130	140
+NULL	220	230	240
+DELETE FROM t2;
+
+#   - Single nullable column, no values for NOT NULL columns.
+
+INSERT INTO t1(a) SELECT a FROM t1_data;
+ERROR HY000: Field 'b' doesn't have a default value
+INSERT INTO v1(a) SELECT a * 100 FROM t1_data;
+ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
+
+# The following SELECT output should have 0 rows.
+SELECT * FROM t1;
+a	b
+DELETE FROM t1;
+
+REPLACE INTO t1(a) SELECT a FROM t1_data;
+ERROR HY000: Field 'b' doesn't have a default value
+REPLACE INTO v1(a) SELECT a * 100 FROM t1_data;
+ERROR HY000: Field of view 'test.v1' underlying table doesn't have a default value
+
+# The following SELECT output should have 0 rows.
+SELECT * FROM t1;
+a	b
+DELETE FROM t1;
+
+INSERT INTO t2(a) SELECT a FROM t2_data;
+ERROR HY000: Field 'b' doesn't have a default value
+INSERT INTO v2(a) SELECT a * 100 FROM t2_data;
+ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
+
+# The following SELECT output should have 0 rows.
+SELECT * FROM t2;
+a	b	c	d
+DELETE FROM t2;
+
+REPLACE INTO t2(a) SELECT a FROM t2_data;
+ERROR HY000: Field 'b' doesn't have a default value
+REPLACE INTO v2(a) SELECT a * 100 FROM t2_data;
+ERROR HY000: Field of view 'test.v2' underlying table doesn't have a default value
+
+# The following SELECT output should have 0 rows.
+SELECT * FROM t2;
+a	b	c	d
+DELETE FROM t2;
+
+#------------------------------------------------------------------
+# Checking LOAD DATA INFILE ...
+#------------------------------------------------------------------
+LOAD DATA INFILE '../../std_data/wl6030_2.dat' INTO TABLE t2 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+ERROR 22004: Column set to default value; NULL supplied to NOT NULL column 'b' at row 3
+
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+
+DELETE FROM t2;
+LOAD DATA INFILE '../../std_data/wl6030_2.dat' INTO TABLE v2 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+ERROR 22004: Column set to default value; NULL supplied to NOT NULL column 'b' at row 3
+
+SELECT * FROM t2;
+a	b	c	d
+11	12	13	14
+NULL	22	23	24
+
+SET sql_mode = @sql_mode_saved;
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t1_data;
+DROP TABLE t2_data;
+DROP VIEW v1;
+DROP VIEW v2;
+
+#------------------------------------------------------------------
+# The following tests were suggested by QA
+#------------------------------------------------------------------
+
+"Test UPDATE SET inside trigger body"
+CREATE TABLE t1(a1 INT NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+UPDATE t1 SET NEW.a1 = 1 WHERE a1 IS NULL;
+INSERT INTO t1 VALUES (NULL);
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for recursive trigger"
+CREATE TABLE t1(a1 INT NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+UPDATE t1 SET NEW.a1 = 1;
+INSERT INTO t1 VALUES (NULL);
+ERROR HY000: Can't update table 't1' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for IFNULL inside trigger body"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 2);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+BEGIN
+SET NEW.a1 = IFNULL(NEW.a1, 10);
+SET NEW.a2 = IFNULL(NEW.a2, 20);
+END;
+|
+INSERT INTO t1 VALUES (NULL, 1);
+SELECT * FROM t1;
+a1	a2
+1	2
+10	1
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for COALESCE Inside trigger body"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+BEGIN
+SET NEW.a1 = COALESCE(NEW.a1, 5);
+SET NEW.a2 = COALESCE(NEW.a2, 7);
+END;
+|
+INSERT INTO t1 VALUES (NULL, 3);
+SELECT * FROM t1;
+a1	a2
+1	1
+5	3
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for PRIMARY KEY"
+CREATE TABLE t1 (a1 INT PRIMARY KEY);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 2;
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+a1
+2
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for PRIMARY KEY (constraint violation)"
+CREATE TABLE t1 (a1 INT PRIMARY KEY);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 1;
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+a1
+1
+INSERT INTO t1 VALUES (NULL);
+ERROR 23000: Duplicate entry '1' for key 'PRIMARY'
+SELECT * FROM t1;
+a1
+1
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for UNIQUE column"
+CREATE TABLE t1(a1 INT UNIQUE);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 1;
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+a1
+1
+INSERT INTO t1 VALUES (NULL);
+ERROR 23000: Duplicate entry '1' for key 'a1'
+SELECT * FROM t1;
+a1
+1
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for date/timestamp datatype"
+CREATE TABLE t1(a1 DATE NOT NULL, a2 TIMESTAMP NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = '2012-03-03', NEW.a2 = '2001-01-01 09:01:00';
+INSERT INTO t1 VALUES (NULL, NULL);
+SELECT * FROM t1;
+a1	a2
+2012-03-03	2001-01-01 09:01:00
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for CHAR/VARCHAR datatype"
+CREATE TABLE t1(a1 CHAR(10) NOT NULL, a2 VARCHAR(255) NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 'MySQL' , NEW.a2 = 'Includes testing of MySQL';
+INSERT INTO t1 VALUES (NULL, NULL);
+SELECT * FROM t1;
+a1	a2
+MySQL	Includes testing of MySQL
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for BINARY/VARBINARY datatype"
+CREATE TABLE t1(a1 BINARY(10) NOT NULL, a2 VARBINARY(255) NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = '0x41', NEW.a2 = '0x42';
+INSERT INTO t1 VALUES (NULL, NULL);
+SELECT * FROM t1;
+a1	a2
+0x41	0x42
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for UNIQUE column‚ constraint violation"
+CREATE TABLE t1(a1 INT UNIQUE, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 1;
+INSERT INTO t1 VALUES (NULL, 2);
+ERROR 23000: Duplicate entry '1' for key 'a1'
+SELECT * FROM t1;
+a1	a2
+1	1
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for UPDATE .. SET .. SELECT"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT);
+CREATE TABLE t2(a1 INT NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t2 VALUES (1, NULL);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = 2;
+UPDATE t1 SET a1 = (SELECT a2 FROM t2);
+SELECT * FROM t1;
+a1	a2
+2	NULL
+DROP TRIGGER t1_bu;
+DROP TABLE t1, t2;
+"Test for multi table update (across engines)"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT) ENGINE = INNODB;
+CREATE TABLE t2(a1 INT NOT NULL, a2 INT) ENGINE = MyISAM;
+INSERT INTO t1 VALUES (1, NULL),(2, 2);
+INSERT INTO t2 VALUES (1, NULL),(2876543, 2098);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = 10;
+CREATE TRIGGER t2_bu BEFORE UPDATE ON t2
+FOR EACH ROW
+SET NEW.a1 = 20;
+UPDATE t1, t2 SET t1.a1 = NULL , t2.a1 = NULL;
+SELECT * FROM t1;
+a1	a2
+10	NULL
+10	2
+SELECT * FROM t2;
+a1	a2
+20	NULL
+20	2098
+DROP TRIGGER t1_bu;
+DROP TRIGGER t2_bu;
+DROP TABLE t1, t2;
+"Test for update on PRIMARY KEY"
+CREATE TABLE t1(a1 INT PRIMARY KEY, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = 2;
+UPDATE t1 SET a1 =  NULL;
+SELECT * FROM t1;
+a1	a2
+2	1
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+"Test for update on UNIQUE column"
+CREATE TABLE t1(a1 INT UNIQUE NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = 2;
+UPDATE t1 SET a1 =  NULL;
+SELECT * FROM t1;
+a1	a2
+2	1
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+"INSERT NOT NULL into NOT NULL column if BEFORE INSERT trigger sets it to NULL."
+"Test for PRIMARY KEY"
+CREATE TABLE t1(a1 INT PRIMARY KEY, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+INSERT INTO t1 VALUES (2, 2);
+ERROR 23000: Column 'a1' cannot be null
+SELECT * FROM t1;
+a1	a2
+1	1
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for UNIQUE column"
+CREATE TABLE t1(a1 INT UNIQUE NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+INSERT INTO t1 VALUES (2, 2),(3,3);
+ERROR 23000: Column 'a1' cannot be null
+SELECT * FROM t1;
+a1	a2
+1	1
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for timestamp"
+CREATE TABLE t1(a1 DATE NOT NULL, a2 TIMESTAMP NOT NULL, a3 TIMESTAMP NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL , NEW.a2 = NULL , NEW.a3 = NULL;
+INSERT INTO t1 VALUES ('2012-12-12','2012-12-12 12:12:12','1980-01-01 01:01:01');
+ERROR 23000: Column 'a1' cannot be null
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for CHAR/VARCHAR datatype"
+CREATE TABLE t1(a1 CHAR(10) NOT NULL, a2 VARCHAR(255) NOT NULL, a3 INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL , NEW.a2 = NULL;
+INSERT INTO t1 VALUES ('MySQL','MySQL Testing', 1);
+ERROR 23000: Column 'a1' cannot be null
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"Test for BINARY/VARBINARY datatype"
+CREATE TABLE t1(a1 BINARY(10) NOT NULL, a2 VARBINARY(255) NOT NULL, a3 INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL , NEW.a2 = NULL;
+INSERT INTO t1 VALUES ('0x101','0x101', 1);
+ERROR 23000: Column 'a1' cannot be null
+SELECT * FROM t1;
+a1	a2	a3
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+"UPDATE NOT NULL into NOT NULL column if BEFORE UPDATE trigger sets it to NULL."
+"Test for UPDATE .. SET .. SELECT"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT) ;
+CREATE TABLE t2(a1 INT NOT NULL, a2 INT) ;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t2 VALUES (1, 1);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+UPDATE t1 SET a1 = (SELECT MAX(a2) FROM t2);
+ERROR 23000: Column 'a1' cannot be null
+SELECT * FROM t1;
+a1	a2
+1	1
+SELECT * FROM t2;
+a1	a2
+1	1
+DROP TRIGGER t1_bu;
+DROP TABLE t1, t2;
+"Test for multi table update (across engines)"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT) ENGINE = INNODB;
+CREATE TABLE t2(a1 INT NOT NULL, a2 INT) ENGINE = MyISAM;
+INSERT INTO t1 VALUES (1, NULL),(2, 2);
+INSERT INTO t2 VALUES (1, NULL),(2876543, 20111098);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+UPDATE t1, t2 SET t1.a1 = 1 , t2.a1 = 2;
+ERROR 23000: Column 'a1' cannot be null
+SELECT * FROM t1;
+a1	a2
+1	NULL
+2	2
+SELECT * FROM t2;
+a1	a2
+1	NULL
+2876543	20111098
+DROP TRIGGER t1_bu;
+DROP TABLE t1, t2;
+"Test for update on PRIMARY KEY"
+CREATE TABLE t1(a1 INT PRIMARY KEY, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+UPDATE t1 SET a1 = 2;
+ERROR 23000: Column 'a1' cannot be null
+SELECT * FROM t1;
+a1	a2
+1	1
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+"Test for update on UNIQUE column"
+CREATE TABLE t1(a1 INT UNIQUE NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 1),(2, 2);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+UPDATE t1 SET a1 = 3;
+ERROR 23000: Column 'a1' cannot be null
+SELECT * FROM t1;
+a1	a2
+1	1
+2	2
+DROP TRIGGER t1_bu;
+DROP TABLE t1;

=== modified file 'mysql-test/r/warnings.result'
--- a/mysql-test/r/warnings.result	2011-04-15 12:14:35 +0000
+++ b/mysql-test/r/warnings.result	2012-12-11 11:58:31 +0000
@@ -119,13 +119,13 @@ Warning	1048	Column 'a' cannot be null
 Warning	1265	Data truncated for column 'b' at row 4
 insert into t2(b) values('mysqlab');
 Warnings:
-Warning	1364	Field 'a' doesn't have a default value
 Warning	1265	Data truncated for column 'b' at row 1
+Warning	1364	Field 'a' doesn't have a default value
 set sql_warnings=1;
 insert into t2(b) values('mysqlab');
 Warnings:
-Warning	1364	Field 'a' doesn't have a default value
 Warning	1265	Data truncated for column 'b' at row 1
+Warning	1364	Field 'a' doesn't have a default value
 set sql_warnings=0;
 drop table t1, t2;
 create table t1(a char(10));

=== added file 'mysql-test/std_data/wl6030.dat'
--- a/mysql-test/std_data/wl6030.dat	1970-01-01 00:00:00 +0000
+++ b/mysql-test/std_data/wl6030.dat	2012-12-11 11:58:31 +0000
@@ -0,0 +1,5 @@
+457,NULL
+321,text
+579,NULL
+789,\n
+987,\N

=== added file 'mysql-test/std_data/wl6030_2.dat'
--- a/mysql-test/std_data/wl6030_2.dat	1970-01-01 00:00:00 +0000
+++ b/mysql-test/std_data/wl6030_2.dat	2012-12-11 11:58:31 +0000
@@ -0,0 +1,9 @@
+11,12,13,14
+NULL,22,23,24
+31,NULL,33,34
+41,42,NULL,44
+51,52,53,NULL
+NULL,NULL,NULL,NULL
+NULL,NULL,73,74
+NULL,82,NULL,84
+NULL,92,93,NULL

=== modified file 'mysql-test/suite/funcs_1/r/innodb_trig_09.result'
--- a/mysql-test/suite/funcs_1/r/innodb_trig_09.result	2009-02-05 13:51:00 +0000
+++ b/mysql-test/suite/funcs_1/r/innodb_trig_09.result	2012-12-11 11:56:43 +0000
@@ -198,7 +198,7 @@ a	NULL	Test 3.5.9.4-trig	00000	999	NULL
 select  @tr_var_b4_118, @tr_var_b4_121, @tr_var_b4_122,
 @tr_var_b4_136, @tr_var_b4_151, @tr_var_b4_163;
 @tr_var_b4_118	@tr_var_b4_121	@tr_var_b4_122	@tr_var_b4_136	@tr_var_b4_151	@tr_var_b4_163
-a	NULL	Test 3.5.9.4-trig	0	999	NULL
+a	NULL	Test 3.5.9.4-trig	NULL	999	NULL
 select  @tr_var_af_118, @tr_var_af_121, @tr_var_af_122,
 @tr_var_af_136, @tr_var_af_151, @tr_var_af_163;
 @tr_var_af_118	@tr_var_af_121	@tr_var_af_122	@tr_var_af_136	@tr_var_af_151	@tr_var_af_163

=== modified file 'mysql-test/suite/funcs_1/r/memory_trig_09.result'
--- a/mysql-test/suite/funcs_1/r/memory_trig_09.result	2009-02-05 13:51:00 +0000
+++ b/mysql-test/suite/funcs_1/r/memory_trig_09.result	2012-12-11 11:56:43 +0000
@@ -199,7 +199,7 @@ a	NULL	Test 3.5.9.4-trig	00000	999	NULL
 select  @tr_var_b4_118, @tr_var_b4_121, @tr_var_b4_122,
 @tr_var_b4_136, @tr_var_b4_151, @tr_var_b4_163;
 @tr_var_b4_118	@tr_var_b4_121	@tr_var_b4_122	@tr_var_b4_136	@tr_var_b4_151	@tr_var_b4_163
-a	NULL	Test 3.5.9.4-trig	0	999	NULL
+a	NULL	Test 3.5.9.4-trig	NULL	999	NULL
 select  @tr_var_af_118, @tr_var_af_121, @tr_var_af_122,
 @tr_var_af_136, @tr_var_af_151, @tr_var_af_163;
 @tr_var_af_118	@tr_var_af_121	@tr_var_af_122	@tr_var_af_136	@tr_var_af_151	@tr_var_af_163

=== modified file 'mysql-test/suite/funcs_1/r/myisam_trig_09.result'
--- a/mysql-test/suite/funcs_1/r/myisam_trig_09.result	2009-02-05 13:51:00 +0000
+++ b/mysql-test/suite/funcs_1/r/myisam_trig_09.result	2012-12-11 11:56:43 +0000
@@ -199,7 +199,7 @@ a	NULL	Test 3.5.9.4-trig	00000	999	NULL
 select  @tr_var_b4_118, @tr_var_b4_121, @tr_var_b4_122,
 @tr_var_b4_136, @tr_var_b4_151, @tr_var_b4_163;
 @tr_var_b4_118	@tr_var_b4_121	@tr_var_b4_122	@tr_var_b4_136	@tr_var_b4_151	@tr_var_b4_163
-a	NULL	Test 3.5.9.4-trig	0	999	NULL
+a	NULL	Test 3.5.9.4-trig	NULL	999	NULL
 select  @tr_var_af_118, @tr_var_af_121, @tr_var_af_122,
 @tr_var_af_136, @tr_var_af_151, @tr_var_af_163;
 @tr_var_af_118	@tr_var_af_121	@tr_var_af_122	@tr_var_af_136	@tr_var_af_151	@tr_var_af_163

=== added file 'mysql-test/t/trigger_wl6030.test'
--- a/mysql-test/t/trigger_wl6030.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/trigger_wl6030.test	2012-12-11 11:58:31 +0000
@@ -0,0 +1,1794 @@
+--echo #
+--echo # WL#6030: Triggers are not processed for NOT NULL columns.
+--echo #
+
+CREATE TABLE t2(a INT, b INT, c INT);
+
+--echo
+--echo ###################################################################
+--echo # Test 1: BEFORE INSERT, NOT NULL.
+--echo #   - Test 1.1: SET to NOT NULL.
+--echo ###################################################################
+
+CREATE TABLE t1(a INT NOT NULL, b INT, c INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a = 1;
+
+INSERT INTO t2 VALUES (1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+
+--echo
+--echo # Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (NULL, 2, 3);
+INSERT INTO t1(a, b, c) VALUES (NULL, 20, 30);
+INSERT INTO t1(b, c) VALUES (200, 300);
+INSERT INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (NULL, 2, 3);
+REPLACE INTO t1(a, b, c) VALUES (NULL, 20, 30);
+REPLACE INTO t1(b, c) VALUES (200, 300);
+REPLACE INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+INSERT INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+REPLACE INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # INSERT ... SELECT.
+INSERT INTO t1 SELECT * FROM t2;
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+INSERT INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # REPLACE ... SELECT.
+REPLACE INTO t1 SELECT * FROM t2;
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+DELETE FROM t2;
+
+DROP TRIGGER t1_bi;
+
+--echo
+--echo ###################################################################
+--echo #   - Test 1.2: SET to NULL.
+--echo ###################################################################
+
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW SET NEW.a = NULL;
+# For a single-row INSERT, no warning occurs when NULL is inserted into a NOT
+# NULL column. Instead, the statement fails with an error.
+
+INSERT INTO t2 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+--echo
+--echo # Single INSERT ... VALUES.
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES (1, 2, 3);
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a, b, c) VALUES (1, 2, 3);
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(b, c) VALUES (2, 3);
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a) VALUES (1);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Single REPLACE ... VALUES.
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1 VALUES (1, 2, 3);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a, b, c) VALUES (1, 2, 3);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(b, c) VALUES (2, 3);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a) VALUES (1);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi INSERT ... VALUES.
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a, b, c) VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a) VALUES (1), (10), (100);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi REPLACE ... VALUES.
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a, b, c) VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a) VALUES (1), (10), (100);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # INSERT ... SELECT.
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 SELECT * FROM t2;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # REPLACE ... SELECT.
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1 SELECT * FROM t2;
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+DROP TRIGGER t1_bi;
+
+--echo
+--echo ###################################################################
+--echo # Test 2: BEFORE UPDATE, NOT NULL.
+--echo #   - Test 2.1: SET to NOT NULL.
+--echo ###################################################################
+
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW SET NEW.a = 999;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+--echo
+--echo # Regular UPDATE.
+UPDATE t1 SET a = NULL WHERE a = 1;
+UPDATE t1 SET a = NULL, c = NULL WHERE a = 100;
+
+--echo
+SELECT * FROM t1;
+--echo
+
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+--echo
+--echo # Multiple UPDATE.
+CREATE TABLE t3(a INT, b INT);
+INSERT INTO t3 VALUES (10, -10);
+
+UPDATE t1, t3 SET t1.a = NULL, t3.a = -20 WHERE t1.a = t3.a AND t3.a = 10;
+
+--echo
+SELECT * FROM t1;
+--echo
+SELECT * FROM t3;
+--echo
+
+DROP TRIGGER t1_bu;
+DROP TABLE t3;
+DELETE FROM t1;
+
+CREATE TABLE t3(a INT NOT NULL, b INT);
+CREATE TRIGGER t3_bu BEFORE UPDATE ON t3 FOR EACH ROW SET NEW.a = 999;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+INSERT INTO t3 VALUES (10, -10);
+
+UPDATE t1, t3 SET t1.a = -20, t3.a = NULL WHERE t1.a = t3.a AND t3.a = 10;
+
+SELECT * FROM t1;
+SELECT * FROM t3;
+DROP TRIGGER t3_bu;
+DROP TABLE t3;
+
+--echo
+--echo #   - Test 2.1: SET to NULL.
+
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW SET NEW.a = NULL;
+DELETE FROM t1;
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+--echo
+--echo # Regular UPDATE.
+--error ER_BAD_NULL_ERROR
+UPDATE t1 SET a = 99 WHERE a = 1;
+--error ER_BAD_NULL_ERROR
+UPDATE t1 SET a = 99, b = 99 WHERE a = 1;
+
+--echo
+SELECT * FROM t1;
+
+--echo
+--echo # Multiple UPDATE.
+CREATE TABLE t3(a INT, b INT);
+INSERT INTO t3 VALUES (10, -10);
+
+--error ER_BAD_NULL_ERROR
+UPDATE t1, t3 SET t1.a = 99, t3.a = -10 WHERE t1.a = t3.a AND t3.a = 10;
+
+--echo
+SELECT * FROM t1;
+--echo
+SELECT * FROM t3;
+--echo
+
+DELETE FROM t1;
+DELETE FROM t2;
+DROP TABLE t3;
+
+DROP TRIGGER t1_bu;
+
+--echo
+--echo ###################################################################
+--echo # Test 3: Using illegal NULL-value as r-value.
+--echo #   - Test 3.1: using NULL.
+--echo ###################################################################
+
+delimiter |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+  SET NEW.b = NEW.a;
+  SET NEW.a = 1;
+END|
+delimiter ;|
+
+INSERT INTO t2 VALUES (1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+
+--echo
+--echo # Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (NULL, 2, 3);
+INSERT INTO t1(a, b, c) VALUES (NULL, 20, 30);
+INSERT INTO t1(b, c) VALUES (200, 300);
+INSERT INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (NULL, 2, 3);
+REPLACE INTO t1(a, b, c) VALUES (NULL, 20, 30);
+REPLACE INTO t1(b, c) VALUES (200, 300);
+REPLACE INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+INSERT INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+REPLACE INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # INSERT ... SELECT
+INSERT INTO t1 SELECT * FROM t2;
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+INSERT INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # REPLACE ... SELECT
+REPLACE INTO t1 SELECT * FROM t2;
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+DROP TRIGGER t1_bi;
+
+--echo
+--echo ###################################################################
+--echo #   - Test 3.2: using NOT NULL.
+--echo ###################################################################
+
+delimiter |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+  SET NEW.a = 99;
+  SET NEW.b = NEW.a;
+END|
+delimiter ;|
+
+--echo
+--echo # Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (NULL, 2, 3);
+INSERT INTO t1(a, b, c) VALUES (NULL, 20, 30);
+INSERT INTO t1(b, c) VALUES (200, 300);
+INSERT INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (NULL, 2, 3);
+REPLACE INTO t1(a, b, c) VALUES (NULL, 20, 30);
+REPLACE INTO t1(b, c) VALUES (200, 300);
+REPLACE INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+INSERT INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (-1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+REPLACE INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # INSERT ... SELECT
+INSERT INTO t1 SELECT * FROM t2;
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+INSERT INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # REPLACE ... SELECT
+REPLACE INTO t1 SELECT * FROM t2;
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+DELETE FROM t2;
+
+DROP TRIGGER t1_bi;
+
+--echo
+--echo ###################################################################
+--echo # Test 4: Temporarily setting to illegal NULL-value in trigger
+--echo # (here we only check that it's possible to temporarily assign
+--echo # NULL in triggers).
+--echo ###################################################################
+
+delimiter |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+  SET NEW.a = NULL;
+  SET NEW.b = NEW.a;
+  SET NEW.a = 99;
+END|
+
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+  SET NEW.a = NULL;
+  SET NEW.b = NEW.a;
+  SET NEW.a = 199;
+END|
+delimiter ;|
+
+--echo
+--echo # Checking BEFORE INSERT trigger.
+INSERT INTO t1 VALUES (1, 2, 3);
+INSERT INTO t1 VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+SELECT * FROM t1;
+
+--echo
+--echo # Checking BEFORE UPDATE trigger.
+UPDATE t1 SET b = 999 WHERE c = 300;
+SELECT * FROM t1;
+
+--echo
+DROP TRIGGER t1_bi;
+DROP TRIGGER t1_bu;
+DELETE FROM t1;
+
+--echo
+--echo ###################################################################
+--echo # Test 5: Using IS NULL inside trigger.
+--echo #   - Test 5.1: BEFORE INSERT trigger.
+--echo ###################################################################
+
+ALTER TABLE t1 ADD COLUMN a_new_is_null BOOLEAN DEFAULT NULL;
+
+delimiter |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+  SET NEW.a_new_is_null = NEW.a IS NULL;
+  SET NEW.a = 99;
+END|
+delimiter ;|
+
+INSERT INTO t2 VALUES (1, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+
+--echo
+--echo # Single INSERT ... VALUES.
+INSERT INTO t1 VALUES (NULL, 2, 3, NULL);
+INSERT INTO t1(a, b, c) VALUES (NULL, 20, 30);
+INSERT INTO t1(b, c) VALUES (200, 300);
+INSERT INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Single REPLACE ... VALUES.
+REPLACE INTO t1 VALUES (NULL, 2, 3, NULL);
+REPLACE INTO t1(a, b, c) VALUES (NULL, 20, 30);
+REPLACE INTO t1(b, c) VALUES (200, 300);
+REPLACE INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi INSERT ... VALUES.
+INSERT INTO t1 VALUES
+  (-1, 2, 3, NULL), (NULL, 20, 30, NULL), (NULL, 200, 300, NULL);
+INSERT INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+INSERT INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+INSERT INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # Multi REPLACE ... VALUES.
+REPLACE INTO t1 VALUES
+  (-1, 2, 3, NULL), (NULL, 20, 30, NULL), (NULL, 200, 300, NULL);
+REPLACE INTO t1(a, b, c) VALUES (-2, 2, 3), (NULL, 20, 30), (NULL, 200, 300);
+REPLACE INTO t1(b, c) VALUES (2, 3), (20, 30), (200, 300);
+REPLACE INTO t1(a) VALUES (-3), (NULL), (NULL);
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # INSERT ... SELECT
+INSERT INTO t1 SELECT t2.*, NULL FROM t2;
+INSERT INTO t1(a, b, c) SELECT * FROM t2;
+INSERT INTO t1(b, c) SELECT b, c FROM t2;
+INSERT INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+--echo
+--echo # REPLACE ... SELECT
+REPLACE INTO t1 SELECT t2.*, NULL FROM t2;
+REPLACE INTO t1(a, b, c) SELECT * FROM t2;
+REPLACE INTO t1(b, c) SELECT b, c FROM t2;
+REPLACE INTO t1(a) SELECT a FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+DELETE FROM t1;
+
+DROP TRIGGER t1_bi;
+
+--echo
+--echo ###################################################################
+--echo #   - Test 5.2: BEFORE UPDATE trigger.
+--echo ###################################################################
+
+ALTER TABLE t1 ADD COLUMN a_old_is_null BOOLEAN DEFAULT NULL;
+ALTER TABLE t1 ADD COLUMN b_new_is_null BOOLEAN DEFAULT NULL;
+ALTER TABLE t1 ADD COLUMN b_old_is_null BOOLEAN DEFAULT NULL;
+
+delimiter |;
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+BEGIN
+  SET NEW.a_new_is_null = NEW.a IS NULL;
+  SET NEW.a_old_is_null = OLD.a IS NULL;
+
+  SET NEW.b_new_is_null = NEW.b IS NULL;
+  SET NEW.b_old_is_null = OLD.b IS NULL;
+
+  SET NEW.a = 99;
+END|
+delimiter ;|
+
+INSERT INTO t1(a, b, c) VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+--echo
+--echo # Regular UPDATE.
+UPDATE t1 SET a = NULL WHERE a = 1;
+UPDATE t1 SET a = NULL, c = NULL WHERE a = 10;
+UPDATE t1 SET b = NULL WHERE a = 100;
+
+--echo
+SELECT * FROM t1;
+--echo
+
+DELETE FROM t1;
+INSERT INTO t1(a, b, c) VALUES (1, 2, 3), (10, 20, 30), (100, 200, 300);
+
+--echo
+--echo # Multiple UPDATE.
+CREATE TABLE t3(a INT, b INT);
+INSERT INTO t3 VALUES (10, -10);
+
+UPDATE t1, t3 SET t1.a = NULL, t3.a = -20 WHERE t1.a = t3.a AND t3.a = 10;
+
+--echo
+SELECT * FROM t1;
+--echo
+SELECT * FROM t3;
+--echo
+
+DROP TABLE t3;
+
+DROP TRIGGER t1_bu;
+
+DROP TABLE t1;
+DROP TABLE t2;
+
+--echo
+--echo ###################################################################
+--echo # Test 6: Nullability of non-updated columns.
+--echo ###################################################################
+
+CREATE TABLE t1(a INT, b INT NOT NULL);
+
+--echo
+--echo # - Unconditional SET in a trigger.
+--echo
+
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+  SET NEW.b = NULL;
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a) VALUES (1);
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a) VALUES (1);
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+DROP TRIGGER t1_bi;
+
+--echo
+--echo # - Conditional SET in a trigger, which is executed for every row.
+--echo
+
+delimiter |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+  SET NEW.b = NEW.a;
+  IF NEW.b IS NULL THEN
+    SET NEW.b = 1;
+  END IF;
+END|
+delimiter ;|
+
+--echo
+INSERT INTO t1(a) VALUES (NULL);
+
+--echo
+REPLACE INTO t1(a) VALUES (NULL);
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+DROP TRIGGER t1_bi;
+
+--echo
+--echo # - Conditional SET in a trigger, which is NOT executed for every row.
+--echo
+
+delimiter |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+  IF (MOD(NEW.a, 2) = 0) THEN
+    SET NEW.b = NEW.a - 1;
+  END IF;
+END|
+delimiter ;|
+
+--echo
+INSERT INTO t1(a) VALUES (1), (2), (3), (4), (5), (6);
+
+--echo
+REPLACE INTO t1(a) VALUES (1), (2), (3), (4), (5), (6);
+
+--echo
+SELECT * FROM t1;
+
+DROP TABLE t1;
+
+--echo
+--echo ###################################################################
+--echo # Test 7: Nullability of column being copied as result of INSERT SELECT.
+--echo ###################################################################
+
+CREATE TABLE t1(a INT NOT NULL);
+
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES (NULL);
+
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+  SET NEW.a = 1;
+
+--echo
+INSERT INTO t1 SELECT * FROM t2;
+REPLACE INTO t1 SELECT * FROM t2;
+
+--echo
+SELECT * FROM t1;
+--echo
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1,t2;
+
+CREATE TABLE t1(a INT NOT NULL);
+INSERT INTO t1 VALUES (1);
+
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
+  SET NEW.a = 2;
+
+CREATE TABLE t2(a INT);
+INSERT INTO t2 VALUES (NULL);
+
+--echo
+UPDATE t1, t2 SET t1.a = t2.a;
+
+--echo
+SELECT * FROM t1;
+--echo
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1,t2;
+
+--echo
+--echo ###################################################################
+--echo # Test 8: Nullability of column being copied as result of
+--echo #         LOAD DATA INFILE.
+--echo ###################################################################
+
+CREATE TABLE t1 (a INT NOT NULL, b VARCHAR(10) NOT NULL);
+
+delimiter |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
+BEGIN
+  IF NEW.b IS NULL THEN
+    SET NEW.b = '123';
+  END IF;
+END |
+delimiter ;|
+
+LOAD DATA INFILE '../../std_data/wl6030.dat' INTO TABLE t1 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+
+SELECT * FROM t1;
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo
+--echo ###################################################################
+--echo # Misc tests.
+--echo ###################################################################
+--echo
+
+# A table with one NOT NULL column.
+CREATE TABLE t1(a INT, b INT NOT NULL);
+CREATE VIEW v1 AS SELECT * FROM t1;
+
+# A table with a few NOT NULL columns.
+CREATE TABLE t2(a INT, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL);
+CREATE VIEW v2 AS SELECT * FROM t2;
+
+# Aux table with data for t1.
+CREATE TABLE t1_data(a INT, b INT);
+INSERT INTO t1_data VALUES
+  (11, 12),
+  (NULL, 22),
+  (31, NULL),
+  (NULL, NULL);
+
+# Aux table with data for t2.
+CREATE TABLE t2_data(a INT, b INT, c INT, d INT);
+INSERT INTO t2_data VALUES
+  (11, 12, 13, 14),
+  (NULL, 22, 23, 24),
+  (31, NULL, 33, 34),
+  (41, 42, NULL, 44),
+  (51, 52, 53, NULL),
+  (NULL, NULL, NULL, NULL);
+
+
+SET @sql_mode_saved = @@sql_mode;
+
+--echo
+--echo ###################################################################
+--echo # Checking permissive SQL_MODE.
+--echo ###################################################################
+--echo
+
+SET sql_mode = '';
+
+--echo
+--echo #------------------------------------------------------------------
+--echo # Checking INSERT INTO ... VALUES ...
+--echo #------------------------------------------------------------------
+
+--echo
+--echo #   - No column list (all columns) + NULL-value for NOT NULL column.
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES (1, NULL);
+--error ER_BAD_NULL_ERROR
+INSERT INTO v1 VALUES (1, NULL);
+
+--echo
+SELECT * FROM t1;
+
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1 VALUES (1, NULL);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v1 VALUES (1, NULL);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t2 VALUES (1, 2, NULL, 4);
+--error ER_BAD_NULL_ERROR
+INSERT INTO v2 VALUES (1, 2, NULL, 4);
+
+--echo
+SELECT * FROM t2;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t2 VALUES (1, 2, NULL, 4);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v2 VALUES (1, 2, NULL, 4);
+
+--echo
+SELECT * FROM t2;
+
+--echo
+--echo #   - All columns + NULL-value for NOT NULL column.
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO v1(a, b) VALUES (1, NULL);
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a, b) VALUES (1, NULL);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v1(a, b) VALUES (1, NULL);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a, b) VALUES (1, NULL);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t2(a, b, c, d) VALUES (1, 2, NULL, 4);
+--error ER_BAD_NULL_ERROR
+INSERT INTO v2(a, b, c, d) VALUES (1, 2, NULL, 4);
+
+--echo
+SELECT * FROM t2;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t2(a, b, c, d) VALUES (1, 2, NULL, 4);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v2(a, b, c, d) VALUES (1, 2, NULL, 4);
+
+--echo
+SELECT * FROM t2;
+
+--echo
+--echo #   - Single nullable column, no values for NOT NULL columns.
+--echo #     Expect exactly 4 warnings and 8 rows being inserted into t1.
+
+--echo
+INSERT INTO t1(a) VALUES (1);
+INSERT INTO t1(a) VALUES (2), (3), (4);
+INSERT INTO v1(a) VALUES (5);
+INSERT INTO v1(a) VALUES (6), (7), (8);
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+REPLACE INTO t1(a) VALUES (1);
+REPLACE INTO t1(a) VALUES (2), (3), (4);
+REPLACE INTO v1(a) VALUES (5);
+REPLACE INTO v1(a) VALUES (6), (7), (8);
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+INSERT INTO t2(a) VALUES (1);
+INSERT INTO t2(a) VALUES (2), (3), (4);
+INSERT INTO v2(a) VALUES (5);
+INSERT INTO v2(a) VALUES (6), (7), (8);
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+REPLACE INTO t2(a) VALUES (1);
+REPLACE INTO t2(a) VALUES (2), (3), (4);
+REPLACE INTO v2(a) VALUES (5);
+REPLACE INTO v2(a) VALUES (6), (7), (8);
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #------------------------------------------------------------------
+--echo # Checking INSERT INTO ... SELECT ...
+--echo #------------------------------------------------------------------
+
+--echo
+--echo #   - No column list (all columns) + NULL-value for NOT NULL column.
+--echo #     Expect 4 warnings for each statement.
+
+--echo
+INSERT INTO t1 SELECT * FROM t1_data;
+INSERT INTO v1 SELECT a * 10, b * 10 FROM t1_data;
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+REPLACE INTO t1 SELECT * FROM t1_data;
+REPLACE INTO v1 SELECT a * 10, b * 10 FROM t1_data;
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--echo #   - No column list (all columns) + NULL-value for NOT NULL column.
+--echo #     Expect 4 warnings for each statement.
+
+--echo
+INSERT INTO t2 SELECT * FROM t2_data;
+INSERT INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+REPLACE INTO t2 SELECT * FROM t2_data;
+REPLACE INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #   - All columns + NULL-value for NOT NULL column.
+--echo #     Expect 4 warnings for each statement.
+
+--echo
+INSERT INTO t1(a, b) SELECT * FROM t1_data;
+INSERT INTO v1(a, b) SELECT a * 10, b * 10 FROM t1_data;
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+REPLACE INTO t1(a, b) SELECT * FROM t1_data;
+REPLACE INTO v1(a, b) SELECT a * 10, b * 10 FROM t1_data;
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+INSERT INTO t2(a, b, c, d) SELECT * FROM t2_data;
+INSERT INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+REPLACE INTO t2(a, b, c, d) SELECT * FROM t2_data;
+REPLACE INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #   - Single nullable column, no values for NOT NULL columns.
+--echo #     Expect 4 warnings for each statement.
+
+--echo
+INSERT INTO t1(a) SELECT a FROM t1_data;
+INSERT INTO v1(a) SELECT a * 100 FROM t1_data;
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+REPLACE INTO t1(a) SELECT a FROM t1_data;
+REPLACE INTO v1(a) SELECT a * 100 FROM t1_data;
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+INSERT INTO t2(a) SELECT a FROM t2_data;
+INSERT INTO v2(a) SELECT a * 100 FROM t2_data;
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+REPLACE INTO t2(a) SELECT a FROM t2_data;
+REPLACE INTO v2(a) SELECT a * 100 FROM t2_data;
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #------------------------------------------------------------------
+--echo # Checking LOAD DATA INFILE ...
+--echo #------------------------------------------------------------------
+
+--echo
+LOAD DATA INFILE '../../std_data/wl6030_2.dat' INTO TABLE t2 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+
+--echo
+SELECT * FROM t2;
+
+--echo
+DELETE FROM t2;
+
+LOAD DATA INFILE '../../std_data/wl6030_2.dat' INTO TABLE v2 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+
+--echo
+SELECT * FROM t2;
+
+--echo
+DELETE FROM t2;
+
+--echo
+--echo ###################################################################
+--echo # Checking strict SQL_MODE.
+--echo ###################################################################
+--echo
+
+SET sql_mode = 'traditional';
+
+--echo
+--echo #------------------------------------------------------------------
+--echo # Checking INSERT INTO ... VALUES ...
+--echo #------------------------------------------------------------------
+
+--echo
+--echo #   - No column list (all columns) + NULL-value for NOT NULL column.
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES (1, NULL);
+--error ER_BAD_NULL_ERROR
+INSERT INTO v1 VALUES (1, NULL);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1 VALUES (1, NULL);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v1 VALUES (1, NULL);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t2 VALUES (1, 2, NULL, 4);
+--error ER_BAD_NULL_ERROR
+INSERT INTO v2 VALUES (1, 2, NULL, 4);
+
+--echo
+SELECT * FROM t2;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t2 VALUES (1, 2, NULL, 4);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v2 VALUES (1, 2, NULL, 4);
+
+--echo
+SELECT * FROM t2;
+
+--echo
+--echo #   - All columns + NULL-value for NOT NULL column.
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO v1(a, b) VALUES (1, NULL);
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a, b) VALUES (1, NULL);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v1(a, b) VALUES (1, NULL);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a, b) VALUES (1, NULL);
+
+--echo
+SELECT * FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t2(a, b, c, d) VALUES (1, 2, NULL, 4);
+--error ER_BAD_NULL_ERROR
+INSERT INTO v2(a, b, c, d) VALUES (1, 2, NULL, 4);
+
+--echo
+SELECT * FROM t2;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t2(a, b, c, d) VALUES (1, 2, NULL, 4);
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v2(a, b, c, d) VALUES (1, 2, NULL, 4);
+
+--echo
+SELECT * FROM t2;
+
+--echo
+--echo #   - Single nullable column, no values for NOT NULL columns.
+
+--echo
+--error ER_NO_DEFAULT_FOR_FIELD
+INSERT INTO t1(a) VALUES (1);
+--error ER_NO_DEFAULT_FOR_FIELD
+INSERT INTO t1(a) VALUES (2), (3), (4);
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+INSERT INTO v1(a) VALUES (5);
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+INSERT INTO v1(a) VALUES (6), (7), (8);
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--error ER_NO_DEFAULT_FOR_FIELD
+REPLACE INTO t1(a) VALUES (1);
+--error ER_NO_DEFAULT_FOR_FIELD
+REPLACE INTO t1(a) VALUES (2), (3), (4);
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+REPLACE INTO v1(a) VALUES (5);
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+REPLACE INTO v1(a) VALUES (6), (7), (8);
+
+--echo
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--error ER_NO_DEFAULT_FOR_FIELD
+INSERT INTO t2(a) VALUES (1);
+--error ER_NO_DEFAULT_FOR_FIELD
+INSERT INTO t2(a) VALUES (2), (3), (4);
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+INSERT INTO v2(a) VALUES (5);
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+INSERT INTO v2(a) VALUES (6), (7), (8);
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--error ER_NO_DEFAULT_FOR_FIELD
+REPLACE INTO t2(a) VALUES (1);
+--error ER_NO_DEFAULT_FOR_FIELD
+REPLACE INTO t2(a) VALUES (2), (3), (4);
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+REPLACE INTO v2(a) VALUES (5);
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+REPLACE INTO v2(a) VALUES (6), (7), (8);
+
+--echo
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #------------------------------------------------------------------
+--echo # Checking INSERT INTO ... SELECT ...
+--echo #------------------------------------------------------------------
+
+--echo
+--echo #   - No column list (all columns) + NULL-value for NOT NULL column.
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 SELECT * FROM t1_data;
+--error ER_BAD_NULL_ERROR
+INSERT INTO v1 SELECT a * 10, b * 10 FROM t1_data;
+
+--echo
+--echo # The following SELECT output should have 4 rows.
+--echo # t1's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1 SELECT * FROM t1_data;
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v1 SELECT a * 10, b * 10 FROM t1_data;
+
+--echo
+--echo # The following SELECT output should have 4 rows.
+--echo # t1's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--echo #   - No column list (all columns) + NULL-value for NOT NULL column.
+--error ER_BAD_NULL_ERROR
+INSERT INTO t2 SELECT * FROM t2_data;
+--error ER_BAD_NULL_ERROR
+INSERT INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+
+--echo
+--echo # The following SELECT output should have 4 rows.
+--echo # t2's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #   - No column list (all columns) + NULL-value for NOT NULL column.
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t2 SELECT * FROM t2_data;
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v2 SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+
+--echo
+--echo # The following SELECT output should have 4 rows.
+--echo # t2's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #   - All columns + NULL-value for NOT NULL column.
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1(a, b) SELECT * FROM t1_data;
+--error ER_BAD_NULL_ERROR
+INSERT INTO v1(a, b) SELECT a * 10, b * 10 FROM t1_data;
+
+--echo
+--echo # The following SELECT output should have 4 rows.
+--echo # t1's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t1(a, b) SELECT * FROM t1_data;
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v1(a, b) SELECT a * 10, b * 10 FROM t1_data;
+
+--echo
+--echo # The following SELECT output should have 4 rows.
+--echo # t1's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--error ER_BAD_NULL_ERROR
+INSERT INTO t2(a, b, c, d) SELECT * FROM t2_data;
+--error ER_BAD_NULL_ERROR
+INSERT INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+
+--echo
+--echo # The following SELECT output should have 4 rows.
+--echo # t2's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--error ER_BAD_NULL_ERROR
+REPLACE INTO t2(a, b, c, d) SELECT * FROM t2_data;
+--error ER_BAD_NULL_ERROR
+REPLACE INTO v2(a, b, c, d) SELECT a * 10, b * 10, c * 10, d * 10 FROM t2_data;
+
+--echo
+--echo # The following SELECT output should have 4 rows.
+--echo # t2's engine is MyISAM, so the transaction can not be fully rolled back.
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #   - Single nullable column, no values for NOT NULL columns.
+
+--echo
+--error ER_NO_DEFAULT_FOR_FIELD
+INSERT INTO t1(a) SELECT a FROM t1_data;
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+INSERT INTO v1(a) SELECT a * 100 FROM t1_data;
+
+--echo
+--echo # The following SELECT output should have 0 rows.
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--error ER_NO_DEFAULT_FOR_FIELD
+REPLACE INTO t1(a) SELECT a FROM t1_data;
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+REPLACE INTO v1(a) SELECT a * 100 FROM t1_data;
+
+--echo
+--echo # The following SELECT output should have 0 rows.
+SELECT * FROM t1;
+DELETE FROM t1;
+
+--echo
+--error ER_NO_DEFAULT_FOR_FIELD
+INSERT INTO t2(a) SELECT a FROM t2_data;
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+INSERT INTO v2(a) SELECT a * 100 FROM t2_data;
+
+--echo
+--echo # The following SELECT output should have 0 rows.
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--error ER_NO_DEFAULT_FOR_FIELD
+REPLACE INTO t2(a) SELECT a FROM t2_data;
+--error ER_NO_DEFAULT_FOR_VIEW_FIELD
+REPLACE INTO v2(a) SELECT a * 100 FROM t2_data;
+
+--echo
+--echo # The following SELECT output should have 0 rows.
+SELECT * FROM t2;
+DELETE FROM t2;
+
+--echo
+--echo #------------------------------------------------------------------
+--echo # Checking LOAD DATA INFILE ...
+--echo #------------------------------------------------------------------
+
+--error ER_WARN_NULL_TO_NOTNULL
+LOAD DATA INFILE '../../std_data/wl6030_2.dat' INTO TABLE t2 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+
+--echo
+SELECT * FROM t2;
+
+--echo
+DELETE FROM t2;
+
+--error ER_WARN_NULL_TO_NOTNULL
+LOAD DATA INFILE '../../std_data/wl6030_2.dat' INTO TABLE v2 FIELDS
+TERMINATED BY ',' ENCLOSED BY '"';
+
+--echo
+SELECT * FROM t2;
+
+--echo
+SET sql_mode = @sql_mode_saved;
+
+DROP TABLE t1;
+DROP TABLE t2;
+DROP TABLE t1_data;
+DROP TABLE t2_data;
+DROP VIEW v1;
+DROP VIEW v2;
+
+--echo
+--echo #------------------------------------------------------------------
+--echo # The following tests were suggested by QA
+--echo #------------------------------------------------------------------
+--echo
+
+--echo "Test UPDATE SET inside trigger body"
+CREATE TABLE t1(a1 INT NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+UPDATE t1 SET NEW.a1 = 1 WHERE a1 IS NULL;
+
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+INSERT INTO t1 VALUES (NULL);
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for recursive trigger"
+CREATE TABLE t1(a1 INT NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+UPDATE t1 SET NEW.a1 = 1;
+
+--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+INSERT INTO t1 VALUES (NULL);
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for IFNULL inside trigger body"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 2);
+delimiter |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+BEGIN
+  SET NEW.a1 = IFNULL(NEW.a1, 10);
+  SET NEW.a2 = IFNULL(NEW.a2, 20);
+END;
+|
+delimiter ;|
+INSERT INTO t1 VALUES (NULL, 1);
+# expect here the row (10, 1);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for COALESCE Inside trigger body"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+DELIMITER |;
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+BEGIN
+ SET NEW.a1 = COALESCE(NEW.a1, 5);
+ SET NEW.a2 = COALESCE(NEW.a2, 7);
+END;
+|
+DELIMITER ;|
+INSERT INTO t1 VALUES (NULL, 3);
+# expect here the row (5, 3)
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for PRIMARY KEY"
+CREATE TABLE t1 (a1 INT PRIMARY KEY); 
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 2;
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for PRIMARY KEY (constraint violation)"
+CREATE TABLE t1 (a1 INT PRIMARY KEY); 
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 1;
+
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+--error ER_DUP_ENTRY
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for UNIQUE column"
+CREATE TABLE t1(a1 INT UNIQUE);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 1;
+
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+--error ER_DUP_ENTRY
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for date/timestamp datatype"
+CREATE TABLE t1(a1 DATE NOT NULL, a2 TIMESTAMP NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = '2012-03-03', NEW.a2 = '2001-01-01 09:01:00';
+INSERT INTO t1 VALUES (NULL, NULL);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for CHAR/VARCHAR datatype"
+CREATE TABLE t1(a1 CHAR(10) NOT NULL, a2 VARCHAR(255) NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 'MySQL' , NEW.a2 = 'Includes testing of MySQL';
+INSERT INTO t1 VALUES (NULL, NULL);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for BINARY/VARBINARY datatype"
+CREATE TABLE t1(a1 BINARY(10) NOT NULL, a2 VARBINARY(255) NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = '0x41', NEW.a2 = '0x42';
+
+INSERT INTO t1 VALUES (NULL, NULL);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for UNIQUE column‚ constraint violation"
+CREATE TABLE t1(a1 INT UNIQUE, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = 1;
+--error ER_DUP_ENTRY
+INSERT INTO t1 VALUES (NULL, 2);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for UPDATE .. SET .. SELECT"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT);
+CREATE TABLE t2(a1 INT NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, NULL);
+INSERT INTO t2 VALUES (1, NULL);
+
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = 2;
+
+UPDATE t1 SET a1 = (SELECT a2 FROM t2);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1, t2;
+
+--echo "Test for multi table update (across engines)"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT) ENGINE = INNODB;
+CREATE TABLE t2(a1 INT NOT NULL, a2 INT) ENGINE = MyISAM;
+INSERT INTO t1 VALUES (1, NULL),(2, 2);
+INSERT INTO t2 VALUES (1, NULL),(2876543, 2098);
+
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = 10;
+
+CREATE TRIGGER t2_bu BEFORE UPDATE ON t2
+FOR EACH ROW
+SET NEW.a1 = 20;
+
+UPDATE t1, t2 SET t1.a1 = NULL , t2.a1 = NULL;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TRIGGER t1_bu;
+DROP TRIGGER t2_bu;
+DROP TABLE t1, t2;
+
+--echo "Test for update on PRIMARY KEY"
+CREATE TABLE t1(a1 INT PRIMARY KEY, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = 2;
+UPDATE t1 SET a1 =  NULL;
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+
+--echo "Test for update on UNIQUE column"
+CREATE TABLE t1(a1 INT UNIQUE NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = 2;
+UPDATE t1 SET a1 =  NULL;
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+
+--echo "INSERT NOT NULL into NOT NULL column if BEFORE INSERT trigger sets it to NULL."
+
+--echo "Test for PRIMARY KEY"
+CREATE TABLE t1(a1 INT PRIMARY KEY, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES (2, 2);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for UNIQUE column"
+CREATE TABLE t1(a1 INT UNIQUE NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES (2, 2),(3,3);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for timestamp"
+CREATE TABLE t1(a1 DATE NOT NULL, a2 TIMESTAMP NOT NULL, a3 TIMESTAMP NOT NULL);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL , NEW.a2 = NULL , NEW.a3 = NULL;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES ('2012-12-12','2012-12-12 12:12:12','1980-01-01 01:01:01');
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for CHAR/VARCHAR datatype"
+CREATE TABLE t1(a1 CHAR(10) NOT NULL, a2 VARCHAR(255) NOT NULL, a3 INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL , NEW.a2 = NULL;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES ('MySQL','MySQL Testing', 1);
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "Test for BINARY/VARBINARY datatype"
+CREATE TABLE t1(a1 BINARY(10) NOT NULL, a2 VARBINARY(255) NOT NULL, a3 INT);
+CREATE TRIGGER t1_bi BEFORE INSERT ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL , NEW.a2 = NULL;
+--error ER_BAD_NULL_ERROR
+INSERT INTO t1 VALUES ('0x101','0x101', 1);
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bi;
+DROP TABLE t1;
+
+--echo "UPDATE NOT NULL into NOT NULL column if BEFORE UPDATE trigger sets it to NULL."
+
+--echo "Test for UPDATE .. SET .. SELECT"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT) ;
+CREATE TABLE t2(a1 INT NOT NULL, a2 INT) ;
+INSERT INTO t1 VALUES (1, 1);
+INSERT INTO t2 VALUES (1, 1);
+
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+--error ER_BAD_NULL_ERROR
+UPDATE t1 SET a1 = (SELECT MAX(a2) FROM t2);
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1, t2;
+
+--echo "Test for multi table update (across engines)"
+CREATE TABLE t1(a1 INT NOT NULL, a2 INT) ENGINE = INNODB;
+CREATE TABLE t2(a1 INT NOT NULL, a2 INT) ENGINE = MyISAM;
+INSERT INTO t1 VALUES (1, NULL),(2, 2);
+INSERT INTO t2 VALUES (1, NULL),(2876543, 20111098);
+
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+--error ER_BAD_NULL_ERROR
+UPDATE t1, t2 SET t1.a1 = 1 , t2.a1 = 2;
+SELECT * FROM t1;
+SELECT * FROM t2;
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1, t2;
+
+--echo "Test for update on PRIMARY KEY"
+CREATE TABLE t1(a1 INT PRIMARY KEY, a2 INT);
+INSERT INTO t1 VALUES (1, 1);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+--error ER_BAD_NULL_ERROR
+UPDATE t1 SET a1 = 2;
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+
+--echo "Test for update on UNIQUE column"
+CREATE TABLE t1(a1 INT UNIQUE NOT NULL, a2 INT);
+INSERT INTO t1 VALUES (1, 1),(2, 2);
+CREATE TRIGGER t1_bu BEFORE UPDATE ON t1
+FOR EACH ROW
+SET NEW.a1 = NULL;
+--error ER_BAD_NULL_ERROR
+UPDATE t1 SET a1 = 3; 
+SELECT * FROM t1;
+
+DROP TRIGGER t1_bu;
+DROP TABLE t1;
+

=== modified file 'sql/field.cc'
--- a/sql/field.cc	2012-11-29 16:57:42 +0000
+++ b/sql/field.cc	2012-12-11 11:58:31 +0000
@@ -924,6 +924,18 @@ static enum_field_types field_types_merg
 
 
 /**
+  Set field to temporary value NULL.
+*/
+void Field::set_tmp_null()
+{
+  m_is_tmp_null= true;
+
+  m_count_cuted_fields_saved= table ? table->in_use->count_cuted_fields :
+                                      current_thd->count_cuted_fields;
+}
+
+
+/**
   Return type of which can carry value of both given types in UNION result.
 
   @param a  type for merging
@@ -1351,20 +1363,121 @@ String *Field::val_int_as_str(String *va
 Field::Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
 	     uchar null_bit_arg,
 	     utype unireg_check_arg, const char *field_name_arg)
-  :ptr(ptr_arg), null_ptr(null_ptr_arg),
+  :ptr(ptr_arg),
+   m_null_ptr(null_ptr_arg),
+   m_is_tmp_nullable(false),
+   m_is_tmp_null(false),
    table(0), orig_table(0), table_name(0),
    field_name(field_name_arg),
    unireg_check(unireg_check_arg),
    field_length(length_arg), null_bit(null_bit_arg), 
-   is_created_from_null_item(FALSE)
+   is_created_from_null_item(FALSE),
+   m_warnings_pushed(0)
 {
-  flags=null_ptr ? 0: NOT_NULL_FLAG;
+  flags=real_maybe_null() ? 0: NOT_NULL_FLAG;
   comment.str= (char*) "";
   comment.length=0;
   field_index= 0;
 }
 
 
+/**
+  Check NOT NULL constraint on the field after temporary nullability is
+  disabled.
+
+  @param warning_no Warning to report.
+
+  @return TYPE_OK if the value is Ok, or corresponding error code from
+  the type_conversion_status enum.
+*/
+type_conversion_status Field::check_constraints(int mysql_errno)
+{
+  /*
+    Ensure that Field::check_constraints() is called only when temporary
+    nullability is disabled.
+  */
+
+  DBUG_ASSERT(!is_tmp_nullable());
+
+  if (real_maybe_null())
+    return TYPE_OK; // If the field is nullable, we're Ok.
+
+  if (!m_is_tmp_null)
+    return TYPE_OK; // If the field was not NULL, we're Ok.
+
+  // The field has been set to NULL.
+
+  /*
+    If the field is of AUTO_INCREMENT, and the next number
+    has been assigned to it, we're Ok.
+  */
+
+  if (this == table->next_number_field)
+    return TYPE_OK;
+
+  /*
+    If the field is of TIMESTAMP its default value is CURRENT_TIMESTAMP
+    and was set before calling this method. Therefore m_is_tmp_null == false
+    for such field and we leave check_constraints() before this
+    DBUG_ASSERT is fired.
+  */
+  DBUG_ASSERT (type() != MYSQL_TYPE_TIMESTAMP);
+
+  switch (m_count_cuted_fields_saved) {
+  case CHECK_FIELD_WARN:
+    set_warning(Sql_condition::SL_WARNING, mysql_errno, 1);
+    /* fall through */
+  case CHECK_FIELD_IGNORE:
+    return TYPE_OK;
+  case CHECK_FIELD_ERROR_FOR_NULL:
+    if (!table->in_use->no_errors)
+      my_error(ER_BAD_NULL_ERROR, MYF(0), field_name);
+    return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
+  }
+
+  DBUG_ASSERT(0); // impossible
+  return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
+}
+
+
+/**
+  Set field to value NULL.
+
+  @param row_offset    This is the offset between the row being updated
+                       and table->record[0]
+*/
+void Field::set_null(my_ptrdiff_t row_offset)
+{
+  if (real_maybe_null())
+  {
+    m_null_ptr[row_offset]|= null_bit;
+  }
+  else if (is_tmp_nullable())
+  {
+    set_tmp_null();
+  }
+}
+
+
+/**
+  Set field to value NOT NULL.
+
+  @param row_offset    This is the offset between the row being updated
+                       and table->record[0]
+*/
+void Field::set_notnull(my_ptrdiff_t row_offset)
+{
+  if (real_maybe_null())
+  {
+    m_null_ptr[row_offset]&= (uchar) ~null_bit;
+  }
+  else if (is_tmp_nullable())
+  {
+    reset_tmp_null();
+  }
+}
+
+
 void Field::hash(ulong *nr, ulong *nr2)
 {
   if (is_null())
@@ -1379,24 +1492,24 @@ void Field::hash(ulong *nr, ulong *nr2)
   }
 }
 
-size_t
-Field::do_last_null_byte() const
+size_t Field::do_last_null_byte() const
 {
-  DBUG_ASSERT(null_ptr == NULL || null_ptr >= table->record[0]);
-  if (null_ptr)
-    return null_offset() + 1;
-  return LAST_NULL_BYTE_UNDEF;
+  DBUG_ASSERT(!real_maybe_null() || m_null_ptr >= table->record[0]);
+  return real_maybe_null() ? null_offset() + 1 : (size_t) LAST_NULL_BYTE_UNDEF;
 }
 
 
-void Field::copy_from_tmp(int row_offset)
+void Field::copy_data(my_ptrdiff_t src_record_offset)
 {
-  memcpy(ptr,ptr+row_offset,pack_length());
-  if (null_ptr)
+  memcpy(ptr, ptr + src_record_offset, pack_length());
+
+  if (real_maybe_null())
   {
-    *null_ptr= (uchar) ((null_ptr[0] & (uchar) ~(uint) null_bit) |
-			(null_ptr[row_offset] & (uchar) null_bit));
-  }
+    // Set to NULL if the source record is NULL, otherwise set to NOT-NULL.
+    m_null_ptr[0]= (m_null_ptr[0]                 & ~null_bit) |
+                   (m_null_ptr[src_record_offset] &  null_bit);
+  } else if (is_tmp_nullable())
+    m_is_tmp_null= false;
 }
 
 
@@ -1894,7 +2007,7 @@ Field *Field::new_key_field(MEM_ROOT *ro
   if ((tmp= new_field(root, new_table, table == new_table)))
   {
     tmp->ptr=      new_ptr;
-    tmp->null_ptr= new_null_ptr;
+    tmp->m_null_ptr= new_null_ptr;
     tmp->null_bit= new_null_bit;
   }
   return tmp;
@@ -6511,7 +6624,7 @@ Field_longstr::check_string_copy_error(c
                                        const char *from_end_pos,
                                        const char *end,
                                        bool count_spaces,
-                                       const CHARSET_INFO *cs) const
+                                       const CHARSET_INFO *cs)
 {
   const char *pos;
   char tmp[32];
@@ -6555,7 +6668,7 @@ Field_longstr::check_string_copy_error(c
 
 type_conversion_status
 Field_longstr::report_if_important_data(const char *pstr, const char *end,
-                                        bool count_spaces) const
+                                        bool count_spaces)
 {
   if ((pstr < end) && table->in_use->count_cuted_fields)
   {
@@ -8909,7 +9022,7 @@ Field_bit::Field_bit(uchar *ptr_arg, uin
   flags|= UNSIGNED_FLAG;
   /*
     Ensure that Field::eq() can distinguish between two different bit fields.
-    (two bit fields that are not null, may have same ptr and null_ptr)
+    (two bit fields that are not null, may have same ptr and m_null_ptr)
   */
   if (!null_ptr_arg)
     null_bit= bit_ofs_arg;
@@ -8947,9 +9060,9 @@ Field_bit::do_last_null_byte() const
   */
   DBUG_PRINT("test", ("bit_ofs: %d, bit_len: %d  bit_ptr: 0x%lx",
                       bit_ofs, bit_len, (long) bit_ptr));
-  uchar *result;
+  const uchar *result;
   if (bit_len == 0)
-    result= null_ptr;
+    result= get_null_ptr();
   else if (bit_ofs + bit_len > 8)
     result= bit_ptr + 1;
   else
@@ -9407,7 +9520,7 @@ void Field_bit::set_default()
 {
   if (bit_len > 0)
   {
-    my_ptrdiff_t const offset= table->s->default_values - table->record[0];
+    my_ptrdiff_t offset= table->default_values_offset();
     uchar bits= get_rec_bits(bit_ptr + offset, bit_ofs, bit_len);
     set_rec_bits(bits, bit_ptr, bit_ofs, bit_len);
   }
@@ -10395,11 +10508,9 @@ Create_field::Create_field(Field *old_fi
   {
     char buff[MAX_FIELD_WIDTH];
     String tmp(buff,sizeof(buff), charset);
-    my_ptrdiff_t diff;
 
     /* Get the value from default_values */
-    diff= (my_ptrdiff_t) (orig_field->table->s->default_values-
-                          orig_field->table->record[0]);
+    my_ptrdiff_t diff= orig_field->table->default_values_offset();
     orig_field->move_field_offset(diff);	// Points now at default_values
     if (!orig_field->is_real_null())
     {
@@ -10477,12 +10588,17 @@ uint32 Field_blob::max_display_length()
  Warning handling
 *****************************************************************************/
 
+
 /**
   Produce warning or note about data saved into field.
 
   @param level            - level of message (Note/Warning/Error)
   @param code             - error code of message to be produced
   @param cut_increment    - whenever we should increase cut fields count
+  @param view_db_name     - if set this is the database name for view
+                            that causes the warning
+  @param view_name        - if set this is the name of view that causes
+                            the warning
 
   @note
     This function won't produce warning and increase cut fields counter
@@ -10491,29 +10607,82 @@ uint32 Field_blob::max_display_length()
     if count_cuted_fields == CHECK_FIELD_IGNORE then we ignore notes.
     This allows us to avoid notes in optimisation, like convert_constant_item().
 
+    In case of execution statements INSERT/INSERT SELECT/REPLACE/REPLACE SELECT
+    the method emits only one warning message for the following
+    types of warning: ER_BAD_NULL_ERROR, ER_WARN_NULL_TO_NOTNULL,
+    ER_NO_DEFAULT_FOR_FIELD.
   @retval
     1 if count_cuted_fields == CHECK_FIELD_IGNORE and error level is not NOTE
   @retval
     0 otherwise
 */
 
-bool 
-Field::set_warning(Sql_condition::enum_severity_level level, uint code,
-                   int cut_increment) const
+bool Field::set_warning(Sql_condition::enum_severity_level level,
+                        uint code,
+                        int cut_increment,
+                        const char *view_db_name,
+                        const char *view_name)
 {
   /*
     If this field was created only for type conversion purposes it
     will have table == NULL.
   */
+
   THD *thd= table ? table->in_use : current_thd;
-  if (thd->count_cuted_fields)
+
+  if (!thd->count_cuted_fields)
+    return level >= Sql_condition::SL_WARNING;
+
+  thd->cuted_fields+= cut_increment;
+
+  if (thd->lex->sql_command != SQLCOM_INSERT &&
+      thd->lex->sql_command != SQLCOM_INSERT_SELECT &&
+      thd->lex->sql_command != SQLCOM_REPLACE &&
+      thd->lex->sql_command != SQLCOM_REPLACE_SELECT)
   {
-    thd->cuted_fields+= cut_increment;
+    // We aggregate warnings from only INSERT and REPLACE statements.
+
     push_warning_printf(thd, level, code, ER(code), field_name,
                         thd->get_stmt_da()->current_row_for_condition());
+
     return 0;
   }
-  return level >= Sql_condition::SL_WARNING;
+
+  unsigned int current_warning_mask= 0;
+
+  if (code == ER_BAD_NULL_ERROR)
+    current_warning_mask= BAD_NULL_ERROR_PUSHED;
+  else if (code == ER_NO_DEFAULT_FOR_FIELD)
+    current_warning_mask= NO_DEFAULT_FOR_FIELD_PUSHED;
+
+  if (current_warning_mask)
+  {
+    if (!(m_warnings_pushed & current_warning_mask))
+    {
+      push_warning_printf(thd, level, code, ER(code), field_name,
+                          thd->get_stmt_da()->current_row_for_condition());
+      m_warnings_pushed|= current_warning_mask;
+    }
+  }
+  else if (code == ER_NO_DEFAULT_FOR_VIEW_FIELD)
+  {
+    if (!(m_warnings_pushed & NO_DEFAULT_FOR_VIEW_FIELD_PUSHED))
+    {
+      push_warning_printf(thd, Sql_condition::SL_WARNING,
+                          ER_NO_DEFAULT_FOR_VIEW_FIELD,
+                          ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
+                          view_db_name,
+                          view_name);
+      m_warnings_pushed|= NO_DEFAULT_FOR_VIEW_FIELD_PUSHED;
+    }
+  }
+  else
+  {
+    push_warning_printf(thd, level, code, ER(code), field_name,
+                        thd->get_stmt_da()->current_row_for_condition());
+  }
+
+  return 0;
 }
 
 

=== modified file 'sql/field.h'
--- a/sql/field.h	2012-11-29 16:57:42 +0000
+++ b/sql/field.h	2012-12-11 11:58:31 +0000
@@ -482,12 +482,40 @@ public:
 
   uchar		*ptr;			// Position to field in record
 
-protected:
+private:
   /**
      Byte where the @c NULL bit is stored inside a record. If this Field is a
      @c NOT @c NULL field, this member is @c NULL.
   */
-  uchar		*null_ptr;
+  uchar *m_null_ptr;
+
+  /**
+    Flag: if the NOT-NULL field can be temporary NULL.
+  */
+  bool m_is_tmp_nullable;
+
+  /**
+    This is a flag with the following semantics:
+      - it can be changed only when m_is_tmp_nullable is true;
+      - it specifies if this field in the first current record
+        (TABLE::record[0]) was set to NULL (temporary NULL).
+
+    This flag is used for trigger handling.
+  */
+  bool m_is_tmp_null;
+
+  /**
+    The value of THD::count_cuted_fields at the moment of setting
+    m_is_tmp_null attribute.
+  */
+  enum_check_fields m_count_cuted_fields_saved;
+
+protected:
+  const uchar *get_null_ptr() const
+  { return m_null_ptr; }
+
+  uchar *get_null_ptr() 
+  { return m_null_ptr; }
 
 public:
   /*
@@ -539,10 +567,74 @@ public:
    */
   bool is_created_from_null_item;
 
+private:
+  enum enum_pushed_warnings
+  {
+    BAD_NULL_ERROR_PUSHED= 1,
+    NO_DEFAULT_FOR_FIELD_PUSHED= 2,
+    NO_DEFAULT_FOR_VIEW_FIELD_PUSHED= 4
+  };
+
+  /*
+    Bitmask specifying which warnings have been already pushed in order
+    not to repeat the same warning for the collmn multiple times.
+    Uses values of enum_pushed_warnings to control pushed warnings.
+  */
+  unsigned int m_warnings_pushed;
+
+public:
   Field(uchar *ptr_arg,uint32 length_arg,uchar *null_ptr_arg,
         uchar null_bit_arg, utype unireg_check_arg,
         const char *field_name_arg);
-  virtual ~Field() {}
+
+  virtual ~Field()
+  { }
+
+  void reset_warnings()
+  { m_warnings_pushed= 0; }
+
+  /**
+    Turn on temporary nullability for the field.
+  */
+  void set_tmp_nullable()
+  {
+    m_is_tmp_nullable= true;
+  }
+
+  /**
+    Turn off temporary nullability for the field.
+  */
+  void reset_tmp_nullable()
+  {
+    m_is_tmp_nullable= false;
+  }
+
+  /**
+    Reset temporary NULL value for field
+  */
+  void reset_tmp_null()
+  {
+    m_is_tmp_null= false;
+  }
+
+  void set_tmp_null();
+
+  /**
+    @return temporary NULL-ability flag.
+    @retval true if NULL can be assigned temporary to the Field.
+    @retval false if NULL can not be assigned even temporary to the Field.
+  */
+  bool is_tmp_nullable() const
+  { return m_is_tmp_nullable; }
+
+  /**
+    @return whether Field has temporary value NULL.
+    @retval true if the Field has temporary value NULL.
+    @retval false if the Field's value is NOT NULL, or if the temporary
+    NULL-ability flag is reset.
+  */
+  bool is_tmp_null() const
+  { return is_tmp_nullable() && m_is_tmp_null; }
 
   /* Store functions returns 1 on overflow and -1 on fatal error */
   virtual type_conversion_status store(const char *to, uint length,
@@ -673,7 +765,7 @@ public:
   static Item_result result_merge_type(enum_field_types);
   virtual bool eq(Field *field)
   {
-    return (ptr == field->ptr && null_ptr == field->null_ptr &&
+    return (ptr == field->ptr && m_null_ptr == field->m_null_ptr &&
             null_bit == field->null_bit && field->type() == type());
   }
   virtual bool eq_def(Field *field);
@@ -776,20 +868,13 @@ public:
     tm.tv_usec= 0;
     store_timestamp(&tm);
   }
+
   virtual void set_default()
   {
     if (has_insert_default_function())
-    {
       evaluate_insert_default_function();
-      return;
-    }
-
-    my_ptrdiff_t l_offset= (my_ptrdiff_t) (table->s->default_values -
-					  table->record[0]);
-    memcpy(ptr, ptr + l_offset, pack_length());
-    if (real_maybe_null())
-      *null_ptr= ((*null_ptr & (uchar) ~null_bit) |
-		  (null_ptr[l_offset] & null_bit));
+    else
+      copy_data(table->default_values_offset());
   }
 
 
@@ -869,6 +954,12 @@ public:
   bool is_temporal_with_date_and_time() const
   { return is_temporal_type_with_date_and_time(type()); }
 
+  /**
+    Check whether the full table's row is NULL or the Field has value NULL.
+
+    @return    true if the full table's row is NULL or the Field has value NULL
+               false if neither table's row nor the Field has value NULL
+  */
   bool is_null(my_ptrdiff_t row_offset= 0) const
   {
     /*
@@ -879,47 +970,79 @@ public:
       this is the case (in which TABLE::null_row is true), the field
       is considered to be NULL.
 
-      Otherwise, if the field is NULLable, it has a valid null_ptr
+      Otherwise, if the field is NULLable, it has a valid m_null_ptr
       pointer, and its NULLity is recorded in the "null_bit" bit of
-      null_ptr[row_offset].
+      m_null_ptr[row_offset].
     */
-    return table->null_row ? true : is_real_null(row_offset);
+    return table->null_row ?
+           true :
+           is_real_null(row_offset);
   }
 
-  bool is_real_null(my_ptrdiff_t row_offset= 0) const
-  { return real_maybe_null() ? test(null_ptr[row_offset] & null_bit) : false; }
-
-  bool is_null_in_record(const uchar *record) const
-  { return real_maybe_null() ? test(record[null_offset()] & null_bit) : false; }
+  /**
+    Check whether the Field has value NULL (temporary or actual).
 
-  void set_null(my_ptrdiff_t row_offset= 0)
+    @return   true if the Field has value NULL (temporary or actual)
+              false if the Field has value NOT NULL.
+  */
+  bool is_real_null(my_ptrdiff_t row_offset= 0) const
   {
     if (real_maybe_null())
-      null_ptr[row_offset]|= null_bit;
+      return test(m_null_ptr[row_offset] & null_bit);
+
+    if (is_tmp_nullable())
+      return m_is_tmp_null;
+
+    return false;
   }
 
-  void set_notnull(my_ptrdiff_t row_offset= 0)
+  /**
+    Check if the Field has value NULL or the record specified by argument
+    has value NULL for this Field.
+
+    @return    true if the Field has value NULL or the record has value NULL
+               for thois Field.
+  */
+  bool is_null_in_record(const uchar *record) const
   {
     if (real_maybe_null())
-      null_ptr[row_offset]&= (uchar) ~null_bit;
+      return test(record[null_offset()] & null_bit);
+
+    return is_tmp_nullable() ? m_is_tmp_null : false;
   }
 
+  void set_null(my_ptrdiff_t row_offset= 0);
+
+  void set_notnull(my_ptrdiff_t row_offset= 0);
+
+  type_conversion_status check_constraints(int mysql_errno);
+
+  /**
+    Remember the value of THD::count_cuted_fields to handle possible
+    NOT-NULL constraint errors after BEFORE-trigger execution is finished.
+    We should save the value of THD::count_cuted_fields before starting
+    BEFORE-trigger processing since during triggers execution the
+    value of THD::count_cuted_fields could be changed.
+  */
+  void set_count_cuted_fields(enum_check_fields count_cuted_fields)
+  { m_count_cuted_fields_saved= count_cuted_fields; }
+
   bool maybe_null(void) const
   { return real_maybe_null() || table->maybe_null; }
 
   /// @return true if this field is NULL-able, false otherwise.
   bool real_maybe_null(void) const
-  { return null_ptr != 0; }
+  { return m_null_ptr != NULL; }
 
   uint null_offset(const uchar *record) const
-  { return (uint) (null_ptr - record); }
+  { return (uint) (m_null_ptr - record); }
 
   uint null_offset() const
   { return null_offset(table->record[0]); }
 
   void set_null_ptr(uchar *p_null_ptr, uint p_null_bit)
   {
-    null_ptr= p_null_ptr;
+    m_null_ptr= p_null_ptr;
     null_bit= p_null_bit;
   }
 
@@ -979,7 +1102,7 @@ public:
                                uint new_null_bit);
 
   Field *new_key_field(MEM_ROOT *root, TABLE *new_table, uchar *new_ptr)
-  { return new_key_field(root, new_table, new_ptr, null_ptr, null_bit); }
+  { return new_key_field(root, new_table, new_ptr, m_null_ptr, null_bit); }
 
   /**
      Makes a shallow copy of the Field object.
@@ -1002,23 +1125,30 @@ public:
      @param mem_root MEM_ROOT to use for memory allocation.
      @retval NULL If memory allocation failed.
    */
-  virtual Field *clone(MEM_ROOT *mem_root) const =0;
-  inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
+  virtual Field *clone(MEM_ROOT *mem_root) const = 0;
+
+  void move_field(uchar *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg)
   {
-    ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
+    ptr= ptr_arg;
+    m_null_ptr= null_ptr_arg;
+    null_bit= null_bit_arg;
   }
-  inline void move_field(uchar *ptr_arg) { ptr=ptr_arg; }
+
+  void move_field(uchar *ptr_arg)
+  { ptr= ptr_arg; }
+
   virtual void move_field_offset(my_ptrdiff_t ptr_diff)
   {
-    ptr=ADD_TO_PTR(ptr,ptr_diff, uchar*);
-    if (null_ptr)
-      null_ptr=ADD_TO_PTR(null_ptr,ptr_diff,uchar*);
+    ptr= ADD_TO_PTR(ptr, ptr_diff, uchar*);
+    if (real_maybe_null())
+      m_null_ptr= ADD_TO_PTR(m_null_ptr, ptr_diff, uchar*);
   }
+
   virtual void get_image(uchar *buff, uint length, const CHARSET_INFO *cs)
-    { memcpy(buff,ptr,length); }
-  virtual void set_image(const uchar *buff,uint length,
-                         const CHARSET_INFO *cs)
-    { memcpy(ptr,buff,length); }
+  { memcpy(buff, ptr, length); }
+
+  virtual void set_image(const uchar *buff, uint length, const CHARSET_INFO *cs)
+  { memcpy(ptr, buff, length); }
 
 
   /*
@@ -1113,7 +1243,9 @@ public:
   {
     return (uint) (ptr - record);
   }
-  void copy_from_tmp(int offset);
+
+  void copy_data(my_ptrdiff_t src_record_offset);
+
   uint fill_cache_field(struct st_cache_field *copy);
   virtual bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
   virtual bool get_time(MYSQL_TIME *ltime);
@@ -1137,8 +1269,37 @@ public:
   { return DERIVATION_IMPLICIT; }
   virtual uint repertoire(void) const { return MY_REPERTOIRE_UNICODE30; }
   virtual void set_derivation(enum Derivation derivation_arg) { }
-  bool set_warning(Sql_condition::enum_severity_level, unsigned int code,
-                   int cuted_increment) const;
+
+  /**
+    Produce warning or note about data saved into field.
+
+    @param level            - level of message (Note/Warning/Error)
+    @param code             - error code of message to be produced
+    @param cut_increment    - whenever we should increase cut fields count
+
+    @note
+      This function won't produce warning and increase cut fields counter
+      if count_cuted_fields == CHECK_FIELD_IGNORE for current thread.
+
+      if count_cuted_fields == CHECK_FIELD_IGNORE then we ignore notes.
+      This allows us to avoid notes in optimization, like
+      convert_constant_item().
+
+    @retval
+      1 if count_cuted_fields == CHECK_FIELD_IGNORE and error level is not NOTE
+    @retval
+      0 otherwise
+  */
+  bool set_warning(Sql_condition::enum_severity_level level, unsigned int code,
+                   int cut_increment)
+  {
+    return set_warning(level, code, cut_increment, NULL, NULL);
+  }
+
+  bool set_warning(Sql_condition::enum_severity_level level, uint code,
+                   int cut_increment, const char *view_db,
+                   const char *view_name);
+
   inline bool check_overflow(int op_result)
   {
     return (op_result == E_DEC_OVERFLOW);
@@ -1493,14 +1654,14 @@ class Field_longstr :public Field_str
 protected:
   type_conversion_status report_if_important_data(const char *ptr,
                                                   const char *end,
-                                                  bool count_spaces) const;
+                                                  bool count_spaces);
   type_conversion_status
     check_string_copy_error(const char *well_formed_error_pos,
                             const char *cannot_convert_error_pos,
                             const char *from_end_pos,
                             const char *end,
                             bool count_spaces,
-                            const CHARSET_INFO *cs) const;
+                            const CHARSET_INFO *cs);
 public:
   Field_longstr(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
                 uchar null_bit_arg, utype unireg_check_arg,

=== modified file 'sql/field_conv.cc'
--- a/sql/field_conv.cc	2012-11-06 14:16:49 +0000
+++ b/sql/field_conv.cc	2012-12-11 11:58:31 +0000
@@ -100,12 +100,22 @@ static void do_field_to_null_str(Copy_fi
 
 type_conversion_status set_field_to_null(Field *field)
 {
-  if (field->real_maybe_null())
+  if (field->real_maybe_null() || field->is_tmp_nullable())
   {
     field->set_null();
     field->reset();
     return TYPE_OK;
   }
+  DBUG_ASSERT(0);
+
+#ifdef DBUG_OFF
+  /**
+    Can not be true, but do not take chances in production.
+    Test coverage discovered that the source code below wasn't
+    executed but to protect mysql server from unexpected behaviour
+    caused by some possible wrong code snippet in the server code base
+    we leave it for server compiled without debug.
+  */
   field->reset();
   switch (field->table->in_use->count_cuted_fields) {
   case CHECK_FIELD_WARN:
@@ -119,7 +129,8 @@ type_conversion_status set_field_to_null
     return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
   }
   DBUG_ASSERT(false); // impossible
-  return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
+  return TYPE_ERR_NULL_CONSTRAINT_VIOLATION; // to avoid compiler's warning
+#endif
 }
 
 
@@ -149,6 +160,7 @@ set_field_to_null_with_conversions(Field
     field->reset();
     return TYPE_OK;
   }
+
   if (no_conversions)
     return TYPE_ERR_NULL_CONSTRAINT_VIOLATION;
 
@@ -166,7 +178,7 @@ set_field_to_null_with_conversions(Field
     Item_func_now_local::store_in(field);
     return TYPE_OK;			// Ok to set time to NULL
   }
-  
+
   // Note: we ignore any potential failure of reset() here.
   field->reset();
 
@@ -175,6 +187,14 @@ set_field_to_null_with_conversions(Field
     field->table->auto_increment_field_not_null= FALSE;
     return TYPE_OK;		        // field is set in fill_record()
   }
+
+  if (field->is_tmp_nullable())
+  {
+    field->set_null();
+    field->reset();
+    return TYPE_OK;
+  }
+
   switch (field->table->in_use->count_cuted_fields) {
   case CHECK_FIELD_WARN:
     field->set_warning(Sql_condition::SL_WARNING, ER_BAD_NULL_ERROR, 1);
@@ -550,7 +570,7 @@ void Copy_field::set(uchar *to,Field *fr
   null_row= &from->table->null_row;
   if (from->maybe_null())
   {
-    from_null_ptr=from->null_ptr;
+    from_null_ptr=from->get_null_ptr();
     from_bit=	  from->null_bit;
     to_ptr[0]=	  1;				// Null as default value
     to_null_ptr=  (uchar*) to_ptr++;
@@ -598,11 +618,11 @@ void Copy_field::set(Field *to,Field *fr
   null_row= &from->table->null_row;
   if (from->maybe_null())
   {
-    from_null_ptr=	from->null_ptr;
+    from_null_ptr=	from->get_null_ptr();
     from_bit=		from->null_bit;
     if (to_field->real_maybe_null())
     {
-      to_null_ptr=	to->null_ptr;
+      to_null_ptr=	to->get_null_ptr();
       to_bit=		to->null_bit;
       do_copy=	do_copy_null;
     }
@@ -618,7 +638,7 @@ void Copy_field::set(Field *to,Field *fr
   }
   else if (to_field->real_maybe_null())
   {
-    to_null_ptr=	to->null_ptr;
+    to_null_ptr=	to->get_null_ptr();
     to_bit=		to->null_bit;
     do_copy= do_copy_maybe_null;
   }

=== modified file 'sql/ha_ndbcluster.cc'
--- a/sql/ha_ndbcluster.cc	2012-11-23 14:18:01 +0000
+++ b/sql/ha_ndbcluster.cc	2012-12-11 11:55:33 +0000
@@ -6231,7 +6231,7 @@ static void get_default_value(void *def_
 {
   DBUG_ASSERT(field != NULL);
 
-  my_ptrdiff_t src_offset= field->table->s->default_values - field->table->record[0];
+  my_ptrdiff_t src_offset= field->table->default_values_offset();
 
   {
     if (bitmap_is_set(field->table->read_set, field->field_index))
@@ -8631,8 +8631,7 @@ static int create_ndb_column(THD *thd,
       {
         if (!(field->flags & NO_DEFAULT_VALUE_FLAG))
         {
-          my_ptrdiff_t src_offset= field->table->s->default_values 
-            - field->table->record[0];
+          my_ptrdiff_t src_offset= field->table->default_values_offset();
           if ((! field->is_real_null(src_offset)) ||
               ((field->flags & NOT_NULL_FLAG)))
           {

=== modified file 'sql/ha_ndbcluster_cond.h'
--- a/sql/ha_ndbcluster_cond.h	2011-11-15 13:13:38 +0000
+++ b/sql/ha_ndbcluster_cond.h	2012-12-11 11:55:33 +0000
@@ -258,7 +258,7 @@ public:
       length= item->max_length;
       my_bitmap_map *old_map=
         dbug_tmp_use_all_columns(field->table, field->table->write_set);
-      ((Item *)item)->save_in_field(field, FALSE);
+      ((Item *)item)->save_in_field(field, false);
       dbug_tmp_restore_column_map(field->table->write_set, old_map);
     }
     DBUG_RETURN(length);

=== modified file 'sql/item.cc'
--- a/sql/item.cc	2012-11-22 14:40:47 +0000
+++ b/sql/item.cc	2012-12-11 11:56:43 +0000
@@ -2534,7 +2534,7 @@ adjust_max_effective_column_length(Field
 void Item_field::set_field(Field *field_par)
 {
   field=result_field=field_par;			// for easy coding with fields
-  maybe_null=field->maybe_null();
+  maybe_null= field->maybe_null() || field->is_tmp_nullable();
   decimals= field->decimals();
   table_name= *field_par->table_name;
   field_name= field_par->field_name;
@@ -7959,9 +7959,7 @@ bool Item_default_value::fix_fields(THD 
   if (def_field == NULL)
     goto error;
 
-  def_field->move_field_offset((my_ptrdiff_t)
-                               (def_field->table->s->default_values -
-                                def_field->table->record[0]));
+  def_field->move_field_offset(def_field->table->default_values_offset());
   set_field(def_field);
   return FALSE;
 
@@ -8206,7 +8204,7 @@ bool Item_trigger_field::set_value(THD *
 
   field->table->copy_blobs= true;
 
-  int err_code= item->save_in_field(field, 0);
+  int err_code= item->save_in_field(field, false);
 
   field->table->copy_blobs= copy_blobs_saved;
 

=== modified file 'sql/item.h'
--- a/sql/item.h	2012-11-29 16:57:42 +0000
+++ b/sql/item.h	2012-12-11 11:58:31 +0000
@@ -24,6 +24,7 @@
 #include "thr_malloc.h"                         /* sql_calloc */
 #include "field.h"                              /* Derivation */
 #include "sql_array.h"
+#include "sql_trigger.h"
 
 class Protocol;
 struct TABLE_LIST;
@@ -796,10 +797,13 @@ public:
   */
   virtual type_conversion_status save_in_field(Field *field,
                                                bool no_conversions);
+
   virtual void save_org_in_field(Field *field)
-  { (void) save_in_field(field, 1); }
+  { save_in_field(field, true); }
+
   virtual type_conversion_status save_safe_in_field(Field *field)
-  { return save_in_field(field, 1); }
+  { return save_in_field(field, true); }
+
   virtual bool send(Protocol *protocol, String *str);
   virtual bool eq(const Item *, bool binary_cmp) const;
   virtual Item_result result_type() const { return REAL_RESULT; }
@@ -4045,7 +4049,11 @@ public:
 
   bool set_value(THD *thd, Item **it)
   {
-    return set_value(thd, NULL, it);
+    bool ret= set_value(thd, NULL, it);
+    if (!ret)
+      bitmap_set_bit(triggers->trigger_table->fields_set_during_insert,
+                     field_idx);
+    return ret;
   }
 
 private:

=== modified file 'sql/item_cmpfunc.cc'
--- a/sql/item_cmpfunc.cc	2012-11-29 16:57:42 +0000
+++ b/sql/item_cmpfunc.cc	2012-12-11 11:55:33 +0000
@@ -451,7 +451,7 @@ static bool convert_constant_item(THD *t
       orig_field_val= field->val_int();
     int rc;
     if (!(*item)->is_null() &&
-        (((rc= (*item)->save_in_field(field, 1)) == TYPE_OK) ||
+        (((rc= (*item)->save_in_field(field, true)) == TYPE_OK) ||
          rc == TYPE_NOTE_TIME_TRUNCATED)) // TS-TODO
     {
       int field_cmp= 0;

=== modified file 'sql/item_func.h'
--- a/sql/item_func.h	2012-11-21 12:44:48 +0000
+++ b/sql/item_func.h	2012-12-11 11:55:33 +0000
@@ -1715,13 +1715,16 @@ public:
   virtual void print(String *str, enum_query_type query_type);
   void print_assignment(String *str, enum_query_type query_type);
   const char *func_name() const { return "set_user_var"; }
+
   type_conversion_status save_in_field(Field *field, bool no_conversions,
                                        bool can_use_result_field);
+
   type_conversion_status save_in_field(Field *field, bool no_conversions)
-  {
-    return save_in_field(field, no_conversions, 1);
-  }
-  void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); }
+  { return save_in_field(field, no_conversions, true); }
+
+  void save_org_in_field(Field *field)
+  { save_in_field(field, true, false); }
+
   bool register_field_in_read_map(uchar *arg);
   bool set_entry(THD *thd, bool create_if_not_exists);
   void cleanup();

=== modified file 'sql/item_sum.cc'
--- a/sql/item_sum.cc	2012-11-14 06:25:46 +0000
+++ b/sql/item_sum.cc	2012-12-11 11:56:43 +0000
@@ -971,7 +971,7 @@ bool Aggregator_distinct::add()
       return TRUE;
 
     for (Field **field=table->field ; *field ; field++)
-      if ((*field)->is_real_null(0))
+      if ((*field)->is_real_null())
         return 0;					// Don't count NULL
 
     if (tree)
@@ -991,7 +991,7 @@ bool Aggregator_distinct::add()
   }
   else
   {
-    item_sum->get_arg(0)->save_in_field(table->field[0], FALSE);
+    item_sum->get_arg(0)->save_in_field(table->field[0], false);
     if (table->field[0]->is_null())
       return 0;
     DBUG_ASSERT(tree);
@@ -2425,7 +2425,7 @@ void Item_sum_hybrid::min_max_update_tem
   nr= args[0]->val_temporal_by_field_type();
   if (!args[0]->null_value)
   {
-    if (result_field->is_null(0))
+    if (result_field->is_null())
       old_nr= nr;
     else
     {
@@ -2436,7 +2436,7 @@ void Item_sum_hybrid::min_max_update_tem
     }
     result_field->set_notnull();
   }
-  else if (result_field->is_null(0))
+  else if (result_field->is_null())
     result_field->set_null();
   result_field->store_packed(old_nr);
 }
@@ -2467,12 +2467,12 @@ void Item_sum_hybrid::min_max_update_rea
   nr= args[0]->val_real();
   if (!args[0]->null_value)
   {
-    if (result_field->is_null(0) ||
+    if (result_field->is_null() ||
 	(cmp_sign > 0 ? old_nr > nr : old_nr < nr))
       old_nr=nr;
     result_field->set_notnull();
   }
-  else if (result_field->is_null(0))
+  else if (result_field->is_null())
     result_field->set_null();
   result_field->store(old_nr);
 }
@@ -2486,7 +2486,7 @@ void Item_sum_hybrid::min_max_update_int
   nr=args[0]->val_int();
   if (!args[0]->null_value)
   {
-    if (result_field->is_null(0))
+    if (result_field->is_null())
       old_nr=nr;
     else
     {
@@ -2499,7 +2499,7 @@ void Item_sum_hybrid::min_max_update_int
     }
     result_field->set_notnull();
   }
-  else if (result_field->is_null(0))
+  else if (result_field->is_null())
     result_field->set_null();
   result_field->store(old_nr, unsigned_flag);
 }
@@ -2517,7 +2517,7 @@ void Item_sum_hybrid::min_max_update_dec
   const my_decimal *nr= args[0]->val_decimal(&nr_val);
   if (!args[0]->null_value)
   {
-    if (result_field->is_null(0))
+    if (result_field->is_null())
       old_nr=nr;
     else
     {
@@ -2528,7 +2528,7 @@ void Item_sum_hybrid::min_max_update_dec
     }
     result_field->set_notnull();
   }
-  else if (result_field->is_null(0))
+  else if (result_field->is_null())
     result_field->set_null();
   result_field->store_decimal(old_nr);
 }

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	2012-11-30 15:26:19 +0000
+++ b/sql/opt_range.cc	2012-12-11 11:55:33 +0000
@@ -6432,7 +6432,7 @@ static bool save_value_and_handle_conver
   */
 
   // Note that value may be a stored function call, executed here.
-  const type_conversion_status err= value->save_in_field_no_warnings(field, 1);
+  const type_conversion_status err= value->save_in_field_no_warnings(field, true);
   field->table->in_use->variables.sql_mode= orig_sql_mode;
 
   switch (err) {

=== modified file 'sql/partition_info.cc'
--- a/sql/partition_info.cc	2012-11-30 15:26:19 +0000
+++ b/sql/partition_info.cc	2012-12-11 11:58:31 +0000
@@ -455,12 +455,13 @@ bool partition_info::set_used_partition(
 
   if (fields.elements || !values.elements)
   {
-    if (fill_record(thd, fields, values, false, &full_part_field_set))
+    if (fill_record(thd, fields, values, false, &full_part_field_set, NULL))
       goto err;
   }
   else
   {
-    if (fill_record(thd, table->field, values, false, &full_part_field_set))
+    if (fill_record(thd, table->field, values, false, &full_part_field_set,
+                    NULL))
       goto err;
   }
   DBUG_ASSERT(!table->auto_increment_field_not_null);
@@ -2667,7 +2668,7 @@ bool partition_info::fix_column_value_fu
         thd->variables.sql_mode= 0;
         save_got_warning= thd->got_warning;
         thd->got_warning= 0;
-        if (column_item->save_in_field(field, TRUE) ||
+        if (column_item->save_in_field(field, true) ||
             thd->got_warning)
         {
           my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));

=== modified file 'sql/rpl_record.cc'
--- a/sql/rpl_record.cc	2012-11-01 11:46:09 +0000
+++ b/sql/rpl_record.cc	2012-12-11 11:55:33 +0000
@@ -67,7 +67,7 @@ pack_row(TABLE *table, MY_BITMAP const* 
   uchar *pack_ptr = row_data + null_byte_count;
   uchar *null_ptr = row_data;
   my_ptrdiff_t const rec_offset= record - table->record[0];
-  my_ptrdiff_t const def_offset= table->s->default_values - table->record[0];
+  my_ptrdiff_t const def_offset= table->default_values_offset();
 
   DBUG_ENTER("pack_row");
 

=== modified file 'sql/rpl_record_old.cc'
--- a/sql/rpl_record_old.cc	2011-09-07 10:08:09 +0000
+++ b/sql/rpl_record_old.cc	2012-12-11 11:55:33 +0000
@@ -28,7 +28,7 @@ pack_row_old(TABLE *table, MY_BITMAP con
   uchar *ptr;
   uint i;
   my_ptrdiff_t const rec_offset= record - table->record[0];
-  my_ptrdiff_t const def_offset= table->s->default_values - table->record[0];
+  my_ptrdiff_t const def_offset= table->default_values_offset();
   memcpy(row_data, record, n_null_bytes);
   ptr= row_data+n_null_bytes;
 

=== modified file 'sql/sp.cc'
--- a/sql/sp.cc	2012-11-21 12:44:48 +0000
+++ b/sql/sp.cc	2012-12-11 11:55:33 +0000
@@ -2679,7 +2679,7 @@ bool sp_eval_expr(THD *thd, Field *resul
 
   /* Save the value in the field. Convert the value if needed. */
 
-  expr_item->save_in_field(result_field, 0);
+  expr_item->save_in_field(result_field, false);
 
   thd->count_cuted_fields= save_count_cuted_fields;
   thd->abort_on_warning= save_abort_on_warning;

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2012-11-30 15:26:19 +0000
+++ b/sql/sql_base.cc	2012-12-11 11:58:31 +0000
@@ -8780,12 +8780,13 @@ err_no_arena:
 /*
   Fill fields with given items.
 
-  @param thd           thread handler
-  @param fields        Item_fields list to be filled
-  @param values        values to fill with
-  @param ignore_errors TRUE if we should ignore errors
-  @param bitmap        Bitmap over fields to fill
-
+  @param thd                        thread handler
+  @param fields                     Item_fields list to be filled
+  @param values                     values to fill with
+  @param ignore_errors              TRUE if we should ignore errors
+  @param bitmap                     Bitmap over fields to fill
+  @param insert_into_fields_bitmap  Bitmap for fields that is set
+                                    in fill_record
   @note fill_record() may set table->auto_increment_field_not_null and a
   caller should make sure that it is reset after their last call to this
   function.
@@ -8797,7 +8798,8 @@ err_no_arena:
 
 bool
 fill_record(THD * thd, List<Item> &fields, List<Item> &values,
-            bool ignore_errors, MY_BITMAP *bitmap)
+            bool ignore_errors, MY_BITMAP *bitmap,
+            MY_BITMAP *insert_into_fields_bitmap)
 {
   List_iterator_fast<Item> f(fields),v(values);
   Item *value, *fld;
@@ -8840,11 +8842,14 @@ fill_record(THD * thd, List<Item> &field
     table= rfield->table;
     if (rfield == table->next_number_field)
       table->auto_increment_field_not_null= TRUE;
-    if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
+    if ((value->save_in_field(rfield, false) < 0) && !ignore_errors)
     {
       my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
       goto err;
     }
+    bitmap_set_bit(table->fields_set_during_insert, rfield->field_index);
+    if (insert_into_fields_bitmap)
+      bitmap_set_bit(insert_into_fields_bitmap, rfield->field_index);
   }
   DBUG_RETURN(thd->is_error());
 err:
@@ -8854,49 +8859,204 @@ err:
 }
 
 
+/**
+  Check the NOT NULL constraint on all the fields of the current record.
+
+  @param thd            Thread context.
+  @param fields         Collection of fields.
+  @param ignore_errors  Flag if errors should be suppressed.
+
+  @return Error status.
+*/
+static bool check_record(THD *thd, List<Item> &fields, bool ignore_errors)
+{
+  List_iterator_fast<Item> f(fields);
+  Item *fld;
+  Item_field *field;
+
+  while ((fld= f++))
+  {
+    field= fld->field_for_view_update();
+    if (field &&
+        field->field->check_constraints(ER_BAD_NULL_ERROR) != TYPE_OK &&
+        !ignore_errors)
+    {
+      my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
+      return true;
+    }
+  }
+  return thd->is_error();
+}
+
+
+/**
+  Check the NOT NULL constraint on all the fields of the current record.
+
+  @param thd  Thread context.
+  @param ptr  Fields.
+
+  @return Error status.
+*/
+static bool check_record(THD *thd, Field **ptr)
+{
+  Field *field;
+  while ((field = *ptr++) && !thd->is_error())
+  {
+    if (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 there is a trigger ON INSERT
+
+  @param event         event type for triggers to be invoked
+
+  @return Test result
+    @retval true    SQL-statement is
+                    INSERT/INSERT SELECT/REPLACE/REPLACE SELECT
+                    and there is a trigger ON INSERT
+    @retval false   Either SQL-statement is not
+                    INSERT/INSERT SELECT/REPLACE/REPLACE SELECT
+                    or there isn't a trigger ON INSERT
+*/
+inline bool command_invokes_insert_triggers(enum trg_event_type event,
+                                            enum_sql_command sql_command)
+{
+  /*
+    If it's 'INSERT INTO ... ON DUPLICATE KEY UPDATE ...' statement
+    the event is TRG_EVENT_UPDATE and the SQL-command is SQLCOM_INSERT.
+  */
+  return event == TRG_EVENT_INSERT &&
+        (sql_command == SQLCOM_INSERT ||
+         sql_command == SQLCOM_INSERT_SELECT ||
+         sql_command == SQLCOM_REPLACE ||
+         sql_command == SQLCOM_REPLACE_SELECT);
+}
+
+
+/**
+  Execute BEFORE INSERT trigger.
+
+  @param thd                        thread context
+  @param triggers                   object holding list of triggers
+                                    to be invoked
+  @param event                      event type for triggers to be invoked
+  @param insert_into_fields_bitmap  Bitmap for fields that is set
+                                    in fill_record
+
+  @return Operation status
+    @retval false   OK
+    @retval true    Error occurred
+*/
+inline bool call_before_insert_triggers(THD *thd,
+                                        Table_triggers_list *triggers,
+                                        enum trg_event_type event,
+                                        MY_BITMAP *insert_into_fields_bitmap)
+{
+  TABLE *tbl= triggers->trigger_table;
+
+  for (Field** f= tbl->field; *f; ++f)
+  {
+    if (((*f)->flags & NO_DEFAULT_VALUE_FLAG) &&
+        !bitmap_is_set(insert_into_fields_bitmap, (*f)->field_index))
+    {
+      (*f)->set_tmp_null();
+    }
+  }
+
+  return triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, true);
+}
+
+
 /*
   Fill fields in list with values from the list of items and invoke
   before triggers.
 
-  SYNOPSIS
-    fill_record_n_invoke_before_triggers()
-      thd           thread context
-      fields        Item_fields list to be filled
-      values        values to fill with
-      ignore_errors TRUE if we should ignore errors
-      triggers      object holding list of triggers to be invoked
-      event         event type for triggers to be invoked
+  @param thd           thread context
+  @param fields        Item_fields list to be filled
+  @param values        values to fill with
+  @param ignore_errors TRUE if we should ignore errors
+  @param triggers      object holding list of triggers to be invoked
+  @param event         event type for triggers to be invoked
 
   NOTE
     This function assumes that fields which values will be set and triggers
     to be invoked belong to the same table, and that TABLE::record[0] and
     record[1] buffers correspond to new and old versions of row respectively.
 
-  RETURN
-    FALSE   OK
-    TRUE    error occured
+  @return Operation status
+    @retval false   OK
+    @retval true    Error occurred
 */
 
 bool
 fill_record_n_invoke_before_triggers(THD *thd, List<Item> &fields,
                                      List<Item> &values, bool ignore_errors,
                                      Table_triggers_list *triggers,
-                                     enum trg_event_type event)
+                                     enum trg_event_type event,
+                                     int num_fields)
 {
-  return (fill_record(thd, fields, values, ignore_errors, NULL) ||
-          (triggers && triggers->process_triggers(thd, event,
-                                                 TRG_ACTION_BEFORE, TRUE)));
+  /*
+    If it's 'INSERT INTO ... ON DUPLICATE KEY UPDATE ...' statement
+    the event is TRG_EVENT_UPDATE and the SQL-command is SQLCOM_INSERT.
+  */
+
+  if (triggers)
+  {
+    bool rc;
+
+    triggers->enable_fields_temporary_nullability(thd);
+
+    if (command_invokes_insert_triggers(event, thd->lex->sql_command))
+    {
+      DBUG_ASSERT(num_fields);
+
+      MY_BITMAP insert_into_fields_bitmap;
+      bitmap_init(&insert_into_fields_bitmap, NULL, num_fields, false);
+
+      rc= fill_record(thd, fields, values, ignore_errors, NULL,
+                      &insert_into_fields_bitmap);
+
+      if (!rc)
+        rc= call_before_insert_triggers(thd, triggers, event,
+                                        &insert_into_fields_bitmap);
+
+      bitmap_free(&insert_into_fields_bitmap);
+    }
+    else
+    {
+      rc= fill_record(thd, fields, values, ignore_errors, NULL, NULL) ||
+          triggers->process_triggers(thd, event, TRG_ACTION_BEFORE, true);
+    }
+
+    triggers->disable_fields_temporary_nullability();
+
+    return rc ||
+           check_record(thd, triggers->trigger_table->field);
+  }
+  else
+  {
+    return
+        fill_record(thd, fields, values, ignore_errors, NULL, NULL) ||
+        check_record(thd, fields, ignore_errors);
+  }
 }
 
 
 /**
   Fill field buffer with values from Field list.
 
-  @param thd           thread handler
-  @param ptr           pointer on pointer to record
-  @param values        list of fields
-  @param ignore_errors True if we should ignore errors
-  @param bitmap        Bitmap over fields to fill
+  @param thd                        thread handler
+  @param ptr                        pointer on pointer to record
+  @param values                     list of fields
+  @param ignore_errors              True if we should ignore errors
+  @param bitmap                     Bitmap over fields to fill
+  @param insert_into_fields_bitmap  Bitmap for fields that is set
+                                    in fill_record
 
   @note fill_record() may set table->auto_increment_field_not_null and a
   caller should make sure that it is reset after their last call to this
@@ -8909,7 +9069,7 @@ fill_record_n_invoke_before_triggers(THD
 
 bool
 fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors,
-            MY_BITMAP *bitmap)
+            MY_BITMAP *bitmap, MY_BITMAP *insert_into_fields_bitmap)
 {
   List_iterator_fast<Item> v(values);
   Item *value;
@@ -8939,8 +9099,16 @@ fill_record(THD *thd, Field **ptr, List<
       continue;
     if (field == table->next_number_field)
       table->auto_increment_field_not_null= TRUE;
-    if (value->save_in_field(field, 0) == TYPE_ERR_NULL_CONSTRAINT_VIOLATION)
+    if (value->save_in_field(field, false) == TYPE_ERR_NULL_CONSTRAINT_VIOLATION)
       goto err;
+    /*
+      fill_record could be called as part of multi update and therefore
+      table->fields_set_during_insert could be NULL.
+    */
+    if (table->fields_set_during_insert)
+      bitmap_set_bit(table->fields_set_during_insert, field->field_index);
+    if (insert_into_fields_bitmap)
+      bitmap_set_bit(insert_into_fields_bitmap, field->field_index);
   }
   DBUG_ASSERT(thd->is_error() || !v++);      // No extra value!
   DBUG_RETURN(thd->is_error());
@@ -8969,6 +9137,11 @@ err:
     This function assumes that fields which values will be set and triggers
     to be invoked belong to the same table, and that TABLE::record[0] and
     record[1] buffers correspond to new and old versions of row respectively.
+    This function is called during handling of statements
+    INSERT/INSERT SELECT/CREATE SELECT. It means that the only trigger's type
+    that can be invoked when this function is called is a BEFORE INSERT
+    trigger so we don't need to make branching based on the result of execution
+    function command_invokes_insert_triggers().
 
   RETURN
     FALSE   OK
@@ -8979,11 +9152,38 @@ bool
 fill_record_n_invoke_before_triggers(THD *thd, Field **ptr,
                                      List<Item> &values, bool ignore_errors,
                                      Table_triggers_list *triggers,
-                                     enum trg_event_type event)
+                                     enum trg_event_type event,
+                                     int num_fields)
 {
-  return (fill_record(thd, ptr, values, ignore_errors, NULL) ||
-          (triggers && triggers->process_triggers(thd, event,
-                                                 TRG_ACTION_BEFORE, TRUE)));
+  bool rc;
+
+  if (triggers)
+  {
+    DBUG_ASSERT(command_invokes_insert_triggers(event, thd->lex->sql_command));
+    DBUG_ASSERT(num_fields);
+
+    triggers->enable_fields_temporary_nullability(thd);
+
+    MY_BITMAP insert_into_fields_bitmap;
+    bitmap_init(&insert_into_fields_bitmap, NULL, num_fields, false);
+
+    rc= fill_record(thd, ptr, values, ignore_errors, NULL,
+                    &insert_into_fields_bitmap);
+
+    if (!rc)
+      rc= call_before_insert_triggers(thd, triggers, event,
+                                      &insert_into_fields_bitmap);
+
+    bitmap_free(&insert_into_fields_bitmap);
+    triggers->disable_fields_temporary_nullability();
+  }
+  else
+    rc= fill_record(thd, ptr, values, ignore_errors, NULL, NULL);
+
+  if (rc)
+    return true;
+
+  return check_record(thd, ptr);
 }
 
 

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	2012-11-30 14:44:53 +0000
+++ b/sql/sql_base.h	2012-12-11 11:58:31 +0000
@@ -176,12 +176,14 @@ bool fill_record_n_invoke_before_trigger
                                           List<Item> &values,
                                           bool ignore_errors,
                                           Table_triggers_list *triggers,
-                                          enum trg_event_type event);
+                                          enum trg_event_type event,
+                                          int num_fields);
 bool fill_record_n_invoke_before_triggers(THD *thd, Field **field,
                                           List<Item> &values,
                                           bool ignore_errors,
                                           Table_triggers_list *triggers,
-                                          enum trg_event_type event);
+                                          enum trg_event_type event,
+                                          int num_fields);
 bool insert_fields(THD *thd, Name_resolution_context *context,
 		   const char *db_name, const char *table_name,
                    List_iterator<Item> *it, bool any_privileges);
@@ -191,9 +193,11 @@ bool setup_fields(THD *thd, Ref_ptr_arra
                   List<Item> &item, enum_mark_columns mark_used_columns,
                   List<Item> *sum_func_list, bool allow_sum_func);
 bool fill_record(THD * thd, List<Item> &fields, List<Item> &values,
-                 bool ignore_errors, MY_BITMAP *bitmap);
+                 bool ignore_errors, MY_BITMAP *bitmap,
+                 MY_BITMAP *insert_into_fields_bitmap);
 bool fill_record(THD *thd, Field **field, List<Item> &values,
-                 bool ignore_errors, MY_BITMAP *bitmap);
+                 bool ignore_errors, MY_BITMAP *bitmap,
+                 MY_BITMAP *insert_into_fields_bitmap);
 
 Field *
 find_field_in_tables(THD *thd, Item_ident *item,

=== modified file 'sql/sql_executor.cc'
--- a/sql/sql_executor.cc	2012-11-29 14:55:55 +0000
+++ b/sql/sql_executor.cc	2012-12-11 11:58:31 +0000
@@ -621,7 +621,7 @@ end_sj_materialize(JOIN *join, JOIN_TAB 
         DBUG_RETURN(NESTED_LOOP_OK);
     }
     fill_record(thd, table->field, sjm->sj_nest->nested_join->sj_inner_exprs,
-                1, NULL);
+                1, NULL, NULL);
     if (thd->is_error())
       DBUG_RETURN(NESTED_LOOP_ERROR); /* purecov: inspected */
     if ((error= table->file->ha_write_row(table->record[0])))

=== modified file 'sql/sql_handler.cc'
--- a/sql/sql_handler.cc	2012-11-21 12:44:48 +0000
+++ b/sql/sql_handler.cc	2012-12-11 11:55:33 +0000
@@ -761,7 +761,7 @@ retry:
 	  goto err;
         }
         old_map= dbug_tmp_use_all_columns(table, table->write_set);
-	(void) item->save_in_field(key_part->field, 1);
+	item->save_in_field(key_part->field, true);
         dbug_tmp_restore_column_map(table->write_set, old_map);
 	key_len+=key_part->store_length;
         keypart_map= (keypart_map << 1) | 1;

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	2012-12-05 17:29:07 +0000
+++ b/sql/sql_insert.cc	2012-12-11 11:58:31 +0000
@@ -319,6 +319,35 @@ void prepare_triggers_for_insert_stmt(TA
 
 
 /**
+   Wrapper for invocation of function check_that_all_fields_are_given_value.
+
+   @param[in] thd               Thread handler
+   @param[in] table             Table to insert into
+   @param[in] table_list        Table list
+   @param[in] abort_on_warning  Whether to report an error or a warning
+                                if some INSERT field is not assigned.
+
+  @return Operation status.
+    @retval false   Success
+    @retval true    Failure
+ */
+static bool safely_check_that_all_fields_are_given_values(
+  THD* thd, TABLE* table,
+  TABLE_LIST* table_list,
+  bool abort_on_warning)
+{
+  bool saved_abort_on_warning= thd->abort_on_warning;
+  thd->abort_on_warning= abort_on_warning;
+
+  bool res= check_that_all_fields_are_given_values(thd, table, table_list);
+
+  thd->abort_on_warning= saved_abort_on_warning;
+
+  return res;
+}
+
+
+/**
   INSERT statement implementation
 
   @note Like implementations of other DDL/DML in MySQL, this function
@@ -369,6 +398,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   MY_BITMAP used_partitions;
   bool prune_needs_default_values;
 #endif /* WITH_PARITITION_STORAGE_ENGINE */
+
   DBUG_ENTER("mysql_insert");
 
   if (open_normal_and_derived_tables(thd, table_list, 0))
@@ -391,7 +421,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 
   /* mysql_prepare_insert set table_list->table if it was not set */
   table= table_list->table;
-
   /* Must be done before can_prune_insert, due to internal initialization. */
   if (info.add_function_default_columns(table, table->write_set))
     goto exit_without_my_ok;
@@ -601,25 +630,27 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 
   prepare_triggers_for_insert_stmt(table);
 
-
   if (table_list->prepare_where(thd, 0, TRUE) ||
       table_list->prepare_check_option(thd))
     error= 1;
 
+  for (Field** next_field= table->field; *next_field; ++next_field)
+  {
+    (*next_field)->reset_warnings();
+  }
+
   while ((values= its++))
   {
     if (fields.elements || !value_count)
     {
       restore_record(table,s->default_values);	// Get empty record
+
       if (fill_record_n_invoke_before_triggers(thd, fields, *values, 0,
                                                table->triggers,
-                                               TRG_EVENT_INSERT))
+                                               TRG_EVENT_INSERT,
+                                               table->s->fields))
       {
-	if (values_list.elements != 1 && ! thd->is_error())
-	{
-	  info.stats.records++;
-	  continue;
-	}
+        DBUG_ASSERT(thd->is_error());
 	/*
 	  TODO: set thd->abort_on_warning if values_list.elements == 1
 	  and check that all items return warning in case of problem with
@@ -628,6 +659,19 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 	error=1;
 	break;
       }
+
+      res= safely_check_that_all_fields_are_given_values(
+        thd,
+        table ? table : context->table_list->table,
+        context->table_list,
+        !ignore && thd->is_strict_mode());
+
+      if (res)
+      {
+        DBUG_ASSERT(thd->is_error());
+        error= 1;
+        break;
+      }
     }
     else
     {
@@ -653,13 +697,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       }
       if (fill_record_n_invoke_before_triggers(thd, table->field, *values, 0,
                                                table->triggers,
-                                               TRG_EVENT_INSERT))
+                                               TRG_EVENT_INSERT,
+                                               table->s->fields))
       {
-	if (values_list.elements != 1 && ! thd->is_error())
-	{
-	  info.stats.records++;
-	  continue;
-	}
+        DBUG_ASSERT(thd->is_error());
 	error=1;
 	break;
       }
@@ -682,6 +723,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
     thd->get_stmt_da()->inc_current_row_for_condition();
   }
 
+  error= thd->get_stmt_da()->is_error();
   free_underlaid_joins(thd, &thd->lex->select_lex);
   joins_freed= TRUE;
 
@@ -783,6 +825,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 
   if (error)
     goto exit_without_my_ok;
+
   if (values_list.elements == 1 && (!(thd->variables.option_bits & OPTION_WARNINGS) ||
 				    !thd->cuted_fields))
   {
@@ -1094,21 +1137,9 @@ bool mysql_prepare_insert(THD *thd, TABL
                        *values, MARK_COLUMNS_READ, 0, 0) ||
           check_insert_fields(thd, context->table_list, fields, *values,
                               !insert_into_view, 0, &map));
-
-    if (!res && check_fields)
-    {
-      bool saved_abort_on_warning= thd->abort_on_warning;
-      thd->abort_on_warning= abort_on_warning;
-      res= check_that_all_fields_are_given_values(thd, 
-                                                  table ? table : 
-                                                  context->table_list->table,
-                                                  context->table_list);
-      thd->abort_on_warning= saved_abort_on_warning;
-    }
-
-   if (!res)
-     res= setup_fields(thd, Ref_ptr_array(),
-                       update_values, MARK_COLUMNS_READ, 0, 0);
+    if (!res)
+      res= setup_fields(thd, Ref_ptr_array(),
+                        update_values, MARK_COLUMNS_READ, 0, 0);
 
     if (!res && duplic == DUP_UPDATE)
     {
@@ -1318,7 +1349,7 @@ int write_record(THD *thd, TABLE *table,
                                                  *update->update_values,
                                                  ignore_errors,
                                                  table->triggers,
-                                                 TRG_EVENT_UPDATE))
+                                                 TRG_EVENT_UPDATE, 0))
           goto before_trg_err;
 
         /* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
@@ -1501,7 +1532,7 @@ int check_that_all_fields_are_given_valu
                                            TABLE_LIST *table_list)
 {
   int err= 0;
-  MY_BITMAP *write_set= entry->write_set;
+  MY_BITMAP *write_set= entry->fields_set_during_insert;
 
   for (Field **field=entry->field ; *field ; field++)
   {
@@ -1516,20 +1547,13 @@ int check_that_all_fields_are_given_valu
         view= test(table_list->view);
       }
       if (view)
-      {
-        push_warning_printf(thd, Sql_condition::SL_WARNING,
-                            ER_NO_DEFAULT_FOR_VIEW_FIELD,
-                            ER(ER_NO_DEFAULT_FOR_VIEW_FIELD),
-                            table_list->view_db.str,
-                            table_list->view_name.str);
-      }
+        (*field)->set_warning(Sql_condition::SL_WARNING,
+                              ER_NO_DEFAULT_FOR_VIEW_FIELD, 1,
+                              table_list->view_db.str,
+                              table_list->view_name.str);
       else
-      {
-        push_warning_printf(thd, Sql_condition::SL_WARNING,
-                            ER_NO_DEFAULT_FOR_FIELD,
-                            ER(ER_NO_DEFAULT_FOR_FIELD),
-                            (*field)->field_name);
-      }
+        (*field)->set_warning(Sql_condition::SL_WARNING,
+                              ER_NO_DEFAULT_FOR_FIELD, 1);
       err= 1;
     }
   }
@@ -1619,17 +1643,6 @@ select_insert::prepare(List<Item> &value
         check_insert_fields(thd, table_list, *fields, values,
                             !insert_into_view, 1, &map));
 
-  if (!res && fields->elements)
-  {
-    bool saved_abort_on_warning= thd->abort_on_warning;
-
-    thd->abort_on_warning= !ignore_errors && thd->is_strict_mode();
-
-    res= check_that_all_fields_are_given_values(thd, table_list->table, 
-                                                table_list);
-    thd->abort_on_warning= saved_abort_on_warning;
-  }
-
   if (duplicate_handling == DUP_UPDATE && !res)
   {
     Name_resolution_context *context= &lex->select_lex.context;
@@ -1744,7 +1757,15 @@ select_insert::prepare(List<Item> &value
         table_list->prepare_check_option(thd));
 
   if (!res)
+  {
      prepare_triggers_for_insert_stmt(table);
+  }
+
+  for (Field** next_field= table->field; *next_field; ++next_field)
+  {
+    (*next_field)->reset_warnings();
+    (*next_field)->reset_tmp_null();
+  }
 
   DBUG_RETURN(res);
 }
@@ -1868,16 +1889,19 @@ bool select_insert::send_data(List<Item>
   DBUG_RETURN(error);
 }
 
-
 void select_insert::store_values(List<Item> &values)
 {
   const bool ignore_err= true;
   if (fields->elements)
     fill_record_n_invoke_before_triggers(thd, *fields, values, ignore_err,
-                                         table->triggers, TRG_EVENT_INSERT);
+                                         table->triggers, TRG_EVENT_INSERT,
+                                         table->s->fields);
   else
     fill_record_n_invoke_before_triggers(thd, table->field, values, ignore_err,
-                                         table->triggers, TRG_EVENT_INSERT);
+                                         table->triggers, TRG_EVENT_INSERT,
+                                         table->s->fields);
+
+  check_that_all_fields_are_given_values(thd, table_list->table, table_list);
 }
 
 void select_insert::send_error(uint errcode,const char *err)
@@ -1951,6 +1975,16 @@ bool select_insert::send_eof()
     table->file->print_error(error,MYF(0));
     DBUG_RETURN(1);
   }
+
+  /*
+    For the strict_mode call of push_warning above results to set
+    error in Diagnostic_area. Therefore it is necessary to check whether
+    the error was set and leave method if it is true. If we didn't do
+    so we would failed later when my_ok is called.
+  */
+  if (thd->get_stmt_da()->is_error())
+    DBUG_RETURN(true);
+
   char buff[160];
   if (info.get_ignore_errors())
     my_snprintf(buff, sizeof(buff),
@@ -2385,12 +2419,19 @@ select_create::prepare2()
   }
   /* Mark all fields that are given values */
   for (Field **f= field ; *f ; f++)
+  {
     bitmap_set_bit(table->write_set, (*f)->field_index);
+    bitmap_set_bit(table->fields_set_during_insert, (*f)->field_index);
+  }
 
   // Set up an empty bitmap of function defaults
   if (info.add_function_default_columns(table, table->write_set))
     DBUG_RETURN(1);
 
+  if (info.add_function_default_columns(table,
+                                        table->fields_set_during_insert))
+    DBUG_RETURN(1);
+
   table->next_number_field=table->found_next_number_field;
 
   restore_record(table,s->default_values);      // Get empty record
@@ -2409,8 +2450,15 @@ select_create::prepare2()
   if (thd->locked_tables_mode <= LTM_LOCK_TABLES)
     table->file->ha_start_bulk_insert((ha_rows) 0);
   thd->abort_on_warning= (!ignore_errors && thd->is_strict_mode());
+
+  enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
+  thd->count_cuted_fields= CHECK_FIELD_WARN;
+
   if (check_that_all_fields_are_given_values(thd, table, table_list))
     DBUG_RETURN(1);
+
+  thd->count_cuted_fields= save_count_cuted_fields;
+
   table->mark_columns_needed_for_insert();
   table->file->extra(HA_EXTRA_WRITE_CACHE);
   DBUG_RETURN(0);
@@ -2469,7 +2517,8 @@ void select_create::store_values(List<It
 {
   const bool ignore_err= true;
   fill_record_n_invoke_before_triggers(thd, field, values, ignore_err,
-                                       table->triggers, TRG_EVENT_INSERT);
+                                       table->triggers, TRG_EVENT_INSERT,
+                                       table->s->fields);
 }
 
 

=== modified file 'sql/sql_insert.h'
--- a/sql/sql_insert.h	2012-10-12 13:09:07 +0000
+++ b/sql/sql_insert.h	2012-12-11 11:58:31 +0000
@@ -35,6 +35,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 void upgrade_lock_type_for_insert(THD *thd, thr_lock_type *lock_type,
                                   enum_duplicates duplic,
                                   bool is_multi_insert);
+
 int check_that_all_fields_are_given_values(THD *thd, TABLE *entry,
                                            TABLE_LIST *table_list);
 void prepare_triggers_for_insert_stmt(TABLE *table);

=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc	2012-11-21 12:44:48 +0000
+++ b/sql/sql_load.cc	2012-12-11 11:58:31 +0000
@@ -264,6 +264,10 @@ int mysql_load(THD *thd,sql_exchange *ex
   }
 
   table= table_list->table;
+
+  for (Field **cur_field= table->field; *cur_field; ++cur_field)
+    (*cur_field)->reset_warnings();
+
   transactional_table= table->file->has_transactions();
 #ifndef EMBEDDED_LIBRARY
   is_concurrent= (table_list->lock_type == TL_WRITE_CONCURRENT_INSERT);
@@ -874,7 +878,8 @@ read_fixed_length(THD *thd, COPY_INFO &i
         fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
                                              ignore_check_option_errors,
                                              table->triggers,
-                                             TRG_EVENT_INSERT))
+                                             TRG_EVENT_INSERT,
+                                             table->s->fields))
       DBUG_RETURN(1);
 
     switch (table_list->view_check_option(thd,
@@ -957,6 +962,13 @@ read_sep_field(THD *thd, COPY_INFO &info
 
       real_item= item->real_item();
 
+      /*
+        Enable temporary nullability for items that corresponds
+        to table fields.
+      */
+      if (real_item->type() == Item::FIELD_ITEM)
+        ((Item_field *)real_item)->field->set_tmp_nullable();
+
       if ((!read_info.enclosed &&
 	  (enclosed_length && length == 4 &&
            !memcmp(pos, STRING_WITH_LEN("NULL")))) ||
@@ -972,18 +984,19 @@ read_sep_field(THD *thd, COPY_INFO &info
                      thd->get_stmt_da()->current_row_for_condition());
             DBUG_RETURN(1);
           }
-          // Try to set to NULL; if it fails, field remains at 0.
-          field->set_null();
-          if (!field->maybe_null())
+          if (!field->real_maybe_null() &&
+              field->type() == FIELD_TYPE_TIMESTAMP)
           {
-            if (field->type() == FIELD_TYPE_TIMESTAMP)
-            {
-              // Specific of TIMESTAMP NOT NULL: set to CURRENT_TIMESTAMP.
-              Item_func_now_local::store_in(field);
-            }
-            else if (field != table->next_number_field)
-              field->set_warning(Sql_condition::SL_WARNING,
-                                 ER_WARN_NULL_TO_NOTNULL, 1);
+            // Specific of TIMESTAMP NOT NULL: set to CURRENT_TIMESTAMP.
+            Item_func_now_local::store_in(field);
+          }
+          else
+          {
+            /*
+              Set field to NULL. Later we will clear temporary nullability flag
+              and check NOT NULL constraint.
+            */
+            field->set_null();
           }
 	}
         else if (item->type() == Item::STRING_ITEM)
@@ -1080,11 +1093,46 @@ read_sep_field(THD *thd, COPY_INFO &info
       }
     }
 
+    // Clear temporary nullability flags for every field in the table.
+
+    it.rewind();
+    while ((item= it++))
+    {
+      Item *real_item= item->real_item();
+      if (real_item->type() == Item::FIELD_ITEM)
+        ((Item_field *)real_item)->field->reset_tmp_nullable();
+    }
+
     if (thd->killed ||
         fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
                                              ignore_check_option_errors,
                                              table->triggers,
-                                             TRG_EVENT_INSERT))
+                                             TRG_EVENT_INSERT,
+                                             table->s->fields))
+      DBUG_RETURN(1);
+
+    if (!table->triggers)
+    {
+      /*
+        If there is no trigger for the table then check the NOT NULL constraint
+        for every table field.
+
+        For the table that has BEFORE-INSERT trigger installed checking for
+        NOT NULL constraint is done inside function
+        fill_record_n_invoke_before_triggers() after all trigger instructions
+        has been executed.
+      */
+      it.rewind();
+
+      while ((item= it++))
+      {
+        Item *real_item= item->real_item();
+        if (real_item->type() == Item::FIELD_ITEM)
+          ((Item_field *) real_item)->field->check_constraints(ER_WARN_NULL_TO_NOTNULL);
+      }
+    }
+
+    if (thd->is_error())
       DBUG_RETURN(1);
 
     switch (table_list->view_check_option(thd,
@@ -1258,7 +1306,8 @@ read_xml_field(THD *thd, COPY_INFO &info
         fill_record_n_invoke_before_triggers(thd, set_fields, set_values,
                                              ignore_check_option_errors,
                                              table->triggers,
-                                             TRG_EVENT_INSERT))
+                                             TRG_EVENT_INSERT,
+                                             table->s->fields))
       DBUG_RETURN(1);
 
     switch (table_list->view_check_option(thd,

=== modified file 'sql/sql_tmp_table.cc'
--- a/sql/sql_tmp_table.cc	2012-12-05 17:29:07 +0000
+++ b/sql/sql_tmp_table.cc	2012-12-11 11:55:33 +0000
@@ -919,11 +919,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARA
          inherit the default value that is defined for the field referred
          by the Item_field object from which 'field' has been created.
       */
-      my_ptrdiff_t diff;
       Field *orig_field= default_field[i];
       /* Get the value from default_values */
-      diff= (my_ptrdiff_t) (orig_field->table->s->default_values-
-                            orig_field->table->record[0]);
+      my_ptrdiff_t diff= orig_field->table->default_values_offset();
       orig_field->move_field_offset(diff);      // Points now at default_values
       if (orig_field->is_real_null())
         field->set_null();

=== modified file 'sql/sql_trigger.cc'
--- a/sql/sql_trigger.cc	2012-12-10 17:22:54 +0000
+++ b/sql/sql_trigger.cc	2012-12-11 11:58:31 +0000
@@ -2252,6 +2252,47 @@ bool Table_triggers_list::is_fields_upda
 
 
 /**
+  Mark all trigger fields as "temporary nullable" and remember the current
+  THD::count_cuted_fields value.
+
+  @param thd Thread context.
+*/
+void Table_triggers_list::enable_fields_temporary_nullability(THD* thd)
+{
+  for (Field** next_field= trigger_table->field; *next_field; ++next_field)
+  {
+    (*next_field)->set_tmp_nullable();
+    (*next_field)->set_count_cuted_fields(thd->count_cuted_fields);
+
+    /*
+      For statement LOAD INFILE we set field values during parsing of data file
+      and later run fill_record_n_invoke_before_triggers() to invoke table's
+      triggers. fill_record_n_invoke_before_triggers() calls this method
+      to enable temporary nullability before running trigger's instructions
+      Since for the case of handling statement LOAD INFILE the null value of
+      fields have been already set we don't have to reset these ones here.
+      In case of handling statements INSERT/REPLACE/INSERT SELECT/
+      REPLACE SELECT we set field's values inside method fill_record
+      that is called from fill_record_n_invoke_before_triggers()
+      after the method enable_fields_temporary_nullability has been executed.
+    */
+    if (thd->lex->sql_command != SQLCOM_LOAD)
+      (*next_field)->reset_tmp_null();
+  }
+}
+
+
+/**
+  Reset "temporary nullable" flag from trigger fields.
+*/
+void Table_triggers_list::disable_fields_temporary_nullability()
+{
+  for (Field** next_field= trigger_table->field; *next_field; ++next_field)
+    (*next_field)->reset_tmp_nullable();
+}
+
+
+/**
   Mark fields of subject table which we read/set in its triggers
   as such.
 

=== modified file 'sql/sql_trigger.h'
--- a/sql/sql_trigger.h	2012-10-04 12:44:07 +0000
+++ b/sql/sql_trigger.h	2012-12-11 11:56:43 +0000
@@ -213,6 +213,10 @@ public:
   bool is_fields_updated_in_trigger(MY_BITMAP *used_fields,
                                     trg_event_type event_type,
                                     trg_action_time_type action_time);
+
+  void enable_fields_temporary_nullability(THD* thd);
+  void disable_fields_temporary_nullability();
+
 private:
   bool prepare_record1_accessors();
   LEX_STRING* change_table_name_in_trignames(const char *old_db_name,

=== modified file 'sql/sql_union.cc'
--- a/sql/sql_union.cc	2012-11-12 12:55:17 +0000
+++ b/sql/sql_union.cc	2012-12-11 11:58:31 +0000
@@ -90,7 +90,7 @@ bool select_union::send_data(List<Item> 
     unit->offset_limit_cnt--;
     return 0;
   }
-  fill_record(thd, table->field, values, 1, NULL);
+  fill_record(thd, table->field, values, 1, NULL, NULL);
   if (thd->is_error())
     return 1;
 

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	2012-11-21 12:44:48 +0000
+++ b/sql/sql_update.cc	2012-12-11 11:58:31 +0000
@@ -736,7 +736,7 @@ int mysql_update(THD *thd,
       store_record(table,record[1]);
       if (fill_record_n_invoke_before_triggers(thd, fields, values, 0,
                                                table->triggers,
-                                               TRG_EVENT_UPDATE))
+                                               TRG_EVENT_UPDATE, 0))
         break; /* purecov: inspected */
 
       found++;
@@ -2011,7 +2011,7 @@ bool multi_update::send_data(List<Item> 
                                                *values_for_table[offset],
                                                false, // ignore_errors
                                                table->triggers,
-                                               TRG_EVENT_UPDATE))
+                                               TRG_EVENT_UPDATE, 0))
 	DBUG_RETURN(1);
 
       /*
@@ -2112,10 +2112,20 @@ bool multi_update::send_data(List<Item> 
         field_num++;
       } while ((tbl= tbl_it++));
 
+      /*
+        Enable temporary nullability for temporary table fields.
+      */
+      for (Field** modified_fields= tmp_table->field + 1 +
+                                    unupdated_check_opt_tables.elements;
+           *modified_fields; ++modified_fields)
+      {
+        (*modified_fields)->set_tmp_nullable();
+      }
+
       /* Store regular updated fields in the row. */
       fill_record(thd,
                   tmp_table->field + 1 + unupdated_check_opt_tables.elements,
-                  *values_for_table[offset], 1, NULL);
+                  *values_for_table[offset], 1, NULL, NULL);
 
       /* Write row, ignoring duplicated updates to a row */
       error= tmp_table->file->ha_write_row(tmp_table->record[0]);

=== modified file 'sql/table.cc'
--- a/sql/table.cc	2012-12-07 13:50:25 +0000
+++ b/sql/table.cc	2012-12-11 11:58:31 +0000
@@ -2306,7 +2306,7 @@ partititon_err:
   /* Allocate bitmaps */
 
   bitmap_size= share->column_bitmap_size;
-  if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*3)))
+  if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size * 4)))
     goto err;
   bitmap_init(&outparam->def_read_set,
               (my_bitmap_map*) bitmaps, share->fields, FALSE);
@@ -2314,6 +2314,9 @@ partititon_err:
               (my_bitmap_map*) (bitmaps+bitmap_size), share->fields, FALSE);
   bitmap_init(&outparam->tmp_set,
               (my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, FALSE);
+  bitmap_init(&outparam->def_fields_set_during_insert,
+              (my_bitmap_map*) (bitmaps + bitmap_size * 3), share->fields,
+              FALSE);
   outparam->default_column_bitmaps();
 
   /* The table struct is now initialized;  Open the table */
@@ -5117,6 +5120,9 @@ void TABLE::clear_column_bitmaps()
   */
   memset(def_read_set.bitmap, 0, s->column_bitmap_size*2);
   column_bitmaps_set(&def_read_set, &def_write_set);
+
+  bitmap_clear_all(&def_fields_set_during_insert);
+  fields_set_during_insert= &def_fields_set_during_insert;
 }
 
 

=== modified file 'sql/table.h'
--- a/sql/table.h	2012-11-29 14:55:55 +0000
+++ b/sql/table.h	2012-12-11 11:58:31 +0000
@@ -1047,7 +1047,31 @@ public:
   uchar		*null_flags;
   my_bitmap_map	*bitmap_init_value;
   MY_BITMAP     def_read_set, def_write_set, tmp_set; /* containers */
+
+  /**
+    Bitmap of table fields (columns), which are explicitly set in the
+    INSERT INTO statement. It is declared here to avoid memory allocation
+    on MEM_ROOT).
+
+    @sa fields_set_during_insert.
+  */
+  MY_BITMAP     def_fields_set_during_insert;
+
   MY_BITMAP     *read_set, *write_set;          /* Active column sets */
+
+  /**
+    A pointer to the bitmap of table fields (columns), which are explicitly set
+    in the INSERT INTO statement.
+
+    fields_set_during_insert points to def_fields_set_during_insert
+    for base (non-temporary) tables. In other cases, it is NULL.
+    Triggers can not be defined for temporary tables, so this bitmap does not
+    matter for temporary tables.
+
+    @sa def_fields_set_during_insert.
+  */
+  MY_BITMAP     *fields_set_during_insert;
+
   /*
    The ID of the query that opened and is using this table. Has different
    meanings depending on the table type.
@@ -1250,6 +1274,9 @@ public:
 
   bool check_read_removal(uint index);
 
+  my_ptrdiff_t default_values_offset() const
+  { return (my_ptrdiff_t) (s->default_values - record[0]); }
+
   /// Return true if table is instantiated, and false otherwise.
   bool is_created() const { return created; }
 

=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc	2012-11-21 12:20:11 +0000
+++ b/sql/unireg.cc	2012-12-11 11:55:33 +0000
@@ -1131,7 +1131,7 @@ static bool make_empty_rec(THD *thd, Fil
         be constant.
       */
       DBUG_ASSERT(field->def->type() != Item::FUNC_ITEM);
-      type_conversion_status res= field->def->save_in_field(regfield, 1);
+      type_conversion_status res= field->def->save_in_field(regfield, true);
       if (res != TYPE_OK && res != TYPE_NOTE_TIME_TRUNCATED &&
           res != TYPE_NOTE_TRUNCATED)
       {

=== modified file 'tests/mysql_client_test.c'
--- a/tests/mysql_client_test.c	2012-12-06 11:34:49 +0000
+++ b/tests/mysql_client_test.c	2012-12-11 11:58:31 +0000
@@ -7851,7 +7851,7 @@ static void test_cuted_rows()
   count= mysql_warning_count(mysql);
   if (!opt_silent)
     fprintf(stdout, "\n total warnings: %d", count);
-  DIE_UNLESS(count == 2);
+  DIE_UNLESS(count == 1);
 
   rc= mysql_query(mysql, "SHOW WARNINGS");
   myquery(rc);
@@ -7860,7 +7860,7 @@ static void test_cuted_rows()
   mytest(result);
 
   rc= my_process_result_set(result);
-  DIE_UNLESS(rc == 2);
+  DIE_UNLESS(rc == 1);
   mysql_free_result(result);
 
   rc= mysql_query(mysql, "INSERT INTO t1 VALUES('junk'), (876789)");

=== modified file 'unittest/gunit/field_date-t.cc'
--- a/unittest/gunit/field_date-t.cc	2012-12-04 12:57:18 +0000
+++ b/unittest/gunit/field_date-t.cc	2012-12-11 11:58:31 +0000
@@ -73,9 +73,9 @@ private:
   void initialize()
   {
     ptr= buffer;
-    null_ptr= &null_byte;
     memset(buffer, 0, PACK_LENGTH);
     null_byte= '\0';
+    set_null_ptr(&null_byte, 1);
   }
 public:
 

=== modified file 'unittest/gunit/field_datetime-t.cc'
--- a/unittest/gunit/field_datetime-t.cc	2012-12-04 12:57:18 +0000
+++ b/unittest/gunit/field_datetime-t.cc	2012-12-11 11:58:31 +0000
@@ -51,9 +51,9 @@ private:
   void initialize()
   {
     ptr= buffer;
-    null_ptr= &null_byte;
     memset(buffer, 0, PACK_LENGTH);
     null_byte= '\0';
+    set_null_ptr(&null_byte, 1);
   }
 
 public:

=== modified file 'unittest/gunit/field_long-t.cc'
--- a/unittest/gunit/field_long-t.cc	2012-12-04 12:57:18 +0000
+++ b/unittest/gunit/field_long-t.cc	2012-12-11 11:58:31 +0000
@@ -47,9 +47,9 @@ class Mock_field_long : public Field_lon
   void initialize()
   {
     ptr= buffer;
-    null_ptr= &null_byte;
     memset(buffer, 0, PACK_LENGTH);
     null_byte= '\0';
+    set_null_ptr(&null_byte, 1);
   }
 public:
   Mock_field_long()
@@ -361,11 +361,14 @@ TEST_F(FieldLongTest, StoreNullValue)
   // Save NULL value in a field that can NOT have NULL value
   field_long.set_null_ptr(NULL, 0);
   {
-    Mock_error_handler error_handler(thd(), WARN_DATA_TRUNCATED);
+    Mock_error_handler error_handler(thd(), 0);
+    // Save NULL value in a field that can be set to NULL temporary
+    field_long.set_tmp_nullable();
     err= set_field_to_null(&field_long);
     EXPECT_EQ(0, field_long.val_int());
     EXPECT_EQ(TYPE_OK, err);
-    EXPECT_EQ(1, error_handler.handle_called());
+    EXPECT_EQ(0, error_handler.handle_called());
+    field_long.reset_tmp_nullable();
   }
 
   {

=== modified file 'unittest/gunit/field_newdecimal-t.cc'
--- a/unittest/gunit/field_newdecimal-t.cc	2012-12-04 12:57:18 +0000
+++ b/unittest/gunit/field_newdecimal-t.cc	2012-12-11 11:58:31 +0000
@@ -52,9 +52,9 @@ class Mock_field_new_decimal : public Fi
   void initialize()
   {
     ptr= buffer;
-    null_ptr= &null_byte;
     memset(buffer, 0, MAX_FIELD_WIDTH);
     null_byte= '\0';
+    set_null_ptr(&null_byte, 1);
   }
 
 public:

=== modified file 'unittest/gunit/mock_field_timestamp.h'
--- a/unittest/gunit/mock_field_timestamp.h	2012-11-29 15:23:48 +0000
+++ b/unittest/gunit/mock_field_timestamp.h	2012-12-11 11:58:31 +0000
@@ -34,7 +34,7 @@ class Mock_field_timestamp : public Fiel
     EXPECT_FALSE(table == NULL) << "Out of memory";
     ptr= buffer;
     memset(buffer, 0, PACK_LENGTH);
-    null_ptr= &null_byte;
+    set_null_ptr(&null_byte, 1);
   }
 
 public:

=== modified file 'unittest/gunit/mock_field_timestampf.h'
--- a/unittest/gunit/mock_field_timestampf.h	2012-01-31 15:16:16 +0000
+++ b/unittest/gunit/mock_field_timestampf.h	2012-12-11 11:58:31 +0000
@@ -28,7 +28,7 @@ class Mock_field_timestampf : public Fie
     EXPECT_FALSE(table == NULL) << "Out of memory";
     ptr= buffer;
     memset(buffer, 0, PACK_LENGTH);
-    null_ptr= &null_byte;
+    set_null_ptr(&null_byte, 1);
   }
 
 public:

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (Dmitry.Shulga:5202 to 5205) WL#6030Dmitry Shulga11 Dec