blob: 19f252677c46f2ea2cdd49a7917cf9cfa36c8feb [file] [log] [blame]
drhffe07b22005-11-03 00:41:17 +00001# 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#
drhdda70fe2009-06-05 17:09:11 +000014# $Id: check.test,v 1.13 2009/06/05 17:09:12 drh Exp $
drhffe07b22005-11-03 00:41:17 +000015
16set testdir [file dirname $argv0]
17source $testdir/tester.tcl
drhddd1fc72013-01-08 12:48:10 +000018set ::testprefix check
drhffe07b22005-11-03 00:41:17 +000019
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 }
drh8a512562005-11-14 22:29:05 +000039} {3 4.0}
drhffe07b22005-11-03 00:41:17 +000040do_test check-1.3 {
41 catchsql {
42 INSERT INTO t1 VALUES(6,7);
43 }
drhf9c8ce32013-11-05 13:33:55 +000044} {1 {CHECK constraint failed: t1}}
drhffe07b22005-11-03 00:41:17 +000045do_test check-1.4 {
46 execsql {
47 SELECT * FROM t1;
48 }
drh8a512562005-11-14 22:29:05 +000049} {3 4.0}
drhffe07b22005-11-03 00:41:17 +000050do_test check-1.5 {
51 catchsql {
52 INSERT INTO t1 VALUES(4,3);
53 }
drhf9c8ce32013-11-05 13:33:55 +000054} {1 {CHECK constraint failed: t1}}
drhffe07b22005-11-03 00:41:17 +000055do_test check-1.6 {
56 execsql {
57 SELECT * FROM t1;
58 }
drh8a512562005-11-14 22:29:05 +000059} {3 4.0}
drhffe07b22005-11-03 00:41:17 +000060do_test check-1.7 {
61 catchsql {
62 INSERT INTO t1 VALUES(NULL,6);
63 }
drh6275b882005-11-03 01:22:30 +000064} {0 {}}
drhffe07b22005-11-03 00:41:17 +000065do_test check-1.8 {
66 execsql {
67 SELECT * FROM t1;
68 }
drh8a512562005-11-14 22:29:05 +000069} {3 4.0 {} 6.0}
drhffe07b22005-11-03 00:41:17 +000070do_test check-1.9 {
71 catchsql {
72 INSERT INTO t1 VALUES(2,NULL);
73 }
drh6275b882005-11-03 01:22:30 +000074} {0 {}}
drhffe07b22005-11-03 00:41:17 +000075do_test check-1.10 {
76 execsql {
77 SELECT * FROM t1;
78 }
drh8a512562005-11-14 22:29:05 +000079} {3 4.0 {} 6.0 2 {}}
drhffe07b22005-11-03 00:41:17 +000080do_test check-1.11 {
81 execsql {
drh6275b882005-11-03 01:22:30 +000082 DELETE FROM t1 WHERE x IS NULL OR x!=3;
drhffe07b22005-11-03 00:41:17 +000083 UPDATE t1 SET x=2 WHERE x==3;
84 SELECT * FROM t1;
85 }
drh8a512562005-11-14 22:29:05 +000086} {2 4.0}
drhffe07b22005-11-03 00:41:17 +000087do_test check-1.12 {
88 catchsql {
89 UPDATE t1 SET x=7 WHERE x==2
90 }
drhf9c8ce32013-11-05 13:33:55 +000091} {1 {CHECK constraint failed: t1}}
drhffe07b22005-11-03 00:41:17 +000092do_test check-1.13 {
93 execsql {
94 SELECT * FROM t1;
95 }
drh8a512562005-11-14 22:29:05 +000096} {2 4.0}
drhffe07b22005-11-03 00:41:17 +000097do_test check-1.14 {
98 catchsql {
99 UPDATE t1 SET x=5 WHERE x==2
100 }
drhf9c8ce32013-11-05 13:33:55 +0000101} {1 {CHECK constraint failed: t1}}
drhffe07b22005-11-03 00:41:17 +0000102do_test check-1.15 {
103 execsql {
104 SELECT * FROM t1;
105 }
drh8a512562005-11-14 22:29:05 +0000106} {2 4.0}
drhffe07b22005-11-03 00:41:17 +0000107do_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 }
drh8a512562005-11-14 22:29:05 +0000116} {4 11.0}
drhffe07b22005-11-03 00:41:17 +0000117
118do_test check-2.1 {
119 execsql {
120 CREATE TABLE t2(
drh2938f922012-03-07 19:13:29 +0000121 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' )
drhffe07b22005-11-03 00:41:17 +0000124 );
125 }
126} {}
127do_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}
drhd9da78a2009-03-24 15:08:09 +0000133db close
134sqlite3 db test.db
drhffe07b22005-11-03 00:41:17 +0000135do_test check-2.3 {
136 execsql {
137 INSERT INTO t2 VALUES(NULL, NULL, NULL);
138 SELECT * FROM t2;
139 }
140} {1 2.2 three {} {} {}}
141do_test check-2.4 {
142 catchsql {
143 INSERT INTO t2 VALUES(1.1, NULL, NULL);
144 }
drhf9c8ce32013-11-05 13:33:55 +0000145} {1 {CHECK constraint failed: one}}
drhffe07b22005-11-03 00:41:17 +0000146do_test check-2.5 {
147 catchsql {
148 INSERT INTO t2 VALUES(NULL, 5, NULL);
149 }
drhf9c8ce32013-11-05 13:33:55 +0000150} {1 {CHECK constraint failed: two}}
drhffe07b22005-11-03 00:41:17 +0000151do_test check-2.6 {
152 catchsql {
153 INSERT INTO t2 VALUES(NULL, NULL, 3.14159);
154 }
drhf9c8ce32013-11-05 13:33:55 +0000155} {1 {CHECK constraint failed: three}}
drhffe07b22005-11-03 00:41:17 +0000156
drh4dc330d2012-05-07 19:21:36 +0000157# 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.
160#
161do_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} {}
171do_test check-2.11 {
172 catchsql {
173 INSERT INTO t2b VALUES('xyzzy','hi',5);
174 }
drhf9c8ce32013-11-05 13:33:55 +0000175} {1 {CHECK constraint failed: t2b}}
drh4dc330d2012-05-07 19:21:36 +0000176do_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} {}
187do_test check-2.13 {
188 catchsql {
189 INSERT INTO t2c VALUES('xyzzy',7,8);
190 }
drhf9c8ce32013-11-05 13:33:55 +0000191} {1 {CHECK constraint failed: x_two}}
drh4dc330d2012-05-07 19:21:36 +0000192do_test check-2.cleanup {
193 execsql {
194 DROP TABLE IF EXISTS t2b;
195 DROP TABLE IF EXISTS t2c;
196 }
197} {}
198
danielk19771576cd92006-01-14 08:02:28 +0000199ifcapable 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}}
208}
209
drh06f65412005-11-03 02:03:13 +0000210do_test check-3.2 {
211 execsql {
212 SELECT name FROM sqlite_master ORDER BY name
213 }
214} {t1 t2}
215do_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}}
223do_test check-3.4 {
224 execsql {
225 SELECT name FROM sqlite_master ORDER BY name
226 }
227} {t1 t2}
228do_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}}
236do_test check-3.6 {
237 execsql {
238 SELECT name FROM sqlite_master ORDER BY name
239 }
240} {t1 t2}
241do_test check-3.7 {
242 catchsql {
243 CREATE TABLE t3(
244 x, y, z,
245 CHECK( t3.x<25 )
246 );
247 }
248} {0 {}}
249do_test check-3.8 {
250 execsql {
251 INSERT INTO t3 VALUES(1,2,3);
252 SELECT * FROM t3;
253 }
254} {1 2 3}
255do_test check-3.9 {
256 catchsql {
257 INSERT INTO t3 VALUES(111,222,333);
258 }
drhf9c8ce32013-11-05 13:33:55 +0000259} {1 {CHECK constraint failed: t3}}
drh06f65412005-11-03 02:03:13 +0000260
261do_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} {}
273do_test check-4.2 {
274 execsql {
275 INSERT INTO t4 VALUES(1,10);
276 SELECT * FROM t4
277 }
278} {1 10}
279do_test check-4.3 {
280 execsql {
281 UPDATE t4 SET x=4, y=3;
282 SELECT * FROM t4
283 }
284} {4 3}
shanehf33a7a82009-12-31 19:48:29 +0000285do_test check-4.4 {
drh06f65412005-11-03 02:03:13 +0000286 execsql {
287 UPDATE t4 SET x=12, y=2;
288 SELECT * FROM t4
289 }
290} {12 2}
shanehf33a7a82009-12-31 19:48:29 +0000291do_test check-4.5 {
drh06f65412005-11-03 02:03:13 +0000292 execsql {
293 UPDATE t4 SET x=12, y=-22;
294 SELECT * FROM t4
295 }
296} {12 -22}
shanehf33a7a82009-12-31 19:48:29 +0000297do_test check-4.6 {
drh06f65412005-11-03 02:03:13 +0000298 catchsql {
299 UPDATE t4 SET x=0, y=1;
300 }
drhf9c8ce32013-11-05 13:33:55 +0000301} {1 {CHECK constraint failed: t4}}
shanehf33a7a82009-12-31 19:48:29 +0000302do_test check-4.7 {
drh06f65412005-11-03 02:03:13 +0000303 execsql {
304 SELECT * FROM t4;
305 }
306} {12 -22}
shanehf33a7a82009-12-31 19:48:29 +0000307do_test check-4.8 {
drh0cd2d4c2005-11-03 02:15:02 +0000308 execsql {
309 PRAGMA ignore_check_constraints=ON;
310 UPDATE t4 SET x=0, y=1;
311 SELECT * FROM t4;
drh8a284dc2017-02-22 14:15:37 +0000312 PRAGMA integrity_check;
drh0cd2d4c2005-11-03 02:15:02 +0000313 }
drh8a284dc2017-02-22 14:15:37 +0000314} {0 1 ok}
315do_execsql_test check-4.8.1 {
316 PRAGMA ignore_check_constraints=OFF;
317 PRAGMA integrity_check;
318} {{CHECK constraint failed in t4}}
shanehf33a7a82009-12-31 19:48:29 +0000319do_test check-4.9 {
drh0cd2d4c2005-11-03 02:15:02 +0000320 catchsql {
drh0cd2d4c2005-11-03 02:15:02 +0000321 UPDATE t4 SET x=0, y=2;
322 }
drhf9c8ce32013-11-05 13:33:55 +0000323} {1 {CHECK constraint failed: t4}}
danielk19773bdca9c2006-01-17 09:35:01 +0000324ifcapable vacuum {
shanehf33a7a82009-12-31 19:48:29 +0000325 do_test check_4.10 {
danielk19773bdca9c2006-01-17 09:35:01 +0000326 catchsql {
327 VACUUM
328 }
329 } {0 {}}
330}
drh0cd2d4c2005-11-03 02:15:02 +0000331
drh4284fb02005-11-03 12:33:28 +0000332do_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}}
339do_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}}
346
danielk19774b2688a2006-06-20 11:01:07 +0000347ifcapable conflict {
348
drhaa01c7e2006-03-15 16:26:10 +0000349do_test check-6.1 {
350 execsql {SELECT * FROM t1}
351} {4 11.0}
352do_test check-6.2 {
353 execsql {
354 UPDATE OR IGNORE t1 SET x=5;
355 SELECT * FROM t1;
356 }
357} {4 11.0}
358do_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}
364do_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}
370do_test check-6.5 {
371 catchsql {
372 UPDATE OR FAIL t1 SET x=7-x, y=y+1;
373 }
drhf9c8ce32013-11-05 13:33:55 +0000374} {1 {CHECK constraint failed: t1}}
drhaa01c7e2006-03-15 16:26:10 +0000375do_test check-6.6 {
376 execsql {
377 SELECT * FROM t1;
378 }
379} {3 12.0 2 20.0}
380do_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 }
drhf9c8ce32013-11-05 13:33:55 +0000386} {1 {CHECK constraint failed: t1}}
drhaa01c7e2006-03-15 16:26:10 +0000387do_test check-6.8 {
388 catchsql {
389 COMMIT;
390 }
391} {1 {cannot commit - no transaction is active}}
392do_test check-6.9 {
393 execsql {
394 SELECT * FROM t1
395 }
396} {3 12.0 2 20.0}
397
drh2e06c672007-07-23 19:39:46 +0000398do_test check-6.11 {
399 execsql {SELECT * FROM t1}
400} {3 12.0 2 20.0}
401do_test check-6.12 {
402 catchsql {
403 REPLACE INTO t1 VALUES(6,7);
404 }
drhf9c8ce32013-11-05 13:33:55 +0000405} {1 {CHECK constraint failed: t1}}
drh2e06c672007-07-23 19:39:46 +0000406do_test check-6.13 {
407 execsql {SELECT * FROM t1}
408} {3 12.0 2 20.0}
409do_test check-6.14 {
410 catchsql {
411 INSERT OR IGNORE INTO t1 VALUES(6,7);
412 }
413} {0 {}}
414do_test check-6.15 {
415 execsql {SELECT * FROM t1}
416} {3 12.0 2 20.0}
417
418
danielk19774b2688a2006-06-20 11:01:07 +0000419}
drh06f65412005-11-03 02:03:13 +0000420
drhddd1fc72013-01-08 12:48:10 +0000421#--------------------------------------------------------------------------
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).
426#
427reset_db
428proc myfunc {x} {expr $x < 10}
429db func myfunc myfunc
430
431do_execsql_test 7.1 { CREATE TABLE t6(a CHECK (myfunc(a))) }
432do_execsql_test 7.2 { INSERT INTO t6 VALUES(9) }
drhf9c8ce32013-11-05 13:33:55 +0000433do_catchsql_test 7.3 { INSERT INTO t6 VALUES(11) } \
434 {1 {CHECK constraint failed: t6}}
drhddd1fc72013-01-08 12:48:10 +0000435
436do_test 7.4 {
437 sqlite3 db2 test.db
438 execsql { SELECT * FROM t6 } db2
439} {9}
440
441do_test 7.5 {
442 catchsql { INSERT INTO t6 VALUES(8) } db2
443} {1 {unknown function: myfunc()}}
444
445do_test 7.6 {
446 catchsql { CREATE TABLE t7(a CHECK (myfunc(a))) } db2
447} {1 {no such function: myfunc}}
448
449do_test 7.7 {
450 db2 func myfunc myfunc
451 execsql { INSERT INTO t6 VALUES(8) } db2
452} {}
453
454do_test 7.8 {
455 db2 func myfunc myfunc
456 catchsql { INSERT INTO t6 VALUES(12) } db2
drhf9c8ce32013-11-05 13:33:55 +0000457} {1 {CHECK constraint failed: t6}}
drhddd1fc72013-01-08 12:48:10 +0000458
drh1e7d43c2013-08-02 14:18:18 +0000459# 2013-08-02: Silently ignore database name qualifiers in CHECK constraints.
460#
461do_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} {}
drhddd1fc72013-01-08 12:48:10 +0000465
drh98bfa162016-02-10 18:24:05 +0000466# Make sure check constraints involving the ROWID are not ignored
467#
468do_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} {}
477do_catchsql_test 9.2 {
478 UPDATE t1 SET b=0 WHERE a=1;
479} {1 {CHECK constraint failed: b-check}}
480do_catchsql_test 9.3 {
481 UPDATE t1 SET c=a*2 WHERE a=1;
482} {1 {CHECK constraint failed: c-check}}
483
484
485
drhffe07b22005-11-03 00:41:17 +0000486finish_test