Skip to content

Commit 2fddb55

Browse files
nokiaMSgithubgxll
authored andcommitted
[fix][core] Union all cast.
1 parent 03ba900 commit 2fddb55

File tree

10 files changed

+81
-13
lines changed

10 files changed

+81
-13
lines changed

core/src/main/java/org/apache/calcite/plan/RelOptNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.apache.calcite.plan;
1818

1919
import org.apache.calcite.rel.type.RelDataType;
20+
import org.apache.calcite.sql.SqlOperator;
2021

2122
import java.util.List;
2223

@@ -65,6 +66,8 @@ public interface RelOptNode {
6566
// may not even be known at planning time.
6667
RelDataType getRowType();
6768

69+
RelDataType getRowTypeWithContext(SqlOperator.CallContext context);
70+
6871
/**
6972
* Returns a string which describes the relational expression and, unlike
7073
* {@link #getDigest()}, also includes the identity. Typically returns

core/src/main/java/org/apache/calcite/rel/AbstractRelNode.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,16 @@
2828
import org.apache.calcite.rel.core.CorrelationId;
2929
import org.apache.calcite.rel.hint.Hintable;
3030
import org.apache.calcite.rel.hint.RelHint;
31+
import org.apache.calcite.rel.logical.LogicalRepeatUnion;
32+
import org.apache.calcite.rel.logical.LogicalUnion;
3133
import org.apache.calcite.rel.metadata.Metadata;
3234
import org.apache.calcite.rel.metadata.MetadataFactory;
3335
import org.apache.calcite.rel.metadata.RelMetadataQuery;
3436
import org.apache.calcite.rel.type.RelDataType;
3537
import org.apache.calcite.rex.RexShuttle;
3638
import org.apache.calcite.sql.SqlExplainLevel;
39+
import org.apache.calcite.sql.SqlKind;
40+
import org.apache.calcite.sql.SqlOperator;
3741
import org.apache.calcite.util.Litmus;
3842
import org.apache.calcite.util.Pair;
3943
import org.apache.calcite.util.Util;
@@ -168,14 +172,36 @@ protected static <T> T sole(List<T> collection) {
168172
return litmus.succeed();
169173
}
170174

171-
@Override public final RelDataType getRowType() {
175+
@Override public RelDataType getRowType() {
172176
if (rowType == null) {
173-
rowType = deriveRowType();
177+
if(this instanceof LogicalUnion) {
178+
if (((LogicalUnion)this).kind == SqlKind.UNION) {
179+
rowType = deriveRowTypeWithContext(SqlOperator.CallContext.IN_UNION);
180+
} else {
181+
rowType = deriveRowType();
182+
}
183+
} else {
184+
rowType = deriveRowType();
185+
}
174186
assert rowType != null : this;
175187
}
176188
return rowType;
177189
}
178190

191+
@Override public final RelDataType getRowTypeWithContext(SqlOperator.CallContext context) {
192+
if (rowType == null) {
193+
rowType = deriveRowTypeWithContext(context);
194+
assert rowType != null : this;
195+
}
196+
return rowType;
197+
}
198+
199+
protected RelDataType deriveRowTypeWithContext(SqlOperator.CallContext context) {
200+
// This method is only called if rowType is null, so you don't NEED to
201+
// implement it if rowType is always set.
202+
throw new UnsupportedOperationException();
203+
}
204+
179205
protected RelDataType deriveRowType() {
180206
// This method is only called if rowType is null, so you don't NEED to
181207
// implement it if rowType is always set.

core/src/main/java/org/apache/calcite/rel/RelNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.calcite.rel.type.RelDataType;
3131
import org.apache.calcite.rex.RexNode;
3232
import org.apache.calcite.rex.RexShuttle;
33+
import org.apache.calcite.sql.SqlOperator;
3334
import org.apache.calcite.util.Litmus;
3435

3536
import org.apiguardian.api.API;
@@ -115,6 +116,8 @@ public interface RelNode extends RelOptNode, Cloneable {
115116
*/
116117
@Override RelDataType getRowType();
117118

119+
@Override RelDataType getRowTypeWithContext(SqlOperator.CallContext context);
120+
118121
/**
119122
* Returns the type of the rows expected for an input. Defaults to
120123
* {@link #getRowType}.

core/src/main/java/org/apache/calcite/rel/core/SetOp.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.calcite.rel.hint.RelHint;
2929
import org.apache.calcite.rel.type.RelDataType;
3030
import org.apache.calcite.sql.SqlKind;
31+
import org.apache.calcite.sql.SqlOperator;
3132
import org.apache.calcite.util.Util;
3233

3334
import com.google.common.base.Preconditions;
@@ -113,10 +114,14 @@ public abstract SetOp copy(
113114
}
114115

115116
@Override protected RelDataType deriveRowType() {
117+
return deriveRowTypeWithContext(SqlOperator.CallContext.INVALID);
118+
}
119+
120+
@Override protected RelDataType deriveRowTypeWithContext(SqlOperator.CallContext context) {
116121
final List<RelDataType> inputRowTypes =
117122
Util.transform(inputs, RelNode::getRowType);
118123
final RelDataType rowType =
119-
getCluster().getTypeFactory().leastRestrictive(inputRowTypes);
124+
getCluster().getTypeFactory().leastRestrictiveWithContext(inputRowTypes, context);
120125
if (rowType == null) {
121126
throw new IllegalArgumentException("Cannot compute compatible row type "
122127
+ "for arguments to set op: "

core/src/main/java/org/apache/calcite/rel/type/RelDataTypeFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.apache.calcite.avatica.util.TimeUnit;
2020
import org.apache.calcite.sql.SqlCollation;
2121
import org.apache.calcite.sql.SqlIntervalQualifier;
22+
import org.apache.calcite.sql.SqlOperator;
2223
import org.apache.calcite.sql.parser.SqlParserPos;
2324
import org.apache.calcite.sql.type.SqlTypeName;
2425
import org.apache.calcite.sql.validate.SqlValidatorUtil;
@@ -208,6 +209,8 @@ RelDataType createTypeWithCharsetAndCollation(
208209
*/
209210
@Nullable RelDataType leastRestrictive(List<RelDataType> types);
210211

212+
@Nullable RelDataType leastRestrictiveWithContext(List<RelDataType> types, SqlOperator.CallContext context);
213+
211214
/**
212215
* Creates a SQL type with no precision or scale.
213216
*

core/src/main/java/org/apache/calcite/rel/type/RelDataTypeFactoryImpl.java

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import org.apache.calcite.linq4j.tree.Primitive;
2020
import org.apache.calcite.sql.SqlCollation;
21+
import org.apache.calcite.sql.SqlOperator;
2122
import org.apache.calcite.sql.type.ArraySqlType;
2223
import org.apache.calcite.sql.type.JavaToSqlTypeConversionRules;
2324
import org.apache.calcite.sql.type.MapSqlType;
@@ -212,18 +213,27 @@ private RelDataType createStructType(
212213
}, nullable);
213214
}
214215

215-
@Override public @Nullable RelDataType leastRestrictive(List<RelDataType> types) {
216+
@Override public @Nullable RelDataType leastRestrictiveWithContext(List<RelDataType> types, SqlOperator.CallContext context) {
216217
assert types != null;
217218
assert types.size() >= 1;
218219
RelDataType type0 = types.get(0);
219220
if (type0.isStruct()) {
220-
return leastRestrictiveStructuredType(types);
221+
return leastRestrictiveStructuredTypeWithContext(types, context);
221222
}
222223
return null;
223224
}
224225

226+
@Override public @Nullable RelDataType leastRestrictive(List<RelDataType> types) {
227+
return leastRestrictiveWithContext(types, SqlOperator.CallContext.INVALID);
228+
}
229+
225230
protected @Nullable RelDataType leastRestrictiveStructuredType(
226-
final List<RelDataType> types) {
231+
final List<RelDataType> types) {
232+
return leastRestrictiveStructuredTypeWithContext(types, SqlOperator.CallContext.INVALID);
233+
}
234+
235+
protected @Nullable RelDataType leastRestrictiveStructuredTypeWithContext(
236+
final List<RelDataType> types, SqlOperator.CallContext context) {
227237
final RelDataType type0 = types.get(0);
228238
// precheck that fieldCount is present
229239
if (!type0.isStruct()) {
@@ -251,8 +261,8 @@ private RelDataType createStructType(
251261
// first type?
252262
final int k = j;
253263

254-
RelDataType type = leastRestrictive(
255-
Util.transform(types, t -> t.getFieldList().get(k).getType())
264+
RelDataType type = leastRestrictiveWithContext(
265+
Util.transform(types, t -> t.getFieldList().get(k).getType()), context
256266
);
257267
if (type == null) {
258268
return null;

core/src/main/java/org/apache/calcite/sql/SqlOperator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public abstract class SqlOperator {
8585
*/
8686
public static final int MDX_PRECEDENCE = 200;
8787

88-
public static enum CallContext{INVALID, IN_VALUES, IN_UPDATE_SOURCE};
88+
public static enum CallContext{INVALID, IN_VALUES, IN_UPDATE_SOURCE, IN_UNION};
8989

9090
//~ Instance fields --------------------------------------------------------
9191

core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.apache.calcite.sql.SqlCollation;
2929
import org.apache.calcite.sql.SqlKind;
3030
import org.apache.calcite.sql.SqlNodeList;
31+
import org.apache.calcite.sql.SqlOperator;
3132
import org.apache.calcite.sql.SqlOperatorBinding;
3233
import org.apache.calcite.sql.SqlUtil;
3334
import org.apache.calcite.sql.validate.SqlValidatorNamespace;
@@ -440,8 +441,14 @@ public static SqlCall stripSeparator(SqlCall call) {
440441
* @see Glossary#SQL99 SQL:1999 Part 2 Section 9.3
441442
*/
442443
public static final SqlReturnTypeInference LEAST_RESTRICTIVE =
443-
opBinding -> opBinding.getTypeFactory().leastRestrictive(
444-
opBinding.collectOperandTypes());
444+
opBinding -> {
445+
if(opBinding.getOperator().getKind() == SqlKind.UNION) {
446+
return opBinding.getTypeFactory().leastRestrictiveWithContext(
447+
opBinding.collectOperandTypes(), SqlOperator.CallContext.IN_UNION);
448+
}
449+
return opBinding.getTypeFactory().leastRestrictive(
450+
opBinding.collectOperandTypes());
451+
};
445452

446453
/**
447454
* Returns the same type as the multiset carries. The multiset type returned

core/src/main/java/org/apache/calcite/sql/type/SetopOperandTypeChecker.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.apache.calcite.rel.type.RelDataType;
2020
import org.apache.calcite.rel.type.RelDataTypeField;
2121
import org.apache.calcite.sql.SqlCallBinding;
22+
import org.apache.calcite.sql.SqlKind;
2223
import org.apache.calcite.sql.SqlNode;
2324
import org.apache.calcite.sql.SqlOperandCountRange;
2425
import org.apache.calcite.sql.SqlOperator;
@@ -108,8 +109,13 @@ public class SetopOperandTypeChecker implements SqlOperandTypeChecker {
108109
}
109110
};
110111

112+
SqlOperator.CallContext context = SqlOperator.CallContext.INVALID;
113+
if(callBinding.getOperator().getKind() == SqlKind.UNION) {
114+
context = SqlOperator.CallContext.IN_UNION;
115+
}
116+
111117
final RelDataType type =
112-
callBinding.getTypeFactory().leastRestrictive(columnIthTypes);
118+
callBinding.getTypeFactory().leastRestrictiveWithContext(columnIthTypes, context);
113119
if (type == null) {
114120
boolean coerced = false;
115121
if (callBinding.isTypeCoercionEnabled()) {

core/src/main/java/org/apache/calcite/sql/type/SqlTypeFactoryImpl.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.apache.calcite.rel.type.RelDataTypeSystem;
2424
import org.apache.calcite.sql.SqlCollation;
2525
import org.apache.calcite.sql.SqlIntervalQualifier;
26+
import org.apache.calcite.sql.SqlOperator;
2627
import org.apache.calcite.util.Util;
2728

2829
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -238,6 +239,10 @@ private static void assertBasic(SqlTypeName typeName) {
238239
}
239240

240241
private @Nullable RelDataType leastRestrictiveSqlType(List<RelDataType> types) {
242+
return leastRestrictiveSqlTypeWithContext(types, SqlOperator.CallContext.INVALID);
243+
}
244+
245+
private @Nullable RelDataType leastRestrictiveSqlTypeWithContext(List<RelDataType> types, SqlOperator.CallContext context) {
241246
RelDataType resultType = null;
242247
int nullCount = 0;
243248
int nullableCount = 0;
@@ -294,7 +299,7 @@ private static void assertBasic(SqlTypeName typeName) {
294299
resultType = type;
295300
SqlTypeName sqlTypeName = resultType.getSqlTypeName();
296301
if (sqlTypeName == SqlTypeName.ROW) {
297-
return leastRestrictiveStructuredType(types);
302+
return leastRestrictiveStructuredTypeWithContext(types, context);
298303
}
299304
if (sqlTypeName == SqlTypeName.ARRAY
300305
|| sqlTypeName == SqlTypeName.MULTISET) {

0 commit comments

Comments
 (0)