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

Trying to insert an incorrect datatype into a STRICT table raises an

SQLITE_CONSTRAINT_DATATYPE error.  Seems to work, though lots more testing
is needed.

FossilOrigin-Name: a19305e5cfedf5c472200d6e05c1396443e348f052a40a0979f860f2ff06851d
This commit is contained in:
drh
2021-08-18 19:22:27 +00:00
parent 44183f83d0
commit 72532f52bc
7 changed files with 163 additions and 17 deletions

View File

@@ -2870,6 +2870,85 @@ op_column_corrupt:
}
}
/* Opcode: TypeCheck P1 P2 * P4 *
** Synopsis: typecheck(r[P1@P2])
**
** Apply affinities to the range of P2 registers beginning with P1.
** Take the affinities from the Table object in P4. If any value
** cannot be coerced into the correct type, then raise an error.
**
** 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".
*/
case OP_TypeCheck: {
Table *pTab;
Column *aCol;
int i;
assert( pOp->p4type==P4_TABLE );
pTab = pOp->p4.pTab;
assert( pTab->tabFlags & TF_Strict );
aCol = pTab->aCol;
pIn1 = &aMem[pOp->p1];
for(i=0; i<pTab->nCol; i++){
if( aCol[i].colFlags & COLFLAG_VIRTUAL ) continue;
assert( pIn1 < &aMem[pOp->p1+pOp->p2] );
applyAffinity(pIn1, aCol[i].affinity, encoding);
if( (pIn1->flags & MEM_Null)==0 ){
switch( aCol[i].eCType ){
case COLTYPE_BLOB: {
if( (pIn1->flags & MEM_Blob)==0 ) goto vdbe_type_error;
break;
}
case COLTYPE_INTEGER:
case COLTYPE_INT: {
if( (pIn1->flags & MEM_Int)==0 ) goto vdbe_type_error;
break;
}
case COLTYPE_TEXT: {
if( (pIn1->flags & MEM_Str)==0 ) goto vdbe_type_error;
break;
}
default: {
assert( aCol[i].eCType==COLTYPE_REAL );
if( pIn1->flags & MEM_Int ){
/* When applying REAL affinity, if the result is still an MEM_Int
** that will fit in 6 bytes, then change the type to MEM_IntReal
** so that we keep the high-resolution integer value but know that
** the type really wants to be REAL. */
testcase( pIn1->u.i==140737488355328LL );
testcase( pIn1->u.i==140737488355327LL );
testcase( pIn1->u.i==-140737488355328LL );
testcase( pIn1->u.i==-140737488355329LL );
if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL){
pIn1->flags |= MEM_IntReal;
pIn1->flags &= ~MEM_Int;
}else{
pIn1->u.r = (double)pIn1->u.i;
pIn1->flags |= MEM_Real;
pIn1->flags &= ~MEM_Int;
}
}else if( (pIn1->flags & MEM_Real)==0 ){
goto vdbe_type_error;
}
break;
}
}
}
REGISTER_TRACE((int)(pIn1-aMem), pIn1);
pIn1++;
}
assert( pIn1 == &aMem[pOp->p1+pOp->p2] );
break;
vdbe_type_error:
sqlite3VdbeError(p, "%s.%s holds only %s values",
pTab->zName, aCol[i].zCnName, sqlite3StdType[aCol[i].eCType-1]);
rc = SQLITE_CONSTRAINT_DATATYPE;
goto abort_due_to_error;
}
/* Opcode: Affinity P1 P2 * P4 *
** Synopsis: affinity(r[P1@P2])
**