-C Merge\sthe\slatest\strunk\senhancements\sinto\sthe\sunion-by-merge\sbranch.
-D 2026-01-23T11:44:40.965
+C Continuing\swork\stoward\susing\ssort-and-merge\sfor\sUNION.
+D 2026-01-23T14:37:08.819
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
F src/resolve.c 47aa7fdc9ec4c19b103ac5e79d7887d30119b5675309facf5eed1118391c868b
F src/rowset.c 8432130e6c344b3401a8874c3cb49fefe6873fec593294de077afea2dce5ec97
-F src/select.c 74061189314a0b74e20918abda7ac099cefd604f3867c103e8fcd45cb39fa721
+F src/select.c 99d3bf20c1f7035c0c8eabdfad86d7239d4670e253d183a3ad62baf642503df5
F src/shell.c.in e8818572acd50464bc00426fe0d755e98239f73d531437c3dc7721d1fecb1231
F src/sqlite.h.in d463dcdd67d4865991cd62dc8d3f678086b38365593861f77c09c3401551d59f
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P bc450aba674a8934d718a88af3c2343555b43c2d8403bd5f6d14e177fce6bc9f cef0eed8054f3f760cf3142a897c7eead20869157da8b2a0ee9443733eecd371
-R c95a08a649c065804e87af20b7d443bf
+P bdf4d6a9398266c98a0d4ad3c60b431cd498bfa80add3e81d717c687634c2602
+R 917664d469853cc469980a3c06f2d7e0
U drh
-Z 6275889fa238c9721e9dc57456657b66
+Z dc45dae74764f0f3e185e346f4a688ed
# Remove this line to create a well-formed Fossil manifest.
ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY"));
}
#endif
- pPrior->selFlags |= SF_NoMerge;
/* Generate code for the left and right SELECT statements.
*/
assert( !pPrior->pLimit );
pPrior->iLimit = p->iLimit;
pPrior->iOffset = p->iOffset;
- pPrior->pLimit = p->pLimit;
+ pPrior->pLimit = sqlite3ExprDup(db, p->pLimit, 0);
TREETRACE(0x200, pParse, p, ("multiSelect UNION ALL left...\n"));
rc = sqlite3Select(pParse, pPrior, &dest);
+ sqlite3ExprDelete(db, pPrior->pLimit);
pPrior->pLimit = 0;
if( rc ){
goto multi_select_end;
*/
codeOffset(v, p->iOffset, iContinue);
- assert( pDest->eDest!=SRT_Exists );
- assert( pDest->eDest!=SRT_Table );
switch( pDest->eDest ){
/* Store the result as data using a unique key.
*/
case SRT_Fifo:
case SRT_DistFifo:
+ case SRT_Table:
case SRT_EphemTab: {
int r1 = sqlite3GetTempReg(pParse);
int r2 = sqlite3GetTempReg(pParse);
int iParm = pDest->iSDParm;
+ testcase( pDest->eDest==SRT_Table );
+ testcase( pDest->eDest==SRT_EphemTab );
+ testcase( pDest->eDest==SRT_Fifo );
+ testcase( pDest->eDest==SRT_DistFifo );
sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iSdst, pIn->nSdst, r1);
+#if !defined(SQLITE_ENABLE_NULL_TRIM) && defined(SQLITE_DEBUG)
+ /* A destination of SRT_Table and a non-zero iSDParm2 parameter means
+ ** that this is an "UPDATE ... FROM" on a virtual table or view. In this
+ ** case set the p5 parameter of the OP_MakeRecord to OPFLAG_NOCHNG_MAGIC.
+ ** This does not affect operation in any way - it just allows MakeRecord
+ ** to process OPFLAG_NOCHANGE values without an assert() failing. */
+ if( pDest->eDest==SRT_Table && pDest->iSDParm2 ){
+ sqlite3VdbeChangeP5(v, OPFLAG_NOCHNG_MAGIC);
+ }
+#endif
#ifndef SQLITE_OMIT_CTE
if( pDest->eDest==SRT_DistFifo ){
/* If the destination is DistFifo, then cursor (iParm+1) is open
break;
}
+ /* If any row exist in the result set, record that fact and abort.
+ */
+ case SRT_Exists: {
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iSDParm);
+ /* The LIMIT clause will terminate the loop for us */
+ break;
+ }
+
#ifndef SQLITE_OMIT_SUBQUERY
/* If we are creating a set for an "expr IN (SELECT ...)".
*/
}
#endif /* SQLITE_OMIT_CTE */
-
- /* If none of the above, then the result destination must be
- ** SRT_Output. This routine is never called with any other
- ** destination other than the ones handled above or SRT_Output.
- **
+ /*
** For SRT_Output, results are stored in a sequence of registers.
** Then the OP_ResultRow opcode is used to cause sqlite3_step() to
** return the next row of result.
*/
- default: {
- assert( pDest->eDest==SRT_Output );
+ case SRT_Output: {
sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iSdst, pIn->nSdst);
break;
}
+
+
+ /* If none of the above, then the result destination must be
+ ** SRT_Discard. Ignore the results.
+ */
+ default: {
+ assert( pDest->eDest==SRT_Discard );
+ break;
+ }
}
/* Jump to the end of the loop if the LIMIT is reached.
p->pOrderBy = 0;
}
p->selFlags &= ~(u32)SF_Distinct;
- p->selFlags |= SF_NoopOrderBy|SF_NoMerge;
+ p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
if( pParse->nErr ){