Additional refinements to Expr handling. Restore compression of trigger

expressions.  Change Expr.zToken to Expr.u.zToken and added Expr.u.iValue.
Remove an unnecessary ExprDup from CHECK constraint processing.  And so forth. (CVS 6682)

FossilOrigin-Name: 4ac2bdfbb4230b6ceaae87e738fa61036bbe03cb
This commit is contained in:
drh 2009-05-28 01:00:55 +00:00
parent b7916a78ff
commit 33e619fc1c
23 changed files with 296 additions and 197 deletions

View File

@ -1,5 +1,5 @@
C Simplifications\sto\sthe\sExpr\sobject:\s\sRemove\sExpr.span\scompletely\sand\sconvert\nExpr.token\sinto\sa\schar*\sExpr.zToken.\s\sAlso\ssimplify\sthe\sToken\sobject\sby\nremoving\sthe\sToken.dyn\sand\sToken.quoted\sfields.\s(CVS\s6681)
D 2009-05-27T10:31:29
C Additional\srefinements\sto\sExpr\shandling.\s\sRestore\scompression\sof\strigger\nexpressions.\s\sChange\sExpr.zToken\sto\sExpr.u.zToken\sand\sadded\sExpr.u.iValue.\nRemove\san\sunnecessary\sExprDup\sfrom\sCHECK\sconstraint\sprocessing.\s\sAnd\sso\sforth.\s(CVS\s6682)
D 2009-05-28T01:00:55
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -99,9 +99,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c accb3c77ef20903e16ec44a04f5ee5ff1bfcf7e4
F src/alter.c 88b8cc66c09853b5723f66cfd0103dbebb62c562
F src/analyze.c e239496cfb5394ac8867f1c112905ddab8d01cd9
F src/attach.c 92517f52fb53037c0584c0ecac922ec83e5d9d42
F src/attach.c ad7eeae19c0844d3b329781c5a35ccda0a2010d2
F src/auth.c 98db07c2088455797678eb1031f42d4d94d18a71
F src/backup.c 437efc2c3371b52bbb943b8c9dfabba774adcf86
F src/bitvec.c ef370407e03440b0852d05024fb016b14a471d3d
@ -109,14 +109,14 @@ F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c
F src/btree.c 7c4b02afea7efb561361f20408414fec68df898c
F src/btree.h 58d876d3ed944a8f4f1fd0e67024b385243fc9dd
F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5
F src/build.c 028255aa488ee3941ee77e16ae078ad5e03fe6d8
F src/build.c 567574f5756e9e462cf50c5da1895dc43672bafe
F src/callback.c 57359fa93de47c341b6b8ee504a88ff276397686
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
F src/delete.c 59da0e52380d7626e98d84082b72f431fafe2799
F src/expr.c cdddb81c68a0d222e03a4b92a7821d370c298a8e
F src/delete.c cb791855c7948cecc96def9d97989879ca26f257
F src/expr.c 2f8b6e5c3c867fa421189ad5692b1ff60ecc59c4
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
F src/func.c be5067593d9c8971e1af803bb503b91ef1541e8d
F src/func.c 9d7b47729c337c5e4b78d795922ed34eec4aef67
F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
@ -148,21 +148,21 @@ F src/os_unix.c e55d977c516ed880a2f83f0610b019efd9f8bc06
F src/os_win.c 725c38a524d168ce280446ad8761d731bc516405
F src/pager.c 8bf62fefc7afefc065d37611ebfd1fe0e1c2eb39
F src/pager.h 73f481a308a873ccd626d97331c081db3b53e2e5
F src/parse.y 6b55e52fb3362ad84130013f861c21f4b3ba5005
F src/parse.y 07690df997d50b3fdb5e5121e5a27f1a080db13d
F src/pcache.c 395f752a13574120bd7513a400ba02a265aaa76d
F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324
F src/pcache1.c bed75f157283e7c666f323df0c874c6a2515f76e
F src/pragma.c cf9adc601f5d0e6de6f3a3ffb8fa5dfef8217d13
F src/pragma.c d4a6fd74fd1dba0f22c8930791f7fbbe80d2ef26
F src/prepare.c f46d1a029760edee5447e27164fb3ae10e2a6839
F src/printf.c 3f4dca207a88258d37af5a7a03e800a825fe6456
F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628
F src/resolve.c 0c9faa469e4e71ff84efd7fa60613036e88498d6
F src/resolve.c 64e7ac825a887eb5e33262f0b355514734b24ccd
F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f
F src/select.c 18c296d45cc8cad8dc4b862d2df000a4681d7883
F src/select.c fd1737a667bab296f50049a841b3aba5ec89418e
F src/shell.c 7eacd0bdaa887931f5ff205c9defc3e8df95a2dd
F src/sqlite.h.in 79210c4d8905cfb4b038486dde5f36fabb796a86
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h 28a5b5c0bfb0efbb735dc0dedc3f076f7de95c57
F src/sqliteInt.h 97f9125229c14cd3afa6c4fed4b419a1899be476
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
@ -197,11 +197,11 @@ F src/test_server.c f0a403b5f699c09bd2b1236b6f69830fd6221f6b
F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4
F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac
F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241
F src/tokenize.c ef5e56bae212d08ff3a334ff059bc5292322251d
F src/trigger.c 6d233d6d737a229e31f810012f38ecac7dd89021
F src/update.c 3aec63a3a85754d16f7571ec80eb928e2fcf6c2e
F src/tokenize.c 75367c7e4d2aee39a3b0496911284b73de5b4363
F src/trigger.c c07c5157c58fcdb704f65d5f5e4775276e45bb8b
F src/update.c 6ae6c26adff8dc34532d578f66e6cfde04b5d177
F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff
F src/util.c f3ee188f05921d450ee2a2ff236e455d3131f9ce
F src/util.c bb2bdd6dd0b51d13301dfb5bfba7abf070aef1dd
F src/vacuum.c e8d178004377e97500c7ea87c8a3542976e3ea45
F src/vdbe.c b859cb274024e5755aa03625251ff859e3e95158
F src/vdbe.h 35a648bc3279a120da24f34d9a25213ec15daf8a
@ -209,10 +209,10 @@ F src/vdbeInt.h 43183a2a18654fa570219ab65e53a608057c48ae
F src/vdbeapi.c 86aa27a5f3493aaffb8ac051782aa3b22670d7ed
F src/vdbeaux.c 1a07329bdf51cc3687f88d9f5b2bd3f1d47cc5a8
F src/vdbeblob.c 5c5abe9af28316772e7829359f6f9cda2c737ebd
F src/vdbemem.c 4d1a9b01ad47a8699b767bfc364168c61510b3d1
F src/vdbemem.c 9f4224911176f27b80d6e8f70f0e909aead5091b
F src/vtab.c b0216337ae7d27708dedd56d220e6f4fecda92f1
F src/walker.c b28cc618f5dc739bc5fb77389b6a42bc1be679ab
F src/where.c 145bb0d0590b36603a38f0fe17887fde06c3ed53
F src/walker.c ec4b9742a4077ef80346e2f9aaf0f44c2d95087a
F src/where.c 1a21128db4905a29c287086acd7962cbba1c6f7b
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
@ -226,7 +226,7 @@ F test/async.test c042ff6d2a29f65e05d498a52448229d25bb5d9d
F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6
F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e
F test/async4.test bdb997924394a2034ff3df1d839ff95b2e602ed4
F test/attach.test 27635c34453504c2df8630730a5eab6e98c59eb9
F test/attach.test e710d543769305942e9354cee5aba8cfcbe89577
F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437
F test/attach3.test 7b92dc8e40c1ebca9732ca6f2d3fefbd46f196df
F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61
@ -521,7 +521,7 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
F test/savepoint6.test e28f7d8ab8a389d4e5bd1dc08bf2c3312754cc67
F test/schema.test deafe5472099ab5bc65748059dc5182fc8ebad74
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
F test/select1.test 313078d5fca7a6fe1fb83e5f2e5b3e317beb8fac
F test/select1.test f67ca2dfc05df41c7b86eb32ca409b427a5f43b0
F test/select2.test 9735da20ccd41e42bf2b4c19fd939141b591adae
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 44aa6e7110592e18110b0b9cf5c024d37d23be17
@ -629,7 +629,7 @@ F test/tkt3457.test e9ca2b90f0eb1fb8be73a30d29aacb2e3abedeb9
F test/tkt3461.test f79d027198b7e2bcf3d2d1a5501b6efef52096ee
F test/tkt3472.test 98c7e54b8fef2b1266a552a66c8e5d88a6908d1d
F test/tkt3493.test 8472b3464e49a27ff7271308eec46154209e667b
F test/tkt3508.test 26dbc10515145627fde6ad8905c842cec18e6f87
F test/tkt3508.test d75704db9501625c7f7deec119fcaf1696aefb7d
F test/tkt3522.test 22ce2ebbcb04a6be56c0977d405c207967318fd6
F test/tkt3527.test ee4af96183579565987e58873a7490bc04934ffb
F test/tkt3541.test 5dc257bde9bc833ab9cc6844bf170b998dbb950a
@ -731,7 +731,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
P 086206e1f51e22ce7b9f45865b370088db126cd2
R 7a6811accc43c94a2230cdb121b78704
P 7cb1c3ba0759539cb035978fdaff6316775986f3
R fbcf886b0709cb6861bc0baa12580b58
U drh
Z 55c79ac1dc5e1ab2bd7febb8a2417351
Z 0ccb491a6522821e67071949c3a88c54

View File

@ -1 +1 @@
7cb1c3ba0759539cb035978fdaff6316775986f3
4ac2bdfbb4230b6ceaae87e738fa61036bbe03cb

View File

@ -12,7 +12,7 @@
** This file contains C code routines that used to generate VDBE code
** that implements the ALTER TABLE command.
**
** $Id: alter.c,v 1.59 2009/05/27 10:31:29 drh Exp $
** $Id: alter.c,v 1.60 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
**
** $Id: attach.c,v 1.91 2009/05/27 10:31:29 drh Exp $
** $Id: attach.c,v 1.92 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
@ -41,7 +41,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr)
if( pExpr->op!=TK_ID ){
rc = sqlite3ResolveExprNames(pName, pExpr);
if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){
sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->zToken);
sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken);
return SQLITE_ERROR;
}
}else{
@ -312,7 +312,7 @@ static void codeAttach(
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pAuthArg ){
char *zAuthArg = pAuthArg->zToken;
char *zAuthArg = pAuthArg->u.zToken;
if( zAuthArg==0 ){
goto attach_end;
}

View File

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.545 2009/05/27 10:31:29 drh Exp $
** $Id: build.c,v 1.546 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
@ -1181,14 +1181,12 @@ void sqlite3AddCheckConstraint(
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
if( pTab && !IN_DECLARE_VTAB ){
/* The CHECK expression must be duplicated so that tokens refer
** to malloced space and not the (ephemeral) text of the CREATE TABLE
** statement */
pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck,
sqlite3ExprDup(db, pCheckExpr, 0));
}
pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, pCheckExpr);
}else
#endif
sqlite3ExprDelete(db, pCheckExpr);
{
sqlite3ExprDelete(db, pCheckExpr);
}
}
/*

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.202 2009/05/27 10:31:29 drh Exp $
** $Id: delete.c,v 1.203 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"

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.437 2009/05/27 10:31:29 drh Exp $
** $Id: expr.c,v 1.438 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
@ -40,7 +40,8 @@ char sqlite3ExprAffinity(Expr *pExpr){
}
#ifndef SQLITE_OMIT_CAST
if( op==TK_CAST ){
return sqlite3AffinityType(pExpr->zToken);
assert( !ExprHasProperty(pExpr, EP_IntValue) );
return sqlite3AffinityType(pExpr->u.zToken);
}
#endif
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER)
@ -388,6 +389,12 @@ int sqlite3SelectExprHeight(Select *p){
** parameter is ignored if pToken is NULL or if the token does not
** appear to be quoted. If the quotes were of the form "..." (double-quotes)
** then the EP_DblQuoted flag is set on the expression node.
**
** Special case: If op==TK_INTEGER and pToken points to a string that
** can be translated into a 32-bit integer, then the token is not
** stored in u.zToken. Instead, the integer values is written
** into u.iValue and the EP_IntValue flag is set. No extra storage
** is allocated to hold the integer text and the dequote flag is ignored.
*/
Expr *sqlite3ExprAlloc(
sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
@ -396,26 +403,33 @@ Expr *sqlite3ExprAlloc(
int dequote /* True to dequote */
){
Expr *pNew;
int nExtra;
int nExtra = 0;
int iValue;
if( pToken ){
nExtra = pToken->n+1;
}else{
nExtra = 0;
if( op!=TK_INTEGER || pToken->z==0
|| sqlite3GetInt32(pToken->z, &iValue)==0 ){
nExtra = pToken->n+1;
}
}
pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
if( pNew ){
pNew->op = (u8)op;
pNew->iAgg = -1;
if( pToken ){
int c;
pNew->zToken = (char*)&pNew[1];
memcpy(pNew->zToken, pToken->z, pToken->n);
pNew->zToken[pToken->n] = 0;
if( dequote && nExtra>=3
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
sqlite3Dequote(pNew->zToken);
if( c=='"' ) pNew->flags |= EP_DblQuoted;
if( nExtra==0 ){
pNew->flags |= EP_IntValue;
pNew->u.iValue = iValue;
}else{
int c;
pNew->u.zToken = (char*)&pNew[1];
memcpy(pNew->u.zToken, pToken->z, pToken->n);
pNew->u.zToken[pToken->n] = 0;
if( dequote && nExtra>=3
&& ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){
sqlite3Dequote(pNew->u.zToken);
if( c=='"' ) pNew->flags |= EP_DblQuoted;
}
}
}
#if SQLITE_MAX_EXPR_DEPTH>0
@ -550,7 +564,8 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
const char *z;
if( pExpr==0 ) return;
z = pExpr->zToken;
assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) );
z = pExpr->u.zToken;
assert( z!=0 );
assert( z[0]!=0 );
if( z[1]==0 ){
@ -584,7 +599,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
for(i=0; i<pParse->nVarExpr; i++){
Expr *pE = pParse->apVarExpr[i];
assert( pE!=0 );
if( memcmp(pE->zToken, z, n)==0 && pE->zToken[n]==0 ){
if( memcmp(pE->u.zToken, z, n)==0 && pE->u.zToken[n]==0 ){
pExpr->iTable = pE->iTable;
break;
}
@ -616,19 +631,13 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
** Substructure is deleted.
*/
void sqlite3ExprClear(sqlite3 *db, Expr *p){
assert( p!=0 );
if( !ExprHasAnyProperty(p, EP_TokenOnly) ){
if( ExprHasProperty(p, EP_Reduced) ){
/* Subtrees are part of the same memory allocation when EP_Reduced set */
if( p->pLeft ) sqlite3ExprClear(db, p->pLeft);
if( p->pRight ) sqlite3ExprClear(db, p->pRight);
}else{
/* Subtrees are separate allocations when EP_Reduced is clear */
sqlite3ExprDelete(db, p->pLeft);
sqlite3ExprDelete(db, p->pRight);
/* Sometimes the zToken is allocated separately */
if( p->flags2 & EP2_FreeToken ) sqlite3DbFree(db, p->zToken);
sqlite3ExprDelete(db, p->pLeft);
sqlite3ExprDelete(db, p->pRight);
if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){
sqlite3DbFree(db, p->u.zToken);
}
/* x.pSelect and x.pList are always separately allocated */
if( ExprHasProperty(p, EP_xIsSelect) ){
sqlite3SelectDelete(db, p->x.pSelect);
}else{
@ -643,7 +652,9 @@ void sqlite3ExprClear(sqlite3 *db, Expr *p){
void sqlite3ExprDelete(sqlite3 *db, Expr *p){
if( p==0 ) return;
sqlite3ExprClear(db, p);
sqlite3DbFree(db, p);
if( !ExprHasProperty(p, EP_Static) ){
sqlite3DbFree(db, p);
}
}
/*
@ -658,34 +669,67 @@ static int exprStructSize(Expr *p){
}
/*
** 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.
** The dupedExpr*Size() routines each return the number of bytes required
** to store a copy of an expression or expression tree. They differ in
** how much of the tree is measured.
**
** dupedExprStructSize() Size of only the Expr structure
** dupedExprNodeSize() Size of Expr + space for token
** dupedExprSize() Expr + token + subtree components
**
***************************************************************************
**
** The dupedExprStructSize() function returns two values OR-ed together:
** (1) the space required for a copy of the Expr structure only and
** (2) the EP_xxx flags that indicate what the structure size should be.
** The return values is always one of:
**
** EXPR_FULLSIZE
** EXPR_REDUCEDSIZE | EP_Reduced
** EXPR_TOKENONLYSIZE | EP_TokenOnly
**
** The size of the structure can be found by masking the return value
** of this routine with 0xfff. The flags can be found by masking the
** return value with EP_Reduced|EP_TokenOnly.
**
** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size
** (unreduced) Expr objects as they or originally constructed by the parser.
** During expression analysis, extra information is computed and moved into
** later parts of teh Expr object and that extra information might get chopped
** off if the expression is reduced. Note also that it does not work to
** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal
** to reduce a pristine expression tree from the parser. The implementation
** of dupedExprStructSize() contain multiple assert() statements that attempt
** to enforce this constraint.
*/
static int dupedExprStructSize(Expr *p, int flags){
int nSize;
assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */
if( 0==(flags&EXPRDUP_REDUCE) ){
nSize = EXPR_FULLSIZE;
}else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
nSize = EXPR_REDUCEDSIZE;
}else{
nSize = EXPR_TOKENONLYSIZE;
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(p, EP_FromJoin) );
assert( (p->flags2 & EP2_MallocedToken)==0 );
assert( (p->flags2 & EP2_Irreducible)==0 );
if( p->pLeft || p->pRight || p->pColl || p->x.pList ){
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
}else{
nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
}
}
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.zToken (if applicable)
** string buffers.
** This function returns the space in bytes required to store the copy
** of the Expr structure and a copy of the Expr.u.zToken string (if that
** string is defined.)
*/
static int dupedExprNodeSize(Expr *p, int flags){
int nByte = dupedExprStructSize(p, flags);
if( p->zToken ){
nByte += sqlite3Strlen30(p->zToken)+1;
int nByte = dupedExprStructSize(p, flags) & 0xfff;
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
nByte += sqlite3Strlen30(p->u.zToken)+1;
}
return ROUND8(nByte);
}
@ -696,7 +740,7 @@ static int dupedExprNodeSize(Expr *p, int flags){
** 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.zToken, if any.
** itself and the buffer referred to by Expr.u.zToken, if any.
**
** 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
@ -717,7 +761,7 @@ static int dupedExprSize(Expr *p, int flags){
/*
** 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->zToken
** to store the copy of expression p, the copies of p->u.zToken
** (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.
@ -727,12 +771,14 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
if( p ){
const int isReduced = (flags&EXPRDUP_REDUCE);
u8 *zAlloc;
u32 staticFlag = 0;
assert( pzBuffer==0 || isReduced );
/* Figure out where to write the new Expr structure. */
if( pzBuffer ){
zAlloc = *pzBuffer;
staticFlag = EP_Static;
}else{
zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags));
}
@ -742,10 +788,16 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
/* 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->zToken string (if any).
** by the copy of the p->u.zToken string (if any).
*/
const int nNewSize = dupedExprStructSize(p, flags);
const int nToken = (p->zToken ? sqlite3Strlen30(p->zToken) + 1 : 0);
const unsigned nStructSize = dupedExprStructSize(p, flags);
const int nNewSize = nStructSize & 0xfff;
int nToken;
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
nToken = sqlite3Strlen30(p->u.zToken) + 1;
}else{
nToken = 0;
}
if( isReduced ){
assert( ExprHasProperty(p, EP_Reduced)==0 );
memcpy(zAlloc, p, nNewSize);
@ -755,17 +807,15 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){
memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize);
}
/* Set the EP_Reduced and EP_TokenOnly flags appropriately. */
pNew->flags &= ~(EP_Reduced|EP_TokenOnly);
switch( nNewSize ){
case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break;
case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break;
}
/* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static);
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
pNew->flags |= staticFlag;
/* Copy the p->zToken string, if any. */
/* Copy the p->u.zToken string, if any. */
if( nToken ){
char *zToken = pNew->zToken = (char*)&zAlloc[nNewSize];
memcpy(zToken, p->zToken, nToken);
char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize];
memcpy(zToken, p->u.zToken, nToken);
}
if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
@ -1180,12 +1230,13 @@ int sqlite3ExprIsConstantOrFunction(Expr *p){
int sqlite3ExprIsInteger(Expr *p, int *pValue){
int rc = 0;
if( p->flags & EP_IntValue ){
*pValue = p->iTable;
*pValue = p->u.iValue;
return 1;
}
switch( p->op ){
case TK_INTEGER: {
rc = sqlite3GetInt32(p->zToken, pValue);
rc = sqlite3GetInt32(p->u.zToken, pValue);
assert( rc==0 );
break;
}
case TK_UPLUS: {
@ -1203,9 +1254,11 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
default: break;
}
if( rc ){
assert( ExprHasAnyProperty(p, EP_Reduced|EP_TokenOnly)
|| (p->flags2 & EP2_MallocedToken)==0 );
p->op = TK_INTEGER;
p->flags |= EP_IntValue;
p->iTable = *pValue;
p->u.iValue = *pValue;
}
return rc;
}
@ -1602,6 +1655,7 @@ void sqlite3CodeSubselect(
return;
}
pExpr->iColumn = dest.iParm;
ExprSetIrreducible(pExpr);
break;
}
}
@ -1662,12 +1716,12 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){
static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){
const char *z;
if( pExpr->flags & EP_IntValue ){
int i = pExpr->iTable;
int i = pExpr->u.iValue;
if( negFlag ) i = -i;
sqlite3VdbeAddOp2(v, OP_Integer, i, iMem);
}else if( (z = pExpr->zToken)!=0 ){
}else if( (z = pExpr->u.zToken)!=0 ){
int i;
int n = sqlite3Strlen30(pExpr->zToken);
int n = sqlite3Strlen30(pExpr->u.zToken);
assert( !sqlite3Isdigit(z[n]) );
if( sqlite3GetInt32(z, &i) ){
if( negFlag ) i = -i;
@ -2078,11 +2132,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
break;
}
case TK_FLOAT: {
codeReal(v, pExpr->zToken, 0, target);
assert( !ExprHasProperty(pExpr, EP_IntValue) );
codeReal(v, pExpr->u.zToken, 0, target);
break;
}
case TK_STRING: {
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->zToken, 0);
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0);
break;
}
case TK_NULL: {
@ -2094,9 +2150,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
int n;
const char *z;
char *zBlob;
assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' );
assert( pExpr->zToken[1]=='\'' );
z = &pExpr->zToken[2];
assert( !ExprHasProperty(pExpr, EP_IntValue) );
assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
assert( pExpr->u.zToken[1]=='\'' );
z = &pExpr->u.zToken[2];
n = sqlite3Strlen30(z) - 1;
assert( z[n]=='\'' );
zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
@ -2107,9 +2164,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
case TK_VARIABLE: {
int iPrior;
VdbeOp *pOp;
assert( pExpr->zToken!=0 );
assert( pExpr->zToken[0]!=0 );
if( pExpr->zToken[1]==0
assert( !ExprHasProperty(pExpr, EP_IntValue) );
assert( pExpr->u.zToken!=0 );
assert( pExpr->u.zToken[0]!=0 );
if( pExpr->u.zToken[1]==0
&& (iPrior = sqlite3VdbeCurrentAddr(v)-1)>=0
&& (pOp = sqlite3VdbeGetOp(v, iPrior))->opcode==OP_Variable
&& pOp->p1+pOp->p3==pExpr->iTable
@ -2124,8 +2182,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
pOp->p3++;
}else{
sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iTable, target, 1);
if( pExpr->zToken[1]!=0 ){
sqlite3VdbeChangeP4(v, -1, pExpr->zToken, 0);
if( pExpr->u.zToken[1]!=0 ){
sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, 0);
}
}
break;
@ -2143,7 +2201,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
/* Expressions of the form: CAST(pLeft AS token) */
int aff, to_op;
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
aff = sqlite3AffinityType(pExpr->zToken);
assert( !ExprHasProperty(pExpr, EP_IntValue) );
aff = sqlite3AffinityType(pExpr->u.zToken);
to_op = aff - SQLITE_AFF_TEXT + OP_ToText;
assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT );
assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE );
@ -2236,7 +2295,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
Expr *pLeft = pExpr->pLeft;
assert( pLeft );
if( pLeft->op==TK_FLOAT ){
codeReal(v, pLeft->zToken, 1, target);
assert( !ExprHasProperty(pExpr, EP_IntValue) );
codeReal(v, pLeft->u.zToken, 1, target);
}else if( pLeft->op==TK_INTEGER ){
codeInteger(v, pLeft, 1, target);
}else{
@ -2279,7 +2339,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
case TK_AGG_FUNCTION: {
AggInfo *pInfo = pExpr->pAggInfo;
if( pInfo==0 ){
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->zToken);
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
}else{
inReg = pInfo->aFunc[pExpr->iAgg].iMem;
}
@ -2306,7 +2367,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
pFarg = pExpr->x.pList;
}
nFarg = pFarg ? pFarg->nExpr : 0;
zId = pExpr->zToken;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId);
pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0);
assert( pDef!=0 );
@ -2589,8 +2651,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
assert( pExpr->affinity==OE_Rollback ||
pExpr->affinity == OE_Abort ||
pExpr->affinity == OE_Fail );
assert( !ExprHasProperty(pExpr, EP_IntValue) );
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0,
pExpr->zToken, 0);
pExpr->u.zToken, 0);
} else {
assert( pExpr->affinity == OE_Ignore );
sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0);
@ -3115,6 +3178,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
if( pA==0||pB==0 ){
return pB==pA;
}
assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) );
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
return 0;
}
@ -3135,9 +3200,13 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
}
if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0;
if( pA->op!=TK_COLUMN && pA->zToken ){
if( pB->zToken==0 ) return 0;
if( sqlite3StrICmp(pA->zToken,pB->zToken)!=0 ){
if( ExprHasProperty(pA, EP_IntValue) ){
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
return 0;
}
}else if( pA->op!=TK_COLUMN && pA->u.zToken ){
if( ExprHasProperty(pB, EP_IntValue) || pB->u.zToken==0 ) return 0;
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){
return 0;
}
}
@ -3204,6 +3273,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
struct SrcList_item *pItem = pSrcList->a;
for(i=0; i<pSrcList->nSrc; i++, pItem++){
struct AggInfo_col *pCol;
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
if( pExpr->iTable==pItem->iCursor ){
/* If we reach this point, it means that pExpr refers to a table
** that is in the FROM clause of the aggregate query.
@ -3252,6 +3322,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
** Convert the pExpr to be a TK_AGG_COLUMN referring to that
** pAggInfo->aCol[] entry.
*/
ExprSetIrreducible(pExpr);
pExpr->pAggInfo = pAggInfo;
pExpr->op = TK_AGG_COLUMN;
pExpr->iAgg = k;
@ -3284,8 +3355,9 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
pItem = &pAggInfo->aFunc[i];
pItem->pExpr = pExpr;
pItem->iMem = ++pParse->nMem;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pItem->pFunc = sqlite3FindFunction(pParse->db,
pExpr->zToken, sqlite3Strlen30(pExpr->zToken),
pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken),
pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0);
if( pExpr->flags & EP_Distinct ){
pItem->iDistinct = pParse->nTab++;
@ -3296,6 +3368,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
}
/* Make pExpr point to the appropriate pAggInfo->aFunc[] entry
*/
assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
ExprSetIrreducible(pExpr);
pExpr->iAgg = i;
pExpr->pAggInfo = pAggInfo;
return WRC_Prune;

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.235 2009/05/27 10:31:29 drh Exp $
** $Id: func.c,v 1.236 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
@ -1368,7 +1368,8 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
return 0;
}
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pDef = sqlite3FindFunction(db, pExpr->zToken, sqlite3Strlen30(pExpr->zToken),
pDef = sqlite3FindFunction(db, pExpr->u.zToken,
sqlite3Strlen30(pExpr->u.zToken),
2, SQLITE_UTF8, 0);
if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){
return 0;

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.277 2009/05/27 10:31:29 drh Exp $
** @(#) $Id: parse.y,v 1.278 2009/05/28 01:00:55 drh Exp $
*/
// All token codes are small integers with #defines that begin with "TK_"

View File

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.210 2009/05/27 10:31:29 drh Exp $
** $Id: pragma.c,v 1.211 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"

View File

@ -14,7 +14,7 @@
** resolve all identifiers by associating them with a particular
** table and column.
**
** $Id: resolve.c,v 1.23 2009/05/27 10:31:29 drh Exp $
** $Id: resolve.c,v 1.24 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
@ -72,15 +72,15 @@ static void resolveAlias(
}
pDup->iTable = pEList->a[iCol].iAlias;
}else{
char *zToken = pOrig->zToken;
pOrig->zToken = 0;
char *zToken = pOrig->u.zToken;
pOrig->u.zToken = 0;
pDup = sqlite3ExprDup(db, pOrig, 0);
pOrig->zToken = zToken;
pOrig->u.zToken = zToken;
if( pDup==0 ) return;
if( zToken ){
assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 );
pDup->flags2 |= EP2_FreeToken;
pDup->zToken = sqlite3DbStrDup(db, zToken);
pDup->flags2 |= EP2_MallocedToken;
pDup->u.zToken = sqlite3DbStrDup(db, zToken);
}
}
if( pExpr->flags & EP_ExpCollate ){
@ -138,10 +138,12 @@ static int lookupName(
assert( pNC ); /* the name context cannot be NULL. */
assert( zCol ); /* The Z in X.Y.Z cannot be NULL */
assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) );
/* Initialize the node to no-match */
pExpr->iTable = -1;
pExpr->pTab = 0;
ExprSetIrreducible(pExpr);
/* Start at the inner-most context and move outward until a match is found */
while( pNC && cnt==0 ){
@ -439,7 +441,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
/* A lone identifier is the name of a column.
*/
case TK_ID: {
lookupName(pParse, 0, 0, pExpr->zToken, pNC, pExpr);
lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr);
return WRC_Prune;
}
@ -456,13 +458,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
zDb = 0;
zTable = pExpr->pLeft->zToken;
zColumn = pRight->zToken;
zTable = pExpr->pLeft->u.zToken;
zColumn = pRight->u.zToken;
}else{
assert( pRight->op==TK_DOT );
zDb = pExpr->pLeft->zToken;
zTable = pRight->pLeft->zToken;
zColumn = pRight->pRight->zToken;
zDb = pExpr->pLeft->u.zToken;
zTable = pRight->pLeft->u.zToken;
zColumn = pRight->pRight->u.zToken;
}
lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr);
return WRC_Prune;
@ -484,7 +486,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
u8 enc = ENC(pParse->db); /* The database encoding */
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
zId = pExpr->zToken;
zId = pExpr->u.zToken;
nId = sqlite3Strlen30(zId);
pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
if( pDef==0 ){
@ -586,8 +588,8 @@ static int resolveAsName(
){
int i; /* Loop counter */
if( pE->op==TK_ID || (pE->op==TK_STRING && pE->zToken[0]!='\'') ){
char *zCol = pE->zToken;
if( pE->op==TK_ID || (pE->op==TK_STRING && pE->u.zToken[0]!='\'') ){
char *zCol = pE->u.zToken;
for(i=0; i<pEList->nExpr; i++){
char *zAs = pEList->a[i].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
@ -748,7 +750,7 @@ static int resolveCompoundOrderBy(
if( pE==0 ) return 1;
pE->pColl = pColl;
pE->flags |= EP_IntValue | flags;
pE->iTable = iCol;
pE->u.iValue = iCol;
pItem->iCol = (u16)iCol;
pItem->done = 1;
}else{

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.519 2009/05/27 10:31:29 drh Exp $
** $Id: select.c,v 1.520 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
@ -232,6 +232,8 @@ static void addWhereTerm(
pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0);
if( pE && isOuterJoin ){
ExprSetProperty(pE, EP_FromJoin);
assert( !ExprHasAnyProperty(pE, EP_TokenOnly|EP_Reduced) );
ExprSetIrreducible(pE);
pE->iRightJoinTable = iRightJoinTable;
}
*ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE);
@ -266,6 +268,8 @@ static void addWhereTerm(
static void setJoinExpr(Expr *p, int iTable){
while( p ){
ExprSetProperty(p, EP_FromJoin);
assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) );
ExprSetIrreducible(p);
p->iRightJoinTable = iTable;
setJoinExpr(p->pLeft, iTable);
p = p->pRight;
@ -1127,7 +1131,8 @@ static int selectColumnsFromExprList(
/* Get an appropriate name for the column
*/
p = pEList->a[i].pExpr;
assert( p->pRight==0 || p->pRight->zToken==0 || p->pRight->zToken[0]!=0 );
assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue)
|| p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 );
if( (zName = pEList->a[i].zName)!=0 ){
/* If the column contains an "AS <name>" phrase, use <name> as the name */
zName = sqlite3DbStrDup(db, zName);
@ -1143,7 +1148,8 @@ static int selectColumnsFromExprList(
zName = sqlite3MPrintf(db, "%s",
iCol>=0 ? pTab->aCol[iCol].zName : "rowid");
}else if( pColExpr->op==TK_ID ){
zName = sqlite3MPrintf(db, "%s", pColExpr->zToken);
assert( !ExprHasProperty(pColExpr, EP_IntValue) );
zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken);
}else{
/* Use the original text of the column expression as its name */
zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan);
@ -2048,7 +2054,7 @@ static int multiSelectOrderBy(
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
if( pNew==0 ) return SQLITE_NOMEM;
pNew->flags |= EP_IntValue;
pNew->iTable = i;
pNew->u.iValue = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
pOrderBy->a[nOrderBy++].iCol = (u16)i;
}
@ -2896,9 +2902,10 @@ static u8 minMaxQuery(Select *p){
pEList = pExpr->x.pList;
if( pEList==0 || pEList->nExpr!=1 ) return 0;
if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL;
if( sqlite3StrICmp(pExpr->zToken,"min")==0 ){
assert( !ExprHasProperty(pExpr, EP_IntValue) );
if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){
return WHERE_ORDERBY_MIN;
}else if( sqlite3StrICmp(pExpr->zToken,"max")==0 ){
}else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){
return WHERE_ORDERBY_MAX;
}
return WHERE_ORDERBY_NORMAL;
@ -3119,7 +3126,8 @@ static int selectExpander(Walker *pWalker, Select *p){
char *zTName; /* text of name of TABLE */
if( pE->op==TK_DOT ){
assert( pE->pLeft!=0 );
zTName = pE->pLeft->zToken;
assert( !ExprHasProperty(pE->pLeft, EP_IntValue) );
zTName = pE->pLeft->u.zToken;
}else{
zTName = 0;
}
@ -4143,8 +4151,8 @@ select_end:
** or from temporary "printf" statements inserted for debugging.
*/
void sqlite3PrintExpr(Expr *p){
if( p->zToken ){
sqlite3DebugPrintf("(%s", p->zToken);
if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){
sqlite3DebugPrintf("(%s", p->u.zToken);
}else{
sqlite3DebugPrintf("(%d", p->op);
}

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.876 2009/05/27 10:31:29 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.877 2009/05/28 01:00:55 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -1464,7 +1464,7 @@ struct AggInfo {
** help reduce memory requirements, sometimes an Expr object will be
** truncated. And to reduce the number of memory allocations, sometimes
** two or more Expr objects will be stored in a single memory allocation,
** together with Expr.token strings.
** together with Expr.zToken strings.
**
** If the EP_Reduced and EP_TokenOnly flags are set when
** an Expr object is truncated. When EP_Reduced is set, then all
@ -1477,7 +1477,10 @@ 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. EP_* See below */
char *zToken; /* Token value. Zero terminated and dequoted */
union {
char *zToken; /* Token value. Zero terminated and dequoted */
int iValue; /* Integer value if EP_IntValue */
} u;
/* 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
@ -1498,8 +1501,7 @@ struct Expr {
*********************************************************************/
int iTable; /* TK_COLUMN: cursor number of table holding column
** TK_REGISTER: register number
** EP_IntValue: integer value */
** TK_REGISTER: register number */
i16 iColumn; /* TK_COLUMN: column index. -1 for rowid */
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
@ -1525,7 +1527,7 @@ struct Expr {
#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
#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_IntValue 0x0800 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x1000 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */
@ -1535,7 +1537,20 @@ struct Expr {
/*
** The following are the meanings of bits in the Expr.flags2 field.
*/
#define EP2_FreeToken 0x0001 /* Need to call sqlite3DbFree() on Expr.zToken */
#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */
#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */
/*
** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible
** flag on an expression structure. This flag is used for VV&A only. The
** routine is implemented as a macro that only works when in debugging mode,
** so as not to burden production code.
*/
#ifdef SQLITE_DEBUG
# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible
#else
# define ExprSetIrreducible(X)
#endif
/*
** These macros can be used to test, set, or clear bits in the

View File

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.157 2009/05/27 10:31:29 drh Exp $
** $Id: tokenize.c,v 1.158 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>

View File

@ -10,7 +10,7 @@
*************************************************************************
**
**
** $Id: trigger.c,v 1.140 2009/05/27 10:31:29 drh Exp $
** $Id: trigger.c,v 1.141 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
@ -375,15 +375,15 @@ TriggerStep *sqlite3TriggerInsertStep(
pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName);
if( pTriggerStep ){
pTriggerStep->pSelect = pSelect;
pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
pTriggerStep->pIdList = pColumn;
pTriggerStep->pExprList = pEList;
pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
pTriggerStep->orconf = orconf;
}else{
sqlite3IdListDelete(db, pColumn);
sqlite3ExprListDelete(db, pEList);
sqlite3SelectDelete(db, pSelect);
}
sqlite3ExprListDelete(db, pEList);
sqlite3SelectDelete(db, pSelect);
return pTriggerStep;
}
@ -403,14 +403,13 @@ TriggerStep *sqlite3TriggerUpdateStep(
TriggerStep *pTriggerStep;
pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName);
if( pTriggerStep==0 ){
sqlite3ExprListDelete(db, pEList);
sqlite3ExprDelete(db, pWhere);
return 0;
if( pTriggerStep ){
pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE);
pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
pTriggerStep->orconf = orconf;
}
pTriggerStep->pExprList = pEList;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = orconf;
sqlite3ExprListDelete(db, pEList);
sqlite3ExprDelete(db, pWhere);
return pTriggerStep;
}
@ -427,13 +426,11 @@ TriggerStep *sqlite3TriggerDeleteStep(
TriggerStep *pTriggerStep;
pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName);
if( pTriggerStep==0 ){
sqlite3ExprDelete(db, pWhere);
return 0;
if( pTriggerStep ){
pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
pTriggerStep->orconf = OE_Default;
}
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = OE_Default;
sqlite3ExprDelete(db, pWhere);
return pTriggerStep;
}
@ -640,7 +637,6 @@ static SrcList *targetSrcList(
Parse *pParse, /* The parsing context */
TriggerStep *pStep /* The trigger containing the target token */
){
Token sDb; /* Dummy database name token */
int iDb; /* Index of the database to use */
SrcList *pSrc; /* SrcList to be returned */

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.201 2009/05/27 10:31:29 drh Exp $
** $Id: update.c,v 1.202 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"

View File

@ -14,7 +14,7 @@
** This file contains functions for allocating memory, comparing
** strings, and stuff like that.
**
** $Id: util.c,v 1.255 2009/05/27 10:31:29 drh Exp $
** $Id: util.c,v 1.256 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
#include <stdarg.h>

View File

@ -15,7 +15,7 @@
** only within the VDBE. Interface routines refer to a Mem using the
** name sqlite_value
**
** $Id: vdbemem.c,v 1.145 2009/05/27 10:31:29 drh Exp $
** $Id: vdbemem.c,v 1.146 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
#include "vdbeInt.h"
@ -974,10 +974,15 @@ int sqlite3ValueFromExpr(
op = pExpr->op;
if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
zVal = sqlite3DbStrDup(db, pExpr->zToken);
pVal = sqlite3ValueNew(db);
if( !zVal || !pVal ) goto no_mem;
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
if( pVal==0 ) goto no_mem;
if( ExprHasProperty(pExpr, EP_IntValue) ){
sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue);
}else{
zVal = sqlite3DbStrDup(db, pExpr->u.zToken);
if( zVal==0 ) goto no_mem;
sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
}
if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){
sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8);
}else{
@ -996,11 +1001,11 @@ int sqlite3ValueFromExpr(
#ifndef SQLITE_OMIT_BLOB_LITERAL
else if( op==TK_BLOB ){
int nVal;
assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' );
assert( pExpr->zToken[1]=='\'' );
assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
assert( pExpr->u.zToken[1]=='\'' );
pVal = sqlite3ValueNew(db);
if( !pVal ) goto no_mem;
zVal = &pExpr->zToken[2];
zVal = &pExpr->u.zToken[2];
nVal = sqlite3Strlen30(zVal)-1;
assert( zVal[nVal]=='\'' );
sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,

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.5 2009/05/27 10:31:29 drh Exp $
** $Id: walker.c,v 1.6 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>

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.398 2009/05/27 10:31:29 drh Exp $
** $Id: where.c,v 1.399 2009/05/28 01:00:55 drh Exp $
*/
#include "sqliteInt.h"
@ -658,7 +658,7 @@ static int isLikeOrGlob(
(pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){
return 0;
}
z = pRight->zToken;
z = pRight->u.zToken;
cnt = 0;
if( z ){
while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){
@ -691,7 +691,7 @@ static int isMatchOfColumn(
if( pExpr->op!=TK_FUNCTION ){
return 0;
}
if( sqlite3StrICmp(pExpr->zToken,"match")!=0 ){
if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){
return 0;
}
pList = pExpr->x.pList;
@ -1161,12 +1161,12 @@ static void exprAnalyze(
pLeft = pExpr->x.pList->a[1].pExpr;
pRight = pExpr->x.pList->a[0].pExpr;
pStr1 = sqlite3Expr(db, TK_STRING, pRight->zToken);
if( pStr1 ) pStr1->zToken[nPattern] = 0;
pStr1 = sqlite3Expr(db, TK_STRING, pRight->u.zToken);
if( pStr1 ) pStr1->u.zToken[nPattern] = 0;
pStr2 = sqlite3ExprDup(db, pStr1, 0);
if( !db->mallocFailed ){
u8 c, *pC;
pC = (u8*)&pStr2->zToken[nPattern-1];
pC = (u8*)&pStr2->u.zToken[nPattern-1];
c = *pC;
if( noCase ){
if( c=='@' ) isComplete = 0;

View File

@ -12,7 +12,7 @@
# focus of this script is testing the ATTACH and DETACH commands
# and related functionality.
#
# $Id: attach.test,v 1.50 2009/05/27 10:31:30 drh Exp $
# $Id: attach.test,v 1.51 2009/05/28 01:00:56 drh Exp $
#
set testdir [file dirname $argv0]

View File

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the SELECT statement.
#
# $Id: select1.test,v 1.69 2009/05/27 10:31:30 drh Exp $
# $Id: select1.test,v 1.70 2009/05/28 01:00:56 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl

View File

@ -10,7 +10,7 @@
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# $Id: tkt3508.test,v 1.4 2009/05/27 10:31:30 drh Exp $
# $Id: tkt3508.test,v 1.5 2009/05/28 01:00:56 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl