1 package com.mapd.calcite.parser;
3 import static org.apache.calcite.runtime.Resources.BaseMessage;
4 import static org.apache.calcite.runtime.Resources.ExInst;
8 import org.apache.calcite.linq4j.Ord;
9 import org.apache.calcite.rel.type.RelDataType;
10 import org.apache.calcite.runtime.CalciteException;
11 import org.apache.calcite.runtime.Resources;
12 import org.apache.calcite.sql.SqlBasicCall;
13 import org.apache.calcite.sql.SqlCall;
14 import org.apache.calcite.sql.SqlCallBinding;
15 import org.apache.calcite.sql.SqlFunctionCategory;
16 import org.apache.calcite.sql.SqlIdentifier;
17 import org.apache.calcite.sql.SqlKind;
18 import org.apache.calcite.sql.SqlNode;
19 import org.apache.calcite.sql.SqlOperandCountRange;
21 import org.apache.calcite.sql.SqlSyntax;
22 import org.apache.calcite.sql.SqlUtil;
23 import org.apache.calcite.sql.type.SqlOperandCountRanges;
24 import org.apache.calcite.sql.type.SqlOperandTypeChecker;
25 import org.apache.calcite.sql.type.SqlTypeName;
26 import org.apache.calcite.sql.validate.SqlNameMatchers;
27 import org.apache.calcite.sql.validate.SqlValidator;
28 import org.apache.calcite.sql.validate.SqlValidatorException;
29 import org.apache.calcite.sql.validate.SqlValidatorScope;
31 import java.util.ArrayList;
32 import java.util.Collections;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.List;
37 import java.util.NoSuchElementException;
39 import java.util.stream.Collectors;
40 import java.util.stream.IntStream;
59 Set<ExtTableFunction> candidateOverloads =
new HashSet<ExtTableFunction>(
62 for (SqlNode operand : callBinding.getCall().getOperandList()) {
63 if (operand != null && operand.getKind() == SqlKind.ARGUMENT_ASSIGNMENT) {
64 final SqlCall assignmentCall = (SqlCall) operand;
65 final SqlIdentifier
id = assignmentCall.operand(1);
66 final String paramName = id.getSimple();
67 if (!candidateOverloads.stream().anyMatch(
68 tf -> tf.getParamNames().
contains(paramName))) {
76 candidateOverloads.removeIf(tf
77 -> (callBinding.getOperandCount()
78 < (tf.getArgTypes().size() - tf.getNumOptionalArguments()))
79 || (callBinding.getOperandCount() > tf.getArgTypes().size()));
81 SqlNode[] operandArray =
new SqlNode[callBinding.getCall().getOperandList().size()];
82 for (Ord<SqlNode> arg : Ord.zip(callBinding.getCall().getOperandList())) {
83 operandArray[arg.i] = arg.e;
89 HashMap<ExtTableFunction, SqlCallBinding> candidateBindings =
90 new HashMap<>(candidateOverloads.size());
92 SqlBasicCall newCall =
new SqlBasicCall(
93 tf, operandArray, callBinding.getCall().getParserPosition());
94 SqlCallBinding candidateBinding =
new SqlCallBinding(
95 callBinding.getValidator(), callBinding.getScope(), newCall);
96 candidateBindings.put(tf, candidateBinding);
101 candidateOverloads.removeIf(tf
104 candidateBindings.get(tf)
109 -> candidateBindings.get(tf)
114 && !tf.isArgumentOptional(idx)));
119 Map<ExtTableFunction, Integer> scoredCandidates =
120 new HashMap<ExtTableFunction, Integer>();
121 candidateOverloads.stream().forEach(udtf
122 -> scoredCandidates.put(udtf,
128 minCandidate = Collections
129 .min(scoredCandidates.entrySet()
131 .filter(entry -> entry.getValue() >= 0)
132 .collect(Collectors.toSet()),
133 Map.Entry.comparingByValue())
135 }
catch (NoSuchElementException e) {
137 if (throwOnFailure) {
143 if (scoredCandidates.get(minCandidate) > 0) {
144 tc.extTableFunctionTypeCoercion(candidateBindings.get(minCandidate), minCandidate);
149 ((SqlBasicCall) callBinding.getCall()).setOperator(minCandidate);
155 List<SqlOperator> overloads =
new ArrayList<>();
156 opTable.lookupOperatorOverloads(op.getNameAsId(),
157 SqlFunctionCategory.USER_DEFINED_TABLE_FUNCTION,
160 SqlNameMatchers.liberal());
162 return overloads.stream()
164 .map(p -> (ExtTableFunction) p)
165 .collect(Collectors.toList());
169 return SqlOperandCountRanges.any();
174 return String.join(System.lineSeparator() +
"\t",
176 .map(tf -> tf.getExtendedSignature())
177 .collect(Collectors.toList()));
181 return Consistency.NONE;
185 SqlCallBinding callBinding, SqlNode operand, String operandName) {
186 return callBinding.getValidator().newValidationError(operand,
188 callBinding.getOperator().getName(), operandName));
192 return callBinding.getValidator().newValidationError(callBinding.permutedCall(),
193 UDTF_ERRORS.typeMismatch(callBinding.getOperator().getName(),
195 callBinding.getValidator(),
196 callBinding.getScope()),
197 System.getProperty(
"line.separator") +
"\t"
198 + callBinding.getOperator().getAllowedSignatures()));
204 SqlCallBinding callBinding, SqlValidator validator, SqlValidatorScope scope) {
205 List<String> signatureList =
new ArrayList<>();
206 for (
final SqlNode operand : callBinding.permutedCall().getOperandList()) {
207 final RelDataType argType = validator.deriveType(scope, operand);
208 if (null == argType) {
210 }
else if (argType.getSqlTypeName() == SqlTypeName.CURSOR) {
211 SqlCall cursorCall = (SqlCall) operand;
212 RelDataType cursorType = callBinding.getValidator().deriveType(
213 callBinding.getScope(), cursorCall.operand(0));
214 StringBuilder cursorTypeName =
new StringBuilder();
215 cursorTypeName.append(
"CURSOR[");
216 for (
int j = 0; j < cursorType.getFieldList().size(); j++) {
218 cursorTypeName.append(
",");
220 cursorTypeName.append(
221 cursorType.getFieldList().
get(j).getType().getSqlTypeName());
223 cursorTypeName.append(
"]");
224 signatureList.add(cursorTypeName.toString());
226 signatureList.add(argType.toString());
229 return SqlUtil.getOperatorSignature(callBinding.getOperator(), signatureList);
234 "No candidate for User-defined Table Function ''{0}'' with input parameter named ''{1}''")
235 ExInst<SqlValidatorException>
239 "Cannot apply User-defined Table Function ''{0}'' to arguments of type {1}. Supported form(s): {2}")
240 ExInst<SqlValidatorException>
241 typeMismatch(String udtf, String call, String overloads);
245 Resources.create(ExtTableFunctionErrors.class);
bool contains(const T &container, const U &element)
CalciteException newExtTableFunctionNameError(SqlCallBinding callBinding, SqlNode operand, String operandName)
final HeavyDBSqlOperatorTable opTable
ExInst< SqlValidatorException > paramNameMismatch(String udtf, String wrongParamName)
ExtTableFunctionTypeChecker(HeavyDBSqlOperatorTable opTable)
Consistency getConsistency()
CalciteException newExtTableFunctionSignatureError(SqlCallBinding callBinding)
int calculateTypeCoercionScore(SqlCallBinding callBinding, ExtTableFunction udtf)
static final ExtTableFunctionErrors UDTF_ERRORS
SqlOperandCountRange getOperandCountRange()
List< ExtTableFunction > getOperatorOverloads(SqlOperator op)
ExInst< SqlValidatorException > typeMismatch(String udtf, String call, String overloads)
boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure)
String getCallSignature(SqlCallBinding callBinding, SqlValidator validator, SqlValidatorScope scope)
boolean isOptional(int argIndex)
String getAllowedSignatures(SqlOperator op, String opName)