Small performance optimization in the codeEqualityTerm() routine of the
code generator. FossilOrigin-Name: 8080c6eafd1280ea870a6ab1ba715ac5af67387e69771be6cbd46dda77c3eaa8
This commit is contained in:
parent
6d98c55b56
commit
0de7da1998
14
manifest
14
manifest
@ -1,5 +1,5 @@
|
|||||||
C Fix\san\sfts5\sproblem\swith\ssecure-delete\smode\scausing\sintegrity-check\sto\serroneously\sreport\sa\scorrupt\sindex.
|
C Small\sperformance\soptimization\sin\sthe\scodeEqualityTerm()\sroutine\sof\sthe\ncode\sgenerator.
|
||||||
D 2024-06-05T14:47:54.677
|
D 2024-06-05T20:41:36.552
|
||||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||||
@ -842,7 +842,7 @@ F src/wal.h ba252daaa94f889f4b2c17c027e823d9be47ce39da1d3799886bbd51f0490452
|
|||||||
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
F src/walker.c 7c7ea0115345851c3da4e04e2e239a29983b61fb5b038b94eede6aba462640e2
|
||||||
F src/where.c 343e74d65856665f2aac59a9fcefecfc988e9af4aafa0bd1b8332a89c6c725b4
|
F src/where.c 343e74d65856665f2aac59a9fcefecfc988e9af4aafa0bd1b8332a89c6c725b4
|
||||||
F src/whereInt.h 002adc3aa2cc10733b9b27958fdbe893987cd989fab25a9853941c1f9b9b0a65
|
F src/whereInt.h 002adc3aa2cc10733b9b27958fdbe893987cd989fab25a9853941c1f9b9b0a65
|
||||||
F src/wherecode.c 5ad509221ebb4d3b35a8a6ef361f2c5b54129b8c273aa434dd3053d2e25d1794
|
F src/wherecode.c c9cac0b0b8e809c5e7e79d7796918907fb685ad99be2aaa9737f9787aa47349c
|
||||||
F src/whereexpr.c 67d15caf88a1a9528283d68ff578e024cf9fe810b517bb0343e5aaf695ad97dd
|
F src/whereexpr.c 67d15caf88a1a9528283d68ff578e024cf9fe810b517bb0343e5aaf695ad97dd
|
||||||
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
|
F src/window.c 5d95122dd330bfaebd732358c8ef067c5a9394a53ac249470d611d0ce2c52be2
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
@ -2194,8 +2194,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P a096eb7554952f8137c6e9330c328164719fb27e958787fbd503bcd1364e6ae4
|
P 80bef4d60ba9e3679ea66655ca36fcfaa888775a3d1598d50e9649ad84a95b63
|
||||||
R 0a424bef53f9d9c6999e5b99ba3f491f
|
R 2c603113ce745efce0c45179f5a33586
|
||||||
U dan
|
U drh
|
||||||
Z bc999b30c47bb6a6c63f18a66f996a4c
|
Z 49fdb8ccd67e18818e3ecc829cf527f5
|
||||||
# Remove this line to create a well-formed Fossil manifest.
|
# Remove this line to create a well-formed Fossil manifest.
|
||||||
|
@ -1 +1 @@
|
|||||||
80bef4d60ba9e3679ea66655ca36fcfaa888775a3d1598d50e9649ad84a95b63
|
8080c6eafd1280ea870a6ab1ba715ac5af67387e69771be6cbd46dda77c3eaa8
|
259
src/wherecode.c
259
src/wherecode.c
@ -604,6 +604,147 @@ static Expr *removeUnindexableInClauseTerms(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SQLITE_OMIT_SUBQUERY
|
||||||
|
/*
|
||||||
|
** Generate code for a single X IN (....) term of the WHERE clause.
|
||||||
|
**
|
||||||
|
** This is a special-case of codeEqualityTerm() that works for IN operators
|
||||||
|
** only. It is broken out into a subroutine because this case is
|
||||||
|
** uncommon and by splitting it off into a subroutine, the common case
|
||||||
|
** runs faster.
|
||||||
|
**
|
||||||
|
** The current value for the constraint is left in register iTarget.
|
||||||
|
** This routine sets up a loop that will iterate over all values of X.
|
||||||
|
*/
|
||||||
|
static SQLITE_NOINLINE void codeINTerm(
|
||||||
|
Parse *pParse, /* The parsing context */
|
||||||
|
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
|
||||||
|
WhereLevel *pLevel, /* The level of the FROM clause we are working on */
|
||||||
|
int iEq, /* Index of the equality term within this level */
|
||||||
|
int bRev, /* True for reverse-order IN operations */
|
||||||
|
int iTarget /* Attempt to leave results in this register */
|
||||||
|
){
|
||||||
|
Expr *pX = pTerm->pExpr;
|
||||||
|
int eType = IN_INDEX_NOOP;
|
||||||
|
int iTab;
|
||||||
|
struct InLoop *pIn;
|
||||||
|
WhereLoop *pLoop = pLevel->pWLoop;
|
||||||
|
Vdbe *v = pParse->pVdbe;
|
||||||
|
int i;
|
||||||
|
int nEq = 0;
|
||||||
|
int *aiMap = 0;
|
||||||
|
|
||||||
|
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
|
||||||
|
&& pLoop->u.btree.pIndex!=0
|
||||||
|
&& pLoop->u.btree.pIndex->aSortOrder[iEq]
|
||||||
|
){
|
||||||
|
testcase( iEq==0 );
|
||||||
|
testcase( bRev );
|
||||||
|
bRev = !bRev;
|
||||||
|
}
|
||||||
|
assert( pX->op==TK_IN );
|
||||||
|
|
||||||
|
for(i=0; i<iEq; i++){
|
||||||
|
if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
|
||||||
|
disableTerm(pLevel, pTerm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(i=iEq;i<pLoop->nLTerm; i++){
|
||||||
|
assert( pLoop->aLTerm[i]!=0 );
|
||||||
|
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
|
||||||
|
}
|
||||||
|
|
||||||
|
iTab = 0;
|
||||||
|
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
|
||||||
|
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
|
||||||
|
}else{
|
||||||
|
Expr *pExpr = pTerm->pExpr;
|
||||||
|
if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
|
||||||
|
sqlite3 *db = pParse->db;
|
||||||
|
pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
|
||||||
|
if( !db->mallocFailed ){
|
||||||
|
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
|
||||||
|
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
|
||||||
|
pExpr->iTable = iTab;
|
||||||
|
}
|
||||||
|
sqlite3ExprDelete(db, pX);
|
||||||
|
}else{
|
||||||
|
int n = sqlite3ExprVectorSize(pX->pLeft);
|
||||||
|
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
|
||||||
|
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
|
||||||
|
}
|
||||||
|
pX = pExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( eType==IN_INDEX_INDEX_DESC ){
|
||||||
|
testcase( bRev );
|
||||||
|
bRev = !bRev;
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
|
||||||
|
VdbeCoverageIf(v, bRev);
|
||||||
|
VdbeCoverageIf(v, !bRev);
|
||||||
|
|
||||||
|
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
|
||||||
|
pLoop->wsFlags |= WHERE_IN_ABLE;
|
||||||
|
if( pLevel->u.in.nIn==0 ){
|
||||||
|
pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
|
||||||
|
}
|
||||||
|
if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
|
||||||
|
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = pLevel->u.in.nIn;
|
||||||
|
pLevel->u.in.nIn += nEq;
|
||||||
|
pLevel->u.in.aInLoop =
|
||||||
|
sqlite3WhereRealloc(pTerm->pWC->pWInfo,
|
||||||
|
pLevel->u.in.aInLoop,
|
||||||
|
sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
|
||||||
|
pIn = pLevel->u.in.aInLoop;
|
||||||
|
if( pIn ){
|
||||||
|
int iMap = 0; /* Index in aiMap[] */
|
||||||
|
pIn += i;
|
||||||
|
for(i=iEq;i<pLoop->nLTerm; i++){
|
||||||
|
if( pLoop->aLTerm[i]->pExpr==pX ){
|
||||||
|
int iOut = iTarget + i - iEq;
|
||||||
|
if( eType==IN_INDEX_ROWID ){
|
||||||
|
pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
|
||||||
|
}else{
|
||||||
|
int iCol = aiMap ? aiMap[iMap++] : 0;
|
||||||
|
pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
|
||||||
|
}
|
||||||
|
sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
|
||||||
|
if( i==iEq ){
|
||||||
|
pIn->iCur = iTab;
|
||||||
|
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
|
||||||
|
if( iEq>0 ){
|
||||||
|
pIn->iBase = iTarget - i;
|
||||||
|
pIn->nPrefix = i;
|
||||||
|
}else{
|
||||||
|
pIn->nPrefix = 0;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
pIn->eEndLoopOp = OP_Noop;
|
||||||
|
}
|
||||||
|
pIn++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
testcase( iEq>0
|
||||||
|
&& (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
|
||||||
|
&& (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
|
||||||
|
if( iEq>0
|
||||||
|
&& (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
|
||||||
|
){
|
||||||
|
sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
pLevel->u.in.nIn = 0;
|
||||||
|
}
|
||||||
|
sqlite3DbFree(pParse->db, aiMap);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code for a single equality term of the WHERE clause. An equality
|
** Generate code for a single equality term of the WHERE clause. An equality
|
||||||
** term can be either X=expr or X IN (...). pTerm is the term to be
|
** term can be either X=expr or X IN (...). pTerm is the term to be
|
||||||
@ -628,7 +769,6 @@ static int codeEqualityTerm(
|
|||||||
int iTarget /* Attempt to leave results in this register */
|
int iTarget /* Attempt to leave results in this register */
|
||||||
){
|
){
|
||||||
Expr *pX = pTerm->pExpr;
|
Expr *pX = pTerm->pExpr;
|
||||||
Vdbe *v = pParse->pVdbe;
|
|
||||||
int iReg; /* Register holding results */
|
int iReg; /* Register holding results */
|
||||||
|
|
||||||
assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
|
assert( pLevel->pWLoop->aLTerm[iEq]==pTerm );
|
||||||
@ -637,125 +777,12 @@ static int codeEqualityTerm(
|
|||||||
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
|
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
|
||||||
}else if( pX->op==TK_ISNULL ){
|
}else if( pX->op==TK_ISNULL ){
|
||||||
iReg = iTarget;
|
iReg = iTarget;
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
|
sqlite3VdbeAddOp2(pParse->pVdbe, OP_Null, 0, iReg);
|
||||||
#ifndef SQLITE_OMIT_SUBQUERY
|
#ifndef SQLITE_OMIT_SUBQUERY
|
||||||
}else{
|
}else{
|
||||||
int eType = IN_INDEX_NOOP;
|
|
||||||
int iTab;
|
|
||||||
struct InLoop *pIn;
|
|
||||||
WhereLoop *pLoop = pLevel->pWLoop;
|
|
||||||
int i;
|
|
||||||
int nEq = 0;
|
|
||||||
int *aiMap = 0;
|
|
||||||
|
|
||||||
if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0
|
|
||||||
&& pLoop->u.btree.pIndex!=0
|
|
||||||
&& pLoop->u.btree.pIndex->aSortOrder[iEq]
|
|
||||||
){
|
|
||||||
testcase( iEq==0 );
|
|
||||||
testcase( bRev );
|
|
||||||
bRev = !bRev;
|
|
||||||
}
|
|
||||||
assert( pX->op==TK_IN );
|
assert( pX->op==TK_IN );
|
||||||
iReg = iTarget;
|
iReg = iTarget;
|
||||||
|
codeINTerm(pParse, pTerm, pLevel, iEq, bRev, iTarget);
|
||||||
for(i=0; i<iEq; i++){
|
|
||||||
if( pLoop->aLTerm[i] && pLoop->aLTerm[i]->pExpr==pX ){
|
|
||||||
disableTerm(pLevel, pTerm);
|
|
||||||
return iTarget;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(i=iEq;i<pLoop->nLTerm; i++){
|
|
||||||
assert( pLoop->aLTerm[i]!=0 );
|
|
||||||
if( pLoop->aLTerm[i]->pExpr==pX ) nEq++;
|
|
||||||
}
|
|
||||||
|
|
||||||
iTab = 0;
|
|
||||||
if( !ExprUseXSelect(pX) || pX->x.pSelect->pEList->nExpr==1 ){
|
|
||||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, 0, &iTab);
|
|
||||||
}else{
|
|
||||||
Expr *pExpr = pTerm->pExpr;
|
|
||||||
if( pExpr->iTable==0 || !ExprHasProperty(pExpr, EP_Subrtn) ){
|
|
||||||
sqlite3 *db = pParse->db;
|
|
||||||
pX = removeUnindexableInClauseTerms(pParse, iEq, pLoop, pX);
|
|
||||||
if( !db->mallocFailed ){
|
|
||||||
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*nEq);
|
|
||||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap,&iTab);
|
|
||||||
pExpr->iTable = iTab;
|
|
||||||
}
|
|
||||||
sqlite3ExprDelete(db, pX);
|
|
||||||
}else{
|
|
||||||
int n = sqlite3ExprVectorSize(pX->pLeft);
|
|
||||||
aiMap = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int)*MAX(nEq,n));
|
|
||||||
eType = sqlite3FindInIndex(pParse, pX, IN_INDEX_LOOP, 0, aiMap, &iTab);
|
|
||||||
}
|
|
||||||
pX = pExpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( eType==IN_INDEX_INDEX_DESC ){
|
|
||||||
testcase( bRev );
|
|
||||||
bRev = !bRev;
|
|
||||||
}
|
|
||||||
sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
|
|
||||||
VdbeCoverageIf(v, bRev);
|
|
||||||
VdbeCoverageIf(v, !bRev);
|
|
||||||
|
|
||||||
assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
|
|
||||||
pLoop->wsFlags |= WHERE_IN_ABLE;
|
|
||||||
if( pLevel->u.in.nIn==0 ){
|
|
||||||
pLevel->addrNxt = sqlite3VdbeMakeLabel(pParse);
|
|
||||||
}
|
|
||||||
if( iEq>0 && (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0 ){
|
|
||||||
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = pLevel->u.in.nIn;
|
|
||||||
pLevel->u.in.nIn += nEq;
|
|
||||||
pLevel->u.in.aInLoop =
|
|
||||||
sqlite3WhereRealloc(pTerm->pWC->pWInfo,
|
|
||||||
pLevel->u.in.aInLoop,
|
|
||||||
sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
|
|
||||||
pIn = pLevel->u.in.aInLoop;
|
|
||||||
if( pIn ){
|
|
||||||
int iMap = 0; /* Index in aiMap[] */
|
|
||||||
pIn += i;
|
|
||||||
for(i=iEq;i<pLoop->nLTerm; i++){
|
|
||||||
if( pLoop->aLTerm[i]->pExpr==pX ){
|
|
||||||
int iOut = iReg + i - iEq;
|
|
||||||
if( eType==IN_INDEX_ROWID ){
|
|
||||||
pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
|
|
||||||
}else{
|
|
||||||
int iCol = aiMap ? aiMap[iMap++] : 0;
|
|
||||||
pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
|
|
||||||
}
|
|
||||||
sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
|
|
||||||
if( i==iEq ){
|
|
||||||
pIn->iCur = iTab;
|
|
||||||
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
|
|
||||||
if( iEq>0 ){
|
|
||||||
pIn->iBase = iReg - i;
|
|
||||||
pIn->nPrefix = i;
|
|
||||||
}else{
|
|
||||||
pIn->nPrefix = 0;
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
pIn->eEndLoopOp = OP_Noop;
|
|
||||||
}
|
|
||||||
pIn++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
testcase( iEq>0
|
|
||||||
&& (pLoop->wsFlags & WHERE_IN_SEEKSCAN)==0
|
|
||||||
&& (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 );
|
|
||||||
if( iEq>0
|
|
||||||
&& (pLoop->wsFlags & (WHERE_IN_SEEKSCAN|WHERE_VIRTUALTABLE))==0
|
|
||||||
){
|
|
||||||
sqlite3VdbeAddOp3(v, OP_SeekHit, pLevel->iIdxCur, 0, iEq);
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
pLevel->u.in.nIn = 0;
|
|
||||||
}
|
|
||||||
sqlite3DbFree(pParse->db, aiMap);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user