use of org.apache.calcite.sql.SqlCallBinding in project calcite by apache.
the class TableFunctionReturnTypeInference method addOutputColumn.
private void addOutputColumn(List<String> expandedFieldNames, List<RelDataType> expandedOutputTypes, int iInputColumn, int iCursor, SqlOperatorBinding opBinding, RelDataTypeField cursorField) {
columnMappings.add(new RelColumnMapping(expandedFieldNames.size(), iCursor, iInputColumn, !isPassthrough));
// As a special case, system fields are implicitly NOT NULL.
// A badly behaved UDX can still provide NULL values, so the
// system must ensure that each generated system field has a
// reasonable value.
boolean nullable = true;
if (opBinding instanceof SqlCallBinding) {
SqlCallBinding sqlCallBinding = (SqlCallBinding) opBinding;
if (sqlCallBinding.getValidator().isSystemField(cursorField)) {
nullable = false;
}
}
RelDataType nullableType = opBinding.getTypeFactory().createTypeWithNullability(cursorField.getType(), nullable);
// Make sure there are no duplicates in the output column names
for (String fieldName : expandedFieldNames) {
if (fieldName.equals(cursorField.getName())) {
throw opBinding.newError(RESOURCE.duplicateColumnName(cursorField.getName()));
}
}
expandedOutputTypes.add(nullableType);
expandedFieldNames.add(cursorField.getName());
}
use of org.apache.calcite.sql.SqlCallBinding in project flink by apache.
the class SqlCastFunction method inferReturnType.
// ~ Methods ----------------------------------------------------------------
public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
assert opBinding.getOperandCount() == 2;
RelDataType ret = opBinding.getOperandType(1);
RelDataType firstType = opBinding.getOperandType(0);
ret = opBinding.getTypeFactory().createTypeWithNullability(ret, firstType.isNullable());
if (opBinding instanceof SqlCallBinding) {
SqlCallBinding callBinding = (SqlCallBinding) opBinding;
SqlNode operand0 = callBinding.operand(0);
// to them using the type they are casted to.
if (((operand0 instanceof SqlLiteral) && (((SqlLiteral) operand0).getValue() == null)) || (operand0 instanceof SqlDynamicParam)) {
final SqlValidatorImpl validator = (SqlValidatorImpl) callBinding.getValidator();
validator.setValidatedNodeType(operand0, ret);
}
}
return ret;
}
use of org.apache.calcite.sql.SqlCallBinding in project flink by apache.
the class SqlValidatorImpl method validatePivot.
public void validatePivot(SqlPivot pivot) {
final PivotScope scope = (PivotScope) getJoinScope(pivot);
final PivotNamespace ns = getNamespace(pivot).unwrap(PivotNamespace.class);
assert ns.rowType == null;
// Given
// query PIVOT (agg1 AS a, agg2 AS b, ...
// FOR (axis1, ..., axisN)
// IN ((v11, ..., v1N) AS label1,
// (v21, ..., v2N) AS label2, ...))
// the type is
// k1, ... kN, a_label1, b_label1, ..., a_label2, b_label2, ...
// where k1, ... kN are columns that are not referenced as an argument to
// an aggregate or as an axis.
// Aggregates, e.g. "PIVOT (sum(x) AS sum_x, count(*) AS c)"
final List<Pair<String, RelDataType>> aggNames = new ArrayList<>();
pivot.forEachAgg((alias, call) -> {
call.validate(this, scope);
final RelDataType type = deriveType(scope, call);
aggNames.add(Pair.of(alias, type));
if (!(call instanceof SqlCall) || !(((SqlCall) call).getOperator() instanceof SqlAggFunction)) {
throw newValidationError(call, RESOURCE.pivotAggMalformed());
}
});
// Axes, e.g. "FOR (JOB, DEPTNO)"
final List<RelDataType> axisTypes = new ArrayList<>();
final List<SqlIdentifier> axisIdentifiers = new ArrayList<>();
for (SqlNode axis : pivot.axisList) {
SqlIdentifier identifier = (SqlIdentifier) axis;
identifier.validate(this, scope);
final RelDataType type = deriveType(scope, identifier);
axisTypes.add(type);
axisIdentifiers.add(identifier);
}
// Columns that have been seen as arguments to aggregates or as axes
// do not appear in the output.
final Set<String> columnNames = pivot.usedColumnNames();
final RelDataTypeFactory.Builder typeBuilder = typeFactory.builder();
scope.getChild().getRowType().getFieldList().forEach(field -> {
if (!columnNames.contains(field.getName())) {
typeBuilder.add(field);
}
});
// Values, e.g. "IN (('CLERK', 10) AS c10, ('MANAGER, 20) AS m20)"
pivot.forEachNameValues((alias, nodeList) -> {
if (nodeList.size() != axisTypes.size()) {
throw newValidationError(nodeList, RESOURCE.pivotValueArityMismatch(nodeList.size(), axisTypes.size()));
}
final SqlOperandTypeChecker typeChecker = OperandTypes.COMPARABLE_UNORDERED_COMPARABLE_UNORDERED;
Pair.forEach(axisIdentifiers, nodeList, (identifier, subNode) -> {
subNode.validate(this, scope);
typeChecker.checkOperandTypes(new SqlCallBinding(this, scope, SqlStdOperatorTable.EQUALS.createCall(subNode.getParserPosition(), identifier, subNode)), true);
});
Pair.forEach(aggNames, (aggAlias, aggType) -> typeBuilder.add(aggAlias == null ? alias : alias + "_" + aggAlias, aggType));
});
final RelDataType rowType = typeBuilder.build();
ns.setType(rowType);
}
use of org.apache.calcite.sql.SqlCallBinding in project hazelcast by hazelcast.
the class HazelcastInOperator method deriveType.
@Override
public RelDataType deriveType(SqlValidator validator, SqlValidatorScope scope, SqlCall call) {
final List<SqlNode> operands = call.getOperandList();
assert operands.size() == 2;
final SqlNode left = operands.get(0);
final SqlNode right = operands.get(1);
final RelDataTypeFactory typeFactory = validator.getTypeFactory();
RelDataType leftType = validator.deriveType(scope, left);
RelDataType rightType;
// Derive type for RHS.
if (right instanceof SqlNodeList) {
// Handle the 'IN (expr, ...)' form.
List<RelDataType> rightTypeList = new ArrayList<>();
SqlNodeList nodeList = (SqlNodeList) right;
for (SqlNode node : nodeList) {
if (node instanceof SqlLiteral) {
SqlLiteral lit = (SqlLiteral) node;
// We are not supporting raw NULL literals within IN right-hand side list.
if (lit.getValue() == null) {
throw validator.newValidationError(right, HZRESOURCE.noRawNullsAllowed());
}
}
RelDataType nodeType = validator.deriveType(scope, node);
rightTypeList.add(nodeType);
}
rightType = typeFactory.leastRestrictive(rightTypeList);
// Same rules as the VALUES operator (per SQL:2003 Part 2 Section 8.4, <in predicate>).
if (null == rightType && validator.config().typeCoercionEnabled()) {
// Do implicit type cast if it is allowed to.
rightType = validator.getTypeCoercion().getWiderTypeFor(rightTypeList, false);
}
if (null == rightType) {
throw validator.newValidationError(right, RESOURCE.incompatibleTypesInList());
}
// Record the RHS type for use by SqlToRelConverter.
validator.setValidatedNodeType(nodeList, rightType);
} else {
// We do not support sub-querying for IN operator.
throw validator.newValidationError(call, HZRESOURCE.noSubQueryAllowed());
}
HazelcastCallBinding hazelcastCallBinding = prepareBinding(new SqlCallBinding(validator, scope, call));
// Coerce type first.
if (hazelcastCallBinding.isTypeCoercionEnabled()) {
boolean coerced = hazelcastCallBinding.getValidator().getTypeCoercion().inOperationCoercion(hazelcastCallBinding);
if (coerced) {
// Update the node data type if we coerced any type.
leftType = validator.deriveType(scope, call.operand(0));
rightType = validator.deriveType(scope, call.operand(1));
}
}
// Now check that the left expression is compatible with the
// type of the list. Same strategy as the '=' operator.
// Normalize the types on both sides to be row types
// for the purposes of compatibility-checking.
RelDataType leftRowType = SqlTypeUtil.promoteToRowType(typeFactory, leftType, null);
RelDataType rightRowType = SqlTypeUtil.promoteToRowType(typeFactory, rightType, null);
final ComparableOperandTypeChecker checker = (ComparableOperandTypeChecker) OperandTypes.COMPARABLE_UNORDERED_COMPARABLE_UNORDERED;
if (!checker.checkOperandTypes(new ExplicitOperatorBinding(hazelcastCallBinding, ImmutableList.of(leftRowType, rightRowType)), hazelcastCallBinding)) {
throw validator.newValidationError(call, RESOURCE.incompatibleValueType(SqlStdOperatorTable.IN.getName()));
}
return typeFactory.createTypeWithNullability(typeFactory.createSqlType(SqlTypeName.BOOLEAN), anyNullable(leftRowType.getFieldList()) || anyNullable(rightRowType.getFieldList()));
}
use of org.apache.calcite.sql.SqlCallBinding in project hazelcast by hazelcast.
the class HazelcastCaseOperator method checkOperandTypes.
@Override
@SuppressWarnings("checkstyle:MethodLength")
public boolean checkOperandTypes(SqlCallBinding callBinding, boolean throwOnFailure) {
HazelcastSqlValidator validator = (HazelcastSqlValidator) callBinding.getValidator();
HazelcastSqlCase sqlCall = (HazelcastSqlCase) callBinding.getCall();
// at this point `CASE x WHEN y ...` is already converted to `CASE WHEN x=y ...`
assert sqlCall.getValueOperand() == null;
SqlNodeList whenList = sqlCall.getWhenOperands();
SqlNodeList thenList = sqlCall.getThenOperands();
SqlNode elseOperand = sqlCall.getElseOperand();
assert whenList.size() > 0 : "no WHEN clause";
assert whenList.size() == thenList.size();
SqlValidatorScope scope = callBinding.getScope();
if (!typeCheckWhen(scope, validator, whenList)) {
if (throwOnFailure) {
throw callBinding.newError(RESOURCE.expectedBoolean());
}
return false;
}
List<RelDataType> argTypes = new ArrayList<>(thenList.size() + 1);
for (SqlNode node : thenList) {
argTypes.add(validator.deriveType(scope, node));
}
argTypes.add(validator.deriveType(scope, elseOperand));
// noinspection OptionalGetWithoutIsPresent
RelDataType caseReturnType = argTypes.stream().reduce(HazelcastTypeUtils::withHigherPrecedence).get();
Supplier<CalciteContextException> exceptionSupplier = () -> validator.newValidationError(sqlCall, HazelcastResources.RESOURCES.cannotInferCaseResult(argTypes.toString(), "CASE"));
for (int i = 0; i < thenList.size(); i++) {
int finalI = i;
if (!coerceItem(validator, scope, thenList.get(i), caseReturnType, sqlNode -> thenList.getList().set(finalI, sqlNode), throwOnFailure, exceptionSupplier)) {
return false;
}
}
return coerceItem(validator, scope, elseOperand, caseReturnType, sqlNode -> sqlCall.setOperand(ELSE_BRANCH_OPERAND_INDEX, sqlNode), throwOnFailure, exceptionSupplier);
}
Aggregations