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