diff --git a/manifest b/manifest index e6daa65ad0..fe94c740c9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sa\scondition\sfrom\sbalance_nonroot()\sthat\sis\salways\strue.\s(CVS\s6806) -D 2009-06-23T16:40:18 +C Enhance\sautoincrement\sso\sthat\sit\sworks\swith\striggers\sthat\salso\sdo\r\nautoincrement\sinserts,\seven\smultiple\sinserts\sinto\sthe\ssame\stable.\r\nTicket\s#3928\s(CVS\s6807) +D 2009-06-23T20:28:54 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 8b8fb7823264331210cddf103831816c286ba446 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -109,11 +109,11 @@ F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c F src/btree.c 807e32c181e681ffd3468d114b5cb11c63984842 F src/btree.h f70b694e8c163227369a66863b01fbff9009f323 F src/btreeInt.h 7267e965e34314aa2bddbdde268b31e1034eda9c -F src/build.c e98868af6a04c8d7191c39fd05c69da34a8d9c68 +F src/build.c d930b3899aea564f01a581e0e9429d92fb5f98f0 F src/callback.c cb68b21b0d4ae7d11ae0e487933bce3323784dcf F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0 F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3 -F src/delete.c cb791855c7948cecc96def9d97989879ca26f257 +F src/delete.c fb05e577ab273cc8a63b44809aa5078f72f475c1 F src/expr.c de80e2d6c2adc453e06f070837ca5b87d4373730 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff F src/func.c 9856373f5315f6b8690d7f07f7191aa9f279ca87 @@ -121,7 +121,7 @@ F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7 F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1 F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb -F src/insert.c 69ef88ce30d1f65315b57aba63b2d4e9bdca1090 +F src/insert.c 94e51344e01aea6be43e95cd24e8baa014d8c3d6 F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0 F src/legacy.c 9a56cf126ceee332b56061bf16bd0fb4ff9e26c0 F src/loadext.c 0e88a335665db0b2fb4cece3e49dcb65d832635a @@ -162,7 +162,7 @@ F src/select.c 71748b8e244112cf73df9446c4246c192276c30d F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb F src/sqlite.h.in ccc67f14d5661240d05eadb8ab308aa637b0630c F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 -F src/sqliteInt.h 9fd22fed12cbb0eccfe14108796ae05fa473786e +F src/sqliteInt.h 2dc684cd94560b0de876098e49d8a91996291a76 F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d @@ -197,9 +197,9 @@ F src/test_server.c f0a403b5f699c09bd2b1236b6f69830fd6221f6b F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4 F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241 -F src/tokenize.c 3743be86c3e73081b5b162adc00e2492a94a3a99 +F src/tokenize.c eadd396fa81e8031d4b4a65eefd661e9c675167f F src/trigger.c c07c5157c58fcdb704f65d5f5e4775276e45bb8b -F src/update.c 6ae6c26adff8dc34532d578f66e6cfde04b5d177 +F src/update.c b58db45e40f11082281d6f94137cd3b5657771d9 F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff F src/util.c a7e981e032c3c9c0887d50d7e658a33cb355b43d F src/vacuum.c 0e14f371ea3326c6b8cfba257286d798cd20db59 @@ -233,7 +233,7 @@ F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61 F test/auth.test b66c571142873cfbf9a141b807f78b93f5d11374 F test/auth2.test ee3ba272e2b975e913afc9b041ee75706e190005 F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5 -F test/autoinc.test ab549b48b389cabd92967b86c379ec8b31fa6c16 +F test/autoinc.test 71bc5183c93ed5e2b8b3a71c218d777b55e4fffc F test/autovacuum.test 25f891bc343a8bf5d9229e2e9ddab9f31a9ab5ec F test/autovacuum_ioerr2.test 598b0663074d3673a9c1bc9a16e80971313bafe6 F test/avtrans.test 1e901d8102706b63534dbd2bdd4d8f16c4082650 @@ -737,7 +737,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746 -P da9893e23caf89090c8b6563cb5f88d7dbf7c260 -R 5253d044c7ec7582bf7c9fd280850376 -U danielk1977 -Z 1a116d3d2ab282f253ce6bf047ecc40c +P c5dc80e6bdd18a5ada728c8d5c9403ac233f1c9a +R 8916621e1801546a3d0feafac918adbe +U drh +Z cb8dc29a045e11a78c5fa19e64b5f95b diff --git a/manifest.uuid b/manifest.uuid index ee7d59a3cc..09a7f53599 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c5dc80e6bdd18a5ada728c8d5c9403ac233f1c9a \ No newline at end of file +1330993de8eae7baeec24100216158063c9bdc19 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 53d03b7437..850ec7fa23 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.552 2009/06/18 17:22:39 drh Exp $ +** $Id: build.c,v 1.553 2009/06/23 20:28:54 drh Exp $ */ #include "sqliteInt.h" @@ -174,6 +174,12 @@ void sqlite3FinishCoding(Parse *pParse){ ** shared-cache feature is enabled. */ codeTableLocks(pParse); + + /* Initialize any AUTOINCREMENT data structures required. + */ + sqlite3AutoincrementBegin(pParse); + + /* Finally, jump back to the beginning of the executable code. */ sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto); } } diff --git a/src/delete.c b/src/delete.c index 95ef3cef74..cbd8b375e7 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.203 2009/05/28 01:00:55 drh Exp $ +** $Id: delete.c,v 1.204 2009/06/23 20:28:54 drh Exp $ */ #include "sqliteInt.h" @@ -475,6 +475,14 @@ void sqlite3DeleteFrom( } } + /* Update the sqlite_sequence table by storing the content of the + ** maximum rowid counter values recorded while inserting into + ** autoincrement tables. + */ + if( pParse->nested==0 && pParse->trigStack==0 ){ + sqlite3AutoincrementEnd(pParse); + } + /* ** Return the number of rows that were deleted. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not diff --git a/src/insert.c b/src/insert.c index 27549f0018..f6d8b1c390 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.268 2009/05/29 19:00:13 drh Exp $ +** $Id: insert.c,v 1.269 2009/06/23 20:28:54 drh Exp $ */ #include "sqliteInt.h" @@ -162,22 +162,24 @@ static int readsTable(Vdbe *v, int iStartAddr, int iDb, Table *pTab){ #ifndef SQLITE_OMIT_AUTOINCREMENT /* -** Write out code to initialize the autoincrement logic. This code -** looks up the current autoincrement value in the sqlite_sequence -** table and stores that value in a register. Code generated by -** autoIncStep() will keep that register holding the largest -** rowid value. Code generated by autoIncEnd() will write the new -** largest value of the counter back into the sqlite_sequence table. +** Locate or create an AutoincInfo structure associated with table pTab +** which is in database iDb. Return the register number for the register +** that holds the maximum rowid. ** -** This routine returns the index of the mem[] cell that contains -** the maximum rowid counter. +** There is at most one AutoincInfo structure per table even if the +** same table is autoincremented multiple times due to inserts within +** triggers. A new AutoincInfo structure is created if this is the +** first use of table pTab. On 2nd and subsequent uses, the original +** AutoincInfo structure is used. ** -** Three consecutive registers are allocated by this routine. The -** first two hold the name of the target table and the maximum rowid -** inserted into the target table, respectively. -** The third holds the rowid in sqlite_sequence where we will -** write back the revised maximum rowid. This routine returns the -** index of the second of these three registers. +** Three memory locations are allocated: +** +** (1) Register to hold the name of the pTab table. +** (2) Register to hold the maximum ROWID of pTab. +** (3) Register to hold the rowid in sqlite_sequence of pTab +** +** The 2nd register is the one that is returned. That is all the +** insert routine needs to know about. */ static int autoIncBegin( Parse *pParse, /* Parsing context */ @@ -186,31 +188,58 @@ static int autoIncBegin( ){ int memId = 0; /* Register holding maximum rowid */ if( pTab->tabFlags & TF_Autoincrement ){ - Vdbe *v = pParse->pVdbe; - Db *pDb = &pParse->db->aDb[iDb]; - int iCur = pParse->nTab++; - int addr; /* Address of the top of the loop */ - assert( v ); - pParse->nMem++; /* Holds name of table */ - memId = ++pParse->nMem; - pParse->nMem++; - sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead); - addr = sqlite3VdbeCurrentAddr(v); - sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, pTab->zName, 0); - sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+9); - sqlite3VdbeAddOp3(v, OP_Column, iCur, 0, memId); - sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); - sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); - sqlite3VdbeAddOp2(v, OP_Rowid, iCur, memId+1); - sqlite3VdbeAddOp3(v, OP_Column, iCur, 1, memId); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); - sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+2); - sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); - sqlite3VdbeAddOp2(v, OP_Close, iCur, 0); + AutoincInfo *pInfo; + + pInfo = pParse->pAinc; + while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; } + if( pInfo==0 ){ + pInfo = sqlite3DbMallocRaw(pParse->db, sizeof(*pInfo)); + if( pInfo==0 ) return 0; + pInfo->pNext = pParse->pAinc; + pParse->pAinc = pInfo; + pInfo->pTab = pTab; + pInfo->iDb = iDb; + pParse->nMem++; /* Register to hold name of table */ + pInfo->regCtr = ++pParse->nMem; /* Max rowid register */ + pParse->nMem++; /* Rowid in sqlite_sequence */ + } + memId = pInfo->regCtr; } return memId; } +/* +** This routine generates code that will initialize all of the +** register used by the autoincrement tracker. +*/ +void sqlite3AutoincrementBegin(Parse *pParse){ + AutoincInfo *p; /* Information about an AUTOINCREMENT */ + sqlite3 *db = pParse->db; /* The database connection */ + Db *pDb; /* Database only autoinc table */ + int memId; /* Register holding max rowid */ + int addr; /* A VDBE address */ + Vdbe *v = pParse->pVdbe; /* VDBE under construction */ + + assert( v ); /* We failed long ago if this is not so */ + for(p = pParse->pAinc; p; p = p->pNext){ + pDb = &db->aDb[p->iDb]; + memId = p->regCtr; + sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenRead); + addr = sqlite3VdbeCurrentAddr(v); + sqlite3VdbeAddOp4(v, OP_String8, 0, memId-1, 0, p->pTab->zName, 0); + sqlite3VdbeAddOp2(v, OP_Rewind, 0, addr+9); + sqlite3VdbeAddOp3(v, OP_Column, 0, 0, memId); + sqlite3VdbeAddOp3(v, OP_Ne, memId-1, addr+7, memId); + sqlite3VdbeChangeP5(v, SQLITE_JUMPIFNULL); + sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); + sqlite3VdbeAddOp3(v, OP_Column, 0, 1, memId); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+9); + sqlite3VdbeAddOp2(v, OP_Next, 0, addr+2); + sqlite3VdbeAddOp2(v, OP_Integer, 0, memId); + sqlite3VdbeAddOp0(v, OP_Close); + } +} + /* ** Update the maximum rowid for an autoincrement calculation. ** @@ -226,32 +255,43 @@ static void autoIncStep(Parse *pParse, int memId, int regRowid){ } /* -** After doing one or more inserts, the maximum rowid is stored -** in reg[memId]. Generate code to write this value back into the -** the sqlite_sequence table. +** This routine generates the code needed to write autoincrement +** maximum rowid values back into the sqlite_sequence register. +** Every statement that might do an INSERT into an autoincrement +** table (either directly or through triggers) needs to call this +** routine just before the "exit" code. */ -static void autoIncEnd( - Parse *pParse, /* The parsing context */ - int iDb, /* Index of the database holding pTab */ - Table *pTab, /* Table we are inserting into */ - int memId /* Memory cell holding the maximum rowid */ -){ - if( pTab->tabFlags & TF_Autoincrement ){ - int iCur = pParse->nTab++; - Vdbe *v = pParse->pVdbe; - Db *pDb = &pParse->db->aDb[iDb]; - int j1; - int iRec = ++pParse->nMem; /* Memory cell used for record */ +void sqlite3AutoincrementEnd(Parse *pParse){ + AutoincInfo *p; + Vdbe *v = pParse->pVdbe; + sqlite3 *db = pParse->db; - assert( v ); - sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); + assert( v ); + for(p = pParse->pAinc; p; p = p->pNext){ + Db *pDb = &db->aDb[p->iDb]; + int j1, j2, j3, j4, j5; + int iRec; + int memId = p->regCtr; + + iRec = sqlite3GetTempReg(pParse); + sqlite3OpenTable(pParse, 0, p->iDb, pDb->pSchema->pSeqTab, OP_OpenWrite); j1 = sqlite3VdbeAddOp1(v, OP_NotNull, memId+1); - sqlite3VdbeAddOp2(v, OP_NewRowid, iCur, memId+1); + j2 = sqlite3VdbeAddOp0(v, OP_Rewind); + j3 = sqlite3VdbeAddOp3(v, OP_Column, 0, 0, iRec); + j4 = sqlite3VdbeAddOp3(v, OP_Eq, memId-1, 0, iRec); + sqlite3VdbeAddOp2(v, OP_Next, 0, j3); + sqlite3VdbeJumpHere(v, j2); + sqlite3VdbeAddOp2(v, OP_NewRowid, 0, memId+1); + j5 = sqlite3VdbeAddOp0(v, OP_Goto); + sqlite3VdbeJumpHere(v, j4); + sqlite3VdbeAddOp2(v, OP_Rowid, 0, memId+1); sqlite3VdbeJumpHere(v, j1); + sqlite3VdbeJumpHere(v, j5); sqlite3VdbeAddOp3(v, OP_MakeRecord, memId-1, 2, iRec); - sqlite3VdbeAddOp3(v, OP_Insert, iCur, iRec, memId+1); + sqlite3VdbeAddOp3(v, OP_Insert, 0, iRec, memId+1); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); - sqlite3VdbeAddOp1(v, OP_Close, iCur); + sqlite3VdbeAddOp0(v, OP_Close); + sqlite3ReleaseTempReg(pParse, iRec); } } #else @@ -261,7 +301,6 @@ static void autoIncEnd( */ # define autoIncBegin(A,B,C) (0) # define autoIncStep(A,B,C) -# define autoIncEnd(A,B,C,D) #endif /* SQLITE_OMIT_AUTOINCREMENT */ @@ -507,7 +546,7 @@ void sqlite3Insert( if( pColumn==0 && xferOptimization(pParse, pTab, pSelect, onError, iDb) ){ assert( !pTrigger ); assert( pList==0 ); - goto insert_cleanup; + goto insert_end; } #endif /* SQLITE_OMIT_XFER_OPT */ @@ -989,11 +1028,14 @@ void sqlite3Insert( } } +insert_end: /* Update the sqlite_sequence table by storing the content of the - ** counter value in memory regAutoinc back into the sqlite_sequence - ** table. + ** maximum rowid counter values recorded while inserting into + ** autoincrement tables. */ - autoIncEnd(pParse, iDb, pTab, regAutoinc); + if( pParse->nested==0 && pParse->trigStack==0 ){ + sqlite3AutoincrementEnd(pParse); + } /* ** Return the number of rows inserted. If this routine is @@ -1716,7 +1758,6 @@ static int xferOptimization( sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND); sqlite3VdbeChangeP4(v, -1, pDest->zName, 0); sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1); - autoIncEnd(pParse, iDbDest, pDest, regAutoinc); for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){ for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){ if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index b0d047b715..81c8e46309 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.886 2009/06/19 14:06:03 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.887 2009/06/23 20:28:54 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -581,6 +581,7 @@ struct BusyHandler { */ typedef struct AggInfo AggInfo; typedef struct AuthContext AuthContext; +typedef struct AutoincInfo AutoincInfo; typedef struct Bitvec Bitvec; typedef struct RowSet RowSet; typedef struct CollSeq CollSeq; @@ -1926,6 +1927,22 @@ struct SelectDest { int nMem; /* Number of registers allocated */ }; +/* +** During code generation of statements that do inserts into AUTOINCREMENT +** tables, the following information is attached to the Table.u.autoInc.p +** pointer of each autoincrement table to record some side information that +** the code generator needs. We have to keep per-table autoincrement +** information in case inserts are down within triggers. Triggers do not +** normally coordinate their activities, but we do need to coordinate the +** loading and saving of autoincrement information. +*/ +struct AutoincInfo { + AutoincInfo *pNext; /* Next info block in a list of them all */ + Table *pTab; /* Table this info block refers to */ + int iDb; /* Index in sqlite3.aDb[] of database holding pTab */ + int regCtr; /* Memory register holding the rowid counter */ +}; + /* ** Size of the column cache */ @@ -1992,6 +2009,7 @@ struct Parse { #endif int regRowid; /* Register holding rowid of CREATE TABLE entry */ int regRoot; /* Register holding root page number for new objects */ + AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */ /* Above is constant between recursions. Below is reset before and after ** each recursion */ @@ -2482,6 +2500,13 @@ void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int); void sqlite3DropTable(Parse*, SrcList*, int, int); void sqlite3DeleteTable(Table*); +#ifndef SQLITE_OMIT_AUTOINCREMENT + void sqlite3AutoincrementBegin(Parse *pParse); + void sqlite3AutoincrementEnd(Parse *pParse); +#else +# define sqlite3AutoincrementBegin(X) +# define sqlite3AutoincrementEnd(X) +#endif void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); void *sqlite3ArrayAllocate(sqlite3*,void*,int,int,int*,int*,int*); IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); diff --git a/src/tokenize.c b/src/tokenize.c index 6761f8c3c2..3fdb38edeb 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.161 2009/06/17 01:17:13 drh Exp $ +** $Id: tokenize.c,v 1.162 2009/06/23 20:28:54 drh Exp $ */ #include "sqliteInt.h" #include @@ -518,6 +518,11 @@ abort_parse: sqlite3DeleteTrigger(db, pParse->pNewTrigger); sqlite3DbFree(db, pParse->apVarExpr); sqlite3DbFree(db, pParse->aAlias); + while( pParse->pAinc ){ + AutoincInfo *p = pParse->pAinc; + pParse->pAinc = p->pNext; + sqlite3DbFree(db, p); + } while( pParse->pZombieTab ){ Table *p = pParse->pZombieTab; pParse->pZombieTab = p->pNextZombie; diff --git a/src/update.c b/src/update.c index 6eb92fb615..12348c91a7 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.202 2009/05/28 01:00:55 drh Exp $ +** $Id: update.c,v 1.203 2009/06/23 20:28:54 drh Exp $ */ #include "sqliteInt.h" @@ -564,6 +564,14 @@ void sqlite3Update( sqlite3VdbeAddOp2(v, OP_Close, oldIdx, 0); } + /* Update the sqlite_sequence table by storing the content of the + ** maximum rowid counter values recorded while inserting into + ** autoincrement tables. + */ + if( pParse->nested==0 && pParse->trigStack==0 ){ + sqlite3AutoincrementEnd(pParse); + } + /* ** Return the number of rows that were changed. If this routine is ** generating code because of a call to sqlite3NestedParse(), do not diff --git a/test/autoinc.test b/test/autoinc.test index c49fb61ebf..9080a3997d 100644 --- a/test/autoinc.test +++ b/test/autoinc.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is testing the AUTOINCREMENT features. # -# $Id: autoinc.test,v 1.13 2008/08/11 18:44:58 drh Exp $ +# $Id: autoinc.test,v 1.14 2009/06/23 20:28:54 drh Exp $ # set testdir [file dirname $argv0] @@ -556,5 +556,82 @@ do_test autoinc-9.1 { } } {t3 0} +# Ticket #3928. Make sure that triggers to not make extra slots in +# the SQLITE_SEQUENCE table. +# +do_test autoinc-3928.1 { + db eval { + CREATE TABLE t3928(a INTEGER PRIMARY KEY AUTOINCREMENT, b); + CREATE TRIGGER t3928r1 BEFORE INSERT ON t3928 BEGIN + INSERT INTO t3928(b) VALUES('before1'); + INSERT INTO t3928(b) VALUES('before2'); + END; + CREATE TRIGGER t3928r2 AFTER INSERT ON t3928 BEGIN + INSERT INTO t3928(b) VALUES('after1'); + INSERT INTO t3928(b) VALUES('after2'); + END; + INSERT INTO t3928(b) VALUES('test'); + SELECT * FROM t3928 ORDER BY a; + } +} {1 before1 2 after1 3 after2 4 before2 5 after1 6 after2 7 test 8 before1 9 before2 10 after1 11 before1 12 before2 13 after2} +do_test autoinc-3928.2 { + db eval { + SELECT * FROM sqlite_sequence WHERE name='t3928' + } +} {t3928 13} + +do_test autoinc-3928.3 { + db eval { + DROP TRIGGER t3928r1; + DROP TRIGGER t3928r2; + CREATE TRIGGER t3928r3 BEFORE UPDATE ON t3928 + WHEN typeof(new.b)=='integer' BEGIN + INSERT INTO t3928(b) VALUES('before-int-' || new.b); + END; + CREATE TRIGGER t3928r4 AFTER UPDATE ON t3928 + WHEN typeof(new.b)=='integer' BEGIN + INSERT INTO t3928(b) VALUES('after-int-' || new.b); + END; + DELETE FROM t3928 WHERE a!=1; + UPDATE t3928 SET b=456 WHERE a=1; + SELECT * FROM t3928 ORDER BY a; + } +} {1 456 14 before-int-456 15 after-int-456} +do_test autoinc-3928.4 { + db eval { + SELECT * FROM sqlite_sequence WHERE name='t3928' + } +} {t3928 15} + +do_test autoinc-3928.5 { + db eval { + CREATE TABLE t3928b(x); + INSERT INTO t3928b VALUES(100); + INSERT INTO t3928b VALUES(200); + INSERT INTO t3928b VALUES(300); + DELETE FROM t3928; + CREATE TABLE t3928c(y INTEGER PRIMARY KEY AUTOINCREMENT, z); + CREATE TRIGGER t3928br1 BEFORE DELETE ON t3928b BEGIN + INSERT INTO t3928(b) VALUES('before-del-'||old.x); + INSERT INTO t3928c(z) VALUES('before-del-'||old.x); + END; + CREATE TRIGGER t3928br2 AFTER DELETE ON t3928b BEGIN + INSERT INTO t3928(b) VALUES('after-del-'||old.x); + INSERT INTO t3928c(z) VALUES('after-del-'||old.x); + END; + DELETE FROM t3928b; + SELECT * FROM t3928 ORDER BY a; + } +} {16 before-del-100 17 after-del-100 18 before-del-200 19 after-del-200 20 before-del-300 21 after-del-300} +do_test autoinc-3928.6 { + db eval { + SELECT * FROM t3928c ORDER BY y; + } +} {1 before-del-100 2 after-del-100 3 before-del-200 4 after-del-200 5 before-del-300 6 after-del-300} +do_test autoinc-3928.7 { + db eval { + SELECT * FROM sqlite_sequence WHERE name LIKE 't3928%' ORDER BY name; + } +} {t3928 21 t3928c 6} finish_test