]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Continuing work toward using sort-and-merge for UNION.
authordrh <>
Fri, 23 Jan 2026 14:37:08 +0000 (14:37 +0000)
committerdrh <>
Fri, 23 Jan 2026 14:37:08 +0000 (14:37 +0000)
FossilOrigin-Name: 94bf43634bbb1fd8e67235b8be0d9744cca1e364ab3cceecca4528e7b78780d1

manifest
manifest.uuid
src/select.c

index 78a1b3f022294738ce9b55618e7b4020de6d7e89..3ea4b993bbf8bb078e1109647b86cb1b1c03c57d 100644 (file)
--- 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.
index 9b1d42e7bdfbffefce5350f4cb0b7bf66fd3609a..2478e5386d223da1b580d5dab0de55a02ff85f7a 100644 (file)
@@ -1 +1 @@
-bdf4d6a9398266c98a0d4ad3c60b431cd498bfa80add3e81d717c687634c2602
+94bf43634bbb1fd8e67235b8be0d9744cca1e364ab3cceecca4528e7b78780d1
index 8cacf1539dc0e8e0036629bfdee336bdda64f093..d8b50706a328ce6fe76a4c46531bad081795e73c 100644 (file)
@@ -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 ){