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