-C Ensure\sthat\sthe\swindow\sfunction\srewrite\sdoes\snot\sleave\sthe\sparse\stree\nin\san\sinvalid\sstate\sthat\smight\scause\sproblems\sdownstream\sbefore\sthe\nerror\sis\srecognized\sand\sunwinds\sthe\sstack.\s\sAlso\stake\ssteps\ssuch\sthat\nan\sinvalid\sparse\stree\sdoes\snot\scause\sproblems\seven\sif\sit\sgoes\s\nunrecognized.\s\s\n[forum:/forumpost/398e9d5aa9|Forum\spost\s398e9d5aa9].
-D 2021-11-07T23:33:01.004
+C Add\sassert()s\sthat\sverify\sthat\scursor\snumbers\son\ssubqueries\sare\salways\ngreater\sthan\souter\scursor\snumbers.\s\sExcept,\sthis\sis\snot\salways\strue\sin\sthe\npresence\sof\squery\sflattening.\s\sWe\smight\sneed\sto\srelax\sthat\sconstraint.\nThis\sbranch\swill\sprobably\sbecome\sa\sdead-end.\s\sFor\snow\sit\sis\ssaved\sfor\nreference.
+D 2021-11-08T16:38:08.067
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
F src/delete.c 0c151975fa99560767d7747f9b60543d0093d9f8b89f13d2d6058e9c83ad19e7
-F src/expr.c f96439c1c58fd8dbb42254ad45339b8487f7e2c0b59eb43b4652ffe458205bdb
+F src/expr.c 2d06e9ee4faec27601bd536042fda2ec260c5b142cc3abfd2f6751eb8c605977
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 187b67af20c5795953a592832c5d985e4313fe503ebd8f95e3e9e9ad5a730bb5
F src/func.c 1cfb09d7ffca81238eccefdb0293e1f5b7cfebbd1816dfad5ec6024742a7496b
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c ae65c88f5d0d4bc0052b203773d407efa2387c2bd6b202f87178006c7bb8632c
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c b4b3a0f32e70d93efbb357783846853dbd8b266ec0d7035aa0a245c33eecf72d
+F src/select.c ac16dee42af39682bfd67539e127698838a2542601ee2eb6ce49196ba7265c74
F src/shell.c.in f8854bcb0d14707d661732698d5210d7f01694000c46e8014b323ad18f575be6
F src/sqlite.h.in 5cd209ac7dc4180f0e19292846f40440b8488015849ca0110c70b906b57d68f0
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8ff2fd2c166150b2e48639f5e506fb44e29f1a3f65031710b9e89d1c126ac839
-F src/sqliteInt.h c280f33f023f87864fa660925f5d5cb49ccfc82eea223fec4e37177c86a26b5a
+F src/sqliteInt.h ab88d3f3d86dae6b2029539938fe742884811c9e64307d71ed0b991657262b38
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 0dc963f63aebc42960125f96865029f16b3f6867126aab350da12882505edb82
-R 3e89981cb2c8fbf47d84ee585ebde83e
+P 0f9fc6b6073365d5159cd71e7fe08f8dadbc7b42abd324361e809502f4359155
+R 4f74580fd63b4e2f86db712346f3cd4a
+T *branch * well-ordered-cursors
+T *sym-well-ordered-cursors *
+T -sym-trunk *
U drh
-Z 073fd661537b1ec07fc06b4c7f20875c
+Z ae9ad8ca1734f1ca1c3ca8135a32d6c4
-0f9fc6b6073365d5159cd71e7fe08f8dadbc7b42abd324361e809502f4359155
\ No newline at end of file
+6f4369666efb8eed84c3d60118baaf35d733ea906df983aeca2b0a475a6298a3
\ No newline at end of file
return !w.eCode;
}
+#ifdef SQLITE_DEBUG
+/* Walker callback for recursion in sqlite3WellOrderedCursors()
+*/
+static int wellOrderedCursors(Walker *pWalker, Select *pSel){
+ pWalker->eCode =
+ sqlite3WellOrderedCursors(pWalker->pParse, pSel, pWalker->u.iCur);
+ return WRC_Abort;
+}
+
+/*
+** Check every cursor number in pSelect. Return false (zero) if any cursor
+** number is less than or equal to iLowerBound. Return true if all cursors
+** number are greater than iLowerBound.
+**
+** Repeat this check recursively on subqueries.
+**
+** Use this routine inside of an assert() to verify that every subquery
+** cursor number is greater than the cursor numbers in all outer queries.
+** This cursor number invariant is required for scoping of aggregate
+** functions. tag-20211108
+*/
+int sqlite3WellOrderedCursors(Parse *pParse, Select *pSelect, int iLowerBound){
+ Walker w;
+ SrcList *pSrc;
+ int i;
+ int mx = 0;
+
+ pSrc = pSelect->pSrc;
+ assert( pSrc!=0 );
+ for(i=0; i<pSrc->nSrc; i++){
+ int iThis = pSrc->a[i].iCursor;
+ if( iThis<=iLowerBound ){
+ SELECTTRACE(1,pParse,pSelect,
+ ("Cursor %d less than cursor %d in outer query\n",iThis, iLowerBound));
+ return 0;
+ }
+ if( iThis>mx ){
+ mx = iThis;
+ }
+ }
+ memset(&w, 0, sizeof(w));
+ w.pParse = pParse;
+ w.xSelectCallback = wellOrderedCursors;
+ w.xExprCallback = sqlite3ExprWalkNoop;
+ w.eCode = 1;
+ w.u.iCur = mx;
+ while( w.eCode ){
+ sqlite3WalkSelectExpr(&w, pSelect);
+ if( w.eCode==0 ) break;
+ sqlite3WalkSelectFrom(&w, pSelect);
+ pSelect = pSelect->pPrior;
+ if( pSelect==0 ) break;
+ }
+ return w.eCode;
+}
+#endif /* SQLITE_DEBUG */
/*
** An instance of the following structure is used by the tree walker
}else if( pExpr->iTable<p->iSrcInner ){
/* In a well-formed parse tree (no name resolution errors),
** TK_COLUMN nodes with smaller Expr.iTable values are in an
- ** outer context. Those are the only ones to count as "other" */
+ ** outer context. Those are the only ones to count as "other"
+ ** See tag-20211108
+ */
p->nOther++;
}
}
sqlite3TreeViewSelect(0, p, 0);
}
#endif
+ assert( sqlite3WellOrderedCursors(pParse, p, -1) );
#endif /* SQLITE_OMIT_WINDOWFUNC */
pTabList = p->pSrc;
isAgg = (p->selFlags & SF_Aggregate)!=0;
if( pParse->nErr ) goto select_end;
/* This subquery can be absorbed into its parent. */
i = -1;
+ assert( sqlite3WellOrderedCursors(pParse, p, -1) );
}
pTabList = p->pSrc;
if( db->mallocFailed ) goto select_end;
void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
+#ifdef SQLITE_DEBUG
+int sqlite3WellOrderedCursors(Parse*,Select*,int);
+#endif
int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
Vdbe *sqlite3GetVdbe(Parse*);
#ifndef SQLITE_UNTESTABLE