1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Optimize the IS NULL and IS NOT NULL operators so that they avoid loading

large strings or blobs off of disk if all it needs to know is whether or
not the string or blob is NULL.

FossilOrigin-Name: cb94350185f555c333b628ee846c47bcc9df5f76bb82de569b8322f30dbbe1bc
This commit is contained in:
drh
2022-10-13 15:09:44 +00:00
7 changed files with 34 additions and 18 deletions

View File

@@ -1,5 +1,5 @@
C Fix\sa\stypo\sin\sthe\sdocumentation\sof\sthe\sOP_Column\sopcode.\n[forum:/forumpost/a2b5bd6d43|Forum\spost\sa2b5bd6d43]. C Optimize\sthe\sIS\sNULL\sand\sIS\sNOT\sNULL\soperators\sso\sthat\sthey\savoid\sloading\nlarge\sstrings\sor\sblobs\soff\sof\sdisk\sif\sall\sit\sneeds\sto\sknow\sis\swhether\sor\nnot\sthe\sstring\sor\sblob\sis\sNULL.
D 2022-10-13T14:01:11.049 D 2022-10-13T15:09:44.252
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
@@ -570,7 +570,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5
F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e
F src/expr.c 1cbdd76eeedb729ea9060df03e3e6b74a302784a13bfa38794a8194f894641ea F src/expr.c d199850a925665df7f8ac29fa938909f65a2bd32354aa206aa8c25fc74ff3d3d
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002
F src/func.c 8f72e88cccdee22185133c10f96ccd61dc34c5ea4b1fa9a73c237ef59b2e64f1 F src/func.c 8f72e88cccdee22185133c10f96ccd61dc34c5ea4b1fa9a73c237ef59b2e64f1
@@ -613,7 +613,7 @@ F src/parse.y 8e67d820030d2655b9942ffe61c1e7e6b96cea2f2f72183533299393907d0564
F src/pcache.c f4268f7f73c6a3db12ce22fd25bc68dc42315d19599414ab1207d7cf32f79197 F src/pcache.c f4268f7f73c6a3db12ce22fd25bc68dc42315d19599414ab1207d7cf32f79197
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc
F src/pragma.c 444f596c9e9123d19451ad762917f0f7545e4acecb10f67e09a19f01289cefce F src/pragma.c 41430ca04735cc8e5d003bfd9315eadede3ec326e50805cc81bcf34e46601292
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7 F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c 1b02be0441eda4579471fea097f678effcbb77ef0c39ab3f703c837822bcd674 F src/prepare.c 1b02be0441eda4579471fea097f678effcbb77ef0c39ab3f703c837822bcd674
F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764 F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764
@@ -692,11 +692,11 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 0be191521ff6d2805995f4910f0b6231b42843678b2efdc1abecaf39929a673f F src/util.c 0be191521ff6d2805995f4910f0b6231b42843678b2efdc1abecaf39929a673f
F src/vacuum.c bb346170b0b54c6683bba4a5983aea40485597fdf605c87ec8bc2e199fe88cd8 F src/vacuum.c bb346170b0b54c6683bba4a5983aea40485597fdf605c87ec8bc2e199fe88cd8
F src/vdbe.c 76c402850156e69eaf43c32fc8e5ecffa2c4a0cf0c2dc24c23e48a60d1bf388a F src/vdbe.c 0c7cb1b934ad8611e14e7efaf2c3a95df7dd3f7964d63ea07fef42a23df86131
F src/vdbe.h 64619af62603dc3c4f5ff6ff6d2c8f389abd667a29ce6007ed44bd22b3211cd0 F src/vdbe.h 58675f47dcf3105bab182c3ad3726efd60ffd003e954386904ac9107d0d2b743
F src/vdbeInt.h 17b7461ffcf9ee760d1341731715a419f6b8c763089a7ece25c2e8098d702b3f F src/vdbeInt.h 17b7461ffcf9ee760d1341731715a419f6b8c763089a7ece25c2e8098d702b3f
F src/vdbeapi.c 1e8713d0b653acb43cd1bdf579c40e005c4844ea90f414f065946a83db3c27fb F src/vdbeapi.c 1e8713d0b653acb43cd1bdf579c40e005c4844ea90f414f065946a83db3c27fb
F src/vdbeaux.c c719cebaffa75e166f16a405b3dee96e7150d60fc563ab2dea716b60c6a51312 F src/vdbeaux.c 6946c7082a0d61566794bd35253f0ccd013a9dba3f33488a23fd5360a5744e5b
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35 F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
@@ -2034,8 +2034,9 @@ 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 ef689e33e464829f5cbe4ca24a53d9dba59abe74d3d80a37a91b93a4eccccf2d P 043e76e6166da5cf8e213cce46aaccb1f910e1fdbdb5556576eafb81b3bc5faa 5e9c67ba18b701aabbb0546acdfc532c9e8f0d27fb0a2c899415a5c47096c90b
R be99ac3662eff783728d08e4d117e169 R c0d9c663bdd4b8318254b199c65d7e13
T +closed 5e9c67ba18b701aabbb0546acdfc532c9e8f0d27fb0a2c899415a5c47096c90b
U drh U drh
Z 157d4043f80d56e9469d6c0aa37164a1 Z 57cc74128fdf4ddaf1ca461d6df422e4
# Remove this line to create a well-formed Fossil manifest. # Remove this line to create a well-formed Fossil manifest.

View File

@@ -1 +1 @@
043e76e6166da5cf8e213cce46aaccb1f910e1fdbdb5556576eafb81b3bc5faa cb94350185f555c333b628ee846c47bcc9df5f76bb82de569b8322f30dbbe1bc

View File

@@ -5241,6 +5241,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL ); assert( TK_ISNULL==OP_IsNull ); testcase( op==TK_ISNULL );
assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); assert( TK_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL );
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
sqlite3VdbeTypeofColumn(v, r1);
sqlite3VdbeAddOp2(v, op, r1, dest); sqlite3VdbeAddOp2(v, op, r1, dest);
VdbeCoverageIf(v, op==TK_ISNULL); VdbeCoverageIf(v, op==TK_ISNULL);
VdbeCoverageIf(v, op==TK_NOTNULL); VdbeCoverageIf(v, op==TK_NOTNULL);
@@ -5415,6 +5416,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
case TK_ISNULL: case TK_ISNULL:
case TK_NOTNULL: { case TK_NOTNULL: {
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree1);
sqlite3VdbeTypeofColumn(v, r1);
sqlite3VdbeAddOp2(v, op, r1, dest); sqlite3VdbeAddOp2(v, op, r1, dest);
testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL); testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL);
testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL); testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL);

View File

@@ -1791,9 +1791,7 @@ void sqlite3Pragma(
|| pTab->iPKey==mxCol) ) mxCol--; || pTab->iPKey==mxCol) ) mxCol--;
if( mxCol>=0 ){ if( mxCol>=0 ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, mxCol, 3); sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, mxCol, 3);
if( sqlite3VdbeGetLastOp(v)->opcode==OP_Column ){ sqlite3VdbeTypeofColumn(v, 3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
} }
if( !isQuick ){ if( !isQuick ){

View File

@@ -2781,10 +2781,12 @@ case OP_Offset: { /* out3 */
** if the P4 argument is a P4_MEM use the value of the P4 argument as ** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result. ** the result.
** **
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then ** If the OPFLAG_LENGTHARG bit is set in P5 then the result is guaranteed
** the result is guaranteed to only be used as the argument of a length() ** to only be used by the length() function or the equivalent. The content
** or typeof() function, respectively. The loading of large blobs can be ** of large blobs is not loaded, thus saving CPU cycles. If the
** skipped for length() and all content loading can be skipped for typeof(). ** OPFLAG_TYPEOFARG bit is set then the result will only be used by the
** typeof() function or the IS NULL or IS NOT NULL operators or the
** equivalent. In this case, all content loading can be omitted.
*/ */
case OP_Column: { case OP_Column: {
u32 p2; /* column number to retrieve */ u32 p2; /* column number to retrieve */

View File

@@ -228,6 +228,7 @@ void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
void sqlite3VdbeChangeP5(Vdbe*, u16 P5); void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
void sqlite3VdbeTypeofColumn(Vdbe*, int);
void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeJumpHere(Vdbe*, int addr);
void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr); void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr);
int sqlite3VdbeChangeToNoop(Vdbe*, int addr); int sqlite3VdbeChangeToNoop(Vdbe*, int addr);

View File

@@ -1155,6 +1155,18 @@ void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5; if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
} }
/*
** If the previous opcode is an OP_Column that delivers results
** into register iDest, then add the OPFLAG_TYPEOFARG flag to that
** opcode.
*/
void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){
VdbeOp *pOp = sqlite3VdbeGetLastOp(p);
if( pOp->p3==iDest && pOp->opcode==OP_Column ){
pOp->p5 |= OPFLAG_TYPEOFARG;
}
}
/* /*
** Change the P2 operand of instruction addr so that it points to ** Change the P2 operand of instruction addr so that it points to
** the address of the next instruction to be coded. ** the address of the next instruction to be coded.