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:
79
src/vdbe.c
79
src/vdbe.c
@@ -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])
|
||||
**
|
||||
|
Reference in New Issue
Block a user