From ad3cab52fed9a86b8f8209c3dfca3ced8380ddfe Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 24 May 2002 02:04:32 +0000 Subject: [PATCH] Split the IdList structure into IdList and SrcList. SrcList is used to represent a FROM clause and IdList is used for everything else. This change allows SrcList to grow to support outer joins without burdening the other uses of IdList. (CVS 584) FossilOrigin-Name: a167b71d8c27e870bc3079c6132e483bffc83298 --- manifest | 32 ++++++++++----------- manifest.uuid | 2 +- src/build.c | 60 +++++++++++++++++++++++++++++++++++---- src/delete.c | 30 ++++++++++---------- src/expr.c | 45 ++++++++++++++++++++---------- src/insert.c | 6 ++-- src/parse.y | 61 +++++++++++++++++++++++----------------- src/select.c | 44 ++++++++++++++--------------- src/sqliteInt.h | 74 ++++++++++++++++++++++++++++++++++++------------- src/trigger.c | 8 +++--- src/update.c | 12 ++++---- src/vdbe.c | 8 +++--- src/where.c | 32 ++++++++++----------- 13 files changed, 263 insertions(+), 151 deletions(-) diff --git a/manifest b/manifest index 4e56023c5f..5d18095104 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Change\sthe\snames\sof\sthe\sPushList\sand\sPopList\sopcodes\sto\sListPush\sand\sListPop\nso\sthat\sthey\swill\sappear\stogether\swith\sthe\sother\sList\sopcodes\sin\sthe\ndocumentation.\s(CVS\s583) -D 2002-05-23T22:07:03 +C Split\sthe\sIdList\sstructure\sinto\sIdList\sand\sSrcList.\s\sSrcList\sis\sused\sto\nrepresent\sa\sFROM\sclause\sand\sIdList\sis\sused\sfor\severything\selse.\s\sThis\schange\nallows\sSrcList\sto\sgrow\sto\ssupport\souter\sjoins\swithout\sburdening\sthe\sother\nuses\sof\sIdList.\s(CVS\s584) +D 2002-05-24T02:04:33 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -20,28 +20,28 @@ F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6 F src/btree.c c01b404b9373ae1c0daf7d1f9211c72ead67638e F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3 -F src/build.c d88ad651bedecba69510d87d734040730305c528 -F src/delete.c 1dba1dd7fb7a477b44178f4990c20fa673ceb5be +F src/build.c 48bb306676b77711919adc3578655e3ebf2ac8f0 +F src/delete.c a2b098cbbf518e6b641847e26de85827793bc523 F src/encode.c 346b12b46148506c32038524b95c4631ab46d760 -F src/expr.c 535c2468cfa9a8d043c6bbe50488849943da237b +F src/expr.c 818a702ba93e444813b8935a7ab509f6e3352b49 F src/func.c a31dcba85bc2ecb9b752980289cf7e6cd0cafbce F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72 F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9 -F src/insert.c 5b6586bb5d8306280253829f42f5f98b1455e757 +F src/insert.c bbbd803da8b125ec5a5f881f4d559887eb922c57 F src/main.c 6e53c49a390fabd5fecce9e3b128c61c85208000 F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b F src/os.c 5ab8b6b4590d0c1ab8e96c67996c170e4462e0fc F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10 F src/pager.c ba5740104cc27b342cd43eebfdc44d60f64a3ded F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e -F src/parse.y 3f2f7334aa1460bf5b208f51b9e1f53747e552ff +F src/parse.y 8053fead169ad8345b5a2cfc39749b63995daffb F src/printf.c d8032ee18b860c812eeff596c9bebfdacb7930fd F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe -F src/select.c 1b623a7d826ec7c245bc542b665d61724da2a62d +F src/select.c c46f4e0784175f2a8ec9fde26b7b4f8090cab9cb F src/shell.c 1d22fe870ee852cfb975fd000dbe3973713d0a15 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in 0038faa6d642de06b91143ee65a131bd831d020b -F src/sqliteInt.h 7ef986dab669bf334bd90aac0cb73f8ef3254ca4 +F src/sqliteInt.h 02d9d16c3eea463ff9bcbd13426627cb79d6d190 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1 F src/test1.c 09d95048b66ce6dcd2bae90f443589043d7d631e @@ -49,12 +49,12 @@ F src/test2.c 669cc22781c6461a273416ec1a7414d25c081730 F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f F src/tokenize.c 5892a8eb8f0063718f5bec1a1b24f4c6029eba9b -F src/trigger.c a7990d424af58d809501a393f72c12d4b039eb63 -F src/update.c 1f8f7fde797bd607fe0afb4f96a6ad83c9e8ab7b +F src/trigger.c bf1a4f6653e482be0052bc9ade9261cf814c705b +F src/update.c f68375173bf5338cae3e97012708e10f206aedd9 F src/util.c 707c30f8c13cddace7c08556ac450c0b786660b3 -F src/vdbe.c 6c2eae8a1d03f41aa51e40772aebf581cf62d5b8 +F src/vdbe.c 46fd7cbefdb788195c978e5d2f480d86ea1416e5 F src/vdbe.h def669b9f2728589aabcb5db756429db02465c9a -F src/where.c 293985b6cf8391c3dcef9efcac4654884370513a +F src/where.c 1516eb1c06ca6d15cd5cf982ae974cf58e5431ed F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 F test/btree.test bf326f546a666617367a7033fa2c07451bd4f8e1 @@ -134,7 +134,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P 82b74a494ac7c751a13e67dcfa7fffb1b98ec808 -R 3e1a04e4d6e0a4fb68b8a11229bc1cc1 +P c53b0b9283c5c34def87d58b03fd979d03dc0890 +R 95dc28a2322a37ee9ed8c63d2402b526 U drh -Z 8e8caac647d0d1fcfa3e14c75f0d3c35 +Z 694384ea6b2e1a364fadbb314a03dd97 diff --git a/manifest.uuid b/manifest.uuid index b1fee1cf7c..3ca21d4886 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c53b0b9283c5c34def87d58b03fd979d03dc0890 \ No newline at end of file +a167b71d8c27e870bc3079c6132e483bffc83298 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 41c5eaccd6..76e22e1d68 100644 --- a/src/build.c +++ b/src/build.c @@ -25,7 +25,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.93 2002/05/22 21:27:03 drh Exp $ +** $Id: build.c,v 1.94 2002/05/24 02:04:33 drh Exp $ */ #include "sqliteInt.h" #include @@ -1535,30 +1535,80 @@ IdList *sqliteIdListAppend(IdList *pList, Token *pToken){ return pList; } +/* +** Append a new table name to the given SrcList. Create a new SrcList if +** need be. A new entry is created in the SrcList even if pToken is NULL. +** +** A new SrcList is returned, or NULL if malloc() fails. +*/ +SrcList *sqliteSrcListAppend(SrcList *pList, Token *pToken){ + if( pList==0 ){ + pList = sqliteMalloc( sizeof(IdList) ); + if( pList==0 ) return 0; + } + if( (pList->nSrc & 7)==0 ){ + struct SrcList_item *a; + a = sqliteRealloc(pList->a, (pList->nSrc+8)*sizeof(pList->a[0]) ); + if( a==0 ){ + sqliteSrcListDelete(pList); + return 0; + } + pList->a = a; + } + memset(&pList->a[pList->nSrc], 0, sizeof(pList->a[0])); + if( pToken ){ + char **pz = &pList->a[pList->nSrc].zName; + sqliteSetNString(pz, pToken->z, pToken->n, 0); + if( *pz==0 ){ + sqliteSrcListDelete(pList); + return 0; + }else{ + sqliteDequote(*pz); + } + } + pList->nSrc++; + return pList; +} + /* ** Add an alias to the last identifier on the given identifier list. */ -void sqliteIdListAddAlias(IdList *pList, Token *pToken){ - if( pList && pList->nId>0 ){ - int i = pList->nId - 1; +void sqliteSrcListAddAlias(SrcList *pList, Token *pToken){ + if( pList && pList->nSrc>0 ){ + int i = pList->nSrc - 1; sqliteSetNString(&pList->a[i].zAlias, pToken->z, pToken->n, 0); sqliteDequote(pList->a[i].zAlias); } } /* -** Delete an entire IdList. +** Delete an IdList. */ void sqliteIdListDelete(IdList *pList){ int i; if( pList==0 ) return; for(i=0; inId; i++){ sqliteFree(pList->a[i].zName); + } + sqliteFree(pList->a); + sqliteFree(pList); +} + +/* +** Delete an entire SrcList including all its substructure. +*/ +void sqliteSrcListDelete(SrcList *pList){ + int i; + if( pList==0 ) return; + for(i=0; inSrc; i++){ + sqliteFree(pList->a[i].zName); sqliteFree(pList->a[i].zAlias); if( pList->a[i].pTab && pList->a[i].pTab->isTransient ){ sqliteDeleteTable(0, pList->a[i].pTab); } sqliteSelectDelete(pList->a[i].pSelect); + sqliteExprDelete(pList->a[i].pOn); + sqliteIdListDelete(pList->a[i].pUsing); } sqliteFree(pList->a); sqliteFree(pList); diff --git a/src/delete.c b/src/delete.c index 7ed2dca445..f48a528ebc 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle DELETE FROM statements. ** -** $Id: delete.c,v 1.35 2002/05/23 12:50:18 drh Exp $ +** $Id: delete.c,v 1.36 2002/05/24 02:04:33 drh Exp $ */ #include "sqliteInt.h" @@ -43,22 +43,22 @@ Table *sqliteTableNameToTable(Parse *pParse, const char *zTab){ /* ** Given a table name, check to make sure the table exists, is writable -** and is not a view. If everything is OK, construct an IdList holding -** the table and return a pointer to the IdList. The calling function -** is responsible for freeing the IdList when it has finished with it. +** and is not a view. If everything is OK, construct an SrcList holding +** the table and return a pointer to the SrcList. The calling function +** is responsible for freeing the SrcList when it has finished with it. ** If there is an error, leave a message on pParse->zErrMsg and return ** NULL. */ -IdList *sqliteTableTokenToIdList(Parse *pParse, Token *pTableName){ +SrcList *sqliteTableTokenToSrcList(Parse *pParse, Token *pTableName){ Table *pTab; - IdList *pTabList; + SrcList *pTabList; - pTabList = sqliteIdListAppend(0, pTableName); + pTabList = sqliteSrcListAppend(0, pTableName); if( pTabList==0 ) return 0; - assert( pTabList->nId==1 ); + assert( pTabList->nSrc==1 ); pTab = sqliteTableNameToTable(pParse, pTabList->a[0].zName); if( pTab==0 ){ - sqliteIdListDelete(pTabList); + sqliteSrcListDelete(pTabList); return 0; } pTabList->a[0].pTab = pTab; @@ -76,7 +76,7 @@ void sqliteDeleteFrom( Vdbe *v; /* The virtual database engine */ Table *pTab; /* The table from which records will be deleted */ char *zTab; /* Name of the table from which we are deleting */ - IdList *pTabList; /* An ID list holding pTab and nothing else */ + SrcList *pTabList; /* A fake FROM clause holding just pTab */ int end, addr; /* A couple addresses of generated code */ int i; /* Loop counter */ WhereInfo *pWInfo; /* Information about the WHERE clause */ @@ -116,13 +116,13 @@ void sqliteDeleteFrom( } /* Locate the table which we want to delete. This table has to be - ** put in an IdList structure because some of the subroutines we + ** put in an SrcList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect - ** an IdList* parameter instead of just a Table* parameter. + ** an SrcList* parameter instead of just a Table* parameter. */ - pTabList = sqliteTableTokenToIdList(pParse, pTableName); + pTabList = sqliteTableTokenToSrcList(pParse, pTableName); if( pTabList==0 ) goto delete_from_cleanup; - assert( pTabList->nId==1 ); + assert( pTabList->nSrc==1 ); pTab = pTabList->a[0].pTab; assert( pTab->pSelect==0 ); /* This table is not a view */ @@ -301,7 +301,7 @@ void sqliteDeleteFrom( } delete_from_cleanup: - sqliteIdListDelete(pTabList); + sqliteSrcListDelete(pTabList); sqliteExprDelete(pWhere); return; } diff --git a/src/expr.c b/src/expr.c index 54b7334245..94aa06df50 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.62 2002/05/23 02:09:04 drh Exp $ +** $Id: expr.c,v 1.63 2002/05/24 02:04:33 drh Exp $ */ #include "sqliteInt.h" @@ -155,11 +155,11 @@ void sqliteSelectMoveStrings(Select *pSelect, int offset){ ** string space that is allocated separately from the expression tree ** itself. These routines do NOT duplicate that string space. ** -** The expression list and ID list return by sqliteExprListDup() and -** sqliteIdListDup() can not be further expanded by subsequent calls -** to sqliteExprListAppend() or sqliteIdListAppend(). +** The expression list, ID, and source lists return by sqliteExprListDup(), +** sqliteIdListDup(), and sqliteSrcListDup() can not be further expanded +** by subsequent calls to sqlite*ListAppend() routines. ** -** Any tables that the ID list might point to are not duplicated. +** Any tables that the SrcList might point to are not duplicated. */ Expr *sqliteExprDup(Expr *p){ Expr *pNew; @@ -196,6 +196,26 @@ ExprList *sqliteExprListDup(ExprList *p){ } return pNew; } +SrcList *sqliteSrcListDup(SrcList *p){ + SrcList *pNew; + int i; + if( p==0 ) return 0; + pNew = sqliteMalloc( sizeof(*pNew) ); + if( pNew==0 ) return 0; + pNew->nSrc = p->nSrc; + pNew->a = sqliteMalloc( p->nSrc*sizeof(p->a[0]) ); + if( pNew->a==0 ) return 0; + for(i=0; inSrc; i++){ + pNew->a[i].zName = sqliteStrDup(p->a[i].zName); + pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias); + pNew->a[i].jointype = p->a[i].jointype; + pNew->a[i].pTab = 0; + pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect); + pNew->a[i].pOn = sqliteExprDup(p->a[i].pOn); + pNew->a[i].pUsing = sqliteIdListDup(p->a[i].pUsing); + } + return pNew; +} IdList *sqliteIdListDup(IdList *p){ IdList *pNew; int i; @@ -207,10 +227,7 @@ IdList *sqliteIdListDup(IdList *p){ if( pNew->a==0 ) return 0; for(i=0; inId; i++){ pNew->a[i].zName = sqliteStrDup(p->a[i].zName); - pNew->a[i].zAlias = sqliteStrDup(p->a[i].zAlias); pNew->a[i].idx = p->a[i].idx; - pNew->a[i].pTab = 0; - pNew->a[i].pSelect = sqliteSelectDup(p->a[i].pSelect); } return pNew; } @@ -221,7 +238,7 @@ Select *sqliteSelectDup(Select *p){ if( pNew==0 ) return 0; pNew->isDistinct = p->isDistinct; pNew->pEList = sqliteExprListDup(p->pEList); - pNew->pSrc = sqliteIdListDup(p->pSrc); + pNew->pSrc = sqliteSrcListDup(p->pSrc); pNew->pWhere = sqliteExprDup(p->pWhere); pNew->pGroupBy = sqliteExprListDup(p->pGroupBy); pNew->pHaving = sqliteExprDup(p->pHaving); @@ -362,12 +379,12 @@ static int sqliteIsRowid(const char *z){ int sqliteExprResolveIds( Parse *pParse, /* The parser context */ int base, /* VDBE cursor number for first entry in pTabList */ - IdList *pTabList, /* List of tables used to resolve column names */ + SrcList *pTabList, /* List of tables used to resolve column names */ ExprList *pEList, /* List of expressions used to resolve "AS" */ Expr *pExpr /* The expression to be analyzed. */ ){ if( pExpr==0 || pTabList==0 ) return 0; - assert( base+pTabList->nId<=pParse->nTab ); + assert( base+pTabList->nSrc<=pParse->nTab ); switch( pExpr->op ){ /* Double-quoted strings (ex: "abc") are used as identifiers if ** possible. Otherwise they remain as strings. Single-quoted @@ -395,7 +412,7 @@ int sqliteExprResolveIds( z = sqliteStrNDup(pExpr->token.z, pExpr->token.n); sqliteDequote(z); if( z==0 ) return 1; - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ int j; Table *pTab = pTabList->a[i].pTab; if( pTab==0 ) continue; @@ -430,7 +447,7 @@ int sqliteExprResolveIds( if( cnt==0 && sqliteIsRowid(z) ){ pExpr->iColumn = -1; pExpr->iTable = base; - cnt = 1 + (pTabList->nId>1); + cnt = 1 + (pTabList->nSrc>1); pExpr->op = TK_COLUMN; } sqliteFree(z); @@ -470,7 +487,7 @@ int sqliteExprResolveIds( sqliteDequote(zLeft); sqliteDequote(zRight); pExpr->iTable = -1; - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ int j; char *zTab; Table *pTab = pTabList->a[i].pTab; diff --git a/src/insert.c b/src/insert.c index c248aaa92f..53c3e76960 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.57 2002/05/21 12:56:43 drh Exp $ +** $Id: insert.c,v 1.58 2002/05/24 02:04:33 drh Exp $ */ #include "sqliteInt.h" @@ -117,12 +117,12 @@ void sqliteInsert( assert( pSelect->pEList ); nColumn = pSelect->pEList->nExpr; }else{ - IdList dummy; + SrcList dummy; assert( pList!=0 ); srcTab = -1; assert( pList ); nColumn = pList->nExpr; - dummy.nId = 0; + dummy.nSrc = 0; for(i=0; ia[i].pExpr) ){ goto insert_cleanup; diff --git a/src/parse.y b/src/parse.y index ead734512f..4ef3dd3d8a 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.67 2002/05/23 00:30:31 drh Exp $ +** @(#) $Id: parse.y,v 1.68 2002/05/24 02:04:33 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -30,14 +30,24 @@ #include "parse.h" /* -** A structure for holding two integers +** An instance of this structure holds information about the +** LIMIT clause of a SELECT statement. */ -struct twoint { int a,b; }; +struct LimitVal { + int limit; /* The LIMIT value. -1 if there is no limit */ + int offset; /* The OFFSET. 0 if there is none */ +}; /* -** A structure for holding an integer and an IdList +** An instance of the following structure describes the event of a +** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT, +** TK_DELETE, or TK_INSTEAD. If the event is of the form +** +** UPDATE ON (a,b,c) +** +** Then the "b" IdList records the list "a,b,c". */ -struct int_idlist { int a; IdList * b; }; +struct TrigEvent { int a; IdList * b; }; } // These are extra tokens used by the lexer but never seen by the @@ -240,7 +250,7 @@ multiselect_op(A) ::= INTERSECT. {A = TK_INTERSECT;} multiselect_op(A) ::= EXCEPT. {A = TK_EXCEPT;} oneselect(A) ::= SELECT distinct(D) selcollist(W) from(X) where_opt(Y) groupby_opt(P) having_opt(Q) orderby_opt(Z) limit_opt(L). { - A = sqliteSelectNew(W,X,Y,P,Q,Z,D,L.a,L.b); + A = sqliteSelectNew(W,X,Y,P,Q,Z,D,L.limit,L.offset); } // The "distinct" nonterminal is true (1) if the DISTINCT keyword is @@ -276,38 +286,38 @@ as ::= . as ::= AS. -%type seltablist {IdList*} -%destructor seltablist {sqliteIdListDelete($$);} -%type stl_prefix {IdList*} -%destructor stl_prefix {sqliteIdListDelete($$);} -%type from {IdList*} -%destructor from {sqliteIdListDelete($$);} +%type seltablist {SrcList*} +%destructor seltablist {sqliteSrcListDelete($$);} +%type stl_prefix {SrcList*} +%destructor stl_prefix {sqliteSrcListDelete($$);} +%type from {SrcList*} +%destructor from {sqliteSrcListDelete($$);} from(A) ::= . {A = sqliteMalloc(sizeof(*A));} from(A) ::= FROM seltablist(X). {A = X;} stl_prefix(A) ::= seltablist(X) COMMA. {A = X;} stl_prefix(A) ::= . {A = 0;} -seltablist(A) ::= stl_prefix(X) ids(Y). {A = sqliteIdListAppend(X,&Y);} +seltablist(A) ::= stl_prefix(X) ids(Y). {A = sqliteSrcListAppend(X,&Y);} seltablist(A) ::= stl_prefix(X) ids(Y) as ids(Z). { - A = sqliteIdListAppend(X,&Y); - sqliteIdListAddAlias(A,&Z); + A = sqliteSrcListAppend(X,&Y); + sqliteSrcListAddAlias(A,&Z); } seltablist(A) ::= stl_prefix(X) LP select(S) RP. { - A = sqliteIdListAppend(X,0); - A->a[A->nId-1].pSelect = S; + A = sqliteSrcListAppend(X,0); + A->a[A->nSrc-1].pSelect = S; if( S->pOrderBy ){ sqliteExprListDelete(S->pOrderBy); S->pOrderBy = 0; } } seltablist(A) ::= stl_prefix(X) LP select(S) RP as ids(Z). { - A = sqliteIdListAppend(X,0); - A->a[A->nId-1].pSelect = S; + A = sqliteSrcListAppend(X,0); + A->a[A->nSrc-1].pSelect = S; if( S->pOrderBy ){ sqliteExprListDelete(S->pOrderBy); S->pOrderBy = 0; } - sqliteIdListAddAlias(A,&Z); + sqliteSrcListAddAlias(A,&Z); } %type orderby_opt {ExprList*} @@ -345,11 +355,11 @@ groupby_opt(A) ::= GROUP BY exprlist(X). {A = X;} having_opt(A) ::= . {A = 0;} having_opt(A) ::= HAVING expr(X). {A = X;} -%type limit_opt {struct twoint} -limit_opt(A) ::= . {A.a = -1; A.b = 0;} -limit_opt(A) ::= LIMIT INTEGER(X). {A.a = atoi(X.z); A.b = 0;} +%type limit_opt {struct LimitVal} +limit_opt(A) ::= . {A.limit = -1; A.offset = 0;} +limit_opt(A) ::= LIMIT INTEGER(X). {A.limit = atoi(X.z); A.offset = 0;} limit_opt(A) ::= LIMIT INTEGER(X) limit_sep INTEGER(Y). - {A.a = atoi(X.z); A.b = atoi(Y.z);} + {A.limit = atoi(X.z); A.offset = atoi(Y.z);} limit_sep ::= OFFSET. limit_sep ::= COMMA. @@ -655,7 +665,8 @@ trigger_time(A) ::= AFTER. { A = TK_AFTER; } trigger_time(A) ::= INSTEAD OF. { A = TK_INSTEAD;} trigger_time(A) ::= . { A = TK_BEFORE; } -%type trigger_event {struct int_idlist} +%type trigger_event {struct TrigEvent} +%destructor trigger_event {sqliteIdListDelete($$.b);} trigger_event(A) ::= DELETE. { A.a = TK_DELETE; A.b = 0; } trigger_event(A) ::= INSERT. { A.a = TK_INSERT; A.b = 0; } trigger_event(A) ::= UPDATE. { A.a = TK_UPDATE; A.b = 0;} diff --git a/src/select.c b/src/select.c index 7038809ce9..d6cbff5a00 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.81 2002/05/08 11:54:15 drh Exp $ +** $Id: select.c,v 1.82 2002/05/24 02:04:33 drh Exp $ */ #include "sqliteInt.h" @@ -22,7 +22,7 @@ */ Select *sqliteSelectNew( ExprList *pEList, /* which columns to include in the result */ - IdList *pSrc, /* the FROM clause -- which tables to scan */ + SrcList *pSrc, /* the FROM clause -- which tables to scan */ Expr *pWhere, /* the WHERE clause */ ExprList *pGroupBy, /* the GROUP BY clause */ Expr *pHaving, /* the HAVING clause */ @@ -35,7 +35,7 @@ Select *sqliteSelectNew( pNew = sqliteMalloc( sizeof(*pNew) ); if( pNew==0 ){ sqliteExprListDelete(pEList); - sqliteIdListDelete(pSrc); + sqliteSrcListDelete(pSrc); sqliteExprDelete(pWhere); sqliteExprListDelete(pGroupBy); sqliteExprDelete(pHaving); @@ -61,7 +61,7 @@ Select *sqliteSelectNew( void sqliteSelectDelete(Select *p){ if( p==0 ) return; sqliteExprListDelete(p->pEList); - sqliteIdListDelete(p->pSrc); + sqliteSrcListDelete(p->pSrc); sqliteExprDelete(p->pWhere); sqliteExprListDelete(p->pGroupBy); sqliteExprDelete(p->pHaving); @@ -234,7 +234,7 @@ static void generateSortTail(Vdbe *v, int nColumn){ static void generateColumnNames( Parse *pParse, /* Parser context */ int base, /* VDBE cursor corresponding to first entry in pTabList */ - IdList *pTabList, /* List of tables */ + SrcList *pTabList, /* List of tables */ ExprList *pEList /* Expressions defining the result set */ ){ Vdbe *v = pParse->pVdbe; @@ -265,7 +265,7 @@ static void generateColumnNames( if( iCol<0 ) iCol = pTab->iPKey; assert( iCol==-1 || (iCol>=0 && iColnCol) ); zCol = iCol<0 ? "_ROWID_" : pTab->aCol[iCol].zName; - if( pTabList->nId>1 || showFullNames ){ + if( pTabList->nSrc>1 || showFullNames ){ char *zName = 0; char *zTab; @@ -352,7 +352,7 @@ Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ /* ** For the given SELECT statement, do two things. ** -** (1) Fill in the pTabList->a[].pTab fields in the IdList that +** (1) Fill in the pTabList->a[].pTab fields in the SrcList that ** defines the set of tables that should be scanned. ** ** (2) Scan the list of columns in the result set (pEList) looking @@ -365,7 +365,7 @@ Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){ */ static int fillInColumnList(Parse *pParse, Select *p){ int i, j, k, rc; - IdList *pTabList; + SrcList *pTabList; ExprList *pEList; Table *pTab; @@ -375,7 +375,7 @@ static int fillInColumnList(Parse *pParse, Select *p){ /* Look up every table in the table list. */ - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ if( pTabList->a[i].pTab ){ /* This routine has run before! No need to continue */ return 0; @@ -454,7 +454,7 @@ static int fillInColumnList(Parse *pParse, Select *p){ }else{ pName = 0; } - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ Table *pTab = pTabList->a[i].pTab; char *zTabName = pTabList->a[i].zAlias; if( zTabName==0 || zTabName[0]==0 ){ @@ -511,10 +511,10 @@ static int fillInColumnList(Parse *pParse, Select *p){ */ void sqliteSelectUnbind(Select *p){ int i; - IdList *pSrc = p->pSrc; + SrcList *pSrc = p->pSrc; Table *pTab; if( p==0 ) return; - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ if( (pTab = pSrc->a[i].pTab)!=0 ){ if( pTab->isTransient ){ sqliteDeleteTable(0, pTab); @@ -932,8 +932,8 @@ substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){ */ int flattenSubquery(Select *p, int iFrom, int isAgg, int subqueryIsAgg){ Select *pSub; /* The inner query or "subquery" */ - IdList *pSrc; /* The FROM clause of the outer query */ - IdList *pSubSrc; /* The FROM clause of the subquery */ + SrcList *pSrc; /* The FROM clause of the outer query */ + SrcList *pSubSrc; /* The FROM clause of the subquery */ ExprList *pList; /* The result set of the outer query */ int i; int iParent, iSub; @@ -943,15 +943,15 @@ int flattenSubquery(Select *p, int iFrom, int isAgg, int subqueryIsAgg){ */ if( p==0 ) return 0; pSrc = p->pSrc; - assert( pSrc && iFrom>=0 && iFromnId ); + assert( pSrc && iFrom>=0 && iFromnSrc ); pSub = pSrc->a[iFrom].pSelect; assert( pSub!=0 ); if( isAgg && subqueryIsAgg ) return 0; - if( subqueryIsAgg && pSrc->nId>1 ) return 0; + if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; pSubSrc = pSub->pSrc; assert( pSubSrc ); - if( pSubSrc->nId!=1 ) return 0; - if( pSub->isDistinct && pSrc->nId>1 ) return 0; + if( pSubSrc->nSrc!=1 ) return 0; + if( pSub->isDistinct && pSrc->nSrc>1 ) return 0; if( pSub->isDistinct && isAgg ) return 0; if( p->isDistinct && subqueryIsAgg ) return 0; @@ -1059,7 +1059,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ ** zero if it is not. */ if( p->pGroupBy || p->pHaving || p->pWhere ) return 0; - if( p->pSrc->nId!=1 ) return 0; + if( p->pSrc->nSrc!=1 ) return 0; if( p->pEList->nExpr!=1 ) return 0; pExpr = p->pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; @@ -1184,7 +1184,7 @@ int sqliteSelect( Vdbe *v; int isAgg = 0; /* True for select lists like "count(*)" */ ExprList *pEList; /* List of columns to extract. */ - IdList *pTabList; /* List of tables to select from */ + SrcList *pTabList; /* List of tables to select from */ Expr *pWhere; /* The WHERE clause. May be NULL */ ExprList *pOrderBy; /* The ORDER BY clause. May be NULL */ ExprList *pGroupBy; /* The GROUP BY clause. May be NULL */ @@ -1216,7 +1216,7 @@ int sqliteSelect( ** FROM clause be consecutive. */ base = p->base = pParse->nTab; - pParse->nTab += pTabList->nId; + pParse->nTab += pTabList->nSrc; /* ** Do not even attempt to generate any code if we have already seen @@ -1351,7 +1351,7 @@ int sqliteSelect( /* Generate code for all sub-queries in the FROM clause */ - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ if( pTabList->a[i].pSelect==0 ) continue; sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable, base+i, p, i, &isAgg); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3a66ff7ce9..04cb42dad3 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.112 2002/05/21 13:18:26 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.113 2002/05/24 02:04:33 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -139,6 +139,7 @@ typedef struct ExprList ExprList; typedef struct Parse Parse; typedef struct Token Token; typedef struct IdList IdList; +typedef struct SrcList SrcList; typedef struct WhereInfo WhereInfo; typedef struct WhereLevel WhereLevel; typedef struct Select Select; @@ -400,7 +401,7 @@ struct Expr { ** name. An expr/name combination can be used in several ways, such ** as the list of "expr AS ID" fields following a "SELECT" or in the ** list of "ID = expr" items in an UPDATE. A list of expressions can -** also be used as the argument to a function, in which case the azName +** also be used as the argument to a function, in which case the a.zName ** field is not used. */ struct ExprList { @@ -415,16 +416,43 @@ struct ExprList { }; /* -** A list of identifiers. +** An instance of this structure can hold a simple list of identifiers, +** such as the list "a,b,c" in the following statements: +** +** INSERT INTO t(a,b,c) VALUES ...; +** CREATE INDEX idx ON t(a,b,c); +** CREATE TRIGGER trig BEFORE UPDATE ON t(a,b,c) ...; +** +** The IdList.a.idx field is used when the IdList represents the list of +** column names after a table name in an INSERT statement. In the statement +** +** INSERT INTO t(a,b,c) ... +** +** If "a" is the k-th column of table "t", then IdList.a[0].idx==k. */ struct IdList { int nId; /* Number of identifiers on the list */ struct IdList_item { - char *zName; /* Text of the identifier. */ - char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ + char *zName; /* Name of the identifier */ int idx; /* Index in some Table.aCol[] of a column named zName */ + } *a; +}; + +/* +** The following structure describes the FROM clause of a SELECT statement. +** Each table or subquery in the FROM clause is a separate element of +** the SrcList.a[] array. +*/ +struct SrcList { + int nSrc; /* Number of tables or subqueries in the FROM clause */ + struct SrcList_item { + char *zName; /* Name of the table */ + char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ + int jointype; /* Type of join between this table and the next */ + Expr *pOn; /* The ON clause of a join */ + IdList *pUsing; /* The USING clause of a join */ } *a; /* One entry for each identifier on the list */ }; @@ -453,7 +481,7 @@ struct WhereLevel { */ struct WhereInfo { Parse *pParse; - IdList *pTabList; /* List of tables in the join */ + SrcList *pTabList; /* List of tables in the join */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int base; /* Index of first Open opcode */ @@ -478,7 +506,7 @@ struct WhereInfo { struct Select { int isDistinct; /* True if the DISTINCT keyword is present */ ExprList *pEList; /* The fields of the result */ - IdList *pSrc; /* The FROM clause */ + SrcList *pSrc; /* The FROM clause */ Expr *pWhere; /* The WHERE clause */ ExprList *pGroupBy; /* The GROUP BY clause */ Expr *pHaving; /* The HAVING clause */ @@ -569,16 +597,17 @@ struct Parse { * 1. In the "trigHash" hash table (part of the sqlite* that represents the * database). This allows Trigger structures to be retrieved by name. * 2. All triggers associated with a single table form a linked list, using the - * pNext member of struct Trigger. A pointer to the first element of the linked - * list is stored as the "pTrigger" member of the associated struct Table. + * pNext member of struct Trigger. A pointer to the first element of the + * linked list is stored as the "pTrigger" member of the associated + * struct Table. * * The "strings" member of struct Trigger contains a pointer to the memory * referenced by the various Token structures referenced indirectly by the * "pWhen", "pColumns" and "step_list" members. (ie. the memory allocated for * use in conjunction with the sqliteExprMoveStrings() etc. interface). * - * The "step_list" member points to the first element of a linked list containing - * the SQL statements specified as the trigger program. + * The "step_list" member points to the first element of a linked list + * containing the SQL statements specified as the trigger program. * * When a trigger is initially created, the "isCommit" member is set to FALSE. * When a transaction is rolled back, any Trigger structures with "isCommit" set @@ -587,8 +616,8 @@ struct Parse { * Trigger structures for which it is FALSE. * * When a trigger is dropped, using the sqliteDropTrigger() interfaced, it is - * removed from the trigHash hash table and added to the trigDrop hash table. If - * the transaction is rolled back, the trigger is re-added into the trigHash + * removed from the trigHash hash table and added to the trigDrop hash table. + * If the transaction is rolled back, the trigger is re-added into the trigHash * hash table (and hence the database schema). If the transaction is commited, * then the Trigger structure is deleted permanently. */ @@ -629,7 +658,8 @@ struct Trigger { * pExprList -> If this is an INSERT INTO ... VALUES ... statement, then * this stores values to be inserted. Otherwise NULL. * pIdList -> If this is an INSERT INTO ... () VALUES ... - * statement, then this stores the column-names to be inserted into. + * statement, then this stores the column-names to be + * inserted into. * * (op == TK_DELETE) * target -> A token holding the name of the table to delete from. @@ -641,7 +671,8 @@ struct Trigger { * pWhere -> The WHERE clause of the UPDATE statement if one is specified. * Otherwise NULL. * pExprList -> A list of the columns to update and the expressions to update - * them to. See sqliteUpdate() documentation of "pChanges" argument. + * them to. See sqliteUpdate() documentation of "pChanges" + * argument. * */ struct TriggerStep { @@ -755,20 +786,22 @@ void sqliteDropTable(Parse*, Token*, int); void sqliteDeleteTable(sqlite*, Table*); void sqliteInsert(Parse*, Token*, ExprList*, Select*, IdList*, int); IdList *sqliteIdListAppend(IdList*, Token*); -void sqliteIdListAddAlias(IdList*, Token*); +SrcList *sqliteSrcListAppend(SrcList*, Token*); +void sqliteSrcListAddAlias(SrcList*, Token*); void sqliteIdListDelete(IdList*); +void sqliteSrcListDelete(SrcList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*); -Select *sqliteSelectNew(ExprList*,IdList*,Expr*,ExprList*,Expr*,ExprList*, +Select *sqliteSelectNew(ExprList*,SrcList*,Expr*,ExprList*,Expr*,ExprList*, int,int,int); void sqliteSelectDelete(Select*); void sqliteSelectUnbind(Select*); Table *sqliteTableNameToTable(Parse*, const char*); -IdList *sqliteTableTokenToIdList(Parse*, Token*); +SrcList *sqliteTableTokenToSrcList(Parse*, Token*); void sqliteDeleteFrom(Parse*, Token*, Expr*); void sqliteUpdate(Parse*, Token*, ExprList*, Expr*, int); -WhereInfo *sqliteWhereBegin(Parse*, int, IdList*, Expr*, int); +WhereInfo *sqliteWhereBegin(Parse*, int, SrcList*, Expr*, int); void sqliteWhereEnd(WhereInfo*); void sqliteExprCode(Parse*, Expr*); void sqliteExprIfTrue(Parse*, Expr*, int); @@ -784,7 +817,7 @@ char *sqliteTableNameFromToken(Token*); int sqliteExprCheck(Parse*, Expr*, int, int*); int sqliteExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); -int sqliteExprResolveIds(Parse*, int, IdList*, ExprList*, Expr*); +int sqliteExprResolveIds(Parse*, int, SrcList*, ExprList*, Expr*); int sqliteExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqliteGetVdbe(Parse*); int sqliteRandomByte(void); @@ -805,6 +838,7 @@ void sqliteExprListMoveStrings(ExprList*, int); void sqliteSelectMoveStrings(Select*, int); Expr *sqliteExprDup(Expr*); ExprList *sqliteExprListDup(ExprList*); +SrcList *sqliteSrcListDup(SrcList*); IdList *sqliteIdListDup(IdList*); Select *sqliteSelectDup(Select*); FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int); diff --git a/src/trigger.c b/src/trigger.c index aedf08873b..d53dff219f 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -571,10 +571,10 @@ int sqliteCodeRowTrigger( if( fire_this && (pTriggerStack = sqliteMalloc(sizeof(TriggerStack)))!=0 ){ int endTrigger; - IdList dummyTablist; + SrcList dummyTablist; Expr * whenExpr; - dummyTablist.nId = 0; + dummyTablist.nSrc = 0; dummyTablist.a = 0; /* Push an entry on to the trigger stack */ @@ -645,7 +645,7 @@ void sqliteViewTriggers( theSelect.isDistinct = 0; theSelect.pEList = sqliteExprListAppend(0, sqliteExpr(TK_ALL, 0, 0, 0), 0); - theSelect.pSrc = sqliteIdListAppend(0, &tblNameToken); + theSelect.pSrc = sqliteSrcListAppend(0, &tblNameToken); theSelect.pWhere = pWhere; pWhere = 0; theSelect.pGroupBy = 0; theSelect.pHaving = 0; @@ -750,7 +750,7 @@ trigger_cleanup: sqliteExprListDelete(pChanges); sqliteExprDelete(pWhere); sqliteExprListDelete(theSelect.pEList); - sqliteIdListDelete(theSelect.pSrc); + sqliteSrcListDelete(theSelect.pSrc); sqliteExprDelete(theSelect.pWhere); return; } diff --git a/src/update.c b/src/update.c index 177cdd6f34..f4f5c66cec 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.42 2002/05/23 22:07:03 drh Exp $ +** $Id: update.c,v 1.43 2002/05/24 02:04:34 drh Exp $ */ #include "sqliteInt.h" @@ -28,7 +28,7 @@ void sqliteUpdate( ){ int i, j; /* Loop counters */ Table *pTab; /* The table to be updated */ - IdList *pTabList = 0; /* List containing only pTab */ + SrcList *pTabList = 0; /* Fake FROM clause containing only pTab */ int addr; /* VDBE instruction address of the start of the loop */ WhereInfo *pWInfo; /* Information about the WHERE clause */ Vdbe *v; /* The virtual database engine */ @@ -80,11 +80,11 @@ void sqliteUpdate( } /* Locate the table which we want to update. This table has to be - ** put in an IdList structure because some of the subroutines we + ** put in an SrcList structure because some of the subroutines we ** will be calling are designed to work with multiple tables and expect - ** an IdList* parameter instead of just a Table* parameter. + ** an SrcList* parameter instead of just a Table* parameter. */ - pTabList = sqliteTableTokenToIdList(pParse, pTableName); + pTabList = sqliteTableTokenToSrcList(pParse, pTableName); if( pTabList==0 ) goto update_cleanup; pTab = pTabList->a[0].pTab; assert( pTab->pSelect==0 ); /* This table is not a VIEW */ @@ -391,7 +391,7 @@ void sqliteUpdate( update_cleanup: sqliteFree(apIdx); sqliteFree(aXRef); - sqliteIdListDelete(pTabList); + sqliteSrcListDelete(pTabList); sqliteExprListDelete(pChanges); sqliteExprDelete(pWhere); return; diff --git a/src/vdbe.c b/src/vdbe.c index 3fcd443c16..d12e55687c 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.146 2002/05/23 22:07:03 drh Exp $ +** $Id: vdbe.c,v 1.147 2002/05/24 02:04:34 drh Exp $ */ #include "sqliteInt.h" #include @@ -233,7 +233,7 @@ struct Vdbe { char **zStack; /* Text or binary values of the stack */ char **azColName; /* Becomes the 4th parameter to callbacks */ int nCursor; /* Number of slots in aCsr[] */ - Cursor *aCsr; /* On element of this array for each open cursor */ + Cursor *aCsr; /* One element of this array for each open cursor */ Keylist *pList; /* A list of ROWIDs */ Sorter *pSort; /* A linked list of objects to be sorted */ FILE *pFile; /* At most one open file handler */ @@ -3823,7 +3823,7 @@ case OP_ListReset: { /* Opcode: ListPush * * * ** -** Save the current Vdbe list such that it can be restored by a PopList +** Save the current Vdbe list such that it can be restored by a ListPop ** opcode. The list is empty after this is executed. */ case OP_ListPush: { @@ -3838,7 +3838,7 @@ case OP_ListPush: { /* Opcode: ListPop * * * ** -** Restore the Vdbe list to the state it was in when PushList was last +** Restore the Vdbe list to the state it was in when ListPush was last ** executed. */ case OP_ListPop: { diff --git a/src/where.c b/src/where.c index 00ddfe74fb..2082d6aec2 100644 --- a/src/where.c +++ b/src/where.c @@ -13,7 +13,7 @@ ** the WHERE clause of SQL statements. Also found here are subroutines ** to generate VDBE code to evaluate expressions. ** -** $Id: where.c,v 1.45 2002/05/21 13:18:26 drh Exp $ +** $Id: where.c,v 1.46 2002/05/24 02:04:34 drh Exp $ */ #include "sqliteInt.h" @@ -159,7 +159,7 @@ static void exprAnalyze(int base, ExprInfo *pInfo){ WhereInfo *sqliteWhereBegin( Parse *pParse, /* The parser context */ int base, /* VDBE cursor index for left-most table in pTabList */ - IdList *pTabList, /* A list of all tables */ + SrcList *pTabList, /* A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ int pushKey /* If TRUE, leave the table key on the stack */ ){ @@ -178,12 +178,12 @@ WhereInfo *sqliteWhereBegin( ExprInfo aExpr[50]; /* The WHERE clause is divided into these expressions */ /* Allocate space for aOrder[] and aiMem[]. */ - aOrder = sqliteMalloc( sizeof(int) * pTabList->nId ); + aOrder = sqliteMalloc( sizeof(int) * pTabList->nSrc ); /* Allocate and initialize the WhereInfo structure that will become the ** return value. */ - pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nId*sizeof(WhereLevel) ); + pWInfo = sqliteMalloc( sizeof(WhereInfo) + pTabList->nSrc*sizeof(WhereLevel)); if( sqlite_malloc_failed ){ sqliteFree(aOrder); sqliteFree(pWInfo); @@ -239,20 +239,20 @@ WhereInfo *sqliteWhereBegin( /* Figure out a good nesting order for the tables. aOrder[0] will ** be the index in pTabList of the outermost table. aOrder[1] will - ** be the first nested loop and so on. aOrder[pTabList->nId-1] will + ** be the first nested loop and so on. aOrder[pTabList->nSrc-1] will ** be the innermost loop. ** ** Someday we will put in a good algorithm here to reorder the loops ** for an effiecient query. But for now, just use whatever order the ** tables appear in in the pTabList. */ - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ aOrder[i] = i; } /* Figure out what index to use (if any) for each nested loop. ** Make pWInfo->a[i].pIdx point to the index to use for the i-th nested - ** loop where i==0 is the outer loop and i==pTabList->nId-1 is the inner + ** loop where i==0 is the outer loop and i==pTabList->nSrc-1 is the inner ** loop. ** ** If terms exist that use the ROWID of any table, then set the @@ -267,7 +267,7 @@ WhereInfo *sqliteWhereBegin( ** to the limit of 32 bits in an integer bitmask. */ loopMask = 0; - for(i=0; inId && inSrc && ia[idx].pTab; @@ -426,7 +426,7 @@ WhereInfo *sqliteWhereBegin( /* Open all tables in the pTabList and all indices used by those tables. */ - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ int openOp; Table *pTab; @@ -449,7 +449,7 @@ WhereInfo *sqliteWhereBegin( /* Generate the code to do the search */ loopMask = 0; - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ int j, k; int idx = aOrder[i]; Index *pIdx; @@ -473,7 +473,7 @@ WhereInfo *sqliteWhereBegin( brk = pLevel->brk = sqliteVdbeMakeLabel(v); cont = pLevel->cont = brk; sqliteVdbeAddOp(v, OP_MustBeInt, 0, brk); - if( i==pTabList->nId-1 && pushKey ){ + if( i==pTabList->nSrc-1 && pushKey ){ /* Note: The OP_Dup below will cause the recno to be left on the ** stack if the record does not exists and the OP_NotExists jump is ** taken. This violates a general rule of the VDBE that you should @@ -536,7 +536,7 @@ WhereInfo *sqliteWhereBegin( start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0); sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk); sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0); - if( i==pTabList->nId-1 && pushKey ){ + if( i==pTabList->nSrc-1 && pushKey ){ haveKey = 1; }else{ sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0); @@ -759,7 +759,7 @@ WhereInfo *sqliteWhereBegin( sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk); } sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0); - if( i==pTabList->nId-1 && pushKey ){ + if( i==pTabList->nSrc-1 && pushKey ){ haveKey = 1; }else{ sqliteVdbeAddOp(v, OP_MoveTo, base+idx, 0); @@ -805,9 +805,9 @@ void sqliteWhereEnd(WhereInfo *pWInfo){ int i; int base = pWInfo->base; WhereLevel *pLevel; - IdList *pTabList = pWInfo->pTabList; + SrcList *pTabList = pWInfo->pTabList; - for(i=pTabList->nId-1; i>=0; i--){ + for(i=pTabList->nSrc-1; i>=0; i--){ pLevel = &pWInfo->a[i]; sqliteVdbeResolveLabel(v, pLevel->cont); if( pLevel->op!=OP_Noop ){ @@ -816,7 +816,7 @@ void sqliteWhereEnd(WhereInfo *pWInfo){ sqliteVdbeResolveLabel(v, pLevel->brk); } sqliteVdbeResolveLabel(v, pWInfo->iBreak); - for(i=0; inId; i++){ + for(i=0; inSrc; i++){ if( pTabList->a[i].pTab->isTransient ) continue; pLevel = &pWInfo->a[i]; sqliteVdbeAddOp(v, OP_Close, base+i, 0);