Skip to content

Commit 0667281

Browse files
author
zstan
committed
IGNITE-23873 Sql. Fix processing Infinite and NaN values after calcite version was bumped
1 parent 7eb75ec commit 0667281

File tree

4 files changed

+62
-24
lines changed

4 files changed

+62
-24
lines changed

modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.junit.jupiter.api.Test;
5151
import org.junit.jupiter.params.ParameterizedTest;
5252
import org.junit.jupiter.params.provider.Arguments;
53+
import org.junit.jupiter.params.provider.CsvSource;
5354
import org.junit.jupiter.params.provider.MethodSource;
5455

5556
/**
@@ -129,6 +130,34 @@ public void exactWithApproxComparison() {
129130
assertQuery("SELECT '1.1'::float > 2").returns(false).check();
130131
}
131132

133+
@ParameterizedTest
134+
@CsvSource({"FLOAT", "REAL", "DOUBLE"})
135+
public void nonFiniteNumerics(String type) {
136+
Number positiveInfinity;
137+
Number negativeInfinity;
138+
Number nan;
139+
140+
if ("DOUBLE".equals(type)) {
141+
positiveInfinity = Double.POSITIVE_INFINITY;
142+
negativeInfinity = Double.NEGATIVE_INFINITY;
143+
nan = Double.NaN;
144+
} else {
145+
positiveInfinity = Float.POSITIVE_INFINITY;
146+
negativeInfinity = Float.NEGATIVE_INFINITY;
147+
nan = Float.NaN;
148+
}
149+
150+
assertQuery(format("select CAST('+Infinity' AS {})", type)).returns(positiveInfinity).check();
151+
assertQuery(format("select CAST('Infinity' AS {})", type)).returns(positiveInfinity).check();
152+
assertQuery(format("select CAST('-Infinity' AS {})", type)).returns(negativeInfinity).check();
153+
assertQuery(format("select CAST('NaN' AS {})", type)).returns(nan).check();
154+
155+
assertQuery(format("SELECT * FROM (VALUES(0)) AS t(k) WHERE k < CAST('+Infinity' AS REAL)", type)).returns(0).check();
156+
assertQuery(format("SELECT * FROM (VALUES(0)) AS t(k) WHERE k < CAST('Infinity' AS REAL)", type)).returns(0).check();
157+
assertQuery(format("SELECT * FROM (VALUES(0)) AS t(k) WHERE k > CAST('-Infinity' AS REAL)", type)).returns(0).check();
158+
assertQuery(format("SELECT * FROM (VALUES(0)) AS t(k) WHERE k <> CAST('NaN' AS REAL)", type)).returns(0).check();
159+
}
160+
132161
@WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "true")
133162
@ParameterizedTest()
134163
@MethodSource("exactDecimalTypes")

modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/externalize/RelJson.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -881,12 +881,6 @@ RexNode toRex(RelInput relInput, Object o) {
881881
literal = new BigDecimal(((Number) literal).longValue());
882882
}
883883

884-
// Stub, it need to be fixed https://issues.apache.org/jira/browse/IGNITE-23873
885-
if (type.getSqlTypeName() == SqlTypeName.DOUBLE && literal instanceof String
886-
&& Double.isNaN(Double.parseDouble(literal.toString()))) {
887-
literal = Double.NaN;
888-
}
889-
890884
if (literal instanceof BigInteger) {
891885
// If the literal is a BigInteger, RexBuilder assumes it represents a long value
892886
// within the valid range and converts it without checking the bounds. If the

modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/rex/IgniteRexBuilder.java

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,37 @@ public RexNode makeLiteral(@Nullable Object value, RelDataType type, boolean all
5555
// IgniteCustomType: Not comparable types are not supported.
5656
assert value instanceof Comparable : "Not comparable IgniteCustomType:" + type + ". value: " + value;
5757
return makeLiteral((Comparable<?>) value, type, type.getSqlTypeName());
58-
} else if (value != null && type.getSqlTypeName() == SqlTypeName.CHAR) {
59-
if (type.isNullable()) {
60-
RelDataType typeNotNull =
61-
typeFactory.createTypeWithNullability(type, false);
62-
if (allowCast) {
63-
RexNode literalNotNull = makeLiteral(value, typeNotNull, allowCast);
64-
return makeAbstractCast(type, literalNotNull, false);
58+
}
59+
60+
if (value != null) {
61+
if (type.getSqlTypeName() == SqlTypeName.CHAR) {
62+
if (type.isNullable()) {
63+
RelDataType typeNotNull =
64+
typeFactory.createTypeWithNullability(type, false);
65+
if (allowCast) {
66+
RexNode literalNotNull = makeLiteral(value, typeNotNull, allowCast);
67+
return makeAbstractCast(type, literalNotNull, false);
68+
}
6569
}
66-
}
6770

68-
NlsString string;
69-
if (value instanceof NlsString) {
70-
string = (NlsString) value;
71-
} else {
72-
assert type.getCharset() != null : type + ".getCharset() must not be null";
73-
string = new NlsString((String) value, type.getCharset().name(), type.getCollation());
74-
}
71+
NlsString string;
72+
if (value instanceof NlsString) {
73+
string = (NlsString) value;
74+
} else {
75+
assert type.getCharset() != null : type + ".getCharset() must not be null";
76+
string = new NlsString((String) value, type.getCharset().name(), type.getCollation());
77+
}
7578

76-
return makeCharLiteral(string);
77-
} else {
78-
return super.makeLiteral(value, type, allowCast, trim);
79+
return makeCharLiteral(string);
80+
} else if (value instanceof String) {
81+
if (type.getSqlTypeName() == SqlTypeName.DOUBLE) {
82+
value = Double.parseDouble((String) value);
83+
} else if (type.getSqlTypeName() == SqlTypeName.REAL || type.getSqlTypeName() == SqlTypeName.FLOAT) {
84+
value = Float.parseFloat((String) value);
85+
}
86+
}
7987
}
88+
89+
return super.makeLiteral(value, type, allowCast, trim);
8090
}
8191
}

modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/IgniteMath.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,11 @@ public static float convertToFloatExact(Number x) {
444444
return value.floatValue();
445445
} else {
446446
double v = x.doubleValue();
447+
448+
if (!Double.isFinite(v)) {
449+
return x.floatValue();
450+
}
451+
447452
if (v > UPPER_FLOAT_DOUBLE || v < LOWER_FLOAT_DOUBLE) {
448453
throw outOfRangeForTypeException(SqlTypeName.REAL);
449454
}

0 commit comments

Comments
 (0)