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:
69
src/vdbe.c
69
src/vdbe.c
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user