Compare commits

...

1 Commits

Author SHA1 Message Date
drh 2bf2f8cbee Modify the OP_IsType opcode so that it does not need to distinguish between
NaN and other floating point values.

FossilOrigin-Name: 242cb36c3bd0192208d948214b510348f561e0fe56f1c77b4a5e4fd84bd42cca
2023-03-29 00:05:54 +00:00
4 changed files with 80 additions and 91 deletions
+10 -7
View File
@@ -1,5 +1,5 @@
C Fix\sa\sweird\scorner\scase\sin\saggregate\sfunction\sprocessing\sthat\sresults\sfrom\sthe\nrecent\saddition\sof\ssupport\sfor\sindex\sexpressions\son\saggregate\squeries.\n[forum:/forumpost/bad532820c|Forum\spost\sbad532820c].
D 2023-03-28T16:02:28.157
C Modify\sthe\sOP_IsType\sopcode\sso\sthat\sit\sdoes\snot\sneed\sto\sdistinguish\sbetween\nNaN\sand\sother\sfloating\spoint\svalues.
D 2023-03-29T00:05:54.101
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -618,7 +618,7 @@ F src/parse.y 424e49ed8fc6c907920db9be5a13a75ed43811e1ea8dd21b0fa9ef97f083dc6b
F src/pcache.c 842410539b544e12d5fccfcf29890782f46a58f227a77bc0bd76243799662c0c
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
F src/pcache1.c dee95e3cd2b61e6512dc814c5ab76d5eb36f0bfc9441dbb4260fccc0d12bbddc
F src/pragma.c 367652f5374b2f17761c96b262d9534d89bf089572a1ebba70d426a138c6802a
F src/pragma.c 2e3413d4509bbae184c0489ef5855267e7a0c1f2c7bc1986b44daf550614adc8
F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
F src/prepare.c ce87a08cfddd45a147150db34190b1986f2d4a0e0828858cb6bd908c78fb02e3
F src/printf.c 7eac1a9896a80697e03e08963e210830532ae2ff610e16c193e95af007ca5623
@@ -695,7 +695,7 @@ F src/upsert.c 5303dc6c518fa7d4b280ec65170f465c7a70b7ac2b22491598f6d0b4875b3145
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 3ff7bc2b48dd425b1448304bb86273b05da1621f136d51dbb9789f8803559a1f
F src/vacuum.c 84ce7f01f8a7a08748e107a441db83bcec13970190ddcb0c9ff522adbc1c23fd
F src/vdbe.c 2bb4694bff3c1c4f52fd47e66be30278b5251d62d23b768af7c3b3a0dd7ba901
F src/vdbe.c 2fb5cace3431d56e866ae5abbbba2700a18e15b57abc0f38f9d6e59fb2107d4f
F src/vdbe.h 73b904a6b3bb27f308c6cc287a5751ebc7f1f89456be0ed068a12b92844c6e8c
F src/vdbeInt.h a4147a4ddf613cb1bcb555ace9e9e74a9c099d65facd88155f191b1fb4d74cfb
F src/vdbeapi.c 40c47b1528d308a322203de21d2e0d711753257ed9771771b6129214b1d65932
@@ -2051,8 +2051,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P c8bedef0d61731c29ae34de1594222d15b578f9e2cddbbd5b74fb3059644fe0f
R 68fb0cae877919b0f69109342d216ada
P c34fd9fe1b76e0a5943f014f46141cbe55d41bb1e6980adf9bcb6785a03e7883
R d40ca8a393cdc77a3a8c6e0ac8d14846
T *branch * istype-opcode-refactor
T *sym-istype-opcode-refactor *
T -sym-trunk *
U drh
Z f12fcdd961dcea42a705ad864ed7007e
Z c3941d4e38d885dcc893fe5f74a5950c
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
c34fd9fe1b76e0a5943f014f46141cbe55d41bb1e6980adf9bcb6785a03e7883
242cb36c3bd0192208d948214b510348f561e0fe56f1c77b4a5e4fd84bd42cca
+36 -11
View File
@@ -346,6 +346,36 @@ static void pragmaFunclistLine(
}
}
/*
** Generate a sequence of opcodes to test the type of a value.
**
** The byte code sequence might be either OP_Column, OP_IsType
** or it might be just OP_IsType. In either case, the address
** returned is the opcode of the OP_IsType.
**
** This subroutine assumes that register 3 is available as a
** temporary register. Hence, this subroutine can really only
** be used by PRAGMA integrity_check.
*/
static int generateIsTypeOpcode(
Vdbe *v, /* VDBE under construction */
int p1, /* Cursor holding the value to check. -1 means none */
int p2, /* Jump here if P1.P3 is correct */
int p3, /* Column to examine */
int p4, /* Default type of P1.P3 if does not exist */
int p5 /* Bitmask of allowed types */
){
int addr;
if( p1<0 ){
addr = sqlite3VdbeAddOp4Int(v, OP_IsType, p5, p2, p3, p4);
}else{
sqlite3VdbeAddOp4Int(v, OP_Column, p1, p3, 3, p4);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
addr = sqlite3VdbeAddOp3(v, OP_IsType, p5, p2, 3);
}
return addr;
}
/*
** Helper subroutine for PRAGMA integrity_check:
@@ -1880,8 +1910,7 @@ void sqlite3Pragma(
labelOk = sqlite3VdbeMakeLabel(pParse);
if( pCol->notNull ){
/* (1) NOT NULL columns may not contain a NULL */
int jmp2 = sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
sqlite3VdbeChangeP5(v, 0x0f);
int jmp2 = generateIsTypeOpcode(v, p1, labelOk, p3, p4, 0x0f);
VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pCol->zCnName);
@@ -1903,9 +1932,8 @@ void sqlite3Pragma(
0x13, /* REAL */
0x14 /* TEXT */
};
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
assert( pCol->eCType>=1 && pCol->eCType<=sizeof(aStdTypeMask) );
sqlite3VdbeChangeP5(v, aStdTypeMask[pCol->eCType-1]);
generateIsTypeOpcode(v, p1, labelOk, p3, p4,
aStdTypeMask[pCol->eCType-1]);
VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "non-%s value in %s.%s",
sqlite3StdType[pCol->eCType-1],
@@ -1914,8 +1942,7 @@ void sqlite3Pragma(
}else if( !bStrict && pCol->affinity==SQLITE_AFF_TEXT ){
/* (3) Datatype for TEXT columns in non-STRICT tables must be
** NULL, TEXT, or BLOB. */
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
generateIsTypeOpcode(v, p1, labelOk, p3, p4, 0x1c);
VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "NUMERIC value in %s.%s",
pTab->zName, pTab->aCol[j].zCnName);
@@ -1923,15 +1950,13 @@ void sqlite3Pragma(
}else if( !bStrict && pCol->affinity>=SQLITE_AFF_NUMERIC ){
/* (4) Datatype for numeric columns in non-STRICT tables must not
** be a TEXT value that can be converted to numeric. */
sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4);
sqlite3VdbeChangeP5(v, 0x1b); /* NULL, INT, FLOAT, or BLOB */
generateIsTypeOpcode(v, p1, labelOk, p3, p4, 0x1b);
VdbeCoverage(v);
if( p1>=0 ){
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
}
sqlite3VdbeAddOp4(v, OP_Affinity, 3, 1, 0, "C", P4_STATIC);
sqlite3VdbeAddOp4Int(v, OP_IsType, -1, labelOk, 3, p4);
sqlite3VdbeChangeP5(v, 0x1c); /* NULL, TEXT, or BLOB */
generateIsTypeOpcode(v, -1, labelOk, 3, p4, 0x1c);
VdbeCoverage(v);
zErr = sqlite3MPrintf(db, "TEXT value in %s.%s",
pTab->zName, pTab->aCol[j].zCnName);
+33 -72
View File
@@ -2606,88 +2606,34 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
break;
}
/* Opcode: IsType P1 P2 P3 P4 P5
** Synopsis: if typeof(P1.P3) in P5 goto P2
/* Opcode: IsType P1 P2 P3 * *
** Synopsis: if typeof(P3) in P1 goto P2
**
** Jump to P2 if the type of a column in a btree is one of the types specified
** by the P5 bitmask.
** Jump to P2 if register P3 has one of the datatypes specified
** by the P1 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
** P1 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.
** value determined by P1 and P3 corresponds to one of the bits in P1.
**
*/
case OP_IsType: { /* jump */
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<pC->nHdrParsed ){
serialType = pC->aType[pOp->p3];
if( serialType>=12 ){
if( serialType&1 ){
typeMask = 0x04; /* SQLITE_TEXT */
}else{
typeMask = 0x08; /* SQLITE_BLOB */
}
}else{
static const unsigned char aMask[] = {
0x10, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x2,
0x01, 0x01, 0x10, 0x10
};
testcase( serialType==0 );
testcase( serialType==1 );
testcase( serialType==2 );
testcase( serialType==3 );
testcase( serialType==4 );
testcase( serialType==5 );
testcase( serialType==6 );
testcase( serialType==7 );
testcase( serialType==8 );
testcase( serialType==9 );
testcase( serialType==10 );
testcase( serialType==11 );
typeMask = aMask[serialType];
}
}else{
typeMask = 1 << (pOp->p4.i - 1);
testcase( typeMask==0x01 );
testcase( typeMask==0x02 );
testcase( typeMask==0x04 );
testcase( typeMask==0x08 );
testcase( typeMask==0x10 );
}
}else{
assert( memIsValid(&aMem[pOp->p3]) );
typeMask = 1 << (sqlite3_value_type((sqlite3_value*)&aMem[pOp->p3])-1);
testcase( typeMask==0x01 );
testcase( typeMask==0x02 );
testcase( typeMask==0x04 );
testcase( typeMask==0x08 );
testcase( typeMask==0x10 );
}
VdbeBranchTaken( (typeMask & pOp->p5)!=0, 2);
if( typeMask & pOp->p5 ){
assert( (pOp->p1 & 0x1f)==pOp->p1 );
assert( pOp->p3>=0 && pOp->p3<(p->nMem+1 - p->nCursor) );
assert( memIsValid(&aMem[pOp->p3]) );
typeMask = 1 << (sqlite3_value_type((sqlite3_value*)&aMem[pOp->p3])-1);
testcase( typeMask==0x01 );
testcase( typeMask==0x02 );
testcase( typeMask==0x04 );
testcase( typeMask==0x08 );
testcase( typeMask==0x10 );
VdbeBranchTaken( (typeMask & pOp->p1)!=0, 2);
if( typeMask & pOp->p1 ){
goto jump_to_p2;
}
break;
@@ -2797,7 +2743,8 @@ case OP_Offset: { /* out3 */
**
** If the record contains fewer than P2 fields, then extract a NULL. Or,
** if the P4 argument is a P4_MEM use the value of the P4 argument as
** the result.
** the result. If the P4 argument is P4_INT32 than P4 determines the
** datatype of a constructed element that becomes the result.
**
** If the OPFLAG_LENGTHARG bit is set in P5 then the result is guaranteed
** to only be used by the length() function or the equivalent. The content
@@ -3003,6 +2950,20 @@ op_column_restart:
sqlite3VdbeMemShallowCopy(pDest, pOp->p4.pMem, MEM_Static);
}else{
sqlite3VdbeMemSetNull(pDest);
if( pOp->p4type==P4_INT32 ){
static unsigned char aType[] = {
0,
MEM_Int,
MEM_Real,
MEM_Str,
MEM_Blob,
MEM_Null
};
assert( pOp->p4.i>=SQLITE_INTEGER );
assert( pOp->p4.i<=SQLITE_NULL );
sqlite3VdbeMemSetZeroBlob(pDest, 0);
pDest->flags = aType[pOp->p4.i];
}
}
goto op_column_out;
}