From: drh <> Date: Thu, 19 Aug 2021 16:29:33 +0000 (+0000) Subject: Improved comments. Fewer opcodes for integrity_check on strict tables. X-Git-Tag: version-3.37.0~276^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=71c770fbda6683780c314ad5ebfa3be3c0c2c718;p=thirdparty%2Fsqlite.git Improved comments. Fewer opcodes for integrity_check on strict tables. FossilOrigin-Name: 4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8 --- diff --git a/manifest b/manifest index 961317c00d..faa664cdb0 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sPRAGMA\sintegrity_check\sso\sthat\sit\sverifies\sthe\sdatatype\sof\nall\scolumns\sin\sSTRICT\stables. -D 2021-08-19T02:58:15.725 +C Improved\scomments.\s\sFewer\sopcodes\sfor\sintegrity_check\son\sstrict\stables. +D 2021-08-19T16:29:33.914 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -488,7 +488,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c e204a9c8fb4fe5dbb910a863ba487f4af9b5c501254ec4ccbfcdd6b1f65b7fb4 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22 F src/btreeInt.h 7bc15a24a02662409ebcd6aeaa1065522d14b7fda71573a2b0568b458f514ae0 -F src/build.c c55bec6a37b3b521c10ac6ae2f73328e3a49c12a1b8c87ca151d81c5e1095142 +F src/build.c 4f58fcdf5b8a7f273edd2fb07a8b7afa91f34cea4396d9b5fc438cbfe1c6b87e F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c 8159d5f706551861c18ec6c8f6bdf105e15ea00367f05d9ab65d31a1077facc1 @@ -500,12 +500,12 @@ F src/expr.c e98375fc63552cc8cdd36a41bdca3039cb603d9fe67abd9c9f40adae8405fbc5 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 1905af1821b88321e1bb9d6a69e704495b6844a9b6c29398d40117cc251e893c F src/func.c c224240cbc97fa5e9c4fe9acb128716cb835ca045532bca6951b7c45b020c56c -F src/global.c 436d4819e48d0272ef1ed72bd5fe44fed06ff5f83f54eebe8c74123771f7ad0b +F src/global.c 24ba3b3e88dd2a70389388c3bc46fd55a44bfae3c44f76dad1ca00556f1c769a F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19 F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38 F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144 F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71 -F src/insert.c dbf6ed6c070661691a50ec135bff47700a01c71ce9987819860c3a992dda8b95 +F src/insert.c d2a3f90a4bdfb98c8f1dc30b6449e400acec689d731ec408324466342302232b F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa F src/loadext.c 0aa9e7f08e168e3874cb54984408e3976dafdf5616d511952c425b5ac088ea3e F src/main.c aab8cefb6bfbdbecc53fd19058fa053c0c5e591b2e5067d883ef999d019dcd29 @@ -537,7 +537,7 @@ F src/parse.y 86aa016b281f61d7664dd8cb7808cab8114d14cfaf362a9b9fc9ead8f33546b7 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65 -F src/pragma.c b6ba4aa11ad3e21a07cfb7be5dad4bdae7e733dd4f91e3f586dfc0ea703c0178 +F src/pragma.c c482a8d529d91e48ebdd5aa3bbbc15edd7f1cd4f4858613be9146866741ad2b8 F src/pragma.h a11b4798f9c49f156f130e1f7041a9fcc9d316a64f3501b6013acdd2e4c6f549 F src/prepare.c 0d53d20532aada295c1690792a125adbd6435f5ce703ff0adf1b9b3605238b67 F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b @@ -616,7 +616,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0 F src/util.c eafc8cfeb66fdbf8839922d13019b7882f242ac31b383e3451aab7744c54df3e F src/vacuum.c 454973a59fb20bb982efc2df568a098616db6328a0491b6e84e2e07f7333db45 -F src/vdbe.c db2033468624757c7560456d0935d7bac6732c626b193ed865da93a4ee6bd3e2 +F src/vdbe.c d2e395271e57203b1b929bfaa8ea8d8305fcf12c1d251954adee9bd492272060 F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5 @@ -1922,7 +1922,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 5efdf9acad9d54783f5134b7e9338f44336862d87dc324d315b8d55e44df1923 -R b81ba137d5fbe2c27e5bf73bf8e1c01f +P 97c9248b3b81facce569bfa3fb405d44a1d1041e87132e8f649458c95620ccb2 +R f9caa21161816acea3d561e69ac639dc U drh -Z cb07934ea9a1c0a07dfc699c730ff260 +Z 247f6cbc04db0661f0c32539094ce344 diff --git a/manifest.uuid b/manifest.uuid index 7844f9394f..9e6477632c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -97c9248b3b81facce569bfa3fb405d44a1d1041e87132e8f649458c95620ccb2 \ No newline at end of file +4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8 \ No newline at end of file diff --git a/src/build.c b/src/build.c index bf9746de04..783b9b7ec5 100644 --- a/src/build.c +++ b/src/build.c @@ -2592,7 +2592,15 @@ void sqlite3EndTable( if( p->tnum==1 ) p->tabFlags |= TF_Readonly; } - /* Do not allow COLTYPE_CUSTOM in STRICT mode */ + /* Special processing for tables that include the STRICT keyword: + ** + ** * Do not allow custom column datatypes. Every column must have + ** a datatype that is one of INT, INTEGER, REAL, TEXT, or BLOB. + ** + ** * If a PRIMARY KEY is defined, other than the INTEGER PRIMARY KEY, + ** then all columns of the PRIMARY KEY must have a NOT NULL + ** constraint. + */ if( tabOpts & TF_Strict ){ int ii; p->tabFlags |= TF_Strict; @@ -2609,8 +2617,6 @@ void sqlite3EndTable( && p->iPKey!=ii && pCol->notNull == OE_None ){ - /* Primary key columns other than the IPK may not be NULL - ** in strict mode */ pCol->notNull = OE_Abort; p->tabFlags |= TF_HasNotNull; } diff --git a/src/global.c b/src/global.c index 98793fbd3f..091310c934 100644 --- a/src/global.c +++ b/src/global.c @@ -351,6 +351,18 @@ const char sqlite3StrBINARY[] = "BINARY"; /* ** Standard typenames. These names must match the COLTYPE_* definitions. ** Adjust the SQLITE_N_STDTYPE value if adding or removing entries. +** +** sqlite3StdType[] The actual names of the datatypes. +** +** sqlite3StdTypeLen[] The length (in bytes) of each entry +** in sqlite3StdType[]. +** +** sqlite3StdTypeAffinity[] The affinity associated with each entry +** in sqlite3StdType[]. +** +** sqlite3StdTypeMap[] The type value (as returned from +** sqlite3_column_type() or sqlite3_value_type()) +** for each entry in sqlite3StdType[]. */ const unsigned char sqlite3StdTypeLen[] = { 4, 3, 7, 4, 4 }; const char sqlite3StdTypeAffinity[] = { diff --git a/src/insert.c b/src/insert.c index 1148257ad2..9617e54e7c 100644 --- a/src/insert.c +++ b/src/insert.c @@ -110,24 +110,44 @@ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ } /* +** Make changes to the evolving bytecode to do affinity transformations +** of values that are about to be gathered into a row for table pTab. +** +** For ordinary (legacy, non-strict) tables: +** ----------------------------------------- +** ** Compute the affinity string for table pTab, if it has not already been ** computed. As an optimization, omit trailing SQLITE_AFF_BLOB affinities. ** -** If the affinity exists (if it is not entirely SQLITE_AFF_BLOB values) and -** if iReg>0 then code an OP_Affinity opcode that will set the affinities -** for register iReg and following. Or if affinities exists and iReg==0, +** If the affinity string is empty (because it was all SQLITE_AFF_BLOB entries +** which were then optimized out) then this routine becomes a no-op. +** +** Otherwise if iReg>0 then code an OP_Affinity opcode that will set the +** affinities for register iReg and following. Or if iReg==0, ** then just set the P4 operand of the previous opcode (which should be ** an OP_MakeRecord) to the affinity string. ** ** A column affinity string has one character per column: ** -** Character Column affinity -** ------------------------------ -** 'A' BLOB -** 'B' TEXT -** 'C' NUMERIC -** 'D' INTEGER -** 'E' REAL +** Character Column affinity +** --------- --------------- +** 'A' BLOB +** 'B' TEXT +** 'C' NUMERIC +** 'D' INTEGER +** 'E' REAL +** +** For STRICT tables: +** ------------------ +** +** Generate an appropropriate OP_TypeCheck opcode that will verify the +** datatypes against the column definitions in pTab. If iReg==0, that +** means an OP_MakeRecord opcode has already been generated and should be +** the last opcode generated. The new OP_TypeCheck needs to be inserted +** before the OP_MakeRecord. The new OP_TypeCheck should use the same +** register set as the OP_MakeRecord. If iReg>0 then register iReg is +** the first of a series of registers that will form the new record. +** Apply the type checking to that array of registers. */ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ int i, j; @@ -140,6 +160,8 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ VdbeOp *pPrev; sqlite3VdbeAppendP4(v, pTab, P4_TABLE); pPrev = sqlite3VdbeGetOp(v, -1); + assert( pPrev!=0 ); + assert( pPrev->opcode==OP_MakeRecord || sqlite3VdbeDb(v)->mallocFailed ); pPrev->opcode = OP_TypeCheck; sqlite3VdbeAddOp3(v, OP_MakeRecord, pPrev->p1, pPrev->p2, pPrev->p3); }else{ @@ -175,6 +197,8 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ if( iReg ){ sqlite3VdbeAddOp4(v, OP_Affinity, iReg, i, 0, zColAff, i); }else{ + assert( sqlite3VdbeGetOp(v, -1)->opcode==OP_MakeRecord + || sqlite3VdbeDb(v)->mallocFailed ); sqlite3VdbeChangeP4(v, -1, zColAff, i); } } diff --git a/src/pragma.c b/src/pragma.c index 39095d82d7..dd1aaf9784 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -1675,6 +1675,7 @@ void sqlite3Pragma( /* Sanity check on record header decoding */ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3); sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); + VdbeComment((v, "(right-most column)")); } /* Verify that all NOT NULL columns really are NOT NULL. At the ** same time verify the type of the content of STRICT tables */ @@ -1682,37 +1683,37 @@ void sqlite3Pragma( for(j=0; jnCol; j++){ char *zErr; Column *pCol = pTab->aCol + j; - int endLabel; + int doError, jmp2; if( j==pTab->iPKey ) continue; if( pCol->notNull==0 && !bStrict ) continue; - endLabel = bStrict ? sqlite3VdbeMakeLabel(pParse) : 0; + doError = bStrict ? sqlite3VdbeMakeLabel(pParse) : 0; sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3); if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG); } if( pCol->notNull ){ - int jmp2; jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v); zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, pCol->zCnName); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); - integrityCheckResultRow(v); - if( bStrict ) sqlite3VdbeGoto(v, endLabel); + if( bStrict ){ + sqlite3VdbeGoto(v, doError); + }else{ + integrityCheckResultRow(v); + } sqlite3VdbeJumpHere(v, jmp2); } if( pTab->tabFlags & TF_Strict ){ - if( pCol->notNull==0 ){ - sqlite3VdbeAddOp2(v, OP_IsNull, 3, endLabel); VdbeCoverage(v); - } - sqlite3VdbeAddOp3(v, OP_IfType, 3, endLabel, + jmp2 = sqlite3VdbeAddOp3(v, OP_IsNullOrType, 3, 0, sqlite3StdTypeMap[pCol->eCType-1]); VdbeCoverage(v); zErr = sqlite3MPrintf(db, "non-%s value in %s.%s", sqlite3StdType[pCol->eCType-1], pTab->zName, pTab->aCol[j].zCnName); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); + sqlite3VdbeResolveLabel(v, doError); integrityCheckResultRow(v); - sqlite3VdbeResolveLabel(v, endLabel); + sqlite3VdbeJumpHere(v, jmp2); } } /* Verify CHECK constraints */ diff --git a/src/vdbe.c b/src/vdbe.c index 01da0a9568..690687a059 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2502,6 +2502,22 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */ break; } +/* Opcode: IsNullOrType P1 P2 P3 * * +** Synopsis: if typeof(r[P1]) IN (P3,5) goto P2 +** +** Jump to P2 if the value in register P1 is NULL or has a datatype P3. +** P3 is an integer which should be one of SQLITE_INTEGER, SQLITE_FLOAT, +** SQLITE_BLOB, SQLITE_NULL, or SQLITE_TEXT. +*/ +case OP_IsNullOrType: { /* jump, in1 */ + int doTheJump; + pIn1 = &aMem[pOp->p1]; + doTheJump = (pIn1->flags & MEM_Null)!=0 || sqlite3_value_type(pIn1)==pOp->p3; + VdbeBranchTaken( doTheJump, 2); + if( doTheJump ) goto jump_to_p2; + break; +} + /* Opcode: ZeroOrNull P1 P2 P3 * * ** Synopsis: r[P2] = 0 OR NULL ** @@ -2534,22 +2550,6 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ break; } -/* Opcode: IfType P1 P2 P3 * * -** Synopsis: if typeof(r[P1])!=P3 goto P2 -** -** Jump to P2 if the value in register has a datatype given by P3. -** P3 is an integer which should be one of SQLITE_INTEGER, SQLITE_FLOAT, -** SQLITE_BLOB, SQLITE_NULL, or SQLITE_TEXT. -*/ -case OP_IfType: { /* jump, in1 */ - int doTheJump; - pIn1 = &aMem[pOp->p1]; - doTheJump = sqlite3_value_type(pIn1)==pOp->p3; - VdbeBranchTaken( doTheJump, 2); - if( doTheJump ) goto jump_to_p2; - break; -} - /* Opcode: IfNullRow P1 P2 P3 * * ** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2 ** @@ -2896,6 +2896,16 @@ op_column_corrupt: ** This opcode is similar to OP_Affinity except that this opcode ** forces the register type to the Table column type. This is used ** to implement "strict affinity". +** +** Preconditions: +** +** +** +** If any precondition is false, an assertion fault occurs. */ case OP_TypeCheck: { Table *pTab; @@ -2905,6 +2915,7 @@ case OP_TypeCheck: { assert( pOp->p4type==P4_TABLE ); pTab = pOp->p4.pTab; assert( pTab->tabFlags & TF_Strict ); + assert( pTab->nNVCol==pOp->p2 ); aCol = pTab->aCol; pIn1 = &aMem[pOp->p1]; for(i=0; inCol; i++){