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:
parent
27d258a3ec
commit
b7f9164e98
62
manifest
62
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
|
||||
|
@ -1 +1 @@
|
||||
2aa506ccb003a25555b414772002d0130db93052
|
||||
be661acfa849bb0d5692797dd221f5a8a457f8ad
|
@ -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"
|
||||
}
|
||||
|
14
src/btree.c
14
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.
|
||||
|
16
src/build.c
16
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 <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
|
||||
}
|
||||
|
||||
/*
|
||||
|
18
src/delete.c
18
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
29
src/insert.c
29
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;
|
||||
}
|
||||
|
82
src/pager.c
82
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->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 );
|
||||
|
||||
|
26
src/parse.y
26
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). {
|
||||
|
@ -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"
|
||||
|
16
src/select.c
16
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.
|
||||
|
@ -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);
|
||||
|
34
src/test1.c
34
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
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
103
src/tokenize.c
103
src/tokenize.c
@ -15,7 +15,7 @@
|
||||
** individual tokens and sends those tokens one-by-one over to the
|
||||
** parser for analysis.
|
||||
**
|
||||
** $Id: tokenize.c,v 1.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 */
|
||||
|
@ -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) */
|
||||
|
22
src/update.c
22
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;
|
||||
}
|
||||
|
@ -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 * * *
|
||||
**
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -49,6 +49,10 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable {!trigger} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# 1.
|
||||
set ii 0
|
||||
|
@ -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; }
|
||||
|
@ -12,6 +12,10 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable {!trigger} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_test trigger4-1.1 {
|
||||
execsql {
|
||||
|
@ -12,6 +12,10 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable {!trigger} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
# Ticket #844
|
||||
#
|
||||
|
Loading…
x
Reference in New Issue
Block a user