From: drh Date: Sat, 26 Oct 2019 17:08:06 +0000 (+0000) Subject: Performance optimization on sqlite3GenerateConstraintChecks() - bypass the X-Git-Tag: version-3.31.0~377 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cbda9c7ac79f8751e18fba943e30fd67f8c68b02;p=thirdparty%2Fsqlite.git Performance optimization on sqlite3GenerateConstraintChecks() - bypass the loop that checks each column for NOT NULL constraints if it is known in advance that the table has no NOT NULL constraints. FossilOrigin-Name: e3c3f4d7872f431a95627d52553101388c1e39458cc7e7f93fc81255f49a89a5 --- diff --git a/manifest b/manifest index 32e13a0efb..9eb5fce1f1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Clarify\ssome\scomments\sand\sadd\sassert()\sand\stestcase()\smacros\sto\sthe\nreplace-trigger\srecheck\slogic\sfor\sticket\s[c1e19e12046d23fe] -D 2019-10-26T16:38:49.916 +C Performance\soptimization\son\ssqlite3GenerateConstraintChecks()\s-\sbypass\sthe\nloop\sthat\schecks\seach\scolumn\sfor\sNOT\sNULL\sconstraints\sif\sit\sis\sknown\sin\nadvance\sthat\sthe\stable\shas\sno\sNOT\sNULL\sconstraints. +D 2019-10-26T17:08:06.316 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -470,7 +470,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c 12e251f8c3eaad05e6d0db94772bf779b3a644e18d884025da6bcbc98cad1d22 F src/btree.h f27a33c49280209a93385e218306c4ee5f46ba8d7649d2f81a7166b282232484 F src/btreeInt.h 91806f01fd1145a9a86ba3042f25c38d8faf6002701bf5e780742cf88bcff437 -F src/build.c 0e558ef847ccc4b6aa38dee44cde9d9df46e953b0a66e4fa4376265824955fe3 +F src/build.c 2e17f27da8ff7bb52cd23dbd6a8c7269babf11bb1beae08e470c5b0f4b077801 F src/callback.c 88615dfc0a82167b65b452b4b305dbf86be77200b3343c6ffc6d03e92a01d181 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251 @@ -487,7 +487,7 @@ F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c 52b5fae35661c3b723c4c51000bc071d7eca5cf803ceb63752527db62134ad5f +F src/insert.c 09e64dd9394a06bb25e54180312f16932c98643b53f576a7dd3b9344a635cf2c F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 4ddc65ae13c0d93db0ceedc8b14a28c8c260513448b0eb8c5a2ac375e3b6a85d F src/main.c 3e01f6a1c96643381b5f9d79e4ff7f2520bc5712197746fb0852283e78cccf66 @@ -1848,7 +1848,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 070b49825c5f87cce15be4b758f0dfdd65226ec379465ca527a18706a1f3b8f4 -R 1028cc5a00baf8569b464c2a7604c8c5 +P 8c0042bd5ccd83f8794d19cbb1ec7564584f0dce54bfebc0ada00b836aca065f +R ea2c4191b4b2904c1eb46d03fcd394de U drh -Z 8bf83f381e575a0d62d743fe518a1706 +Z 5817472d3119aa1dc0ce67b1f895a616 diff --git a/manifest.uuid b/manifest.uuid index 4803638fa3..ea0e6e6048 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -8c0042bd5ccd83f8794d19cbb1ec7564584f0dce54bfebc0ada00b836aca065f \ No newline at end of file +e3c3f4d7872f431a95627d52553101388c1e39458cc7e7f93fc81255f49a89a5 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 22a57a240b..9adc4d5934 100644 --- a/src/build.c +++ b/src/build.c @@ -1836,6 +1836,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ pTab->aCol[i].notNull = OE_Abort; } } + pTab->tabFlags |= TF_HasNotNull; } /* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY diff --git a/src/insert.c b/src/insert.c index 7e7fb0847d..215aafb321 100644 --- a/src/insert.c +++ b/src/insert.c @@ -1352,64 +1352,67 @@ void sqlite3GenerateConstraintChecks( /* Test all NOT NULL constraints. */ - for(i=0; iiPKey ){ - continue; /* ROWID is never NULL */ - } - if( aiChng && aiChng[i]<0 ){ - /* Don't bother checking for NOT NULL on columns that do not change */ - continue; - } - onError = pTab->aCol[i].notNull; - if( onError==OE_None ) continue; /* This column is allowed to be NULL */ - if( overrideError!=OE_Default ){ - onError = overrideError; - }else if( onError==OE_Default ){ - onError = OE_Abort; - } - if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ - onError = OE_Abort; - } - assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail - || onError==OE_Ignore || onError==OE_Replace ); - addr1 = 0; - switch( onError ){ - case OE_Replace: { - assert( onError==OE_Replace ); - addr1 = sqlite3VdbeMakeLabel(pParse); - sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1); - VdbeCoverage(v); - sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i); - sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1); - VdbeCoverage(v); + if( pTab->tabFlags & TF_HasNotNull ){ + for(i=0; iaCol[i].notNull; + if( onError==OE_None ) continue; /* No NOT NULL on this column */ + assert( pTab->tabFlags & TF_HasNotNull ); + if( i==pTab->iPKey ){ + continue; /* ROWID is never NULL */ + } + if( aiChng && aiChng[i]<0 ){ + /* Don't bother checking for NOT NULL on columns that do not change */ + continue; + } + if( overrideError!=OE_Default ){ + onError = overrideError; + }else if( onError==OE_Default ){ onError = OE_Abort; - /* Fall through into the OE_Abort case to generate code that runs - ** if both the input and the default value are NULL */ } - case OE_Abort: - sqlite3MayAbort(pParse); - /* Fall through */ - case OE_Rollback: - case OE_Fail: { - char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, - pTab->aCol[i].zName); - sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError, - regNewData+1+i); - sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); - sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); - VdbeCoverage(v); - if( addr1 ) sqlite3VdbeResolveLabel(v, addr1); - break; + if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){ + onError = OE_Abort; } - default: { - assert( onError==OE_Ignore ); - sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest); - VdbeCoverage(v); - break; + assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail + || onError==OE_Ignore || onError==OE_Replace ); + addr1 = 0; + switch( onError ){ + case OE_Replace: { + assert( onError==OE_Replace ); + addr1 = sqlite3VdbeMakeLabel(pParse); + sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1); + VdbeCoverage(v); + sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i); + sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1); + VdbeCoverage(v); + onError = OE_Abort; + /* Fall through into the OE_Abort case to generate code that runs + ** if both the input and the default value are NULL */ + } + case OE_Abort: + sqlite3MayAbort(pParse); + /* Fall through */ + case OE_Rollback: + case OE_Fail: { + char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName, + pTab->aCol[i].zName); + sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, + onError, regNewData+1+i); + sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC); + sqlite3VdbeChangeP5(v, P5_ConstraintNotNull); + VdbeCoverage(v); + if( addr1 ) sqlite3VdbeResolveLabel(v, addr1); + break; + } + default: { + assert( onError==OE_Ignore ); + sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest); + VdbeCoverage(v); + break; + } } } } - + /* Test all CHECK constraints */ #ifndef SQLITE_OMIT_CHECK