From: drh <> Date: Fri, 23 Jan 2026 14:37:08 +0000 (+0000) Subject: Continuing work toward using sort-and-merge for UNION. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40573642e8aed9efc1973eabfb83c137b20cdb2a;p=thirdparty%2Fsqlite.git Continuing work toward using sort-and-merge for UNION. FossilOrigin-Name: 94bf43634bbb1fd8e67235b8be0d9744cca1e364ab3cceecca4528e7b78780d1 --- diff --git a/manifest b/manifest index 78a1b3f022..3ea4b993bb 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -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 @@ -738,7 +738,7 @@ F src/printf.c b1b29b5e58e1530d5daeee5963d3c318d8ab2d7e38437580e28755753e0c1ded 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 @@ -2193,8 +2193,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee 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. diff --git a/manifest.uuid b/manifest.uuid index 9b1d42e7bd..2478e5386d 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bdf4d6a9398266c98a0d4ad3c60b431cd498bfa80add3e81d717c687634c2602 +94bf43634bbb1fd8e67235b8be0d9744cca1e364ab3cceecca4528e7b78780d1 diff --git a/src/select.c b/src/select.c index 8cacf1539d..d8b50706a3 100644 --- a/src/select.c +++ b/src/select.c @@ -2998,7 +2998,6 @@ static int multiSelect( ExplainQueryPlan((pParse, 1, "LEFT-MOST SUBQUERY")); } #endif - pPrior->selFlags |= SF_NoMerge; /* Generate code for the left and right SELECT statements. */ @@ -3009,9 +3008,10 @@ static int multiSelect( 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; @@ -3377,18 +3377,31 @@ static int generateOutputSubroutine( */ 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 @@ -3412,6 +3425,14 @@ static int generateOutputSubroutine( 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 ...)". */ @@ -3506,20 +3527,24 @@ static int generateOutputSubroutine( } #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. @@ -7827,7 +7852,7 @@ int sqlite3Select( 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 ){