]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improved comments. Fewer opcodes for integrity_check on strict tables.
authordrh <>
Thu, 19 Aug 2021 16:29:33 +0000 (16:29 +0000)
committerdrh <>
Thu, 19 Aug 2021 16:29:33 +0000 (16:29 +0000)
FossilOrigin-Name: 4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8

manifest
manifest.uuid
src/build.c
src/global.c
src/insert.c
src/pragma.c
src/vdbe.c

index 961317c00d0d5e705564fd13337c1bcf56e2742c..faa664cdb0b474782fae5008806a3107963750ae 100644 (file)
--- 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
index 7844f9394f1ebd82d58985fe1f25486051f6d84d..9e6477632cfa7470e4be98d168994e88c8b04b01 100644 (file)
@@ -1 +1 @@
-97c9248b3b81facce569bfa3fb405d44a1d1041e87132e8f649458c95620ccb2
\ No newline at end of file
+4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8
\ No newline at end of file
index bf9746de049668a79db221598036263804c51341..783b9b7ec54b6de77c0954846ffdbee5b8c5dbdf 100644 (file)
@@ -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;
       }
index 98793fbd3fcb040ff3a2bb635f7a4510cba6b729..091310c9346fa0cf60af371794e921fed40980f2 100644 (file)
@@ -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[] = {
index 1148257ad26f2d8e59b1d6842fbde4c3c58b553e..9617e54e7c1fde3a8a8e2bd807c041d5304107a0 100644 (file)
@@ -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);
     }
   }
index 39095d82d75b604b97f77688a6a4d207162b0573..dd1aaf97842140414e725cda68506e95a69f632a 100644 (file)
@@ -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; j<pTab->nCol; 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 */
index 01da0a956836c8ef064d0de503903ee580a84475..690687a05994b813b888b458366e5dd5e9055d86 100644 (file)
@@ -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:
+**
+** <ul>
+** <li> P2 should be the number of non-virtual columns in the
+**      table of P4.
+** <li> Table P4 should be a STRICT table.
+** </ul>
+**
+** 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; i<pTab->nCol; i++){