1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

An attempt to enhance PRAGMA integrity check so that it does data type

checking on non-STRICT tables.  Specifically:  (1) Columns with TEXT affinity
should not contain numeric values, and (2) columns with numeric affinity should
not contain text values that can be converted to numeric.

FossilOrigin-Name: 8b1e7f0524637728cebe81c7d3ff8ad8a5a55782eac6409b425dad538024f596
This commit is contained in:
drh
2022-10-10 18:25:05 +00:00
parent 005c9d8295
commit 49d77ee642
6 changed files with 177 additions and 41 deletions

View File

@@ -2588,19 +2588,66 @@ 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
/* Opcode: IsType P1 P2 P3 P4 P5
** Synopsis: if typeof(P1.P3) in P5 goto P2
**
** Jump to P2 if the type of a column in a btree is one of the types specified
** by the P5 bitmask.
**
** P1 is normally a cursor on a btree for which the row decode cache is
** valid through at least column P3. In other words, there should have been
** a prior OP_Column for column P3 or greater. If the cursor is not valid,
** then this opcode might give spurious results.
** The the btree row has fewer than P3 columns, then use P4 as the
** datatype.
**
** If P1 is -1, then P3 is a register number and the datatype is taken
** from the value in that register.
**
** P5 is a bitmask of data types. SQLITE_INTEGER is the least significant
** (0x01) bit. SQLITE_FLOAT is the 0x02 bit. SQLITE_TEXT is 0x04.
** SQLITE_BLOB is 0x08. SQLITE_NULL is 0x10.
**
** Take the jump to address P2 if and only if the datatype of the
** value determined by P1 and P3 corresponds to one of the bits in the
** P5 bitmask.
**
** 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;
case OP_IsType: {
VdbeCursor *pC;
u16 typeMask;
u32 serialType;
assert( pOp->p1>=(-1) && pOp->p1<p->nCursor );
assert( pOp->p1>=0 || (pOp->p3>=0 && pOp->p3<=(p->nMem+1 - p->nCursor)) );
if( pOp->p1>=0 ){
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
assert( pOp->p3>=0 );
if( pOp->p3<(u32)pC->nHdrParsed ){
serialType = pC->aType[pOp->p3];
if( serialType==0 ){
typeMask = 0x10; /* SQLITE_NULL */
}else if( serialType==7 ){
typeMask = 0x02; /* SQLITE_FLOAT */
}else if( serialType<12 ){
typeMask = 0x01; /* SQLITE_INTEGER */
}else if( serialType&1 ){
typeMask = 0x04; /* SQLITE_TEXT */
}else{
typeMask = 0x08; /* SQLITE_BLOB */
}
}else{
typeMask = 1 << (pOp->p4.i - 1);
}
}else{
assert( memIsValid(&aMem[pOp->p3]) );
typeMask = 1 << (sqlite3_value_type((sqlite3_value*)&aMem[pOp->p3])-1);
}
VdbeBranchTaken( (typeMask & pOp->p5)!=0, 2);
if( typeMask & pOp->p5 ){
goto jump_to_p2;
}
break;
}