diff --git a/manifest b/manifest index 852780318b..096bd80127 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sproblem\swith\sON\sDELETE\sSET\sDEFAULT\sactions. -D 2009-09-22T16:08:58 +C Fix\sanother\sOOM\srelated\sproblem\sin\sfkey.c. +D 2009-09-22T16:55:39 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -109,14 +109,14 @@ F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7 F src/btree.c 9c425425784c5d569bc0309c22251698ba906451 F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705 -F src/build.c 6520093d962891dae01eea545836860fd72f8915 +F src/build.c b0aee84fe34138eda3b8b4ff2fc0766714139ed3 F src/callback.c 10d237171472865f58fb07d515737238c9e06688 F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0 F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638 F src/delete.c 15499f5d10047d38e68ce991b3f88cbddb6e0931 F src/expr.c 638b599adad562d41c3bf90f542f9419664aa7b8 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff -F src/fkey.c db2225a0d7d2bfe1ffd4b694d7ca7f3e994a6a88 +F src/fkey.c fa1ad144926a8536e23cbbf64c0e51b8f2fdd4bf F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606 F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32 F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7 @@ -331,7 +331,7 @@ F test/filectrl.test 8923a6dc7630f31c8a9dd3d3d740aa0922df7bf8 F test/filefmt.test 84e3d0fe9f12d0d2ac852465c6f8450aea0d6f43 F test/fkey1.test 01c7de578e11747e720c2d9aeef27f239853c4da F test/fkey2.test b752d0290886063b42b96584eca5ddeada4c3db1 -F test/fkey_malloc.test 9926c3b4fd5f7edeb2025359d35452e733a2fbba +F test/fkey_malloc.test 91fb797bca97fd2cb170a3c7e2be7035e5f95244 F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb F test/fts1a.test 46090311f85da51bb33bd5ce84f7948359c6d8d7 F test/fts1b.test 5d8a01aefbecc8b7442b36c94c05eb7a845462d5 @@ -509,7 +509,7 @@ F test/pragma2.test 5364893491b9231dd170e3459bfc2e2342658b47 F test/printf.test 47e9e5bbec8509023479d54ceb71c9d05a95308a F test/progress.test 5b075c3c790c7b2a61419bc199db87aaf48b8301 F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc -F test/quick.test f6eb3a98643b5856626ad38933334762270db129 +F test/quick.test 12fdc7656b4d20a537a686fb223eb99b5fe54483 F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6 F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459 F test/randexpr1.test 1084050991e9ba22c1c10edd8d84673b501cc25a @@ -753,7 +753,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f -P 635d6a775a3f192d4292738905f5e01bc956a712 -R adb59c314ed6e84fb5e109c808025d01 +P 9406995055f53639b0af46985c7b0a24a80308ae +R be99954fa8ecdadd209ed99aeb4f1f2e U dan -Z ca9f75785688b952325cd06be253de5b +Z 514ea3128db14a2b11336b16d800bc8f diff --git a/manifest.uuid b/manifest.uuid index fd62f8684a..70e3d7d9c1 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -9406995055f53639b0af46985c7b0a24a80308ae \ No newline at end of file +e2bc51bc61d54d103ccffd12106c27a574e4e997 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 0fbe07e19a..06c0a0fc1b 100644 --- a/src/build.c +++ b/src/build.c @@ -2233,7 +2233,10 @@ void sqlite3CreateForeignKey( pNextTo = (FKey *)sqlite3HashInsert(&p->pSchema->fkeyHash, pFKey->zTo, sqlite3Strlen30(pFKey->zTo), (void *)pFKey ); - if( pNextTo==pFKey ) goto fk_end; + if( pNextTo==pFKey ){ + db->mallocFailed = 1; + goto fk_end; + } if( pNextTo ){ assert( pNextTo->pPrevTo==0 ); pFKey->pNextTo = pNextTo; diff --git a/src/fkey.c b/src/fkey.c index ceb5bedcef..32aef9bbe0 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -364,7 +364,9 @@ static void fkScanReferences( pParse, OE_Abort, "foreign key constraint failed", P4_STATIC ); } - sqlite3WhereEnd(pWInfo); + if( pWInfo ){ + sqlite3WhereEnd(pWInfo); + } /* Clean up the WHERE clause constructed above. */ sqlite3ExprDelete(db, pWhere); @@ -510,49 +512,50 @@ void sqlite3FkCheck( ** the foreign key that refers to this table is attached to). This ** is required for the sqlite3WhereXXX() interface. */ pSrc = sqlite3SrcListAppend(db, 0, 0, 0); - if( !pSrc ) return; - pSrc->a->pTab = pFKey->pFrom; - pSrc->a->pTab->nRef++; - pSrc->a->iCursor = pParse->nTab++; - - /* If this is an UPDATE, and none of the columns associated with this - ** FK have been modified, do not scan the referencing table. Unlike - ** the compile-time test implemented above, this is not just an - ** optimization. It is required so that immediate foreign keys do not - ** throw exceptions when the user executes a statement like: - ** - ** UPDATE refd_table SET refd_column = refd_column - */ - if( pChanges ){ - int i; - int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; - for(i=0; inCol; i++){ - int iOff = (pIdx ? pIdx->aiColumn[i] : -1) + 1; - sqlite3VdbeAddOp3(v, OP_Ne, regOld+iOff, iJump, regNew+iOff); + if( pSrc ){ + pSrc->a->pTab = pFKey->pFrom; + pSrc->a->pTab->nRef++; + pSrc->a->iCursor = pParse->nTab++; + + /* If this is an UPDATE, and none of the columns associated with this + ** FK have been modified, do not scan the referencing table. Unlike + ** the compile-time test implemented above, this is not just an + ** optimization. It is required so that immediate foreign keys do not + ** throw exceptions when the user executes a statement like: + ** + ** UPDATE refd_table SET refd_column = refd_column + */ + if( pChanges ){ + int i; + int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1; + for(i=0; inCol; i++){ + int iOff = (pIdx ? pIdx->aiColumn[i] : -1) + 1; + sqlite3VdbeAddOp3(v, OP_Ne, regOld+iOff, iJump, regNew+iOff); + } + iGoto = sqlite3VdbeAddOp0(v, OP_Goto); } - iGoto = sqlite3VdbeAddOp0(v, OP_Goto); + + if( regNew!=0 && pFKey->isDeferred ){ + fkScanReferences(pParse, pSrc, pIdx, pFKey, aiCol, regNew, -1); + } + if( regOld!=0 ){ + /* If there is a RESTRICT action configured for the current operation + ** on the referenced table of this FK, then throw an exception + ** immediately if the FK constraint is violated, even if this is a + ** deferred trigger. That's what RESTRICT means. To defer checking + ** the constraint, the FK should specify NO ACTION (represented + ** using OE_None). NO ACTION is the default. */ + fkScanReferences(pParse, pSrc, pIdx, pFKey, aiCol, regOld, + (pChanges!=0 && pFKey->updateConf!=OE_Restrict) + || (pChanges==0 && pFKey->deleteConf!=OE_Restrict) + ); + } + + if( pChanges ){ + sqlite3VdbeJumpHere(v, iGoto); + } + sqlite3SrcListDelete(db, pSrc); } - - if( regNew!=0 && pFKey->isDeferred ){ - fkScanReferences(pParse, pSrc, pIdx, pFKey, aiCol, regNew, -1); - } - if( regOld!=0 ){ - /* If there is a RESTRICT action configured for the current operation - ** on the referenced table of this FK, then throw an exception - ** immediately if the FK constraint is violated, even if this is a - ** deferred trigger. That's what RESTRICT means. To defer checking - ** the constraint, the FK should specify NO ACTION (represented - ** using OE_None). NO ACTION is the default. */ - fkScanReferences(pParse, pSrc, pIdx, pFKey, aiCol, regOld, - (pChanges!=0 && pFKey->updateConf!=OE_Restrict) - || (pChanges==0 && pFKey->deleteConf!=OE_Restrict) - ); - } - - if( pChanges ){ - sqlite3VdbeJumpHere(v, iGoto); - } - sqlite3SrcListDelete(db, pSrc); sqlite3DbFree(db, aiCol); } } diff --git a/test/fkey_malloc.test b/test/fkey_malloc.test index 63c99a5f72..a8bf28c182 100644 --- a/test/fkey_malloc.test +++ b/test/fkey_malloc.test @@ -31,6 +31,23 @@ do_malloc_test fkey_malloc-1 -sqlprep { DELETE FROM t1; } +do_malloc_test fkey_malloc-2 -sqlprep { + PRAGMA foreign_keys = 1; + CREATE TABLE t1(a, b, UNIQUE(a, b)); +} -sqlbody { + CREATE TABLE t2(x, y, + FOREIGN KEY(x, y) REFERENCES t1(a, b) DEFERRABLE INITIALLY DEFERRED + ); + BEGIN; + INSERT INTO t2 VALUES('a', 'b'); + INSERT INTO t1 VALUES('a', 'b'); + UPDATE t1 SET a = 'c'; + DELETE FROM t2; + INSERT INTO t2 VALUES('d', 'b'); + UPDATE t2 SET x = 'c'; + COMMIT; +} + finish_test diff --git a/test/quick.test b/test/quick.test index 8783a10781..a56455a141 100644 --- a/test/quick.test +++ b/test/quick.test @@ -58,6 +58,7 @@ set EXCLUDE { crash7.test delete3.test fts3.test + fkey_malloc.test fuzz.test fuzz3.test fuzz_malloc.test