xref: /sqlite-3.40.0/test/check.test (revision e99cb2da)
1# 2005 November 2
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#***********************************************************************
11# This file implements regression tests for SQLite library.  The
12# focus of this file is testing CHECK constraints
13#
14# $Id: check.test,v 1.13 2009/06/05 17:09:12 drh Exp $
15
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
18set ::testprefix check
19
20# Only run these tests if the build includes support for CHECK constraints
21ifcapable !check {
22  finish_test
23  return
24}
25
26do_test check-1.1 {
27  execsql {
28    CREATE TABLE t1(
29      x INTEGER CHECK( x<5 ),
30      y REAL CHECK( y>x )
31    );
32  }
33} {}
34do_test check-1.2 {
35  execsql {
36    INSERT INTO t1 VALUES(3,4);
37    SELECT * FROM t1;
38  }
39} {3 4.0}
40do_test check-1.3 {
41  catchsql {
42    INSERT INTO t1 VALUES(6,7);
43  }
44} {1 {CHECK constraint failed: t1}}
45do_test check-1.4 {
46  execsql {
47    SELECT * FROM t1;
48  }
49} {3 4.0}
50do_test check-1.5 {
51  catchsql {
52    INSERT INTO t1 VALUES(4,3);
53  }
54} {1 {CHECK constraint failed: t1}}
55do_test check-1.6 {
56  execsql {
57    SELECT * FROM t1;
58  }
59} {3 4.0}
60do_test check-1.7 {
61  catchsql {
62    INSERT INTO t1 VALUES(NULL,6);
63  }
64} {0 {}}
65do_test check-1.8 {
66  execsql {
67    SELECT * FROM t1;
68  }
69} {3 4.0 {} 6.0}
70do_test check-1.9 {
71  catchsql {
72    INSERT INTO t1 VALUES(2,NULL);
73  }
74} {0 {}}
75do_test check-1.10 {
76  execsql {
77    SELECT * FROM t1;
78  }
79} {3 4.0 {} 6.0 2 {}}
80do_test check-1.11 {
81  execsql {
82    DELETE FROM t1 WHERE x IS NULL OR x!=3;
83    UPDATE t1 SET x=2 WHERE x==3;
84    SELECT * FROM t1;
85  }
86} {2 4.0}
87do_test check-1.12 {
88  catchsql {
89    UPDATE t1 SET x=7 WHERE x==2
90  }
91} {1 {CHECK constraint failed: t1}}
92do_test check-1.13 {
93  execsql {
94    SELECT * FROM t1;
95  }
96} {2 4.0}
97do_test check-1.14 {
98  catchsql {
99    UPDATE t1 SET x=5 WHERE x==2
100  }
101} {1 {CHECK constraint failed: t1}}
102do_test check-1.15 {
103  execsql {
104    SELECT * FROM t1;
105  }
106} {2 4.0}
107do_test check-1.16 {
108  catchsql {
109    UPDATE t1 SET x=4, y=11 WHERE x==2
110  }
111} {0 {}}
112do_test check-1.17 {
113  execsql {
114    SELECT * FROM t1;
115  }
116} {4 11.0}
117
118do_test check-2.1 {
119  execsql {
120    PRAGMA writable_schema = 1;
121    CREATE TABLE t2(
122      x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ),
123      y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ),
124      z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' )
125    );
126    CREATE TABLE t2n(
127      x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ),
128      y NUMERIC CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ),
129      z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' )
130    );
131    PRAGMA writable_schema = 0;
132  }
133} {}
134do_test check-2.2 {
135  execsql {
136    INSERT INTO t2 VALUES(1,2.2,'three');
137    SELECT * FROM t2;
138  }
139} {1 2.2 three}
140db close
141sqlite3 db test.db
142do_test check-2.3 {
143  execsql {
144    INSERT INTO t2 VALUES(NULL, NULL, NULL);
145    SELECT * FROM t2;
146  }
147} {1 2.2 three {} {} {}}
148do_test check-2.4 {
149  catchsql {
150    INSERT INTO t2 VALUES(1.1, NULL, NULL);
151  }
152} {1 {CHECK constraint failed: one}}
153do_test check-2.5 {
154  # The 5 gets automatically promoted to 5.0 because the column type is REAL
155  catchsql {
156    INSERT INTO t2 VALUES(NULL, 5, NULL);
157  }
158} {0 {}}
159do_test check-2.5b {
160  # This time the column type is NUMERIC, so not automatic promption to REAL
161  # occurs and the constraint fails.
162  catchsql {
163    INSERT INTO t2n VALUES(NULL, 5, NULL);
164  }
165} {1 {CHECK constraint failed: two}}
166do_test check-2.6 {
167  catchsql {
168    INSERT INTO t2 VALUES(NULL, NULL, 3.14159);
169  }
170} {1 {CHECK constraint failed: three}}
171
172# Undocumented behavior:  The CONSTRAINT name clause can follow a constraint.
173# Such a clause is ignored.  But the parser must accept it for backwards
174# compatibility.
175#
176do_test check-2.10 {
177  execsql {
178    CREATE TABLE t2b(
179      x INTEGER CHECK( typeof(coalesce(x,0))=='integer' ) CONSTRAINT one,
180      y TEXT PRIMARY KEY constraint two,
181      z INTEGER,
182      UNIQUE(x,z) constraint three
183    );
184  }
185} {}
186do_test check-2.11 {
187  catchsql {
188    INSERT INTO t2b VALUES('xyzzy','hi',5);
189  }
190} {1 {CHECK constraint failed: t2b}}
191do_test check-2.12 {
192  execsql {
193    CREATE TABLE t2c(
194      x INTEGER CONSTRAINT x_one CONSTRAINT x_two
195          CHECK( typeof(coalesce(x,0))=='integer' )
196          CONSTRAINT x_two CONSTRAINT x_three,
197      y INTEGER, z INTEGER,
198      CONSTRAINT u_one UNIQUE(x,y,z) CONSTRAINT u_two
199    );
200  }
201} {}
202do_test check-2.13 {
203  catchsql {
204    INSERT INTO t2c VALUES('xyzzy',7,8);
205  }
206} {1 {CHECK constraint failed: x_two}}
207do_test check-2.cleanup {
208  execsql {
209    DROP TABLE IF EXISTS t2b;
210    DROP TABLE IF EXISTS t2c;
211    DROP TABLE IF EXISTS t2n;
212  }
213} {}
214
215ifcapable subquery {
216  do_test check-3.1 {
217    catchsql {
218      CREATE TABLE t3(
219        x, y, z,
220        CHECK( x<(SELECT min(x) FROM t1) )
221      );
222    }
223  } {1 {subqueries prohibited in CHECK constraints}}
224}
225
226do_test check-3.2 {
227  execsql {
228    SELECT name FROM sqlite_master ORDER BY name
229  }
230} {t1 t2}
231do_test check-3.3 {
232  catchsql {
233    CREATE TABLE t3(
234      x, y, z,
235      CHECK( q<x )
236    );
237  }
238} {1 {no such column: q}}
239do_test check-3.4 {
240  execsql {
241    SELECT name FROM sqlite_master ORDER BY name
242  }
243} {t1 t2}
244do_test check-3.5 {
245  catchsql {
246    CREATE TABLE t3(
247      x, y, z,
248      CHECK( t2.x<x )
249    );
250  }
251} {1 {no such column: t2.x}}
252do_test check-3.6 {
253  execsql {
254    SELECT name FROM sqlite_master ORDER BY name
255  }
256} {t1 t2}
257do_test check-3.7 {
258  catchsql {
259    CREATE TABLE t3(
260      x, y, z,
261      CHECK( t3.x<25 )
262    );
263  }
264} {0 {}}
265do_test check-3.8 {
266  execsql {
267    INSERT INTO t3 VALUES(1,2,3);
268    SELECT * FROM t3;
269  }
270} {1 2 3}
271do_test check-3.9 {
272  catchsql {
273    INSERT INTO t3 VALUES(111,222,333);
274  }
275} {1 {CHECK constraint failed: t3}}
276
277do_test check-4.1 {
278  execsql {
279    CREATE TABLE t4(x, y,
280      CHECK (
281           x+y==11
282        OR x*y==12
283        OR x/y BETWEEN 5 AND 8
284        OR -x==y+10
285      )
286    );
287  }
288} {}
289do_test check-4.2 {
290  execsql {
291    INSERT INTO t4 VALUES(1,10);
292    SELECT * FROM t4
293  }
294} {1 10}
295do_test check-4.3 {
296  execsql {
297    UPDATE t4 SET x=4, y=3;
298    SELECT * FROM t4
299  }
300} {4 3}
301do_test check-4.4 {
302  execsql {
303    UPDATE t4 SET x=12, y=2;
304    SELECT * FROM t4
305  }
306} {12 2}
307do_test check-4.5 {
308  execsql {
309    UPDATE t4 SET x=12, y=-22;
310    SELECT * FROM t4
311  }
312} {12 -22}
313do_test check-4.6 {
314  catchsql {
315    UPDATE t4 SET x=0, y=1;
316  }
317} {1 {CHECK constraint failed: t4}}
318do_test check-4.7 {
319  execsql {
320    SELECT * FROM t4;
321  }
322} {12 -22}
323do_test check-4.8 {
324  execsql {
325    PRAGMA ignore_check_constraints=ON;
326    UPDATE t4 SET x=0, y=1;
327    SELECT * FROM t4;
328    PRAGMA integrity_check;
329  }
330} {0 1 ok}
331do_execsql_test check-4.8.1 {
332  PRAGMA ignore_check_constraints=OFF;
333  PRAGMA integrity_check;
334} {{CHECK constraint failed in t4}}
335do_test check-4.9 {
336  catchsql {
337    UPDATE t4 SET x=0, y=2;
338  }
339} {1 {CHECK constraint failed: t4}}
340ifcapable vacuum {
341  do_test check_4.10 {
342    catchsql {
343      VACUUM
344    }
345  } {0 {}}
346}
347
348do_test check-5.1 {
349  catchsql {
350    CREATE TABLE t5(x, y,
351      CHECK( x*y<:abc )
352    );
353  }
354} {1 {parameters prohibited in CHECK constraints}}
355do_test check-5.2 {
356  catchsql {
357    CREATE TABLE t5(x, y,
358      CHECK( x*y<? )
359    );
360  }
361} {1 {parameters prohibited in CHECK constraints}}
362
363ifcapable conflict {
364
365do_test check-6.1 {
366  execsql {SELECT * FROM t1}
367} {4 11.0}
368do_test check-6.2 {
369  execsql {
370    UPDATE OR IGNORE t1 SET x=5;
371    SELECT * FROM t1;
372  }
373} {4 11.0}
374do_test check-6.3 {
375  execsql {
376    INSERT OR IGNORE INTO t1 VALUES(5,4.0);
377    SELECT * FROM t1;
378  }
379} {4 11.0}
380do_test check-6.4 {
381  execsql {
382    INSERT OR IGNORE INTO t1 VALUES(2,20.0);
383    SELECT * FROM t1;
384  }
385} {4 11.0 2 20.0}
386do_test check-6.5 {
387  catchsql {
388    UPDATE OR FAIL t1 SET x=7-x, y=y+1;
389  }
390} {1 {CHECK constraint failed: t1}}
391do_test check-6.6 {
392  execsql {
393    SELECT * FROM t1;
394  }
395} {3 12.0 2 20.0}
396do_test check-6.7 {
397  catchsql {
398    BEGIN;
399    INSERT INTO t1 VALUES(1,30.0);
400    INSERT OR ROLLBACK INTO t1 VALUES(8,40.0);
401  }
402} {1 {CHECK constraint failed: t1}}
403do_test check-6.8 {
404  catchsql {
405    COMMIT;
406  }
407} {1 {cannot commit - no transaction is active}}
408do_test check-6.9 {
409  execsql {
410    SELECT * FROM t1
411  }
412} {3 12.0 2 20.0}
413
414do_test check-6.11 {
415  execsql {SELECT * FROM t1}
416} {3 12.0 2 20.0}
417do_test check-6.12 {
418  catchsql {
419    REPLACE INTO t1 VALUES(6,7);
420  }
421} {1 {CHECK constraint failed: t1}}
422do_test check-6.13 {
423  execsql {SELECT * FROM t1}
424} {3 12.0 2 20.0}
425do_test check-6.14 {
426  catchsql {
427    INSERT OR IGNORE INTO t1 VALUES(6,7);
428  }
429} {0 {}}
430do_test check-6.15 {
431  execsql {SELECT * FROM t1}
432} {3 12.0 2 20.0}
433
434
435}
436
437#--------------------------------------------------------------------------
438# If a connection opens a database that contains a CHECK constraint that
439# uses an unknown UDF, the schema should not be considered malformed.
440# Attempting to modify the table should fail (since the CHECK constraint
441# cannot be tested).
442#
443reset_db
444proc myfunc {x} {expr $x < 10}
445db func myfunc -deterministic myfunc
446
447do_execsql_test  7.1 { CREATE TABLE t6(a CHECK (myfunc(a))) }
448do_execsql_test  7.2 { INSERT INTO t6 VALUES(9)  }
449do_catchsql_test 7.3 { INSERT INTO t6 VALUES(11) } \
450          {1 {CHECK constraint failed: t6}}
451
452do_test 7.4 {
453  sqlite3 db2 test.db
454  execsql { SELECT * FROM t6 } db2
455} {9}
456
457do_test 7.5 {
458  catchsql { INSERT INTO t6 VALUES(8) } db2
459} {1 {unknown function: myfunc()}}
460
461do_test 7.6 {
462  catchsql { CREATE TABLE t7(a CHECK (myfunc(a))) } db2
463} {1 {no such function: myfunc}}
464
465do_test 7.7 {
466  db2 func myfunc myfunc
467  execsql { INSERT INTO t6 VALUES(8) } db2
468} {}
469
470do_test 7.8 {
471  db2 func myfunc myfunc
472  catchsql { INSERT INTO t6 VALUES(12) } db2
473} {1 {CHECK constraint failed: t6}}
474
475# 2013-08-02:  Silently ignore database name qualifiers in CHECK constraints.
476#
477do_execsql_test 8.1 {
478  CREATE TABLE t810(a, CHECK( main.t810.a>0 ));
479  CREATE TABLE t811(b, CHECK( xyzzy.t811.b BETWEEN 5 AND 10 ));
480} {}
481
482# Make sure check constraints involving the ROWID are not ignored
483#
484do_execsql_test 9.1 {
485  CREATE TABLE t1(
486    a INTEGER PRIMARY KEY,
487    b INTEGER NOT NULL CONSTRAINT 'b-check' CHECK( b>a ),
488    c INTEGER NOT NULL CONSTRAINT 'c-check' CHECK( c>rowid*2 ),
489    d INTEGER NOT NULL CONSTRAINT 'd-check' CHECK( d BETWEEN b AND c )
490  );
491  INSERT INTO t1(a,b,c,d) VALUES(1,2,4,3),(2,4,6,5),(3,10,30,20);
492} {}
493do_catchsql_test 9.2 {
494  UPDATE t1 SET b=0 WHERE a=1;
495} {1 {CHECK constraint failed: b-check}}
496do_catchsql_test 9.3 {
497  UPDATE t1 SET c=a*2 WHERE a=1;
498} {1 {CHECK constraint failed: c-check}}
499
500# Integrity check on a VIEW with columns.
501#
502db close
503db2 close
504forcedelete test.db
505sqlite3 db test.db
506do_execsql_test 10.1 {
507  CREATE TABLE t1(x);
508  CREATE VIEW v1(y) AS SELECT x FROM t1;
509  PRAGMA integrity_check;
510} {ok}
511
512#-------------------------------------------------------------------------
513reset_db
514do_execsql_test 11.0 {
515  CREATE TABLE t1 (Col0 CHECK(1 COLLATE BINARY BETWEEN 1 AND 1) ) ;
516}
517do_execsql_test 11.1 {
518  INSERT INTO t1 VALUES (NULL);
519}
520do_execsql_test 11.2 {
521  INSERT  INTO t1 VALUES (NULL);
522}
523
524do_execsql_test 11.3 {
525  CREATE TABLE t2(b, a CHECK(
526      CASE 'abc' COLLATE nocase WHEN a THEN 1 ELSE 0 END)
527  );
528}
529do_execsql_test 11.4 {
530  INSERT INTO t2(a) VALUES('abc');
531}
532do_execsql_test 11.5 {
533  INSERT INTO t2(b, a) VALUES(1, 'abc'||'');
534}
535do_execsql_test 11.6 {
536  INSERT INTO t2(b, a) VALUES(2, 'abc');
537}
538
539finish_test
540
541
542finish_test
543