xref: /sqlite-3.40.0/test/check.test (revision 5976b2c8)
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    PRAGMA writable_schema = 0;
127  }
128} {}
129do_test check-2.2 {
130  execsql {
131    INSERT INTO t2 VALUES(1,2.2,'three');
132    SELECT * FROM t2;
133  }
134} {1 2.2 three}
135db close
136sqlite3 db test.db
137do_test check-2.3 {
138  execsql {
139    INSERT INTO t2 VALUES(NULL, NULL, NULL);
140    SELECT * FROM t2;
141  }
142} {1 2.2 three {} {} {}}
143do_test check-2.4 {
144  catchsql {
145    INSERT INTO t2 VALUES(1.1, NULL, NULL);
146  }
147} {1 {CHECK constraint failed: one}}
148do_test check-2.5 {
149  catchsql {
150    INSERT INTO t2 VALUES(NULL, 5, NULL);
151  }
152} {1 {CHECK constraint failed: two}}
153do_test check-2.6 {
154  catchsql {
155    INSERT INTO t2 VALUES(NULL, NULL, 3.14159);
156  }
157} {1 {CHECK constraint failed: three}}
158
159# Undocumented behavior:  The CONSTRAINT name clause can follow a constraint.
160# Such a clause is ignored.  But the parser must accept it for backwards
161# compatibility.
162#
163do_test check-2.10 {
164  execsql {
165    CREATE TABLE t2b(
166      x INTEGER CHECK( typeof(coalesce(x,0))=='integer' ) CONSTRAINT one,
167      y TEXT PRIMARY KEY constraint two,
168      z INTEGER,
169      UNIQUE(x,z) constraint three
170    );
171  }
172} {}
173do_test check-2.11 {
174  catchsql {
175    INSERT INTO t2b VALUES('xyzzy','hi',5);
176  }
177} {1 {CHECK constraint failed: t2b}}
178do_test check-2.12 {
179  execsql {
180    CREATE TABLE t2c(
181      x INTEGER CONSTRAINT x_one CONSTRAINT x_two
182          CHECK( typeof(coalesce(x,0))=='integer' )
183          CONSTRAINT x_two CONSTRAINT x_three,
184      y INTEGER, z INTEGER,
185      CONSTRAINT u_one UNIQUE(x,y,z) CONSTRAINT u_two
186    );
187  }
188} {}
189do_test check-2.13 {
190  catchsql {
191    INSERT INTO t2c VALUES('xyzzy',7,8);
192  }
193} {1 {CHECK constraint failed: x_two}}
194do_test check-2.cleanup {
195  execsql {
196    DROP TABLE IF EXISTS t2b;
197    DROP TABLE IF EXISTS t2c;
198  }
199} {}
200
201ifcapable subquery {
202  do_test check-3.1 {
203    catchsql {
204      CREATE TABLE t3(
205        x, y, z,
206        CHECK( x<(SELECT min(x) FROM t1) )
207      );
208    }
209  } {1 {subqueries prohibited in CHECK constraints}}
210}
211
212do_test check-3.2 {
213  execsql {
214    SELECT name FROM sqlite_master ORDER BY name
215  }
216} {t1 t2}
217do_test check-3.3 {
218  catchsql {
219    CREATE TABLE t3(
220      x, y, z,
221      CHECK( q<x )
222    );
223  }
224} {1 {no such column: q}}
225do_test check-3.4 {
226  execsql {
227    SELECT name FROM sqlite_master ORDER BY name
228  }
229} {t1 t2}
230do_test check-3.5 {
231  catchsql {
232    CREATE TABLE t3(
233      x, y, z,
234      CHECK( t2.x<x )
235    );
236  }
237} {1 {no such column: t2.x}}
238do_test check-3.6 {
239  execsql {
240    SELECT name FROM sqlite_master ORDER BY name
241  }
242} {t1 t2}
243do_test check-3.7 {
244  catchsql {
245    CREATE TABLE t3(
246      x, y, z,
247      CHECK( t3.x<25 )
248    );
249  }
250} {0 {}}
251do_test check-3.8 {
252  execsql {
253    INSERT INTO t3 VALUES(1,2,3);
254    SELECT * FROM t3;
255  }
256} {1 2 3}
257do_test check-3.9 {
258  catchsql {
259    INSERT INTO t3 VALUES(111,222,333);
260  }
261} {1 {CHECK constraint failed: t3}}
262
263do_test check-4.1 {
264  execsql {
265    CREATE TABLE t4(x, y,
266      CHECK (
267           x+y==11
268        OR x*y==12
269        OR x/y BETWEEN 5 AND 8
270        OR -x==y+10
271      )
272    );
273  }
274} {}
275do_test check-4.2 {
276  execsql {
277    INSERT INTO t4 VALUES(1,10);
278    SELECT * FROM t4
279  }
280} {1 10}
281do_test check-4.3 {
282  execsql {
283    UPDATE t4 SET x=4, y=3;
284    SELECT * FROM t4
285  }
286} {4 3}
287do_test check-4.4 {
288  execsql {
289    UPDATE t4 SET x=12, y=2;
290    SELECT * FROM t4
291  }
292} {12 2}
293do_test check-4.5 {
294  execsql {
295    UPDATE t4 SET x=12, y=-22;
296    SELECT * FROM t4
297  }
298} {12 -22}
299do_test check-4.6 {
300  catchsql {
301    UPDATE t4 SET x=0, y=1;
302  }
303} {1 {CHECK constraint failed: t4}}
304do_test check-4.7 {
305  execsql {
306    SELECT * FROM t4;
307  }
308} {12 -22}
309do_test check-4.8 {
310  execsql {
311    PRAGMA ignore_check_constraints=ON;
312    UPDATE t4 SET x=0, y=1;
313    SELECT * FROM t4;
314    PRAGMA integrity_check;
315  }
316} {0 1 ok}
317do_execsql_test check-4.8.1 {
318  PRAGMA ignore_check_constraints=OFF;
319  PRAGMA integrity_check;
320} {{CHECK constraint failed in t4}}
321do_test check-4.9 {
322  catchsql {
323    UPDATE t4 SET x=0, y=2;
324  }
325} {1 {CHECK constraint failed: t4}}
326ifcapable vacuum {
327  do_test check_4.10 {
328    catchsql {
329      VACUUM
330    }
331  } {0 {}}
332}
333
334do_test check-5.1 {
335  catchsql {
336    CREATE TABLE t5(x, y,
337      CHECK( x*y<:abc )
338    );
339  }
340} {1 {parameters prohibited in CHECK constraints}}
341do_test check-5.2 {
342  catchsql {
343    CREATE TABLE t5(x, y,
344      CHECK( x*y<? )
345    );
346  }
347} {1 {parameters prohibited in CHECK constraints}}
348
349ifcapable conflict {
350
351do_test check-6.1 {
352  execsql {SELECT * FROM t1}
353} {4 11.0}
354do_test check-6.2 {
355  execsql {
356    UPDATE OR IGNORE t1 SET x=5;
357    SELECT * FROM t1;
358  }
359} {4 11.0}
360do_test check-6.3 {
361  execsql {
362    INSERT OR IGNORE INTO t1 VALUES(5,4.0);
363    SELECT * FROM t1;
364  }
365} {4 11.0}
366do_test check-6.4 {
367  execsql {
368    INSERT OR IGNORE INTO t1 VALUES(2,20.0);
369    SELECT * FROM t1;
370  }
371} {4 11.0 2 20.0}
372do_test check-6.5 {
373  catchsql {
374    UPDATE OR FAIL t1 SET x=7-x, y=y+1;
375  }
376} {1 {CHECK constraint failed: t1}}
377do_test check-6.6 {
378  execsql {
379    SELECT * FROM t1;
380  }
381} {3 12.0 2 20.0}
382do_test check-6.7 {
383  catchsql {
384    BEGIN;
385    INSERT INTO t1 VALUES(1,30.0);
386    INSERT OR ROLLBACK INTO t1 VALUES(8,40.0);
387  }
388} {1 {CHECK constraint failed: t1}}
389do_test check-6.8 {
390  catchsql {
391    COMMIT;
392  }
393} {1 {cannot commit - no transaction is active}}
394do_test check-6.9 {
395  execsql {
396    SELECT * FROM t1
397  }
398} {3 12.0 2 20.0}
399
400do_test check-6.11 {
401  execsql {SELECT * FROM t1}
402} {3 12.0 2 20.0}
403do_test check-6.12 {
404  catchsql {
405    REPLACE INTO t1 VALUES(6,7);
406  }
407} {1 {CHECK constraint failed: t1}}
408do_test check-6.13 {
409  execsql {SELECT * FROM t1}
410} {3 12.0 2 20.0}
411do_test check-6.14 {
412  catchsql {
413    INSERT OR IGNORE INTO t1 VALUES(6,7);
414  }
415} {0 {}}
416do_test check-6.15 {
417  execsql {SELECT * FROM t1}
418} {3 12.0 2 20.0}
419
420
421}
422
423#--------------------------------------------------------------------------
424# If a connection opens a database that contains a CHECK constraint that
425# uses an unknown UDF, the schema should not be considered malformed.
426# Attempting to modify the table should fail (since the CHECK constraint
427# cannot be tested).
428#
429reset_db
430proc myfunc {x} {expr $x < 10}
431db func myfunc myfunc
432
433do_execsql_test  7.1 { CREATE TABLE t6(a CHECK (myfunc(a))) }
434do_execsql_test  7.2 { INSERT INTO t6 VALUES(9)  }
435do_catchsql_test 7.3 { INSERT INTO t6 VALUES(11) } \
436          {1 {CHECK constraint failed: t6}}
437
438do_test 7.4 {
439  sqlite3 db2 test.db
440  execsql { SELECT * FROM t6 } db2
441} {9}
442
443do_test 7.5 {
444  catchsql { INSERT INTO t6 VALUES(8) } db2
445} {1 {unknown function: myfunc()}}
446
447do_test 7.6 {
448  catchsql { CREATE TABLE t7(a CHECK (myfunc(a))) } db2
449} {1 {no such function: myfunc}}
450
451do_test 7.7 {
452  db2 func myfunc myfunc
453  execsql { INSERT INTO t6 VALUES(8) } db2
454} {}
455
456do_test 7.8 {
457  db2 func myfunc myfunc
458  catchsql { INSERT INTO t6 VALUES(12) } db2
459} {1 {CHECK constraint failed: t6}}
460
461# 2013-08-02:  Silently ignore database name qualifiers in CHECK constraints.
462#
463do_execsql_test 8.1 {
464  CREATE TABLE t810(a, CHECK( main.t810.a>0 ));
465  CREATE TABLE t811(b, CHECK( xyzzy.t811.b BETWEEN 5 AND 10 ));
466} {}
467
468# Make sure check constraints involving the ROWID are not ignored
469#
470do_execsql_test 9.1 {
471  CREATE TABLE t1(
472    a INTEGER PRIMARY KEY,
473    b INTEGER NOT NULL CONSTRAINT 'b-check' CHECK( b>a ),
474    c INTEGER NOT NULL CONSTRAINT 'c-check' CHECK( c>rowid*2 ),
475    d INTEGER NOT NULL CONSTRAINT 'd-check' CHECK( d BETWEEN b AND c )
476  );
477  INSERT INTO t1(a,b,c,d) VALUES(1,2,4,3),(2,4,6,5),(3,10,30,20);
478} {}
479do_catchsql_test 9.2 {
480  UPDATE t1 SET b=0 WHERE a=1;
481} {1 {CHECK constraint failed: b-check}}
482do_catchsql_test 9.3 {
483  UPDATE t1 SET c=a*2 WHERE a=1;
484} {1 {CHECK constraint failed: c-check}}
485
486# Integrity check on a VIEW with columns.
487#
488db close
489db2 close
490forcedelete test.db
491sqlite3 db test.db
492do_execsql_test 10.1 {
493  CREATE TABLE t1(x);
494  CREATE VIEW v1(y) AS SELECT x FROM t1;
495  PRAGMA integrity_check;
496} {ok}
497
498#-------------------------------------------------------------------------
499reset_db
500do_execsql_test 11.0 {
501  CREATE TABLE t1 (Col0 CHECK(1 COLLATE BINARY BETWEEN 1 AND 1) ) ;
502}
503do_execsql_test 11.1 {
504  INSERT INTO t1 VALUES (NULL);
505}
506do_execsql_test 11.2 {
507  INSERT  INTO t1 VALUES (NULL);
508}
509
510do_execsql_test 11.3 {
511  CREATE TABLE t2(b, a CHECK(
512      CASE 'abc' COLLATE nocase WHEN a THEN 1 ELSE 0 END)
513  );
514}
515do_execsql_test 11.4 {
516  INSERT INTO t2(a) VALUES('abc');
517}
518do_execsql_test 11.5 {
519  INSERT INTO t2(b, a) VALUES(1, 'abc'||'');
520}
521do_execsql_test 11.6 {
522  INSERT INTO t2(b, a) VALUES(2, 'abc');
523}
524
525finish_test
526
527
528finish_test
529