OLD | NEW |
1 # 2005 November 2 | 1 # 2005 November 2 |
2 # | 2 # |
3 # The author disclaims copyright to this source code. In place of | 3 # The author disclaims copyright to this source code. In place of |
4 # a legal notice, here is a blessing: | 4 # a legal notice, here is a blessing: |
5 # | 5 # |
6 # May you do good and not evil. | 6 # May you do good and not evil. |
7 # May you find forgiveness for yourself and forgive others. | 7 # May you find forgiveness for yourself and forgive others. |
8 # May you share freely, never taking more than you give. | 8 # May you share freely, never taking more than you give. |
9 # | 9 # |
10 #*********************************************************************** | 10 #*********************************************************************** |
11 # This file implements regression tests for SQLite library. The | 11 # This file implements regression tests for SQLite library. The |
12 # focus of this file is testing CHECK constraints | 12 # focus of this file is testing CHECK constraints |
13 # | 13 # |
14 # $Id: check.test,v 1.13 2009/06/05 17:09:12 drh Exp $ | 14 # $Id: check.test,v 1.13 2009/06/05 17:09:12 drh Exp $ |
15 | 15 |
16 set testdir [file dirname $argv0] | 16 set testdir [file dirname $argv0] |
17 source $testdir/tester.tcl | 17 source $testdir/tester.tcl |
| 18 set ::testprefix check |
18 | 19 |
19 # Only run these tests if the build includes support for CHECK constraints | 20 # Only run these tests if the build includes support for CHECK constraints |
20 ifcapable !check { | 21 ifcapable !check { |
21 finish_test | 22 finish_test |
22 return | 23 return |
23 } | 24 } |
24 | 25 |
25 do_test check-1.1 { | 26 do_test check-1.1 { |
26 execsql { | 27 execsql { |
27 CREATE TABLE t1( | 28 CREATE TABLE t1( |
28 x INTEGER CHECK( x<5 ), | 29 x INTEGER CHECK( x<5 ), |
29 y REAL CHECK( y>x ) | 30 y REAL CHECK( y>x ) |
30 ); | 31 ); |
31 } | 32 } |
32 } {} | 33 } {} |
33 do_test check-1.2 { | 34 do_test check-1.2 { |
34 execsql { | 35 execsql { |
35 INSERT INTO t1 VALUES(3,4); | 36 INSERT INTO t1 VALUES(3,4); |
36 SELECT * FROM t1; | 37 SELECT * FROM t1; |
37 } | 38 } |
38 } {3 4.0} | 39 } {3 4.0} |
39 do_test check-1.3 { | 40 do_test check-1.3 { |
40 catchsql { | 41 catchsql { |
41 INSERT INTO t1 VALUES(6,7); | 42 INSERT INTO t1 VALUES(6,7); |
42 } | 43 } |
43 } {1 {constraint failed}} | 44 } {1 {CHECK constraint failed: t1}} |
44 do_test check-1.4 { | 45 do_test check-1.4 { |
45 execsql { | 46 execsql { |
46 SELECT * FROM t1; | 47 SELECT * FROM t1; |
47 } | 48 } |
48 } {3 4.0} | 49 } {3 4.0} |
49 do_test check-1.5 { | 50 do_test check-1.5 { |
50 catchsql { | 51 catchsql { |
51 INSERT INTO t1 VALUES(4,3); | 52 INSERT INTO t1 VALUES(4,3); |
52 } | 53 } |
53 } {1 {constraint failed}} | 54 } {1 {CHECK constraint failed: t1}} |
54 do_test check-1.6 { | 55 do_test check-1.6 { |
55 execsql { | 56 execsql { |
56 SELECT * FROM t1; | 57 SELECT * FROM t1; |
57 } | 58 } |
58 } {3 4.0} | 59 } {3 4.0} |
59 do_test check-1.7 { | 60 do_test check-1.7 { |
60 catchsql { | 61 catchsql { |
61 INSERT INTO t1 VALUES(NULL,6); | 62 INSERT INTO t1 VALUES(NULL,6); |
62 } | 63 } |
63 } {0 {}} | 64 } {0 {}} |
(...skipping 16 matching lines...) Expand all Loading... |
80 execsql { | 81 execsql { |
81 DELETE FROM t1 WHERE x IS NULL OR x!=3; | 82 DELETE FROM t1 WHERE x IS NULL OR x!=3; |
82 UPDATE t1 SET x=2 WHERE x==3; | 83 UPDATE t1 SET x=2 WHERE x==3; |
83 SELECT * FROM t1; | 84 SELECT * FROM t1; |
84 } | 85 } |
85 } {2 4.0} | 86 } {2 4.0} |
86 do_test check-1.12 { | 87 do_test check-1.12 { |
87 catchsql { | 88 catchsql { |
88 UPDATE t1 SET x=7 WHERE x==2 | 89 UPDATE t1 SET x=7 WHERE x==2 |
89 } | 90 } |
90 } {1 {constraint failed}} | 91 } {1 {CHECK constraint failed: t1}} |
91 do_test check-1.13 { | 92 do_test check-1.13 { |
92 execsql { | 93 execsql { |
93 SELECT * FROM t1; | 94 SELECT * FROM t1; |
94 } | 95 } |
95 } {2 4.0} | 96 } {2 4.0} |
96 do_test check-1.14 { | 97 do_test check-1.14 { |
97 catchsql { | 98 catchsql { |
98 UPDATE t1 SET x=5 WHERE x==2 | 99 UPDATE t1 SET x=5 WHERE x==2 |
99 } | 100 } |
100 } {1 {constraint failed}} | 101 } {1 {CHECK constraint failed: t1}} |
101 do_test check-1.15 { | 102 do_test check-1.15 { |
102 execsql { | 103 execsql { |
103 SELECT * FROM t1; | 104 SELECT * FROM t1; |
104 } | 105 } |
105 } {2 4.0} | 106 } {2 4.0} |
106 do_test check-1.16 { | 107 do_test check-1.16 { |
107 catchsql { | 108 catchsql { |
108 UPDATE t1 SET x=4, y=11 WHERE x==2 | 109 UPDATE t1 SET x=4, y=11 WHERE x==2 |
109 } | 110 } |
110 } {0 {}} | 111 } {0 {}} |
111 do_test check-1.17 { | 112 do_test check-1.17 { |
112 execsql { | 113 execsql { |
113 SELECT * FROM t1; | 114 SELECT * FROM t1; |
114 } | 115 } |
115 } {4 11.0} | 116 } {4 11.0} |
116 | 117 |
117 do_test check-2.1 { | 118 do_test check-2.1 { |
118 execsql { | 119 execsql { |
119 CREATE TABLE t2( | 120 CREATE TABLE t2( |
120 x INTEGER CHECK( typeof(coalesce(x,0))=="integer" ), | 121 x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ), |
121 y REAL CHECK( typeof(coalesce(y,0.1))=='real' ), | 122 y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ), |
122 z TEXT CHECK( typeof(coalesce(z,''))=='text' ) | 123 z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' ) |
123 ); | 124 ); |
124 } | 125 } |
125 } {} | 126 } {} |
126 do_test check-2.2 { | 127 do_test check-2.2 { |
127 execsql { | 128 execsql { |
128 INSERT INTO t2 VALUES(1,2.2,'three'); | 129 INSERT INTO t2 VALUES(1,2.2,'three'); |
129 SELECT * FROM t2; | 130 SELECT * FROM t2; |
130 } | 131 } |
131 } {1 2.2 three} | 132 } {1 2.2 three} |
132 db close | 133 db close |
133 sqlite3 db test.db | 134 sqlite3 db test.db |
134 do_test check-2.3 { | 135 do_test check-2.3 { |
135 execsql { | 136 execsql { |
136 INSERT INTO t2 VALUES(NULL, NULL, NULL); | 137 INSERT INTO t2 VALUES(NULL, NULL, NULL); |
137 SELECT * FROM t2; | 138 SELECT * FROM t2; |
138 } | 139 } |
139 } {1 2.2 three {} {} {}} | 140 } {1 2.2 three {} {} {}} |
140 do_test check-2.4 { | 141 do_test check-2.4 { |
141 catchsql { | 142 catchsql { |
142 INSERT INTO t2 VALUES(1.1, NULL, NULL); | 143 INSERT INTO t2 VALUES(1.1, NULL, NULL); |
143 } | 144 } |
144 } {1 {constraint failed}} | 145 } {1 {CHECK constraint failed: one}} |
145 do_test check-2.5 { | 146 do_test check-2.5 { |
146 catchsql { | 147 catchsql { |
147 INSERT INTO t2 VALUES(NULL, 5, NULL); | 148 INSERT INTO t2 VALUES(NULL, 5, NULL); |
148 } | 149 } |
149 } {1 {constraint failed}} | 150 } {1 {CHECK constraint failed: two}} |
150 do_test check-2.6 { | 151 do_test check-2.6 { |
151 catchsql { | 152 catchsql { |
152 INSERT INTO t2 VALUES(NULL, NULL, 3.14159); | 153 INSERT INTO t2 VALUES(NULL, NULL, 3.14159); |
153 } | 154 } |
154 } {1 {constraint failed}} | 155 } {1 {CHECK constraint failed: three}} |
| 156 |
| 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. |
| 160 # |
| 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 } {} |
155 | 198 |
156 ifcapable subquery { | 199 ifcapable subquery { |
157 do_test check-3.1 { | 200 do_test check-3.1 { |
158 catchsql { | 201 catchsql { |
159 CREATE TABLE t3( | 202 CREATE TABLE t3( |
160 x, y, z, | 203 x, y, z, |
161 CHECK( x<(SELECT min(x) FROM t1) ) | 204 CHECK( x<(SELECT min(x) FROM t1) ) |
162 ); | 205 ); |
163 } | 206 } |
164 } {1 {subqueries prohibited in CHECK constraints}} | 207 } {1 {subqueries prohibited in CHECK constraints}} |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 do_test check-3.8 { | 249 do_test check-3.8 { |
207 execsql { | 250 execsql { |
208 INSERT INTO t3 VALUES(1,2,3); | 251 INSERT INTO t3 VALUES(1,2,3); |
209 SELECT * FROM t3; | 252 SELECT * FROM t3; |
210 } | 253 } |
211 } {1 2 3} | 254 } {1 2 3} |
212 do_test check-3.9 { | 255 do_test check-3.9 { |
213 catchsql { | 256 catchsql { |
214 INSERT INTO t3 VALUES(111,222,333); | 257 INSERT INTO t3 VALUES(111,222,333); |
215 } | 258 } |
216 } {1 {constraint failed}} | 259 } {1 {CHECK constraint failed: t3}} |
217 | 260 |
218 do_test check-4.1 { | 261 do_test check-4.1 { |
219 execsql { | 262 execsql { |
220 CREATE TABLE t4(x, y, | 263 CREATE TABLE t4(x, y, |
221 CHECK ( | 264 CHECK ( |
222 x+y==11 | 265 x+y==11 |
223 OR x*y==12 | 266 OR x*y==12 |
224 OR x/y BETWEEN 5 AND 8 | 267 OR x/y BETWEEN 5 AND 8 |
225 OR -x==y+10 | 268 OR -x==y+10 |
226 ) | 269 ) |
(...skipping 21 matching lines...) Expand all Loading... |
248 do_test check-4.5 { | 291 do_test check-4.5 { |
249 execsql { | 292 execsql { |
250 UPDATE t4 SET x=12, y=-22; | 293 UPDATE t4 SET x=12, y=-22; |
251 SELECT * FROM t4 | 294 SELECT * FROM t4 |
252 } | 295 } |
253 } {12 -22} | 296 } {12 -22} |
254 do_test check-4.6 { | 297 do_test check-4.6 { |
255 catchsql { | 298 catchsql { |
256 UPDATE t4 SET x=0, y=1; | 299 UPDATE t4 SET x=0, y=1; |
257 } | 300 } |
258 } {1 {constraint failed}} | 301 } {1 {CHECK constraint failed: t4}} |
259 do_test check-4.7 { | 302 do_test check-4.7 { |
260 execsql { | 303 execsql { |
261 SELECT * FROM t4; | 304 SELECT * FROM t4; |
262 } | 305 } |
263 } {12 -22} | 306 } {12 -22} |
264 do_test check-4.8 { | 307 do_test check-4.8 { |
265 execsql { | 308 execsql { |
266 PRAGMA ignore_check_constraints=ON; | 309 PRAGMA ignore_check_constraints=ON; |
267 UPDATE t4 SET x=0, y=1; | 310 UPDATE t4 SET x=0, y=1; |
268 SELECT * FROM t4; | 311 SELECT * FROM t4; |
269 } | 312 } |
270 } {0 1} | 313 } {0 1} |
271 do_test check-4.9 { | 314 do_test check-4.9 { |
272 catchsql { | 315 catchsql { |
273 PRAGMA ignore_check_constraints=OFF; | 316 PRAGMA ignore_check_constraints=OFF; |
274 UPDATE t4 SET x=0, y=2; | 317 UPDATE t4 SET x=0, y=2; |
275 } | 318 } |
276 } {1 {constraint failed}} | 319 } {1 {CHECK constraint failed: t4}} |
277 ifcapable vacuum { | 320 ifcapable vacuum { |
278 do_test check_4.10 { | 321 do_test check_4.10 { |
279 catchsql { | 322 catchsql { |
280 VACUUM | 323 VACUUM |
281 } | 324 } |
282 } {0 {}} | 325 } {0 {}} |
283 } | 326 } |
284 | 327 |
285 do_test check-5.1 { | 328 do_test check-5.1 { |
286 catchsql { | 329 catchsql { |
(...skipping 30 matching lines...) Expand all Loading... |
317 do_test check-6.4 { | 360 do_test check-6.4 { |
318 execsql { | 361 execsql { |
319 INSERT OR IGNORE INTO t1 VALUES(2,20.0); | 362 INSERT OR IGNORE INTO t1 VALUES(2,20.0); |
320 SELECT * FROM t1; | 363 SELECT * FROM t1; |
321 } | 364 } |
322 } {4 11.0 2 20.0} | 365 } {4 11.0 2 20.0} |
323 do_test check-6.5 { | 366 do_test check-6.5 { |
324 catchsql { | 367 catchsql { |
325 UPDATE OR FAIL t1 SET x=7-x, y=y+1; | 368 UPDATE OR FAIL t1 SET x=7-x, y=y+1; |
326 } | 369 } |
327 } {1 {constraint failed}} | 370 } {1 {CHECK constraint failed: t1}} |
328 do_test check-6.6 { | 371 do_test check-6.6 { |
329 execsql { | 372 execsql { |
330 SELECT * FROM t1; | 373 SELECT * FROM t1; |
331 } | 374 } |
332 } {3 12.0 2 20.0} | 375 } {3 12.0 2 20.0} |
333 do_test check-6.7 { | 376 do_test check-6.7 { |
334 catchsql { | 377 catchsql { |
335 BEGIN; | 378 BEGIN; |
336 INSERT INTO t1 VALUES(1,30.0); | 379 INSERT INTO t1 VALUES(1,30.0); |
337 INSERT OR ROLLBACK INTO t1 VALUES(8,40.0); | 380 INSERT OR ROLLBACK INTO t1 VALUES(8,40.0); |
338 } | 381 } |
339 } {1 {constraint failed}} | 382 } {1 {CHECK constraint failed: t1}} |
340 do_test check-6.8 { | 383 do_test check-6.8 { |
341 catchsql { | 384 catchsql { |
342 COMMIT; | 385 COMMIT; |
343 } | 386 } |
344 } {1 {cannot commit - no transaction is active}} | 387 } {1 {cannot commit - no transaction is active}} |
345 do_test check-6.9 { | 388 do_test check-6.9 { |
346 execsql { | 389 execsql { |
347 SELECT * FROM t1 | 390 SELECT * FROM t1 |
348 } | 391 } |
349 } {3 12.0 2 20.0} | 392 } {3 12.0 2 20.0} |
350 | 393 |
351 do_test check-6.11 { | 394 do_test check-6.11 { |
352 execsql {SELECT * FROM t1} | 395 execsql {SELECT * FROM t1} |
353 } {3 12.0 2 20.0} | 396 } {3 12.0 2 20.0} |
354 do_test check-6.12 { | 397 do_test check-6.12 { |
355 catchsql { | 398 catchsql { |
356 REPLACE INTO t1 VALUES(6,7); | 399 REPLACE INTO t1 VALUES(6,7); |
357 } | 400 } |
358 } {1 {constraint failed}} | 401 } {1 {CHECK constraint failed: t1}} |
359 do_test check-6.13 { | 402 do_test check-6.13 { |
360 execsql {SELECT * FROM t1} | 403 execsql {SELECT * FROM t1} |
361 } {3 12.0 2 20.0} | 404 } {3 12.0 2 20.0} |
362 do_test check-6.14 { | 405 do_test check-6.14 { |
363 catchsql { | 406 catchsql { |
364 INSERT OR IGNORE INTO t1 VALUES(6,7); | 407 INSERT OR IGNORE INTO t1 VALUES(6,7); |
365 } | 408 } |
366 } {0 {}} | 409 } {0 {}} |
367 do_test check-6.15 { | 410 do_test check-6.15 { |
368 execsql {SELECT * FROM t1} | 411 execsql {SELECT * FROM t1} |
369 } {3 12.0 2 20.0} | 412 } {3 12.0 2 20.0} |
370 | 413 |
371 | 414 |
372 } | 415 } |
373 | 416 |
| 417 #-------------------------------------------------------------------------- |
| 418 # If a connection opens a database that contains a CHECK constraint that |
| 419 # uses an unknown UDF, the schema should not be considered malformed. |
| 420 # Attempting to modify the table should fail (since the CHECK constraint |
| 421 # cannot be tested). |
| 422 # |
| 423 reset_db |
| 424 proc myfunc {x} {expr $x < 10} |
| 425 db func myfunc myfunc |
| 426 |
| 427 do_execsql_test 7.1 { CREATE TABLE t6(a CHECK (myfunc(a))) } |
| 428 do_execsql_test 7.2 { INSERT INTO t6 VALUES(9) } |
| 429 do_catchsql_test 7.3 { INSERT INTO t6 VALUES(11) } \ |
| 430 {1 {CHECK constraint failed: t6}} |
| 431 |
| 432 do_test 7.4 { |
| 433 sqlite3 db2 test.db |
| 434 execsql { SELECT * FROM t6 } db2 |
| 435 } {9} |
| 436 |
| 437 do_test 7.5 { |
| 438 catchsql { INSERT INTO t6 VALUES(8) } db2 |
| 439 } {1 {unknown function: myfunc()}} |
| 440 |
| 441 do_test 7.6 { |
| 442 catchsql { CREATE TABLE t7(a CHECK (myfunc(a))) } db2 |
| 443 } {1 {no such function: myfunc}} |
| 444 |
| 445 do_test 7.7 { |
| 446 db2 func myfunc myfunc |
| 447 execsql { INSERT INTO t6 VALUES(8) } db2 |
| 448 } {} |
| 449 |
| 450 do_test 7.8 { |
| 451 db2 func myfunc myfunc |
| 452 catchsql { INSERT INTO t6 VALUES(12) } db2 |
| 453 } {1 {CHECK constraint failed: t6}} |
| 454 |
| 455 # 2013-08-02: Silently ignore database name qualifiers in CHECK constraints. |
| 456 # |
| 457 do_execsql_test 8.1 { |
| 458 CREATE TABLE t810(a, CHECK( main.t810.a>0 )); |
| 459 CREATE TABLE t811(b, CHECK( xyzzy.t811.b BETWEEN 5 AND 10 )); |
| 460 } {} |
| 461 |
374 finish_test | 462 finish_test |
OLD | NEW |