Skip to content

Commit 3443fae

Browse files
committed
Add unit tests for utilities and shuttles for validation
Signed-off-by: Yuanchun Shen <yuanchu@amazon.com>
1 parent 78051d6 commit 3443fae

5 files changed

Lines changed: 1209 additions & 5 deletions

File tree

core/src/main/java/org/opensearch/sql/calcite/utils/OpenSearchTypeUtil.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,18 +39,18 @@ public static boolean isUserDefinedType(RelDataType type) {
3939
* @return true if the type is numeric or string, false otherwise
4040
*/
4141
public static boolean isNumericOrCharacter(RelDataType fieldType) {
42-
// Check standard SQL numeric types & string types (VARCHAR, CHAR)
43-
if (SqlTypeUtil.isNumeric(fieldType) || SqlTypeUtil.isCharacter(fieldType)) {
44-
return true;
45-
}
46-
4742
// Check for OpenSearch UDT numeric types
4843
if (isUserDefinedType(fieldType)) {
4944
AbstractExprRelDataType<?> exprType = (AbstractExprRelDataType<?>) fieldType;
5045
ExprType udtType = exprType.getExprType();
5146
return ExprCoreType.numberTypes().contains(udtType);
5247
}
5348

49+
// Check standard SQL numeric types & string types (VARCHAR, CHAR)
50+
if (SqlTypeUtil.isNumeric(fieldType) || SqlTypeUtil.isCharacter(fieldType)) {
51+
return true;
52+
}
53+
5454
return false;
5555
}
5656

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package org.opensearch.sql.calcite.utils;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertNotNull;
10+
import static org.junit.jupiter.api.Assertions.assertNull;
11+
import static org.junit.jupiter.api.Assertions.assertTrue;
12+
import static org.opensearch.sql.calcite.utils.OpenSearchTypeFactory.TYPE_FACTORY;
13+
14+
import java.util.List;
15+
import org.apache.calcite.rel.type.RelDataType;
16+
import org.apache.calcite.sql.type.SqlTypeName;
17+
import org.junit.jupiter.api.Test;
18+
import org.opensearch.sql.calcite.utils.OpenSearchTypeFactory.ExprUDT;
19+
20+
public class OpenSearchTypeFactoryTest {
21+
22+
// ==================== leastRestrictive with UDT types tests ====================
23+
24+
@Test
25+
public void testLeastRestrictive_dateUdtsOnly_returnsDateUdt() {
26+
RelDataType dateUdt1 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE);
27+
RelDataType dateUdt2 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE);
28+
29+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(dateUdt1, dateUdt2));
30+
31+
assertNotNull(result);
32+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
33+
assertTrue(OpenSearchTypeUtil.isDate(result));
34+
}
35+
36+
@Test
37+
public void testLeastRestrictive_timeUdtsOnly_returnsTimeUdt() {
38+
RelDataType timeUdt1 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_TIME);
39+
RelDataType timeUdt2 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_TIME);
40+
41+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(timeUdt1, timeUdt2));
42+
43+
assertNotNull(result);
44+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
45+
assertTrue(OpenSearchTypeUtil.isTime(result));
46+
}
47+
48+
@Test
49+
public void testLeastRestrictive_timestampUdtsOnly_returnsTimestampUdt() {
50+
RelDataType timestampUdt1 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_TIMESTAMP);
51+
RelDataType timestampUdt2 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_TIMESTAMP);
52+
53+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(timestampUdt1, timestampUdt2));
54+
55+
assertNotNull(result);
56+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
57+
assertTrue(OpenSearchTypeUtil.isTimestamp(result));
58+
}
59+
60+
@Test
61+
public void testLeastRestrictive_ipUdtsOnly_returnsIpUdt() {
62+
RelDataType ipUdt1 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_IP);
63+
RelDataType ipUdt2 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_IP);
64+
65+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(ipUdt1, ipUdt2));
66+
67+
assertNotNull(result);
68+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
69+
assertTrue(OpenSearchTypeUtil.isIp(result));
70+
}
71+
72+
@Test
73+
public void testLeastRestrictive_binaryUdtsOnly_returnsBinaryUdt() {
74+
RelDataType binaryUdt1 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_BINARY);
75+
RelDataType binaryUdt2 = TYPE_FACTORY.createUDT(ExprUDT.EXPR_BINARY);
76+
77+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(binaryUdt1, binaryUdt2));
78+
79+
assertNotNull(result);
80+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
81+
assertTrue(OpenSearchTypeUtil.isBinary(result));
82+
}
83+
84+
@Test
85+
public void testLeastRestrictive_dateAndNull_returnsDateUdt() {
86+
RelDataType dateUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE);
87+
RelDataType nullType = TYPE_FACTORY.createSqlType(SqlTypeName.NULL);
88+
89+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(dateUdt, nullType));
90+
91+
assertNotNull(result);
92+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
93+
assertTrue(OpenSearchTypeUtil.isDate(result));
94+
assertTrue(result.isNullable());
95+
}
96+
97+
@Test
98+
public void testLeastRestrictive_timeAndNull_returnsTimeUdt() {
99+
RelDataType timeUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_TIME);
100+
RelDataType nullType = TYPE_FACTORY.createSqlType(SqlTypeName.NULL);
101+
102+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(timeUdt, nullType));
103+
104+
assertNotNull(result);
105+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
106+
assertTrue(OpenSearchTypeUtil.isTime(result));
107+
assertTrue(result.isNullable());
108+
}
109+
110+
@Test
111+
public void testLeastRestrictive_ipAndNull_returnsIpUdt() {
112+
RelDataType ipUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_IP);
113+
RelDataType nullType = TYPE_FACTORY.createSqlType(SqlTypeName.NULL);
114+
115+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(ipUdt, nullType));
116+
117+
assertNotNull(result);
118+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
119+
assertTrue(OpenSearchTypeUtil.isIp(result));
120+
assertTrue(result.isNullable());
121+
}
122+
123+
@Test
124+
public void testLeastRestrictive_binaryAndNull_returnsBinaryUdt() {
125+
RelDataType binaryUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_BINARY);
126+
RelDataType nullType = TYPE_FACTORY.createSqlType(SqlTypeName.NULL);
127+
128+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(binaryUdt, nullType));
129+
130+
assertNotNull(result);
131+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
132+
assertTrue(OpenSearchTypeUtil.isBinary(result));
133+
assertTrue(result.isNullable());
134+
}
135+
136+
@Test
137+
public void testLeastRestrictive_mixedDatetimeTypes_returnsTimestampUdt() {
138+
RelDataType dateUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE);
139+
RelDataType timeUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_TIME);
140+
141+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(dateUdt, timeUdt));
142+
143+
assertNotNull(result);
144+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
145+
assertTrue(OpenSearchTypeUtil.isTimestamp(result));
146+
}
147+
148+
@Test
149+
public void testLeastRestrictive_dateTimeTimestamp_returnsTimestampUdt() {
150+
RelDataType dateUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE);
151+
RelDataType timeUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_TIME);
152+
RelDataType timestampUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_TIMESTAMP);
153+
154+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(dateUdt, timeUdt, timestampUdt));
155+
156+
assertNotNull(result);
157+
assertTrue(OpenSearchTypeUtil.isUserDefinedType(result));
158+
assertTrue(OpenSearchTypeUtil.isTimestamp(result));
159+
}
160+
161+
@Test
162+
public void testLeastRestrictive_ipAndBinary_returnsVarchar() {
163+
// IP and BINARY are incompatible UDT types, should fall back to VARCHAR
164+
RelDataType ipUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_IP);
165+
RelDataType binaryUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_BINARY);
166+
167+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(ipUdt, binaryUdt));
168+
169+
assertNotNull(result);
170+
assertEquals(SqlTypeName.VARCHAR, result.getSqlTypeName());
171+
}
172+
173+
@Test
174+
public void testLeastRestrictive_ipUdtAndOther_returnsIpUdt() {
175+
// When IP UDT is mixed with OTHER type (which is used as intermediate for IP)
176+
RelDataType ipUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_IP);
177+
RelDataType nullType = TYPE_FACTORY.createSqlType(SqlTypeName.NULL);
178+
179+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(ipUdt, nullType));
180+
181+
assertNotNull(result);
182+
assertTrue(OpenSearchTypeUtil.isIp(result));
183+
assertTrue(result.isNullable());
184+
}
185+
186+
@Test
187+
public void testLeastRestrictive_nullableUdts_preservesNullability() {
188+
RelDataType nullableDateUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE, true);
189+
RelDataType nonNullableDateUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE, false);
190+
191+
RelDataType result =
192+
TYPE_FACTORY.leastRestrictive(List.of(nullableDateUdt, nonNullableDateUdt));
193+
194+
assertNotNull(result);
195+
assertTrue(OpenSearchTypeUtil.isDate(result));
196+
assertTrue(result.isNullable());
197+
}
198+
199+
// ==================== leastRestrictive with standard types tests ====================
200+
201+
@Test
202+
public void testLeastRestrictive_standardNumericTypes_returnsLeastRestrictive() {
203+
RelDataType intType = TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER);
204+
RelDataType bigintType = TYPE_FACTORY.createSqlType(SqlTypeName.BIGINT);
205+
206+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(intType, bigintType));
207+
208+
assertNotNull(result);
209+
assertEquals(SqlTypeName.BIGINT, result.getSqlTypeName());
210+
}
211+
212+
@Test
213+
public void testLeastRestrictive_charType_convertsToVarchar() {
214+
RelDataType charType = TYPE_FACTORY.createSqlType(SqlTypeName.CHAR, 10);
215+
216+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(charType));
217+
218+
assertNotNull(result);
219+
assertEquals(SqlTypeName.VARCHAR, result.getSqlTypeName());
220+
}
221+
222+
@Test
223+
public void testLeastRestrictive_charAndVarchar_returnsVarchar() {
224+
RelDataType charType = TYPE_FACTORY.createSqlType(SqlTypeName.CHAR, 5);
225+
RelDataType varcharType = TYPE_FACTORY.createSqlType(SqlTypeName.VARCHAR);
226+
227+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(charType, varcharType));
228+
229+
assertNotNull(result);
230+
assertEquals(SqlTypeName.VARCHAR, result.getSqlTypeName());
231+
}
232+
233+
@Test
234+
public void testLeastRestrictive_withAnyType_fallsThrough() {
235+
RelDataType dateUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE);
236+
RelDataType anyType = TYPE_FACTORY.createSqlType(SqlTypeName.ANY);
237+
238+
// When ANY is present, should fall through to standard leastRestrictive
239+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(dateUdt, anyType));
240+
241+
// Result depends on standard Calcite behavior
242+
assertNotNull(result);
243+
assertEquals(SqlTypeName.ANY, result.getSqlTypeName());
244+
}
245+
246+
@Test
247+
public void testLeastRestrictive_incompatibleTypes_returnsNull() {
248+
RelDataType intType = TYPE_FACTORY.createSqlType(SqlTypeName.INTEGER);
249+
RelDataType boolType = TYPE_FACTORY.createSqlType(SqlTypeName.BOOLEAN);
250+
251+
// Integer and boolean are incompatible
252+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(intType, boolType));
253+
254+
assertNull(result);
255+
}
256+
257+
@Test
258+
public void testLeastRestrictive_singleType_returnsSameType() {
259+
RelDataType dateUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE);
260+
261+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(dateUdt));
262+
263+
assertNotNull(result);
264+
assertTrue(OpenSearchTypeUtil.isDate(result));
265+
}
266+
267+
@Test
268+
public void testLeastRestrictive_multipleNulls_returnsNullableUdt() {
269+
RelDataType dateUdt = TYPE_FACTORY.createUDT(ExprUDT.EXPR_DATE);
270+
RelDataType nullType1 = TYPE_FACTORY.createSqlType(SqlTypeName.NULL);
271+
RelDataType nullType2 = TYPE_FACTORY.createSqlType(SqlTypeName.NULL);
272+
273+
RelDataType result = TYPE_FACTORY.leastRestrictive(List.of(dateUdt, nullType1, nullType2));
274+
275+
assertNotNull(result);
276+
assertTrue(OpenSearchTypeUtil.isDate(result));
277+
assertTrue(result.isNullable());
278+
}
279+
}

0 commit comments

Comments
 (0)