diff --git a/manifest b/manifest index 899192c841..cde9fe6261 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Begin\sadding\sthe\sability\sto\sremove\sunused\sfeatures\sat\scompile-time\sand\sstill\nhave\sall\sthe\stests\spass.\s(CVS\s2033) -D 2004-10-30T20:23:09 +C Insert\s#ifdefs\sthat\scan\soptionally\sremove\sfeatures\sat\scompiletime\sresulting\nin\sa\sdatabase\sengine\swith\sa\ssmaller\sfootprint.\s(CVS\s2034) +D 2004-10-31T02:22:48 F Makefile.in 9e90c685d69f09039015a6b1f3b0a48e9738c9e5 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1 @@ -18,7 +18,7 @@ F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826 F main.mk c7c97f809e5e7897bc843db64f692c7ef9013a92 F mkdll.sh 468d4f41d3ea98221371df4825cfbffbaac4d7e4 -F mkopcodec.awk 80311cdeb16d78017cc62e4ad6c6d008e5fe0e17 +F mkopcodec.awk 14a794f7b206976afc416b30fe8e0fc97f3434e9 F mkopcodeh.awk 4090944e4de0a2ccb99aa0083290f73bce4db406 F mkso.sh 7b67da1d63070875ba948e749aee9ef50ce36e3d F publish.sh 72bde067dda3fc2d33e92f20253b924e3b97da30 @@ -29,16 +29,16 @@ F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689 F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea -F src/btree.c d8426846c0db61c97a0e3e11531781be7a96f1bc +F src/btree.c 3764bdd9839075eb6dcc2369caca659b9b89d3f5 F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029 -F src/build.c cb0232e0f239d7cea8598d982039b99259074f64 +F src/build.c bb896c5f85ab749d17ae5d730235134c12c08033 F src/date.c 34bdb0082db7ec2a83ef00063f7b44e61ee19dad -F src/delete.c 531525eca2885afc1d9c63e110bc7aa568e170c3 -F src/expr.c 2f492bf532d700bd2c38e16caa49048535e8ed27 +F src/delete.c cf0efbef1f42d4eec385a3f59af2b37a5e232074 +F src/expr.c 3a43e508a3dc213703808bbcbb17633b88b57d17 F src/func.c 600e506bccf7648df8ad03efb417560d0f7ad4c1 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 -F src/insert.c 7e8ce8834c3716a313694e5340dbf28ff828677a +F src/insert.c 64a3716522cbc81d91176eac0d944cc14be6236c F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b F src/main.c ba1b26f03af4b7f8be3394748123dd671b9ea147 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 @@ -52,38 +52,38 @@ F src/os_unix.c 5824b22ba41fe9d514ef9169aac1b5fde73af229 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13 F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b -F src/pager.c cc2e7fb3d7913862d7b1170f923d2dcfdbac3bed +F src/pager.c 6e19f9a64a9fae60bcf00140cecb5981765f3d95 F src/pager.h 774d1973acbda341827d21b0da0150575d69f7d9 -F src/parse.y 8d97a91cba7e35b5eaac064c9f6e597dc6442b29 -F src/pragma.c 263e20f7640df1e7937f1c71372fa286356aaf09 +F src/parse.y 08f4971f89e651f47b3f83fe7369c7edde254331 +F src/pragma.c 44e192eb5928157bdb015926f858a7c6e3ef6c98 F src/printf.c 7a92adc00b758cd5ce087dae80181a8bbdb70ed2 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 -F src/select.c de51ec24aef0d5370819dac6c2613460effac42c +F src/select.c 156990c636102bb6b8de85e7ff3396a62568476b F src/shell.c 55adda3cf3c1cc2f6c1919aac17b2318f9c2a96f F src/sqlite.h.in 4f97b5907acfd2a5068cb0cec9d5178816734db7 -F src/sqliteInt.h 008c205896a1c531ec6249de20ecfe23c89ae243 +F src/sqliteInt.h 84d5ca7b02793697641a74fb125fcee3995ea2ff F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9 F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008 -F src/test1.c 23fd40832736c46b9c2d897fa13c7d913a3f1626 +F src/test1.c cc5bc94006d23584a966c12b0b9fa1db0d94af76 F src/test2.c b11fa244fff02190707dd0879987c37c75e61fc8 -F src/test3.c 5b5b0f3d11b097399c1054fff73d8f3711092301 +F src/test3.c f423597e220b3d446a65c9cc0c49cb4eb00c0215 F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1 -F src/tokenize.c f073bbf85fe527e1a8a191a1fda88313c09710ad -F src/trigger.c b51a120d53e8b85359be11bf5e50854e5725fe3d -F src/update.c 174c3b593b8f4928e510a51ec309e8ce69d2371c +F src/tokenize.c a0a999bf4800e7295ac66c8694f84414ceff1755 +F src/trigger.c f9a0a8d3a87238de1a934eeb7d0b6b1f13e6a55b +F src/update.c ee15b7ba712c2292802eba2d465f039b5deada39 F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed F src/util.c f4ab796b9def353feed2191d7ce8e39a0f5059cd F src/vacuum.c ecb4a2c6f1ac5cc9b394dc64d3bb14ca650c4f60 -F src/vdbe.c adbcdbc817ae2f411904cd12582f06fc1ca8be1e +F src/vdbe.c 253beaae665f50a1320f0a068f9dda68e3c3df47 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181 F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b -F src/vdbeapi.c 81ab9e84c55f5762f552904e6e5d309269b02017 -F src/vdbeaux.c 73928b98034cf3321afb6aa815723f08705bb135 +F src/vdbeapi.c 3965bf4678ae32c05f73550c1b5be3268f9f3006 +F src/vdbeaux.c 544ff66308d3184b519decc731abb65c5233bc2d F src/vdbemem.c ef9ac7d32acfe4bce5c5b408b1294c8d9e0cdb56 F src/where.c 6e637a6b3e61fe3104adc4e5caa4738bf6570daa F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c -F test/attach.test feb2ce54e78688df4c84553416d5aec3b2a0112e +F test/attach.test 6ad560eb3e77751a4faecd77da09deac9e38cc41 F test/attach2.test f7795123d3051ace1672b6d23973da6435de3745 F test/attach3.test 6d060986ff004ebb89e1876a331d96c6bb62269e F test/auth.test 1cc252d9e7b3bdc1314199cbf3a0d3c5ed026c21 @@ -110,7 +110,7 @@ F test/conflict.test c5b849b01cfbe0a4f63a90cba6f68e2fe3a75f87 F test/corrupt.test 0080ddcece23e8ba47c44608c4fb73fd4d1d8ce2 F test/crash.test a3f6d27f7cb7f7bd752461db1e14f7c781ecedc3 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 -F test/date.test b4f8bb8e3e3ee6eb3efa1ccef47cfe206dafe4b8 +F test/date.test dda578ec1857837156bd8b32f8e09d81d7d7881c F test/delete.test ec0b455f2dcc0e189d96ee438438ba026c4e51d8 F test/delete2.test 050a3a6e8ea0f83aed817d164b16af2a499fb452 F test/diskfull.test e2f6cfd868713ead06dc82b84a4938e868128fc0 @@ -180,11 +180,11 @@ F test/threadtest1.c 6029d9c5567db28e6dc908a0c63099c3ba6c383b F test/threadtest2.c 97a830d53c24c42290501fdfba4a6e5bdd34748b F test/trace.test a54fa8df0d01cf827289a7659d78959e8fd2f955 F test/trans.test 29645b344d2b9b6792793562b12340177ddd8f96 -F test/trigger1.test dc015c410161f1a6109fd52638dfac852e2a34de -F test/trigger2.test a5d06e6e8e1e773cfcb5aaa75ab381b2ff35de63 -F test/trigger3.test 70931be83fa3f563f7a5ca9e88b86f476af73948 -F test/trigger4.test 97c11d3cf43d752b172809bb82536372ee5e399c -F test/trigger5.test 25ba4d352282cd05753496a50f0bd23162cc97b9 +F test/trigger1.test 63a74ae12bccac86036f1c4f8f952fb0cf80703f +F test/trigger2.test fec8f9091ff1248eafb5a33690ad4ff7615f5215 +F test/trigger3.test f1c0cc1365f00b21a8cd41c189edca139c2d6cc6 +F test/trigger4.test ce5c97aba6a8a11be5820e694659438c3e982ada +F test/trigger5.test 619391a3e9fc194081d22cefd830d811e7badf83 F test/types.test 1f5f0670cf07e44c0a5b03a31e31ec5ed39a482e F test/types2.test f23c147a2ab3e51d5dbcfa9987200db5acba7aa7 F test/unique.test 0e38d4cc7affeef2527720d1dafd1f6870f02f2b @@ -251,7 +251,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c -P 87a3c668f0dcd43f5d9b38d92a75a4ac38d49057 -R 7ce19f5cec69820ac47d8f047cf87ee1 +P 2aa506ccb003a25555b414772002d0130db93052 +R a7fa315527f5cd6a01abf8ab34756c15 U drh -Z 49adbf5abf742ee3280084694fca0270 +Z ec22b5e4f08c77bf263552544e24fca1 diff --git a/manifest.uuid b/manifest.uuid index 7f381d9122..f6cd11f1b5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -2aa506ccb003a25555b414772002d0130db93052 \ No newline at end of file +be661acfa849bb0d5692797dd221f5a8a457f8ad \ No newline at end of file diff --git a/mkopcodec.awk b/mkopcodec.awk index 6119272bd7..2b702e5283 100644 --- a/mkopcodec.awk +++ b/mkopcodec.awk @@ -11,6 +11,10 @@ BEGIN { print "/* Automatically generated. Do not edit */" print "/* See the mkopcodec.h script for details. */" + printf "#if !defined(SQLITE_OMIT_EXPLAIN)" + printf " || !defined(NDEBUG)" + printf " || defined(VDBE_PROFILE)" + print " || defined(SQLITE_DEBUG)" print "const char *const sqlite3OpcodeNames[] = { \"?\"," } /^#define OP_/ { @@ -19,4 +23,5 @@ BEGIN { } END { print "};" + print "#endif" } diff --git a/src/btree.c b/src/btree.c index 677e48c61f..41c6519956 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.193 2004/10/22 16:22:58 drh Exp $ +** $Id: btree.c,v 1.194 2004/10/31 02:22:49 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -4067,6 +4067,7 @@ struct IntegrityCk { char *zErrMsg; /* An error message. NULL of no errors seen. */ }; +#ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Append a message to the error message string. */ @@ -4092,7 +4093,9 @@ static void checkAppendMsg( } sqliteFree(zMsg2); } +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ +#ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Add 1 to the reference count for page iPage. If this is the second ** reference to the page, add an error message to pCheck->zErrMsg. @@ -4113,7 +4116,9 @@ static int checkRef(IntegrityCk *pCheck, int iPage, char *zContext){ } return (pCheck->anRef[iPage]++)>1; } +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ +#ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Check the integrity of the freelist or of an overflow page list. ** Verify that the number of pages on the list is N. @@ -4158,7 +4163,9 @@ static void checkList( sqlite3pager_unref(pOvfl); } } +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ +#ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** Do various sanity checks on a single page of a tree. Return ** the tree depth. Root pages return 0. Parents of root pages @@ -4296,7 +4303,9 @@ static int checkTreePage( releasePage(pPage); return depth+1; } +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ +#ifndef SQLITE_OMIT_INTEGRITY_CHECK /* ** This routine does a complete check of the given BTree file. aRoot[] is ** an array of pages numbers were each page number is the root page of @@ -4366,6 +4375,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *pBt, int *aRoot, int nRoot){ sqliteFree(sCheck.anRef); return sCheck.zErrMsg; } +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* ** Return the full pathname of the underlying database file. @@ -4393,6 +4403,7 @@ const char *sqlite3BtreeGetJournalname(Btree *pBt){ return sqlite3pager_journalname(pBt->pPager); } +#ifndef SQLITE_OMIT_VACUUM /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. @@ -4434,6 +4445,7 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ } return rc; } +#endif /* SQLITE_OMIT_VACUUM */ /* ** Return non-zero if a transaction is active. diff --git a/src/build.c b/src/build.c index 7ae1868af4..250ca28338 100644 --- a/src/build.c +++ b/src/build.c @@ -23,7 +23,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.257 2004/10/06 15:41:16 drh Exp $ +** $Id: build.c,v 1.258 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" #include @@ -1400,6 +1400,7 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ } } +#ifndef SQLITE_OMIT_VIEW /* ** The parser calls this routine in order to create a new VIEW */ @@ -1461,7 +1462,9 @@ void sqlite3CreateView( sqlite3EndTable(pParse, &sEnd, 0); return; } +#endif /* SQLITE_OMIT_VIEW */ +#ifndef SQLITE_OMIT_VIEW /* ** The Table structure pTable is really a VIEW. Fill in the names of ** the columns of the view in the pTable structure. Return the number @@ -1530,7 +1533,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){ pSel->pEList = pEList; return nErr; } +#endif /* SQLITE_OMIT_VIEW */ +#ifndef SQLITE_OMIT_VIEW /* ** Clear the column names from every VIEW in database idx. */ @@ -1545,6 +1550,9 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){ } DbClearProperty(db, idx, DB_UnresetViews); } +#else +# define sqliteViewResetAll(A,B) +#endif /* SQLITE_OMIT_VIEW */ /* ** This routine is called to do the work of a DROP TABLE statement. @@ -1693,12 +1701,13 @@ void sqlite3CreateForeignKey( ExprList *pToCol, /* Columns in the other table */ int flags /* Conflict resolution algorithms. */ ){ + FKey *pFKey = 0; +#ifndef SQLITE_OMIT_FOREIGN_KEY Table *p = pParse->pNewTable; int nByte; int i; int nCol; char *z; - FKey *pFKey = 0; assert( pTo!=0 ); if( p==0 || pParse->nErr ) goto fk_end; @@ -1779,6 +1788,7 @@ void sqlite3CreateForeignKey( fk_end: sqliteFree(pFKey); +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ sqlite3ExprListDelete(pFromCol); sqlite3ExprListDelete(pToCol); } @@ -1791,10 +1801,12 @@ fk_end: ** accordingly. */ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){ +#ifndef SQLITE_OMIT_FOREIGN_KEY Table *pTab; FKey *pFKey; if( (pTab = pParse->pNewTable)==0 || (pFKey = pTab->pFKey)==0 ) return; pFKey->isDeferred = isDeferred; +#endif } /* diff --git a/src/delete.c b/src/delete.c index d6d4cd7334..e9b2bf7070 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 ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.83 2004/10/22 20:29:22 drh Exp $ +** $Id: delete.c,v 1.84 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" @@ -104,12 +104,28 @@ void sqlite3DeleteFrom( */ pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ) goto delete_from_cleanup; + + /* Figure out if we have any triggers and if the table being + ** deleted from is a view + */ +#ifndef SQLITE_OMIT_TRIGGER before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_DELETE, TK_BEFORE, TK_ROW, 0); after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_DELETE, TK_AFTER, TK_ROW, 0); row_triggers_exist = before_triggers || after_triggers; isView = pTab->pSelect!=0; +#else +# define before_triggers 0 +# define after_triggers 0 +# define row_triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ goto delete_from_cleanup; } diff --git a/src/expr.c b/src/expr.c index 75167579b3..daf7dc4929 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.166 2004/10/04 13:19:24 drh Exp $ +** $Id: expr.c,v 1.167 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" #include @@ -700,6 +700,7 @@ static int lookupName( } } +#ifndef SQLITE_OMIT_TRIGGER /* If we have not already resolved the name, then maybe ** it is a new.* or old.* trigger argument reference */ @@ -733,6 +734,7 @@ static int lookupName( } } } +#endif /* !defined(SQLITE_OMIT_TRIGGER) */ /* ** Perhaps the name is a reference to the ROWID diff --git a/src/insert.c b/src/insert.c index 114942e8c4..d7a202a5df 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.119 2004/10/05 02:41:42 drh Exp $ +** $Id: insert.c,v 1.120 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" @@ -213,16 +213,31 @@ void sqlite3Insert( goto insert_cleanup; } + /* Figure out if we have any triggers and if the table being + ** inserted into is a view + */ +#ifndef SQLITE_OMIT_TRIGGER + before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, + TK_INSERT, TK_BEFORE, TK_ROW, 0); + after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, + TK_INSERT, TK_AFTER, TK_ROW, 0); + row_triggers_exist = before_triggers || after_triggers; + isView = pTab->pSelect!=0; +#else +# define before_triggers 0 +# define after_triggers 0 +# define row_triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + /* Ensure that: * (a) the table is not read-only, * (b) that if it is a view then ON INSERT triggers exist */ - before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT, - TK_BEFORE, TK_ROW, 0); - after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, TK_INSERT, - TK_AFTER, TK_ROW, 0); - row_triggers_exist = before_triggers || after_triggers; - isView = pTab->pSelect!=0; if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ goto insert_cleanup; } diff --git a/src/pager.c b/src/pager.c index fe06e2a4b3..2395649ade 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.168 2004/10/22 16:22:59 drh Exp $ +** @(#) $Id: pager.c,v 1.169 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -308,6 +308,21 @@ static const unsigned char aJournalMagic[] = { */ #define JOURNAL_HDR_SZ(pPager) (pPager->sectorSize) +/* +** The macro MEMDB is true if we are dealing with an in-memory database. +** We do this as a macro so that if the SQLITE_OMIT_MEMORYDB macro is set, +** the value of MEMDB will be a constant and the compiler will optimize +** out code that would never execute. +*/ +#ifdef SQLITE_OMIT_MEMORYDB +# define MEMDB 0 +#else +# define MEMDB pPager->memDb +#endif + +/* +** The default size of a disk sector +*/ #define PAGER_SECTOR_SIZE 512 /* @@ -779,7 +794,7 @@ static void pager_reset(Pager *pPager){ static int pager_unwritelock(Pager *pPager){ PgHdr *pPg; int rc; - assert( !pPager->memDb ); + assert( !MEMDB ); if( pPager->statememDb==0 ){ + if( MEMDB==0 ){ sqlite3OsSeek(&pPager->fd, 0); sqlite3OsRead(&pPager->fd, pDest, N); } @@ -1602,7 +1620,7 @@ int sqlite3pager_pagecount(Pager *pPager){ return 0; } n /= pPager->pageSize; - if( !pPager->memDb && n==PENDING_BYTE/pPager->pageSize ){ + if( !MEMDB && n==PENDING_BYTE/pPager->pageSize ){ n++; } if( pPager->state!=PAGER_UNLOCK ){ @@ -1699,7 +1717,7 @@ int sqlite3pager_truncate(Pager *pPager, Pgno nPage){ if( nPage>=(unsigned)pPager->dbSize ){ return SQLITE_OK; } - if( pPager->memDb ){ + if( MEMDB ){ pPager->dbSize = nPage; memoryTruncate(pPager); return SQLITE_OK; @@ -1731,14 +1749,14 @@ int sqlite3pager_close(Pager *pPager){ case PAGER_SYNCED: case PAGER_EXCLUSIVE: { sqlite3pager_rollback(pPager); - if( !pPager->memDb ){ + if( !MEMDB ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } assert( pPager->journalOpen==0 ); break; } case PAGER_SHARED: { - if( !pPager->memDb ){ + if( !MEMDB ){ sqlite3OsUnlock(&pPager->fd, NO_LOCK); } break; @@ -1750,7 +1768,7 @@ int sqlite3pager_close(Pager *pPager){ } for(pPg=pPager->pAll; pPg; pPg=pNext){ #ifndef NDEBUG - if( pPager->memDb ){ + if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); assert( !pPg->alwaysRollback ); assert( !pHist->pOrig ); @@ -2066,7 +2084,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ /* If this is the first page accessed, then get a SHARED lock ** on the database file. */ - if( pPager->nRef==0 && !pPager->memDb ){ + if( pPager->nRef==0 && !MEMDB ){ rc = pager_wait_on_lock(pPager, SHARED_LOCK); if( rc!=SQLITE_OK ){ return rc; @@ -2132,7 +2150,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ }else{ /* Search for page in cache */ pPg = pager_lookup(pPager, pgno); - if( pPager->memDb && pPager->state==PAGER_UNLOCK ){ + if( MEMDB && pPager->state==PAGER_UNLOCK ){ pPager->state = PAGER_SHARED; } } @@ -2140,20 +2158,20 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ /* The requested page is not in the page cache. */ int h; pPager->nMiss++; - if( pPager->nPagemxPage || pPager->pFirst==0 || pPager->memDb ){ + if( pPager->nPagemxPage || pPager->pFirst==0 || MEMDB ){ /* Create a new page */ pPg = sqliteMallocRaw( sizeof(*pPg) + pPager->psAligned + sizeof(u32) + pPager->nExtra - + pPager->memDb*sizeof(PgHistory) ); + + MEMDB*sizeof(PgHistory) ); if( pPg==0 ){ - if( !pPager->memDb ){ + if( !MEMDB ){ pager_unwritelock(pPager); } pPager->errMask |= PAGER_ERR_MEM; return SQLITE_NOMEM; } memset(pPg, 0, sizeof(*pPg)); - if( pPager->memDb ){ + if( MEMDB ){ memset(PGHDR_TO_HIST(pPg, pPager), 0, sizeof(PgHistory)); } pPg->pPager = pPager; @@ -2266,7 +2284,7 @@ int sqlite3pager_get(Pager *pPager, Pgno pgno, void **ppPage){ memset(PGHDR_TO_DATA(pPg), 0, pPager->pageSize); }else{ int rc; - assert( pPager->memDb==0 ); + assert( MEMDB==0 ); sqlite3OsSeek(&pPager->fd, (pgno-1)*(i64)pPager->pageSize); rc = sqlite3OsRead(&pPager->fd, PGHDR_TO_DATA(pPg), pPager->pageSize); TRACE3("FETCH %d page %d\n", pPager->fd.h, pPg->pgno); @@ -2360,7 +2378,7 @@ int sqlite3pager_unref(void *pData){ */ pPager->nRef--; assert( pPager->nRef>=0 ); - if( pPager->nRef==0 && !pPager->memDb ){ + if( pPager->nRef==0 && !MEMDB ){ pager_reset(pPager); } } @@ -2376,7 +2394,7 @@ int sqlite3pager_unref(void *pData){ */ static int pager_open_journal(Pager *pPager){ int rc; - assert( !pPager->memDb ); + assert( !MEMDB ); assert( pPager->state>=PAGER_RESERVED ); assert( pPager->journalOpen==0 ); assert( pPager->useJournal ); @@ -2461,7 +2479,7 @@ int sqlite3pager_begin(void *pData, int exFlag){ assert( pPager->state!=PAGER_UNLOCK ); if( pPager->state==PAGER_SHARED ){ assert( pPager->aInJournal==0 ); - if( pPager->memDb ){ + if( MEMDB ){ pPager->state = PAGER_EXCLUSIVE; pPager->origDbSize = pPager->dbSize; }else{ @@ -2555,11 +2573,11 @@ int sqlite3pager_write(void *pData){ ** EXCLUSIVE lock on the main database file. Write the current page to ** the transaction journal if it is not there already. */ - if( !pPg->inJournal && (pPager->useJournal || pPager->memDb) ){ + if( !pPg->inJournal && (pPager->useJournal || MEMDB) ){ if( (int)pPg->pgno <= pPager->origDbSize ){ int szPg; u32 saved; - if( pPager->memDb ){ + if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); TRACE3("JOURNAL %d page %d\n", pPager->fd.h, pPg->pgno); assert( pHist->pOrig==0 ); @@ -2613,7 +2631,7 @@ int sqlite3pager_write(void *pData){ */ if( pPager->stmtInUse && !pPg->inStmt && (int)pPg->pgno<=pPager->stmtSize ){ assert( pPg->inJournal || (int)pPg->pgno>pPager->origDbSize ); - if( pPager->memDb ){ + if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); assert( pHist->pStmt==0 ); pHist->pStmt = sqliteMallocRaw( pPager->pageSize ); @@ -2643,7 +2661,7 @@ int sqlite3pager_write(void *pData){ */ if( pPager->dbSize<(int)pPg->pgno ){ pPager->dbSize = pPg->pgno; - if( !pPager->memDb && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){ + if( !MEMDB && pPager->dbSize==PENDING_BYTE/pPager->pageSize ){ pPager->dbSize++; } } @@ -2706,7 +2724,7 @@ int sqlite3pager_overwrite(Pager *pPager, Pgno pgno, void *pData){ void sqlite3pager_dont_write(Pager *pPager, Pgno pgno){ PgHdr *pPg; - if( pPager->memDb ) return; + if( MEMDB ) return; pPg = pager_lookup(pPager, pgno); pPg->alwaysRollback = 1; @@ -2738,7 +2756,7 @@ void sqlite3pager_dont_rollback(void *pData){ Pager *pPager = pPg->pPager; if( pPager->state!=PAGER_EXCLUSIVE || pPager->journalOpen==0 ) return; - if( pPg->alwaysRollback || pPager->alwaysRollback || pPager->memDb ) return; + if( pPg->alwaysRollback || pPager->alwaysRollback || MEMDB ) return; if( !pPg->inJournal && (int)pPg->pgno <= pPager->origDbSize ){ assert( pPager->aInJournal!=0 ); pPager->aInJournal[pPg->pgno/8] |= 1<<(pPg->pgno&7); @@ -2794,7 +2812,7 @@ int sqlite3pager_commit(Pager *pPager){ return SQLITE_ERROR; } TRACE2("COMMIT %d\n", pPager->fd.h); - if( pPager->memDb ){ + if( MEMDB ){ pPg = pager_get_all_dirty_pages(pPager); while( pPg ){ clearHistory(PGHDR_TO_HIST(pPg, pPager)); @@ -2855,7 +2873,7 @@ commit_abort: int sqlite3pager_rollback(Pager *pPager){ int rc; TRACE2("ROLLBACK %d\n", pPager->fd.h); - if( pPager->memDb ){ + if( MEMDB ){ PgHdr *p; for(p=pPager->pAll; p; p=p->pNextAll){ PgHistory *pHist; @@ -2962,7 +2980,7 @@ int sqlite3pager_stmt_begin(Pager *pPager){ assert( !pPager->stmtInUse ); assert( pPager->dbSize>=0 ); TRACE2("STMT-BEGIN %d\n", pPager->fd.h); - if( pPager->memDb ){ + if( MEMDB ){ pPager->stmtInUse = 1; pPager->stmtSize = pPager->dbSize; return SQLITE_OK; @@ -3010,7 +3028,7 @@ int sqlite3pager_stmt_commit(Pager *pPager){ if( pPager->stmtInUse ){ PgHdr *pPg, *pNext; TRACE2("STMT-COMMIT %d\n", pPager->fd.h); - if( !pPager->memDb ){ + if( !MEMDB ){ sqlite3OsSeek(&pPager->stfd, 0); /* sqlite3OsTruncate(&pPager->stfd, 0); */ sqliteFree( pPager->aInStmt ); @@ -3021,7 +3039,7 @@ int sqlite3pager_stmt_commit(Pager *pPager){ assert( pPg->inStmt ); pPg->inStmt = 0; pPg->pPrevStmt = pPg->pNextStmt = 0; - if( pPager->memDb ){ + if( MEMDB ){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); sqliteFree(pHist->pStmt); pHist->pStmt = 0; @@ -3042,7 +3060,7 @@ int sqlite3pager_stmt_rollback(Pager *pPager){ int rc; if( pPager->stmtInUse ){ TRACE2("STMT-ROLLBACK %d\n", pPager->fd.h); - if( pPager->memDb ){ + if( MEMDB ){ PgHdr *pPg; for(pPg=pPager->pStmt; pPg; pPg=pPg->pNextStmt){ PgHistory *pHist = PGHDR_TO_HIST(pPg, pPager); @@ -3148,7 +3166,7 @@ int sqlite3pager_sync(Pager *pPager, const char *zMaster){ /* If this is an in-memory db, or no pages have been written to, or this ** function has already been called, it is a no-op. */ - if( pPager->state!=PAGER_SYNCED && !pPager->memDb && pPager->dirtyCache ){ + if( pPager->state!=PAGER_SYNCED && !MEMDB && pPager->dirtyCache ){ PgHdr *pPg; assert( pPager->journalOpen ); diff --git a/src/parse.y b/src/parse.y index e9f9fc336c..8a4ee62e3d 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.144 2004/10/07 03:06:29 drh Exp $ +** @(#) $Id: parse.y,v 1.145 2004/10/31 02:22:49 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -81,11 +81,13 @@ struct AttachKey { int type; Token key; }; input ::= cmdlist. cmdlist ::= cmdlist ecmd. cmdlist ::= ecmd. -ecmd ::= explain cmdx SEMI. -ecmd ::= SEMI. cmdx ::= cmd. { sqlite3FinishCoding(pParse); } -explain ::= EXPLAIN. { sqlite3BeginParse(pParse, 1); } +ecmd ::= SEMI. +ecmd ::= explain cmdx SEMI. explain ::= . { sqlite3BeginParse(pParse, 0); } +%ifndef SQLITE_OMIT_EXPLAIN +explain ::= EXPLAIN. { sqlite3BeginParse(pParse, 1); } +%endif ///////////////////// Begin and end transactions. //////////////////////////// // @@ -144,7 +146,11 @@ id(A) ::= ID(X). {A = X;} DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR GLOB IGNORE IMMEDIATE INITIALLY INSTEAD LIKE MATCH KEY OF OFFSET PRAGMA RAISE REPLACE RESTRICT ROW STATEMENT - TEMP TRIGGER VACUUM VIEW. + TEMP TRIGGER VACUUM VIEW +%ifdef SQLITE_OMIT_COMPOUND_SELECT + EXCEPT INTERSECT UNION +%endif + . // Define operator precedence early so that this is the first occurance // of the operator tokens in the grammer. Keeping the operators together @@ -285,12 +291,14 @@ cmd ::= DROP TABLE fullname(X). { ///////////////////// The CREATE VIEW statement ///////////////////////////// // +%ifndef SQLITE_OMIT_VIEW cmd ::= CREATE(X) temp(T) VIEW nm(Y) dbnm(Z) AS select(S). { sqlite3CreateView(pParse, &X, &Y, &Z, S, T); } cmd ::= DROP VIEW fullname(X). { sqlite3DropTable(pParse, X, 1); } +%endif // SQLITE_OMIT_VIEW //////////////////////// The SELECT statement ///////////////////////////////// // @@ -305,6 +313,7 @@ cmd ::= select(X). { %destructor oneselect {sqlite3SelectDelete($$);} select(A) ::= oneselect(X). {A = X;} +%ifndef SQLITE_OMIT_COMPOUND_SELECT select(A) ::= select(X) multiselect_op(Y) oneselect(Z). { if( Z ){ Z->op = Y; @@ -317,6 +326,7 @@ multiselect_op(A) ::= UNION(OP). {A = @OP;} multiselect_op(A) ::= UNION ALL. {A = TK_ALL;} multiselect_op(A) ::= INTERSECT(OP). {A = @OP;} multiselect_op(A) ::= EXCEPT(OP). {A = @OP;} +%endif // SQLITE_OMIT_COMPOUND_SELECT oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { A = sqlite3SelectNew(W,X,Y,P,Q,Z,D,L.limit,L.offset); @@ -793,6 +803,8 @@ plus_opt ::= . //////////////////////////// The CREATE TRIGGER command ///////////////////// +%ifndef SQLITE_OMIT_TRIGGER + cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). { Token all; all.z = A.z; @@ -869,6 +881,8 @@ expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). { A->iColumn = T; sqlite3ExprSpan(A, &X, &Y); } +%endif // !SQLITE_OMIT_TRIGGER + %type raisetype {int} raisetype(A) ::= ROLLBACK. {A = OE_Rollback;} raisetype(A) ::= ABORT. {A = OE_Abort;} @@ -876,9 +890,11 @@ raisetype(A) ::= FAIL. {A = OE_Fail;} //////////////////////// DROP TRIGGER statement ////////////////////////////// +%ifndef SQLITE_OMIT_TRIGGER cmd ::= DROP TRIGGER fullname(X). { sqlite3DropTrigger(pParse,X); } +%endif // !SQLITE_OMIT_TRIGGER //////////////////////// ATTACH DATABASE file AS name ///////////////////////// cmd ::= ATTACH database_kw_opt ids(F) AS nm(D) key_opt(K). { diff --git a/src/pragma.c b/src/pragma.c index d238d4264f..4b10e12333 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.72 2004/10/25 20:33:44 drh Exp $ +** $Id: pragma.c,v 1.73 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" #include @@ -444,6 +444,7 @@ void sqlite3Pragma( } }else +#ifndef SQLITE_OMIT_FOREIGN_KEY if( sqlite3StrICmp(zLeft, "foreign_key_list")==0 && zRight ){ FKey *pFK; Table *pTab; @@ -477,6 +478,7 @@ void sqlite3Pragma( } } }else +#endif /* !defined(SQLITE_OMIT_FOREIGN_KEY) */ if( sqlite3StrICmp(zLeft, "database_list")==0 ){ int i; @@ -507,6 +509,7 @@ void sqlite3Pragma( }else #endif +#ifndef SQLITE_OMIT_INTEGRITY_CHECK if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){ int i, j, addr; @@ -631,6 +634,8 @@ void sqlite3Pragma( addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode); sqlite3VdbeChangeP2(v, addr+2, addr+ArraySize(endCode)); }else +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ + /* ** PRAGMA encoding ** PRAGMA encoding = "utf-8"|"utf-16"|"utf-16le"|"utf-16be" diff --git a/src/select.c b/src/select.c index 75ff2fbef5..155ae9c0a2 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.212 2004/10/06 15:41:17 drh Exp $ +** $Id: select.c,v 1.213 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" @@ -1282,6 +1282,7 @@ static int openTempIndex(Parse *pParse, Select *p, int iTab, int keyAsData){ return addr; } +#ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** Add the address "addr" to the set of all OpenTemp opcode addresses ** that are being accumulated in p->ppOpenTemp. @@ -1294,7 +1295,9 @@ static int multiSelectOpenTempAddr(Select *p, int addr){ pList->a[pList->nId-1].idx = addr; return SQLITE_OK; } +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ +#ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** Return the appropriate collating sequence for the iCol-th column of ** the result set for the compound-select statement "p". Return NULL if @@ -1315,7 +1318,9 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ } return pRet; } +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ +#ifndef SQLITE_OMIT_COMPOUND_SELECT /* ** This routine is called to process a query that is really the union ** or intersection of two or more separate queries. @@ -1704,7 +1709,9 @@ multi_select_end: p->ppOpenTemp = 0; return rc; } +#endif /* SQLITE_OMIT_COMPOUND_SELECT */ +#ifndef SQLITE_OMIT_VIEW /* ** Scan through the expression pExpr. Replace every reference to ** a column in table number iTable with a copy of the iColumn-th @@ -1757,7 +1764,9 @@ substExprList(ExprList *pList, int iTable, ExprList *pEList){ substExpr(pList->a[i].pExpr, iTable, pEList); } } +#endif /* !defined(SQLITE_OMIT_VIEW) */ +#ifndef SQLITE_OMIT_VIEW /* ** This routine attempts to flatten subqueries in order to speed ** execution. It returns 1 if it makes changes and 0 if no flattening @@ -2009,6 +2018,7 @@ static int flattenSubquery( sqlite3SelectDelete(pSub); return 1; } +#endif /* SQLITE_OMIT_VIEW */ /* ** Analyze the SELECT statement passed in as an argument to see if it @@ -2262,11 +2272,13 @@ int sqlite3Select( if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1; if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; +#ifndef SQLITE_OMIT_COMPOUND_SELECT /* If there is are a sequence of queries, do the earlier ones first. */ if( p->pPrior ){ return multiSelect(pParse, p, eDest, iParm, aff); } +#endif /* Make local copies of the parameters for this query. */ @@ -2400,11 +2412,13 @@ int sqlite3Select( /* Check to see if this is a subquery that can be "flattened" into its parent. ** If flattening is a possiblity, do so and return immediately. */ +#ifndef SQLITE_OMIT_VIEW if( pParent && pParentAgg && flattenSubquery(pParse, pParent, parentTab, *pParentAgg, isAgg) ){ if( isAgg ) *pParentAgg = 1; return rc; } +#endif /* If there is an ORDER BY clause, resolve any collation sequences ** names that have been explicitly specified. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2380dc7381..6e2bf58904 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.328 2004/10/22 20:29:22 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.329 2004/10/31 02:22:49 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1259,8 +1259,14 @@ void sqlite3AddColumnType(Parse*,Token*,Token*); void sqlite3AddDefaultValue(Parse*,Token*,int); void sqlite3AddCollateType(Parse*, const char*, int); void sqlite3EndTable(Parse*,Token*,Select*); -void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int); -int sqlite3ViewGetColumnNames(Parse*,Table*); + +#ifndef SQLITE_OMIT_VIEW + void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int); + int sqlite3ViewGetColumnNames(Parse*,Table*); +#else +# define sqlite3ViewGetColumnNames(A,B) 0 +#endif + void sqlite3DropTable(Parse*, SrcList*, int); void sqlite3DeleteTable(sqlite3*, Table*); void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); @@ -1297,7 +1303,6 @@ Table *sqlite3LocateTable(Parse*,const char*, const char*); Index *sqlite3FindIndex(sqlite3*,const char*, const char*); void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*); void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*); -void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); void sqlite3Vacuum(Parse*, Token*); int sqlite3RunVacuum(char**, sqlite3*); char *sqlite3NameFromToken(Token*); @@ -1337,21 +1342,32 @@ int sqlite3SafetyOn(sqlite3*); int sqlite3SafetyOff(sqlite3*); int sqlite3SafetyCheck(sqlite3*); void sqlite3ChangeCookie(sqlite3*, Vdbe*, int); -void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, - int,Expr*,int); -void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); -void sqlite3DropTrigger(Parse*, SrcList*); -void sqlite3DropTriggerPtr(Parse*, Trigger*, int); -int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*); -int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, - int, int); -void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); -void sqlite3DeleteTriggerStep(TriggerStep*); -TriggerStep *sqlite3TriggerSelectStep(Select*); -TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*, Select*, int); -TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int); -TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*); -void sqlite3DeleteTrigger(Trigger*); + +#ifndef SQLITE_OMIT_TRIGGER + void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*, + int,Expr*,int); + void sqlite3FinishTrigger(Parse*, TriggerStep*, Token*); + void sqlite3DropTrigger(Parse*, SrcList*); + void sqlite3DropTriggerPtr(Parse*, Trigger*, int); + int sqlite3TriggersExist(Parse* , Trigger* , int , int , int, ExprList*); + int sqlite3CodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, + int, int); + void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*); + void sqlite3DeleteTriggerStep(TriggerStep*); + TriggerStep *sqlite3TriggerSelectStep(Select*); + TriggerStep *sqlite3TriggerInsertStep(Token*, IdList*, ExprList*,Select*,int); + TriggerStep *sqlite3TriggerUpdateStep(Token*, ExprList*, Expr*, int); + TriggerStep *sqlite3TriggerDeleteStep(Token*, Expr*); + void sqlite3DeleteTrigger(Trigger*); + void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*); +#else +# define sqlite3TriggersExist(A,B,C,D,E,F) 0 +# define sqlite3DeleteTrigger(A) +# define sqlite3DropTriggerPtr(A,B,C) +# define sqlite3UnlinkAndDeleteTrigger(A,B,C) +# define sqlite3CodeRowTrigger(A,B,C,D,E,F,G,H,I) 0 +#endif + int sqlite3JoinType(Parse*, Token*, Token*, Token*); void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); void sqlite3DeferForeignKey(Parse*, int); diff --git a/src/test1.c b/src/test1.c index 0c9d16d184..18458eff03 100644 --- a/src/test1.c +++ b/src/test1.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test1.c,v 1.105 2004/10/30 20:23:09 drh Exp $ +** $Id: test1.c,v 1.106 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -2491,7 +2491,7 @@ static void set_options(Tcl_Interp *interp){ #ifdef SQLITE_OMIT_DATETIME_FUNCS Tcl_SetVar2(interp, "sqlite_options", "datetime", "0", TCL_GLOBAL_ONLY); #else - Tcl_SetVar2(interp, "sqlite_options", "datatime", "1", TCL_GLOBAL_ONLY); + Tcl_SetVar2(interp, "sqlite_options", "datetime", "1", TCL_GLOBAL_ONLY); #endif #if defined(THREADSAFE) && THREADSAFE Tcl_SetVar2(interp, "sqlite_options", "threadsafe", "1", TCL_GLOBAL_ONLY); @@ -2528,6 +2528,36 @@ static void set_options(Tcl_Interp *interp){ #else Tcl_SetVar2(interp, "sqlite_options", "conflict", "1", TCL_GLOBAL_ONLY); #endif +#ifdef SQLITE_OMIT_FLOATING_POINT + Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "floatingpoint", "1", TCL_GLOBAL_ONLY); +#endif +#ifdef SQLITE_OMIT_MEMORYDB + Tcl_SetVar2(interp, "sqlite_options", "memorydb", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "memorydb", "1", TCL_GLOBAL_ONLY); +#endif +#ifdef SQLITE_OMIT_UTF16 + Tcl_SetVar2(interp, "sqlite_options", "utf16", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "utf16", "1", TCL_GLOBAL_ONLY); +#endif +#ifdef SQLITE_OMIT_EXPLAIN + Tcl_SetVar2(interp, "sqlite_options", "explain", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "explain", "1", TCL_GLOBAL_ONLY); +#endif +#ifdef SQLITE_OMIT_TCL_VARIABLE + Tcl_SetVar2(interp, "sqlite_options", "tclvar", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "tclvar", "1", TCL_GLOBAL_ONLY); +#endif +#ifdef SQLITE_OMIT_BLOB_LITERAL + Tcl_SetVar2(interp, "sqlite_options", "bloblit", "0", TCL_GLOBAL_ONLY); +#else + Tcl_SetVar2(interp, "sqlite_options", "bloblit", "1", TCL_GLOBAL_ONLY); +#endif } /* diff --git a/src/test3.c b/src/test3.c index b2974a77bb..cc62b8c23a 100644 --- a/src/test3.c +++ b/src/test3.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test3.c,v 1.52 2004/09/17 19:39:24 drh Exp $ +** $Id: test3.c,v 1.53 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -578,7 +578,11 @@ static int btree_integrity_check( for(i=0; i1 ? TK_VARIABLE : TK_ILLEGAL; return i; } +#ifndef SQLITE_OMIT_TCL_VARIABLE case '$': { *tokenType = TK_VARIABLE; if( z[1]=='{' ){ @@ -354,7 +357,9 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){ if( n==0 ) *tokenType = TK_ILLEGAL; } return i; - } + } +#endif +#ifndef SQLITE_OMIT_BLOB_LITERAL case 'x': case 'X': { if( (c=z[1])=='\'' || c=='"' ){ int delim = c; @@ -374,6 +379,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){ } /* Otherwise fall through to the next case */ } +#endif default: { if( !IdChar(*z) ){ break; @@ -502,14 +508,14 @@ abort_parse: ** Token types used by the sqlite3_complete() routine. See the header ** comments on that procedure for additional information. */ -#define tkEXPLAIN 0 -#define tkCREATE 1 -#define tkTEMP 2 -#define tkTRIGGER 3 -#define tkEND 4 -#define tkSEMI 5 -#define tkWS 6 -#define tkOTHER 7 +#define tkSEMI 0 +#define tkWS 1 +#define tkOTHER 2 +#define tkEXPLAIN 3 +#define tkCREATE 4 +#define tkTEMP 5 +#define tkTRIGGER 6 +#define tkEND 7 /* ** Return TRUE if the given SQL string ends in a semicolon. @@ -524,16 +530,16 @@ abort_parse: ** returns 1 if it ends in the START state and 0 if it ends ** in any other state. ** -** (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of +** (1) NORMAL We are in the middle of statement which ends with a single +** semicolon. +** +** (2) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** -** (2) CREATE The keyword CREATE has been seen at the beginning of a +** (3) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** -** (3) NORMAL We are in the middle of statement which ends with a single -** semicolon. -** ** (4) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** @@ -546,36 +552,51 @@ abort_parse: ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: ** -** (0) tkEXPLAIN The "explain" keyword. -** (1) tkCREATE The "create" keyword. -** (2) tkTEMP The "temp" or "temporary" keyword. -** (3) tkTRIGGER The "trigger" keyword. -** (4) tkEND The "end" keyword. -** (5) tkSEMI A semicolon. -** (6) tkWS Whitespace -** (7) tkOTHER Any other SQL token. +** (0) tkSEMI A semicolon. +** (1) tkWS Whitespace +** (2) tkOTHER Any other SQL token. +** (3) tkEXPLAIN The "explain" keyword. +** (4) tkCREATE The "create" keyword. +** (5) tkTEMP The "temp" or "temporary" keyword. +** (6) tkTRIGGER The "trigger" keyword. +** (7) tkEND The "end" keyword. ** ** Whitespace never causes a state transition and is always ignored. +** +** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed +** to recognize the end of a trigger can be omitted. All we have to do +** is look for a semicolon that is not part of an string or comment. */ int sqlite3_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ - /* The following matrix defines the transition from one state to another - ** according to what token is seen. trans[state][token] returns the - ** next state. +#ifndef SQLITE_OMIT_TRIGGER + /* A complex statement machine used to detect the end of a CREATE TRIGGER + ** statement. This is the normal case. */ static const u8 trans[7][8] = { /* Token: */ - /* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */ - /* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, }, - /* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, }, - /* 2 CREATE: */ { 3, 3, 2, 4, 3, 0, 2, 3, }, - /* 3 NORMAL: */ { 3, 3, 3, 3, 3, 0, 3, 3, }, - /* 4 TRIGGER: */ { 4, 4, 4, 4, 4, 5, 4, 4, }, - /* 5 SEMI: */ { 4, 4, 4, 4, 6, 5, 5, 4, }, - /* 6 END: */ { 4, 4, 4, 4, 4, 0, 6, 4, }, + /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ + /* 0 START: */ { 0, 0, 1, 2, 3, 1, 1, 1, }, + /* 1 NORMAL: */ { 0, 1, 1, 1, 1, 1, 1, 1, }, + /* 2 EXPLAIN: */ { 0, 2, 1, 1, 3, 1, 1, 1, }, + /* 3 CREATE: */ { 0, 3, 1, 1, 1, 3, 4, 1, }, + /* 4 TRIGGER: */ { 5, 4, 4, 4, 4, 4, 4, 4, }, + /* 5 SEMI: */ { 5, 5, 4, 4, 4, 4, 4, 6, }, + /* 6 END: */ { 0, 6, 4, 4, 4, 4, 4, 4, }, }; +#else + /* If triggers are not suppored by this compile then the statement machine + ** used to detect the end of a statement is much simplier + */ + static const u8 trans[2][3] = { + /* Token: */ + /* State: ** SEMI WS OTHER */ + /* 0 START: */ { 0, 0, 1, }, + /* 1 NORMAL: */ { 0, 1, 1, }, + }; +#endif /* SQLITE_OMIT_TRIGGER */ while( *zSql ){ switch( *zSql ){ @@ -635,6 +656,9 @@ int sqlite3_complete(const char *zSql){ /* Keywords and unquoted identifiers */ int nId; for(nId=1; IdChar(zSql[nId]); nId++){} +#ifdef SQLITE_OMIT_TRIGGER + token = tkOTHER; +#else switch( *zSql ){ case 'c': case 'C': { if( nId==6 && sqlite3StrNICmp(zSql, "create", 6)==0 ){ @@ -659,9 +683,13 @@ int sqlite3_complete(const char *zSql){ case 'e': case 'E': { if( nId==3 && sqlite3StrNICmp(zSql, "end", 3)==0 ){ token = tkEND; - }else if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ + }else +#ifndef SQLITE_OMIT_EXPLAIN + if( nId==7 && sqlite3StrNICmp(zSql, "explain", 7)==0 ){ token = tkEXPLAIN; - }else{ + }else +#endif + { token = tkOTHER; } break; @@ -671,6 +699,7 @@ int sqlite3_complete(const char *zSql){ break; } } +#endif /* SQLITE_OMIT_TRIGGER */ zSql += nId-1; }else{ /* Operators and special symbols */ @@ -685,6 +714,7 @@ int sqlite3_complete(const char *zSql){ return state==0; } +#ifndef SQLITE_OMIT_UTF16 /* ** This routine is the same as the sqlite3_complete() routine described ** above, except that the parameter is required to be UTF-16 encoded, not @@ -704,3 +734,4 @@ int sqlite3_complete16(const void *zSql){ sqlite3ValueFree(pVal); return rc; } +#endif /* SQLITE_OMIT_UTF16 */ diff --git a/src/trigger.c b/src/trigger.c index bbb526f802..90b8b775e0 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -12,6 +12,7 @@ */ #include "sqliteInt.h" +#ifndef SQLITE_OMIT_TRIGGER /* ** Delete a linked list of TriggerStep structures. */ @@ -802,3 +803,4 @@ int sqlite3CodeRowTrigger( } return 0; } +#endif /* !defined(SQLITE_OMIT_TRIGGER) */ diff --git a/src/update.c b/src/update.c index ca15000786..1905c3073b 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.90 2004/10/05 02:41:43 drh Exp $ +** $Id: update.c,v 1.91 2004/10/31 02:22:49 drh Exp $ */ #include "sqliteInt.h" @@ -67,12 +67,28 @@ void sqlite3Update( */ pTab = sqlite3SrcListLookup(pParse, pTabList); if( pTab==0 ) goto update_cleanup; + + /* Figure out if we have any triggers and if the table being + ** updated is a view + */ +#ifndef SQLITE_OMIT_TRIGGER before_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, - TK_UPDATE, TK_BEFORE, TK_ROW, pChanges); + TK_UPDATE, TK_BEFORE, TK_ROW, pChanges); after_triggers = sqlite3TriggersExist(pParse, pTab->pTrigger, - TK_UPDATE, TK_AFTER, TK_ROW, pChanges); + TK_UPDATE, TK_AFTER, TK_ROW, pChanges); row_triggers_exist = before_triggers || after_triggers; isView = pTab->pSelect!=0; +#else +# define before_triggers 0 +# define after_triggers 0 +# define row_triggers_exist 0 +# define isView 0 +#endif +#ifdef SQLITE_OMIT_VIEW +# undef isView +# define isView 0 +#endif + if( sqlite3IsReadOnly(pParse, pTab, before_triggers) ){ goto update_cleanup; } diff --git a/src/vdbe.c b/src/vdbe.c index 854a09577c..bcf37f465b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.419 2004/10/19 16:40:59 drh Exp $ +** $Id: vdbe.c,v 1.420 2004/10/31 02:22:50 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -3735,6 +3735,7 @@ case OP_DropTrigger: { } +#ifndef SQLITE_OMIT_INTEGRITY_CHECK /* Opcode: IntegrityCk * P2 * ** ** Do an analysis of the currently open database. Push onto the @@ -3786,6 +3787,7 @@ case OP_IntegrityCk: { sqliteFree(aRoot); break; } +#endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* Opcode: ListWrite * * * ** diff --git a/src/vdbeapi.c b/src/vdbeapi.c index f6047f6fbe..bd39a539f4 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -177,9 +177,12 @@ int sqlite3_step(sqlite3_stmt *pStmt){ db->activeVdbeCnt++; p->pc = 0; } +#ifndef SQLITE_OMIT_EXPLAIN if( p->explain ){ rc = sqlite3VdbeList(p); - }else{ + }else +#endif /* SQLITE_OMIT_EXPLAIN */ + { rc = sqlite3VdbeExec(p); } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index fa9751daab..b2fad8e39a 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -375,6 +375,8 @@ VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){ return &p->aOp[addr]; } +#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ + || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) /* ** Compute a string that describes the P3 parameter for an opcode. ** Use zTemp for any required temporary buffer space. @@ -444,6 +446,7 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){ } return zP3; } +#endif #if !defined(NDEBUG) || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) @@ -473,6 +476,7 @@ static void releaseMemArray(Mem *p, int N){ } } +#ifndef SQLITE_OMIT_EXPLAIN /* ** Give a listing of the program in the virtual machine. ** @@ -549,6 +553,7 @@ int sqlite3VdbeList( } return rc; } +#endif /* SQLITE_OMIT_EXPLAIN */ /* ** Print the SQL that was used to generate a VDBE program. diff --git a/test/attach.test b/test/attach.test index dc511f12b1..26376d7bb5 100644 --- a/test/attach.test +++ b/test/attach.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach.test,v 1.26 2004/08/18 15:58:24 drh Exp $ +# $Id: attach.test,v 1.27 2004/10/31 02:22:50 drh Exp $ # set testdir [file dirname $argv0] @@ -205,6 +205,7 @@ do_test attach-1.29 { db_list db } {0 main 1 temp} +ifcapable {trigger} { # Only do the following tests if triggers are enabled do_test attach-2.1 { execsql { CREATE TABLE tx(x1,x2,y1,y2); @@ -292,6 +293,7 @@ do_test attach-2.16 { SELECT type, name, tbl_name FROM db2.sqlite_master; } } {table t2 t2 table tx tx trigger r1 t2 index i2 t2} +} ;# End of ifcapable {trigger} do_test attach-3.1 { db close @@ -302,6 +304,24 @@ do_test attach-3.1 { SELECT * FROM t1 } } {1 2 3 4} + +# If we are testing a version of the code that lacks trigger support, +# adjust the database contents so that they are the same if triggers +# had been enabled. +ifcapable {!trigger} { + db2 eval { + DELETE FROM t2; + INSERT INTO t2 VALUES(21, 'x'); + INSERT INTO t2 VALUES(22, 'y'); + CREATE TABLE tx(x1,x2,y1,y2); + INSERT INTO tx VALUES(1, 11, 'x', 'x'); + INSERT INTO tx VALUES(2, 12, 'y', 'y'); + INSERT INTO tx VALUES(11, 21, 'x', 'x'); + INSERT INTO tx VALUES(12, 22, 'y', 'y'); + CREATE INDEX i2 ON t2(x); + } +} + do_test attach-3.2 { catchsql { SELECT * FROM t2 @@ -434,29 +454,31 @@ do_test attach-4.5 { SELECT * FROM db2.t3; } } {1 2 9 10} -do_test attach-4.6 { - execsql { - DETACH db2; - } - execsql { - CREATE TABLE t4(x); - CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN - INSERT INTO t4 VALUES('db2.' || NEW.x); - END; - INSERT INTO t3 VALUES(6,7); - SELECT * FROM t4; - } db2 -} {db2.6} -do_test attach-4.7 { - execsql { - CREATE TABLE t4(y); - CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN - INSERT INTO t4 VALUES('main.' || NEW.a); - END; - INSERT INTO main.t3 VALUES(11,12); - SELECT * FROM main.t4; - } -} {main.11} +ifcapable {trigger} { + do_test attach-4.6 { + execsql { + DETACH db2; + } + execsql { + CREATE TABLE t4(x); + CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN + INSERT INTO t4 VALUES('db2.' || NEW.x); + END; + INSERT INTO t3 VALUES(6,7); + SELECT * FROM t4; + } db2 + } {db2.6} + do_test attach-4.7 { + execsql { + CREATE TABLE t4(y); + CREATE TRIGGER t3r3 AFTER INSERT ON t3 BEGIN + INSERT INTO t4 VALUES('main.' || NEW.a); + END; + INSERT INTO main.t3 VALUES(11,12); + SELECT * FROM main.t4; + } + } {main.11} +} # This one is tricky. On the UNION ALL select, we have to make sure # the schema for both main and db2 is valid before starting to execute diff --git a/test/date.test b/test/date.test index a234e7a082..a0150a610a 100644 --- a/test/date.test +++ b/test/date.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing date and time functions. # -# $Id: date.test,v 1.10 2004/10/30 20:23:10 drh Exp $ +# $Id: date.test,v 1.11 2004/10/31 02:22:50 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -19,7 +19,7 @@ source $testdir/tester.tcl # Skip this whole file if date and time functions are omitted # at compile-time # -if {!$sqlite_options(datetime)} { +ifcapable {!datetime} { finish_test return } diff --git a/test/trigger1.test b/test/trigger1.test index 80bd313465..5978a3e8b3 100644 --- a/test/trigger1.test +++ b/test/trigger1.test @@ -29,8 +29,12 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +ifcapable {!trigger} { + finish_test + return +} -do_test trigger1-1.1.2 { +do_test trigger1-1.1.1 { catchsql { CREATE TRIGGER trig UPDATE ON no_such_table BEGIN SELECT * from sqlite_master; diff --git a/test/trigger2.test b/test/trigger2.test index 33d1108df8..d24e801056 100644 --- a/test/trigger2.test +++ b/test/trigger2.test @@ -49,6 +49,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +ifcapable {!trigger} { + finish_test + return +} # 1. set ii 0 diff --git a/test/trigger3.test b/test/trigger3.test index 955d385b91..d13effcf54 100644 --- a/test/trigger3.test +++ b/test/trigger3.test @@ -13,6 +13,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +ifcapable {!trigger} { + finish_test + return +} # Test that we can cause ROLLBACK, FAIL and ABORT correctly # catchsql { DROP TABLE tbl; } diff --git a/test/trigger4.test b/test/trigger4.test index 16ed467814..6607a43252 100644 --- a/test/trigger4.test +++ b/test/trigger4.test @@ -12,6 +12,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +ifcapable {!trigger} { + finish_test + return +} do_test trigger4-1.1 { execsql { diff --git a/test/trigger5.test b/test/trigger5.test index 587c69d1cf..75c56b19c9 100644 --- a/test/trigger5.test +++ b/test/trigger5.test @@ -12,6 +12,10 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl +ifcapable {!trigger} { + finish_test + return +} # Ticket #844 #