Insert #ifdefs that can optionally remove features at compiletime resulting

in a database engine with a smaller footprint. (CVS 2034)

FossilOrigin-Name: be661acfa849bb0d5692797dd221f5a8a457f8ad
This commit is contained in:
drh 2004-10-31 02:22:47 +00:00
parent 27d258a3ec
commit b7f9164e98
28 changed files with 439 additions and 173 deletions

View File

@ -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

View File

@ -1 +1 @@
2aa506ccb003a25555b414772002d0130db93052
be661acfa849bb0d5692797dd221f5a8a457f8ad

View File

@ -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"
}

View File

@ -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.

View File

@ -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 <ctype.h>
@ -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
}
/*

View File

@ -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;
}

View File

@ -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 <ctype.h>
@ -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

View File

@ -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;
}

View File

@ -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->state<PAGER_RESERVED ){
return SQLITE_OK;
}
@ -1454,11 +1469,14 @@ int sqlite3pager_open(
return SQLITE_NOMEM;
}
if( zFilename && zFilename[0] ){
#ifndef SQLITE_OMIT_MEMORYDB
if( strcmp(zFilename,":memory:")==0 ){
memDb = 1;
zFullPathname = sqliteStrDup("");
rc = SQLITE_OK;
}else{
}else
#endif
{
zFullPathname = sqlite3OsFullPathname(zFilename);
if( zFullPathname ){
rc = sqlite3OsOpenReadWrite(zFullPathname, &fd, &readOnly);
@ -1581,7 +1599,7 @@ void sqlite3pager_set_pagesize(Pager *pPager, int pageSize){
*/
void sqlite3pager_read_fileheader(Pager *pPager, int N, unsigned char *pDest){
memset(pDest, 0, N);
if( pPager->memDb==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->nPage<pPager->mxPage || pPager->pFirst==0 || pPager->memDb ){
if( pPager->nPage<pPager->mxPage || 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 );

View File

@ -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). {

View File

@ -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 <ctype.h>
@ -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"

View File

@ -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.

View File

@ -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);

View File

@ -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
}
/*

View File

@ -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; i<argc-2; i++){
if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
}
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot);
#else
zResult = "ok";
#endif
if( zResult ){
Tcl_AppendResult(interp, zResult, 0);
sqliteFree(zResult);

View File

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.92 2004/10/23 05:10:18 drh Exp $
** $Id: tokenize.c,v 1.93 2004/10/31 02:22:49 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -287,6 +287,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
case '5': case '6': case '7': case '8': case '9': {
*tokenType = TK_INTEGER;
for(i=1; isdigit(z[i]); i++){}
#ifndef SQLITE_OMIT_FLOATING_POINT
if( z[i]=='.' && isdigit(z[i+1]) ){
i += 2;
while( isdigit(z[i]) ){ i++; }
@ -301,6 +302,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
while( isdigit(z[i]) ){ i++; }
*tokenType = TK_FLOAT;
}
#endif
return i;
}
case '[': {
@ -318,6 +320,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
*tokenType = i>1 ? 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 */

View File

@ -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) */

View File

@ -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;
}

View File

@ -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 * * *
**

View File

@ -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);
}

View File

@ -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.

View File

@ -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

View File

@ -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
}

View File

@ -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;

View File

@ -49,6 +49,10 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
finish_test
return
}
# 1.
set ii 0

View File

@ -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; }

View File

@ -12,6 +12,10 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
finish_test
return
}
do_test trigger4-1.1 {
execsql {

View File

@ -12,6 +12,10 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
ifcapable {!trigger} {
finish_test
return
}
# Ticket #844
#