Improved comments. Fewer opcodes for integrity_check on strict tables.

FossilOrigin-Name: 4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8
This commit is contained in:
drh 2021-08-19 16:29:33 +00:00
parent 9e1209d111
commit 71c770fbda
7 changed files with 104 additions and 50 deletions

View File

@ -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

View File

@ -1 +1 @@
97c9248b3b81facce569bfa3fb405d44a1d1041e87132e8f649458c95620ccb2
4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8

View 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;
}

View 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[] = {

View 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);
}
}

View 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 */

View 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++){