From: drh <> Date: Wed, 28 Jan 2026 16:59:34 +0000 (+0000) Subject: Improved (faster) bytecode for the merge algorithm. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fabd481c76cc146d6de1352c25b6a2ddc5347c37;p=thirdparty%2Fsqlite.git Improved (faster) bytecode for the merge algorithm. FossilOrigin-Name: 0b7f4b97e68f17ae2fec86017cdb170f3b318a71cda34b5c82ec2d9df780564f --- diff --git a/manifest b/manifest index 0dad05dfe7..639d8f323d 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sa\scomment\sto\ssqlite3Stat4Value()\sexplaining\sthat\sit\sread\sa\sfew\sbytes\spast\sthe\send\sof\sthe\sspecified\sbuffer. -D 2026-01-28T10:52:53.788 +C Improved\s(faster)\sbytecode\sfor\sthe\smerge\salgorithm. +D 2026-01-28T16:59:34.852 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 89db4768dc2ffed05755e072006dd13455cd387a2c169f167b48c1d48c56b257 +F src/select.c 4bee1bb231771e7c6e5aef243b1f74c3d330df5a005909d5e2c338fb1510fe55 F src/shell.c.in d7c1041d6ad00bee2515842a1950640afe424df2e89ad2d6e3b9e68b184824a5 F src/sqlite.h.in 8bcbaecfe2cbecf8c5c1381354fcdd7d307443e88b4953fccb222456c1267b61 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 631c8d44cd1624ddc45babd3f0d810908c2a368784744262042c63506ff2e333 -R 9d3d16bae5779cc20645971566ff547b -U dan -Z 967d464084320ff484ef70ae7aceb51f +P b95644eafdd42293096a3760af8b2110f3c7d83feecdeff5ff9f008d9748e874 +R e12fe81159464b3fa2ae49533a88f39a +U drh +Z 443016052e3b7e21943bf488170474d9 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index bc6a27e457..c6a504886a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -b95644eafdd42293096a3760af8b2110f3c7d83feecdeff5ff9f008d9748e874 +0b7f4b97e68f17ae2fec86017cdb170f3b318a71cda34b5c82ec2d9df780564f diff --git a/src/select.c b/src/select.c index 9b910b890c..98f4047da0 100644 --- a/src/select.c +++ b/src/select.c @@ -2586,7 +2586,7 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){ */ static KeyInfo *multiSelectByMergeKeyInfo(Parse *pParse, Select *p, int nExtra){ ExprList *pOrderBy = p->pOrderBy; - int nOrderBy = ALWAYS(pOrderBy!=0) ? pOrderBy->nExpr : 0; + int nOrderBy = (pOrderBy!=0) ? pOrderBy->nExpr : 0; sqlite3 *db = pParse->db; KeyInfo *pRet = sqlite3KeyInfoAlloc(db, nOrderBy+nExtra, 1); if( pRet ){ @@ -3389,10 +3389,8 @@ static int generateOutputSubroutine( ** AeqB: ... ** AgtB: ... ** Init: initialize coroutine registers -** yield coA -** if eof(A) goto EofA -** yield coB -** if eof(B) goto EofB +** yield coA, on eof goto EofA +** yield coB, on eof goto EofB ** Cmpr: Compare A, B ** Jump AltB, AeqB, AgtB ** End: ... @@ -3484,26 +3482,29 @@ static int multiSelectByMerge( } /* Compute the comparison permutation and keyinfo that is used with - ** the permutation used to determine if the next - ** row of results comes from selectA or selectB. Also add explicit - ** collations to the ORDER BY clause terms so that when the subqueries - ** to the right and the left are evaluated, they use the correct - ** collation. + ** the permutation to determine if the next row of results comes + ** from selectA or selectB. Also add literal collations to the + ** ORDER BY clause terms so that when selectA and selectB are + ** evaluated, they use the correct collation. */ aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1)); if( aPermute ){ struct ExprList_item *pItem; + int bKeep = 0; aPermute[0] = nOrderBy; for(i=1, pItem=pOrderBy->a; i<=nOrderBy; i++, pItem++){ assert( pItem!=0 ); assert( pItem->u.x.iOrderByCol>0 ); assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ); aPermute[i] = pItem->u.x.iOrderByCol - 1; + if( aPermute[i]!=i-1 ) bKeep = 1; + } + if( bKeep==0 ){ + sqlite3DbFreeNN(db, aPermute); + aPermute = 0; } - pKeyMerge = multiSelectByMergeKeyInfo(pParse, p, 1); - }else{ - pKeyMerge = 0; } + pKeyMerge = multiSelectByMergeKeyInfo(pParse, p, 1); /* Allocate a range of temporary registers and the KeyInfo needed ** for the logic that removes duplicate result rows when the @@ -3657,7 +3658,6 @@ static int multiSelectByMerge( /* Generate code to handle the case of AB */ - VdbeNoopComment((v, "SUBR: A-gt-B")); addrAgtB = sqlite3VdbeCurrentAddr(v); if( op==TK_ALL || op==TK_UNION ){ sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB); VdbeComment((v, "out-B")); + sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); + VdbeComment((v, "next-B")); + sqlite3VdbeGoto(v, labelCmpr); + }else{ + addrAgtB++; /* Just do next-B. Might as well use the next-B call + ** in the next code block */ } - sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); - VdbeComment((v, "next-B")); - sqlite3VdbeGoto(v, labelCmpr); /* This code runs once to initialize everything. */ sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp2(v, OP_Yield, regAddrA, addrEofA_noB); VdbeCoverage(v); + VdbeComment((v, "next-A")); + /* v--- Also the A>B case for EXCEPT and INTERSECT */ sqlite3VdbeAddOp2(v, OP_Yield, regAddrB, addrEofB); VdbeCoverage(v); + VdbeComment((v, "next-B")); /* Implement the main merge loop */ + if( aPermute!=0 ){ + sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); + } sqlite3VdbeResolveLabel(v, labelCmpr); - sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO); - sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); + if( aPermute!=0 ){ + sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); + } sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); VdbeCoverageIf(v, op==TK_ALL); VdbeCoverageIf(v, op==TK_UNION);