SQLite

View Ticket
Login
Ticket Hash: 830277d9db6c3ba10df1c79c6c2be58323553240
Title: Non-deterministic date/time functions allowed in CHECK constraints
Status: Closed Type: Code_Defect
Severity: Critical Priority: Low
Subsystem: Unknown Resolution: Not_A_Bug
Last Modified: 2020-01-18 21:35:33
Version Found In:
User Comments:
drh added on 2019-10-30 02:09:39:

The functions found in CHECK constraints should be deterministic - meaning that they should aways give the same answer for the same inputs.

Date and time functions can sometimes be deterministic and sometimes now. They are deterministic if they avoid arguments like 'now' and 'localtime'. The functions are coded in such a way that if those arguments are used in a context where a deterministic function is required, then the function throws an error at run-time.

But this mechanism sometimes does not work. Example:

CREATE TABLE t1(a REAL CHECK( a<julianday('now') ));
INSERT INTO t1(a) VALUES(julianday('now')-0.01); -- works
INSERT INTO t1(a) VALUES(julianday('now')+0.01); -- error

Because of the use of "julianday('now')" inside of a CHECK constraint, *every* insert into table t1 ought to fail. But sometimes the inserts run to completion without error.


drh added on 2019-10-30 10:33:09:

This same problem can lead to index corruption:

CREATE TABLE t1(a,b);
CREATE INDEX t1x1 ON t1(julianday('now')+b);
INSERT INTO t1(a,b) VALUES(12345, 15);
.shell sleep 1
SELECT a FROM t1 WHERE julianday('now')+b=julianday('now')+15;
-- previous query returns zero row, but should return one row of 12345
PRAGMA integrity_check; -- reports missing index entry


drh added on 2020-01-18 21:35:33:

It turns out that PostgreSQL, MySQL, and SQLServer all allow non-deterministic functions like CURRENT_TIMESTAMP and RANDOM() inside of CHECK constraints. So, SQLite will too.