diff --git a/manifest b/manifest index 9ef0f6be6d..4572e29048 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sthe\sindex7.test\sscript\sfor\stesting\spartial\sindices\swith\sWITHOUT\sROWID\ntables.\s\sFix\sbugs\sin\sANALYZE\slocated\sby\sthat\sscript. -D 2013-11-04T22:04:17.582 +C Add\sthe\sconflict2.test\sscript.\s\sFix\sissues\sdiscovered\sby\sthis\sscript. +D 2013-11-05T01:59:07.014 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -168,7 +168,7 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7 F src/btree.c 509722ce305471b626d3401c0631a808fd33237b F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0 -F src/build.c 10b7e687299ffeafd52d14f8844bf3385a0ca338 +F src/build.c 309f387dae4aa267ec0371fe69b76831d639b367 F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2 F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c @@ -182,7 +182,7 @@ F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 -F src/insert.c b89a81a5c4cfc5cf83f29751e07b45527af27dc2 +F src/insert.c 7f6a62008e0f70bac2e808977544de2272ba0160 F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b @@ -275,7 +275,7 @@ F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9 F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4 F src/trigger.c 53d6b5d50b3b23d4fcd0a36504feb5cff9aed716 -F src/update.c a804e71818927510d351e4ed14d29f75416a7a91 +F src/update.c c60e6169d7ae29a269cca03be44fb859f9ef78d9 F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269 F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918 F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179 @@ -375,7 +375,7 @@ F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91 F test/collate1.test b709989e6e6ff6e1d2bd64231c2c1d8146846c9e F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621 F test/collate3.test 79558a286362cb9ed603c6fa543f1cda7f563f0f -F test/collate4.test 031f7265c13308b724ba3c49f41cc04612bd92b1 +F test/collate4.test 1768c1f373eccbd40a519ed64e7fbfd6867290da F test/collate5.test 65d928034d30d2d263a80f6359f7549ee1598ec6 F test/collate6.test 8be65a182abaac8011a622131486dafb8076e907 F test/collate7.test 8ec29d98f3ee4ccebce6e16ce3863fb6b8c7b868 @@ -385,6 +385,7 @@ F test/collateA.test b8218ab90d1fa5c59dcf156efabb1b2599c580d6 F test/colmeta.test 087c42997754b8c648819832241daf724f813322 F test/colname.test 08948a4809d22817e0e5de89c7c0a8bd90cb551b F test/conflict.test 0b3922d2304a14a47e3ccd61bbd6824327af659b +F test/conflict2.test 73b8cfed6a04571cc79d36e55c09d79d15187201 F test/contrib01.test 2a1cbc0f2f48955d7d073f725765da6fbceda6b4 F test/corrupt.test 4aabd06cff3fe759e3e658bcc17b71789710665e F test/corrupt2.test 9c0ab4becd50e9050bc1ebb8675456a4e5587bf0 @@ -429,7 +430,7 @@ F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2 F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e F test/distinct.test 44028aaf161a5e80a2f229622b3a174d3b352810 F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376 -F test/e_createtable.test ee9b70a38369ae44360febb411976aa3c8cf2689 +F test/e_createtable.test b0dcad4160781e8fe703acee200ca455ad25fe51 F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412 F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306 @@ -460,7 +461,7 @@ F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146 F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b -F test/fkey2.test 06e0b4cc9e1b3271ae2ae6feeb19755468432111 +F test/fkey2.test c9b3a4f1e67546a92b568de59d555eaf5480ed65 F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 8a1fde4e7721ae00b05b3178888833726ca2df8d @@ -686,7 +687,7 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354 F test/minmax4.test 536a3360470633a177e42fbc19660d146b51daef -F test/misc1.test 889b40722442380a2f6575f30831b32b2372d70e +F test/misc1.test fc2e45c71d630d87382c8866ef2ca84dc0d57219 F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6 @@ -752,7 +753,7 @@ F test/rollback.test a1b4784b864331eae8b2a98c189efa2a8b11ff07 F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 F test/rowid.test f777404492adb0e00868fd706a3721328fd3af48 F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798 -F test/savepoint.test f5acd87d0c7a5f4ad6c547b47fd18c0e1aeaf048 +F test/savepoint.test e04f1ca181b706310af944146df39e2bed03cdd5 F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7 F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0 @@ -763,7 +764,7 @@ F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38 F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5 -F test/schema5.test 0103e4c0313b3725b5ae5600bdca53006ab53db3 +F test/schema5.test 9ef976783eb3d9a612aacb75690bb45975ffa812 F test/securedel.test 87a2561151af1f1e349071a89fdd77059f50113c F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5 F test/select1.test fc2a61f226a649393664ad54bc5376631801517c @@ -901,7 +902,7 @@ F test/tkt1512.test a1df1f66caf0b9122d6220c15dcee230298c2c2f F test/tkt1514.test ddef38e34fea72eb1ab935ded9f17a3fb71dd9df F test/tkt1536.test 83ff7a7b6e248016f8d682d4f7a4ae114070d466 F test/tkt1537.test e3a14332de9770be8ff14bd15c19a49cbec10808 -F test/tkt1567.test 18023cc3626a365f0118e17b66decedec93b1a6f +F test/tkt1567.test 80e7144f828b4959bc50b0bba47bf3eb87dbba10 F test/tkt1644.test 80b6a2bb17885f3cf1cb886d97cdad13232bb869 F test/tkt1667.test 4700d931ed19ea3983e8e703becb28079250b460 F test/tkt1873.test 0e1b8c023050a430c2525179ed4022ddc7c31264 @@ -983,7 +984,7 @@ F test/trans2.test d5337e61de45e66b1fcbf9db833fa8c82e624b22 F test/trans3.test 373ac5183cc56be69f48ae44090e7f672939f732 F test/transitive1.test 03f532954f46cdf5608f7766bff0b0c52bf2a7cd F test/trigger1.test dc47573ac79ffe0ee3eecaa517d70d8dacbccd03 -F test/trigger2.test 834187beafd1db383af0c659cfa49b0576832816 +F test/trigger2.test 1996d775f4370044b8414505477f632e1fa24376 F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945 F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359 F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83 @@ -1000,7 +1001,7 @@ F test/tt3_checkpoint.c 415eccce672d681b297485fc20f44cdf0eac93af F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84 F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a -F test/unique.test cadb172bbd5a2e83cd644d186ccd602085e54edc +F test/unique.test 196505faa97f12ca76c1a67f526fc8daf1a74c31 F test/unixexcl.test a9870e46cc6f8390a494513d4f2bf55b5a8b3e46 F test/unordered.test ef85ac8f2f3c93ed2b9e811b684de73175fc464c F test/update.test 8bc86fd7ef1a00014f76dc6a6a7c974df4aef172 @@ -1077,10 +1078,10 @@ F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31 F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361 F test/win32longpath.test e2aafc07e6990fe86c69be22a3d1a0e210cd329b -F test/without_rowid1.test de6f9e6ea36a7e4b087e44084abed3c0456f7dfe +F test/without_rowid1.test 80f14d449a810eb33eb4735e75189c17a94910a5 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 -F test/without_rowid3.test 8ad27697fbe319d0e858b790c0ec53abf4f8617b -F test/without_rowid4.test 3c6ee0ab3d49944cb4be1b59361b693266f53083 +F test/without_rowid3.test fb9835ccccf50a9d45295206a9c3f6baaf114d55 +F test/without_rowid4.test 27594b4b47880042532afba0153dda7dc64cef9c F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688 F test/zerodamage.test 209d7ed441f44cc5299e4ebffbef06fd5aabfefd F tool/build-all-msvc.bat 1bac6adc3fdb4d9204f21d17b14be25778370e48 x @@ -1132,7 +1133,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01 F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff -P 1ea43c0f236792a3bc13e1cb330f5ff3402c2851 -R 2790af370c8f6a52d4127dc2f2cbcd12 +P 79befe3ac1f676272b78423b9aa5dac41435420e +R 766c023e71cd0186fc0f56e56f90b7bf U drh -Z b133b4e74344b0b311a15909e57836eb +Z e7978228c6b42136e19f0b3015aa0577 diff --git a/manifest.uuid b/manifest.uuid index c49d26963c..0d524b8c04 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -79befe3ac1f676272b78423b9aa5dac41435420e \ No newline at end of file +294ed33756b06375e56c41f1088d42ee48adbdc8 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 41e738cac9..56bc11c570 100644 --- a/src/build.c +++ b/src/build.c @@ -1691,8 +1691,8 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ j++; } } - assert( pIdx->nColumn==j ); - assert( pIdx->nKeyCol+n==j ); + assert( pIdx->nColumn>=pIdx->nKeyCol+n ); + assert( pIdx->nColumn>=j ); } /* Add all table columns to the PRIMARY KEY index diff --git a/src/insert.c b/src/insert.c index a6cab3e899..18522a6ce1 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1463,7 +1463,7 @@ void sqlite3GenerateConstraintChecks( ** of a WITHOUT ROWID table and there has been no change the ** primary key, then no collision is possible. The collision detection ** logic below can all be skipped. */ - if( isUpdate && pPk && pkChng==0 ){ + if( isUpdate && pPk==pIdx && pkChng==0 ){ sqlite3VdbeResolveLabel(v, addrUniqueOk); continue; } @@ -1546,26 +1546,31 @@ void sqlite3GenerateConstraintChecks( case OE_Rollback: case OE_Abort: case OE_Fail: { - int j; - StrAccum errMsg; - const char *zSep; - char *zErr; + if( pIdx->autoIndex==2 ){ + sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_PRIMARYKEY, + onError, "PRIMARY KEY must be unique", 0); + }else{ + int j; + StrAccum errMsg; + const char *zSep; + char *zErr; - sqlite3StrAccumInit(&errMsg, 0, 0, 200); - errMsg.db = db; - zSep = pIdx->nKeyCol>1 ? "columns " : "column "; - for(j=0; jnKeyCol; j++){ - char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; - sqlite3StrAccumAppend(&errMsg, zSep, -1); - zSep = ", "; - sqlite3StrAccumAppend(&errMsg, zCol, -1); + sqlite3StrAccumInit(&errMsg, 0, 0, 200); + errMsg.db = db; + zSep = pIdx->nKeyCol>1 ? "columns " : "column "; + for(j=0; jnKeyCol; j++){ + char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName; + sqlite3StrAccumAppend(&errMsg, zSep, -1); + zSep = ", "; + sqlite3StrAccumAppend(&errMsg, zCol, -1); + } + sqlite3StrAccumAppend(&errMsg, + pIdx->nKeyCol>1 ? " are not unique" : " is not unique", -1); + zErr = sqlite3StrAccumFinish(&errMsg); + sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE, + onError, zErr, 0); + sqlite3DbFree(errMsg.db, zErr); } - sqlite3StrAccumAppend(&errMsg, - pIdx->nKeyCol>1 ? " are not unique" : " is not unique", -1); - zErr = sqlite3StrAccumFinish(&errMsg); - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_UNIQUE, - onError, zErr, 0); - sqlite3DbFree(errMsg.db, zErr); break; } case OE_Ignore: { diff --git a/src/update.c b/src/update.c index 82975c6504..f7e4ec346e 100644 --- a/src/update.c +++ b/src/update.c @@ -453,7 +453,7 @@ void sqlite3Update( for(i=0; inCol; i++){ if( oldmask==0xffffffff || (i<32 && (oldmask & (1<aCol[i].colFlags & COLFLAG_PRIMKEY)!=0) + || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0 ){ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i); }else{ diff --git a/test/collate4.test b/test/collate4.test index 5ae1e7b930..bc18a03b52 100644 --- a/test/collate4.test +++ b/test/collate4.test @@ -473,7 +473,7 @@ do_test collate4-3.1 { INSERT INTO collate4t1 VALUES('abc'); INSERT INTO collate4t1 VALUES('ABC'); } -} {1 {column a is not unique}} +} {1 {PRIMARY KEY must be unique}} do_test collate4-3.2 { execsql { SELECT * FROM collate4t1; @@ -483,13 +483,13 @@ do_test collate4-3.3 { catchsql { INSERT INTO collate4t1 SELECT upper(a) FROM collate4t1; } -} {1 {column a is not unique}} +} {1 {PRIMARY KEY must be unique}} do_test collate4-3.4 { catchsql { INSERT INTO collate4t1 VALUES(1); UPDATE collate4t1 SET a = 'abc'; } -} {1 {column a is not unique}} +} {1 {PRIMARY KEY must be unique}} do_test collate4-3.5 { execsql { DROP TABLE collate4t1; diff --git a/test/conflict2.test b/test/conflict2.test new file mode 100644 index 0000000000..73e41a376d --- /dev/null +++ b/test/conflict2.test @@ -0,0 +1,822 @@ +# 2013-11-04 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# May you do good and not evil. +# May you find forgiveness for yourself and forgive others. +# May you share freely, never taking more than you give. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. +# +# This file implements tests for the conflict resolution extension +# in WITHOUT ROWID tables +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable !conflict { + finish_test + return +} + +# Create tables for the first group of tests. +# +do_test conflict2-1.0 { + execsql { + CREATE TABLE t1(a, b, c, PRIMARY KEY(a,b)) WITHOUT rowid; + CREATE TABLE t2(x); + SELECT c FROM t1 ORDER BY c; + } +} {} + +# Six columns of configuration data as follows: +# +# i The reference number of the test +# cmd An INSERT or REPLACE command to execute against table t1 +# t0 True if there is an error from $cmd +# t1 Content of "c" column of t1 assuming no error in $cmd +# t2 Content of "x" column of t2 +# t3 Number of temporary files created by this test +# +foreach {i cmd t0 t1 t2 t3} { + 1 INSERT 1 {} 1 0 + 2 {INSERT OR IGNORE} 0 3 1 0 + 3 {INSERT OR REPLACE} 0 4 1 0 + 4 REPLACE 0 4 1 0 + 5 {INSERT OR FAIL} 1 {} 1 0 + 6 {INSERT OR ABORT} 1 {} 1 0 + 7 {INSERT OR ROLLBACK} 1 {} {} 0 +} { + do_test conflict2-1.$i { + set ::sqlite_opentemp_count 0 + set r0 [catch {execsql [subst { + DELETE FROM t1; + DELETE FROM t2; + INSERT INTO t1 VALUES(1,2,3); + BEGIN; + INSERT INTO t2 VALUES(1); + $cmd INTO t1 VALUES(1,2,4); + }]} r1] + catch {execsql {COMMIT}} + if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]} + set r2 [execsql {SELECT x FROM t2}] + set r3 $::sqlite_opentemp_count + list $r0 $r1 $r2 $r3 + } [list $t0 $t1 $t2 $t3] +} + +# Create tables for the first group of tests. +# +do_test conflict2-2.0 { + execsql { + DROP TABLE t1; + DROP TABLE t2; + CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, UNIQUE(a,b)) WITHOUT rowid; + CREATE TABLE t2(x); + SELECT c FROM t1 ORDER BY c; + } +} {} + +# Six columns of configuration data as follows: +# +# i The reference number of the test +# cmd An INSERT or REPLACE command to execute against table t1 +# t0 True if there is an error from $cmd +# t1 Content of "c" column of t1 assuming no error in $cmd +# t2 Content of "x" column of t2 +# +foreach {i cmd t0 t1 t2} { + 1 INSERT 1 {} 1 + 2 {INSERT OR IGNORE} 0 3 1 + 3 {INSERT OR REPLACE} 0 4 1 + 4 REPLACE 0 4 1 + 5 {INSERT OR FAIL} 1 {} 1 + 6 {INSERT OR ABORT} 1 {} 1 + 7 {INSERT OR ROLLBACK} 1 {} {} +} { + do_test conflict2-2.$i { + set r0 [catch {execsql [subst { + DELETE FROM t1; + DELETE FROM t2; + INSERT INTO t1 VALUES(1,2,3); + BEGIN; + INSERT INTO t2 VALUES(1); + $cmd INTO t1 VALUES(1,2,4); + }]} r1] + catch {execsql {COMMIT}} + if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]} + set r2 [execsql {SELECT x FROM t2}] + list $r0 $r1 $r2 + } [list $t0 $t1 $t2] +} + +# Create tables for the first group of tests. +# +do_test conflict2-3.0 { + execsql { + DROP TABLE t1; + DROP TABLE t2; + CREATE TABLE t1(a, b, c INTEGER, PRIMARY KEY(c), UNIQUE(a,b)) WITHOUT rowid; + CREATE TABLE t2(x); + SELECT c FROM t1 ORDER BY c; + } +} {} + +# Six columns of configuration data as follows: +# +# i The reference number of the test +# cmd An INSERT or REPLACE command to execute against table t1 +# t0 True if there is an error from $cmd +# t1 Content of "c" column of t1 assuming no error in $cmd +# t2 Content of "x" column of t2 +# +foreach {i cmd t0 t1 t2} { + 1 INSERT 1 {} 1 + 2 {INSERT OR IGNORE} 0 3 1 + 3 {INSERT OR REPLACE} 0 4 1 + 4 REPLACE 0 4 1 + 5 {INSERT OR FAIL} 1 {} 1 + 6 {INSERT OR ABORT} 1 {} 1 + 7 {INSERT OR ROLLBACK} 1 {} {} +} { + do_test conflict2-3.$i { + set r0 [catch {execsql [subst { + DELETE FROM t1; + DELETE FROM t2; + INSERT INTO t1 VALUES(1,2,3); + BEGIN; + INSERT INTO t2 VALUES(1); + $cmd INTO t1 VALUES(1,2,4); + }]} r1] + catch {execsql {COMMIT}} + if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]} + set r2 [execsql {SELECT x FROM t2}] + list $r0 $r1 $r2 + } [list $t0 $t1 $t2] +} + +do_test conflict2-4.0 { + execsql { + DROP TABLE t2; + CREATE TABLE t2(x); + SELECT x FROM t2; + } +} {} + +# Six columns of configuration data as follows: +# +# i The reference number of the test +# conf1 The conflict resolution algorithm on the UNIQUE constraint +# cmd An INSERT or REPLACE command to execute against table t1 +# t0 True if there is an error from $cmd +# t1 Content of "c" column of t1 assuming no error in $cmd +# t2 Content of "x" column of t2 +# +foreach {i conf1 cmd t0 t1 t2} { + 1 {} INSERT 1 {} 1 + 2 REPLACE INSERT 0 4 1 + 3 IGNORE INSERT 0 3 1 + 4 FAIL INSERT 1 {} 1 + 5 ABORT INSERT 1 {} 1 + 6 ROLLBACK INSERT 1 {} {} + 7 REPLACE {INSERT OR IGNORE} 0 3 1 + 8 IGNORE {INSERT OR REPLACE} 0 4 1 + 9 FAIL {INSERT OR IGNORE} 0 3 1 + 10 ABORT {INSERT OR REPLACE} 0 4 1 + 11 ROLLBACK {INSERT OR IGNORE } 0 3 1 +} { + do_test conflict2-4.$i { + if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"} + set r0 [catch {execsql [subst { + DROP TABLE t1; + CREATE TABLE t1(a,b,c,PRIMARY KEY(a,b) $conf1) WITHOUT rowid; + DELETE FROM t2; + INSERT INTO t1 VALUES(1,2,3); + BEGIN; + INSERT INTO t2 VALUES(1); + $cmd INTO t1 VALUES(1,2,4); + }]} r1] + catch {execsql {COMMIT}} + if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]} + set r2 [execsql {SELECT x FROM t2}] + list $r0 $r1 $r2 + } [list $t0 $t1 $t2] +} + +do_test conflict2-5.0 { + execsql { + DROP TABLE t2; + CREATE TABLE t2(x); + SELECT x FROM t2; + } +} {} + +# Six columns of configuration data as follows: +# +# i The reference number of the test +# conf1 The conflict resolution algorithm on the NOT NULL constraint +# cmd An INSERT or REPLACE command to execute against table t1 +# t0 True if there is an error from $cmd +# t1 Content of "c" column of t1 assuming no error in $cmd +# t2 Content of "x" column of t2 +# +foreach {i conf1 cmd t0 t1 t2} { + 1 {} INSERT 1 {} 1 + 2 REPLACE INSERT 0 5 1 + 3 IGNORE INSERT 0 {} 1 + 4 FAIL INSERT 1 {} 1 + 5 ABORT INSERT 1 {} 1 + 6 ROLLBACK INSERT 1 {} {} + 7 REPLACE {INSERT OR IGNORE} 0 {} 1 + 8 IGNORE {INSERT OR REPLACE} 0 5 1 + 9 FAIL {INSERT OR IGNORE} 0 {} 1 + 10 ABORT {INSERT OR REPLACE} 0 5 1 + 11 ROLLBACK {INSERT OR IGNORE} 0 {} 1 + 12 {} {INSERT OR IGNORE} 0 {} 1 + 13 {} {INSERT OR REPLACE} 0 5 1 + 14 {} {INSERT OR FAIL} 1 {} 1 + 15 {} {INSERT OR ABORT} 1 {} 1 + 16 {} {INSERT OR ROLLBACK} 1 {} {} +} { + if {$t0} {set t1 {t1.c may not be NULL}} + do_test conflict2-5.$i { + if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"} + set r0 [catch {execsql [subst { + DROP TABLE t1; + CREATE TABLE t1(a,b,c NOT NULL $conf1 DEFAULT 5); + DELETE FROM t2; + BEGIN; + INSERT INTO t2 VALUES(1); + $cmd INTO t1 VALUES(1,2,NULL); + }]} r1] + catch {execsql {COMMIT}} + if {!$r0} {set r1 [execsql {SELECT c FROM t1}]} + set r2 [execsql {SELECT x FROM t2}] + list $r0 $r1 $r2 + } [list $t0 $t1 $t2] +} + +do_test conflict2-6.0 { + execsql { + DROP TABLE t2; + CREATE TABLE t2(a,b,c); + INSERT INTO t2 VALUES(1,2,1); + INSERT INTO t2 VALUES(2,3,2); + INSERT INTO t2 VALUES(3,4,1); + INSERT INTO t2 VALUES(4,5,4); + SELECT c FROM t2 ORDER BY b; + CREATE TABLE t3(x); + INSERT INTO t3 VALUES(1); + } +} {1 2 1 4} + +# Six columns of configuration data as follows: +# +# i The reference number of the test +# conf1 The conflict resolution algorithm on the UNIQUE constraint +# cmd An UPDATE command to execute against table t1 +# t0 True if there is an error from $cmd +# t1 Content of "b" column of t1 assuming no error in $cmd +# t2 Content of "x" column of t3 +# t3 Number of temporary files for tables +# t4 Number of temporary files for statement journals +# +# Update: Since temporary table files are now opened lazily, and none +# of the following tests use large quantities of data, t3 is always 0. +# +foreach {i conf1 cmd t0 t1 t2 t3 t4} { + 1 {} UPDATE 1 {6 7 8 9} 1 0 1 + 2 REPLACE UPDATE 0 {7 6 9} 1 0 0 + 3 IGNORE UPDATE 0 {6 7 3 9} 1 0 0 + 4 FAIL UPDATE 1 {6 7 3 4} 1 0 0 + 5 ABORT UPDATE 1 {1 2 3 4} 1 0 1 + 6 ROLLBACK UPDATE 1 {1 2 3 4} 0 0 0 + 7 REPLACE {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 + 8 IGNORE {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1 + 9 FAIL {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 + 10 ABORT {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1 + 11 ROLLBACK {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 + 12 {} {UPDATE OR IGNORE} 0 {6 7 3 9} 1 0 0 + 13 {} {UPDATE OR REPLACE} 0 {7 6 9} 1 0 1 + 14 {} {UPDATE OR FAIL} 1 {6 7 3 4} 1 0 0 + 15 {} {UPDATE OR ABORT} 1 {1 2 3 4} 1 0 1 + 16 {} {UPDATE OR ROLLBACK} 1 {1 2 3 4} 0 0 0 +} { + if {$t0} {set t1 {PRIMARY KEY must be unique}} + if {[info exists TEMP_STORE] && $TEMP_STORE==3} { + set t3 0 + } else { + set t3 [expr {$t3+$t4}] + } + do_test conflict2-6.$i { + db close + sqlite3 db test.db + if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"} + execsql {pragma temp_store=file} + set ::sqlite_opentemp_count 0 + set r0 [catch {execsql [subst { + DROP TABLE t1; + CREATE TABLE t1(a,b,c, PRIMARY KEY(a) $conf1) WITHOUT rowid; + INSERT INTO t1 SELECT * FROM t2; + UPDATE t3 SET x=0; + BEGIN; + $cmd t3 SET x=1; + $cmd t1 SET b=b*2; + $cmd t1 SET a=c+5; + }]} r1] + catch {execsql {COMMIT}} + if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]} + set r2 [execsql {SELECT x FROM t3}] + list $r0 $r1 $r2 $::sqlite_opentemp_count + } [list $t0 $t1 $t2 $t3] +} + +# Test to make sure a lot of IGNOREs don't cause a stack overflow +# +do_test conflict2-7.1 { + execsql { + DROP TABLE t1; + DROP TABLE t2; + DROP TABLE t3; + CREATE TABLE t1(a PRIMARY KEY, b) without rowid; + } + for {set i 1} {$i<=50} {incr i} { + execsql "INSERT into t1 values($i,[expr {$i+1}]);" + } + execsql { + SELECT count(*), min(a), max(b) FROM t1; + } +} {50 1 51} +do_test conflict2-7.2 { + execsql { + PRAGMA count_changes=on; + UPDATE OR IGNORE t1 SET a=1000; + } +} {1} +do_test conflict2-7.2.1 { + db changes +} {1} +do_test conflict2-7.3 { + execsql { + SELECT b FROM t1 WHERE a=1000; + } +} {2} +do_test conflict2-7.4 { + execsql { + SELECT count(*) FROM t1; + } +} {50} +do_test conflict2-7.5 { + execsql { + PRAGMA count_changes=on; + UPDATE OR REPLACE t1 SET a=1001; + } +} {50} +do_test conflict2-7.5.1 { + db changes +} {50} +do_test conflict2-7.6 { + execsql { + SELECT b FROM t1 WHERE a=1001; + } +} {51} +do_test conflict2-7.7 { + execsql { + SELECT count(*) FROM t1; + } +} {1} + +# Update for version 3: A SELECT statement no longer resets the change +# counter (Test result changes from 0 to 50). +do_test conflict2-7.7.1 { + db changes +} {50} + +# Make sure the row count is right for rows that are ignored on +# an insert. +# +do_test conflict2-8.1 { + execsql { + DELETE FROM t1; + INSERT INTO t1 VALUES(1,2); + } + execsql { + INSERT OR IGNORE INTO t1 VALUES(2,3); + } +} {1} +do_test conflict2-8.1.1 { + db changes +} {1} +do_test conflict2-8.2 { + execsql { + INSERT OR IGNORE INTO t1 VALUES(2,4); + } +} {0} +do_test conflict2-8.2.1 { + db changes +} {0} +do_test conflict2-8.3 { + execsql { + INSERT OR REPLACE INTO t1 VALUES(2,4); + } +} {1} +do_test conflict2-8.3.1 { + db changes +} {1} +do_test conflict2-8.4 { + execsql { + INSERT OR IGNORE INTO t1 SELECT * FROM t1; + } +} {0} +do_test conflict2-8.4.1 { + db changes +} {0} +do_test conflict2-8.5 { + execsql { + INSERT OR IGNORE INTO t1 SELECT a+2,b+2 FROM t1; + } +} {2} +do_test conflict2-8.5.1 { + db changes +} {2} +do_test conflict2-8.6 { + execsql { + INSERT OR IGNORE INTO t1 SELECT a+3,b+3 FROM t1; + } +} {3} +do_test conflict2-8.6.1 { + db changes +} {3} + +integrity_check conflict2-8.99 + +do_test conflict2-9.1 { + execsql { + PRAGMA count_changes=0; + CREATE TABLE t2( + a INTEGER PRIMARY KEY ON CONFLICT IGNORE, + b INTEGER UNIQUE ON CONFLICT FAIL, + c INTEGER UNIQUE ON CONFLICT REPLACE, + d INTEGER UNIQUE ON CONFLICT ABORT, + e INTEGER UNIQUE ON CONFLICT ROLLBACK + ) WITHOUT rowid; + CREATE TABLE t3(x); + INSERT INTO t3 VALUES(1); + SELECT * FROM t3; + } +} {1} +do_test conflict2-9.2 { + catchsql { + INSERT INTO t2 VALUES(1,1,1,1,1); + INSERT INTO t2 VALUES(2,2,2,2,2); + SELECT * FROM t2; + } +} {0 {1 1 1 1 1 2 2 2 2 2}} +do_test conflict2-9.3 { + catchsql { + INSERT INTO t2 VALUES(1,3,3,3,3); + SELECT * FROM t2; + } +} {0 {1 1 1 1 1 2 2 2 2 2}} +do_test conflict2-9.4 { + catchsql { + UPDATE t2 SET a=a+1 WHERE a=1; + SELECT * FROM t2; + } +} {0 {1 1 1 1 1 2 2 2 2 2}} +do_test conflict2-9.5 { + catchsql { + INSERT INTO t2 VALUES(3,1,3,3,3); + } +} {1 {column b is not unique}} +do_test conflict2-9.5b { + db eval {SELECT * FROM t2;} +} {1 1 1 1 1 2 2 2 2 2} +do_test conflict2-9.6 { + catchsql { + UPDATE t2 SET b=b+1 WHERE b=1; + SELECT * FROM t2; + } +} {1 {column b is not unique}} +do_test conflict2-9.6b { + db eval {SELECT * FROM t2;} +} {1 1 1 1 1 2 2 2 2 2} +do_test conflict2-9.7 { + catchsql { + BEGIN; + UPDATE t3 SET x=x+1; + INSERT INTO t2 VALUES(3,1,3,3,3); + SELECT * FROM t2; + } +} {1 {column b is not unique}} +do_test conflict2-9.8 { + execsql {COMMIT} + execsql {SELECT * FROM t3} +} {2} +do_test conflict2-9.9 { + catchsql { + BEGIN; + UPDATE t3 SET x=x+1; + UPDATE t2 SET b=b+1 WHERE b=1; + SELECT * FROM t2; + } +} {1 {column b is not unique}} +do_test conflict2-9.10 { + execsql {COMMIT} + execsql {SELECT * FROM t3} +} {3} +do_test conflict2-9.11 { + catchsql { + INSERT INTO t2 VALUES(3,3,3,1,3); + SELECT * FROM t2; + } +} {1 {column d is not unique}} +do_test conflict2-9.12 { + catchsql { + UPDATE t2 SET d=d+1 WHERE d=1; + SELECT * FROM t2; + } +} {1 {column d is not unique}} +do_test conflict2-9.13 { + catchsql { + BEGIN; + UPDATE t3 SET x=x+1; + INSERT INTO t2 VALUES(3,3,3,1,3); + SELECT * FROM t2; + } +} {1 {column d is not unique}} +do_test conflict2-9.14 { + execsql {COMMIT} + execsql {SELECT * FROM t3} +} {4} +do_test conflict2-9.15 { + catchsql { + BEGIN; + UPDATE t3 SET x=x+1; + UPDATE t2 SET d=d+1 WHERE d=1; + SELECT * FROM t2; + } +} {1 {column d is not unique}} +do_test conflict2-9.16 { + execsql {COMMIT} + execsql {SELECT * FROM t3} +} {5} +do_test conflict2-9.17 { + catchsql { + INSERT INTO t2 VALUES(3,3,3,3,1); + SELECT * FROM t2; + } +} {1 {column e is not unique}} +do_test conflict2-9.18 { + catchsql { + UPDATE t2 SET e=e+1 WHERE e=1; + SELECT * FROM t2; + } +} {1 {column e is not unique}} +do_test conflict2-9.19 { + catchsql { + BEGIN; + UPDATE t3 SET x=x+1; + INSERT INTO t2 VALUES(3,3,3,3,1); + SELECT * FROM t2; + } +} {1 {column e is not unique}} +verify_ex_errcode conflict2-9.21b SQLITE_CONSTRAINT_UNIQUE +do_test conflict2-9.20 { + catch {execsql {COMMIT}} + execsql {SELECT * FROM t3} +} {5} +do_test conflict2-9.21 { + catchsql { + BEGIN; + UPDATE t3 SET x=x+1; + UPDATE t2 SET e=e+1 WHERE e=1; + SELECT * FROM t2; + } +} {1 {column e is not unique}} +verify_ex_errcode conflict2-9.21b SQLITE_CONSTRAINT_UNIQUE +do_test conflict2-9.22 { + catch {execsql {COMMIT}} + execsql {SELECT * FROM t3} +} {5} +do_test conflict2-9.23 { + catchsql { + INSERT INTO t2 VALUES(3,3,1,3,3); + SELECT * FROM t2; + } +} {0 {2 2 2 2 2 3 3 1 3 3}} +do_test conflict2-9.24 { + catchsql { + UPDATE t2 SET c=c-1 WHERE c=2; + SELECT * FROM t2; + } +} {0 {2 2 1 2 2}} +do_test conflict2-9.25 { + catchsql { + BEGIN; + UPDATE t3 SET x=x+1; + INSERT INTO t2 VALUES(3,3,1,3,3); + SELECT * FROM t2; + } +} {0 {3 3 1 3 3}} +do_test conflict2-9.26 { + catch {execsql {COMMIT}} + execsql {SELECT * FROM t3} +} {6} + +do_test conflict2-10.1 { + catchsql { + DELETE FROM t1; + BEGIN; + INSERT OR ROLLBACK INTO t1 VALUES(1,2); + INSERT OR ROLLBACK INTO t1 VALUES(1,3); + COMMIT; + } + execsql {SELECT * FROM t1} +} {} +do_test conflict2-10.2 { + catchsql { + CREATE TABLE t4(x); + CREATE UNIQUE INDEX t4x ON t4(x); + BEGIN; + INSERT OR ROLLBACK INTO t4 VALUES(1); + INSERT OR ROLLBACK INTO t4 VALUES(1); + COMMIT; + } + execsql {SELECT * FROM t4} +} {} + +# Ticket #1171. Make sure statement rollbacks do not +# damage the database. +# +do_test conflict2-11.1 { + execsql { + -- Create a database object (pages 2, 3 of the file) + BEGIN; + CREATE TABLE abc(a PRIMARY KEY, b, c) WITHOUT rowid; + INSERT INTO abc VALUES(1, 2, 3); + INSERT INTO abc VALUES(4, 5, 6); + INSERT INTO abc VALUES(7, 8, 9); + COMMIT; + } + + + # Set a small cache size so that changes will spill into + # the database file. + execsql { + PRAGMA cache_size = 10; + } + + # Make lots of changes. Because of the small cache, some + # (most?) of these changes will spill into the disk file. + # In other words, some of the changes will not be held in + # cache. + # + execsql { + BEGIN; + -- Make sure the pager is in EXCLUSIVE state. + CREATE TABLE def(d, e, f); + INSERT INTO def VALUES + ('xxxxxxxxxxxxxxx', 'yyyyyyyyyyyyyyyy', 'zzzzzzzzzzzzzzzz'); + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + DELETE FROM abc WHERE a = 4; + } + + # Execute a statement that does a statement rollback due to + # a constraint failure. + # + catchsql { + INSERT INTO abc SELECT 10, 20, 30 FROM def; + } + + # Rollback the database. Verify that the state of the ABC table + # is unchanged from the beginning of the transaction. In other words, + # make sure the DELETE on table ABC that occurred within the transaction + # had no effect. + # + execsql { + ROLLBACK; + SELECT * FROM abc; + } +} {1 2 3 4 5 6 7 8 9} +integrity_check conflict2-11.2 + +# Repeat test conflict2-11.1 but this time commit. +# +do_test conflict2-11.3 { + execsql { + BEGIN; + -- Make sure the pager is in EXCLUSIVE state. + UPDATE abc SET a=a+1; + CREATE TABLE def(d, e, f); + INSERT INTO def VALUES + ('xxxxxxxxxxxxxxx', 'yyyyyyyyyyyyyyyy', 'zzzzzzzzzzzzzzzz'); + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + DELETE FROM abc WHERE a = 4; + } + catchsql { + INSERT INTO abc SELECT 10, 20, 30 FROM def; + } + execsql { + ROLLBACK; + SELECT * FROM abc; + } +} {1 2 3 4 5 6 7 8 9} +# Repeat test conflict2-11.1 but this time commit. +# +do_test conflict2-11.5 { + execsql { + BEGIN; + -- Make sure the pager is in EXCLUSIVE state. + CREATE TABLE def(d, e, f); + INSERT INTO def VALUES + ('xxxxxxxxxxxxxxx', 'yyyyyyyyyyyyyyyy', 'zzzzzzzzzzzzzzzz'); + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + INSERT INTO def SELECT * FROM def; + DELETE FROM abc WHERE a = 4; + } + catchsql { + INSERT INTO abc SELECT 10, 20, 30 FROM def; + } + execsql { + COMMIT; + SELECT * FROM abc; + } +} {1 2 3 7 8 9} +integrity_check conflict2-11.6 + +# Make sure UPDATE OR REPLACE works on tables that have only +# an INTEGER PRIMARY KEY. +# +do_test conflict2-12.1 { + execsql { + CREATE TABLE t5(a INTEGER PRIMARY KEY, b text) WITHOUT rowid; + INSERT INTO t5 VALUES(1,'one'); + INSERT INTO t5 VALUES(2,'two'); + SELECT * FROM t5 + } +} {1 one 2 two} +do_test conflict2-12.2 { + execsql { + UPDATE OR IGNORE t5 SET a=a+1 WHERE a=1; + SELECT * FROM t5; + } +} {1 one 2 two} +do_test conflict2-12.3 { + catchsql { + UPDATE t5 SET a=a+1 WHERE a=1; + } +} {1 {PRIMARY KEY must be unique}} +verify_ex_errcode conflict2-12.3b SQLITE_CONSTRAINT_PRIMARYKEY +do_test conflict2-12.4 { + execsql { + UPDATE OR REPLACE t5 SET a=a+1 WHERE a=1; + SELECT * FROM t5; + } +} {2 one} + + +# Ticket [c38baa3d969eab7946dc50ba9d9b4f0057a19437] +# REPLACE works like ABORT on a CHECK constraint. +# +do_test conflict2-13.1 { + execsql { + CREATE TABLE t13(a PRIMARY KEY CHECK(a!=2)) WITHOUT rowid; + BEGIN; + REPLACE INTO t13 VALUES(1); + } + catchsql { + REPLACE INTO t13 VALUES(2); + } +} {1 {constraint failed}} +verify_ex_errcode conflict2-13.1b SQLITE_CONSTRAINT_CHECK +do_test conflict2-13.2 { + execsql { + REPLACE INTO t13 VALUES(3); + COMMIT; + SELECT * FROM t13; + } +} {1 3} + + +finish_test diff --git a/test/e_createtable.test b/test/e_createtable.test index b231cee804..69db2201d8 100644 --- a/test/e_createtable.test +++ b/test/e_createtable.test @@ -1182,7 +1182,7 @@ do_execsql_test 4.3.0 { INSERT INTO t2 VALUES(X'ABCDEF', 'three'); } {} -do_createtable_tests 4.3.1 -error { %s not unique } { +do_createtable_tests 4.3.1 -error {PRIMARY KEY must be unique} { 1 "INSERT INTO t1 VALUES(0, 0)" {"column x is"} 2 "INSERT INTO t1 VALUES(45.5, 'abc')" {"column x is"} 3 "INSERT INTO t1 VALUES(0.0, 'abc')" {"column x is"} @@ -1208,7 +1208,7 @@ do_createtable_tests 4.3.2 { 9 "INSERT INTO t2 VALUES('brambles', 'abc')" {} 10 "INSERT INTO t2 VALUES(X'ABCDEF', 'abc')" {} } -do_createtable_tests 4.3.3 -error { %s not unique } { +do_createtable_tests 4.3.3 -error {PRIMARY KEY must be unique} { 1 "UPDATE t1 SET x=0 WHERE y='two'" {"column x is"} 2 "UPDATE t1 SET x='brambles' WHERE y='three'" {"column x is"} 3 "UPDATE t1 SET x=45.5 WHERE y='zero'" {"column x is"} @@ -1537,12 +1537,12 @@ do_execsql_test 4.15.0 { } foreach {tn tbl res ac data} { - 1 t1_ab {1 {column a is not unique}} 0 {1 one 2 two 3 three} - 2 t1_ro {1 {column a is not unique}} 1 {1 one 2 two} - 3 t1_fa {1 {column a is not unique}} 0 {1 one 2 two 3 three 4 string} + 1 t1_ab {1 {PRIMARY KEY must be unique}} 0 {1 one 2 two 3 three} + 2 t1_ro {1 {PRIMARY KEY must be unique}} 1 {1 one 2 two} + 3 t1_fa {1 {PRIMARY KEY must be unique}} 0 {1 one 2 two 3 three 4 string} 4 t1_ig {0 {}} 0 {1 one 2 two 3 three 4 string 6 string} 5 t1_re {0 {}} 0 {1 one 2 two 4 string 3 string 6 string} - 6 t1_xx {1 {column a is not unique}} 0 {1 one 2 two 3 three} + 6 t1_xx {1 {PRIMARY KEY must be unique}} 0 {1 one 2 two 3 three} } { catchsql COMMIT do_execsql_test 4.15.$tn.1 "BEGIN; INSERT INTO $tbl VALUES(3, 'three')" @@ -1747,16 +1747,16 @@ do_execsql_test 5.4.3 { do_catchsql_test 5.4.4.1 { INSERT INTO t6 VALUES(2) -} {1 {column pk is not unique}} +} {1 {PRIMARY KEY must be unique}} do_catchsql_test 5.4.4.2 { INSERT INTO t7 VALUES(2) -} {1 {column pk is not unique}} +} {1 {PRIMARY KEY must be unique}} do_catchsql_test 5.4.4.3 { INSERT INTO t8 VALUES(2) -} {1 {column pk is not unique}} +} {1 {PRIMARY KEY must be unique}} do_catchsql_test 5.4.4.4 { INSERT INTO t9 VALUES(2) -} {1 {column pk is not unique}} +} {1 {PRIMARY KEY must be unique}} # EVIDENCE-OF: R-56094-57830 the following three table declarations all # cause the column "x" to be an alias for the rowid (an integer primary diff --git a/test/fkey2.test b/test/fkey2.test index 3e5b27c1e6..fea77f963e 100644 --- a/test/fkey2.test +++ b/test/fkey2.test @@ -375,7 +375,7 @@ fkey2-2-test 65 1 "INSERT INTO leaf VALUES('b', 2)" fkey2-2-test 66 1 "INSERT INTO leaf VALUES('c', 1)" do_test fkey2-2-test-67 { catchsql "INSERT INTO node SELECT parent, 3 FROM leaf" -} {1 {column nodeid is not unique}} +} {1 {PRIMARY KEY must be unique}} fkey2-2-test 68 0 "COMMIT" FKV fkey2-2-test 69 1 "INSERT INTO node VALUES(1, NULL)" fkey2-2-test 70 0 "INSERT INTO node VALUES(2, NULL)" diff --git a/test/misc1.test b/test/misc1.test index 188a2837ba..9863da0741 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -235,7 +235,7 @@ do_test misc1-7.4 { catchsql { INSERT INTO t5 VALUES(1,2,4); } -} {1 {columns a, b are not unique}} +} {1 {PRIMARY KEY must be unique}} do_test misc1-7.5 { catchsql { INSERT INTO t5 VALUES(0,2,4); diff --git a/test/savepoint.test b/test/savepoint.test index 015d97fe1a..9fdc9da608 100644 --- a/test/savepoint.test +++ b/test/savepoint.test @@ -858,7 +858,7 @@ do_test savepoint-12.2 { SAVEPOINT sp2; INSERT OR ROLLBACK INTO t4 VALUES(1, 'one'); } -} {1 {column a is not unique}} +} {1 {PRIMARY KEY must be unique}} do_test savepoint-12.3 { sqlite3_get_autocommit db } {1} diff --git a/test/schema5.test b/test/schema5.test index 6dea5e8f5f..b3904cf6c6 100644 --- a/test/schema5.test +++ b/test/schema5.test @@ -30,7 +30,7 @@ do_test schema5-1.1 { } {1 2 3} do_test schema5-1.2 { catchsql {INSERT INTO t1 VALUES(1,3,4);} -} {1 {column a is not unique}} +} {1 {PRIMARY KEY must be unique}} do_test schema5-1.3 { db eval { DROP TABLE t1; @@ -60,7 +60,7 @@ do_test schema5-1.6 { } {1 {column a is not unique}} do_test schema5-1.7 { catchsql {INSERT INTO t1 VALUES(10,2,3)} -} {1 {columns b, c are not unique}} +} {1 {PRIMARY KEY must be unique}} diff --git a/test/tkt1567.test b/test/tkt1567.test index 6c4548a314..ba928ee721 100644 --- a/test/tkt1567.test +++ b/test/tkt1567.test @@ -40,7 +40,7 @@ do_test tkt1567-1.4 { catchsql { UPDATE t1 SET a = CASE WHEN rowid<90 THEN substr(a,1,10) ELSE '9999' END; } -} {1 {column a is not unique}} +} {1 {PRIMARY KEY must be unique}} do_test tkt1567-1.5 { execsql { COMMIT; @@ -48,4 +48,35 @@ do_test tkt1567-1.5 { } {} integrity_check tkt1567-1.6 +do_test tkt1567-2.1 { + execsql { + CREATE TABLE t2(a TEXT PRIMARY KEY, rowid INT) WITHOUT rowid; + } + set bigstr abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ + for {set i 0} {$i<100} {incr i} { + set x [format %5d [expr $i*2]] + set sql "INSERT INTO t2 VALUES('$x-$bigstr', $i+1)" + execsql $sql + } +} {} +integrity_check tkt1567-2.2 + +do_test tkt1567-2.3 { + execsql { + BEGIN; + UPDATE t2 SET a = a||'x' WHERE rowid%2==0; + } +} {} +do_test tkt1567-2.4 { + catchsql { + UPDATE t2 SET a = CASE WHEN rowid<90 THEN substr(a,1,10) ELSE '9999' END; + } +} {1 {PRIMARY KEY must be unique}} +do_test tkt1567-2.5 { + execsql { + COMMIT; + } +} {} +integrity_check tkt1567-2.6 + finish_test diff --git a/test/trigger2.test b/test/trigger2.test index b4b922a5ee..f5a869e627 100644 --- a/test/trigger2.test +++ b/test/trigger2.test @@ -497,7 +497,7 @@ ifcapable conflict { catchsql { INSERT OR ABORT INTO tbl values (2, 2, 3); } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test trigger2-6.1c { execsql { SELECT * from tbl; @@ -507,7 +507,7 @@ ifcapable conflict { catchsql { INSERT OR FAIL INTO tbl values (2, 2, 3); } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test trigger2-6.1e { execsql { SELECT * from tbl; @@ -523,7 +523,7 @@ ifcapable conflict { catchsql { INSERT OR ROLLBACK INTO tbl values (3, 2, 3); } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test trigger2-6.1h { execsql { SELECT * from tbl; @@ -551,7 +551,7 @@ ifcapable conflict { catchsql { UPDATE OR ABORT tbl SET a = 4 WHERE a = 1; } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test trigger2-6.2c { execsql { SELECT * from tbl; @@ -561,7 +561,7 @@ ifcapable conflict { catchsql { UPDATE OR FAIL tbl SET a = 4 WHERE a = 1; } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test trigger2-6.2e { execsql { SELECT * from tbl; @@ -583,7 +583,7 @@ ifcapable conflict { catchsql { UPDATE OR ROLLBACK tbl SET a = 4 WHERE a = 1; } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test trigger2-6.2h { execsql { SELECT * from tbl; diff --git a/test/unique.test b/test/unique.test index eac19b59e0..2c30bbc8b7 100644 --- a/test/unique.test +++ b/test/unique.test @@ -47,8 +47,8 @@ do_test unique-1.3 { catchsql { INSERT INTO t1(a,b,c) VALUES(1,3,4) } -} {1 {column a is not unique}} -verify_ex_errcode unique-1.3b SQLITE_CONSTRAINT_UNIQUE +} {1 {PRIMARY KEY must be unique}} +verify_ex_errcode unique-1.3b SQLITE_CONSTRAINT_PRIMARYKEY do_test unique-1.4 { execsql { SELECT * FROM t1 ORDER BY a; diff --git a/test/without_rowid1.test b/test/without_rowid1.test index 70948592b4..3d2f7f22e3 100644 --- a/test/without_rowid1.test +++ b/test/without_rowid1.test @@ -52,7 +52,7 @@ do_test without_rowid1-1.21 { catchsql { INSERT INTO t1 VALUES('dynamic','phone','flipper','harvard'); } -} {1 {columns c, a are not unique}} +} {1 {PRIMARY KEY must be unique}} # REPLACE INTO works, however. # diff --git a/test/without_rowid3.test b/test/without_rowid3.test index 550f318ccb..f5cf91bd4c 100644 --- a/test/without_rowid3.test +++ b/test/without_rowid3.test @@ -375,7 +375,7 @@ without_rowid3-2-test 65 1 "INSERT INTO leaf VALUES('b', 2)" without_rowid3-2-test 66 1 "INSERT INTO leaf VALUES('c', 1)" do_test without_rowid3-2-test-67 { catchsql "INSERT INTO node SELECT parent, 3 FROM leaf" -} {1 {column nodeid is not unique}} +} {1 {PRIMARY KEY must be unique}} without_rowid3-2-test 68 0 "COMMIT" FKV without_rowid3-2-test 69 1 "INSERT INTO node VALUES(1, NULL)" without_rowid3-2-test 70 0 "INSERT INTO node VALUES(2, NULL)" diff --git a/test/without_rowid4.test b/test/without_rowid4.test index 6c8fdb49bc..be2a0f4738 100644 --- a/test/without_rowid4.test +++ b/test/without_rowid4.test @@ -502,7 +502,7 @@ ifcapable conflict { catchsql { INSERT OR ABORT INTO tbl values (2, 2, 3); } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test without_rowid4-6.1c { execsql { SELECT * from tbl; @@ -512,7 +512,7 @@ ifcapable conflict { catchsql { INSERT OR FAIL INTO tbl values (2, 2, 3); } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test without_rowid4-6.1e { execsql { SELECT * from tbl; @@ -528,7 +528,7 @@ ifcapable conflict { catchsql { INSERT OR ROLLBACK INTO tbl values (3, 2, 3); } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test without_rowid4-6.1h { execsql { SELECT * from tbl; @@ -556,7 +556,7 @@ ifcapable conflict { catchsql { UPDATE OR ABORT tbl SET a = 4 WHERE a = 1; } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test without_rowid4-6.2c { execsql { SELECT * from tbl; @@ -566,7 +566,7 @@ ifcapable conflict { catchsql { UPDATE OR FAIL tbl SET a = 4 WHERE a = 1; } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test without_rowid4-6.2e { execsql { SELECT * from tbl; @@ -588,7 +588,7 @@ ifcapable conflict { catchsql { UPDATE OR ROLLBACK tbl SET a = 4 WHERE a = 1; } - } {1 {column a is not unique}} + } {1 {PRIMARY KEY must be unique}} do_test without_rowid4-6.2h { execsql { SELECT * from tbl;