Improved comments. Fewer opcodes for integrity_check on strict tables.
FossilOrigin-Name: 4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8
This commit is contained in:
parent
9e1209d111
commit
71c770fbda
20
manifest
20
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
|
||||
|
@ -1 +1 @@
|
||||
97c9248b3b81facce569bfa3fb405d44a1d1041e87132e8f649458c95620ccb2
|
||||
4ee57fb588b41ab76649c605f57c7bcf5b7b638435af458d69f69a8ccbb121e8
|
12
src/build.c
12
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;
|
||||
}
|
||||
|
12
src/global.c
12
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[] = {
|
||||
|
44
src/insert.c
44
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);
|
||||
}
|
||||
}
|
||||
|
21
src/pragma.c
21
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; 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 */
|
||||
|
43
src/vdbe.c
43
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:
|
||||
**
|
||||
** <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++){
|
||||
|
Loading…
Reference in New Issue
Block a user