Use OpenHash instead of OpenEphemeral for the RHS of IN operators if the
result is not needed for sorting. FossilOrigin-Name: 715fac7749a6b1523fe9f7de8263f0c4d1571d07
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
C Separate\sout\sthe\scode\sgenerators\sfor\sthe\sRHS\sof\san\sIN\soperator\sand\sfor\nSELECT/EXISTS\sexpressions.
|
||||
D 2014-02-05T19:10:06.824
|
||||
C Use\sOpenHash\sinstead\sof\sOpenEphemeral\sfor\sthe\sRHS\sof\sIN\soperators\sif\sthe\nresult\sis\snot\sneeded\sfor\ssorting.
|
||||
D 2014-02-06T03:31:41.891
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 2ef13430cd359f7b361bb863504e227b25cc7f81
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@@ -175,7 +175,7 @@ F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
|
||||
F src/ctime.c 77779efbe78dd678d84bfb4fc2e87b6b6ad8dccd
|
||||
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
|
||||
F src/delete.c 6765a421f08adbedc5d52d21760ec6dbe5123fd3
|
||||
F src/expr.c 9bc9ed4fdc6e594f207d7d76c21b553843f4a8c3
|
||||
F src/expr.c fa9cd9b4bdc8989efce99d49c7e46484e17f41f4
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c 2ab0f5384b70594468ef3ac5c7ed8ca24bfd17d5
|
||||
F src/func.c f4499b39d66b71825514334ce67b32ff14bd19f5
|
||||
@@ -224,7 +224,7 @@ F src/shell.c 24722d24d4ea8ca93db35e44db7308de786767ca
|
||||
F src/sqlite.h.in eed7f7d66a60daaa7b4a597dcd9bad87aad9611b
|
||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||
F src/sqliteInt.h 3f3b1f593539e9e763942affae420e0923481388
|
||||
F src/sqliteInt.h 29b97acb02309ad07de107a81c381512066fc2e4
|
||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||
@@ -293,7 +293,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||
F src/where.c bacb79fb31e082c9c599e68e5e9f161e1d5430ca
|
||||
F src/where.c 087307272e374c35c7eb1eb722f0ab7db09317f2
|
||||
F src/whereInt.h 921f935af8b684ffb49705610bda7284db1db138
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -593,9 +593,9 @@ F test/hook.test 162d7cef7a2d2b04839fe14402934e6a1b79442f
|
||||
F test/icu.test 70df4faca133254c042d02ae342c0a141f2663f4
|
||||
F test/in.test 047c4671328e9032ab95666a67021adbbd36e98e
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in3.test dbf41c0c073c10a8c0fee280cba3e9dddbd4a9c6
|
||||
F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
|
||||
F test/in5.test 99f9a40af01711b06d2d614ecfe96129f334fba3
|
||||
F test/in5.test 9d8c15bfc9a06da5b354d4d4ecfea9f928769641
|
||||
F test/incrblob.test e81846d214f3637622620fbde7cd526781cfe328
|
||||
F test/incrblob2.test bf4d549aa4a466d7fbe3e3a3693d3861263d5600
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
@@ -1152,7 +1152,7 @@ F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||
P 2997e181575da7e37fe70d20bdddf934f064ae1d
|
||||
R 2ac4bdb95fe25b50af34e24039580145
|
||||
P 61c34ba71b733b81312078d90c1e21a8cbad669a
|
||||
R 2869c52facbdf294824830f655817bcb
|
||||
U drh
|
||||
Z 128a2d5633bd3dcd3b86c50896a50a83
|
||||
Z 2c24fe059c95b02acd2b9be5d0d0ed85
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
61c34ba71b733b81312078d90c1e21a8cbad669a
|
||||
715fac7749a6b1523fe9f7de8263f0c4d1571d07
|
||||
+10
-5
@@ -1509,7 +1509,8 @@ int sqlite3CodeOnce(Parse *pParse){
|
||||
static void sqlite3CreateInOperatorRhsTable(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Expr *pExpr, /* The IN, SELECT, or EXISTS operator */
|
||||
int isRowid /* If true, LHS of IN operator is a rowid */
|
||||
int isRowid, /* If true, LHS of IN operator is a rowid */
|
||||
int bOrdered /* If true, must use btree, not a hash */
|
||||
){
|
||||
int testAddr = -1; /* One-time test address */
|
||||
Vdbe *v = sqlite3GetVdbe(pParse); /* prepared stmt under construction */
|
||||
@@ -1561,7 +1562,8 @@ static void sqlite3CreateInOperatorRhsTable(
|
||||
** is used.
|
||||
*/
|
||||
pExpr->iTable = pParse->nTab++;
|
||||
addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, !isRowid);
|
||||
addr = sqlite3VdbeAddOp2(v, bOrdered ? OP_OpenEphemeral : OP_OpenHash,
|
||||
pExpr->iTable, !isRowid);
|
||||
pKeyInfo = isRowid ? 0 : sqlite3KeyInfoAlloc(pParse->db, 1, 1);
|
||||
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
@@ -1722,9 +1724,12 @@ static void sqlite3CreateInOperatorRhsTable(
|
||||
**
|
||||
** in order to avoid running the <test if data structure contains null>
|
||||
** test more often than is necessary.
|
||||
**
|
||||
** IN_INDEX_EPH ephemeral tables must be in key order if the bOrdered flag
|
||||
** is true. If bOrdered is false, the generated table can be a hash.
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
||||
int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound, int bOrdered){
|
||||
Select *p; /* SELECT to the right of IN operator */
|
||||
int eType = 0; /* Type of RHS table. IN_INDEX_* */
|
||||
int iTab = pParse->nTab++; /* Cursor of the RHS table */
|
||||
@@ -1817,7 +1822,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){
|
||||
eType = IN_INDEX_ROWID;
|
||||
}
|
||||
}
|
||||
sqlite3CreateInOperatorRhsTable(pParse, pX, eType==IN_INDEX_ROWID);
|
||||
sqlite3CreateInOperatorRhsTable(pParse, pX, eType==IN_INDEX_ROWID,bOrdered);
|
||||
pParse->nQueryLoop = savedNQueryLoop;
|
||||
}else{
|
||||
pX->iTable = iTab;
|
||||
@@ -1943,7 +1948,7 @@ static void sqlite3ExprCodeIN(
|
||||
v = pParse->pVdbe;
|
||||
assert( v!=0 ); /* OOM detected prior to this routine */
|
||||
VdbeNoopComment((v, "begin IN expr"));
|
||||
eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull);
|
||||
eType = sqlite3FindInIndex(pParse, pExpr, &rRhsHasNull, 0);
|
||||
|
||||
/* Figure out the affinity to use to create a key from the results
|
||||
** of the expression. affinityStr stores a static string suitable for
|
||||
|
||||
+1
-1
@@ -3478,7 +3478,7 @@ const char *sqlite3JournalModename(int);
|
||||
#define IN_INDEX_EPH 2
|
||||
#define IN_INDEX_INDEX_ASC 3
|
||||
#define IN_INDEX_INDEX_DESC 4
|
||||
int sqlite3FindInIndex(Parse *, Expr *, int*);
|
||||
int sqlite3FindInIndex(Parse *, Expr *, int*, int);
|
||||
|
||||
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
|
||||
int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int);
|
||||
|
||||
+12
-10
@@ -2348,16 +2348,17 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
|
||||
** this routine sets up a loop that will iterate over all values of X.
|
||||
*/
|
||||
static int codeEqualityTerm(
|
||||
Parse *pParse, /* The parsing context */
|
||||
WhereInfo *pWInfo, /* WHERE clause */
|
||||
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;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int iReg; /* Register holding results */
|
||||
Expr *pX = pTerm->pExpr; /* Expression to be coded */
|
||||
Parse *pParse = pWInfo->pParse; /* Parsing context */
|
||||
Vdbe *v = pParse->pVdbe; /* Prepared stmt under construction */
|
||||
int iReg; /* Register holding results */
|
||||
|
||||
assert( iTarget>0 );
|
||||
if( pX->op==TK_EQ ){
|
||||
@@ -2382,7 +2383,7 @@ static int codeEqualityTerm(
|
||||
}
|
||||
assert( pX->op==TK_IN );
|
||||
iReg = iTarget;
|
||||
eType = sqlite3FindInIndex(pParse, pX, 0);
|
||||
eType = sqlite3FindInIndex(pParse, pX, 0, pWInfo->bOBSat);
|
||||
if( eType==IN_INDEX_INDEX_DESC ){
|
||||
testcase( bRev );
|
||||
bRev = !bRev;
|
||||
@@ -2464,7 +2465,7 @@ static int codeEqualityTerm(
|
||||
** string in this example would be set to SQLITE_AFF_NONE.
|
||||
*/
|
||||
static int codeAllEqualityTerms(
|
||||
Parse *pParse, /* Parsing context */
|
||||
WhereInfo *pWInfo, /* WHERE clause */
|
||||
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
|
||||
int bRev, /* Reverse the order of IN operators */
|
||||
int nExtraReg, /* Number of extra registers to allocate */
|
||||
@@ -2472,6 +2473,7 @@ static int codeAllEqualityTerms(
|
||||
){
|
||||
u16 nEq; /* The number of == or IN constraints to code */
|
||||
u16 nSkip; /* Number of left-most columns to skip */
|
||||
Parse *pParse = pWInfo->pParse; /* Parsing context */
|
||||
Vdbe *v = pParse->pVdbe; /* The vm under construction */
|
||||
Index *pIdx; /* The index being used for this loop */
|
||||
WhereTerm *pTerm; /* A single constraint term */
|
||||
@@ -2526,7 +2528,7 @@ static int codeAllEqualityTerms(
|
||||
** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */
|
||||
testcase( (pTerm->wtFlags & TERM_CODED)!=0 );
|
||||
testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
||||
r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j);
|
||||
r1 = codeEqualityTerm(pWInfo, pTerm, pLevel, j, bRev, regBase+j);
|
||||
if( r1!=regBase+j ){
|
||||
if( nReg==1 ){
|
||||
sqlite3ReleaseTempReg(pParse, regBase);
|
||||
@@ -2809,7 +2811,7 @@ static Bitmask codeOneLoopStart(
|
||||
pTerm = pLoop->aLTerm[j];
|
||||
if( pTerm==0 ) continue;
|
||||
if( pTerm->eOperator & WO_IN ){
|
||||
codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget);
|
||||
codeEqualityTerm(pWInfo, pTerm, pLevel, j, bRev, iTarget);
|
||||
addrNotFound = pLevel->addrNxt;
|
||||
}else{
|
||||
sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
|
||||
@@ -2849,7 +2851,7 @@ static Bitmask codeOneLoopStart(
|
||||
assert( pTerm->pExpr!=0 );
|
||||
assert( omitTable==0 );
|
||||
testcase( pTerm->wtFlags & TERM_VIRTUAL );
|
||||
iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg);
|
||||
iRowidReg = codeEqualityTerm(pWInfo, pTerm, pLevel, 0, bRev, iReleaseReg);
|
||||
addrNxt = pLevel->addrNxt;
|
||||
sqlite3VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg);
|
||||
@@ -3039,7 +3041,7 @@ static Bitmask codeOneLoopStart(
|
||||
** and store the values of those terms in an array of registers
|
||||
** starting at regBase.
|
||||
*/
|
||||
regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
|
||||
regBase = codeAllEqualityTerms(pWInfo,pLevel,bRev,nExtraReg,&zStartAff);
|
||||
assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
|
||||
if( zStartAff ) cEndAff = zStartAff[nEq];
|
||||
addrNxt = pLevel->addrNxt;
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ ifcapable !subquery {
|
||||
proc nEphemeral {sql} {
|
||||
set nEph 0
|
||||
foreach op [execsql "EXPLAIN $sql"] {
|
||||
if {$op eq "OpenEphemeral"} {incr nEph}
|
||||
if {$op eq "OpenEphemeral" || $op eq "OpenHash"} {incr nEph}
|
||||
}
|
||||
set nEph
|
||||
}
|
||||
|
||||
+3
-3
@@ -65,17 +65,17 @@ do_test in5-2.4 {
|
||||
}
|
||||
} {12a 56e}
|
||||
do_test in5-2.5.1 {
|
||||
regexp {OpenEphemeral} [db eval {
|
||||
regexp {Open(Ephemeral|Hash)} [db eval {
|
||||
EXPLAIN SELECT d FROM t2 WHERE a IN t3x AND b IN t1y AND c IN t1z
|
||||
}]
|
||||
} {1}
|
||||
do_test in5-2.5.2 {
|
||||
regexp {OpenEphemeral} [db eval {
|
||||
regexp {Open(Ephemeral|Hash)} [db eval {
|
||||
EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t3y AND c IN t1z
|
||||
}]
|
||||
} {1}
|
||||
do_test in5-2.5.3 {
|
||||
regexp {OpenEphemeral} [db eval {
|
||||
regexp {Open(Ephemeral|Hash)} [db eval {
|
||||
EXPLAIN SELECT d FROM t2 WHERE a IN t1x AND b IN t1y AND c IN t3z
|
||||
}]
|
||||
} {1}
|
||||
|
||||
Reference in New Issue
Block a user