use of org.apache.calcite.sql.SqlDynamicParam in project flink by apache.
the class SqlValidatorImpl method inferUnknownTypes.
protected void inferUnknownTypes(@Nonnull RelDataType inferredType, @Nonnull SqlValidatorScope scope, @Nonnull SqlNode node) {
Objects.requireNonNull(inferredType);
Objects.requireNonNull(scope);
Objects.requireNonNull(node);
final SqlValidatorScope newScope = scopes.get(node);
if (newScope != null) {
scope = newScope;
}
boolean isNullLiteral = SqlUtil.isNullLiteral(node, false);
if ((node instanceof SqlDynamicParam) || isNullLiteral) {
if (inferredType.equals(unknownType)) {
if (isNullLiteral) {
if (config.typeCoercionEnabled()) {
// derive type of null literal
deriveType(scope, node);
return;
} else {
throw newValidationError(node, RESOURCE.nullIllegal());
}
} else {
throw newValidationError(node, RESOURCE.dynamicParamIllegal());
}
}
// REVIEW: should dynamic parameter types always be nullable?
RelDataType newInferredType = typeFactory.createTypeWithNullability(inferredType, true);
if (SqlTypeUtil.inCharFamily(inferredType)) {
newInferredType = typeFactory.createTypeWithCharsetAndCollation(newInferredType, inferredType.getCharset(), inferredType.getCollation());
}
setValidatedNodeType(node, newInferredType);
} else if (node instanceof SqlNodeList) {
SqlNodeList nodeList = (SqlNodeList) node;
if (inferredType.isStruct()) {
if (inferredType.getFieldCount() != nodeList.size()) {
// bust out, and the error will be detected higher up
return;
}
}
int i = 0;
for (SqlNode child : nodeList) {
RelDataType type;
if (inferredType.isStruct()) {
type = inferredType.getFieldList().get(i).getType();
++i;
} else {
type = inferredType;
}
inferUnknownTypes(type, scope, child);
}
} else if (node instanceof SqlCase) {
final SqlCase caseCall = (SqlCase) node;
final RelDataType whenType = caseCall.getValueOperand() == null ? booleanType : unknownType;
for (SqlNode sqlNode : caseCall.getWhenOperands().getList()) {
inferUnknownTypes(whenType, scope, sqlNode);
}
RelDataType returnType = deriveType(scope, node);
for (SqlNode sqlNode : caseCall.getThenOperands().getList()) {
inferUnknownTypes(returnType, scope, sqlNode);
}
if (!SqlUtil.isNullLiteral(caseCall.getElseOperand(), false)) {
inferUnknownTypes(returnType, scope, caseCall.getElseOperand());
} else {
setValidatedNodeType(caseCall.getElseOperand(), returnType);
}
} else if (node.getKind() == SqlKind.AS) {
// For AS operator, only infer the operand not the alias
inferUnknownTypes(inferredType, scope, ((SqlCall) node).operand(0));
} else if (node instanceof SqlCall) {
final SqlCall call = (SqlCall) node;
final SqlOperandTypeInference operandTypeInference = call.getOperator().getOperandTypeInference();
final SqlCallBinding callBinding = new SqlCallBinding(this, scope, call);
final List<SqlNode> operands = callBinding.operands();
final RelDataType[] operandTypes = new RelDataType[operands.size()];
Arrays.fill(operandTypes, unknownType);
// instead; for now just eat it
if (operandTypeInference != null) {
operandTypeInference.inferOperandTypes(callBinding, inferredType, operandTypes);
}
for (int i = 0; i < operands.size(); ++i) {
final SqlNode operand = operands.get(i);
if (operand != null) {
inferUnknownTypes(operandTypes[i], scope, operand);
}
}
}
}
use of org.apache.calcite.sql.SqlDynamicParam in project flink by apache.
the class SqlValidatorImpl method getParameterRowType.
public RelDataType getParameterRowType(SqlNode sqlQuery) {
// NOTE: We assume that bind variables occur in depth-first tree
// traversal in the same order that they occurred in the SQL text.
final List<RelDataType> types = new ArrayList<>();
// NOTE: but parameters on fetch/offset would be counted twice
// as they are counted in the SqlOrderBy call and the inner SqlSelect call
final Set<SqlNode> alreadyVisited = new HashSet<>();
sqlQuery.accept(new SqlShuttle() {
@Override
public SqlNode visit(SqlDynamicParam param) {
if (alreadyVisited.add(param)) {
RelDataType type = getValidatedNodeType(param);
types.add(type);
}
return param;
}
});
return typeFactory.createStructType(types, new AbstractList<String>() {
@Override
public String get(int index) {
return "?" + index;
}
@Override
public int size() {
return types.size();
}
});
}
use of org.apache.calcite.sql.SqlDynamicParam in project flink by apache.
the class SqlValidatorImpl method checkTypeAssignment.
/**
* Checks the type assignment of an INSERT or UPDATE query.
*
* <p>Skip the virtual columns(can not insert into) type assignment check if the source fields
* count equals with the real target table fields count, see how #checkFieldCount was used.
*
* @param sourceScope Scope of query source which is used to infer node type
* @param table Target table
* @param sourceRowType Source row type
* @param targetRowType Target row type, it should either contain all the virtual columns (can
* not insert into) or exclude all the virtual columns
* @param query The query
*/
protected void checkTypeAssignment(SqlValidatorScope sourceScope, SqlValidatorTable table, RelDataType sourceRowType, RelDataType targetRowType, final SqlNode query) {
// NOTE jvs 23-Feb-2006: subclasses may allow for extra targets
// representing system-maintained columns, so stop after all sources
// matched
boolean isUpdateModifiableViewTable = false;
if (query instanceof SqlUpdate) {
final SqlNodeList targetColumnList = ((SqlUpdate) query).getTargetColumnList();
if (targetColumnList != null) {
final int targetColumnCnt = targetColumnList.size();
targetRowType = SqlTypeUtil.extractLastNFields(typeFactory, targetRowType, targetColumnCnt);
sourceRowType = SqlTypeUtil.extractLastNFields(typeFactory, sourceRowType, targetColumnCnt);
}
isUpdateModifiableViewTable = table.unwrap(ModifiableViewTable.class) != null;
}
if (SqlTypeUtil.equalAsStructSansNullability(typeFactory, sourceRowType, targetRowType, null)) {
// Returns early if source and target row type equals sans nullability.
return;
}
if (config.typeCoercionEnabled() && !isUpdateModifiableViewTable) {
// Try type coercion first if implicit type coercion is allowed.
boolean coerced = typeCoercion.querySourceCoercion(sourceScope, sourceRowType, targetRowType, query);
if (coerced) {
return;
}
}
// Fall back to default behavior: compare the type families.
List<RelDataTypeField> sourceFields = sourceRowType.getFieldList();
List<RelDataTypeField> targetFields = targetRowType.getFieldList();
final int sourceCount = sourceFields.size();
for (int i = 0; i < sourceCount; ++i) {
RelDataType sourceType = sourceFields.get(i).getType();
RelDataType targetType = targetFields.get(i).getType();
if (!SqlTypeUtil.canAssignFrom(targetType, sourceType)) {
SqlNode node = getNthExpr(query, i, sourceCount);
if (node instanceof SqlDynamicParam) {
continue;
}
String targetTypeString;
String sourceTypeString;
if (SqlTypeUtil.areCharacterSetsMismatched(sourceType, targetType)) {
sourceTypeString = sourceType.getFullTypeString();
targetTypeString = targetType.getFullTypeString();
} else {
sourceTypeString = sourceType.toString();
targetTypeString = targetType.toString();
}
throw newValidationError(node, RESOURCE.typeNotAssignable(targetFields.get(i).getName(), targetTypeString, sourceFields.get(i).getName(), sourceTypeString));
}
}
}
use of org.apache.calcite.sql.SqlDynamicParam in project calcite by apache.
the class AbstractTypeCoercion method coerceColumnType.
/**
* Cast column at index {@code index} to target type.
*
* @param scope Validator scope for the node list
* @param nodeList Column node list
* @param index Index of column
* @param targetType Target type to cast to
*/
protected boolean coerceColumnType(@Nullable SqlValidatorScope scope, SqlNodeList nodeList, int index, RelDataType targetType) {
// does not support deriving JavaType yet.
if (RelDataTypeFactoryImpl.isJavaType(targetType)) {
targetType = ((JavaTypeFactory) factory).toSql(targetType);
}
// See SqlToRelConverter#convertSelectList for details.
if (index >= nodeList.size()) {
// just return true.
return true;
}
final SqlNode node = nodeList.get(index);
if (node instanceof SqlDynamicParam) {
// Do not support implicit type coercion for dynamic param.
return false;
}
if (node instanceof SqlIdentifier) {
// Do not expand a star/dynamic table col.
SqlIdentifier node1 = (SqlIdentifier) node;
if (node1.isStar()) {
return true;
} else if (DynamicRecordType.isDynamicStarColName(Util.last(node1.names))) {
// Should support implicit cast for dynamic table.
return false;
}
}
requireNonNull(scope, "scope is needed for needToCast(scope, operand, targetType)");
if (node instanceof SqlCall) {
SqlCall node2 = (SqlCall) node;
if (node2.getOperator().kind == SqlKind.AS) {
final SqlNode operand = node2.operand(0);
if (!needToCast(scope, operand, targetType)) {
return false;
}
RelDataType targetType2 = syncAttributes(validator.deriveType(scope, operand), targetType);
final SqlNode casted = castTo(operand, targetType2);
node2.setOperand(0, casted);
updateInferredType(casted, targetType2);
return true;
}
}
if (!needToCast(scope, node, targetType)) {
return false;
}
RelDataType targetType3 = syncAttributes(validator.deriveType(scope, node), targetType);
final SqlNode node3 = castTo(node, targetType3);
nodeList.set(index, node3);
updateInferredType(node3, targetType3);
return true;
}
use of org.apache.calcite.sql.SqlDynamicParam in project calcite by apache.
the class AbstractTypeCoercion method coerceOperandType.
// ~ Methods ----------------------------------------------------------------
/**
* Cast operand at index {@code index} to target type.
* we do this base on the fact that validate happens before type coercion.
*/
protected boolean coerceOperandType(@Nullable SqlValidatorScope scope, SqlCall call, int index, RelDataType targetType) {
// does not support deriving JavaType yet.
if (RelDataTypeFactoryImpl.isJavaType(targetType)) {
targetType = ((JavaTypeFactory) factory).toSql(targetType);
}
SqlNode operand = call.getOperandList().get(index);
if (operand instanceof SqlDynamicParam) {
// Do not support implicit type coercion for dynamic param.
return false;
}
requireNonNull(scope, "scope");
// Check it early.
if (!needToCast(scope, operand, targetType)) {
return false;
}
// Fix up nullable attr.
RelDataType targetType1 = syncAttributes(validator.deriveType(scope, operand), targetType);
SqlNode desired = castTo(operand, targetType1);
call.setOperand(index, desired);
updateInferredType(desired, targetType1);
return true;
}
Aggregations