Modify the OP_IsType opcode so that it does not need to distinguish between
NaN and other floating point values. FossilOrigin-Name: 242cb36c3bd0192208d948214b510348f561e0fe56f1c77b4a5e4fd84bd42cca
This commit is contained in:
@@ -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
@@ -1 +1 @@
|
||||
c34fd9fe1b76e0a5943f014f46141cbe55d41bb1e6980adf9bcb6785a03e7883
|
||||
242cb36c3bd0192208d948214b510348f561e0fe56f1c77b4a5e4fd84bd42cca
|
||||
+36
-11
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user