Skip to content

Commit 3d4bc23

Browse files
committed
fixed the bug that caused incompatible behavior when comparing int64 or int32 column with double literals in query filter conditions.
introduce tsfile version: 2.2.0-251216-SNAPSHOT, update interfaces provided by tsfile
1 parent c663477 commit 3d4bc23

File tree

10 files changed

+2008
-11
lines changed

10 files changed

+2008
-11
lines changed
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.apache.iotdb.db.it.query;
21+
22+
import org.apache.iotdb.it.env.EnvFactory;
23+
import org.apache.iotdb.it.framework.IoTDBTestRunner;
24+
import org.apache.iotdb.itbase.category.ClusterIT;
25+
import org.apache.iotdb.itbase.category.LocalStandaloneIT;
26+
27+
import org.junit.AfterClass;
28+
import org.junit.BeforeClass;
29+
import org.junit.Test;
30+
import org.junit.experimental.categories.Category;
31+
import org.junit.runner.RunWith;
32+
33+
import java.sql.Connection;
34+
import java.sql.Statement;
35+
36+
import static org.apache.iotdb.db.it.utils.TestUtils.resultSetEqualTest;
37+
import static org.junit.Assert.fail;
38+
39+
@RunWith(IoTDBTestRunner.class)
40+
@Category({LocalStandaloneIT.class, ClusterIT.class})
41+
public class IoTDBPredicateConversionTreeIT {
42+
43+
private static final String DATABASE_NAME = "root.test_pred";
44+
private static final String DEVICE_ID = DATABASE_NAME + ".d1";
45+
46+
private static final String[] SQLs =
47+
new String[] {
48+
"CREATE DATABASE " + DATABASE_NAME,
49+
"CREATE TIMESERIES " + DEVICE_ID + ".int32_col WITH DATATYPE=INT32, ENCODING=PLAIN",
50+
"CREATE TIMESERIES " + DEVICE_ID + ".int64_col WITH DATATYPE=INT64, ENCODING=PLAIN",
51+
"INSERT INTO " + DEVICE_ID + "(time, int32_col, int64_col) VALUES(1, 20, 20)",
52+
"INSERT INTO " + DEVICE_ID + "(time, int32_col, int64_col) VALUES(2, 29, 29)",
53+
"INSERT INTO " + DEVICE_ID + "(time, int32_col, int64_col) VALUES(3, 30, 30)",
54+
"INSERT INTO " + DEVICE_ID + "(time, int32_col, int64_col) VALUES(4, 31, 31)",
55+
"INSERT INTO " + DEVICE_ID + "(time, int64_col) VALUES(5, 35)",
56+
"INSERT INTO " + DEVICE_ID + "(time, int32_col) VALUES(6, 35)",
57+
"INSERT INTO " + DEVICE_ID + "(time, int32_col, int64_col) VALUES(7, null, null)",
58+
"INSERT INTO " + DEVICE_ID + "(time, int32_col, int64_col) VALUES(8, 1000, 1000)",
59+
"INSERT INTO " + DEVICE_ID + "(time, int32_col, int64_col) VALUES(9, -29, -29)",
60+
"INSERT INTO " + DEVICE_ID + "(time, int32_col, int64_col) VALUES(10, -30, -30)"
61+
};
62+
63+
@BeforeClass
64+
public static void setUp() throws Exception {
65+
EnvFactory.getEnv().initClusterEnvironment();
66+
67+
importData();
68+
}
69+
70+
@AfterClass
71+
public static void tearDown() throws Exception {
72+
EnvFactory.getEnv().cleanClusterEnvironment();
73+
}
74+
75+
private static void importData() {
76+
try (Connection connection = EnvFactory.getEnv().getConnection();
77+
Statement statement = connection.createStatement()) {
78+
79+
for (String sql : SQLs) {
80+
statement.execute(sql);
81+
}
82+
} catch (Exception e) {
83+
e.printStackTrace();
84+
fail(e.getMessage());
85+
}
86+
}
87+
88+
@Test
89+
public void testDoubleLiteralAndInt32Column() {
90+
// Common header definition for Tree Model
91+
String expectedHeader = "Time," + DEVICE_ID + ".int32_col,";
92+
93+
// ----------------------------------------------------------------------
94+
// Group 1: Positive boundary 29.1
95+
// ----------------------------------------------------------------------
96+
97+
// TC-1: int32_col >= 29.1
98+
// Logic: Ceil(29.1) = 30 -> int32_col >= 30
99+
// Expected result: Row 3(30), Row 4(31), Row 6(35), Row 8(1000)
100+
String[] retArrayGtEqPositive = {"3,30,", "4,31,", "6,35,", "8,1000,"};
101+
resultSetEqualTest(
102+
"SELECT int32_col FROM " + DEVICE_ID + " WHERE int32_col >= 29.1",
103+
expectedHeader,
104+
retArrayGtEqPositive);
105+
106+
// TC-2: int32_col > 29.1
107+
// Logic: Floor(29.1) = 29 -> int32_col > 29 -> equivalent to int32_col >= 30
108+
// Expected result: Same as above
109+
resultSetEqualTest(
110+
"SELECT int32_col FROM " + DEVICE_ID + " WHERE int32_col > 29.1",
111+
expectedHeader,
112+
retArrayGtEqPositive);
113+
114+
// TC-3: int32_col <= 29.1
115+
// Logic: Floor(29.1) = 29 -> int32_col <= 29
116+
// Expected result: Row 1(20), Row 2(29), Row 9(-29), Row 10(-30)
117+
String[] retArrayLtEqPositive = {"1,20,", "2,29,", "9,-29,", "10,-30,"};
118+
resultSetEqualTest(
119+
"SELECT int32_col FROM " + DEVICE_ID + " WHERE int32_col <= 29.1",
120+
expectedHeader,
121+
retArrayLtEqPositive);
122+
123+
// TC-4: int32_col < 29.1
124+
// Logic: Ceil(29.1) = 30 -> int32_col < 30 -> equivalent to int32_col <= 29
125+
// Expected result: Same as above
126+
resultSetEqualTest(
127+
"SELECT int32_col FROM " + DEVICE_ID + " WHERE int32_col < 29.1",
128+
expectedHeader,
129+
retArrayLtEqPositive);
130+
131+
// TC-5: int32_col = 29.1
132+
// Logic: Integer values can never equal a decimal fraction -> Empty result
133+
String[] retArrayEmpty = {};
134+
resultSetEqualTest(
135+
"SELECT int32_col FROM " + DEVICE_ID + " WHERE int32_col = 29.1",
136+
expectedHeader,
137+
retArrayEmpty);
138+
139+
// TC-6: int32_col != 29.1
140+
// Logic: Integer values are never equal to a decimal fraction -> Return all non-null rows
141+
// Expected result: All rows with int32 data (Row 5 and Row 7 are null, excluded)
142+
String[] retArrayNotEq = {
143+
"1,20,", "2,29,", "3,30,", "4,31,", "6,35,", "8,1000,", "9,-29,", "10,-30,"
144+
};
145+
resultSetEqualTest(
146+
"SELECT int32_col FROM " + DEVICE_ID + " WHERE int32_col != 29.1",
147+
expectedHeader,
148+
retArrayNotEq);
149+
}
150+
151+
@Test
152+
public void testDoubleLiteralAndInt64Column() {
153+
// Common header definition for Tree Model
154+
String expectedHeader = "Time," + DEVICE_ID + ".int64_col,";
155+
156+
// ----------------------------------------------------------------------
157+
// Group 1: Positive boundary 29.1
158+
// ----------------------------------------------------------------------
159+
160+
// TC-1: int64_col >= 29.1
161+
// Logic: Ceil(29.1) = 30 -> int64_col >= 30
162+
// Expected result: Row 3(30), Row 4(31), Row 5(35), Row 8(1000)
163+
// Note: Row 5 (35) is included here (it is int64). Row 6 is excluded (it is int32).
164+
String[] retArrayGtEqPositive = {"3,30,", "4,31,", "5,35,", "8,1000,"};
165+
resultSetEqualTest(
166+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col >= 29.1",
167+
expectedHeader,
168+
retArrayGtEqPositive);
169+
170+
// TC-2: int64_col > 29.1
171+
// Logic: Floor(29.1) = 29 -> int64_col > 29 -> equivalent to int64_col >= 30
172+
// Expected result: Same as above
173+
resultSetEqualTest(
174+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col > 29.1",
175+
expectedHeader,
176+
retArrayGtEqPositive);
177+
178+
// TC-3: int64_col <= 29.1
179+
// Logic: Floor(29.1) = 29 -> int64_col <= 29
180+
// Expected result: Row 1(20), Row 2(29), Row 9(-29), Row 10(-30)
181+
String[] retArrayLtEqPositive = {"1,20,", "2,29,", "9,-29,", "10,-30,"};
182+
resultSetEqualTest(
183+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col <= 29.1",
184+
expectedHeader,
185+
retArrayLtEqPositive);
186+
187+
// TC-4: int64_col < 29.1
188+
// Logic: Ceil(29.1) = 30 -> int64_col < 30 -> equivalent to int64_col <= 29
189+
// Expected result: Same as above
190+
resultSetEqualTest(
191+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col < 29.1",
192+
expectedHeader,
193+
retArrayLtEqPositive);
194+
195+
// TC-5: int64_col = 29.1
196+
// Logic: Long values can never equal a decimal fraction -> Empty result
197+
String[] retArrayEmpty = {};
198+
resultSetEqualTest(
199+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col = 29.1",
200+
expectedHeader,
201+
retArrayEmpty);
202+
203+
// TC-6: int64_col != 29.1
204+
// Logic: Long values are never equal to a decimal fraction -> Return all non-null rows
205+
// Expected result: All rows with int64 data (Row 6 and Row 7 are null, excluded)
206+
String[] retArrayNotEq = {
207+
"1,20,", "2,29,", "3,30,", "4,31,", "5,35,", "8,1000,", "9,-29,", "10,-30,"
208+
};
209+
resultSetEqualTest(
210+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col != 29.1",
211+
expectedHeader,
212+
retArrayNotEq);
213+
214+
// ----------------------------------------------------------------------
215+
// Group 2: Negative boundary -29.1
216+
// ----------------------------------------------------------------------
217+
218+
// TC-7: int64_col <= -29.1
219+
// Logic: Floor(-29.1) = -30 -> int64_col <= -30
220+
// Expected result: Row 10(-30)
221+
String[] retArrayLtEqNegative = {"10,-30,"};
222+
resultSetEqualTest(
223+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col <= -29.1",
224+
expectedHeader,
225+
retArrayLtEqNegative);
226+
227+
// TC-8: int64_col >= -29.1
228+
// Logic: Ceil(-29.1) = -29 -> int64_col >= -29
229+
// Expected result: Row 9(-29) and all larger positive numbers (20, 29, 30, 31, 35, 1000)
230+
String[] retArrayGtEqNegative = {
231+
"1,20,", "2,29,", "3,30,", "4,31,", "5,35,", "8,1000,", "9,-29,"
232+
};
233+
resultSetEqualTest(
234+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col >= -29.1",
235+
expectedHeader,
236+
retArrayGtEqNegative);
237+
}
238+
239+
@Test
240+
public void testDoubleLiteralOverflow() {
241+
String expectedHeaderInt32 = "Time," + DEVICE_ID + ".int32_col,";
242+
String expectedHeaderInt64 = "Time," + DEVICE_ID + ".int64_col,";
243+
String[] emptyResult = {};
244+
245+
// ----------------------------------------------------------------------
246+
// Part 1: INT32 Column vs Double > Integer.MAX_VALUE (~2.14E9)
247+
// Literal: 3.0E9
248+
// ----------------------------------------------------------------------
249+
250+
// TC-1: int32 >= 3.0E9
251+
// Logic: Impossible for any INT32 value.
252+
// Expected: Empty result.
253+
resultSetEqualTest(
254+
"SELECT int32_col FROM " + DEVICE_ID + " WHERE int32_col >= 3.0E9",
255+
expectedHeaderInt32,
256+
emptyResult);
257+
258+
// TC-2: int32 <= 3.0E9
259+
// Logic: Always True for valid values. Must exclude NULLs.
260+
// Expected: All rows where int32_col is not null (Row 5 and 7 are null).
261+
String[] allInt32Rows = {
262+
"1,20,", "2,29,", "3,30,", "4,31,", "6,35,", "8,1000,", "9,-29,", "10,-30,"
263+
};
264+
resultSetEqualTest(
265+
"SELECT int32_col FROM " + DEVICE_ID + " WHERE int32_col <= 3.0E9",
266+
expectedHeaderInt32,
267+
allInt32Rows);
268+
269+
// ----------------------------------------------------------------------
270+
// Part 2: INT64 Column vs Double > Long.MAX_VALUE (~9.22E18)
271+
// Literal: 1.0E19
272+
// ----------------------------------------------------------------------
273+
274+
// TC-3: int64 >= 1.0E19
275+
// Logic: Impossible for any INT64 value.
276+
// Expected: Empty result.
277+
resultSetEqualTest(
278+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col >= 1.0E19",
279+
expectedHeaderInt64,
280+
emptyResult);
281+
282+
// TC-4: int64 <= 1.0E19
283+
// Logic: Always True for valid values. Must exclude NULLs.
284+
// Expected: All rows where int64_col is not null (Row 6 and 7 are null).
285+
String[] allInt64Rows = {
286+
"1,20,", "2,29,", "3,30,", "4,31,", "5,35,", "8,1000,", "9,-29,", "10,-30,"
287+
};
288+
resultSetEqualTest(
289+
"SELECT int64_col FROM " + DEVICE_ID + " WHERE int64_col <= 1.0E19",
290+
expectedHeaderInt64,
291+
allInt64Rows);
292+
}
293+
}

0 commit comments

Comments
 (0)