-C STRICT\stables\srequire\sall\sfields\sof\sthe\sPRIMARY\sKEY\sto\sbe\sNOT\sNULL.
-D 2021-08-19T00:24:43.029
+C Enhance\sPRAGMA\sintegrity_check\sso\sthat\sit\sverifies\sthe\sdatatype\sof\nall\scolumns\sin\sSTRICT\stables.
+D 2021-08-19T02:58:15.725
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 1905af1821b88321e1bb9d6a69e704495b6844a9b6c29398d40117cc251e893c
F src/func.c c224240cbc97fa5e9c4fe9acb128716cb835ca045532bca6951b7c45b020c56c
-F src/global.c 5eba017ebbd887e2365e6e6e815e1619e41406b8946d17594e94116174787df5
+F src/global.c 436d4819e48d0272ef1ed72bd5fe44fed06ff5f83f54eebe8c74123771f7ad0b
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 9d56a9079d523b648774c1784b74b89bd93fac7b365210157482e4319a468f38
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
-F src/pragma.c af0f43789545622fd5377d71f6d4c0e7c9b9295a3f5d5b1242e4032d38ca12b5
+F src/pragma.c b6ba4aa11ad3e21a07cfb7be5dad4bdae7e733dd4f91e3f586dfc0ea703c0178
F src/pragma.h a11b4798f9c49f156f130e1f7041a9fcc9d316a64f3501b6013acdd2e4c6f549
F src/prepare.c 0d53d20532aada295c1690792a125adbd6435f5ce703ff0adf1b9b3605238b67
F src/printf.c 78fabb49b9ac9a12dd1c89d744abdc9b67fd3205e62967e158f78b965a29ec4b
F src/sqlite.h.in 4e977a5e2ed1a9e8987ff65a2cab5f99a4298ebf040ea5ff636e1753339ff45a
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
-F src/sqliteInt.h 732ef4ade4ea3e95ddc0a6be657c5f9eb1e4b8ede3105395fe0161c15fab9214
+F src/sqliteInt.h a0e00a52b90f236c77fd0c0b839cc091d9926aca7627eb6ad8cf3f55a9847a71
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c eafc8cfeb66fdbf8839922d13019b7882f242ac31b383e3451aab7744c54df3e
F src/vacuum.c 454973a59fb20bb982efc2df568a098616db6328a0491b6e84e2e07f7333db45
-F src/vdbe.c 0e70bef8e65fc217beb7909235502ce132d231fb656554205e0c13927b4140d1
+F src/vdbe.c db2033468624757c7560456d0935d7bac6732c626b193ed865da93a4ee6bd3e2
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
F src/vdbeInt.h 38206c8dd6b60ff03d9fd4f626b1b4fd0eef7cdc44f2fc2c1973b0f932a3f26b
F src/vdbeapi.c aa5aaf2c37676b83af5724c6cd8207a3064ed46a217fd180957f75ac84f7a2a5
F test/stmt.test 54ed2cc0764bf3e48a058331813c3dbd19fc1d0827c3d8369914a5d8f564ec75
F test/stmtvtab1.test 6873dfb24f8e79cbb5b799b95c2e4349060eb7a3b811982749a84b359468e2d5
F test/strict1.test dab7a84f5445e696beb3e2eedda9b3a28fb16bf3092be1917b3f1a6163916197
+F test/strict2.test fe1928b3768f51b39774d753ac7e71727718d1c3305eead0e5ea60f75e9e6b4c
F test/subjournal.test 8d4e2572c0ee9a15549f0d8e40863161295107e52f07a3e8012a2e1fdd093c49
F test/subquery.test d7268d193dd33d5505df965399d3a594e76ae13f
F test/subquery2.test 90cf944b9de8204569cf656028391e4af1ccc8c0cc02d4ef38ee3be8de1ffb12
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 7ee01ee47da247a80bcf16f88eb187b8c0928024536435ed20797a1a90495511
-R 9431b5ba9e76c466e3043738fddec247
+P 5efdf9acad9d54783f5134b7e9338f44336862d87dc324d315b8d55e44df1923
+R b81ba137d5fbe2c27e5bf73bf8e1c01f
U drh
-Z 0e5e6ca613f5601fc51663462528d032
+Z cb07934ea9a1c0a07dfc699c730ff260
-5efdf9acad9d54783f5134b7e9338f44336862d87dc324d315b8d55e44df1923
\ No newline at end of file
+97c9248b3b81facce569bfa3fb405d44a1d1041e87132e8f649458c95620ccb2
\ No newline at end of file
SQLITE_AFF_REAL,
SQLITE_AFF_TEXT
};
+const char sqlite3StdTypeMap[] = {
+ SQLITE_BLOB,
+ SQLITE_INTEGER,
+ SQLITE_INTEGER,
+ SQLITE_FLOAT,
+ SQLITE_TEXT
+};
const char *sqlite3StdType[] = {
"BLOB",
"INT",
int loopTop;
int iDataCur, iIdxCur;
int r1 = -1;
+ int bStrict;
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
if( pObjTab && pObjTab!=pTab ) continue;
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
- /* Verify that all NOT NULL columns really are NOT NULL */
+ /* Verify that all NOT NULL columns really are NOT NULL. At the
+ ** same time verify the type of the content of STRICT tables */
+ bStrict = (pTab->tabFlags & TF_Strict)!=0;
for(j=0; j<pTab->nCol; j++){
char *zErr;
- int jmp2;
+ Column *pCol = pTab->aCol + j;
+ int endLabel;
if( j==pTab->iPKey ) continue;
- if( pTab->aCol[j].notNull==0 ) continue;
+ if( pCol->notNull==0 && !bStrict ) continue;
+ endLabel = bStrict ? sqlite3VdbeMakeLabel(pParse) : 0;
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
}
- jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
- zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
- pTab->aCol[j].zCnName);
- sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
- integrityCheckResultRow(v);
- sqlite3VdbeJumpHere(v, jmp2);
+ 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);
+ 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,
+ 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);
+ integrityCheckResultRow(v);
+ sqlite3VdbeResolveLabel(v, endLabel);
+ }
}
/* Verify CHECK constraints */
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
extern const char sqlite3StrBINARY[];
extern const unsigned char sqlite3StdTypeLen[];
extern const char sqlite3StdTypeAffinity[];
+extern const char sqlite3StdTypeMap[];
extern const char *sqlite3StdType[];
extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char *sqlite3aLTb;
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
**
--- /dev/null
+# 2021-08-19
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+# May you do good and not evil.
+# May you find forgiveness for yourself and forgive others.
+# May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file implements regression tests for SQLite library. The
+# focus of this file is testing STRICT tables.
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+set testprefix strict2
+
+# PRAGMA integrity_check on a STRICT table should verify that
+# all of the values are of the correct type.
+#
+do_execsql_test strict2-1.1 {
+ CREATE TABLE t1(
+ a INT,
+ b INTEGER,
+ c TEXT,
+ d REAL,
+ e BLOB
+ ) STRICT;
+ CREATE TABLE t1nn(
+ a INT NOT NULL,
+ b INTEGER NOT NULL,
+ c TEXT NOT NULL,
+ d REAL NOT NULL,
+ e BLOB NOT NULL
+ ) STRICT;
+ CREATE TABLE t2(a,b,c,d,e);
+ INSERT INTO t1(a,b,c,d,e) VALUES(1,1,'one',1.0,x'b1'),(2,2,'two',2.25,x'b2b2b2');
+ PRAGMA writable_schema=on;
+ UPDATE sqlite_schema SET rootpage=(SELECT rootpage FROM sqlite_schema WHERE name='t1');
+} {}
+db close
+sqlite3 db test.db
+do_execsql_test strict2-1.2 {
+ PRAGMA quick_check('t1');
+} {ok}
+do_execsql_test strict2-1.3 {
+ UPDATE t2 SET a=2.5 WHERE b=2;
+ PRAGMA quick_check('t1');
+} {{non-INT value in t1.a}}
+do_execsql_test strict2-1.4 {
+ UPDATE t2 SET a='xyz' WHERE b=2;
+ PRAGMA quick_check('t1');
+} {{non-INT value in t1.a}}
+do_execsql_test strict2-1.5 {
+ UPDATE t2 SET a=x'445566' WHERE b=2;
+ PRAGMA quick_check('t1');
+} {{non-INT value in t1.a}}
+do_execsql_test strict2-1.6 {
+ UPDATE t2 SET a=2.5 WHERE b=2;
+ PRAGMA quick_check('t1nn');
+} {{non-INT value in t1nn.a}}
+do_execsql_test strict2-1.7 {
+ UPDATE t2 SET a='xyz' WHERE b=2;
+ PRAGMA quick_check('t1nn');
+} {{non-INT value in t1nn.a}}
+do_execsql_test strict2-1.8 {
+ UPDATE t2 SET a=x'445566' WHERE b=2;
+ PRAGMA quick_check('t1nn');
+} {{non-INT value in t1nn.a}}
+
+do_execsql_test strict2-1.13 {
+ UPDATE t2 SET a=2 WHERE b=2;
+ UPDATE t2 SET b=2.5 WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-INTEGER value in t1.b}}
+do_execsql_test strict2-1.14 {
+ UPDATE t2 SET b='two' WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-INTEGER value in t1.b}}
+do_execsql_test strict2-1.15 {
+ UPDATE t2 SET b=x'b0b1b2b3b4' WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-INTEGER value in t1.b}}
+do_execsql_test strict2-1.16 {
+ UPDATE t2 SET b=NULL WHERE a=2;
+ PRAGMA quick_check('t1');
+} {ok}
+do_execsql_test strict2-1.17 {
+ UPDATE t2 SET b=2.5 WHERE a=2;
+ PRAGMA quick_check('t1nn');
+} {{non-INTEGER value in t1nn.b}}
+do_execsql_test strict2-1.18 {
+ UPDATE t2 SET b=NULL WHERE a=2;
+ PRAGMA quick_check('t1nn');
+} {{NULL value in t1nn.b}}
+
+do_execsql_test strict2-1.23 {
+ UPDATE t2 SET b=2 WHERE a=2;
+ UPDATE t2 SET c=9 WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-TEXT value in t1.c}}
+do_execsql_test strict2-1.24 {
+ UPDATE t2 SET c=9.5 WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-TEXT value in t1.c}}
+do_execsql_test strict2-1.25 {
+ UPDATE t2 SET c=x'b0b1b2b3b4' WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-TEXT value in t1.c}}
+
+do_execsql_test strict2-1.33 {
+ UPDATE t2 SET c='two' WHERE a=2;
+ UPDATE t2 SET d=9 WHERE a=2;
+ PRAGMA quick_check('t1');
+} {ok}
+do_execsql_test strict2-1.34 {
+ UPDATE t2 SET d='nine' WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-REAL value in t1.d}}
+do_execsql_test strict2-1.35 {
+ UPDATE t2 SET d=x'b0b1b2b3b4' WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-REAL value in t1.d}}
+
+do_execsql_test strict2-1.43 {
+ UPDATE t2 SET d=2.5 WHERE a=2;
+ UPDATE t2 SET e=9 WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-BLOB value in t1.e}}
+do_execsql_test strict2-1.44 {
+ UPDATE t2 SET e=9.5 WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-BLOB value in t1.e}}
+do_execsql_test strict2-1.45 {
+ UPDATE t2 SET e='hello' WHERE a=2;
+ PRAGMA quick_check('t1');
+} {{non-BLOB value in t1.e}}
+
+
+
+finish_test