- C Remove\san\sALWAYS()\sthat\sis\sno\slonger\salways\strue.
- D 2014-01-15T20:10:15.729
-C Fix\sharmless\scompiler\swarning\sin\sLEMON.
-D 2014-01-14T10:17:21.693
++C Merge\strunk\schanges.\s\sFix\sa\spossible\sNULL-pointer\sdeference\sin\sWITH\sclause\nname\sresolution.
++D 2014-01-16T04:37:13.145
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_unix.c 3a4dcb554d3c915075766162f28c3fd4cdb75968
- F src/os_win.c 16eac0961603182ffc10c02b39fe830126538e07
+ F src/os_win.c 1b21af72c5fa6f9e519a5fcab33e80d182b1aedb
F src/pager.c efa923693e958696eee69b205a20bfbc402c8480
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
-F src/parse.y 3c5384533a8bfce5abd256cc9cb2c38bec05ad61
+F src/parse.y 824eeb752c026b551bda2b66163889d7664b42e4
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 57fee9a9a617218f5037afbbe49b09da65bde56b
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
F src/printf.c 85d07756e45d7496d19439dcae3e6e9e0090f269
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
-F src/resolve.c 7eda9097b29fcf3d2b42fdc17d1de672134e09b6
+F src/resolve.c ae278d8ce037883323f677e78c241f64289f12ec
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
- F src/select.c ab437f252415754963b1adfa501120d5364da3ef
- F src/shell.c a3541193d5fce37e91dad8ef46a9505aa7c9b344
-F src/select.c 996d8b88603edbd478aaa70b75d535a3ddea933d
++F src/select.c c9af659146dd1fe924fbfb14a7477f6b2b90f03b
+ F src/shell.c 9f3bc02a658b8f61d2cbe60cfc482f660c1c6c48
F src/sqlite.h.in d94a8b89522f526ba711182ee161e06f8669bcc9
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
- P 3908e2ea2e7e5f466cbbbffdc27e0fe8dc9751ac
- R ec33026d9a1a4e4ae1384253da1cbe65
-P 1e131094b522103a0829f72193b067b04e42ce82
-R fe4a4148cfbc4d588ee2679597656da4
-U mistachkin
-Z d589f5ec7c09b4ac8c97497c20166016
++P c95823cd451f7721174393817a801403647467db f61a70589ac7e05008a362bd9d5b7bde5d07a758
++R 8a379a80b7992f91c6a6d54869d6bc5d
+U drh
- Z d40f91394b02fb8b902b74395abcc185
++Z 69979a1b738527f03c61f40bf3b0d3cb
return WRC_Continue;
}
- if( pItem->zDatabase==0 ){
- const char *zName = pItem->zName;
+#ifndef SQLITE_OMIT_CTE
+/*
+** Argument pWith (which may be NULL) points to a linked list of nested
+** WITH contexts, from inner to outermost. If the table identified by
+** FROM clause element pItem is really a common-table-expression (CTE)
+** then return a pointer to the CTE definition for that table. Otherwise
+** return NULL.
+*/
+static struct Cte *searchWith(With *pWith, struct SrcList_item *pItem){
++ const char *zName;
++ if( pItem->zDatabase==0 && (zName = pItem->zName)!=0 ){
+ With *p;
+ for(p=pWith; p; p=p->pOuter){
+ int i;
+ for(i=0; i<p->nCte; i++){
+ if( sqlite3StrICmp(zName, p->a[i].zName)==0 ){
+ return &p->a[i];
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+/* The code generator maintains a stack of active WITH clauses
+** with the inner-most WITH clause being at the top of the stack.
+**
+** These routines push and pull WITH clauses on the stack.
+*/
+void sqlite3WithPush(Parse *pParse, With *pWith){
+ if( pWith ){
+ pWith->pOuter = pParse->pWith;
+ pParse->pWith = pWith;
+ }
+}
+
+/*
+** If argument pCte is not NULL, check if it is already a part of the
+** stack of CTEs stored by the parser. If so, this indicates an illegal
+** recursive reference in a CTE, set of mutually recursive CTEs. Store
+** an error in the parser and return SQLITE_ERROR if this is the case.
+**
+** Otherwise, if pCte is not already part of the stack of CTEs stored
+** in the parser, push it onto the stop of that stack.
+*/
+static int ctePush(Parse *pParse, struct Cte *pCte){
+ if( pCte ){
+ struct Cte *p;
+ for(p=pParse->pCte; p; p=p->pOuterCte){
+ if( p==pCte ){
+ sqlite3ErrorMsg(
+ pParse, "illegal recursive defininition in cte: %s", pCte->zName
+ );
+ return SQLITE_ERROR;
+ }
+ }
+
+ pCte->pOuterCte = pParse->pCte;
+ pParse->pCte = pCte;
+ }
+ return SQLITE_OK;
+}
+/*
+** If argument pCte is not NULL, it must be a pointer to the CTE currently
+** on top of the stack of CTEs stored in the parser. Remove it from that
+** stack.
+*/
+static void ctePop(Parse *pParse, struct Cte *pCte){
+ if( pCte ){
+ assert( pParse->pCte==pCte );
+ pParse->pCte = pCte->pOuterCte;
+ }
+}
+
+/*
+** This function checks if argument pFrom refers to a CTE declared by
+** a WITH clause on the stack currently maintained by the parser. And,
+** if currently processing a CTE expression, if it is a recursive
+** reference to the current CTE.
+**
+** If pFrom falls into either of the two categories above, pFrom->pTab
+** and other fields are populated accordingly. The caller should check
+** (pFrom->pTab!=0) to determine whether or not a successful match
+** was found.
+**
+** Whether or not a match is found, SQLITE_OK is returned if no error
+** occurs. If an error does occur, an error message is stored in the
+** parser and some error code other than SQLITE_OK returned.
+*/
+static int withExpand(
+ Walker *pWalker,
+ struct SrcList_item *pFrom
+){
+ Table *pTab;
+ Parse *pParse = pWalker->pParse;
+ sqlite3 *db = pParse->db;
+ struct Cte *pCte;
+
+ assert( pFrom->pTab==0 );
+
+ pCte = searchWith(pParse->pWith, pFrom);
+ if( pCte==0 ){
+ /* no-op */
+ }else if( pCte==pParse->pCte && (pTab = pCte->pTab) ){
+ /* This is the recursive part of a recursive CTE */
+ assert( pFrom->pTab==0 && pFrom->isRecursive==0 && pFrom->pSelect==0 );
+ pFrom->pTab = pTab;
+ pFrom->isRecursive = 1;
+ pTab->nRef++;
+ }else{
+ ExprList *pEList;
+ Select *pSel;
+ Select *pLeft; /* Left-most SELECT statement */
+ int bRecursive;
+
+ pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
+ if( pTab==0 ) return WRC_Abort;
+ pTab->nRef = 1;
+ pTab->zName = sqlite3MPrintf(db, "%s", pCte->zName);
+ pTab->iPKey = -1;
+ pTab->nRowEst = 1048576;
+ pTab->tabFlags |= TF_Ephemeral;
+ pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
+ if( db->mallocFailed ) return SQLITE_NOMEM;
+ assert( pFrom->pSelect );
+
+ if( ctePush(pParse, pCte) ) return WRC_Abort;
+ pSel = pFrom->pSelect;
+ bRecursive = (pSel->op==TK_ALL || pSel->op==TK_UNION);
+ if( bRecursive ){
+ assert( pSel->pPrior );
+ sqlite3WalkSelect(pWalker, pSel->pPrior);
+ }else{
+ sqlite3WalkSelect(pWalker, pSel);
+ }
+
+ for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
+ pEList = pLeft->pEList;
+ if( pCte->pCols ){
+ if( pEList->nExpr!=pCte->pCols->nExpr ){
+ sqlite3ErrorMsg(pParse, "cte \"%s\" returns %d values for %d columns",
+ pCte->zName, pEList->nExpr, pCte->pCols->nExpr
+ );
+ return WRC_Abort;
+ }
+ pEList = pCte->pCols;
+ }
+
+ selectColumnsFromExprList(pParse, pEList, &pTab->nCol, &pTab->aCol);
+
+ if( bRecursive ){
+ int nRef = pTab->nRef;
+ pCte->pTab = pTab;
+ sqlite3WalkSelect(pWalker, pSel);
+ pCte->pTab = 0;
+ if( pTab->nRef > nRef){
+ pSel->pRecurse = pTab;
+ assert( pTab->tnum==0 );
+ }
+ }
+
+ ctePop(pParse, pCte);
+ }
+
+ return SQLITE_OK;
+}
+#endif
+
/*
** This routine is a Walker callback for "expanding" a SELECT statement.
** "Expanding" means to do the following: