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