Skip to content

Commit 2fafa52

Browse files
xuzifu666mihaibudiu
authored andcommitted
[CALCITE-7114] Invalid unparse for cast to array type in Spark
1 parent 7ecd358 commit 2fafa52

File tree

4 files changed

+98
-74
lines changed

4 files changed

+98
-74
lines changed

core/src/main/java/org/apache/calcite/sql/dialect/SparkSqlDialect.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@
3737
import org.apache.calcite.sql.fun.SqlLibraryOperators;
3838
import org.apache.calcite.sql.fun.SqlStdOperatorTable;
3939
import org.apache.calcite.sql.parser.SqlParserPos;
40-
import org.apache.calcite.sql.type.BasicSqlType;
41-
import org.apache.calcite.sql.type.SqlTypeName;
4240
import org.apache.calcite.util.RelToSqlConverterUtil;
4341

4442
import com.google.common.collect.ImmutableList;
@@ -163,10 +161,19 @@ public SparkSqlDialect(SqlDialect.Context context) {
163161
}
164162

165163
@Override public @Nullable SqlNode getCastSpec(RelDataType type) {
166-
if (type instanceof BasicSqlType && type.getSqlTypeName() == SqlTypeName.VARCHAR) {
164+
switch (type.getSqlTypeName()) {
165+
case VARCHAR:
167166
return new SqlDataTypeSpec(
168167
new SqlAlienSystemTypeNameSpec("STRING", type.getSqlTypeName(),
169168
SqlParserPos.ZERO), SqlParserPos.ZERO);
169+
case ARRAY:
170+
return RelToSqlConverterUtil.getCastSpecAngleBracketArrayType(this, type,
171+
SqlParserPos.ZERO);
172+
case MULTISET:
173+
throw new UnsupportedOperationException("Spark dialect does not support cast to "
174+
+ type.getSqlTypeName());
175+
default:
176+
break;
170177
}
171178
return super.getCastSpec(type);
172179
}

core/src/main/java/org/apache/calcite/sql/dialect/StarRocksSqlDialect.java

Lines changed: 49 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -25,21 +25,16 @@
2525
import org.apache.calcite.rex.RexNode;
2626
import org.apache.calcite.sql.SqlAbstractDateTimeLiteral;
2727
import org.apache.calcite.sql.SqlAlienSystemTypeNameSpec;
28-
import org.apache.calcite.sql.SqlArrayWithAngleBracketsNameSpec;
2928
import org.apache.calcite.sql.SqlBasicTypeNameSpec;
3029
import org.apache.calcite.sql.SqlCall;
3130
import org.apache.calcite.sql.SqlDataTypeSpec;
3231
import org.apache.calcite.sql.SqlDialect;
3332
import org.apache.calcite.sql.SqlLiteral;
3433
import org.apache.calcite.sql.SqlMapTypeNameSpec;
3534
import org.apache.calcite.sql.SqlNode;
36-
import org.apache.calcite.sql.SqlTypeNameSpec;
3735
import org.apache.calcite.sql.SqlWriter;
3836
import org.apache.calcite.sql.fun.SqlFloorFunction;
3937
import org.apache.calcite.sql.parser.SqlParserPos;
40-
import org.apache.calcite.sql.type.AbstractSqlType;
41-
import org.apache.calcite.sql.type.ArraySqlType;
42-
import org.apache.calcite.sql.type.BasicSqlType;
4338
import org.apache.calcite.sql.type.MapSqlType;
4439
import org.apache.calcite.sql.type.SqlTypeName;
4540
import org.apache.calcite.util.RelToSqlConverterUtil;
@@ -177,72 +172,55 @@ public StarRocksSqlDialect(Context context) {
177172
}
178173

179174
@Override public @Nullable SqlNode getCastSpec(RelDataType type) {
180-
if (type instanceof BasicSqlType) {
181-
switch (type.getSqlTypeName()) {
182-
case INTEGER:
183-
return new SqlDataTypeSpec(
184-
new SqlAlienSystemTypeNameSpec(
185-
"INT",
186-
type.getSqlTypeName(),
187-
SqlParserPos.ZERO),
188-
SqlParserPos.ZERO);
189-
case REAL:
190-
return new SqlDataTypeSpec(
191-
new SqlAlienSystemTypeNameSpec("FLOAT", type.getSqlTypeName(),
192-
SqlParserPos.ZERO),
193-
SqlParserPos.ZERO);
194-
case BIGINT:
195-
return new SqlDataTypeSpec(
196-
new SqlBasicTypeNameSpec(SqlTypeName.BIGINT, SqlParserPos.ZERO),
197-
SqlParserPos.ZERO);
198-
case TIMESTAMP:
199-
return new SqlDataTypeSpec(
200-
new SqlAlienSystemTypeNameSpec(
201-
"DATETIME",
202-
type.getSqlTypeName(),
203-
SqlParserPos.ZERO),
204-
SqlParserPos.ZERO);
205-
case VARCHAR:
206-
return new SqlDataTypeSpec(
207-
new SqlBasicTypeNameSpec(SqlTypeName.VARCHAR, type.getPrecision(), SqlParserPos.ZERO),
208-
SqlParserPos.ZERO);
209-
default:
210-
break;
211-
}
212-
}
213-
214-
if (type instanceof AbstractSqlType) {
215-
switch (type.getSqlTypeName()) {
216-
case MAP:
217-
MapSqlType mapSqlType = (MapSqlType) type;
218-
SqlDataTypeSpec keySpec = (SqlDataTypeSpec) getCastSpec(mapSqlType.getKeyType());
219-
SqlDataTypeSpec valueSpec =
220-
(SqlDataTypeSpec) getCastSpec(mapSqlType.getValueType());
221-
SqlDataTypeSpec nonNullKeySpec =
222-
requireNonNull(keySpec, "keySpec");
223-
SqlDataTypeSpec nonNullValueSpec =
224-
requireNonNull(valueSpec, "valueSpec");
225-
SqlMapTypeNameSpec sqlMapTypeNameSpec =
226-
new SqlMapTypeNameSpec(nonNullKeySpec, nonNullValueSpec, SqlParserPos.ZERO);
227-
return new SqlDataTypeSpec(sqlMapTypeNameSpec,
228-
SqlParserPos.ZERO);
229-
case ARRAY:
230-
ArraySqlType arraySqlType = (ArraySqlType) type;
231-
SqlDataTypeSpec arrayValueSpec =
232-
(SqlDataTypeSpec) getCastSpec(arraySqlType.getComponentType());
233-
SqlDataTypeSpec nonNullarrayValueSpec =
234-
requireNonNull(arrayValueSpec, "arrayValueSpec");
235-
SqlTypeNameSpec typeNameSpec =
236-
new SqlArrayWithAngleBracketsNameSpec(
237-
nonNullarrayValueSpec.getTypeNameSpec(),
238-
arraySqlType.getSqlTypeName(), SqlParserPos.ZERO);
239-
return new SqlDataTypeSpec(typeNameSpec, SqlParserPos.ZERO);
240-
case MULTISET:
241-
throw new UnsupportedOperationException("StarRocks dialect does not support cast to "
242-
+ type.getSqlTypeName());
243-
default:
244-
break;
245-
}
175+
switch (type.getSqlTypeName()) {
176+
case INTEGER:
177+
return new SqlDataTypeSpec(
178+
new SqlAlienSystemTypeNameSpec(
179+
"INT",
180+
type.getSqlTypeName(),
181+
SqlParserPos.ZERO),
182+
SqlParserPos.ZERO);
183+
case REAL:
184+
return new SqlDataTypeSpec(
185+
new SqlAlienSystemTypeNameSpec("FLOAT", type.getSqlTypeName(),
186+
SqlParserPos.ZERO),
187+
SqlParserPos.ZERO);
188+
case BIGINT:
189+
return new SqlDataTypeSpec(
190+
new SqlBasicTypeNameSpec(SqlTypeName.BIGINT, SqlParserPos.ZERO),
191+
SqlParserPos.ZERO);
192+
case TIMESTAMP:
193+
return new SqlDataTypeSpec(
194+
new SqlAlienSystemTypeNameSpec(
195+
"DATETIME",
196+
type.getSqlTypeName(),
197+
SqlParserPos.ZERO),
198+
SqlParserPos.ZERO);
199+
case VARCHAR:
200+
return new SqlDataTypeSpec(
201+
new SqlBasicTypeNameSpec(SqlTypeName.VARCHAR, type.getPrecision(), SqlParserPos.ZERO),
202+
SqlParserPos.ZERO);
203+
case MAP:
204+
MapSqlType mapSqlType = (MapSqlType) type;
205+
SqlDataTypeSpec keySpec = (SqlDataTypeSpec) getCastSpec(mapSqlType.getKeyType());
206+
SqlDataTypeSpec valueSpec =
207+
(SqlDataTypeSpec) getCastSpec(mapSqlType.getValueType());
208+
SqlDataTypeSpec nonNullKeySpec =
209+
requireNonNull(keySpec, "keySpec");
210+
SqlDataTypeSpec nonNullValueSpec =
211+
requireNonNull(valueSpec, "valueSpec");
212+
SqlMapTypeNameSpec sqlMapTypeNameSpec =
213+
new SqlMapTypeNameSpec(nonNullKeySpec, nonNullValueSpec, SqlParserPos.ZERO);
214+
return new SqlDataTypeSpec(sqlMapTypeNameSpec,
215+
SqlParserPos.ZERO);
216+
case ARRAY:
217+
return RelToSqlConverterUtil.getCastSpecAngleBracketArrayType(this, type,
218+
SqlParserPos.ZERO);
219+
case MULTISET:
220+
throw new UnsupportedOperationException("StarRocks dialect does not support cast to "
221+
+ type.getSqlTypeName());
222+
default:
223+
break;
246224
}
247225

248226
return super.getCastSpec(type);

core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.calcite.rex.RexCall;
2222
import org.apache.calcite.rex.RexNode;
2323
import org.apache.calcite.rex.RexUtil;
24+
import org.apache.calcite.sql.SqlArrayWithAngleBracketsNameSpec;
2425
import org.apache.calcite.sql.SqlCall;
2526
import org.apache.calcite.sql.SqlCharStringLiteral;
2627
import org.apache.calcite.sql.SqlCollectionTypeNameSpec;
@@ -373,6 +374,22 @@ public static SqlDataTypeSpec getCastSpecClickHouseSqlArrayType(SqlDialect diale
373374
return new SqlDataTypeSpec(sqlArrayTypeNameSpec, SqlParserPos.ZERO);
374375
}
375376

377+
/**
378+
* Transformation ARRAY type from {@code VARCHAR ARRAY} to {@code Array<VARCHAR>}.
379+
*/
380+
public static SqlDataTypeSpec getCastSpecAngleBracketArrayType(SqlDialect dialect,
381+
RelDataType type, SqlParserPos pos) {
382+
ArraySqlType arraySqlType = (ArraySqlType) type;
383+
SqlDataTypeSpec arrayValueSpec =
384+
(SqlDataTypeSpec) dialect.getCastSpec(arraySqlType.getComponentType());
385+
SqlDataTypeSpec nonNullarrayValueSpec =
386+
requireNonNull(arrayValueSpec, "arrayValueSpec");
387+
SqlArrayWithAngleBracketsNameSpec sqlArrayTypeNameSpec =
388+
new SqlArrayWithAngleBracketsNameSpec(nonNullarrayValueSpec.getTypeNameSpec(),
389+
arraySqlType.getSqlTypeName(), pos);
390+
return new SqlDataTypeSpec(sqlArrayTypeNameSpec, SqlParserPos.ZERO);
391+
}
392+
376393
/**
377394
* ClickHouseSqlMapTypeNameSpec to parse or unparse SQL MAP type to {@code Map(VARCHAR, VARCHAR)}.
378395
*/

core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2604,6 +2604,27 @@ private SqlDialect nonOrdinalDialect() {
26042604
sql(query4).withCalcite().ok(expected4);
26052605
}
26062606

2607+
/** Test case for
2608+
* <a href="https://issues.apache.org/jira/browse/CALCITE-7114">[CALCITE-7114]
2609+
* Invalid unparse for cast to array type in Spark</a>.
2610+
*/
2611+
@Test void testCastArraySpark() {
2612+
final String query = "select cast(array['a','b','c']"
2613+
+ " as varchar array)";
2614+
final String expectedSpark = "SELECT CAST(ARRAY ('a', 'b', 'c') AS ARRAY< STRING >)\n"
2615+
+ "FROM (VALUES (0)) `t` (`ZERO`)";
2616+
sql(query)
2617+
.withSpark().ok(expectedSpark);
2618+
2619+
final String query1 = "select cast(array[array['a'], array['b'], array['c']]"
2620+
+ " as varchar array array)";
2621+
final String expectedSpark1 =
2622+
"SELECT CAST(ARRAY (ARRAY ('a'), ARRAY ('b'), ARRAY ('c')) AS ARRAY< ARRAY< STRING > >)\n"
2623+
+ "FROM (VALUES (0)) `t` (`ZERO`)";
2624+
sql(query1)
2625+
.withSpark().ok(expectedSpark1);
2626+
}
2627+
26072628
/** Test case for
26082629
* <a href="https://issues.apache.org/jira/browse/CALCITE-7055">[CALCITE-7055]
26092630
* Invalid unparse for cast to array type in StarRocks</a>.
@@ -10301,6 +10322,7 @@ private void checkLiteral2(String expression, String expected) {
1030110322
.withPhoenix().throws_("Phoenix dialect does not support cast to MULTISET")
1030210323
.withStarRocks().throws_("StarRocks dialect does not support cast to MULTISET")
1030310324
.withClickHouse().throws_("ClickHouse dialect does not support cast to MULTISET")
10325+
.withSpark().throws_("Spark dialect does not support cast to MULTISET")
1030410326
.withHive().throws_("Hive dialect does not support cast to MULTISET");
1030510327

1030610328
String query3 = "SELECT CAST(MAP[1.0,2.0,3.0,4.0] AS MAP<FLOAT, REAL>) FROM \"employee\"";

0 commit comments

Comments
 (0)