use of org.apache.calcite.sql.SqlCall in project flink by apache.
the class SqlValidatorImpl method rewriteMerge.
private void rewriteMerge(SqlMerge call) {
SqlNodeList selectList;
SqlUpdate updateStmt = call.getUpdateCall();
if (updateStmt != null) {
// if we have an update statement, just clone the select list
// from the update statement's source since it's the same as
// what we want for the select list of the merge source -- '*'
// followed by the update set expressions
selectList = SqlNode.clone(updateStmt.getSourceSelect().getSelectList());
} else {
// otherwise, just use select *
selectList = new SqlNodeList(SqlParserPos.ZERO);
selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
}
SqlNode targetTable = call.getTargetTable();
if (call.getAlias() != null) {
targetTable = SqlValidatorUtil.addAlias(targetTable, call.getAlias().getSimple());
}
// Provided there is an insert substatement, the source select for
// the merge is a left outer join between the source in the USING
// clause and the target table; otherwise, the join is just an
// inner join. Need to clone the source table reference in order
// for validation to work
SqlNode sourceTableRef = call.getSourceTableRef();
SqlInsert insertCall = call.getInsertCall();
JoinType joinType = (insertCall == null) ? JoinType.INNER : JoinType.LEFT;
final SqlNode leftJoinTerm = SqlNode.clone(sourceTableRef);
SqlNode outerJoin = new SqlJoin(SqlParserPos.ZERO, leftJoinTerm, SqlLiteral.createBoolean(false, SqlParserPos.ZERO), joinType.symbol(SqlParserPos.ZERO), targetTable, JoinConditionType.ON.symbol(SqlParserPos.ZERO), call.getCondition());
SqlSelect select = new SqlSelect(SqlParserPos.ZERO, null, selectList, outerJoin, null, null, null, null, null, null, null, null);
call.setSourceSelect(select);
// that via the from clause on the select
if (insertCall != null) {
SqlCall valuesCall = (SqlCall) insertCall.getSource();
SqlCall rowCall = valuesCall.operand(0);
selectList = new SqlNodeList(rowCall.getOperandList(), SqlParserPos.ZERO);
final SqlNode insertSource = SqlNode.clone(sourceTableRef);
select = new SqlSelect(SqlParserPos.ZERO, null, selectList, insertSource, null, null, null, null, null, null, null, null);
insertCall.setSource(select);
}
}
use of org.apache.calcite.sql.SqlCall in project flink by apache.
the class SqlValidatorImpl method getTableConstructorRowType.
/**
* Returns null if there is no common type. E.g. if the rows have a different number of columns.
*/
RelDataType getTableConstructorRowType(SqlCall values, SqlValidatorScope scope) {
final List<SqlNode> rows = values.getOperandList();
assert rows.size() >= 1;
final List<RelDataType> rowTypes = new ArrayList<>();
for (final SqlNode row : rows) {
assert row.getKind() == SqlKind.ROW;
SqlCall rowConstructor = (SqlCall) row;
// REVIEW jvs 10-Sept-2003: Once we support single-row queries as
// rows, need to infer aliases from there.
final List<String> aliasList = new ArrayList<>();
final List<RelDataType> typeList = new ArrayList<>();
for (Ord<SqlNode> column : Ord.zip(rowConstructor.getOperandList())) {
final String alias = deriveAlias(column.e, column.i);
aliasList.add(alias);
final RelDataType type = deriveType(scope, column.e);
typeList.add(type);
}
rowTypes.add(typeFactory.createStructType(typeList, aliasList));
}
if (rows.size() == 1) {
// leastRestrictive can handle all cases
return rowTypes.get(0);
}
return typeFactory.leastRestrictive(rowTypes);
}
use of org.apache.calcite.sql.SqlCall in project flink by apache.
the class SqlValidatorImpl method validateValues.
/**
* Validates a VALUES clause.
*
* @param node Values clause
* @param targetRowType Row type which expression must conform to
* @param scope Scope within which clause occurs
*/
protected void validateValues(SqlCall node, RelDataType targetRowType, final SqlValidatorScope scope) {
assert node.getKind() == SqlKind.VALUES;
final List<SqlNode> operands = node.getOperandList();
for (SqlNode operand : operands) {
if (!(operand.getKind() == SqlKind.ROW)) {
throw Util.needToImplement("Values function where operands are scalars");
}
SqlCall rowConstructor = (SqlCall) operand;
if (this.config.sqlConformance().isInsertSubsetColumnsAllowed() && targetRowType.isStruct() && rowConstructor.operandCount() < targetRowType.getFieldCount()) {
targetRowType = typeFactory.createStructType(targetRowType.getFieldList().subList(0, rowConstructor.operandCount()));
} else if (targetRowType.isStruct() && rowConstructor.operandCount() != targetRowType.getFieldCount()) {
return;
}
inferUnknownTypes(targetRowType, scope, rowConstructor);
if (targetRowType.isStruct()) {
for (Pair<SqlNode, RelDataTypeField> pair : Pair.zip(rowConstructor.getOperandList(), targetRowType.getFieldList())) {
if (!pair.right.getType().isNullable() && SqlUtil.isNullLiteral(pair.left, false)) {
throw newValidationError(node, RESOURCE.columnNotNullable(pair.right.getName()));
}
}
}
}
for (SqlNode operand : operands) {
operand.validate(this, scope);
}
// validate that all row types have the same number of columns
// and that expressions in each column are compatible.
// A values expression is turned into something that looks like
// ROW(type00, type01,...), ROW(type11,...),...
final int rowCount = operands.size();
if (rowCount >= 2) {
SqlCall firstRow = (SqlCall) operands.get(0);
final int columnCount = firstRow.operandCount();
// 1. check that all rows have the same cols length
for (SqlNode operand : operands) {
SqlCall thisRow = (SqlCall) operand;
if (columnCount != thisRow.operandCount()) {
throw newValidationError(node, RESOURCE.incompatibleValueType(SqlStdOperatorTable.VALUES.getName()));
}
}
// 2. check if types at i:th position in each row are compatible
for (int col = 0; col < columnCount; col++) {
final int c = col;
final RelDataType type = typeFactory.leastRestrictive(new AbstractList<RelDataType>() {
public RelDataType get(int row) {
SqlCall thisRow = (SqlCall) operands.get(row);
return deriveType(scope, thisRow.operand(c));
}
public int size() {
return rowCount;
}
});
if (null == type) {
throw newValidationError(node, RESOURCE.incompatibleValueType(SqlStdOperatorTable.VALUES.getName()));
}
}
}
}
use of org.apache.calcite.sql.SqlCall in project flink by apache.
the class SqlValidatorImpl method checkRollUp.
private void checkRollUp(SqlNode grandParent, SqlNode parent, SqlNode current, SqlValidatorScope scope, String optionalClause) {
current = stripAs(current);
if (current instanceof SqlCall && !(current instanceof SqlSelect)) {
// Validate OVER separately
checkRollUpInWindow(getWindowInOver(current), scope);
current = stripOver(current);
List<SqlNode> children = ((SqlCall) stripAs(stripDot(current))).getOperandList();
for (SqlNode child : children) {
checkRollUp(parent, current, child, scope, optionalClause);
}
} else if (current instanceof SqlIdentifier) {
SqlIdentifier id = (SqlIdentifier) current;
if (!id.isStar() && isRolledUpColumn(id, scope)) {
if (!isAggregation(parent.getKind()) || !isRolledUpColumnAllowedInAgg(id, scope, (SqlCall) parent, grandParent)) {
String context = optionalClause != null ? optionalClause : parent.getKind().toString();
throw newValidationError(id, RESOURCE.rolledUpNotAllowed(deriveAlias(id, 0), context));
}
}
}
}
use of org.apache.calcite.sql.SqlCall in project flink by apache.
the class SqlValidatorImpl method navigationInMeasure.
private SqlNode navigationInMeasure(SqlNode node, boolean allRows) {
final Set<String> prefix = node.accept(new PatternValidator(true));
Util.discard(prefix);
final List<SqlNode> ops = ((SqlCall) node).getOperandList();
final SqlOperator defaultOp = allRows ? SqlStdOperatorTable.RUNNING : SqlStdOperatorTable.FINAL;
final SqlNode op0 = ops.get(0);
if (!isRunningOrFinal(op0.getKind()) || !allRows && op0.getKind() == SqlKind.RUNNING) {
SqlNode newNode = defaultOp.createCall(SqlParserPos.ZERO, op0);
node = SqlStdOperatorTable.AS.createCall(SqlParserPos.ZERO, newNode, ops.get(1));
}
node = new NavigationExpander().go(node);
return node;
}
Aggregations