From 580d7dc71d0a5f820df8062d76e8b27590ff5fcc Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 9 Jul 2013 15:56:44 +0000 Subject: [PATCH 1/5] Adjust the costs in the xBestIndex function of the spellfix1 virtual table to force the use of the MATCH term if it is available. FossilOrigin-Name: f003bea9fe1b79e2b4d18fbef86c1d8f0f60e4b6 --- ext/misc/spellfix.c | 4 ++-- manifest | 12 ++++++------ manifest.uuid | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/misc/spellfix.c b/ext/misc/spellfix.c index eb5442ed2f..7d4f5e9870 100644 --- a/ext/misc/spellfix.c +++ b/ext/misc/spellfix.c @@ -2148,10 +2148,10 @@ static int spellfix1BestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ pIdxInfo->aConstraintUsage[iDistTerm].argvIndex = idx++; pIdxInfo->aConstraintUsage[iDistTerm].omit = 1; } - pIdxInfo->estimatedCost = (double)10000; + pIdxInfo->estimatedCost = 1e5; }else{ pIdxInfo->idxNum = 0; - pIdxInfo->estimatedCost = (double)10000000; + pIdxInfo->estimatedCost = 1e50; } return SQLITE_OK; } diff --git a/manifest b/manifest index 048d682c0a..4f18895950 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Modify\sseveral\sextensions\sto\suse\sthe\snew\sexported\sfunction\snaming.\s\nFix\ssome\sshared\slibrary\scompilation\sissues. -D 2013-07-09T12:36:30.399 +C Adjust\sthe\scosts\sin\sthe\sxBestIndex\sfunction\sof\sthe\sspellfix1\svirtual\stable\nto\sforce\sthe\suse\sof\sthe\sMATCH\sterm\sif\sit\sis\savailable. +D 2013-07-09T15:56:44.605 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -114,7 +114,7 @@ F ext/misc/nextchar.c 80ba262d23238efcfcb3d72d71aa4513098e26a6 F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63 F ext/misc/regexp.c c25c65fe775f5d9801fb8573e36ebe73f2c0c2e0 F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a -F ext/misc/spellfix.c 6d7ce6105a4b7729f6c44ccdf1ab7e80d9707c02 +F ext/misc/spellfix.c 5e1d547e9a2aed13897fa91bac924333f62fd2d9 F ext/misc/vtshim.c 5fb6be7fe37659a8cbd1e16982d74cceacbc4543 F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212 F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761 @@ -1101,7 +1101,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 52a49cbc1621094b2fe2b021209b768d29e0426b f2ab8747825ab5131ffab174aa0ffe5e474f6811 -R f4d92c08ade3445d4abd0e6606f44c69 +P 1e39f85077f1f2b96c3a656c5b6334bafb005908 +R 2ea622f28aaf7cdeeb856cb215ef9fb3 U drh -Z 1ae873026565d0007b698ed53e93eb8a +Z 80087d9cff19d8b6d80e8c14572ef089 diff --git a/manifest.uuid b/manifest.uuid index b2a7e956cd..1984d58a78 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -1e39f85077f1f2b96c3a656c5b6334bafb005908 \ No newline at end of file +f003bea9fe1b79e2b4d18fbef86c1d8f0f60e4b6 \ No newline at end of file From 49afe3aaa067eb050d0e831d351683c8251cba42 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Jul 2013 03:05:14 +0000 Subject: [PATCH 2/5] Run progress callback checks less frequently in the main VDBE evaluation loop. This makes up for the extra CPU cycles used to increment the cycle counter for SQLITE_STMTSTATUS_VM_STEP. FossilOrigin-Name: 3e8b02011db2f393d4850115a471709b0a88594f --- manifest | 14 ++++----- manifest.uuid | 2 +- src/vdbe.c | 72 ++++++++++++++++++++++++---------------------- test/progress.test | 2 +- 4 files changed, 47 insertions(+), 43 deletions(-) diff --git a/manifest b/manifest index 4f18895950..abe4d511cf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Adjust\sthe\scosts\sin\sthe\sxBestIndex\sfunction\sof\sthe\sspellfix1\svirtual\stable\nto\sforce\sthe\suse\sof\sthe\sMATCH\sterm\sif\sit\sis\savailable. -D 2013-07-09T15:56:44.605 +C Run\sprogress\scallback\schecks\sless\sfrequently\sin\sthe\smain\sVDBE\sevaluation\nloop.\s\sThis\smakes\sup\sfor\sthe\sextra\sCPU\scycles\sused\sto\sincrement\sthe\scycle\ncounter\sfor\sSQLITE_STMTSTATUS_VM_STEP. +D 2013-07-10T03:05:14.910 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -277,7 +277,7 @@ F src/update.c 8e76c3d03e4b7b21cb250bd2df0c05e12993e577 F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9 F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8 -F src/vdbe.c 2e3fc618ff964cd559844fdbf186fdc582b66b1e +F src/vdbe.c b4d29f875ff2c8506783c6831b2d539cdeb39b91 F src/vdbe.h b52887278cb173e66188da84dfab216bea61119d F src/vdbeInt.h aa185c6df4f2b5ec9896cdb5f96789af1ef69f76 F src/vdbeapi.c e3ad4cddb713a387527f982e79d9e001a0dbffa5 @@ -715,7 +715,7 @@ F test/permutations.test 461ef4ea10db02cd421dfe5f988eac3e99b5cd9a F test/pragma.test 5e7de6c32a5d764f09437d2025f07e4917b9e178 F test/pragma2.test 3a55f82b954242c642f8342b17dffc8b47472947 F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552 -F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 +F test/progress.test 552dc1edc37333a8d3098b8c26a2b7f06f5799d7 F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc F test/quick.test 1681febc928d686362d50057c642f77a02c62e57 F test/quota-glob.test 32901e9eed6705d68ca3faee2a06b73b57cb3c26 @@ -1101,7 +1101,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 1e39f85077f1f2b96c3a656c5b6334bafb005908 -R 2ea622f28aaf7cdeeb856cb215ef9fb3 +P f003bea9fe1b79e2b4d18fbef86c1d8f0f60e4b6 +R 04afd42ac3962714b1d32f16a2fdd2ad U drh -Z 80087d9cff19d8b6d80e8c14572ef089 +Z 82045c2120955e8475cc20915ea24bea diff --git a/manifest.uuid b/manifest.uuid index 1984d58a78..655deedd5a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -f003bea9fe1b79e2b4d18fbef86c1d8f0f60e4b6 \ No newline at end of file +3e8b02011db2f393d4850115a471709b0a88594f \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index f539b400a9..9a56518c57 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -552,12 +552,11 @@ int sqlite3VdbeExec( sqlite3 *db = p->db; /* The database */ u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */ u8 encoding = ENC(db); /* The database encoding */ -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - int checkProgress; /* True if progress callbacks are enabled */ - int nProgressOps = 0; /* Opcodes executed since progress callback. */ -#endif int iCompare = 0; /* Result of last OP_Compare operation */ unsigned nVmStep = 0; /* Number of virtual machine steps */ +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + unsigned nProgressOps = 0; /* nVmStep at last progress callback. */ +#endif Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn2 = 0; /* 2nd input operand */ @@ -586,9 +585,6 @@ int sqlite3VdbeExec( db->busyHandler.nBusy = 0; CHECK_FOR_INTERRUPT; sqlite3VdbeIOTraceSql(p); -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - checkProgress = db->xProgress!=0; -#endif #ifdef SQLITE_DEBUG sqlite3BeginBenignMalloc(); if( p->pc==0 && (p->db->flags & SQLITE_VdbeListing)!=0 ){ @@ -636,27 +632,6 @@ int sqlite3VdbeExec( } #endif -#ifndef SQLITE_OMIT_PROGRESS_CALLBACK - /* Call the progress callback if it is configured and the required number - ** of VDBE ops have been executed (either since this invocation of - ** sqlite3VdbeExec() or since last time the progress callback was called). - ** If the progress callback returns non-zero, exit the virtual machine with - ** a return code SQLITE_ABORT. - */ - if( checkProgress ){ - if( db->nProgressOps==nProgressOps ){ - int prc; - prc = db->xProgress(db->pProgressArg); - if( prc!=0 ){ - rc = SQLITE_INTERRUPT; - goto vdbe_error_halt; - } - nProgressOps = 0; - } - nProgressOps++; - } -#endif - /* On any opcode with the "out2-prerelease" tag, free any ** external allocations out of mem[p2] and set mem[p2] to be ** an undefined integer. Opcodes will either fill in the integer @@ -749,8 +724,38 @@ int sqlite3VdbeExec( ** the program. */ case OP_Goto: { /* jump */ - CHECK_FOR_INTERRUPT; pc = pOp->p2 - 1; + + /* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev, + ** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon + ** completion. Check to see if sqlite3_interrupt() has been called + ** or if the progress callback needs to be invoked. + ** + ** This code uses unstructured "goto" statements and does not look clean. + ** But that is not due to sloppy coding habits. The code is written this + ** way for performance, to avoid having to run the interrupt and progress + ** checks on every opcode. This helps sqlite3_step() to run about 1.5% + ** faster according to "valgrind --tool=cachegrind" */ +check_for_interrupt: + CHECK_FOR_INTERRUPT; +#ifndef SQLITE_OMIT_PROGRESS_CALLBACK + /* Call the progress callback if it is configured and the required number + ** of VDBE ops have been executed (either since this invocation of + ** sqlite3VdbeExec() or since last time the progress callback was called). + ** If the progress callback returns non-zero, exit the virtual machine with + ** a return code SQLITE_ABORT. + */ + if( db->xProgress!=0 && (nVmStep - nProgressOps)>=db->nProgressOps ){ + int prc; + prc = db->xProgress(db->pProgressArg); + if( prc!=0 ){ + rc = SQLITE_INTERRUPT; + goto vdbe_error_halt; + } + nProgressOps = nVmStep; + } +#endif + break; } @@ -4502,7 +4507,6 @@ case OP_Next: { /* jump */ VdbeCursor *pC; int res; - CHECK_FOR_INTERRUPT; assert( pOp->p1>=0 && pOp->p1nCursor ); assert( pOp->p5<=ArraySize(p->aCounter) ); pC = p->apCsr[pOp->p1]; @@ -4531,7 +4535,7 @@ case OP_Next: { /* jump */ #endif } pC->rowidIsValid = 0; - break; + goto check_for_interrupt; } /* Opcode: IdxInsert P1 P2 P3 * P5 @@ -5057,7 +5061,7 @@ case OP_RowSetAdd: { /* in1, in2 */ */ case OP_RowSetRead: { /* jump, in1, out3 */ i64 val; - CHECK_FOR_INTERRUPT; + pIn1 = &aMem[pOp->p1]; if( (pIn1->flags & MEM_RowSet)==0 || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0 @@ -5069,7 +5073,7 @@ case OP_RowSetRead: { /* jump, in1, out3 */ /* A value was pulled from the index */ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val); } - break; + goto check_for_interrupt; } /* Opcode: RowSetTest P1 P2 P3 P4 @@ -5970,7 +5974,7 @@ case OP_VNext: { /* jump */ /* If there is data, jump to P2 */ pc = pOp->p2 - 1; } - break; + goto check_for_interrupt; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ diff --git a/test/progress.test b/test/progress.test index b25a100530..381f4826c8 100644 --- a/test/progress.test +++ b/test/progress.test @@ -166,7 +166,7 @@ do_test progress-1.7 { set ::res [list] db eval {SELECT a, b, c FROM abc} { lappend ::res $a $b $c - db progress 10 "expr 1" + db progress 5 "expr 1" catch {db eval {SELECT a, b, c FROM abc} { }} msg lappend ::res $msg } From 13447bf6c7c63f247e5765d19086c006a57ebae3 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Jul 2013 13:33:49 +0000 Subject: [PATCH 3/5] Experimental "PRAGMA query_only=BOOLEAN" statement that is able to turn write capabilities on and off. FossilOrigin-Name: ece960c496717a3a6c25526ef77dd76b08d607bc --- manifest | 19 +++++++++++-------- manifest.uuid | 2 +- src/pragma.c | 1 + src/sqliteInt.h | 1 + src/vdbe.c | 4 ++++ 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/manifest b/manifest index abe4d511cf..024b499450 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Run\sprogress\scallback\schecks\sless\sfrequently\sin\sthe\smain\sVDBE\sevaluation\nloop.\s\sThis\smakes\sup\sfor\sthe\sextra\sCPU\scycles\sused\sto\sincrement\sthe\scycle\ncounter\sfor\sSQLITE_STMTSTATUS_VM_STEP. -D 2013-07-10T03:05:14.910 +C Experimental\s"PRAGMA\squery_only=BOOLEAN"\sstatement\sthat\sis\sable\sto\sturn\nwrite\scapabilities\son\sand\soff. +D 2013-07-10T13:33:49.764 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -210,7 +210,7 @@ F src/parse.y 9acfcc83ddbf0cf82f0ed9582ccf0ad6c366ff37 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c d23d07716de96c7c0c2503ec5051a4384c3fb938 -F src/pragma.c 67a611bd4be0754f27ee13eb87932c3b14415862 +F src/pragma.c f91b64b84cbc3f3d2a1bbcae0d59e0a782fc67f8 F src/prepare.c 2306be166bbeddf454e18bf8b21dba8388d05328 F src/printf.c 41c49dac366a3a411190001a8ab495fa8887974e F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 @@ -221,7 +221,7 @@ F src/shell.c c8cd06e6b66250a3ea0149c4edec30de14f57b6f F src/sqlite.h.in 0a87152a6dde55381afb8f1cf37f337b2f32fd06 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h e461e0f9109ca49ad6aba52198fbe7d237c4a75b +F src/sqliteInt.h 2819a1e48805199a957570223e54e787935937d6 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -277,7 +277,7 @@ F src/update.c 8e76c3d03e4b7b21cb250bd2df0c05e12993e577 F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9 F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8 -F src/vdbe.c b4d29f875ff2c8506783c6831b2d539cdeb39b91 +F src/vdbe.c c714445b47b4f242082e97de01272f0c31c3c921 F src/vdbe.h b52887278cb173e66188da84dfab216bea61119d F src/vdbeInt.h aa185c6df4f2b5ec9896cdb5f96789af1ef69f76 F src/vdbeapi.c e3ad4cddb713a387527f982e79d9e001a0dbffa5 @@ -1101,7 +1101,10 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P f003bea9fe1b79e2b4d18fbef86c1d8f0f60e4b6 -R 04afd42ac3962714b1d32f16a2fdd2ad +P 3e8b02011db2f393d4850115a471709b0a88594f +R 2ffb7f6b213f90920cd38490a5dc43b1 +T *branch * query_only +T *sym-query_only * +T -sym-trunk * U drh -Z 82045c2120955e8475cc20915ea24bea +Z c3b9d6d6edee565b9fc4629e8b5e8b24 diff --git a/manifest.uuid b/manifest.uuid index 655deedd5a..3cbb719398 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3e8b02011db2f393d4850115a471709b0a88594f \ No newline at end of file +ece960c496717a3a6c25526ef77dd76b08d607bc \ No newline at end of file diff --git a/src/pragma.c b/src/pragma.c index 5803f6c4a5..f38e679a44 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -177,6 +177,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ { "fullfsync", SQLITE_FullFSync }, { "checkpoint_fullfsync", SQLITE_CkptFullFSync }, { "reverse_unordered_selects", SQLITE_ReverseOrder }, + { "query_only", SQLITE_QueryOnly }, #ifndef SQLITE_OMIT_AUTOMATIC_INDEX { "automatic_index", SQLITE_AutoIndex }, #endif diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5e3b4d0a0b..48a1f96ea3 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -1009,6 +1009,7 @@ struct sqlite3 { #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ +#define SQLITE_QueryOnly 0x00800000 /* Disable database changes */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the diff --git a/src/vdbe.c b/src/vdbe.c index 9a56518c57..1fa21df6d1 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2946,6 +2946,10 @@ case OP_Transaction: { assert( p->readOnly==0 || pOp->p2==0 ); assert( pOp->p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (((yDbMask)1)<p1))!=0 ); + if( pOp->p2 && (db->flags & SQLITE_QueryOnly)!=0 ){ + rc = SQLITE_READONLY; + goto abort_due_to_error; + } pBt = db->aDb[pOp->p1].pBt; if( pBt ){ From 8f8c65f79bbea1e125fe02042c57cf963288abc5 Mon Sep 17 00:00:00 2001 From: drh Date: Wed, 10 Jul 2013 18:14:29 +0000 Subject: [PATCH 4/5] Fix harmless compiler warnings in the progress callback logic. FossilOrigin-Name: 908141d5bf7a9ad8f40c2332476847733eca7fdc --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/main.c | 2 +- src/sqliteInt.h | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/manifest b/manifest index abe4d511cf..817d63dd60 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Run\sprogress\scallback\schecks\sless\sfrequently\sin\sthe\smain\sVDBE\sevaluation\nloop.\s\sThis\smakes\sup\sfor\sthe\sextra\sCPU\scycles\sused\sto\sincrement\sthe\scycle\ncounter\sfor\sSQLITE_STMTSTATUS_VM_STEP. -D 2013-07-10T03:05:14.910 +C Fix\sharmless\scompiler\swarnings\sin\sthe\sprogress\scallback\slogic. +D 2013-07-10T18:14:29.988 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -185,7 +185,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c c48f7f3f170e502fe0cc20748e03c6e0b5a016c2 -F src/main.c a1f4bb79e15c3f0a2e4efb2f52781ccbfb3010d4 +F src/main.c 97b8ebbab272ab0d97966c791956dad1921357ba F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa @@ -221,7 +221,7 @@ F src/shell.c c8cd06e6b66250a3ea0149c4edec30de14f57b6f F src/sqlite.h.in 0a87152a6dde55381afb8f1cf37f337b2f32fd06 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h e461e0f9109ca49ad6aba52198fbe7d237c4a75b +F src/sqliteInt.h df1a921448e765227de3ed8933fcc1e22bebec82 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e @@ -1101,7 +1101,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P f003bea9fe1b79e2b4d18fbef86c1d8f0f60e4b6 -R 04afd42ac3962714b1d32f16a2fdd2ad +P 3e8b02011db2f393d4850115a471709b0a88594f +R e1fccaff7bc35266cc5b7f175242cdcd U drh -Z 82045c2120955e8475cc20915ea24bea +Z 1564bfae3de8c8d60d1d15cc4d698c7c diff --git a/manifest.uuid b/manifest.uuid index 655deedd5a..193a2a3d04 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3e8b02011db2f393d4850115a471709b0a88594f \ No newline at end of file +908141d5bf7a9ad8f40c2332476847733eca7fdc \ No newline at end of file diff --git a/src/main.c b/src/main.c index 12a1ad19b6..fe30d43f2c 100644 --- a/src/main.c +++ b/src/main.c @@ -1298,7 +1298,7 @@ void sqlite3_progress_handler( sqlite3_mutex_enter(db->mutex); if( nOps>0 ){ db->xProgress = xProgress; - db->nProgressOps = nOps; + db->nProgressOps = (unsigned)nOps; db->pProgressArg = pArg; }else{ db->xProgress = 0; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5e3b4d0a0b..d1d73cd5bb 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -936,7 +936,7 @@ struct sqlite3 { #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int (*xProgress)(void *); /* The progress callback */ void *pProgressArg; /* Argument to the progress callback */ - int nProgressOps; /* Number of opcodes for progress callback */ + unsigned nProgressOps; /* Number of opcodes for progress callback */ #endif #ifndef SQLITE_OMIT_VIRTUALTABLE int nVTrans; /* Allocated size of aVTrans */ From 648e264342fe3315d23979c8779a4200babea891 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 11 Jul 2013 15:03:32 +0000 Subject: [PATCH 5/5] Add the "defer_foreign_keys" pragma and the SQLITE_DBSTATUS_DEFERRED_FKS value for sqlite3_db_status(). This is a cherry-pick of a sequence of five checkins in the sessions branch between [1d44e5d3c2] and [d39e65fe70]. FossilOrigin-Name: 527121ac3cdc96ac33ad975c227a6685a2f7e999 --- manifest | 35 ++++++++-------- manifest.uuid | 2 +- src/fkey.c | 9 +++- src/main.c | 2 + src/pragma.c | 6 ++- src/sqlite.h.in | 9 +++- src/sqliteInt.h | 3 ++ src/status.c | 10 +++++ src/test_malloc.c | 3 +- src/vdbe.c | 13 ++++-- src/vdbeInt.h | 1 + src/vdbeapi.c | 4 +- src/vdbeaux.c | 7 +++- test/fkey1.test | 3 ++ test/fkey6.test | 103 ++++++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 180 insertions(+), 30 deletions(-) create mode 100644 test/fkey6.test diff --git a/manifest b/manifest index 817d63dd60..e85691eaa3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sharmless\scompiler\swarnings\sin\sthe\sprogress\scallback\slogic. -D 2013-07-10T18:14:29.988 +C Add\sthe\s"defer_foreign_keys"\spragma\sand\sthe\sSQLITE_DBSTATUS_DEFERRED_FKS\nvalue\sfor\ssqlite3_db_status().\s\sThis\sis\sa\scherry-pick\sof\sa\ssequence\sof\sfive\ncheckins\sin\sthe\ssessions\sbranch\sbetween\s[1d44e5d3c2]\sand\s[d39e65fe70]. +D 2013-07-11T15:03:32.117 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -174,7 +174,7 @@ F src/date.c 067a81c9942c497aafd2c260e13add8a7d0c7dd4 F src/delete.c aeabdabeeeaa0584127f291baa9617153d334778 F src/expr.c 2b47ae9da6c9f34eff6736962ea2e102c6c4a755 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb -F src/fkey.c e16942bd5c8a868ac53287886464a5ed0e72b179 +F src/fkey.c 914a6bbd987d857c41ac9d244efa6641f36faadb F src/func.c 5c50c1ea31fd864b0fe921fe1a8d4c55acd609ef F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759 F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4 @@ -185,7 +185,7 @@ F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12 F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b F src/loadext.c c48f7f3f170e502fe0cc20748e03c6e0b5a016c2 -F src/main.c 97b8ebbab272ab0d97966c791956dad1921357ba +F src/main.c e5810b2d7a0bd19f3d75ce60e3ed918cafc0a3f3 F src/malloc.c fe085aa851b666b7c375c1ff957643dc20a04bf6 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645 F src/mem1.c 437c7c4af964895d4650f29881df63535caaa1fa @@ -210,7 +210,7 @@ F src/parse.y 9acfcc83ddbf0cf82f0ed9582ccf0ad6c366ff37 F src/pcache.c f8043b433a57aba85384a531e3937a804432a346 F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222 F src/pcache1.c d23d07716de96c7c0c2503ec5051a4384c3fb938 -F src/pragma.c 67a611bd4be0754f27ee13eb87932c3b14415862 +F src/pragma.c c87581d93a7518cba656b7919e32ded5d331b76a F src/prepare.c 2306be166bbeddf454e18bf8b21dba8388d05328 F src/printf.c 41c49dac366a3a411190001a8ab495fa8887974e F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 @@ -218,12 +218,12 @@ F src/resolve.c 89f9003e8316ee3a172795459efc2a0274e1d5a8 F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0 F src/select.c 91b62654caf8dfe292fb8882715e575d34ad3874 F src/shell.c c8cd06e6b66250a3ea0149c4edec30de14f57b6f -F src/sqlite.h.in 0a87152a6dde55381afb8f1cf37f337b2f32fd06 +F src/sqlite.h.in 80d11140d401f366f7249f3c4fe031c49a5a06f8 F src/sqlite3.rc fea433eb0a59f4c9393c8e6d76a6e2596b1fe0c0 F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc -F src/sqliteInt.h df1a921448e765227de3ed8933fcc1e22bebec82 +F src/sqliteInt.h 074f5cdfb99e0d4dc8100c217824f384c16af56b F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d -F src/status.c bedc37ec1a6bb9399944024d63f4c769971955a9 +F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/tclsqlite.c b8835978e853a89bf58de88acc943a5ca94d752e F src/test1.c 870fc648a48cb6d6808393174f7ebe82b8c840fa @@ -250,7 +250,7 @@ F src/test_intarray.c 87847c71c3c36889c0bcc9c4baf9d31881665d61 F src/test_intarray.h b999bb18d090b8d9d9c49d36ec37ef8f341fe169 F src/test_journal.c f5c0a05b7b3d5930db769b5ee6c3766dc2221a64 F src/test_loadext.c df586c27176e3c2cb2e099c78da67bf14379a56e -F src/test_malloc.c 2855429b8232107b3296409be2a8eb68345290c2 +F src/test_malloc.c a105801222c0514f8befa2a1712a95505cce099a F src/test_multiplex.c 5d691eeb6cb6aa7888da28eba5e62a9a857d3c0f F src/test_multiplex.h 9b63b95f07acedee425fdfe49a47197c9bf5f9d8 F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f @@ -277,11 +277,11 @@ F src/update.c 8e76c3d03e4b7b21cb250bd2df0c05e12993e577 F src/utf.c 8d819e2e5104a430fc2005f018db14347c95a38f F src/util.c f566b5138099a2df8533b190d0dcc74b7dfbe0c9 F src/vacuum.c d9c5759f4c5a438bb43c2086f72c5d2edabc36c8 -F src/vdbe.c b4d29f875ff2c8506783c6831b2d539cdeb39b91 +F src/vdbe.c 0661945edc8b8d85dccc137925c45542fad9a5a4 F src/vdbe.h b52887278cb173e66188da84dfab216bea61119d -F src/vdbeInt.h aa185c6df4f2b5ec9896cdb5f96789af1ef69f76 -F src/vdbeapi.c e3ad4cddb713a387527f982e79d9e001a0dbffa5 -F src/vdbeaux.c 9683f262c7fd0af8cb03f0053651135005cdda8a +F src/vdbeInt.h 5e666c971c555c7977714b0e34cb8d4b20282557 +F src/vdbeapi.c c88222946d657984bdaf394604cb58ed1d641460 +F src/vdbeaux.c 1633408f6dea06129441c5e2f22b2a5ce30fe97e F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69 F src/vdbemem.c 833005f1cbbf447289f1973dba2a0c2228c7b8ab F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017 @@ -452,11 +452,12 @@ F test/expr.test 67c9fd6f8f829e239dc8b0f4a08a73c08b09196d F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7 F test/filectrl.test 14fa712e42c4cb791e09dfd58a6a03efb47ef13a F test/filefmt.test cb34663f126cbc2d358af552dcaf5c72769b0146 -F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da +F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b F test/fkey2.test 06e0b4cc9e1b3271ae2ae6feeb19755468432111 F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 0bf64f2d19ad80433ca0b24edbf604a18b353d5f +F test/fkey6.test 2d76497c54db0e5bfbecee0acf00bb8a706b37db F test/fkey_malloc.test bb74c9cb8f8fceed03b58f8a7ef2df98520bbd51 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts-9fd058691.test 78b887e30ae6816df0e1fed6259de4b5a64ad33c @@ -1101,7 +1102,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac -P 3e8b02011db2f393d4850115a471709b0a88594f -R e1fccaff7bc35266cc5b7f175242cdcd +P 908141d5bf7a9ad8f40c2332476847733eca7fdc +R f701d887eba2f81d7816617ba86ca3a2 U drh -Z 1564bfae3de8c8d60d1d15cc4d698c7c +Z 50e77e8dbcbbcc008f0da119505e5900 diff --git a/manifest.uuid b/manifest.uuid index 193a2a3d04..698be2beaf 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -908141d5bf7a9ad8f40c2332476847733eca7fdc \ No newline at end of file +527121ac3cdc96ac33ad975c227a6685a2f7e999 \ No newline at end of file diff --git a/src/fkey.c b/src/fkey.c index ac35bc194c..bb59c656f6 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -422,7 +422,10 @@ static void fkLookupParent( } } - if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ + if( !pFKey->isDeferred && !(pParse->db->flags & SQLITE_DeferFKs) + && !pParse->pToplevel + && !pParse->isMultiWrite + ){ /* Special case: If this is an INSERT statement that will insert exactly ** one row into the table, raise a constraint immediately instead of ** incrementing a counter. This is necessary as the VM code is being @@ -813,7 +816,9 @@ void sqlite3FkCheck( SrcList *pSrc; int *aiCol = 0; - if( !pFKey->isDeferred && !pParse->pToplevel && !pParse->isMultiWrite ){ + if( !pFKey->isDeferred && !(db->flags & SQLITE_DeferFKs) + && !pParse->pToplevel && !pParse->isMultiWrite + ){ assert( regOld==0 && regNew!=0 ); /* Inserting a single row into a parent table cannot cause an immediate ** foreign key violation. So do nothing in this case. */ diff --git a/src/main.c b/src/main.c index fe30d43f2c..c23a6212d3 100644 --- a/src/main.c +++ b/src/main.c @@ -1037,6 +1037,8 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; + db->nDeferredImmCons = 0; + db->flags &= ~SQLITE_DeferFKs; /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ diff --git a/src/pragma.c b/src/pragma.c index 5803f6c4a5..fd0ebc727c 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -197,12 +197,13 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ /* TODO: Maybe it shouldn't be possible to change the ReadUncommitted ** flag if there are any active statements. */ { "read_uncommitted", SQLITE_ReadUncommitted }, - { "recursive_triggers", SQLITE_RecTriggers }, + { "recursive_triggers", SQLITE_RecTriggers }, /* This flag may only be set if both foreign-key and trigger support ** are present in the build. */ #if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER) - { "foreign_keys", SQLITE_ForeignKeys }, + { "foreign_keys", SQLITE_ForeignKeys }, + { "defer_foreign_keys", SQLITE_DeferFKs }, #endif }; int i; @@ -228,6 +229,7 @@ static int flagPragma(Parse *pParse, const char *zLeft, const char *zRight){ db->flags |= mask; }else{ db->flags &= ~mask; + if( mask==SQLITE_DeferFKs ) db->nDeferredImmCons = 0; } /* Many of the flag-pragmas modify the code generated by the SQL diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 87bce973a4..4d8ba21f30 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -6239,6 +6239,12 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); ** on subsequent SQLITE_DBSTATUS_CACHE_WRITE requests is undefined.)^ ^The ** highwater mark associated with SQLITE_DBSTATUS_CACHE_WRITE is always 0. ** +** +** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(
SQLITE_DBSTATUS_DEFERRED_FKS
+**
This parameter returns the zero for the current value if and only if +** there all foreign key constraints (deferred or immediate) have been +** resolved. The highwater mark is always 0. +**
** */ #define SQLITE_DBSTATUS_LOOKASIDE_USED 0 @@ -6251,7 +6257,8 @@ int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg); #define SQLITE_DBSTATUS_CACHE_HIT 7 #define SQLITE_DBSTATUS_CACHE_MISS 8 #define SQLITE_DBSTATUS_CACHE_WRITE 9 -#define SQLITE_DBSTATUS_MAX 9 /* Largest defined DBSTATUS */ +#define SQLITE_DBSTATUS_DEFERRED_FKS 10 +#define SQLITE_DBSTATUS_MAX 10 /* Largest defined DBSTATUS */ /* diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d1d73cd5bb..dcd74f91d2 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -954,6 +954,7 @@ struct sqlite3 { int nSavepoint; /* Number of non-transaction savepoints */ int nStatement; /* Number of nested statement-transactions */ i64 nDeferredCons; /* Net deferred constraints this transaction. */ + i64 nDeferredImmCons; /* Net deferred immediate constraints */ int *pnBytesFreed; /* If not NULL, increment this in DbFree() */ #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY @@ -1009,6 +1010,7 @@ struct sqlite3 { #define SQLITE_PreferBuiltin 0x00100000 /* Preference to built-in funcs */ #define SQLITE_LoadExtension 0x00200000 /* Enable load_extension */ #define SQLITE_EnableTrigger 0x00400000 /* True to enable triggers */ +#define SQLITE_DeferFKs 0x00800000 /* Defer all FK constraints */ /* ** Bits of the sqlite3.dbOptFlags field that are used by the @@ -1155,6 +1157,7 @@ struct FuncDestructor { struct Savepoint { char *zName; /* Savepoint name (nul-terminated) */ i64 nDeferredCons; /* Number of deferred fk violations */ + i64 nDeferredImmCons; /* Number of deferred imm fk. */ Savepoint *pNext; /* Parent savepoint (if any) */ }; diff --git a/src/status.c b/src/status.c index 28349e6d3d..5fcb68ddc3 100644 --- a/src/status.c +++ b/src/status.c @@ -243,6 +243,16 @@ int sqlite3_db_status( break; } + /* Set *pCurrent to non-zero if there are unresolved deferred foreign + ** key constraints. Set *pCurrent to zero if all foreign key constraints + ** have been satisfied. The *pHighwater is always set to zero. + */ + case SQLITE_DBSTATUS_DEFERRED_FKS: { + *pHighwater = 0; + *pCurrent = db->nDeferredImmCons>0 || db->nDeferredCons>0; + break; + } + default: { rc = SQLITE_ERROR; } diff --git a/src/test_malloc.c b/src/test_malloc.c index cf98a8fb21..2e31f0833d 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -1349,7 +1349,8 @@ static int test_db_status( { "LOOKASIDE_MISS_FULL", SQLITE_DBSTATUS_LOOKASIDE_MISS_FULL }, { "CACHE_HIT", SQLITE_DBSTATUS_CACHE_HIT }, { "CACHE_MISS", SQLITE_DBSTATUS_CACHE_MISS }, - { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE } + { "CACHE_WRITE", SQLITE_DBSTATUS_CACHE_WRITE }, + { "DEFERRED_FKS", SQLITE_DBSTATUS_DEFERRED_FKS } }; Tcl_Obj *pResult; if( objc!=4 ){ diff --git a/src/vdbe.c b/src/vdbe.c index 9a56518c57..104ea8b702 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -874,7 +874,7 @@ case OP_Halt: { p->rc = rc = SQLITE_BUSY; }else{ assert( rc==SQLITE_OK || (p->rc&0xff)==SQLITE_CONSTRAINT ); - assert( rc==SQLITE_OK || db->nDeferredCons>0 ); + assert( rc==SQLITE_OK || db->nDeferredCons>0 || db->nDeferredImmCons>0 ); rc = p->rc ? SQLITE_ERROR : SQLITE_DONE; } goto vdbe_return; @@ -2734,6 +2734,7 @@ case OP_Savepoint: { pNew->pNext = db->pSavepoint; db->pSavepoint = pNew; pNew->nDeferredCons = db->nDeferredCons; + pNew->nDeferredImmCons = db->nDeferredImmCons; } } }else{ @@ -2821,6 +2822,7 @@ case OP_Savepoint: { } }else{ db->nDeferredCons = pSavepoint->nDeferredCons; + db->nDeferredImmCons = pSavepoint->nDeferredImmCons; } if( !isTransaction ){ @@ -2978,6 +2980,7 @@ case OP_Transaction: { ** counter. If the statement transaction needs to be rolled back, ** the value of this counter needs to be restored too. */ p->nStmtDefCons = db->nDeferredCons; + p->nStmtDefImmCons = db->nDeferredImmCons; } } break; @@ -5287,7 +5290,9 @@ case OP_Param: { /* out2-prerelease */ ** statement counter is incremented (immediate foreign key constraints). */ case OP_FkCounter: { - if( pOp->p1 ){ + if( db->flags & SQLITE_DeferFKs ){ + db->nDeferredImmCons += pOp->p2; + }else if( pOp->p1 ){ db->nDeferredCons += pOp->p2; }else{ p->nFkConstraint += pOp->p2; @@ -5308,9 +5313,9 @@ case OP_FkCounter: { */ case OP_FkIfZero: { /* jump */ if( pOp->p1 ){ - if( db->nDeferredCons==0 ) pc = pOp->p2-1; + if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; }else{ - if( p->nFkConstraint==0 ) pc = pOp->p2-1; + if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1; } break; } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 289f83d45d..11c34fd524 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -351,6 +351,7 @@ struct Vdbe { #endif i64 nFkConstraint; /* Number of imm. FK constraints this VM */ i64 nStmtDefCons; /* Number of def. constraints when stmt started */ + i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ #ifdef SQLITE_DEBUG diff --git a/src/vdbeapi.c b/src/vdbeapi.c index efa9e96962..ad3eea13a7 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -386,7 +386,9 @@ static int sqlite3Step(Vdbe *p){ db->u1.isInterrupted = 0; } - assert( db->nVdbeWrite>0 || db->autoCommit==0 || db->nDeferredCons==0 ); + assert( db->nVdbeWrite>0 || db->autoCommit==0 + || (db->nDeferredCons==0 && db->nDeferredImmCons==0) + ); #ifndef SQLITE_OMIT_TRACE if( db->xProfile && !db->init.busy ){ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index fb8294a256..dfdf7800a4 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -2065,6 +2065,7 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ ** the statement transaction was opened. */ if( eOp==SAVEPOINT_ROLLBACK ){ db->nDeferredCons = p->nStmtDefCons; + db->nDeferredImmCons = p->nStmtDefImmCons; } } return rc; @@ -2083,7 +2084,9 @@ int sqlite3VdbeCloseStatement(Vdbe *p, int eOp){ #ifndef SQLITE_OMIT_FOREIGN_KEY int sqlite3VdbeCheckFk(Vdbe *p, int deferred){ sqlite3 *db = p->db; - if( (deferred && db->nDeferredCons>0) || (!deferred && p->nFkConstraint>0) ){ + if( (deferred && (db->nDeferredCons+db->nDeferredImmCons)>0) + || (!deferred && p->nFkConstraint>0) + ){ p->rc = SQLITE_CONSTRAINT_FOREIGNKEY; p->errorAction = OE_Abort; sqlite3SetString(&p->zErrMsg, db, "foreign key constraint failed"); @@ -2216,6 +2219,8 @@ int sqlite3VdbeHalt(Vdbe *p){ sqlite3RollbackAll(db, SQLITE_OK); }else{ db->nDeferredCons = 0; + db->nDeferredImmCons = 0; + db->flags &= ~SQLITE_DeferFKs; sqlite3CommitInternalChanges(db); } }else{ diff --git a/test/fkey1.test b/test/fkey1.test index e7c00d16d4..90a4c44409 100644 --- a/test/fkey1.test +++ b/test/fkey1.test @@ -117,5 +117,8 @@ do_test fkey1-3.4 { {0 0 t5 d {} {SET DEFAULT} CASCADE NONE} \ {0 1 t5 e {} {SET DEFAULT} CASCADE NONE} \ ] +do_test fkey1-3.5 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 0 0} finish_test diff --git a/test/fkey6.test b/test/fkey6.test new file mode 100644 index 0000000000..66286b43ec --- /dev/null +++ b/test/fkey6.test @@ -0,0 +1,103 @@ +# 2012 December 17 +# +# 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 tests the PRAGMA defer_foreign_keys and +# SQLITE_DBSTATUS_DEFERRED_FKS +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +ifcapable {!foreignkey} { + finish_test + return +} + +do_execsql_test fkey6-1.1 { + PRAGMA foreign_keys=ON; + CREATE TABLE t1(x INTEGER PRIMARY KEY); + CREATE TABLE t2(y INTEGER PRIMARY KEY, + z INTEGER REFERENCES t1(x) DEFERRABLE INITIALLY DEFERRED); + CREATE INDEX t2z ON t2(z); + CREATE TABLE t3(u INTEGER PRIMARY KEY, v INTEGER REFERENCES t1(x)); + CREATE INDEX t3v ON t3(v); + INSERT INTO t1 VALUES(1),(2),(3),(4),(5); + INSERT INTO t2 VALUES(1,1),(2,2); + INSERT INTO t3 VALUES(3,3),(4,4); +} {} +do_test fkey6-1.2 { + catchsql {DELETE FROM t1 WHERE x=2;} +} {1 {foreign key constraint failed}} +do_test fkey6-1.3 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 0 0} +do_test fkey6-1.4 { + execsql { + BEGIN; + DELETE FROM t1 WHERE x=1; + } +} {} +do_test fkey6-1.5.1 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 1 +} {0 1 0} +do_test fkey6-1.5.2 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 1 0} +do_test fkey6-1.6 { + execsql { + ROLLBACK; + } +} {} +do_test fkey6-1.7 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 0 0} +do_test fkey6-1.8 { + execsql { + PRAGMA defer_foreign_keys=ON; + BEGIN; + DELETE FROM t1 WHERE x=3; + } +} {} +do_test fkey6-1.9 { + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 1 0} +do_test fkey6-1.10 { + execsql { + ROLLBACK; + PRAGMA defer_foreign_keys=OFF; + BEGIN; + } + catchsql {DELETE FROM t1 WHERE x=3} +} {1 {foreign key constraint failed}} +db eval {ROLLBACK} + +do_test fkey6-1.20 { + execsql { + BEGIN; + DELETE FROM t1 WHERE x=1; + } + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 1 0} +do_test fkey6-1.21 { + execsql { + DELETE FROM t2 WHERE y=1; + } + sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0 +} {0 0 0} +do_test fkey6-1.22 { + execsql { + COMMIT; + } +} {} + + +finish_test