Changes to reduce the heap space consumed by triggers, views and tables in the in-memory representation of the schema. Also to reduce the space used by prepared statements slightly. (CVS 6305)

FossilOrigin-Name: d9f6ffbc5ea090ba0daac571fc9a6c68b9c864e4
This commit is contained in:
danielk1977 2009-02-19 14:39:25 +00:00
parent 076d4661a6
commit 6ab3a2ec8a
27 changed files with 664 additions and 366 deletions

View File

@ -1,5 +1,5 @@
C Make\ssure\sthe\sauto_vacuum=INCREMENTAL\ssetting\sis\spreserved\sacross\sa\sVACUUM.\nTicket\s#3663.\s(CVS\s6304)
D 2009-02-18T20:31:18
C Changes\sto\sreduce\sthe\sheap\sspace\sconsumed\sby\striggers,\sviews\sand\stables\sin\sthe\sin-memory\srepresentation\sof\sthe\sschema.\sAlso\sto\sreduce\sthe\sspace\sused\sby\sprepared\sstatements\sslightly.\s(CVS\s6305)
D 2009-02-19T14:39:25
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 1d83fa2b1fd326b9e121012bd1ff9740537e12b3
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -98,8 +98,8 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.def a1be7b9a4b8b51ac41c6ff6e8e44a14ef66b338b
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c f93d13aae63ea1a5ee604d76041be354311d08a5
F src/analyze.c fc6056826fe67aa0856d4e01591be8f9266ac415
F src/attach.c 81d37d1948f409146a7b22b96998fd90649d1fd3
F src/analyze.c 2ca143d83ce545992cab74efeb5e8a446c61ab4b
F src/attach.c d34589d5c85d81e755e4a8fc946d313915a6fa6d
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/backup.c 2d3f31148d7b086c5c72d9edcd04fc2751b0aa6e
F src/bitvec.c 44f7059ac1f874d364b34af31b9617e52223ba75
@ -107,19 +107,19 @@ F src/btmutex.c 63c5cc4ad5715690767ffcb741e185d7bc35ec1a
F src/btree.c 086fdb4505aa00275d6873829aeb51bf57da8d16
F src/btree.h 4eab72af6adf95f0b08b61a72ef9781bdb0bf63f
F src/btreeInt.h 0a4884e6152d7cae9c741e91b830064c19fd2c05
F src/build.c a394b2511c5c768f14a9d7c1c31606b9fa569f1b
F src/build.c 0860029ca6e29b2bfcadbbe90084e02af98d768f
F src/callback.c 5f10bca853e59a2c272bbfd5b720303f8b69e520
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
F src/date.c 0d804df3bbda46329946a01ff5c75c3f4f135218
F src/delete.c 6249005bdd8f85db6ec5f31ddb5c07de023693cc
F src/expr.c e60f69f624a03a8f493900b071b3affbfa699585
F src/delete.c 8d2fb05b32b5dea65277a574fedb0ebaa5dd877c
F src/expr.c 2e62c2621c0375125cacb93ad6686bb2911b629e
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
F src/func.c 35d6f4a98c5fd5d504fd92a9197bae3220bbac39
F src/func.c 2fb36cd7cc24e16845db203187d1e52811b0fa9c
F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
F src/hash.c 5824e6ff7ba78cd34c8d6cd724367713583e5b55
F src/hash.h 28f38ebb1006a5beedcb013bcdfe31befe7437ae
F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
F src/insert.c f6db1e6f43aae337e64a755208abb6ff124edc19
F src/insert.c 6bd2464ec48ddcb1d9c6fbfd294de91b5dd47075
F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
F src/legacy.c 8b3b95d48d202614946d7ce7256e7ba898905c3b
F src/loadext.c 3f96631089fc4f3871a67f02f2e4fc7ea4d51edc
@ -127,7 +127,7 @@ F src/main.c 4912460dab29e4d37e4ba1d78320c6a77bb95ad8
F src/malloc.c 552d993ee414ead65cafcaa636e22c84085999cb
F src/mem0.c f2f84062d1f35814d6535c9f9e33de3bfb3b132c
F src/mem1.c 3bfb39e4f60b0179713a7c087b2d4f0dc205735f
F src/mem2.c 6f46eef2c2cce452ae38f5b98c2632712e858bc9
F src/mem2.c 692c5b50141f49c32d85d7c0c39c751f6d520093
F src/mem3.c 67153ec933e08b70714055e872efb58a6b287939
F src/mem5.c 838309b521c96a2a34507f74a5a739d28de4aac6
F src/memjournal.c 17e9281ea5d7981e3e7b0dd3274921ecba4f773c
@ -145,21 +145,21 @@ F src/os_unix.c 4e916cafbf5ec0166213ac62d680ebbe12b8c5a7
F src/os_win.c 45cb430884da7e9360a55a0fcd5c2c44c22dd79d
F src/pager.c d62fd62f7c0ad257019c21158b597fdbb0182529
F src/pager.h 0c9f3520c00d8a3b8e792ca56c9a11b6b02b4b0f
F src/parse.y 4f4d16aee0d11f69fec2adb77dac88878043ed8d
F src/parse.y 5202dc712407fd6723f6639b88b86ddf8b33aef5
F src/pcache.c fcf7738c83c4d3e9d45836b2334c8a368cc41274
F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324
F src/pcache1.c dabb8ab14827e090321f17150ce96fda172974e8
F src/pragma.c 04c13c79fd559d769f5bcb3aa661b32d484b1e7b
F src/prepare.c 9ec504ddd4a8e34e5fb502033312da6a78f5f76a
F src/pragma.c 9ed2acb94efee8059efcc52c2e2140b43170831e
F src/prepare.c d0bbb4b1a8b9c1db6d13788929839bb63764680e
F src/printf.c 9866a9a9c4a90f6d4147407f373df3fd5d5f9b6f
F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
F src/resolve.c 18dc9f0df1d60048e012ce6632251063e0dd356a
F src/resolve.c b3aa625ec135d53a7e80c86c25ad56de46e0b415
F src/rowset.c ba9375f37053d422dd76965a9c370a13b6e1aac4
F src/select.c 164934bd8a9fae29e4d21530688dbac53b420da6
F src/select.c fc21f384db6207a987141859ac770d83c669c933
F src/shell.c f109ebbb50132926ebbc173a6c2d8838d5d78527
F src/sqlite.h.in 14f4d065bafed8500ea558a75a8e2be89c784d61
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h 55cc7e45a7fcc166be62b984168dd69159d877eb
F src/sqliteInt.h 8bd8f5bb583832df68034525c1d763a35cd0365f
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
F src/table.c 332ab0ea691e63862e2a8bdfe2c0617ee61062a3
@ -195,21 +195,21 @@ F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4
F src/test_thread.c adb9175c466e1f487295b5b957603fc0a88ea293
F src/test_wsd.c c297d7d6b8a990239e1bd25935e81d612d8ae31d
F src/tokenize.c 6987fb7f0d6a87ac53499aee568cabb05eb4bea8
F src/trigger.c ca6d78f7c1314053800386ca64361e487774fda3
F src/update.c 8c4925f9ca664effc8a1faaad67449d2074567b1
F src/trigger.c 9957e16e5445478f2cc60e26ac1bc836bb18d21a
F src/update.c 9edb83cc4322fb2dc5b7a0087cdb8fa00391f402
F src/utf.c 1da9c832dba0fa8f865b5b902d93f420a1ee4245
F src/util.c 1363f64351f3b544790f3c523439354c02f8c4e9
F src/vacuum.c 4929a585ef0fb1dfaf46302f8a9c4aa30c2d9cf5
F src/vdbe.c 02e70c48ffd11aa470060fa03a2bfa65d72bc8df
F src/vdbe.h 03516f28bf5aca00a53c4dccd6c313f96adb94f6
F src/vdbeInt.h 13cb4868ea579b5a8f6b6b5098caa99cd5a14078
F src/vdbeapi.c b23c4b1686f150a0ddc36459c8e3876be62638e1
F src/vdbeaux.c 75c3ac2a3c37747ae66ea0935f8f48bb1879234a
F src/vdbe.c d7b996a5b75753ade4471fbe0452a684dc047d72
F src/vdbe.h d70a68bee196ab228914a3902c79dbd24342a0f2
F src/vdbeInt.h 9dd984cf80ef4f2970266b05f1dbb5622ac3817b
F src/vdbeapi.c f94fe2eb6f48687e918f0df7eed1409cff9dcf58
F src/vdbeaux.c f636fd01adbab85675167a25cf194eddd58b13dd
F src/vdbeblob.c b0dcebfafedcf9c0addc7901ad98f6f986c08935
F src/vdbemem.c 543a79d722734d2f8b7ad70f08218c30bcc5bbf5
F src/vtab.c e39e011d7443a8d574b1b9cde207a35522e6df43
F src/walker.c 488c2660e13224ff70c0c82761118efb547f8f0d
F src/where.c 63bb752784b352d8e226dc6b1ec02f0d19fed916
F src/walker.c 42bd3f00ca2ef5ae842304ec0d59903ef051412d
F src/where.c 2284de47b03e285a142926bc8a8022983c455a76
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 597662c5d777a122f9a3df0047ea5c5bd383a911
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
@ -299,7 +299,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test 199cf68f44e5d9e87a0b8afc7130fdeb4def3272
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/date.test bb2cc648333c04d09e8e23cfc0cddc398c334a92
F test/default.test 252298e42a680146b1dd64f563b95bdf088d94fb
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/delete.test f171c1011395a8dd63169438fe1d8cc625eb7442
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
@ -552,7 +552,7 @@ F test/tableapi.test 505031f15b18a750184d967d2c896cf88fcc969c
F test/tclsqlite.test 413a8a887d89ea8fa7055e8d118ffb03b0a4c91a
F test/tempdb.test b88ac8a19823cf771d742bf61eef93ef337c06b1
F test/temptable.test 5d8ca46be28cc06c887c5a77df650843b7edbae1
F test/tester.tcl b28d5eb97e95b19eacdb5afb38db2c8558f398b0
F test/tester.tcl 66546f6766029384360b24cacb3896376c5f5f69
F test/thread001.test 06c45ed9597d478e7bbdc2a8937e1ebea2a20a32
F test/thread002.test 3c03900f03fd2fe8e2fbb1bbdef7fa8206fdb7ad
F test/thread003.test 6d360c15afe7f6ef6186801d2cb8407bccbe3aa3
@ -701,7 +701,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P 419eb48b6b4238526850091eef28af503b6c4579
R 379eb6edfb0135905a7c816f1113ae71
U drh
Z bfca2c680cc89c0b0c6a5ad192f03b32
P ded04f12f41504e4a3ecd5164f0d4cbbde5e16f7
R beea4442dc6507223c6db2a960f9f40a
U danielk1977
Z 5a9e5027f061557095d1ee54ae664ed7

View File

@ -1 +1 @@
ded04f12f41504e4a3ecd5164f0d4cbbde5e16f7
d9f6ffbc5ea090ba0daac571fc9a6c68b9c864e4

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
** @(#) $Id: analyze.c,v 1.48 2009/02/13 16:59:53 drh Exp $
** @(#) $Id: analyze.c,v 1.49 2009/02/19 14:39:25 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"
@ -117,7 +117,7 @@ static void analyzeOneTable(
/* Establish a read-lock on the table at the shared-cache level. */
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
iIdxCur = pParse->nTab;
iIdxCur = pParse->nTab++;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
int regFields; /* Register block for building records */

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.82 2009/02/03 16:51:25 danielk1977 Exp $
** $Id: attach.c,v 1.83 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -488,11 +488,11 @@ int sqlite3FixExpr(
Expr *pExpr /* The expression to be fixed to one database */
){
while( pExpr ){
if( sqlite3FixSelect(pFix, pExpr->pSelect) ){
return 1;
}
if( sqlite3FixExprList(pFix, pExpr->pList) ){
return 1;
if( ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanOnly) ) break;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
}else{
if( sqlite3FixExprList(pFix, pExpr->x.pList) ) return 1;
}
if( sqlite3FixExpr(pFix, pExpr->pRight) ){
return 1;

View File

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.518 2009/02/13 03:43:32 drh Exp $
** $Id: build.c,v 1.519 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -178,19 +178,6 @@ void sqlite3FinishCoding(Parse *pParse){
codeTableLocks(pParse);
sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto);
}
#ifndef SQLITE_OMIT_TRACE
if( !db->init.busy ){
/* Change the P4 argument of the first opcode (which will always be
** an OP_Trace) to be the complete text of the current SQL statement.
*/
VdbeOp *pOp = sqlite3VdbeGetOp(v, 0);
if( pOp && pOp->opcode==OP_Trace ){
sqlite3VdbeChangeP4(v, 0, pParse->zSql,
(int)(pParse->zTail - pParse->zSql));
}
}
#endif /* SQLITE_OMIT_TRACE */
}
@ -202,8 +189,8 @@ void sqlite3FinishCoding(Parse *pParse){
sqlite3VdbeTrace(v, trace);
#endif
assert( pParse->disableColCache==0 ); /* Disables and re-enables match */
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
pParse->nTab+3, pParse->explain);
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem,
pParse->nTab, pParse->explain);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
}else if( pParse->rc==SQLITE_OK ){
@ -618,6 +605,9 @@ void sqlite3OpenMasterTable(Parse *p, int iDb){
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb));
sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5);/* sqlite_master has 5 columns */
sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb);
if( p->nTab==0 ){
p->nTab = 1;
}
}
/*
@ -1116,12 +1106,12 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
}else{
Expr *pCopy;
/* A copy of pExpr is used instead of the original, as pExpr contains
** tokens that point to volatile memory. The 'span' of the expression
** is required by pragma table_info.
*/
sqlite3ExprDelete(db, pCol->pDflt);
pCol->pDflt = pCopy = sqlite3ExprDup(db, pExpr);
if( pCopy ){
sqlite3TokenCopy(db, &pCopy->span, &pExpr->span);
}
pCol->pDflt = sqlite3ExprDup(db, pExpr, EXPRDUP_REDUCE|EXPRDUP_SPAN);
}
}
sqlite3ExprDelete(db, pExpr);
@ -1217,7 +1207,7 @@ void sqlite3AddCheckConstraint(
** to malloced space and not the (ephemeral) text of the CREATE TABLE
** statement */
pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck,
sqlite3ExprDup(db, pCheckExpr));
sqlite3ExprDup(db, pCheckExpr, 0));
}
#endif
sqlite3ExprDelete(db, pCheckExpr);
@ -1540,7 +1530,7 @@ void sqlite3EndTable(
SelectDest dest;
Table *pSelTab;
assert(pParse->nTab==0);
assert(pParse->nTab==1);
sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
sqlite3VdbeChangeP5(v, 1);
pParse->nTab = 2;
@ -1701,7 +1691,7 @@ void sqlite3CreateView(
** allocated rather than point to the input string - which means that
** they will persist after the current sqlite3_exec() call returns.
*/
p->pSelect = sqlite3SelectDup(db, pSelect);
p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
sqlite3SelectDelete(db, pSelect);
if( db->mallocFailed ){
return;
@ -1783,7 +1773,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
** statement that defines the view.
*/
assert( pTable->pSelect );
pSel = sqlite3SelectDup(db, pTable->pSelect);
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if( pSel ){
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
@ -2277,8 +2267,8 @@ void sqlite3DeferForeignKey(Parse *pParse, int isDeferred){
*/
static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
Table *pTab = pIndex->pTable; /* The table that is indexed */
int iTab = pParse->nTab; /* Btree cursor used for pTab */
int iIdx = pParse->nTab+1; /* Btree cursor used for pIndex */
int iTab = pParse->nTab++; /* Btree cursor used for pTab */
int iIdx = pParse->nTab++; /* Btree cursor used for pIndex */
int addr1; /* Address of top of loop */
int tnum; /* Root page of index */
Vdbe *v; /* Generate code into this virtual machine */

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.191 2008/12/23 23:56:22 drh Exp $
** $Id: delete.c,v 1.192 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -99,12 +99,12 @@ void sqlite3MaterializeView(
Select *pDup;
sqlite3 *db = pParse->db;
pDup = sqlite3SelectDup(db, pView->pSelect);
pDup = sqlite3SelectDup(db, pView->pSelect, 0);
if( pWhere ){
SrcList *pFrom;
Token viewName;
pWhere = sqlite3ExprDup(db, pWhere);
pWhere = sqlite3ExprDup(db, pWhere, 0);
viewName.z = (u8*)pView->zName;
viewName.n = (unsigned int)sqlite3Strlen30((const char*)viewName.z);
pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
@ -174,7 +174,7 @@ Expr *sqlite3LimitWhere(
/* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
** and the SELECT subtree. */
pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc);
pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
if( pSelectSrc == 0 ) {
sqlite3ExprListDelete(pParse->db, pEList);
goto limit_where_cleanup_2;

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.411 2009/02/04 03:59:25 shane Exp $
** $Id: expr.c,v 1.412 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -35,7 +35,8 @@
char sqlite3ExprAffinity(Expr *pExpr){
int op = pExpr->op;
if( op==TK_SELECT ){
return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr);
assert( pExpr->flags&EP_xIsSelect );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
@ -155,11 +156,9 @@ static char comparisonAffinity(Expr *pExpr){
aff = sqlite3ExprAffinity(pExpr->pLeft);
if( pExpr->pRight ){
aff = sqlite3CompareAffinity(pExpr->pRight, aff);
}
else if( pExpr->pSelect ){
aff = sqlite3CompareAffinity(pExpr->pSelect->pEList->a[0].pExpr, aff);
}
else if( !aff ){
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
aff = sqlite3CompareAffinity(pExpr->x.pSelect->pEList->a[0].pExpr, aff);
}else if( !aff ){
aff = SQLITE_AFF_NONE;
}
return aff;
@ -345,8 +344,11 @@ static void exprSetHeight(Expr *p){
int nHeight = 0;
heightOfExpr(p->pLeft, &nHeight);
heightOfExpr(p->pRight, &nHeight);
heightOfExprList(p->pList, &nHeight);
heightOfSelect(p->pSelect, &nHeight);
if( ExprHasProperty(p, EP_xIsSelect) ){
heightOfSelect(p->x.pSelect, &nHeight);
}else{
heightOfExprList(p->x.pList, &nHeight);
}
p->nHeight = nHeight + 1;
}
@ -510,7 +512,8 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
return 0;
}
pNew->op = TK_FUNCTION;
pNew->pList = pList;
pNew->x.pList = pList;
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
assert( pToken->dyn==0 );
pNew->token = *pToken;
pNew->span = pNew->token;
@ -607,12 +610,22 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
** Substructure is deleted.
*/
void sqlite3ExprClear(sqlite3 *db, Expr *p){
if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z);
if( p->token.dyn ) sqlite3DbFree(db, (char*)p->token.z);
if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanOnly) ){
if( p->span.dyn ) sqlite3DbFree(db, (char*)p->span.z);
if( ExprHasProperty(p, EP_Reduced) ){
if( p->pLeft ) sqlite3ExprClear(db, p->pLeft);
if( p->pRight ) sqlite3ExprClear(db, p->pRight);
}else{
sqlite3ExprDelete(db, p->pLeft);
sqlite3ExprDelete(db, p->pRight);
sqlite3ExprListDelete(db, p->pList);
sqlite3SelectDelete(db, p->pSelect);
}
if( ExprHasProperty(p, EP_xIsSelect) ){
sqlite3SelectDelete(db, p->x.pSelect);
}else{
sqlite3ExprListDelete(db, p->x.pList);
}
}
}
/*
@ -633,12 +646,190 @@ void sqlite3DequoteExpr(sqlite3 *db, Expr *p){
return;
}
ExprSetProperty(p, EP_Dequoted);
if( p->token.dyn==0 ){
if( p->token.dyn==0 && !ExprHasProperty(p, EP_Reduced) ){
sqlite3TokenCopy(db, &p->token, &p->token);
}
sqlite3Dequote((char*)p->token.z);
}
/*
** Return the number of bytes allocated for the expression structure
** passed as the first argument. This is always one of EXPR_FULLSIZE,
** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
*/
static int exprStructSize(Expr *p){
if( ExprHasProperty(p, EP_TokenOnly) ) return EXPR_TOKENONLYSIZE;
if( ExprHasProperty(p, EP_SpanOnly) ) return EXPR_SPANONLYSIZE;
if( ExprHasProperty(p, EP_Reduced) ) return EXPR_REDUCEDSIZE;
return EXPR_FULLSIZE;
}
/*
** sqlite3ExprDup() has been called to create a copy of expression p with
** the EXPRDUP_XXX flags passed as the second argument. This function
** returns the space required for the copy of the Expr structure only.
** This is always one of EXPR_FULLSIZE, EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
*/
static int dupedExprStructSize(Expr *p, int flags){
int nSize;
if( 0==(flags&EXPRDUP_REDUCE) ){
nSize = EXPR_FULLSIZE;
}else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
nSize = EXPR_REDUCEDSIZE;
}else if( flags&EXPRDUP_SPAN ){
nSize = EXPR_SPANONLYSIZE;
}else{
nSize = EXPR_TOKENONLYSIZE;
}
return nSize;
}
/*
** sqlite3ExprDup() has been called to create a copy of expression p with
** the EXPRDUP_XXX passed as the second argument. This function returns
** the space in bytes required to store the copy of the Expr structure
** and the copies of the Expr.token.z and Expr.span.z (if applicable)
** string buffers.
*/
static int dupedExprNodeSize(Expr *p, int flags){
int nByte = dupedExprStructSize(p, flags) + (p->token.z ? p->token.n + 1 : 0);
if( flags&EXPRDUP_SPAN && (p->token.z!=p->span.z || p->token.n!=p->span.n) ){
nByte += p->span.n;
}
return (nByte+7)&~7;
}
/*
** Return the number of bytes required to create a duplicate of the
** expression passed as the first argument. The second argument is a
** mask containing EXPRDUP_XXX flags.
**
** The value returned includes space to create a copy of the Expr struct
** itself and the buffer referred to by Expr.token, if any. If the
** EXPRDUP_SPAN flag is set, then space to create a copy of the buffer
** refered to by Expr.span is also included.
**
** If the EXPRDUP_REDUCE flag is set, then the return value includes
** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
** and Expr.pRight variables (but not for any structures pointed to or
** descended from the Expr.x.pList or Expr.x.pSelect variables).
*/
static int dupedExprSize(Expr *p, int flags){
int nByte = 0;
if( p ){
nByte = dupedExprNodeSize(p, flags);
if( flags&EXPRDUP_REDUCE ){
int f = flags&(~EXPRDUP_SPAN);
nByte += dupedExprSize(p->pLeft, f) + dupedExprSize(p->pRight, f);
}
}
return nByte;
}
/*
** This function is similar to sqlite3ExprDup(), except that if pzBuffer
** is not NULL then *pzBuffer is assumed to point to a buffer large enough
** to store the copy of expression p, the copies of p->token and p->span
** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
** if any. Before returning, *pzBuffer is set to the first byte passed the
** portion of the buffer copied into by this function.
*/
static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
Expr *pNew = 0; /* Value to return */
if( p ){
const int isRequireSpan = (flags&EXPRDUP_SPAN);
const int isReduced = (flags&EXPRDUP_REDUCE);
u8 *zAlloc;
assert( pzBuffer==0 || isReduced );
/* Figure out where to write the new Expr structure. */
if( pzBuffer ){
zAlloc = *pzBuffer;
}else{
zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags));
}
pNew = (Expr *)zAlloc;
if( pNew ){
/* Set nNewSize to the size allocated for the structure pointed to
** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
** by the copy of the p->token.z string (if any).
*/
const int nNewSize = dupedExprStructSize(p, flags);
const int nToken = (p->token.z ? p->token.n + 1 : 0);
if( isReduced ){
assert( ExprHasProperty(p, EP_Reduced)==0 );
memcpy(zAlloc, p, nNewSize);
}else{
int nSize = exprStructSize(p);
memcpy(zAlloc, p, nSize);
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
}
/* Set the EP_Reduced and EP_TokenOnly flags appropriately. */
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_SpanOnly);
switch( nNewSize ){
case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break;
case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break;
case EXPR_SPANONLYSIZE: pNew->flags |= EP_SpanOnly; break;
}
/* Copy the p->token string, if any. */
if( nToken ){
unsigned char *zToken = &zAlloc[nNewSize];
memcpy(zToken, p->token.z, nToken-1);
zToken[nToken-1] = '\0';
pNew->token.dyn = 0;
pNew->token.z = zToken;
}
if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
/* Fill in the pNew->span token, if required. */
if( isRequireSpan ){
if( p->token.z!=p->span.z || p->token.n!=p->span.n ){
pNew->span.z = &zAlloc[nNewSize+nToken];
memcpy((char *)pNew->span.z, p->span.z, p->span.n);
pNew->span.dyn = 0;
}else{
pNew->span.z = pNew->token.z;
pNew->span.n = pNew->token.n;
}
}else{
pNew->span.z = 0;
pNew->span.n = 0;
}
}
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_SpanOnly)) ){
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
if( ExprHasProperty(p, EP_xIsSelect) ){
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, isReduced);
}else{
pNew->x.pList = sqlite3ExprListDup(db, p->x.pList, isReduced);
}
}
/* Fill in pNew->pLeft and pNew->pRight. */
if( ExprHasAnyProperty(pNew, EP_Reduced|EP_TokenOnly|EP_SpanOnly) ){
zAlloc += dupedExprNodeSize(p, flags);
if( ExprHasProperty(pNew, EP_Reduced) ){
pNew->pLeft = exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc);
pNew->pRight = exprDup(db, p->pRight, EXPRDUP_REDUCE, &zAlloc);
}
if( pzBuffer ){
*pzBuffer = zAlloc;
}
}else if( !ExprHasAnyProperty(p, EP_TokenOnly|EP_SpanOnly) ){
pNew->pLeft = sqlite3ExprDup(db, p->pLeft, 0);
pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
}
}
}
return pNew;
}
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
@ -650,25 +841,19 @@ void sqlite3DequoteExpr(sqlite3 *db, Expr *p){
** by subsequent calls to sqlite*ListAppend() routines.
**
** Any tables that the SrcList might point to are not duplicated.
**
** The flags parameter contains a combination of the EXPRDUP_XXX flags. If
** the EXPRDUP_SPAN flag is set in the argument parameter, then the
** Expr.span field of the input expression is copied. If EXPRDUP_SPAN is
** clear, then the Expr.span field of the returned expression structure
** is zeroed.
**
** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
** truncated version of the usual Expr structure that will be stored as
** part of the in-memory representation of the database schema.
*/
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p){
Expr *pNew;
if( p==0 ) return 0;
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
if( pNew==0 ) return 0;
memcpy(pNew, p, sizeof(*pNew));
if( p->token.z!=0 ){
pNew->token.z = (u8*)sqlite3DbStrNDup(db, (char*)p->token.z, p->token.n);
pNew->token.dyn = 1;
}else{
assert( pNew->token.z==0 );
}
pNew->span.z = 0;
pNew->pLeft = sqlite3ExprDup(db, p->pLeft);
pNew->pRight = sqlite3ExprDup(db, p->pRight);
pNew->pList = sqlite3ExprListDup(db, p->pList);
pNew->pSelect = sqlite3SelectDup(db, p->pSelect);
return pNew;
Expr *sqlite3ExprDup(sqlite3 *db, Expr *p, int flags){
return exprDup(db, p, flags, 0);
}
void sqlite3TokenCopy(sqlite3 *db, Token *pTo, Token *pFrom){
if( pTo->dyn ) sqlite3DbFree(db, (char*)pTo->z);
@ -680,7 +865,7 @@ void sqlite3TokenCopy(sqlite3 *db, Token *pTo, Token *pFrom){
pTo->z = 0;
}
}
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){
ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
ExprList *pNew;
struct ExprList_item *pItem, *pOldItem;
int i;
@ -696,17 +881,9 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){
}
pOldItem = p->a;
for(i=0; i<p->nExpr; i++, pItem++, pOldItem++){
Expr *pNewExpr, *pOldExpr;
pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr = pOldItem->pExpr);
if( pOldExpr->span.z!=0 && pNewExpr ){
/* Always make a copy of the span for top-level expressions in the
** expression list. The logic in SELECT processing that determines
** the names of columns in the result set needs this information */
sqlite3TokenCopy(db, &pNewExpr->span, &pOldExpr->span);
}
assert( pNewExpr==0 || pNewExpr->span.z!=0
|| pOldExpr->span.z==0
|| db->mallocFailed );
Expr *pNewExpr;
Expr *pOldExpr = pOldItem->pExpr;
pItem->pExpr = pNewExpr = sqlite3ExprDup(db, pOldExpr, flags);
pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
pItem->sortOrder = pOldItem->sortOrder;
pItem->done = 0;
@ -724,7 +901,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p){
*/
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
|| !defined(SQLITE_OMIT_SUBQUERY)
SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p){
SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p, int flags){
SrcList *pNew;
int i;
int nByte;
@ -750,8 +927,8 @@ SrcList *sqlite3SrcListDup(sqlite3 *db, SrcList *p){
if( pTab ){
pTab->nRef++;
}
pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect);
pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn);
pNewItem->pSelect = sqlite3SelectDup(db, pOldItem->pSelect, flags);
pNewItem->pOn = sqlite3ExprDup(db, pOldItem->pOn, flags);
pNewItem->pUsing = sqlite3IdListDup(db, pOldItem->pUsing);
pNewItem->colUsed = pOldItem->colUsed;
}
@ -777,21 +954,24 @@ IdList *sqlite3IdListDup(sqlite3 *db, IdList *p){
}
return pNew;
}
Select *sqlite3SelectDup(sqlite3 *db, Select *p){
Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
Select *pNew;
if( p==0 ) return 0;
pNew = sqlite3DbMallocRaw(db, sizeof(*p) );
if( pNew==0 ) return 0;
pNew->pEList = sqlite3ExprListDup(db, p->pEList);
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc);
pNew->pWhere = sqlite3ExprDup(db, p->pWhere);
pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy);
pNew->pHaving = sqlite3ExprDup(db, p->pHaving);
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy);
/* Always make a copy of the span for top-level expressions in the
** expression list. The logic in SELECT processing that determines
** the names of columns in the result set needs this information */
pNew->pEList = sqlite3ExprListDup(db, p->pEList, flags|EXPRDUP_SPAN);
pNew->pSrc = sqlite3SrcListDup(db, p->pSrc, flags);
pNew->pWhere = sqlite3ExprDup(db, p->pWhere, flags);
pNew->pGroupBy = sqlite3ExprListDup(db, p->pGroupBy, flags);
pNew->pHaving = sqlite3ExprDup(db, p->pHaving, flags);
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, flags);
pNew->op = p->op;
pNew->pPrior = sqlite3SelectDup(db, p->pPrior);
pNew->pLimit = sqlite3ExprDup(db, p->pLimit);
pNew->pOffset = sqlite3ExprDup(db, p->pOffset);
pNew->pPrior = sqlite3SelectDup(db, p->pPrior, flags);
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
pNew->pOffset = sqlite3ExprDup(db, p->pOffset, flags);
pNew->iLimit = 0;
pNew->iOffset = 0;
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
@ -802,7 +982,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *p){
return pNew;
}
#else
Select *sqlite3SelectDup(sqlite3 *db, Select *p){
Select *sqlite3SelectDup(sqlite3 *db, Select *p, int flags){
assert( p==0 );
return 0;
}
@ -1143,7 +1323,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
** If this is the case, it may be possible to use an existing table
** or index instead of generating an epheremal table.
*/
p = pX->pSelect;
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
if( isCandidateForInOpt(p) ){
sqlite3 *db = pParse->db;
Index *pIdx;
@ -1222,7 +1402,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
eType = IN_INDEX_EPH;
if( prNotFound ){
*prNotFound = rMayHaveNull = ++pParse->nMem;
}else if( pX->pLeft->iColumn<0 && pX->pSelect==0 ){
}else if( pX->pLeft->iColumn<0 && !ExprHasAnyProperty(pX, EP_xIsSelect) ){
eType = IN_INDEX_ROWID;
}
sqlite3CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID);
@ -1311,7 +1491,7 @@ void sqlite3CodeSubselect(
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
if( pExpr->pSelect ){
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
/* Case 1: expr IN (SELECT ...)
**
** Generate code to write the results of the select into the temporary
@ -1324,15 +1504,15 @@ void sqlite3CodeSubselect(
sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
dest.affinity = (u8)affinity;
assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
if( sqlite3Select(pParse, pExpr->pSelect, &dest) ){
if( sqlite3Select(pParse, pExpr->x.pSelect, &dest) ){
return;
}
pEList = pExpr->pSelect->pEList;
pEList = pExpr->x.pSelect->pEList;
if( pEList && pEList->nExpr>0 ){
keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
pEList->a[0].pExpr);
}
}else if( pExpr->pList ){
}else if( pExpr->x.pList ){
/* Case 2: expr IN (exprlist)
**
** For each expression, build an index key from the evaluation and
@ -1341,7 +1521,7 @@ void sqlite3CodeSubselect(
** a column, use numeric affinity.
*/
int i;
ExprList *pList = pExpr->pList;
ExprList *pList = pExpr->x.pList;
struct ExprList_item *pItem;
int r1, r2, r3;
@ -1401,7 +1581,8 @@ void sqlite3CodeSubselect(
Select *pSel;
SelectDest dest;
pSel = pExpr->pSelect;
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
pSel = pExpr->x.pSelect;
sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
if( pExpr->op==TK_SELECT ){
dest.eDest = SRT_Mem;
@ -1985,7 +2166,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pList = pExpr->pList;
ExprList *pList = (
ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_SpanOnly) ? 0 : pExpr->x.pList
);
int nExpr = pList ? pList->nExpr : 0;
FuncDef *pDef;
int nId;
@ -1995,6 +2178,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
u8 enc = ENC(db);
CollSeq *pColl = 0;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
testcase( op==TK_CONST_FUNC );
testcase( op==TK_FUNCTION );
zId = (char*)pExpr->token.z;
@ -2162,7 +2346,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
*/
case TK_BETWEEN: {
Expr *pLeft = pExpr->pLeft;
struct ExprList_item *pLItem = pExpr->pList->a;
struct ExprList_item *pLItem = pExpr->x.pList->a;
Expr *pRight = pLItem->pExpr;
codeCompareOperands(pParse, pLeft, &r1, &regFree1,
@ -2222,10 +2406,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
assert(pExpr->pList);
assert((pExpr->pList->nExpr % 2) == 0);
assert(pExpr->pList->nExpr > 0);
pEList = pExpr->pList;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
assert((pExpr->x.pList->nExpr % 2) == 0);
assert(pExpr->x.pList->nExpr > 0);
pEList = pExpr->x.pList;
aListelem = pEList->a;
nExpr = pEList->nExpr;
endLabel = sqlite3VdbeMakeLabel(v);
@ -2273,15 +2457,15 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
"RAISE() may only be used within a trigger-program");
return 0;
}
if( pExpr->iColumn!=OE_Ignore ){
assert( pExpr->iColumn==OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail );
if( pExpr->affinity!=OE_Ignore ){
assert( pExpr->affinity==OE_Rollback ||
pExpr->affinity == OE_Abort ||
pExpr->affinity == OE_Fail );
sqlite3DequoteExpr(db, pExpr);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, 0,
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0,
(char*)pExpr->token.z, pExpr->token.n);
} else {
assert( pExpr->iColumn == OE_Ignore );
assert( pExpr->affinity == OE_Ignore );
sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0);
sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
VdbeComment((v, "raise(IGNORE)"));
@ -2438,7 +2622,8 @@ static int evalConstExpr(Walker *pWalker, Expr *pExpr){
** Mark them this way to avoid generated unneeded OP_SCopy
** instructions.
*/
ExprList *pList = pExpr->pList;
ExprList *pList = pExpr->x.pList;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( pList ){
int i = pList->nExpr;
struct ExprList_item *pItem = pList->a;
@ -2614,16 +2799,17 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Expr compRight;
Expr exprX;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
exprX = *pExpr->pLeft;
exprAnd.op = TK_AND;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
compLeft.op = TK_GE;
compLeft.pLeft = &exprX;
compLeft.pRight = pExpr->pList->a[0].pExpr;
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
compRight.op = TK_LE;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->pList->a[1].pExpr;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
testcase( regFree1==0 );
exprX.op = TK_REGISTER;
@ -2765,16 +2951,17 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Expr compRight;
Expr exprX;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
exprX = *pExpr->pLeft;
exprAnd.op = TK_AND;
exprAnd.pLeft = &compLeft;
exprAnd.pRight = &compRight;
compLeft.op = TK_GE;
compLeft.pLeft = &exprX;
compLeft.pRight = pExpr->pList->a[0].pExpr;
compLeft.pRight = pExpr->x.pList->a[0].pExpr;
compRight.op = TK_LE;
compRight.pLeft = &exprX;
compRight.pRight = pExpr->pList->a[1].pExpr;
compRight.pRight = pExpr->x.pList->a[1].pExpr;
exprX.iTable = sqlite3ExprCodeTemp(pParse, &exprX, &regFree1);
testcase( regFree1==0 );
exprX.op = TK_REGISTER;
@ -2813,22 +3000,25 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
if( pA==0||pB==0 ){
return pB==pA;
}
if( pA->op!=pB->op ) return 0;
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
return 0;
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0;
if( pA->op!=pB->op ) return 0;
if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0;
if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0;
if( pA->pList ){
if( pB->pList==0 ) return 0;
if( pA->pList->nExpr!=pB->pList->nExpr ) return 0;
for(i=0; i<pA->pList->nExpr; i++){
if( !sqlite3ExprCompare(pA->pList->a[i].pExpr, pB->pList->a[i].pExpr) ){
if( pA->x.pList && pB->x.pList ){
if( pA->x.pList->nExpr!=pB->x.pList->nExpr ) return 0;
for(i=0; i<pA->x.pList->nExpr; i++){
Expr *pExprA = pA->x.pList->a[i].pExpr;
Expr *pExprB = pB->x.pList->a[i].pExpr;
if( !sqlite3ExprCompare(pExprA, pExprB) ) return 0;
}
}else if( pA->x.pList || pB->x.pList ){
return 0;
}
}
}else if( pB->pList ){
return 0;
}
if( pA->pSelect || pB->pSelect ) return 0;
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
if( pA->op!=TK_COLUMN && pA->token.z ){
if( pB->token.z==0 ) return 0;
@ -2976,12 +3166,13 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
u8 enc = ENC(pParse->db);
i = addAggInfoFunc(pParse->db, pAggInfo);
if( i>=0 ){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pItem = &pAggInfo->aFunc[i];
pItem->pExpr = pExpr;
pItem->iMem = ++pParse->nMem;
pItem->pFunc = sqlite3FindFunction(pParse->db,
(char*)pExpr->token.z, pExpr->token.n,
pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0);
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
if( pExpr->flags & EP_Distinct ){
pItem->iDistinct = pParse->nTab++;
}else{

View File

@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.222 2009/02/04 03:59:25 shane Exp $
** $Id: func.c,v 1.223 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
@ -1323,12 +1323,13 @@ void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive){
*/
int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
if( pExpr->op!=TK_FUNCTION || !pExpr->pList ){
return 0;
}
if( pExpr->pList->nExpr!=2 ){
if( pExpr->op!=TK_FUNCTION
|| !pExpr->x.pList
|| pExpr->x.pList->nExpr!=2
){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pDef = sqlite3FindFunction(db, (char*)pExpr->token.z, pExpr->token.n, 2,
SQLITE_UTF8, 0);
if( pDef==0 || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){

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.256 2008/12/10 21:19:57 drh Exp $
** $Id: insert.c,v 1.257 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -168,7 +168,7 @@ static int autoIncBegin(
if( pTab->tabFlags & TF_Autoincrement ){
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int iCur = pParse->nTab;
int iCur = pParse->nTab++;
int addr; /* Address of the top of the loop */
assert( v );
pParse->nMem++; /* Holds name of table */
@ -217,7 +217,7 @@ static void autoIncEnd(
int memId /* Memory cell holding the maximum rowid */
){
if( pTab->tabFlags & TF_Autoincrement ){
int iCur = pParse->nTab;
int iCur = pParse->nTab++;
Vdbe *v = pParse->pVdbe;
Db *pDb = &pParse->db->aDb[iDb];
int j1;

View File

@ -19,7 +19,7 @@
** This file contains implementations of the low-level memory allocation
** routines specified in the sqlite3_mem_methods object.
**
** $Id: mem2.c,v 1.43 2009/02/05 03:00:06 shane Exp $
** $Id: mem2.c,v 1.44 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -248,6 +248,7 @@ static void *sqlite3MemMalloc(int nByte){
void *aAddr[40];
pHdr->nBacktrace = backtrace(aAddr, mem.nBacktrace+1)-1;
memcpy(pBt, &aAddr[1], pHdr->nBacktrace*sizeof(void*));
assert(pBt[0]);
if( mem.xBacktrace ){
mem.xBacktrace(nByte, pHdr->nBacktrace-1, &aAddr[1]);
}

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.268 2009/01/29 19:27:47 drh Exp $
** @(#) $Id: parse.y,v 1.269 2009/02/19 14:39:25 danielk1977 Exp $
*/
// All token codes are small integers with #defines that begin with "TK_"
@ -824,7 +824,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
pList = sqlite3ExprListAppend(pParse,pList, Y, 0);
A = sqlite3PExpr(pParse, TK_BETWEEN, W, 0, 0);
if( A ){
A->pList = pList;
A->x.pList = pList;
}else{
sqlite3ExprListDelete(pParse->db, pList);
}
@ -838,7 +838,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
expr(A) ::= expr(X) in_op(N) LP exprlist(Y) RP(E). [IN] {
A = sqlite3PExpr(pParse, TK_IN, X, 0, 0);
if( A ){
A->pList = Y;
A->x.pList = Y;
sqlite3ExprSetHeight(pParse, A);
}else{
sqlite3ExprListDelete(pParse->db, Y);
@ -849,7 +849,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
expr(A) ::= LP(B) select(X) RP(E). {
A = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
if( A ){
A->pSelect = X;
A->x.pSelect = X;
ExprSetProperty(A, EP_xIsSelect);
sqlite3ExprSetHeight(pParse, A);
}else{
sqlite3SelectDelete(pParse->db, X);
@ -859,7 +860,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
expr(A) ::= expr(X) in_op(N) LP select(Y) RP(E). [IN] {
A = sqlite3PExpr(pParse, TK_IN, X, 0, 0);
if( A ){
A->pSelect = Y;
A->x.pSelect = Y;
ExprSetProperty(A, EP_xIsSelect);
sqlite3ExprSetHeight(pParse, A);
}else{
sqlite3SelectDelete(pParse->db, Y);
@ -871,7 +873,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
A = sqlite3PExpr(pParse, TK_IN, X, 0, 0);
if( A ){
A->pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
A->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
ExprSetProperty(A, EP_xIsSelect);
sqlite3ExprSetHeight(pParse, A);
}else{
sqlite3SrcListDelete(pParse->db, pSrc);
@ -882,7 +885,8 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
Expr *p = A = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
if( p ){
p->pSelect = Y;
p->x.pSelect = Y;
ExprSetProperty(A, EP_xIsSelect);
sqlite3ExprSpan(p,&B,&E);
sqlite3ExprSetHeight(pParse, A);
}else{
@ -895,7 +899,7 @@ expr(A) ::= expr(W) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
A = sqlite3PExpr(pParse, TK_CASE, X, Z, 0);
if( A ){
A->pList = Y;
A->x.pList = Y;
sqlite3ExprSetHeight(pParse, A);
}else{
sqlite3ExprListDelete(pParse->db, Y);
@ -1100,14 +1104,14 @@ trigger_cmd(A) ::= select(X). {A = sqlite3TriggerSelectStep(pParse->db, X); }
expr(A) ::= RAISE(X) LP IGNORE RP(Y). {
A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, 0);
if( A ){
A->iColumn = OE_Ignore;
A->affinity = OE_Ignore;
sqlite3ExprSpan(A, &X, &Y);
}
}
expr(A) ::= RAISE(X) LP raisetype(T) COMMA nm(Z) RP(Y). {
A = sqlite3PExpr(pParse, TK_RAISE, 0, 0, &Z);
if( A ) {
A->iColumn = T;
A->affinity = T;
sqlite3ExprSpan(A, &X, &Y);
}
}

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.202 2009/01/20 16:53:41 danielk1977 Exp $
** $Id: pragma.c,v 1.203 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -831,7 +831,6 @@ void sqlite3Pragma(
sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "pk", SQLITE_STATIC);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
const Token *pDflt;
if( IsHiddenColumn(pCol) ){
nHidden++;
continue;
@ -842,9 +841,9 @@ void sqlite3Pragma(
pCol->zType ? pCol->zType : "", 0);
sqlite3VdbeAddOp2(v, OP_Integer, (pCol->notNull ? 1 : 0), 4);
if( pCol->pDflt ){
pDflt = &pCol->pDflt->span;
assert( pDflt->z );
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)pDflt->z, pDflt->n);
const Token *p = &pCol->pDflt->span;
assert( p->z );
sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, (char*)p->z, p->n);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, 5);
}

View File

@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.105 2009/01/20 16:53:41 danielk1977 Exp $
** $Id: prepare.c,v 1.106 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -621,8 +621,10 @@ static int sqlite3Prepare(
rc = SQLITE_MISUSE;
}
if( saveSqlFlag ){
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail - zSql));
assert( db->init.busy==0 || saveSqlFlag==0 );
if( db->init.busy==0 ){
Vdbe *pVdbe = sParse.pVdbe;
sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag);
}
if( rc!=SQLITE_OK || db->mallocFailed ){
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);

View File

@ -14,7 +14,7 @@
** resolve all identifiers by associating them with a particular
** table and column.
**
** $Id: resolve.c,v 1.15 2008/12/10 19:26:24 drh Exp $
** $Id: resolve.c,v 1.16 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
@ -63,7 +63,7 @@ static void resolveAlias(
assert( pOrig!=0 );
assert( pOrig->flags & EP_Resolved );
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig);
pDup = sqlite3ExprDup(db, pOrig, 0);
if( pDup==0 ) return;
if( pDup->op!=TK_COLUMN && zType[0]!='G' ){
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
@ -282,8 +282,8 @@ static int lookupName(
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
Expr *pOrig;
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
assert( pExpr->pList==0 );
assert( pExpr->pSelect==0 );
assert( pExpr->x.pList==0 );
assert( pExpr->x.pSelect==0 );
pOrig = pEList->a[j].pExpr;
if( !pNC->allowAgg && ExprHasProperty(pOrig, EP_Agg) ){
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
@ -474,7 +474,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
*/
case TK_CONST_FUNC:
case TK_FUNCTION: {
ExprList *pList = pExpr->pList; /* The argument list */
ExprList *pList = pExpr->x.pList; /* The argument list */
int n = pList ? pList->nExpr : 0; /* Number of arguments */
int no_such_func = 0; /* True if no such function exists */
int wrong_num_args = 0; /* True if wrong number of arguments */
@ -485,6 +485,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
FuncDef *pDef; /* Information about the function */
u8 enc = ENC(pParse->db); /* The database encoding */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
zId = (char*)pExpr->token.z;
nId = pExpr->token.n;
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
@ -541,14 +542,14 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
case TK_EXISTS:
#endif
case TK_IN: {
if( pExpr->pSelect ){
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
int nRef = pNC->nRef;
#ifndef SQLITE_OMIT_CHECK
if( pNC->isCheck ){
sqlite3ErrorMsg(pParse,"subqueries prohibited in CHECK constraints");
}
#endif
sqlite3WalkSelect(pWalker, pExpr->pSelect);
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
assert( pNC->nRef>=nRef );
if( nRef!=pNC->nRef ){
ExprSetProperty(pExpr, EP_VarSelect);
@ -736,7 +737,7 @@ static int resolveCompoundOrderBy(
}else{
iCol = resolveAsName(pParse, pEList, pE);
if( iCol==0 ){
pDup = sqlite3ExprDup(db, pE);
pDup = sqlite3ExprDup(db, pE, 0);
if( !db->mallocFailed ){
assert(pDup);
iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup);

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.499 2009/02/09 13:19:28 drh Exp $
** $Id: select.c,v 1.500 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -987,8 +987,9 @@ static const char *columnType(
** statement.
*/
NameContext sNC;
Select *pS = pExpr->pSelect;
Select *pS = pExpr->x.pSelect;
Expr *p = pS->pEList->a[0].pExpr;
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
@ -2141,7 +2142,7 @@ static int multiSelectOrderBy(
/* Reattach the ORDER BY clause to the query.
*/
p->pOrderBy = pOrderBy;
pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy);
pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);
/* Allocate a range of temporary registers and the KeyInfo needed
** for the logic that removes duplicate result rows when the
@ -2392,23 +2393,26 @@ static void substExpr(
}else{
Expr *pNew;
assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
assert( pExpr->pLeft==0 && pExpr->pRight==0 && pExpr->pList==0 );
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
pNew = pEList->a[pExpr->iColumn].pExpr;
assert( pNew!=0 );
pExpr->op = pNew->op;
assert( pExpr->pLeft==0 );
pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft);
pExpr->pLeft = sqlite3ExprDup(db, pNew->pLeft, 0);
assert( pExpr->pRight==0 );
pExpr->pRight = sqlite3ExprDup(db, pNew->pRight);
assert( pExpr->pList==0 );
pExpr->pList = sqlite3ExprListDup(db, pNew->pList);
pExpr->pRight = sqlite3ExprDup(db, pNew->pRight, 0);
pExpr->iTable = pNew->iTable;
pExpr->pTab = pNew->pTab;
pExpr->iColumn = pNew->iColumn;
pExpr->iAgg = pNew->iAgg;
sqlite3TokenCopy(db, &pExpr->token, &pNew->token);
sqlite3TokenCopy(db, &pExpr->span, &pNew->span);
pExpr->pSelect = sqlite3SelectDup(db, pNew->pSelect);
assert( pExpr->x.pList==0 && pExpr->x.pSelect==0 );
if( ExprHasProperty(pNew, EP_xIsSelect) ){
pExpr->x.pSelect = sqlite3SelectDup(db, pNew->x.pSelect, 0);
}else{
pExpr->x.pList = sqlite3ExprListDup(db, pNew->x.pList, 0);
}
pExpr->flags = pNew->flags;
pExpr->pAggInfo = pNew->pAggInfo;
pNew->pAggInfo = 0;
@ -2416,8 +2420,11 @@ static void substExpr(
}else{
substExpr(db, pExpr->pLeft, iTable, pEList);
substExpr(db, pExpr->pRight, iTable, pEList);
substSelect(db, pExpr->pSelect, iTable, pEList);
substExprList(db, pExpr->pList, iTable, pEList);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
substSelect(db, pExpr->x.pSelect, iTable, pEList);
}else{
substExprList(db, pExpr->x.pList, iTable, pEList);
}
}
}
static void substExprList(
@ -2729,7 +2736,7 @@ static int flattenSubquery(
p->pSrc = 0;
p->pPrior = 0;
p->pLimit = 0;
pNew = sqlite3SelectDup(db, p);
pNew = sqlite3SelectDup(db, p, 0);
p->pLimit = pLimit;
p->pOrderBy = pOrderBy;
p->pSrc = pSrc;
@ -2873,7 +2880,7 @@ static int flattenSubquery(
substExprList(db, pParent->pOrderBy, iParent, pSub->pEList);
}
if( pSub->pWhere ){
pWhere = sqlite3ExprDup(db, pSub->pWhere);
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
}else{
pWhere = 0;
}
@ -2883,9 +2890,9 @@ static int flattenSubquery(
pParent->pWhere = pWhere;
substExpr(db, pParent->pHaving, iParent, pSub->pEList);
pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
sqlite3ExprDup(db, pSub->pHaving));
sqlite3ExprDup(db, pSub->pHaving, 0));
assert( pParent->pGroupBy==0 );
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy);
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
}else{
substExpr(db, pParent->pWhere, iParent, pSub->pEList);
pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
@ -2934,7 +2941,8 @@ static u8 minMaxQuery(Select *p){
if( pEList->nExpr!=1 ) return WHERE_ORDERBY_NORMAL;
pExpr = pEList->a[0].pExpr;
pEList = pExpr->pList;
if( ExprHasProperty(pExpr, EP_xIsSelect) ) return 0;
pEList = pExpr->x.pList;
if( pExpr->op!=TK_AGG_FUNCTION || pEList==0 || pEList->nExpr!=1 ) return 0;
if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
if( pExpr->token.n!=3 ) return WHERE_ORDERBY_NORMAL;
@ -3065,7 +3073,7 @@ static int selectExpander(Walker *pWalker, Select *p){
** in the inner view.
*/
if( pFrom->pSelect==0 ){
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect);
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
sqlite3WalkSelect(pWalker, pFrom->pSelect);
}
}
@ -3364,12 +3372,13 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
sqlite3VdbeAddOp2(v, OP_Null, 0, pFunc->iMem);
if( pFunc->iDistinct>=0 ){
Expr *pE = pFunc->pExpr;
if( pE->pList==0 || pE->pList->nExpr!=1 ){
assert( !ExprHasProperty(pE, EP_xIsSelect) );
if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
"argument");
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList);
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->x.pList);
sqlite3VdbeAddOp4(v, OP_OpenEphemeral, pFunc->iDistinct, 0, 0,
(char*)pKeyInfo, P4_KEYINFO_HANDOFF);
}
@ -3386,7 +3395,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList = pF->pExpr->pList;
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
sqlite3VdbeAddOp4(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0, 0,
(void*)pF->pFunc, P4_FUNCDEF);
}
@ -3407,7 +3417,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
int nArg;
int addrNext = 0;
int regAgg;
ExprList *pList = pF->pExpr->pList;
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
if( pList ){
nArg = pList->nExpr;
regAgg = sqlite3GetTempRange(pParse, nArg);
@ -3657,7 +3668,7 @@ int sqlite3Select(
** GROUP BY might use an index, DISTINCT never does.
*/
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct && !p->pGroupBy ){
p->pGroupBy = sqlite3ExprListDup(db, p->pEList);
p->pGroupBy = sqlite3ExprListDup(db, p->pEList, 0);
pGroupBy = p->pGroupBy;
p->selFlags &= ~SF_Distinct;
isDistinct = 0;
@ -3780,7 +3791,8 @@ int sqlite3Select(
}
sAggInfo.nAccumulator = sAggInfo.nColumn;
for(i=0; i<sAggInfo.nFunc; i++){
sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->pList);
assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
}
if( db->mallocFailed ) goto select_end;
@ -4018,7 +4030,9 @@ int sqlite3Select(
*/
flag = minMaxQuery(p);
if( flag ){
pDel = pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList);
assert( !ExprHasProperty(p->pEList->a[0].pExpr, EP_xIsSelect) );
pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->x.pList,0);
pDel = pMinMax;
if( pMinMax && !db->mallocFailed ){
pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0;
pMinMax->a[0].pExpr->op = TK_COLUMN;

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.833 2009/02/05 16:53:43 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.834 2009/02/19 14:39:25 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -1369,13 +1369,21 @@ struct AggInfo {
** to represent the greater-than-or-equal-to operator in the expression
** tree.
**
** Expr.pRight and Expr.pLeft are subexpressions. Expr.pList is a list
** of argument if the expression is a function.
** If the expression is an SQL literal (TK_INTEGER, TK_FLOAT, TK_BLOB,
** or TK_STRING), then Expr.token contains the text of the SQL literal. If
** the expression is a variable (TK_VARIABLE), then Expr.token contains the
** variable name. Finally, if the expression is an SQL function (TK_FUNCTION),
** then Expr.token contains the name of the function.
**
** Expr.token is the operator token for this node. For some expressions
** that have subexpressions, Expr.token can be the complete text that gave
** rise to the Expr. In the latter case, the token is marked as being
** a compound token.
** Expr.pRight and Expr.pLeft are the left and right subexpressions of a
** binary operator. Either or both may be NULL.
**
** Expr.x.pList is a list of arguments if the expression is an SQL function,
** a CASE expression or an IN expression of the form "<lhs> IN (<y>, <z>...)".
** Expr.x.pSelect is used if the expression is a sub-select or an expression of
** the form "<lhs> IN (SELECT ...)". If the EP_xIsSelect bit is set in the
** Expr.flags mask, then Expr.x.pSelect is valid. Otherwise, Expr.x.pList is
** valid.
**
** An expression of the form ID or ID.ID refers to a column in a table.
** For such expressions, Expr.op is set to TK_COLUMN and Expr.iTable is
@ -1385,10 +1393,9 @@ struct AggInfo {
** value is also stored in the Expr.iAgg column in the aggregate so that
** it can be accessed after all aggregates are computed.
**
** If the expression is a function, the Expr.iTable is an integer code
** representing which function. If the expression is an unbound variable
** marker (a question mark character '?' in the original SQL) then the
** Expr.iTable holds the index number for that variable.
** If the expression is an unbound variable marker (a question mark
** character '?' in the original SQL) then the Expr.iTable holds the index
** number for that variable.
**
** If the expression is a subquery then Expr.iColumn holds an integer
** register number containing the result of the subquery. If the
@ -1396,32 +1403,62 @@ struct AggInfo {
** gives a different answer at different times during statement processing
** then iTable is the address of a subroutine that computes the subquery.
**
** The Expr.pSelect field points to a SELECT statement. The SELECT might
** be the right operand of an IN operator. Or, if a scalar SELECT appears
** in an expression the opcode is TK_SELECT and Expr.pSelect is the only
** operand.
**
** If the Expr is of type OP_Column, and the table it is selecting from
** is a disk table or the "old.*" pseudo-table, then pTab points to the
** corresponding table definition.
**
** ALLOCATION NOTES:
**
** Expr structures may be stored as part of the in-memory database schema,
** for example as part of trigger, view or table definitions. In this case,
** the amount of memory consumed by complex expressions may be significant.
** For this reason, less than sizeof(Expr) bytes may be allocated for some
** Expr structs stored as part of the in-memory database schema.
**
** If the EP_Reduced flag is set in Expr.flags, then only EXPR_REDUCEDSIZE
** bytes of space are allocated for the expression structure. This is enough
** space to store all fields up to and including the "Token span;" field.
**
** If the EP_TokenOnly flag is set in Expr.flags, then only EXPR_TOKENONLYSIZE
** bytes of space are allocated for the expression structure. This is enough
** space to store all fields up to and including the "Token token;" field.
*/
struct Expr {
u8 op; /* Operation performed by this node */
char affinity; /* The affinity of the column or 0 if not a column */
u16 flags; /* Various flags. See below */
CollSeq *pColl; /* The collation type of the column or 0 */
Expr *pLeft, *pRight; /* Left and right subnodes */
ExprList *pList; /* A list of expressions used as function arguments
** or in "<expr> IN (<expr-list)" */
Token token; /* An operand token */
/* If the EP_TokenOnly flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
** access them will result in a segfault or malfunction.
*********************************************************************/
Token span; /* Complete text of the expression */
/* If the EP_SpanOnly flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
** access them will result in a segfault or malfunction.
*********************************************************************/
Expr *pLeft; /* Left subnode */
Expr *pRight; /* Right subnode */
union {
ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */
Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */
} x;
CollSeq *pColl; /* The collation type of the column or 0 */
/* If the EP_Reduced flag is set in the Expr.flags mask, then no
** space is allocated for the fields below this point. An attempt to
** access them will result in a segfault or malfunction.
*********************************************************************/
int iTable, iColumn; /* When op==TK_COLUMN, then this expr node means the
** iColumn-th field of the iTable-th table. */
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
int iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
int iRightJoinTable; /* If EP_FromJoin, the right table of the join */
Select *pSelect; /* When the expression is a sub-select. Also the
** right side of "<expr> IN (<select>)" */
Table *pTab; /* Table for TK_COLUMN expressions. */
#if SQLITE_MAX_EXPR_DEPTH>0
int nHeight; /* Height of the tree headed by this node */
@ -1443,6 +1480,12 @@ struct Expr {
#define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */
#define EP_FixedDest 0x0400 /* Result needed in a specific register */
#define EP_IntValue 0x0800 /* Integer value contained in iTable */
#define EP_xIsSelect 0x1000 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
#define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */
#define EP_SpanOnly 0x8000 /* Expr struct is EXPR_SPANONLYSIZE bytes only */
/*
** These macros can be used to test, set, or clear bits in the
** Expr.flags field.
@ -1452,6 +1495,23 @@ struct Expr {
#define ExprSetProperty(E,P) (E)->flags|=(P)
#define ExprClearProperty(E,P) (E)->flags&=~(P)
/*
** Macros to determine the number of bytes required by a normal Expr
** struct, an Expr struct with the EP_Reduced flag set in Expr.flags
** and an Expr struct with the EP_TokenOnly flag set.
*/
#define EXPR_FULLSIZE sizeof(Expr)
#define EXPR_REDUCEDSIZE ((int)(&((Expr*)(0))->iTable))
#define EXPR_TOKENONLYSIZE ((int)(&((Expr*)(0))->span))
#define EXPR_SPANONLYSIZE ((int)(&((Expr*)(0))->pLeft))
/*
** Flags passed to the sqlite3ExprDup() function. See the header comment
** above sqlite3ExprDup() for details.
*/
#define EXPRDUP_REDUCE 0x0001
#define EXPRDUP_SPAN 0x0002
/*
** A list of expressions. Each expression may optionally have a
** name. An expr/name combination can be used in several ways, such
@ -2379,12 +2439,12 @@ void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
Expr *sqlite3ExprDup(sqlite3*,Expr*);
Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
void sqlite3TokenCopy(sqlite3*,Token*, Token*);
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*);
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*);
Select *sqlite3SelectDup(sqlite3*,Select*,int);
void sqlite3FuncDefInsert(FuncDefHash*, FuncDef*);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,int,u8,int);
void sqlite3RegisterBuiltinFunctions(sqlite3*);

View File

@ -10,7 +10,7 @@
*************************************************************************
**
**
** $Id: trigger.c,v 1.133 2008/12/26 07:56:39 danielk1977 Exp $
** $Id: trigger.c,v 1.134 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -182,7 +182,7 @@ void sqlite3BeginTrigger(
pTrigger->pTabSchema = pTab->pSchema;
pTrigger->op = (u8)op;
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
pTrigger->pWhen = sqlite3ExprDup(db, pWhen);
pTrigger->pWhen = sqlite3ExprDup(db, pWhen, EXPRDUP_REDUCE);
pTrigger->pColumns = sqlite3IdListDup(db, pColumns);
sqlite3TokenCopy(db, &pTrigger->nameToken,pName);
assert( pParse->pNewTrigger==0 );
@ -292,17 +292,17 @@ static void sqlitePersistTriggerStep(sqlite3 *db, TriggerStep *p){
p->target.dyn = 1;
}
if( p->pSelect ){
Select *pNew = sqlite3SelectDup(db, p->pSelect);
Select *pNew = sqlite3SelectDup(db, p->pSelect, 1);
sqlite3SelectDelete(db, p->pSelect);
p->pSelect = pNew;
}
if( p->pWhere ){
Expr *pNew = sqlite3ExprDup(db, p->pWhere);
Expr *pNew = sqlite3ExprDup(db, p->pWhere, EXPRDUP_REDUCE);
sqlite3ExprDelete(db, p->pWhere);
p->pWhere = pNew;
}
if( p->pExprList ){
ExprList *pNew = sqlite3ExprListDup(db, p->pExprList);
ExprList *pNew = sqlite3ExprListDup(db, p->pExprList, 1);
sqlite3ExprListDelete(db, p->pExprList);
p->pExprList = pNew;
}
@ -546,6 +546,9 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
sqlite3ChangeCookie(pParse, iDb);
sqlite3VdbeAddOp2(v, OP_Close, 0, 0);
sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->name, 0);
if( pParse->nMem<3 ){
pParse->nMem = 3;
}
}
}
@ -677,7 +680,7 @@ static int codeTriggerProgram(
pParse->trigStack->orconf = orconf;
switch( pTriggerStep->op ){
case TK_SELECT: {
Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect);
Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect, 0);
if( ss ){
SelectDest dest;
@ -692,8 +695,8 @@ static int codeTriggerProgram(
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
sqlite3Update(pParse, pSrc,
sqlite3ExprListDup(db, pTriggerStep->pExprList),
sqlite3ExprDup(db, pTriggerStep->pWhere), orconf);
sqlite3ExprListDup(db, pTriggerStep->pExprList, 0),
sqlite3ExprDup(db, pTriggerStep->pWhere, 0), orconf);
sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
break;
}
@ -702,8 +705,8 @@ static int codeTriggerProgram(
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
sqlite3Insert(pParse, pSrc,
sqlite3ExprListDup(db, pTriggerStep->pExprList),
sqlite3SelectDup(db, pTriggerStep->pSelect),
sqlite3ExprListDup(db, pTriggerStep->pExprList, 0),
sqlite3SelectDup(db, pTriggerStep->pSelect, 0),
sqlite3IdListDup(db, pTriggerStep->pIdList), orconf);
sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
break;
@ -713,7 +716,7 @@ static int codeTriggerProgram(
sqlite3VdbeAddOp2(v, OP_ResetCount, 0, 0);
pSrc = targetSrcList(pParse, pTriggerStep);
sqlite3DeleteFrom(pParse, pSrc,
sqlite3ExprDup(db, pTriggerStep->pWhere));
sqlite3ExprDup(db, pTriggerStep->pWhere, 0));
sqlite3VdbeAddOp2(v, OP_ResetCount, 1, 0);
break;
}
@ -830,7 +833,7 @@ int sqlite3CodeRowTrigger(
/* code the WHEN clause */
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
whenExpr = sqlite3ExprDup(db, p->pWhen);
whenExpr = sqlite3ExprDup(db, p->pWhen, 0);
if( db->mallocFailed || sqlite3ResolveExprNames(&sNC, whenExpr) ){
pParse->trigStack = trigStackEntry.pNext;
sqlite3ExprDelete(db, whenExpr);

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.191 2008/12/23 23:56:22 drh Exp $
** $Id: update.c,v 1.192 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -633,12 +633,12 @@ static void updateVirtualTable(
sqlite3CreateIdExpr(pParse, "_rowid_"), 0);
if( pRowid ){
pEList = sqlite3ExprListAppend(pParse, pEList,
sqlite3ExprDup(db, pRowid), 0);
sqlite3ExprDup(db, pRowid, 0), 0);
}
assert( pTab->iPKey<0 );
for(i=0; i<pTab->nCol; i++){
if( aXRef[i]>=0 ){
pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr);
pExpr = sqlite3ExprDup(db, pChanges->a[aXRef[i]].pExpr, 0);
}else{
pExpr = sqlite3CreateIdExpr(pParse, pTab->aCol[i].zName);
}

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.817 2009/02/16 17:55:47 shane Exp $
** $Id: vdbe.c,v 1.818 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -1002,15 +1002,14 @@ case OP_Move: {
int n = pOp->p3;
int p1 = pOp->p1;
int p2 = pOp->p2;
assert( n>0 );
assert( p1>0 );
assert( p1+n<p->nMem );
pIn1 = &p->aMem[p1];
assert( p2>0 );
assert( p2+n<p->nMem );
pOut = &p->aMem[p2];
assert( n>0 && p1>0 && p2>0 );
assert( p1+n<=p2 || p2+n<=p1 );
pIn1 = &p->aMem[p1];
pOut = &p->aMem[p2];
while( n-- ){
assert( pOut<=&p->aMem[p->nMem] );
assert( pIn1<=&p->aMem[p->nMem] );
zMalloc = pOut->zMalloc;
pOut->zMalloc = 0;
sqlite3VdbeMemMove(pOut, pIn1);
@ -1076,7 +1075,7 @@ case OP_ResultRow: {
int i;
assert( p->nResColumn==pOp->p2 );
assert( pOp->p1>0 );
assert( pOp->p1+pOp->p2<=p->nMem );
assert( pOp->p1+pOp->p2<=p->nMem+1 );
/* Invalidate all ephemeral cursor row caches */
p->cacheCtr = (p->cacheCtr + 2)|1;
@ -1095,7 +1094,6 @@ case OP_ResultRow: {
/* Return SQLITE_ROW
*/
p->nCallback++;
p->pc = pc + 1;
rc = SQLITE_ROW;
goto vdbe_return;
@ -1300,7 +1298,7 @@ case OP_Function: {
apVal = p->apArg;
assert( apVal || n==0 );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem) );
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
pArg = &p->aMem[pOp->p2];
for(i=0; i<n; i++, pArg++){
@ -1736,9 +1734,9 @@ case OP_Compare: {
assert( n>0 );
assert( pKeyInfo!=0 );
p1 = pOp->p1;
assert( p1>0 && p1+n-1<p->nMem );
assert( p1>0 && p1+n<=p->nMem+1 );
p2 = pOp->p2;
assert( p2>0 && p2+n-1<p->nMem );
assert( p2>0 && p2+n<=p->nMem+1 );
for(i=0; i<n; i++){
int idx = aPermute ? aPermute[i] : i;
CollSeq *pColl; /* Collating sequence to use on this term */
@ -2253,7 +2251,7 @@ case OP_MakeRecord: {
nField = pOp->p1;
zAffinity = pOp->p4.z;
assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem );
assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem+1 );
pData0 = &p->aMem[nField];
nField = pOp->p2;
pLast = &pData0[nField-1];
@ -4066,7 +4064,7 @@ case OP_IdxDelete: {
VdbeCursor *pC;
BtCursor *pCrsr;
assert( pOp->p3>0 );
assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem );
assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 );
assert( i>=0 && i<p->nCursor );
assert( p->apCsr[i]!=0 );
if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
@ -5204,13 +5202,14 @@ case OP_Pagecount: { /* out2-prerelease */
** the UTF-8 string contained in P4 is emitted on the trace callback.
*/
case OP_Trace: {
if( pOp->p4.z ){
char *zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
if( zTrace ){
if( db->xTrace ){
db->xTrace(db->pTraceArg, pOp->p4.z);
db->xTrace(db->pTraceArg, zTrace);
}
#ifdef SQLITE_DEBUG
if( (db->flags & SQLITE_SqlTrace)!=0 ){
sqlite3DebugPrintf("SQL-trace: %s\n", pOp->p4.z);
sqlite3DebugPrintf("SQL-trace: %s\n", zTrace);
}
#endif /* SQLITE_DEBUG */
}

View File

@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.139 2008/10/31 10:53:23 danielk1977 Exp $
** $Id: vdbe.h,v 1.140 2009/02/19 14:39:25 danielk1977 Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@ -181,7 +181,7 @@ void sqlite3VdbeSetNumCols(Vdbe*,int);
int sqlite3VdbeSetColName(Vdbe*, int, int, const char *, void(*)(void*));
void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, int);
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT

View File

@ -15,7 +15,7 @@
** 6000 lines long) it was split up into several smaller files and
** this header information was factored out.
**
** $Id: vdbeInt.h,v 1.162 2009/02/03 15:39:01 drh Exp $
** $Id: vdbeInt.h,v 1.163 2009/02/19 14:39:25 danielk1977 Exp $
*/
#ifndef _VDBEINT_H_
#define _VDBEINT_H_
@ -279,16 +279,13 @@ struct Vdbe {
u32 magic; /* Magic number for sanity checking */
int nMem; /* Number of memory locations currently allocated */
Mem *aMem; /* The memory locations */
int nCallback; /* Number of callbacks invoked so far */
int cacheCtr; /* VdbeCursor row cache generation counter */
int contextStackTop; /* Index of top element in the context stack */
int contextStackDepth; /* The size of the "context" stack */
Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
int pc; /* The program counter */
int rc; /* Value to return */
unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
int errorAction; /* Recovery action to do in case of an error */
int inTempTrans; /* True if temp database is transactioned */
int nResColumn; /* Number of columns in one row of the result set */
char **azResColumn; /* Values for one row of result */
char *zErrMsg; /* Error message written here */
@ -300,12 +297,12 @@ struct Vdbe {
u8 inVtabMethod; /* See comments above */
u8 usesStmtJournal; /* True if uses a statement journal */
u8 readOnly; /* True for read-only statements */
u8 isPrepareV2; /* True if prepared with prepare_v2() */
int nChange; /* Number of db changes made since last reset */
i64 startTime; /* Time when query started - used for profiling */
int btreeMask; /* Bitmask of db->aDb[] entries referenced */
BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
int aCounter[2]; /* Counters used by sqlite3_stmt_status() */
int nSql; /* Number of bytes in zSql */
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_DEBUG
FILE *trace; /* Write an execution trace here, if not NULL */

View File

@ -13,7 +13,7 @@
** This file contains code use to implement APIs that are part of the
** VDBE.
**
** $Id: vdbeapi.c,v 1.151 2009/02/04 03:59:25 shane Exp $
** $Id: vdbeapi.c,v 1.152 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -488,15 +488,14 @@ static int sqlite3Step(Vdbe *p){
#ifndef SQLITE_OMIT_TRACE
/* Invoke the profile callback if there is one
*/
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->nOp>0
&& p->aOp[0].opcode==OP_Trace && p->aOp[0].p4.z!=0 ){
if( rc!=SQLITE_ROW && db->xProfile && !db->init.busy && p->zSql ){
double rNow;
u64 elapseTime;
sqlite3OsCurrentTime(db->pVfs, &rNow);
elapseTime = (u64)((rNow - (int)rNow)*3600.0*24.0*1000000000.0);
elapseTime -= p->startTime;
db->xProfile(db->pProfileArg, p->aOp[0].p4.z, elapseTime);
db->xProfile(db->pProfileArg, p->zSql, elapseTime);
}
#endif
@ -505,7 +504,7 @@ static int sqlite3Step(Vdbe *p){
p->rc = sqlite3ApiExit(p->db, p->rc);
end_of_step:
assert( (rc&0xff)==rc );
if( p->zSql && (rc&0xff)<SQLITE_ROW ){
if( p->isPrepareV2 && (rc&0xff)<SQLITE_ROW ){
/* This behavior occurs if sqlite3_prepare_v2() was used to build
** the prepared statement. Return error codes directly */
p->db->errCode = p->rc;
@ -549,7 +548,7 @@ int sqlite3_step(sqlite3_stmt *pStmt){
sqlite3_reset(pStmt);
v->expired = 0;
}
if( rc==SQLITE_SCHEMA && v->zSql && db->pErr ){
if( rc==SQLITE_SCHEMA && v->isPrepareV2 && db->pErr ){
/* This case occurs after failing to recompile an sql statement.
** The error message from the SQL compiler has already been loaded
** into the database handle. This block copies the error message

View File

@ -14,7 +14,7 @@
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.435 2009/02/03 16:51:25 danielk1977 Exp $
** $Id: vdbeaux.c,v 1.436 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -52,17 +52,22 @@ Vdbe *sqlite3VdbeCreate(sqlite3 *db){
/*
** Remember the SQL string for a prepared statement.
*/
void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n){
void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){
if( p==0 ) return;
#ifdef SQLITE_OMIT_TRACE
if( !isPrepareV2 ) return;
#endif
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
p->isPrepareV2 = isPrepareV2;
}
/*
** Return the SQL associated with a prepared statement
*/
const char *sqlite3_sql(sqlite3_stmt *pStmt){
return ((Vdbe *)pStmt)->zSql;
Vdbe *p = (Vdbe *)pStmt;
return (p->isPrepareV2 ? p->zSql : 0);
}
/*
@ -71,7 +76,6 @@ const char *sqlite3_sql(sqlite3_stmt *pStmt){
void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
Vdbe tmp, *pTmp;
char *zTmp;
int nTmp;
tmp = *pA;
*pA = *pB;
*pB = tmp;
@ -84,9 +88,7 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
nTmp = pA->nSql;
pA->nSql = pB->nSql;
pB->nSql = nTmp;
pB->isPrepareV2 = pA->isPrepareV2;
}
#ifdef SQLITE_DEBUG
@ -1007,6 +1009,14 @@ void sqlite3VdbeIOTraceSql(Vdbe *p){
**
** This is the only way to move a VDBE from VDBE_MAGIC_INIT to
** VDBE_MAGIC_RUN.
**
** This function may be called more than once on a single virtual machine.
** The first call is made while compiling the SQL statement. Subsequent
** calls are made as part of the process of resetting a statement to be
** re-executed (from a call to sqlite3_reset()). The nVar, nMem, nCursor
** and isExplain parameters are only passed correct values the first time
** the function is called. On subsequent calls, from sqlite3_reset(), nVar
** is passed -1 and nMem, nCursor and isExplain are all passed zero.
*/
void sqlite3VdbeMakeReady(
Vdbe *p, /* The VDBE */
@ -1039,23 +1049,26 @@ void sqlite3VdbeMakeReady(
*/
nMem += nCursor;
/*
** Allocation space for registers.
/* Allocate space for memory registers, SQL variables, VDBE cursors and
** an array to marshal SQL function arguments in. This is only done the
** first time this function is called for a given VDBE, not when it is
** being called from sqlite3_reset() to reset the virtual machine.
*/
if( p->aMem==0 ){
if( nVar>=0 ){
int nByte;
int nArg; /* Maximum number of args passed to a user function. */
resolveP2Values(p, &nArg);
assert( nVar>=0 );
if( isExplain && nMem<10 ){
nMem = 10;
}
p->aMem = sqlite3DbMallocZero(db,
nMem*sizeof(Mem) /* aMem */
nByte = nMem*sizeof(Mem) /* aMem */
+ nVar*sizeof(Mem) /* aVar */
+ nArg*sizeof(Mem*) /* apArg */
+ nVar*sizeof(char*) /* azVar */
+ nCursor*sizeof(VdbeCursor*)+1 /* apCsr */
);
+ nCursor*sizeof(VdbeCursor*); /* apCsr */
if( nByte ){
p->aMem = sqlite3DbMallocZero(db, nByte);
}
if( !db->mallocFailed ){
p->aMem--; /* aMem[] goes from 1..nMem */
p->nMem = nMem; /* not from 0..nMem-1 */
@ -1084,7 +1097,6 @@ void sqlite3VdbeMakeReady(
p->pc = -1;
p->rc = SQLITE_OK;
p->uniqueCnt = 0;
p->errorAction = OE_Abort;
p->explain |= isExplain;
p->magic = VDBE_MAGIC_RUN;

View File

@ -12,7 +12,7 @@
** This file contains routines used for walking the parser tree for
** an SQL statement.
**
** $Id: walker.c,v 1.1 2008/08/20 16:35:10 drh Exp $
** $Id: walker.c,v 1.2 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
@ -45,9 +45,10 @@ int sqlite3WalkExpr(Walker *pWalker, Expr *pExpr){
if( rc==WRC_Continue ){
if( sqlite3WalkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
if( sqlite3WalkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
if( sqlite3WalkExprList(pWalker, pExpr->pList) ) return WRC_Abort;
if( sqlite3WalkSelect(pWalker, pExpr->pSelect) ){
return WRC_Abort;
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
}else{
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
}
}
return rc & WRC_Abort;

View File

@ -16,7 +16,7 @@
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.368 2009/02/04 03:59:25 shane Exp $
** $Id: where.c,v 1.369 2009/02/19 14:39:25 danielk1977 Exp $
*/
#include "sqliteInt.h"
@ -431,8 +431,11 @@ static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){
}
mask = exprTableUsage(pMaskSet, p->pRight);
mask |= exprTableUsage(pMaskSet, p->pLeft);
mask |= exprListTableUsage(pMaskSet, p->pList);
mask |= exprSelectTableUsage(pMaskSet, p->pSelect);
if( ExprHasProperty(p, EP_xIsSelect) ){
mask |= exprSelectTableUsage(pMaskSet, p->x.pSelect);
}else{
mask |= exprListTableUsage(pMaskSet, p->x.pList);
}
return mask;
}
static Bitmask exprListTableUsage(WhereMaskSet *pMaskSet, ExprList *pList){
@ -634,7 +637,7 @@ static int isLikeOrGlob(
#ifdef SQLITE_EBCDIC
if( *pnoCase ) return 0;
#endif
pList = pExpr->pList;
pList = pExpr->x.pList;
pRight = pList->a[0].pExpr;
if( pRight->op!=TK_STRING ){
return 0;
@ -689,7 +692,7 @@ static int isMatchOfColumn(
sqlite3StrNICmp((const char*)pExpr->token.z,"match",5)!=0 ){
return 0;
}
pList = pExpr->pList;
pList = pExpr->x.pList;
if( pList->nExpr!=2 ){
return 0;
}
@ -953,17 +956,18 @@ static void exprAnalyzeOrTerm(
assert( pOrTerm->eOperator==WO_EQ );
assert( pOrTerm->leftCursor==iCursor );
assert( pOrTerm->u.leftColumn==iColumn );
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight);
pDup = sqlite3ExprDup(db, pOrTerm->pExpr->pRight, 0);
pList = sqlite3ExprListAppend(pWC->pParse, pList, pDup, 0);
pLeft = pOrTerm->pExpr->pLeft;
}
assert( pLeft!=0 );
pDup = sqlite3ExprDup(db, pLeft);
pDup = sqlite3ExprDup(db, pLeft, 0);
pNew = sqlite3Expr(db, TK_IN, pDup, 0, 0);
if( pNew ){
int idxNew;
transferJoinMarkings(pNew, pExpr);
pNew->pList = pList;
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
pNew->x.pList = pList;
idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
@ -1026,8 +1030,11 @@ static void exprAnalyze(
op = pExpr->op;
if( op==TK_IN ){
assert( pExpr->pRight==0 );
pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->pList)
| exprSelectTableUsage(pMaskSet, pExpr->pSelect);
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect);
}else{
pTerm->prereqRight = exprListTableUsage(pMaskSet, pExpr->x.pList);
}
}else if( op==TK_ISNULL ){
pTerm->prereqRight = 0;
}else{
@ -1057,7 +1064,7 @@ static void exprAnalyze(
Expr *pDup;
if( pTerm->leftCursor>=0 ){
int idxNew;
pDup = sqlite3ExprDup(db, pExpr);
pDup = sqlite3ExprDup(db, pExpr, 0);
if( db->mallocFailed ){
sqlite3ExprDelete(db, pDup);
return;
@ -1100,7 +1107,7 @@ static void exprAnalyze(
** BETWEEN term is skipped.
*/
else if( pExpr->op==TK_BETWEEN && pWC->op==TK_AND ){
ExprList *pList = pExpr->pList;
ExprList *pList = pExpr->x.pList;
int i;
static const u8 ops[] = {TK_GE, TK_LE};
assert( pList!=0 );
@ -1108,8 +1115,8 @@ static void exprAnalyze(
for(i=0; i<2; i++){
Expr *pNewExpr;
int idxNew;
pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft),
sqlite3ExprDup(db, pList->a[i].pExpr), 0);
pNewExpr = sqlite3Expr(db, ops[i], sqlite3ExprDup(db, pExpr->pLeft, 0),
sqlite3ExprDup(db, pList->a[i].pExpr, 0), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
exprAnalyze(pSrc, pWC, idxNew);
@ -1148,18 +1155,18 @@ static void exprAnalyze(
Expr *pNewExpr1, *pNewExpr2;
int idxNew1, idxNew2;
pLeft = pExpr->pList->a[1].pExpr;
pRight = pExpr->pList->a[0].pExpr;
pLeft = pExpr->x.pList->a[1].pExpr;
pRight = pExpr->x.pList->a[0].pExpr;
pStr1 = sqlite3PExpr(pParse, TK_STRING, 0, 0, 0);
if( pStr1 ){
sqlite3TokenCopy(db, &pStr1->token, &pRight->token);
pStr1->token.n = nPattern;
pStr1->flags = EP_Dequoted;
}
pStr2 = sqlite3ExprDup(db, pStr1);
pStr2 = sqlite3ExprDup(db, pStr1, 0);
if( !db->mallocFailed ){
u8 c, *pC;
assert( pStr2->token.dyn );
/* assert( pStr2->token.dyn ); */
pC = (u8*)&pStr2->token.z[nPattern-1];
c = *pC;
if( noCase ){
@ -1168,11 +1175,11 @@ static void exprAnalyze(
}
*pC = c + 1;
}
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft), pStr1, 0);
pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprDup(db,pLeft,0),pStr1,0);
idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew1==0 );
exprAnalyze(pSrc, pWC, idxNew1);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft), pStr2, 0);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprDup(db,pLeft,0),pStr2,0);
idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew2==0 );
exprAnalyze(pSrc, pWC, idxNew2);
@ -1198,13 +1205,13 @@ static void exprAnalyze(
WhereTerm *pNewTerm;
Bitmask prereqColumn, prereqExpr;
pRight = pExpr->pList->a[0].pExpr;
pLeft = pExpr->pList->a[1].pExpr;
pRight = pExpr->x.pList->a[0].pExpr;
pLeft = pExpr->x.pList->a[1].pExpr;
prereqExpr = exprTableUsage(pMaskSet, pRight);
prereqColumn = exprTableUsage(pMaskSet, pLeft);
if( (prereqExpr & prereqColumn)==0 ){
Expr *pNewExpr;
pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight), 0);
pNewExpr = sqlite3Expr(db, TK_MATCH, 0, sqlite3ExprDup(db, pRight, 0), 0);
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
testcase( idxNew==0 );
pNewTerm = &pWC->a[idxNew];
@ -1776,10 +1783,12 @@ static void bestIndex(
pCost->rCost = 0;
pCost->nRow = 1;
return;
}else if( (pExpr = pTerm->pExpr)->pList!=0 ){
}else if( !ExprHasProperty((pExpr = pTerm->pExpr), EP_xIsSelect)
&& pExpr->x.pList
){
/* Rowid IN (LIST): cost is NlogN where N is the number of list
** elements. */
pCost->rCost = pCost->nRow = pExpr->pList->nExpr;
pCost->rCost = pCost->nRow = pExpr->x.pList->nExpr;
pCost->rCost *= estLog(pCost->rCost);
}else{
/* Rowid IN (SELECT): cost is NlogN where N is the number of rows
@ -1925,10 +1934,10 @@ static void bestIndex(
if( pTerm->eOperator & WO_IN ){
Expr *pExpr = pTerm->pExpr;
wsFlags |= WHERE_COLUMN_IN;
if( pExpr->pSelect!=0 ){
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
inMultiplier *= 25;
}else if( pExpr->pList ){
inMultiplier *= pExpr->pList->nExpr + 1;
}else if( pExpr->x.pList ){
inMultiplier *= pExpr->x.pList->nExpr + 1;
}
}
}

View File

@ -12,7 +12,7 @@
# focus of this file is testing corner cases of the DEFAULT syntax
# on table definitions.
#
# $Id: default.test,v 1.2 2005/08/20 03:03:04 drh Exp $
# $Id: default.test,v 1.3 2009/02/19 14:39:25 danielk1977 Exp $
#
set testdir [file dirname $argv0]
@ -49,4 +49,19 @@ do_test default-1.3 {
}
} {1 {default value of column [y] is not constant}}
ifcapable pragma {
do_test default-2.1 {
execsql {
CREATE TABLE t4(c DEFAULT 'abc');
PRAGMA table_info(t4);
}
} {0 c {} 0 'abc' 0}
do_test default-2.2 {
execsql {
INSERT INTO t4 DEFAULT VALUES;
PRAGMA table_info(t4);
}
} {0 c {} 0 'abc' 0}
}
finish_test

View File

@ -11,7 +11,7 @@
# This file implements some common TCL routines used for regression
# testing the SQLite library
#
# $Id: tester.tcl,v 1.139 2009/02/05 16:31:46 drh Exp $
# $Id: tester.tcl,v 1.140 2009/02/19 14:39:25 danielk1977 Exp $
#
# What for user input before continuing. This gives an opportunity
@ -895,16 +895,16 @@ proc memdebug_log_sql {{filename mallocs.sql}} {
set database temp
set tbl "CREATE TABLE ${database}.malloc(nCall, nByte"
for {set ii 1} {$ii <= $nFrame} {incr ii} {
append tbl ", f${ii}"
}
append tbl ");\n"
set tbl "CREATE TABLE ${database}.malloc(zTest, nCall, nByte, lStack);"
set sql ""
foreach e $data {
append sql "INSERT INTO ${database}.malloc VALUES([join $e ,]);\n"
foreach f [lrange $e 2 end] {
set nCall [lindex $e 0]
set nByte [lindex $e 1]
set lStack [lrange $e 2 end]
append sql "INSERT INTO ${database}.malloc VALUES"
append sql "('test', $nCall, $nByte, '$lStack');\n"
foreach f $lStack {
set frames($f) 1
}
}