-C Fix\sa\spart\sof\sthe\sheader\scomment\sfor\sflattenSubquery().
-D 2020-12-17T17:17:12.113
+C When\sflattening\sUNION\sALL\ssubqueries\sinto\sa\sjoin\squery,\sensure\sthat\sseparate\scursor\snumbers\sare\sused\sfor\seach\ssegment\sof\sthe\snewly\sflattened\squery.
+D 2020-12-18T16:13:39.603
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 1948a92ca9eab776632816b97e57c61d933474a78aad4f4ef835c916a83dbb1c
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c a9c7607d8fe60e17df2b8839abad2e333b306e40e0b20e53747b3dcf600832ec
+F src/select.c 7282b1a0fc81ce3c61c988b228b63b45a5521254033370d1ad6bf3366b5c2788
F src/shell.c.in e9f674ee4ec6c345679e8a5b16c869c6c59eb1540dd98ac69e4736ecddce0090
F src/sqlite.h.in 5b7593bb0f3658e682a9fcd1cd8fcedf244ec45ca93d645055a53172f55eb783
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F test/types.test bf816ce73c7dfcfe26b700c19f97ef4050d194ff
F test/types2.test 1aeb81976841a91eef292723649b5c4fe3bc3cac
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
-F test/unionall.test d2a6956fa3f01e0566b2cb81b2eea6e10be67c54ca1b1623685c6dbff8bd465b
-F test/unionallfault.test 8dcc3f680ace498d8d3110ddcfdaa6a3d8aa1843bc7c266b990f13815ee6d7fe
+F test/unionall.test 6676ff915eced719e7010149d758ba85665c0aef6a782e693b6fb5e83fb4e4e1
+F test/unionallfault.test 652bfbb630e6c43135965dc1e8f0a9a791da83aec885d626a632fe1909c56f73
F test/unionvtab.test e1704ab1b4c1bb3ffc9da4681f8e85a0b909fd80b937984fc94b27415ac8e5a4
F test/unionvtabfault.test e8759f3d14fb938ce9657e2342db34aeac0fb9bc1692b0d1ebb0069630151d06
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 5d6dc29d5f81738b07e4fee652fb2343fc409c2545f2f4667e8ee82d1a75f721
-R 856c8700228bcdbf610d5cdb34881db9
+P dc0937ce9d5569e3409b2b036a9f15b896125f4eb2eec30e3f0bbe4a92bcd0ad
+R d7f9897a9bbc548d53ddd8cd562a8b6a
U dan
-Z d0c22076b1f40da6b64269c66f6c133c
+Z aa626afff11dd6191a903497d2bb6cf2
}
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
+/*
+** Assign new cursor numbers to each of the items in pSrc. For each
+** new cursor number assigned, set an entry in the aCsrMap[] array
+** to map the old cursor number to the new:
+**
+** aCsrMap[iOld] = iNew;
+**
+** The array is guaranteed by the caller to be large enough for all
+** existing cursor numbers in pSrc.
+**
+** If pSrc contains any sub-selects, call this routine recursively
+** on the FROM clause of each such sub-select, with iExcept set to -1.
+*/
+static void srclistRenumberCursors(
+ Parse *pParse, /* Parse context */
+ int *aCsrMap, /* Array to store cursor mappings in */
+ SrcList *pSrc, /* FROM clause to renumber */
+ int iExcept /* FROM clause item to skip */
+){
+ int i;
+ struct SrcList_item *pItem;
+ for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
+ if( i!=iExcept ){
+ int iNew = pParse->nTab++;
+ aCsrMap[pItem->iCursor] = iNew;
+ pItem->iCursor = iNew;
+ if( pItem->pSelect ){
+ srclistRenumberCursors(pParse, aCsrMap, pItem->pSelect->pSrc, -1);
+ }
+ }
+ }
+}
+
+/*
+** Expression walker callback used by renumberCursors() to update
+** Expr objects to match newly assigned cursor numbers.
+*/
+static int renumberCursorsCb(Walker *pWalker, Expr *pExpr){
+ int *aCsrMap = pWalker->u.aiCol;
+ if( pExpr->op==TK_COLUMN && aCsrMap[pExpr->iTable] ){
+ pExpr->iTable = aCsrMap[pExpr->iTable];
+ }
+ return WRC_Continue;
+}
+
+/*
+** Assign a new cursor number to each cursor in the FROM clause (Select.pSrc)
+** of the SELECT statement passed as the second argument, and to each
+** cursor in the FROM clause of any FROM clause sub-selects, recursively.
+** Except, do not assign a new cursor number to the iExcept'th element in
+** the FROM clause of (*p). Update all expressions and other references
+** to refer to the new cursor numbers.
+**
+** Argument aCsrMap is an array that may be used for temporary working
+** space. Two guarantees are made by the caller:
+**
+** * the array is larger than the largest cursor number used within the
+** select statement passed as an argument, and
+**
+** * the array entries for all cursor numbers that do *not* appear in
+** FROM clauses of the select statement as described above are
+** initialized to zero.
+*/
+static void renumberCursors(
+ Parse *pParse, /* Parse context */
+ Select *p, /* Select to renumber cursors within */
+ int iExcept, /* FROM clause item to skip */
+ int *aCsrMap /* Working space */
+){
+ Walker w;
+ srclistRenumberCursors(pParse, aCsrMap, p->pSrc, iExcept);
+ memset(&w, 0, sizeof(w));
+ w.u.aiCol = aCsrMap;
+ w.xExprCallback = renumberCursorsCb;
+ w.xSelectCallback = sqlite3SelectWalkNoop;
+ sqlite3WalkSelect(&w, p);
+}
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
+
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries as a performance optimization.
struct SrcList_item *pSubitem; /* The subquery */
sqlite3 *db = pParse->db;
Walker w; /* Walker to persist agginfo data */
+ int *aCsrMap = 0;
/* Check to see if flattening is permitted. Return 0 if not.
*/
/* Restriction (23) */
if( (p->selFlags & SF_Recursive) ) return 0;
+
+ if( pSrc->nSrc>1 ){
+ aCsrMap = sqlite3DbMallocZero(db, pParse->nTab*sizeof(int));
+ }
}
/***** If we reach this point, flattening is permitted. *****/
if( pNew==0 ){
p->pPrior = pPrior;
}else{
+ if( aCsrMap && db->mallocFailed==0 ){
+ renumberCursors(pParse, pNew, iFrom, aCsrMap);
+ }
pNew->pPrior = pPrior;
if( pPrior ) pPrior->pNext = pNew;
pNew->pNext = p;
" creates %u as peer\n",pNew->selId));
}
assert( pSubitem->pSelect==0 );
- if( db->mallocFailed ){
- pSubitem->pSelect = pSub1;
- return 1;
- }
+ }
+ sqlite3DbFree(db, aCsrMap);
+ if( db->mallocFailed ){
+ pSubitem->pSelect = pSub1;
+ return 1;
}
/* Defer deleting the Table object associated with the
3 three 3 iii
3 THREE 3 iii
}
+do_execsql_test 2.2.9a {
+ SELECT * FROM t1, t2 ORDER BY +k
+} {
+ 1 one 2 ii 1 ONE 2 ii 2 two 2 ii
+ 2 TWO 2 ii 3 three 2 ii 3 THREE 2 ii
+
+ 1 one 3 iii 1 ONE 3 iii 2 two 3 iii
+ 2 TWO 3 iii 3 three 3 iii 3 THREE 3 iii
+
+ 1 one 4 iv 1 ONE 4 iv 2 two 4 iv
+ 2 TWO 4 iv 3 three 4 iv 3 THREE 4 iv
+
+ 1 one 5 v 1 ONE 5 v 2 two 5 v
+ 2 TWO 5 v 3 three 5 v 3 THREE 5 v
+}
+
+do_execsql_test 2.2.9b {
+ SELECT * FROM t1, t2 ORDER BY k
+} {
+ 1 one 2 ii 1 ONE 2 ii 2 two 2 ii
+ 2 TWO 2 ii 3 three 2 ii 3 THREE 2 ii
+
+ 1 one 3 iii 1 ONE 3 iii 2 two 3 iii
+ 2 TWO 3 iii 3 three 3 iii 3 THREE 3 iii
+
+ 1 one 4 iv 1 ONE 4 iv 2 two 4 iv
+ 2 TWO 4 iv 3 three 4 iv 3 THREE 4 iv
+
+ 1 one 5 v 1 ONE 5 v 2 two 5 v
+ 2 TWO 5 v 3 three 5 v 3 THREE 5 v
+}
finish_test