diff --git a/babel/src/test/resources/sql/big-query.iq b/babel/src/test/resources/sql/big-query.iq index c31141d2dba8..2818c7aa7b32 100755 --- a/babel/src/test/resources/sql/big-query.iq +++ b/babel/src/test/resources/sql/big-query.iq @@ -1937,7 +1937,7 @@ SELECT SELECT TIMESTAMP "2010-07-07 10:20:00" AS later_timestamp, TIMESTAMP "2008-12-25 15:30:00" AS earlier_timestamp, - TIMESTAMP_DIFF(TIMESTAMP "2010-07-07 10:20:00", TIMESTAMP "2008-12-25 15:30:00", HOUR) AS hours; + TIMESTAMP_DIFF(1, TIMESTAMP "2008-12-25 15:30:00", HOUR) AS hours; +---------------------+---------------------+-------+ | later_timestamp | earlier_timestamp | hours | +---------------------+---------------------+-------+ diff --git a/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java b/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java index e6271d23ec76..186c41a86a20 100644 --- a/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java +++ b/core/src/main/java/org/apache/calcite/prepare/CalciteCatalogReader.java @@ -16,8 +16,13 @@ */ package org.apache.calcite.prepare; +import com.google.common.collect.BiMap; + +import com.google.common.collect.HashBiMap; + import org.apache.calcite.config.CalciteConnectionConfig; import org.apache.calcite.jdbc.CalciteSchema; +import org.apache.calcite.jdbc.CalciteSchema.TypeEntry; import org.apache.calcite.jdbc.JavaTypeFactoryImpl; import org.apache.calcite.linq4j.function.Hints; import org.apache.calcite.model.ModelHandler; @@ -88,6 +93,7 @@ public class CalciteCatalogReader implements Prepare.CatalogReader { private final List> schemaPaths; protected final SqlNameMatcher nameMatcher; protected final CalciteConnectionConfig config; + protected BiMap aliasTypeMap; public CalciteCatalogReader(CalciteSchema rootSchema, List defaultSchema, RelDataTypeFactory typeFactory, CalciteConnectionConfig config) { @@ -108,6 +114,23 @@ protected CalciteCatalogReader(CalciteSchema rootSchema, : new LinkedHashSet<>(schemaPaths)); this.typeFactory = typeFactory; this.config = config; + this.aliasTypeMap = HashBiMap.create(); + populateAliasTypeMap(this.aliasTypeMap, rootSchema); + } + + + public static void populateAliasTypeMap(BiMap aliasTypeMap, + CalciteSchema schema) { + + for (String typeName: schema.getTypeNames()){ + TypeEntry typeEntry = schema.getType(typeName, true); + if (typeEntry!=null){ + aliasTypeMap.put(typeEntry, typeName); + } + } + for (CalciteSchema subschema: schema.getSubSchemaMap().values()){ + populateAliasTypeMap(aliasTypeMap, subschema); + } } @Override public CalciteCatalogReader withSchemaPath(List schemaPath) { @@ -172,8 +195,14 @@ private Collection getFunctionsFrom( } return functions2; } + // public @Nullable SqlIdentifier getNameFromType(RelDataType type) { + // // fill this out + // // SqlValidatorUtil.getNameFromType(getRootSchema(), type); + // return null; + // } @Override public @Nullable RelDataType getNamedType(SqlIdentifier typeName) { + // getRootSchema().schema. CalciteSchema.TypeEntry typeEntry = SqlValidatorUtil.getTypeEntry(getRootSchema(), typeName); if (typeEntry != null) { return typeEntry.getType().apply(typeFactory); @@ -452,4 +481,9 @@ private static RelDataType toSql(RelDataTypeFactory typeFactory, } return null; } + + @Override + public BiMap getAliasTypeMap() { + return aliasTypeMap; + } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java b/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java index 3504228944cf..ff9b52596510 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlCallBinding.java @@ -398,10 +398,13 @@ public SqlCall permutedCall() { * @return signature exception */ public CalciteException newValidationSignatureError() { + // String type = validator.getCatalogReader().getNamedType(call.getOperator() + // .getNameAsId()).getSqlTypeName().getName(); return validator.newValidationError(call, RESOURCE.canNotApplyOp2Type(getOperator().getName(), call.getCallSignature(validator, scope), - getOperator().getAllowedSignatures())); + // getOperator().getAllowedSignatures())); + getOperator().getAllowedSignaturesUsingValidator(validator))); } /** diff --git a/core/src/main/java/org/apache/calcite/sql/SqlHopTableFunction.java b/core/src/main/java/org/apache/calcite/sql/SqlHopTableFunction.java index 8c616b0f5673..123500ba4b7f 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlHopTableFunction.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlHopTableFunction.java @@ -16,6 +16,8 @@ */ package org.apache.calcite.sql; +import org.apache.calcite.sql.validate.SqlValidator; + import com.google.common.collect.ImmutableList; /** @@ -61,5 +63,11 @@ private static class OperandMetadataImpl extends AbstractOperandMetadata { return opName + "(TABLE table_name, DESCRIPTOR(timecol), " + "datetime interval, datetime interval[, datetime interval])"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return opName + "(TABLE table_name, DESCRIPTOR(timecol), " + + "datetime interval, datetime interval[, datetime interval])"; + } } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java index 466c1e74b868..e260d124a54d 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlOperator.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlOperator.java @@ -583,7 +583,6 @@ public RelDataType deriveType( RelDataType nodeType = validator.deriveType(scope, operand); assert nodeType != null; } - final List args = constructOperandList(validator, call, null); final List argTypes = constructArgTypeList(validator, scope, @@ -806,6 +805,9 @@ public final String getAllowedSignatures() { return getAllowedSignatures(name); } + public final String getAllowedSignaturesUsingValidator(SqlValidator validator) { + return getAllowedSignaturesUsingValidator(name, validator); + } /** * Returns a string describing the expected operand types of a call, e.g. * "SUBSTRING(VARCHAR, INTEGER, INTEGER)" where the name (SUBSTRING in this @@ -815,10 +817,18 @@ public String getAllowedSignatures(String opNameToUse) { requireNonNull(operandTypeChecker, "If you see this, assign operandTypeChecker a value " + "or override this function"); + // is validator available here? return operandTypeChecker.getAllowedSignatures(this, opNameToUse) .trim(); } + public String getAllowedSignaturesUsingValidator(String opNameToUse, SqlValidator validator) { + requireNonNull(operandTypeChecker, + "If you see this, assign operandTypeChecker a value " + + "or override this function"); + return operandTypeChecker.getAllowedSignaturesUsingValidator(this, opNameToUse, validator); + } + public @Nullable SqlOperandTypeInference getOperandTypeInference() { return operandTypeInference; } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlSessionTableFunction.java b/core/src/main/java/org/apache/calcite/sql/SqlSessionTableFunction.java index c031dea217f6..04a430a16098 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlSessionTableFunction.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlSessionTableFunction.java @@ -79,5 +79,11 @@ private static class OperandMetadataImpl extends AbstractOperandMetadata { return opName + "(TABLE table_name, DESCRIPTOR(timecol), " + "DESCRIPTOR(key) optional, datetime interval)"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return opName + "(TABLE table_name, DESCRIPTOR(timecol), " + + "DESCRIPTOR(key) optional, datetime interval)"; + } } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlTumbleTableFunction.java b/core/src/main/java/org/apache/calcite/sql/SqlTumbleTableFunction.java index 58e29208be88..c2a28c3cb1f3 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlTumbleTableFunction.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlTumbleTableFunction.java @@ -16,6 +16,8 @@ */ package org.apache.calcite.sql; +import org.apache.calcite.sql.validate.SqlValidator; + import com.google.common.collect.ImmutableList; /** @@ -62,5 +64,12 @@ private static class OperandMetadataImpl extends AbstractOperandMetadata { return opName + "(TABLE table_name, DESCRIPTOR(timecol), datetime interval" + "[, datetime interval])"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return opName + "(TABLE table_name, DESCRIPTOR(timecol), datetime interval" + + "[, datetime interval])"; + } + } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlUtil.java b/core/src/main/java/org/apache/calcite/sql/SqlUtil.java index 37c5afbe158b..3fe9473f7e2b 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlUtil.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlUtil.java @@ -38,6 +38,7 @@ import org.apache.calcite.sql.type.SqlTypeUtil; import org.apache.calcite.sql.util.SqlBasicVisitor; import org.apache.calcite.sql.validate.SqlNameMatcher; +import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.sql.validate.SqlValidatorUtil; import org.apache.calcite.util.BarfingInvocationHandler; import org.apache.calcite.util.ConversionUtil; @@ -905,6 +906,43 @@ public static String getAliasedSignature( return ret.toString(); } + public static String getAliasedSignatureWithValidator( + SqlOperator op, + String opName, + List typeList, + SqlValidator validator + ) { + StringBuilder ret = new StringBuilder(); + String template = op.getSignatureTemplate(typeList.size()); + if (null == template) { + ret.append("'"); + ret.append(opName); + ret.append("("); + for (int i = 0; i < typeList.size(); i++) { + if (i > 0) { + ret.append(", "); + } + final String t = String.valueOf(typeList.get(i)).toUpperCase(Locale.ROOT); + String aliasedType = SqlValidatorUtil.getAliasedTypeName(validator, t); + ret.append("<").append(aliasedType).append(">"); + } + ret.append(")'"); + } else { + Object[] values = new Object[typeList.size() + 1]; + values[0] = opName; + ret.append("'"); + for (int i = 0; i < typeList.size(); i++) { + final String t = String.valueOf(typeList.get(i)).toUpperCase(Locale.ROOT); + values[i + 1] = "<" + t + ">"; + } + ret.append(new MessageFormat(template, Locale.ROOT).format(values)); + ret.append("'"); + assert (typeList.size() + 1) == values.length; + } + + return ret.toString(); + } + /** * Wraps an exception with context. */ diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlItemOperator.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlItemOperator.java index 99d57822995e..42f19abf3d7f 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlItemOperator.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlItemOperator.java @@ -37,6 +37,8 @@ import java.util.Arrays; +import org.apache.calcite.sql.validate.SqlValidator; + import static org.apache.calcite.sql.type.NonNullableAccessors.getComponentTypeOrThrow; import static org.apache.calcite.sql.validate.SqlNonNullableAccessors.getOperandLiteralValueOrThrow; @@ -127,6 +129,11 @@ private static SqlSingleOperandTypeChecker getChecker(SqlCallBinding callBinding + "[|]"; } + @Override public String getAllowedSignaturesUsingValidator(String name, SqlValidator validator) { + return "[]\n" + + "[]\n" + + "[|]"; + } @Override public RelDataType inferReturnType(SqlOperatorBinding opBinding) { final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); final RelDataType operandType = opBinding.getOperandType(0); diff --git a/core/src/main/java/org/apache/calcite/sql/type/AssignableOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/AssignableOperandTypeChecker.java index 9f65e9ee470d..6f2e7c6cfa50 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/AssignableOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/AssignableOperandTypeChecker.java @@ -16,12 +16,17 @@ */ package org.apache.calcite.sql.type; +import java.util.stream.Stream; + +import org.apache.calcite.jdbc.CalciteSchema.TypeEntry; import org.apache.calcite.linq4j.Ord; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.sql.SqlCallBinding; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperandCountRange; import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.validate.SqlValidator; +import org.apache.calcite.sql.validate.SqlValidatorUtil; import org.apache.calcite.util.Pair; import com.google.common.collect.ImmutableList; @@ -102,4 +107,29 @@ public AssignableOperandTypeChecker(List paramTypes, sb.append(")"); return sb.toString(); } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + StringBuilder sb = new StringBuilder(); + // validator.getCatalogReader().alias + sb.append(opName); + sb.append("("); + for (Ord paramType : Ord.zip(paramTypes)) { + if (paramType.i > 0) { + sb.append(", "); + } + if (paramNames != null) { + String paramTypeName = paramNames.get(paramType.i); + // String aliasedName = SqlValidatorUtil.getAliasedTypeName(validator, paramTypeName); + String aliasedName = paramTypeName; + sb.append(aliasedName) + .append(" => "); + } + sb.append("<"); + sb.append(paramType.e.getFamily()); + sb.append(">"); + } + sb.append(")"); + return sb.toString(); + } } diff --git a/core/src/main/java/org/apache/calcite/sql/type/CompositeOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/CompositeOperandTypeChecker.java index 075ff788eb80..a7e2b8599a1a 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/CompositeOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/CompositeOperandTypeChecker.java @@ -21,6 +21,7 @@ import org.apache.calcite.sql.SqlCallBinding; import org.apache.calcite.sql.SqlOperandCountRange; import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.sql.validate.implicit.TypeCoercion; import org.apache.calcite.util.Util; @@ -154,6 +155,8 @@ public ImmutableList getRules() { if (ord.i > 0) { ret.append(SqlOperator.NL); } + // is call binding available here? + ret.append(ord.e.getAllowedSignatures(op, opName)); if (composition == Composition.AND) { break; @@ -162,6 +165,37 @@ public ImmutableList getRules() { return ret.toString(); } + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + if (allowedSignatures != null) { + return allowedSignatures; + } + if (signatureGenerator != null) { + return signatureGenerator.apply(op, opName); + } + if (composition == Composition.SEQUENCE) { + throw new AssertionError( + "specify allowedSignatures or override getAllowedSignatures"); + } + StringBuilder ret = new StringBuilder(); + for (Ord ord + : Ord.zip(allowedRules)) { + if (ord.i > 0) { + ret.append(SqlOperator.NL); + } + // is call binding available here? + ret.append("test"); + validator.getCatalogReader().getRootSchema(); + + ret.append(ord.e.getAllowedSignaturesUsingValidator(op, opName, validator)); + if (composition == Composition.AND) { + break; + } + } + return ret.toString(); + + } + @Override public SqlOperandCountRange getOperandCountRange() { switch (composition) { case REPEAT: diff --git a/core/src/main/java/org/apache/calcite/sql/type/ExplicitOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/ExplicitOperandTypeChecker.java index fb68086d347c..0426f5d2b173 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/ExplicitOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/ExplicitOperandTypeChecker.java @@ -21,6 +21,7 @@ import org.apache.calcite.sql.SqlCallBinding; import org.apache.calcite.sql.SqlOperandCountRange; import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.validate.SqlValidator; import java.util.ArrayList; import java.util.List; @@ -69,4 +70,9 @@ public ExplicitOperandTypeChecker(RelDataType type) { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return " " + opName + " "; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return " " + opName + " "; + } } diff --git a/core/src/main/java/org/apache/calcite/sql/type/FamilyOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/FamilyOperandTypeChecker.java index fd7338b7cbd8..30b419b6a4ac 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/FamilyOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/FamilyOperandTypeChecker.java @@ -23,6 +23,7 @@ import org.apache.calcite.sql.SqlOperandCountRange; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlUtil; +import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.sql.validate.implicit.TypeCoercion; import com.google.common.collect.ImmutableList; @@ -189,4 +190,9 @@ public class FamilyOperandTypeChecker implements SqlSingleOperandTypeChecker, @Override public String getAllowedSignatures(SqlOperator op, String opName) { return SqlUtil.getAliasedSignature(op, opName, families); } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return SqlUtil.getAliasedSignatureWithValidator(op, opName, families, validator); + } } diff --git a/core/src/main/java/org/apache/calcite/sql/type/IntervalOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/IntervalOperandTypeChecker.java index f86299ebbfea..1db6c2482799 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/IntervalOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/IntervalOperandTypeChecker.java @@ -20,6 +20,7 @@ import org.apache.calcite.sql.SqlIntervalQualifier; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.util.Static; import org.apache.calcite.util.Util; @@ -57,4 +58,9 @@ public class IntervalOperandTypeChecker implements SqlSingleOperandTypeChecker { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return ""; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return ""; + } } diff --git a/core/src/main/java/org/apache/calcite/sql/type/LiteralOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/LiteralOperandTypeChecker.java index 2c0309c8d4af..0aea8574fff0 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/LiteralOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/LiteralOperandTypeChecker.java @@ -20,6 +20,7 @@ import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlUtil; +import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.util.Util; import static org.apache.calcite.util.Static.RESOURCE; @@ -76,4 +77,9 @@ public LiteralOperandTypeChecker(boolean allowNull) { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return ""; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return ""; + } } diff --git a/core/src/main/java/org/apache/calcite/sql/type/MultisetOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/MultisetOperandTypeChecker.java index fec7eaa1dae6..98612994dd6c 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/MultisetOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/MultisetOperandTypeChecker.java @@ -21,6 +21,7 @@ import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperandCountRange; import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.validate.SqlValidator; import com.google.common.collect.ImmutableList; @@ -84,4 +85,9 @@ public class MultisetOperandTypeChecker implements SqlOperandTypeChecker { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return " " + opName + " "; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return " " + opName + " "; + } } diff --git a/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java b/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java index cd927392aa4a..d189e0ac02c0 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java +++ b/core/src/main/java/org/apache/calcite/sql/type/OperandTypes.java @@ -27,6 +27,7 @@ import org.apache.calcite.sql.SqlOperandCountRange; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlUtil; +import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.sql.validate.SqlValidatorScope; import org.apache.calcite.util.ImmutableIntList; import org.apache.calcite.util.Util; @@ -376,6 +377,11 @@ public static SqlOperandTypeChecker variadic( @Override public String getAllowedSignatures(SqlOperator op, String opName) { return opName + "(...)"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return opName + "(...)"; + } }; } @@ -774,7 +780,12 @@ public static SqlSingleOperandTypeChecker same(int operandCount, @Override public String getAllowedSignatures(SqlOperator op, String opName) { return opName + "(, )"; } - }; + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return opName + "(, )"; + } + }; public static final SqlSingleOperandTypeChecker CURSOR = family(SqlTypeFamily.CURSOR); @@ -912,6 +923,11 @@ public static SqlSingleOperandTypeChecker same(int operandCount, @Override public String getAllowedSignatures(SqlOperator op, String opName) { return "UNNEST()"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return "UNNEST()"; + } }; /** @@ -969,7 +985,12 @@ private RecordTypeWithOneFieldChecker(Predicate predicate) { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return "UNNEST()\nUNNEST()\nUNNEST()"; } - }); + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, + String opName, SqlValidator validator) { + return "UNNEST()\nUNNEST()\nUNNEST()"; + } + }); public static final SqlOperandTypeChecker MULTISET_MULTISET = new MultisetOperandTypeChecker(); @@ -1007,6 +1028,12 @@ private RecordTypeWithOneFieldChecker(Predicate predicate) { return SqlUtil.getAliasedSignature(op, opName, ImmutableList.of("RECORDTYPE(SINGLE FIELD)")); } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return SqlUtil.getAliasedSignature(op, opName, + ImmutableList.of("RECORDTYPE(SINGLE FIELD)")); + } }; /** Operand type-checker that accepts period types. Examples: @@ -1050,6 +1077,13 @@ private static class PeriodOperandTypeChecker ImmutableList.of("PERIOD (DATETIME, INTERVAL)", "PERIOD (DATETIME, DATETIME)")); } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return SqlUtil.getAliasedSignature(op, opName, + ImmutableList.of("PERIOD (DATETIME, INTERVAL)", + "PERIOD (DATETIME, DATETIME)")); + } } /** Checker that passes if the operand's type has a particular @@ -1083,5 +1117,10 @@ private static class TypeNameChecker implements SqlSingleOperandTypeChecker, @Override public String getAllowedSignatures(SqlOperator op, String opName) { return opName + "(" + typeName.getSpaceName() + ")"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return opName + "(" + typeName.getSpaceName() + ")"; + } } } diff --git a/core/src/main/java/org/apache/calcite/sql/type/SameOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/SameOperandTypeChecker.java index 4eb271dbfa2b..46179dd48edd 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/SameOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/SameOperandTypeChecker.java @@ -23,6 +23,7 @@ import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlOperatorBinding; import org.apache.calcite.sql.SqlUtil; +import org.apache.calcite.sql.validate.SqlValidator; import org.apache.calcite.util.Util; import com.google.common.collect.ImmutableList; @@ -132,6 +133,15 @@ public boolean checkOperandTypes( : Collections.nCopies(nOperands, typeName)); } + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + final String typeName = getTypeName(); + return SqlUtil.getAliasedSignature(op, opName, + nOperands == -1 + ? ImmutableList.of(typeName, typeName, "...") + : Collections.nCopies(nOperands, typeName)); + } + /** Override to change the behavior of * {@link #getAllowedSignatures(SqlOperator, String)}. */ protected String getTypeName() { diff --git a/core/src/main/java/org/apache/calcite/sql/type/SetopOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/SetopOperandTypeChecker.java index 6249cc9398af..a9dd9d87f22c 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/SetopOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/SetopOperandTypeChecker.java @@ -148,4 +148,9 @@ public class SetopOperandTypeChecker implements SqlOperandTypeChecker { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return "{0} " + opName + " {1}"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return "{0} " + opName + " {1}"; + } } diff --git a/core/src/main/java/org/apache/calcite/sql/type/SqlOperandTypeChecker.java b/core/src/main/java/org/apache/calcite/sql/type/SqlOperandTypeChecker.java index 2689f2a0dc28..70fce185585b 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/SqlOperandTypeChecker.java +++ b/core/src/main/java/org/apache/calcite/sql/type/SqlOperandTypeChecker.java @@ -19,6 +19,7 @@ import org.apache.calcite.sql.SqlCallBinding; import org.apache.calcite.sql.SqlOperandCountRange; import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.validate.SqlValidator; import org.checkerframework.checker.nullness.qual.Nullable; @@ -60,6 +61,8 @@ boolean checkOperandTypes( */ String getAllowedSignatures(SqlOperator op, String opName); + String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, SqlValidator validator); + /** Returns the strategy for making the arguments have consistency types. */ default Consistency getConsistency() { return Consistency.NONE; diff --git a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingSqlValidatorCatalogReader.java b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingSqlValidatorCatalogReader.java index 6f9b7531cbd2..e738f59fc5b1 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/DelegatingSqlValidatorCatalogReader.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/DelegatingSqlValidatorCatalogReader.java @@ -16,6 +16,12 @@ */ package org.apache.calcite.sql.validate; +import com.google.common.collect.BiMap; + +import com.google.common.collect.HashBiMap; + +import org.apache.calcite.jdbc.CalciteSchema.TypeEntry; +import org.apache.calcite.prepare.CalciteCatalogReader; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.sql.SqlIdentifier; @@ -31,6 +37,7 @@ public abstract class DelegatingSqlValidatorCatalogReader implements SqlValidatorCatalogReader { protected final SqlValidatorCatalogReader catalogReader; + final BiMap aliasTypeMap; /** * Creates a DelegatingSqlValidatorCatalogReader. @@ -40,6 +47,8 @@ public abstract class DelegatingSqlValidatorCatalogReader protected DelegatingSqlValidatorCatalogReader( SqlValidatorCatalogReader catalogReader) { this.catalogReader = catalogReader; + this.aliasTypeMap = HashBiMap.create(); + CalciteCatalogReader.populateAliasTypeMap(this.aliasTypeMap, catalogReader.getRootSchema()); } @Override public @Nullable SqlValidatorTable getTable(List names) { @@ -61,4 +70,8 @@ protected DelegatingSqlValidatorCatalogReader( @Override public @Nullable C unwrap(Class aClass) { return catalogReader.unwrap(aClass); } + + @Override public BiMap getAliasTypeMap() { + return catalogReader.getAliasTypeMap(); + } } diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorCatalogReader.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorCatalogReader.java index 65b12a4d5367..9319d7b82696 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorCatalogReader.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorCatalogReader.java @@ -16,8 +16,11 @@ */ package org.apache.calcite.sql.validate; +import com.google.common.collect.BiMap; + import org.apache.calcite.config.CalciteConnectionConfig; import org.apache.calcite.jdbc.CalciteSchema; +import org.apache.calcite.jdbc.CalciteSchema.TypeEntry; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeField; import org.apache.calcite.schema.Wrapper; @@ -117,4 +120,6 @@ RelDataType createTypeFromProjection(RelDataType type, /** Returns Config settings. */ CalciteConnectionConfig getConfig(); + + BiMap getAliasTypeMap(); } diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java index 99e52c5e4ed7..543189294188 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java @@ -1040,7 +1040,10 @@ private static void findAllValidFunctionNames( if ((op.getSyntax() == SqlSyntax.FUNCTION) || (op.getSyntax() == SqlSyntax.PREFIX)) { if (op.getOperandTypeChecker() != null) { + // is validator available here? yes + // validator.getCatalogReader().getTypeFromName(op.getName()) String sig = op.getAllowedSignatures(); + // String sig = op.getAllowedSignaturesUsingValidator(validator); sig = sig.replace("'", ""); result.add( new SqlMonikerImpl( diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java index 74e6c9ec59cc..235d520b3b67 100644 --- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java +++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorUtil.java @@ -16,10 +16,17 @@ */ package org.apache.calcite.sql.validate; +import java.util.ArrayDeque; +import java.util.Optional; +import java.util.Queue; + +import java.util.stream.Stream; + import org.apache.calcite.config.CalciteConnectionConfig; import org.apache.calcite.config.CalciteConnectionConfigImpl; import org.apache.calcite.config.CalciteConnectionProperty; import org.apache.calcite.jdbc.CalciteSchema; +import org.apache.calcite.jdbc.CalciteSchema.TypeEntry; import org.apache.calcite.linq4j.Linq4j; import org.apache.calcite.linq4j.Ord; import org.apache.calcite.plan.RelOptSchemaWithSampling; @@ -1039,6 +1046,25 @@ public static ImmutableList cube( return schema.getType(name, false); } + // public static SqlIdentifier getNameFromType( + // CalciteSchema rootSchema, RelDataType type) { + // // SqlIdentifier target = type.; + // Queue queue = new ArrayDeque<>(); + // queue.add(rootSchema); + // while(!queue.isEmpty()){ + // CalciteSchema currentSchema = queue.remove(); + // if currentSchema.getType + // } + // return null; + // } + public static String getAliasedTypeName(SqlValidator validator, String typeName){ + ImmutableList matches = validator.getCatalogReader().getAliasTypeMap().keySet().stream().filter(key -> + key.getType().apply(validator.getTypeFactory()).getSqlTypeName().getName() == typeName + ).collect(Util.toImmutableList()); + return matches.size() > 0 ? + matches.get(0).name : typeName; + } + /** * Finds a {@link org.apache.calcite.jdbc.CalciteSchema.TableEntry} in a * given catalog reader whose table has the given name, possibly qualified. diff --git a/piglet/src/main/java/org/apache/calcite/piglet/PigRelSqlUdfs.java b/piglet/src/main/java/org/apache/calcite/piglet/PigRelSqlUdfs.java index 3018929d511a..8897645ffa50 100644 --- a/piglet/src/main/java/org/apache/calcite/piglet/PigRelSqlUdfs.java +++ b/piglet/src/main/java/org/apache/calcite/piglet/PigRelSqlUdfs.java @@ -38,6 +38,7 @@ import org.apache.calcite.sql.type.SqlTypeFamily; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.sql.validate.SqlUserDefinedFunction; +import org.apache.calcite.sql.validate.SqlValidator; import org.apache.pig.FuncSpec; import org.apache.pig.data.BagFactory; @@ -220,6 +221,11 @@ private static SqlOperandMetadata multisetProjectionCheck() { return opName + "(...)"; } + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return opName + "(...)"; + } + @Override public List paramTypes( RelDataTypeFactory typeFactory) { return Functions.generate(paramCount, diff --git a/testkit/src/main/java/org/apache/calcite/test/MockSqlOperatorTable.java b/testkit/src/main/java/org/apache/calcite/test/MockSqlOperatorTable.java index 60e9e2559e65..1714bff362a2 100644 --- a/testkit/src/main/java/org/apache/calcite/test/MockSqlOperatorTable.java +++ b/testkit/src/main/java/org/apache/calcite/test/MockSqlOperatorTable.java @@ -271,7 +271,12 @@ private static class OperandMetadataImpl implements SqlOperandMetadata { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return "Score(TABLE table_name)"; - }; + } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return "Score(TABLE table_name)"; + } } } @@ -358,6 +363,11 @@ private static class OperandMetadataImpl implements SqlOperandMetadata { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return "TopN(TABLE table_name, BIGINT rows)"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return "TopN(TABLE table_name, BIGINT rows)"; + } } } @@ -427,6 +437,11 @@ private static class OperandMetadataImpl implements SqlOperandMetadata { @Override public String getAllowedSignatures(SqlOperator op, String opName) { return "SIMILARITY(TABLE table_name, TABLE table_name)"; } + + @Override public String getAllowedSignaturesUsingValidator(SqlOperator op, String opName, + SqlValidator validator) { + return "SIMILARITY(TABLE table_name, TABLE table_name)"; + } } } diff --git a/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java b/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java index 52bb25ea4b55..e2f410f9736a 100644 --- a/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java +++ b/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReader.java @@ -16,11 +16,16 @@ */ package org.apache.calcite.test.catalog; +import com.google.common.collect.BiMap; + +import com.google.common.collect.HashBiMap; + import org.apache.calcite.adapter.java.AbstractQueryableTable; import org.apache.calcite.adapter.java.JavaTypeFactory; import org.apache.calcite.config.CalciteConnectionConfig; import org.apache.calcite.jdbc.CalcitePrepare; import org.apache.calcite.jdbc.CalciteSchema; +import org.apache.calcite.jdbc.CalciteSchema.TypeEntry; import org.apache.calcite.jdbc.JavaTypeFactoryImpl; import org.apache.calcite.linq4j.QueryProvider; import org.apache.calcite.linq4j.Queryable; @@ -115,6 +120,7 @@ public abstract class MockCatalogReader extends CalciteCatalogReader { static final String DEFAULT_SCHEMA = "SALES"; static final List PREFIX = ImmutableList.of(DEFAULT_SCHEMA); + static BiMap aliasTypeMap = HashBiMap.create(); /** * Creates a MockCatalogReader. * diff --git a/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReaderSimple.java b/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReaderSimple.java index 4418b7a4b8f6..4bcf31859a55 100644 --- a/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReaderSimple.java +++ b/testkit/src/main/java/org/apache/calcite/test/catalog/MockCatalogReaderSimple.java @@ -16,6 +16,11 @@ */ package org.apache.calcite.test.catalog; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +import org.apache.calcite.jdbc.CalciteSchema.TypeEntry; +import org.apache.calcite.prepare.CalciteCatalogReader; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeField; @@ -45,6 +50,7 @@ */ public class MockCatalogReaderSimple extends MockCatalogReader { private final ObjectSqlType addressType; + static BiMap aliasTypeMap; /** * Creates a MockCatalogReader. @@ -60,6 +66,7 @@ protected MockCatalogReaderSimple(RelDataTypeFactory typeFactory, super(typeFactory, caseSensitive); addressType = new Fixture(typeFactory).addressType; + this.aliasTypeMap = HashBiMap.create(); } /** Creates and initializes a MockCatalogReaderSimple. */ @@ -439,6 +446,7 @@ protected MockCatalogReaderSimple(RelDataTypeFactory typeFactory, } registerTable(struct10View); registerTablesWithRollUp(salesSchema, fixture); + populateAliasTypeMap(aliasTypeMap, getRootSchema()); return this; }