in core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java [5978:6184]
throw newValidationError(node,
RESOURCE.incompatibleValueType(
SqlStdOperatorTable.VALUES.getName()));
}
}
}
}
@Override public void validateDataType(SqlDataTypeSpec dataType) {
}
@Override public void validateDynamicParam(SqlDynamicParam dynamicParam) {
}
/**
* Throws a validator exception with access to the validator context.
* The exception is determined when an instance is created.
*/
private class ValidationError implements Supplier<CalciteContextException> {
private final SqlNode sqlNode;
private final Resources.ExInst<SqlValidatorException> validatorException;
ValidationError(SqlNode sqlNode,
Resources.ExInst<SqlValidatorException> validatorException) {
this.sqlNode = sqlNode;
this.validatorException = validatorException;
}
@Override public CalciteContextException get() {
return newValidationError(sqlNode, validatorException);
}
}
/**
* Throws a validator exception with access to the validator context.
* The exception is determined when the function is applied.
*/
class ValidationErrorFunction
implements BiFunction<SqlNode, Resources.ExInst<SqlValidatorException>,
CalciteContextException> {
@Override public CalciteContextException apply(
SqlNode v0, Resources.ExInst<SqlValidatorException> v1) {
return newValidationError(v0, v1);
}
}
public ValidationErrorFunction getValidationErrorFunction() {
return validationErrorFunction;
}
@Override public CalciteContextException newValidationError(SqlNode node,
Resources.ExInst<SqlValidatorException> e) {
requireNonNull(node, "node");
final SqlParserPos pos = node.getParserPosition();
return SqlUtil.newContextException(pos, e);
}
protected SqlWindow getWindowByName(
SqlIdentifier id,
SqlValidatorScope scope) {
SqlWindow window = null;
if (id.isSimple()) {
final String name = id.getSimple();
window = scope.lookupWindow(name);
}
if (window == null) {
throw newValidationError(id, RESOURCE.windowNotFound(id.toString()));
}
return window;
}
@Override public SqlWindow resolveWindow(
SqlNode windowOrRef,
SqlValidatorScope scope) {
SqlWindow window;
if (windowOrRef instanceof SqlIdentifier) {
window = getWindowByName((SqlIdentifier) windowOrRef, scope);
} else {
window = (SqlWindow) windowOrRef;
}
while (true) {
final SqlIdentifier refId = window.getRefName();
if (refId == null) {
break;
}
final String refName = refId.getSimple();
SqlWindow refWindow = scope.lookupWindow(refName);
if (refWindow == null) {
throw newValidationError(refId, RESOURCE.windowNotFound(refName));
}
window = window.overlay(refWindow, this);
}
return window;
}
public SqlNode getOriginal(SqlNode expr) {
SqlNode original = originalExprs.get(expr);
if (original == null) {
original = expr;
}
return original;
}
public void setOriginal(SqlNode expr, SqlNode original) {
// Don't overwrite the original original.
originalExprs.putIfAbsent(expr, original);
}
@Nullable SqlValidatorNamespace lookupFieldNamespace(RelDataType rowType, String name) {
final SqlNameMatcher nameMatcher = catalogReader.nameMatcher();
final RelDataTypeField field = nameMatcher.field(rowType, name);
if (field == null) {
return null;
}
return new FieldNamespace(this, field.getType());
}
@Override public void validateWindow(
SqlNode windowOrId,
SqlValidatorScope scope,
@Nullable SqlCall call) {
// Enable nested aggregates with window aggregates (OVER operator)
inWindow = true;
final SqlWindow targetWindow;
switch (windowOrId.getKind()) {
case IDENTIFIER:
// Just verify the window exists in this query. It will validate
// when the definition is processed
targetWindow = getWindowByName((SqlIdentifier) windowOrId, scope);
break;
case WINDOW:
targetWindow = (SqlWindow) windowOrId;
break;
default:
throw Util.unexpected(windowOrId.getKind());
}
requireNonNull(call, () -> "call is null when validating windowOrId " + windowOrId);
assert targetWindow.getWindowCall() == null;
targetWindow.setWindowCall(call);
targetWindow.validate(this, scope);
targetWindow.setWindowCall(null);
call.validate(this, scope);
validateAggregateParams(call, null, null, null, scope);
// Disable nested aggregates post validation
inWindow = false;
}
@Override public void validateLambda(SqlLambda lambdaExpr) {
final SqlLambdaScope scope = (SqlLambdaScope) scopes.get(lambdaExpr);
requireNonNull(scope, "scope");
final LambdaNamespace ns =
getNamespaceOrThrow(lambdaExpr).unwrap(LambdaNamespace.class);
deriveType(scope, lambdaExpr.getExpression());
RelDataType type = deriveTypeImpl(scope, lambdaExpr);
setValidatedNodeType(lambdaExpr, type);
ns.setType(type);
}
@Override public void validateMatchRecognize(SqlCall call) {
final SqlMatchRecognize matchRecognize = (SqlMatchRecognize) call;
final MatchRecognizeScope scope =
(MatchRecognizeScope) getMatchRecognizeScope(matchRecognize);
final MatchRecognizeNamespace ns =
getNamespaceOrThrow(call).unwrap(MatchRecognizeNamespace.class);
assert ns.rowType == null;
// rows per match
final SqlLiteral rowsPerMatch = matchRecognize.getRowsPerMatch();
final boolean allRows = rowsPerMatch != null
&& rowsPerMatch.getValue()
== SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS;
final RelDataTypeFactory.Builder typeBuilder = typeFactory.builder();
// parse PARTITION BY column
for (SqlNode node : matchRecognize.getPartitionList()) {
SqlIdentifier identifier = (SqlIdentifier) node;
identifier.validate(this, scope);
RelDataType type = deriveType(scope, identifier);
String name = identifier.names.get(1);
typeBuilder.add(name, type);
}
// parse ORDER BY column
for (SqlNode node : matchRecognize.getOrderList()) {
node.validate(this, scope);
SqlIdentifier identifier;
if (node instanceof SqlBasicCall) {
identifier = ((SqlBasicCall) node).operand(0);
} else {
identifier =
requireNonNull((SqlIdentifier) node,
() -> "order by field is null. All fields: "
+ matchRecognize.getOrderList());
}
if (allRows) {
RelDataType type = deriveType(scope, identifier);
String name = identifier.names.get(1);
if (!typeBuilder.nameExists(name)) {