Bug #11491 Misleading error message if not NULL column set to NULL, SQL mode TRADITIONAL
Submitted: 21 Jun 2005 20:42 Modified: 2 Dec 2005 3:39
Reporter: Guillaume Lebur Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S2 (Serious)
Version:5.0.7-beta-nt OS:Windows (WinXP SP2)
Assigned to: Sergei Glukhov CPU Architecture:Any

[21 Jun 2005 20:42] Guillaume Lebur
Description:
Contrary to what had been said after I reported the same bug a few weeks ago, it seems that NULL constraint violations are still not handled properly in triggers.

When in a BEFORE UPDATE (or INSERT) trigger you set the new value of a NOT NULL column to NULL, it takes a fake value ('' or 0 for an integer) instead of generating a constraint violation error.

This can lead to incoherence in the database integrity (for example if the column the trigger tries to set to NULL is a key).

How to repeat:
>CREATE TABLE foo (
id INT PRIMARY KEY,
bar INT)

>INSERT INTO foo (id, bar) VALUES (1, 5)

>CREATE TRIGGER tgr_bu_foo BEFORE UPDATE ON foo FOR EACH ROW
BEGIN
   IF new.bar<0 THEN
      SET new.id=NULL;
   END IF;
END;

>UPDATE foo SET bar=-8 WHERE id=1;
1 records affected

>SELECT * FROM foo;

id     bar
--     ----
0      -8
[22 Jun 2005 5:32] Heikki Tuuri
Guillaume,

please test with an InnoDB type table, and set the SQL mode to 'TRADITIONAL'.

For MyISAM type tables, handling a constraint violation is problematic, since there is no rollback.

Regards,

Heikki
[22 Jun 2005 17:56] Guillaume Lebur
InnoDB is a little more verbose but handles the error in the same way ("Column set to default value, NULL supplied to NOT NULL column 'id' at row 1).

My sql_mode variable contains TRADITIONAL but I couldn't get it to contain only TRADITIONAL :

mysql> SET GLOBAL sql_mode='TRADITIONAL';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @@sql_mode;
+-------------------------------------------------------------------------------
------------------------------------------------+
| @@sql_mode
                                                |
+-------------------------------------------------------------------------------
------------------------------------------------+
| STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_D
IVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER |
+-------------------------------------------------------------------------------
------------------------------------------------+
1 row in set (0.00 sec)

Anyway, I'm reporting this bug because the behaviour INSIDE a trigger is not the same as OUTSIDE. If you try to set a NOT NULL column to NULL (even with a MyISAM table) outside a trigger, an error will be generated, forbidding the operation.
[23 Jun 2005 4:32] Heikki Tuuri
Guillaume,

you are right, it should not set a not-NULL column to NULL.

I am raising the priority of this bug to P1 since it is essential that a database obeys integrity constraints.

Thank you,

Heikki
[23 Jun 2005 4:40] Heikki Tuuri
Oops, I misread the description. The bug sets the column to a fake default value (not to NULL). Anyway, in the TRADITIONAL SQL mode at least, it should not do that but roll back the SQL statement. I am lowering the priority to P2.

Thank you,

Heikki
[23 Jun 2005 5:05] Heikki Tuuri
Guillaume,

both MyISAM and InnoDB do set the column to a fake default value also in a normal update. This behavior is not specific to triggers:

mysql> CREATE TABLE `foo2` (
    ->   `id` int(11) NOT NULL,
    ->   `bar` int(11) default NULL,
    ->   PRIMARY KEY  (`id`)
    -> ) type = myisam;
Query OK, 0 rows affected, 1 warning (0.02 sec)

mysql> insert into foo2 values (1, 5);
Query OK, 1 row affected (0.01 sec)

mysql> update foo2 set id = NULL;
Query OK, 1 row affected, 1 warning (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 1

mysql> select * from foo2;
+----+------+
| id | bar  |
+----+------+
|  0 |    5 |
+----+------+
1 row in set (0.00 sec)

mysql>

I tested InnoDB in the SQL mode 'TRADITIONAL'. The error message is misleading, but MySQL works correctly: it does not change the column value.

Since MyISAM does not have a rollback, it must set the column value to a fake default value. This behavior also applies to transactional table types in the default SQL mode. In the 'TRADITIONAL' mode, transactional tables will roll back the SQL statement.

I recommend using InnoDB in the 'TRADITIONAL' mode because then the behavior is like in most other database brands: no fake default values are used.

Thus, the only bug here is the misleading error message in the 'TRADITIONAL' mode. The error message should be something like: "NOT NULL constraint violation".

I am updating the synopsis, and lowering the priority to P3.

Regards,

Heikki

mysql> CREATE TABLE foo (
    -> id INT PRIMARY KEY,
    -> bar INT)
    -> type = innodb;
Query OK, 0 rows affected, 1 warning (0.11 sec)

mysql> INSERT INTO foo (id, bar) VALUES (1, 5)
    -> ;
Query OK, 1 row affected (0.03 sec)

mysql> delimiter //
mysql> CREATE TRIGGER tgr_bu_foo BEFORE UPDATE ON foo FOR EACH ROW
    -> BEGIN
    ->    IF new.bar<0 THEN
    ->       SET new.id=NULL;
    ->    END IF;
    -> END;
    -> //
Query OK, 0 rows affected (0.00 sec)

mysql> delimiter ;
mysql> set session sql_mode='traditional';
Query OK, 0 rows affected (0.00 sec)

mysql> UPDATE foo SET bar=-8 WHERE id=1;
ERROR 1263 (22004): Column set to default value; NULL supplied to NOT NULL colum
n 'id' at row 1
mysql> select * from foo;
+----+------+
| id | bar  |
+----+------+
|  1 |    5 |
+----+------+
1 row in set (0.00 sec)
[23 Jun 2005 17:11] Guillaume Lebur
You're right. I mixed up the behaviour of UPDATE with INSERT regarding NOT NULL columns (in a BEFORE INSERT trigger, an error is generated and the insertion fails when you try to set a NOT NULL column to NULL).

I'm still wondering how come I couldn't set sql_mode to only TRADITIONAL with the command : SET GLOBAL sql_mode='TRADITIONAL'...

Anyway, thanks for the answers.
[26 Oct 2005 12:53] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/31494
[7 Nov 2005 12:04] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/32038
[1 Dec 2005 11:26] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/internals/32902
[1 Dec 2005 11:29] Sergei Glukhov
Fixed in 5.1.4-alpha
[2 Dec 2005 3:39] Paul DuBois
Noted in 5.1.4 changelog.
[30 May 2007 12:07] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/27675

ChangeSet@1.2505, 2007-05-30 17:04:04+05:00, gluh@mysql.com +19 -0
  backport of Bug#11491 Misleading error message if not NULL column set to NULL, SQL mode TRADITIONAL
[4 Jun 2007 21:20] Bugs System
Pushed into 5.1.20-beta
[4 Jun 2007 21:22] Bugs System
Pushed into 5.0.44