From e995d2c226e2b65c5e40cd238415bdfeb0936e8c Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 13 Oct 2022 12:47:33 +0000 Subject: [PATCH 1/3] Proposed optimization to the IS NULL and NOT NULL operators that avoids loading the entire content of larges strings and BLOBs. Response to [forum:/info/3c08d4715dc05b00|forum post 3c08d4715dc05b00]. FossilOrigin-Name: 45f171565442f9fd6574fb93ae7abe83c168b20be68af42531bc55571450d3ab --- manifest | 21 ++++++++++++--------- manifest.uuid | 2 +- src/expr.c | 2 ++ src/pragma.c | 4 +--- src/vdbe.h | 1 + src/vdbeaux.c | 16 ++++++++++++++++ 6 files changed, 33 insertions(+), 13 deletions(-) diff --git a/manifest b/manifest index d95623c883..507552e771 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Updates\sto\sthe\sfuzzer\squery\sinvariant\schecker\s-\stracking\schanges\smade\nover\sin\sdbsqlfuzz. -D 2022-10-12T18:40:25.766 +C Proposed\soptimization\sto\sthe\sIS\sNULL\sand\sNOT\sNULL\soperators\sthat\savoids\nloading\sthe\sentire\scontent\sof\slarges\sstrings\sand\sBLOBs.\s\sResponse\sto\n[forum:/info/3c08d4715dc05b00|forum\spost\s3c08d4715dc05b00]. +D 2022-10-13T12:47:33.470 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -570,7 +570,7 @@ F src/date.c 94ce83b4cd848a387680a5f920c9018c16655db778c4d36525af0a0f34679ac5 F src/dbpage.c 5808e91bc27fa3981b028000f8fadfdc10ce9e59a34ce7dc4e035a69be3906ec F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d F src/delete.c 86573edae75e3d3e9a8b590d87db8e47222103029df4f3e11fa56044459b514e -F src/expr.c 1cbdd76eeedb729ea9060df03e3e6b74a302784a13bfa38794a8194f894641ea +F src/expr.c d199850a925665df7f8ac29fa938909f65a2bd32354aa206aa8c25fc74ff3d3d F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 722f20779f5342a787922deded3628d8c74b5249cab04098cf17ee2f2aaff002 F src/func.c 8f72e88cccdee22185133c10f96ccd61dc34c5ea4b1fa9a73c237ef59b2e64f1 @@ -613,7 +613,7 @@ F src/parse.y 8e67d820030d2655b9942ffe61c1e7e6b96cea2f2f72183533299393907d0564 F src/pcache.c f4268f7f73c6a3db12ce22fd25bc68dc42315d19599414ab1207d7cf32f79197 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc -F src/pragma.c 444f596c9e9123d19451ad762917f0f7545e4acecb10f67e09a19f01289cefce +F src/pragma.c 41430ca04735cc8e5d003bfd9315eadede3ec326e50805cc81bcf34e46601292 F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7 F src/prepare.c 1b02be0441eda4579471fea097f678effcbb77ef0c39ab3f703c837822bcd674 F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764 @@ -693,10 +693,10 @@ F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 0be191521ff6d2805995f4910f0b6231b42843678b2efdc1abecaf39929a673f F src/vacuum.c bb346170b0b54c6683bba4a5983aea40485597fdf605c87ec8bc2e199fe88cd8 F src/vdbe.c 4e51ba30edcdcec171fdb1db1133147ea1084d8b6842bc601b174e8a0e4b3b7f -F src/vdbe.h 64619af62603dc3c4f5ff6ff6d2c8f389abd667a29ce6007ed44bd22b3211cd0 +F src/vdbe.h 58675f47dcf3105bab182c3ad3726efd60ffd003e954386904ac9107d0d2b743 F src/vdbeInt.h 17b7461ffcf9ee760d1341731715a419f6b8c763089a7ece25c2e8098d702b3f F src/vdbeapi.c 1e8713d0b653acb43cd1bdf579c40e005c4844ea90f414f065946a83db3c27fb -F src/vdbeaux.c c719cebaffa75e166f16a405b3dee96e7150d60fc563ab2dea716b60c6a51312 +F src/vdbeaux.c 3468ba4e9910fc6659030ea1a3f523f3bdf16396dab28a836f7f36c27c5aa771 F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35 @@ -2034,8 +2034,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 368fa6b25bc803ded7c1a0184615980902657879370caec22ceea42496ec0566 -R b6417444abfe9dc882e90feaa0e7d85d +P 4ca16a304ad10fbb48f78b4384b347fe883e1a4f222f113ac981e89845c3e113 +R f35663338c50b8e03d89b8b5f5341f38 +T *branch * isnull-opt +T *sym-isnull-opt * +T -sym-trunk * U drh -Z 6e9d8b3a258c07649344995d3cb09455 +Z 5002c0678afa100b4df523686944d5c0 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index ca633fd6b3..97f10acb71 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4ca16a304ad10fbb48f78b4384b347fe883e1a4f222f113ac981e89845c3e113 \ No newline at end of file +45f171565442f9fd6574fb93ae7abe83c168b20be68af42531bc55571450d3ab \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index baa0fe6476..bceb5efb08 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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_NOTNULL==OP_NotNull ); testcase( op==TK_NOTNULL ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + sqlite3VdbeTypeofColumn(v, r1); sqlite3VdbeAddOp2(v, op, r1, dest); VdbeCoverageIf(v, op==TK_ISNULL); VdbeCoverageIf(v, op==TK_NOTNULL); @@ -5415,6 +5416,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ case TK_ISNULL: case TK_NOTNULL: { r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); + sqlite3VdbeTypeofColumn(v, r1); sqlite3VdbeAddOp2(v, op, r1, dest); testcase( op==TK_ISNULL ); VdbeCoverageIf(v, op==TK_ISNULL); testcase( op==TK_NOTNULL ); VdbeCoverageIf(v, op==TK_NOTNULL); diff --git a/src/pragma.c b/src/pragma.c index 7976f83c6f..7aea3dd2cb 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1791,9 +1791,7 @@ void sqlite3Pragma( || pTab->iPKey==mxCol) ) mxCol--; if( mxCol>=0 ){ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, mxCol, 3); - if( sqlite3VdbeGetLastOp(v)->opcode==OP_Column ){ - sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); - } + sqlite3VdbeTypeofColumn(v, 3); } if( !isQuick ){ diff --git a/src/vdbe.h b/src/vdbe.h index eb1445f1db..a244468b52 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -228,6 +228,7 @@ void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); void sqlite3VdbeChangeP5(Vdbe*, u16 P5); +void sqlite3VdbeTypeofColumn(Vdbe*, int); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr); int sqlite3VdbeChangeToNoop(Vdbe*, int addr); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8785e3b568..275ba6f770 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1155,6 +1155,22 @@ void sqlite3VdbeChangeP5(Vdbe *p, u16 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_TYPEOF flag to that +** opcode. +*/ +void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){ + if( p->nOp>0 ){ + VdbeOp *pOp = &p->aOp[p->nOp-1]; + if( pOp->opcode==OP_Column && pOp->p3==iDest ){ + pOp->p5 |= OPFLAG_TYPEOFARG; + } + }else{ + assert( p->db->mallocFailed ); + } +} + /* ** Change the P2 operand of instruction addr so that it points to ** the address of the next instruction to be coded. From bd1c634546dea473ed734a33b77ea1f54a202299 Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 13 Oct 2022 14:35:20 +0000 Subject: [PATCH 2/3] Adjust the implementation of sqlite3VdbeTypeofColumn() to make it easier to test (and slightly smaller). FossilOrigin-Name: 79fdd021df256c6a2b9973fd6bf8e52ffaaf4d369d40489b8395ac97880b1325 --- manifest | 15 ++++++--------- manifest.uuid | 2 +- src/vdbeaux.c | 10 +++------- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/manifest b/manifest index 507552e771..b6c85bb266 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Proposed\soptimization\sto\sthe\sIS\sNULL\sand\sNOT\sNULL\soperators\sthat\savoids\nloading\sthe\sentire\scontent\sof\slarges\sstrings\sand\sBLOBs.\s\sResponse\sto\n[forum:/info/3c08d4715dc05b00|forum\spost\s3c08d4715dc05b00]. -D 2022-10-13T12:47:33.470 +C Adjust\sthe\simplementation\sof\ssqlite3VdbeTypeofColumn()\sto\smake\sit\seasier\nto\stest\s(and\sslightly\ssmaller). +D 2022-10-13T14:35:20.191 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -696,7 +696,7 @@ F src/vdbe.c 4e51ba30edcdcec171fdb1db1133147ea1084d8b6842bc601b174e8a0e4b3b7f F src/vdbe.h 58675f47dcf3105bab182c3ad3726efd60ffd003e954386904ac9107d0d2b743 F src/vdbeInt.h 17b7461ffcf9ee760d1341731715a419f6b8c763089a7ece25c2e8098d702b3f F src/vdbeapi.c 1e8713d0b653acb43cd1bdf579c40e005c4844ea90f414f065946a83db3c27fb -F src/vdbeaux.c 3468ba4e9910fc6659030ea1a3f523f3bdf16396dab28a836f7f36c27c5aa771 +F src/vdbeaux.c e22cf8b85b8b0b8dd585e46f13a4db24f42053a549685e79907d7c0812f00fbd F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd F src/vdbemem.c 6cfed43758d57b6e3b99d9cdedfeccd86e45a07e427b22d8487cbdbebb6c522a F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35 @@ -2034,11 +2034,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 4ca16a304ad10fbb48f78b4384b347fe883e1a4f222f113ac981e89845c3e113 -R f35663338c50b8e03d89b8b5f5341f38 -T *branch * isnull-opt -T *sym-isnull-opt * -T -sym-trunk * +P 45f171565442f9fd6574fb93ae7abe83c168b20be68af42531bc55571450d3ab +R 0e1d021509719a6dc58294a46bab294e U drh -Z 5002c0678afa100b4df523686944d5c0 +Z b79894d44bbaa33297da5bbb579b93c8 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 97f10acb71..414ca045b4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -45f171565442f9fd6574fb93ae7abe83c168b20be68af42531bc55571450d3ab \ No newline at end of file +79fdd021df256c6a2b9973fd6bf8e52ffaaf4d369d40489b8395ac97880b1325 \ No newline at end of file diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 275ba6f770..45e573535e 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1161,13 +1161,9 @@ void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){ ** opcode. */ void sqlite3VdbeTypeofColumn(Vdbe *p, int iDest){ - if( p->nOp>0 ){ - VdbeOp *pOp = &p->aOp[p->nOp-1]; - if( pOp->opcode==OP_Column && pOp->p3==iDest ){ - pOp->p5 |= OPFLAG_TYPEOFARG; - } - }else{ - assert( p->db->mallocFailed ); + VdbeOp *pOp = sqlite3VdbeGetLastOp(p); + if( pOp->p3==iDest && pOp->opcode==OP_Column ){ + pOp->p5 |= OPFLAG_TYPEOFARG; } } From eddfa9840eac8a15ac02db65b96d3db85f6c8f4a Mon Sep 17 00:00:00 2001 From: drh <> Date: Thu, 13 Oct 2022 14:54:32 +0000 Subject: [PATCH 3/3] Improvements to the description of the OPFLAG_TYPEOFARG option to OP_Column. FossilOrigin-Name: 5e9c67ba18b701aabbb0546acdfc532c9e8f0d27fb0a2c899415a5c47096c90b --- manifest | 12 ++++++------ manifest.uuid | 2 +- src/vdbe.c | 10 ++++++---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/manifest b/manifest index b6c85bb266..3fd16f1266 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Adjust\sthe\simplementation\sof\ssqlite3VdbeTypeofColumn()\sto\smake\sit\seasier\nto\stest\s(and\sslightly\ssmaller). -D 2022-10-13T14:35:20.191 +C Improvements\sto\sthe\sdescription\sof\sthe\sOPFLAG_TYPEOFARG\soption\sto\sOP_Column. +D 2022-10-13T14:54:32.397 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -692,7 +692,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c 0be191521ff6d2805995f4910f0b6231b42843678b2efdc1abecaf39929a673f F src/vacuum.c bb346170b0b54c6683bba4a5983aea40485597fdf605c87ec8bc2e199fe88cd8 -F src/vdbe.c 4e51ba30edcdcec171fdb1db1133147ea1084d8b6842bc601b174e8a0e4b3b7f +F src/vdbe.c 581496d84d7ce5b4f7302f14b3bc5271bbcef5dce28ce97c505297340e0c46e3 F src/vdbe.h 58675f47dcf3105bab182c3ad3726efd60ffd003e954386904ac9107d0d2b743 F src/vdbeInt.h 17b7461ffcf9ee760d1341731715a419f6b8c763089a7ece25c2e8098d702b3f F src/vdbeapi.c 1e8713d0b653acb43cd1bdf579c40e005c4844ea90f414f065946a83db3c27fb @@ -2034,8 +2034,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 45f171565442f9fd6574fb93ae7abe83c168b20be68af42531bc55571450d3ab -R 0e1d021509719a6dc58294a46bab294e +P 79fdd021df256c6a2b9973fd6bf8e52ffaaf4d369d40489b8395ac97880b1325 +R f513ee84e2c3c752a45dcdac513b8ce6 U drh -Z b79894d44bbaa33297da5bbb579b93c8 +Z 5b4f99a755b8cb54cd55294bc14ffa4e # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 414ca045b4..fc10115bbe 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -79fdd021df256c6a2b9973fd6bf8e52ffaaf4d369d40489b8395ac97880b1325 \ No newline at end of file +5e9c67ba18b701aabbb0546acdfc532c9e8f0d27fb0a2c899415a5c47096c90b \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index b4a96468f1..f8878db316 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2781,10 +2781,12 @@ case OP_Offset: { /* out3 */ ** if the P4 argument is a P4_MEM use the value of the P4 argument as ** the result. ** -** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then -** the result is guaranteed to only be used as the argument of a length() -** or typeof() function, respectively. The loading of large blobs can be -** skipped for length() and all content loading can be skipped for typeof(). +** If the OPFLAG_LENGTHARG bit is set in P5 then the result is guaranteed +** to only be used by the length() function or the equivalent. The content +** of large blobs is not loaded, thus saving CPU cycles. If the +** 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: { u32 p2; /* column number to retrieve */