diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java index 18abd1997532..2f8517a94048 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java @@ -955,10 +955,38 @@ static RelDataType deriveTypeSplit(SqlOperatorBinding operatorBinding, .withKind(SqlKind.CONCAT_WS_MSSQL); private static RelDataType arrayReturnType(SqlOperatorBinding opBinding) { - RelDataType type = - opBinding.getOperandCount() > 0 - ? ReturnTypes.LEAST_RESTRICTIVE.inferReturnType(opBinding) - : opBinding.getTypeFactory().createUnknownType(); + // only numeric & character types check + List numericTypes = new ArrayList<>(); + List characterTypes = new ArrayList<>(); + List nullTypes = new ArrayList<>(); + for (int i = 0; i < opBinding.getOperandCount(); i++) { + SqlTypeFamily family = opBinding.getOperandType(i).getSqlTypeName().getFamily(); + if (family == SqlTypeFamily.NUMERIC) { + numericTypes.add(opBinding.getOperandType(i)); + } else if (family == SqlTypeFamily.CHARACTER) { + characterTypes.add(opBinding.getOperandType(i)); + } else if (family == SqlTypeFamily.NULL) { + nullTypes.add(opBinding.getOperandType(i)); + } else { + break; + } + } + + boolean onlyNumericCharacterTypes = opBinding.getOperandCount() > 0 + && numericTypes.size() > 0 && characterTypes.size() > 0 + && numericTypes.size() + characterTypes.size() + nullTypes.size() + == opBinding.getOperandCount(); + RelDataType type; + if (onlyNumericCharacterTypes) { + List types = new ArrayList<>(characterTypes); + types.addAll(nullTypes); + type = opBinding.getTypeFactory().leastRestrictive(types); + } else { + type = + opBinding.getOperandCount() > 0 + ? ReturnTypes.LEAST_RESTRICTIVE.inferReturnType(opBinding) + : opBinding.getTypeFactory().createUnknownType(); + } requireNonNull(type, "inferred array element type"); return SqlTypeUtil.createArrayType(opBinding.getTypeFactory(), type, false); } diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java index 7771cf1948ba..c9c2e9037b0e 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -8894,6 +8894,14 @@ private static void checkArrayConcatAggFuncFails(SqlOperatorFixture t) { "[null, foo]", "CHAR(3) ARRAY NOT NULL"); f2.checkScalar("array(null)", "[null]", "NULL ARRAY NOT NULL"); + f2.checkScalar("array(1, 2, 'Hi')", + "[1, 2, Hi]", "CHAR(2) NOT NULL ARRAY NOT NULL"); + f2.checkScalar("array(1, 2, 'Hi', 'Hello')", + "[1, 2, Hi, Hello]", "CHAR(5) NOT NULL ARRAY NOT NULL"); + f2.checkScalar("array(1, 2, 'Hi', null)", + "[1, 2, Hi, null]", "CHAR(2) ARRAY NOT NULL"); + f2.checkScalar("array(1, 2, 'Hi', cast(null as char(10)))", + "[1, 2, Hi, null]", "CHAR(10) ARRAY NOT NULL"); } /**