-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
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
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
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
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
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
-97c9248b3b81facce569bfa3fb405d44a1d1041e87132e8f649458c95620ccb2
\ No newline at end of file
+4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8
\ No newline at end of file
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;
&& 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;
}
/*
** 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[] = {
}
/*
+** 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;
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{
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);
}
}
/* 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 */
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 */
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
**
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
**
** 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;
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++){