When computing an expression value for an index-on-expression or a CHECK

constraint and the expressions uses a REAL table column, but the value of
that column is an integer (in other words, when it is using the 
store-real-as-integer optimization) be sure to promote the value to real
before evaluating the expression.  Ticket [57af00b6642ecd68].

FossilOrigin-Name: 0658c16e311393c8a347b1bd41fa5dbfd2e184aa75d84c011aa8dbac79b632e9
This commit is contained in:
drh 2019-09-02 00:58:44 +00:00
parent cc80db69e9
commit bffdd63633
5 changed files with 60 additions and 10 deletions

View File

@ -1,5 +1,5 @@
C Remove\san\sobsolete\sparagraph\sfrom\sthe\sOP_Column\sdocumentation.\s\sNo\scode\nchanges.
D 2019-09-01T23:36:33.093
C When\scomputing\san\sexpression\svalue\sfor\san\sindex-on-expression\sor\sa\sCHECK\nconstraint\sand\sthe\sexpressions\suses\sa\sREAL\stable\scolumn,\sbut\sthe\svalue\sof\nthat\scolumn\sis\san\sinteger\s(in\sother\swords,\swhen\sit\sis\susing\sthe\s\nstore-real-as-integer\soptimization)\sbe\ssure\sto\spromote\sthe\svalue\sto\sreal\nbefore\sevaluating\sthe\sexpression.\s\sTicket\s[57af00b6642ecd68].
D 2019-09-02T00:58:44.169
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -475,7 +475,7 @@ F src/date.c e1d8ac7102f3f283e63e13867acb0efa33861cf34f0faf4cdbaf9fa7a1eb7041
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319
F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf
F src/expr.c 150acd113edf50e807c70eedf1629b1d94b1177b8a56497e23d8ccf1e1e2a74f
F src/expr.c dcf6eb84656d3c5b41d6755cdb55a264a3f6f8f12e68bf87fa27bdd33e263ee3
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 6b79f4c2447691aa9ac86e2a6a774b65f3b3dd053d4220a4893051a0de20f82e
F src/func.c 4ee36219698d50d672a28eca4adb0fd6b92e607a1883d318315e0d2fd5044467
@ -724,7 +724,7 @@ F test/capi3d.test aba917805573a03deed961a21f07a5a84505ad0a616f7e3fc1508844a15bc
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 3619f0c58c2e4b2a94aa86e75607e497d34ef40ab74418e71aef7b4ca5155895
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
F test/check.test e6527bed2b5557ffdbf5680765c4ae6fe61e9b68b7ee69a7f776787a4527b5da
F test/check.test 4b57ecbbb300336382ca21ef983dfa70b291a70ae430690494d13f1629f45a38
F test/checkfault.test da6cb3d50247169efcb20bdf57863a3ccfa1d27d9e55cd324f0680096970f014
F test/chunksize.test 427d87791743486cbf0c3b8c625002f3255cb3a89c6eba655a98923b1387b760
F test/close.test eccbad8ecd611d974cbf47278c3d4e5874faf02d811338d5d348af42d56d647c
@ -1052,7 +1052,7 @@ F test/index7.test 1d764c0cca45f5a76150b08e127ccc8d52492cfa788b5fafed4be784a351b
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
F test/indexexpr1.test 0f293369ed6f56764cfc3db05685d45469d9e685ba87e3698527049ba359ae24
F test/indexexpr1.test fb56f0b9a9d147b38979d154176f150b5e45fdd5d0162fab639a7f9478134fa3
F test/indexexpr2.test b580f378423bca443ffab47ada677203cfcf8a60f48a8aa20065f27c8f7739b5
F test/indexfault.test 98d78a8ff1f5335628b62f886a1cb7c7dac1ef6d48fa39c51ec871c87dce9811
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
@ -1838,7 +1838,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 63c67a54b4d3e501f3059dcdfc6bb50c6b8dad63a34eb773e4408d9e4e780d7a
R c1da51105a0bd41bcf8b282b1f2a62fa
P f6d8956cf8b5993a4332b9330e89d5c3d5f8872ea5a2ce3d2e91127406cc1839
R cad500c6656aba1cd58b9ed6ead8c93d
U drh
Z 7a37af4640fc76b6e62eb0e6e9abd09a
Z 159d6991963aae3d8bb85f2594c26695

View File

@ -1 +1 @@
f6d8956cf8b5993a4332b9330e89d5c3d5f8872ea5a2ce3d2e91127406cc1839
0658c16e311393c8a347b1bd41fa5dbfd2e184aa75d84c011aa8dbac79b632e9

View File

@ -3532,7 +3532,19 @@ expr_code_doover:
if( iTab<0 ){
if( pParse->iSelfTab<0 ){
/* Generating CHECK constraints or inserting into partial index */
return pExpr->iColumn - pParse->iSelfTab;
assert( pExpr->y.pTab!=0 );
assert( pExpr->iColumn>=XN_ROWID );
assert( pExpr->iColumn<pExpr->y.pTab->nCol );
if( pExpr->iColumn>=0
&& pExpr->y.pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
){
sqlite3VdbeAddOp2(v, OP_SCopy, pExpr->iColumn - pParse->iSelfTab,
target);
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
return target;
}else{
return pExpr->iColumn - pParse->iSelfTab;
}
}else{
/* Coding an expression that is part of an index where column names
** in the index refer to the table to which the index belongs */

View File

@ -123,6 +123,11 @@ do_test check-2.1 {
y REAL CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ),
z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' )
);
CREATE TABLE t2n(
x INTEGER CONSTRAINT one CHECK( typeof(coalesce(x,0))=="integer" ),
y NUMERIC CONSTRAINT two CHECK( typeof(coalesce(y,0.1))=='real' ),
z TEXT CONSTRAINT three CHECK( typeof(coalesce(z,''))=='text' )
);
PRAGMA writable_schema = 0;
}
} {}
@ -146,9 +151,17 @@ do_test check-2.4 {
}
} {1 {CHECK constraint failed: one}}
do_test check-2.5 {
# The 5 gets automatically promoted to 5.0 because the column type is REAL
catchsql {
INSERT INTO t2 VALUES(NULL, 5, NULL);
}
} {0 {}}
do_test check-2.5b {
# This time the column type is NUMERIC, so not automatic promption to REAL
# occurs and the constraint fails.
catchsql {
INSERT INTO t2n VALUES(NULL, 5, NULL);
}
} {1 {CHECK constraint failed: two}}
do_test check-2.6 {
catchsql {
@ -195,6 +208,7 @@ do_test check-2.cleanup {
execsql {
DROP TABLE IF EXISTS t2b;
DROP TABLE IF EXISTS t2c;
DROP TABLE IF EXISTS t2n;
}
} {}

View File

@ -457,4 +457,28 @@ do_execsql_test indexexpr-1700 {
SELECT * FROM t0 WHERE ((NULL IS FALSE) IS FALSE);
} {0}
# 2019-09-02 https://www.sqlite.org/src/tktview/57af00b6642ecd6848
# When the expression of an an index-on-expression references a
# table column of type REAL that is actually holding an MEM_IntReal
# value, be sure to use the REAL value and not the INT value when
# computing the expression.
#
do_execsql_test indexexpr-1800 {
DROP TABLE IF EXISTS t0;
CREATE TABLE t0(c0 REAL, c1 TEXT);
CREATE INDEX i0 ON t0(+c0, c0);
INSERT INTO t0(c0) VALUES(0);
SELECT CAST(+ t0.c0 AS BLOB) LIKE 0 FROM t0;
} {0}
do_execsql_test indexexpr-1810 {
SELECT CAST(+ t0.c0 AS BLOB) LIKE '0.0' FROM t0;
} {1}
do_execsql_test indexexpr-1820 {
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(x REAL);
CREATE INDEX t1x ON t1(x, +x);
INSERT INTO t1(x) VALUES(2);
SELECT +x FROM t1 WHERE x=2;
} {2.0}
finish_test