use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project flink by apache.
the class RexSimplify method simplifyNot.
private RexNode simplifyNot(RexCall call, RexUnknownAs unknownAs) {
final RexNode a = call.getOperands().get(0);
switch(a.getKind()) {
case NOT:
// NOT NOT x ==> x
return simplify(((RexCall) a).getOperands().get(0), unknownAs);
case LITERAL:
if (a.getType().getSqlTypeName() == SqlTypeName.BOOLEAN && !RexLiteral.isNullLiteral(a)) {
return rexBuilder.makeLiteral(!RexLiteral.booleanValue(a));
}
}
final SqlKind negateKind = a.getKind().negate();
if (a.getKind() != negateKind) {
return simplify(rexBuilder.makeCall(RexUtil.op(negateKind), ((RexCall) a).getOperands()), unknownAs);
}
final SqlKind negateKind2 = a.getKind().negateNullSafe();
if (a.getKind() != negateKind2) {
return simplify(rexBuilder.makeCall(RexUtil.op(negateKind2), ((RexCall) a).getOperands()), unknownAs);
}
if (a.getKind() == SqlKind.AND) {
// NOT distributivity for AND
final List<RexNode> newOperands = new ArrayList<>();
for (RexNode operand : ((RexCall) a).getOperands()) {
newOperands.add(simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, operand), unknownAs));
}
return simplify(rexBuilder.makeCall(SqlStdOperatorTable.OR, newOperands), unknownAs);
}
if (a.getKind() == SqlKind.OR) {
// NOT distributivity for OR
final List<RexNode> newOperands = new ArrayList<>();
for (RexNode operand : ((RexCall) a).getOperands()) {
newOperands.add(simplify(rexBuilder.makeCall(SqlStdOperatorTable.NOT, operand), unknownAs));
}
return simplify(rexBuilder.makeCall(SqlStdOperatorTable.AND, newOperands), unknownAs);
}
if (a.getKind() == SqlKind.CASE) {
final List<RexNode> newOperands = new ArrayList<>();
List<RexNode> operands = ((RexCall) a).getOperands();
for (int i = 0; i < operands.size(); i += 2) {
if (i + 1 == operands.size()) {
newOperands.add(rexBuilder.makeCall(SqlStdOperatorTable.NOT, operands.get(i)));
} else {
newOperands.add(operands.get(i));
newOperands.add(rexBuilder.makeCall(SqlStdOperatorTable.NOT, operands.get(i + 1)));
}
}
return simplify(rexBuilder.makeCall(SqlStdOperatorTable.CASE, newOperands), unknownAs);
}
RexNode a2 = simplify(a, unknownAs.negate());
if (a == a2) {
return call;
}
if (a2.isAlwaysTrue()) {
return rexBuilder.makeLiteral(false);
}
if (a2.isAlwaysFalse()) {
return rexBuilder.makeLiteral(true);
}
return rexBuilder.makeCall(SqlStdOperatorTable.NOT, a2);
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project flink by apache.
the class FlinkAggregateExpandDistinctAggregatesRule method rewriteUsingGroupingSets.
private void rewriteUsingGroupingSets(RelOptRuleCall call, Aggregate aggregate) {
final Set<ImmutableBitSet> groupSetTreeSet = new TreeSet<>(ImmutableBitSet.ORDERING);
final Map<ImmutableBitSet, Integer> groupSetToDistinctAggCallFilterArg = new HashMap<>();
for (AggregateCall aggCall : aggregate.getAggCallList()) {
if (!aggCall.isDistinct()) {
groupSetTreeSet.add(aggregate.getGroupSet());
} else {
ImmutableBitSet groupSet = ImmutableBitSet.of(aggCall.getArgList()).setIf(aggCall.filterArg, aggCall.filterArg >= 0).union(aggregate.getGroupSet());
groupSetToDistinctAggCallFilterArg.put(groupSet, aggCall.filterArg);
groupSetTreeSet.add(groupSet);
}
}
final com.google.common.collect.ImmutableList<ImmutableBitSet> groupSets = com.google.common.collect.ImmutableList.copyOf(groupSetTreeSet);
final ImmutableBitSet fullGroupSet = ImmutableBitSet.union(groupSets);
final List<AggregateCall> distinctAggCalls = new ArrayList<>();
for (Pair<AggregateCall, String> aggCall : aggregate.getNamedAggCalls()) {
if (!aggCall.left.isDistinct()) {
AggregateCall newAggCall = aggCall.left.adaptTo(aggregate.getInput(), aggCall.left.getArgList(), aggCall.left.filterArg, aggregate.getGroupCount(), fullGroupSet.cardinality());
distinctAggCalls.add(newAggCall.rename(aggCall.right));
}
}
final RelBuilder relBuilder = call.builder();
relBuilder.push(aggregate.getInput());
final int groupCount = fullGroupSet.cardinality();
final Map<ImmutableBitSet, Integer> filters = new LinkedHashMap<>();
final int z = groupCount + distinctAggCalls.size();
distinctAggCalls.add(AggregateCall.create(SqlStdOperatorTable.GROUPING, false, false, false, ImmutableIntList.copyOf(fullGroupSet), -1, RelCollations.EMPTY, groupSets.size(), relBuilder.peek(), null, "$g"));
for (Ord<ImmutableBitSet> groupSet : Ord.zip(groupSets)) {
filters.put(groupSet.e, z + groupSet.i);
}
relBuilder.aggregate(relBuilder.groupKey(fullGroupSet, groupSets), distinctAggCalls);
final RelNode distinct = relBuilder.peek();
// values to BOOLEAN.
if (!filters.isEmpty()) {
final List<RexNode> nodes = new ArrayList<>(relBuilder.fields());
final RexNode nodeZ = nodes.remove(nodes.size() - 1);
for (Map.Entry<ImmutableBitSet, Integer> entry : filters.entrySet()) {
final long v = groupValue(fullGroupSet, entry.getKey());
// Get and remap the filterArg of the distinct aggregate call.
int distinctAggCallFilterArg = remap(fullGroupSet, groupSetToDistinctAggCallFilterArg.getOrDefault(entry.getKey(), -1));
RexNode expr;
if (distinctAggCallFilterArg < 0) {
expr = relBuilder.equals(nodeZ, relBuilder.literal(v));
} else {
RexBuilder rexBuilder = aggregate.getCluster().getRexBuilder();
// merge the filter of the distinct aggregate call itself.
expr = relBuilder.and(relBuilder.equals(nodeZ, relBuilder.literal(v)), rexBuilder.makeCall(SqlStdOperatorTable.IS_TRUE, relBuilder.field(distinctAggCallFilterArg)));
}
nodes.add(relBuilder.alias(expr, "$g_" + v));
}
relBuilder.project(nodes);
}
int aggCallIdx = 0;
int x = groupCount;
final List<AggregateCall> newCalls = new ArrayList<>();
// TODO supports more aggCalls (currently only supports COUNT)
// Some aggregate functions (e.g. COUNT) have the special property that they can return a
// non-null result without any input. We need to make sure we return a result in this case.
final List<Integer> needDefaultValueAggCalls = new ArrayList<>();
for (AggregateCall aggCall : aggregate.getAggCallList()) {
final int newFilterArg;
final List<Integer> newArgList;
final SqlAggFunction aggregation;
if (!aggCall.isDistinct()) {
aggregation = SqlStdOperatorTable.MIN;
newArgList = ImmutableIntList.of(x++);
newFilterArg = filters.get(aggregate.getGroupSet());
switch(aggCall.getAggregation().getKind()) {
case COUNT:
needDefaultValueAggCalls.add(aggCallIdx);
break;
default:
}
} else {
aggregation = aggCall.getAggregation();
newArgList = remap(fullGroupSet, aggCall.getArgList());
newFilterArg = filters.get(ImmutableBitSet.of(aggCall.getArgList()).setIf(aggCall.filterArg, aggCall.filterArg >= 0).union(aggregate.getGroupSet()));
}
final AggregateCall newCall = AggregateCall.create(aggregation, false, aggCall.isApproximate(), false, newArgList, newFilterArg, RelCollations.EMPTY, aggregate.getGroupCount(), distinct, null, aggCall.name);
newCalls.add(newCall);
aggCallIdx++;
}
relBuilder.aggregate(relBuilder.groupKey(remap(fullGroupSet, aggregate.getGroupSet()), remap(fullGroupSet, aggregate.getGroupSets())), newCalls);
if (!needDefaultValueAggCalls.isEmpty() && aggregate.getGroupCount() == 0) {
final Aggregate newAgg = (Aggregate) relBuilder.peek();
final List<RexNode> nodes = new ArrayList<>();
for (int i = 0; i < newAgg.getGroupCount(); ++i) {
nodes.add(RexInputRef.of(i, newAgg.getRowType()));
}
for (int i = 0; i < newAgg.getAggCallList().size(); ++i) {
final RexNode inputRef = RexInputRef.of(newAgg.getGroupCount() + i, newAgg.getRowType());
RexNode newNode = inputRef;
if (needDefaultValueAggCalls.contains(i)) {
SqlKind originalFunKind = aggregate.getAggCallList().get(i).getAggregation().getKind();
switch(originalFunKind) {
case COUNT:
newNode = relBuilder.call(SqlStdOperatorTable.CASE, relBuilder.isNotNull(inputRef), inputRef, relBuilder.literal(BigDecimal.ZERO));
break;
default:
}
}
nodes.add(newNode);
}
relBuilder.project(nodes);
}
relBuilder.convert(aggregate.getRowType(), true);
call.transformTo(relBuilder.build());
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project flink by apache.
the class SqlValidatorImpl method performUnconditionalRewrites.
/**
* Performs expression rewrites which are always used unconditionally. These rewrites massage
* the expression tree into a standard form so that the rest of the validation logic can be
* simpler.
*
* @param node expression to be rewritten
* @param underFrom whether node appears directly under a FROM clause
* @return rewritten expression
*/
protected SqlNode performUnconditionalRewrites(SqlNode node, boolean underFrom) {
if (node == null) {
return null;
}
SqlNode newOperand;
// first transform operands and invoke generic call rewrite
if (node instanceof SqlCall) {
if (node instanceof SqlMerge) {
validatingSqlMerge = true;
}
SqlCall call = (SqlCall) node;
final SqlKind kind = call.getKind();
final List<SqlNode> operands = call.getOperandList();
for (int i = 0; i < operands.size(); i++) {
SqlNode operand = operands.get(i);
boolean childUnderFrom;
if (kind == SqlKind.SELECT) {
childUnderFrom = i == SqlSelect.FROM_OPERAND;
} else if (kind == SqlKind.AS && (i == 0)) {
// for an aliased expression, it is under FROM if
// the AS expression is under FROM
childUnderFrom = underFrom;
} else {
childUnderFrom = false;
}
newOperand = performUnconditionalRewrites(operand, childUnderFrom);
if (newOperand != null && newOperand != operand) {
call.setOperand(i, newOperand);
}
}
if (call.getOperator() instanceof SqlUnresolvedFunction) {
assert call instanceof SqlBasicCall;
final SqlUnresolvedFunction function = (SqlUnresolvedFunction) call.getOperator();
// This function hasn't been resolved yet. Perform
// a half-hearted resolution now in case it's a
// builtin function requiring special casing. If it's
// not, we'll handle it later during overload resolution.
final List<SqlOperator> overloads = new ArrayList<>();
opTab.lookupOperatorOverloads(function.getNameAsId(), function.getFunctionType(), SqlSyntax.FUNCTION, overloads, catalogReader.nameMatcher());
if (overloads.size() == 1) {
((SqlBasicCall) call).setOperator(overloads.get(0));
}
}
if (config.callRewrite()) {
node = call.getOperator().rewriteCall(this, call);
}
} else if (node instanceof SqlNodeList) {
SqlNodeList list = (SqlNodeList) node;
for (int i = 0, count = list.size(); i < count; i++) {
SqlNode operand = list.get(i);
newOperand = performUnconditionalRewrites(operand, false);
if (newOperand != null) {
list.getList().set(i, newOperand);
}
}
}
// now transform node itself
final SqlKind kind = node.getKind();
switch(kind) {
case VALUES:
// CHECKSTYLE: IGNORE 1
if (underFrom || true) {
// over and over
return node;
} else {
final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
return new SqlSelect(node.getParserPosition(), null, selectList, node, null, null, null, null, null, null, null, null);
}
case ORDER_BY:
{
SqlOrderBy orderBy = (SqlOrderBy) node;
handleOffsetFetch(orderBy.offset, orderBy.fetch);
if (orderBy.query instanceof SqlSelect) {
SqlSelect select = (SqlSelect) orderBy.query;
// an order-sensitive function like RANK.
if (select.getOrderList() == null) {
// push ORDER BY into existing select
select.setOrderBy(orderBy.orderList);
select.setOffset(orderBy.offset);
select.setFetch(orderBy.fetch);
return select;
}
}
if (orderBy.query instanceof SqlWith && ((SqlWith) orderBy.query).body instanceof SqlSelect) {
SqlWith with = (SqlWith) orderBy.query;
SqlSelect select = (SqlSelect) with.body;
// an order-sensitive function like RANK.
if (select.getOrderList() == null) {
// push ORDER BY into existing select
select.setOrderBy(orderBy.orderList);
select.setOffset(orderBy.offset);
select.setFetch(orderBy.fetch);
return with;
}
}
final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
final SqlNodeList orderList;
if (getInnerSelect(node) != null && isAggregate(getInnerSelect(node))) {
orderList = SqlNode.clone(orderBy.orderList);
// We assume that ORDER BY item is present in SELECT list.
for (int i = 0; i < orderList.size(); i++) {
SqlNode sqlNode = orderList.get(i);
SqlNodeList selectList2 = getInnerSelect(node).getSelectList();
for (Ord<SqlNode> sel : Ord.zip(selectList2)) {
if (stripAs(sel.e).equalsDeep(sqlNode, Litmus.IGNORE)) {
orderList.set(i, SqlLiteral.createExactNumeric(Integer.toString(sel.i + 1), SqlParserPos.ZERO));
}
}
}
} else {
orderList = orderBy.orderList;
}
return new SqlSelect(SqlParserPos.ZERO, null, selectList, orderBy.query, null, null, null, null, orderList, orderBy.offset, orderBy.fetch, null);
}
case EXPLICIT_TABLE:
{
// (TABLE t) is equivalent to (SELECT * FROM t)
SqlCall call = (SqlCall) node;
final SqlNodeList selectList = new SqlNodeList(SqlParserPos.ZERO);
selectList.add(SqlIdentifier.star(SqlParserPos.ZERO));
return new SqlSelect(SqlParserPos.ZERO, null, selectList, call.operand(0), null, null, null, null, null, null, null, null);
}
case DELETE:
{
SqlDelete call = (SqlDelete) node;
SqlSelect select = createSourceSelectForDelete(call);
call.setSourceSelect(select);
break;
}
case UPDATE:
{
SqlUpdate call = (SqlUpdate) node;
SqlSelect select = createSourceSelectForUpdate(call);
call.setSourceSelect(select);
// in which case leave it alone).
if (!validatingSqlMerge) {
SqlNode selfJoinSrcExpr = getSelfJoinExprForUpdate(call.getTargetTable(), UPDATE_SRC_ALIAS);
if (selfJoinSrcExpr != null) {
node = rewriteUpdateToMerge(call, selfJoinSrcExpr);
}
}
break;
}
case MERGE:
{
SqlMerge call = (SqlMerge) node;
rewriteMerge(call);
break;
}
}
return node;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project calcite by apache.
the class SqlToRelConverter method convertOver.
private RexNode convertOver(Blackboard bb, SqlNode node) {
SqlCall call = (SqlCall) node;
SqlCall aggCall = call.operand(0);
SqlNode windowOrRef = call.operand(1);
final SqlWindow window = validator.resolveWindow(windowOrRef, bb.scope, true);
// ROW_NUMBER() expects specific kind of framing.
if (aggCall.getKind() == SqlKind.ROW_NUMBER) {
window.setLowerBound(SqlWindow.createUnboundedPreceding(SqlParserPos.ZERO));
window.setUpperBound(SqlWindow.createCurrentRow(SqlParserPos.ZERO));
window.setRows(SqlLiteral.createBoolean(true, SqlParserPos.ZERO));
}
final SqlNodeList partitionList = window.getPartitionList();
final ImmutableList.Builder<RexNode> partitionKeys = ImmutableList.builder();
for (SqlNode partition : partitionList) {
partitionKeys.add(bb.convertExpression(partition));
}
RexNode lowerBound = bb.convertExpression(window.getLowerBound());
RexNode upperBound = bb.convertExpression(window.getUpperBound());
SqlNodeList orderList = window.getOrderList();
if ((orderList.size() == 0) && !window.isRows()) {
// A logical range requires an ORDER BY clause. Use the implicit
// ordering of this relation. There must be one, otherwise it would
// have failed validation.
orderList = bb.scope.getOrderList();
if (orderList == null) {
throw new AssertionError("Relation should have sort key for implicit ORDER BY");
}
}
final ImmutableList.Builder<RexFieldCollation> orderKeys = ImmutableList.builder();
final Set<SqlKind> flags = EnumSet.noneOf(SqlKind.class);
for (SqlNode order : orderList) {
flags.clear();
RexNode e = bb.convertSortExpression(order, flags);
orderKeys.add(new RexFieldCollation(e, flags));
}
try {
Preconditions.checkArgument(bb.window == null, "already in window agg mode");
bb.window = window;
RexNode rexAgg = exprConverter.convertCall(bb, aggCall);
rexAgg = rexBuilder.ensureType(validator.getValidatedNodeType(call), rexAgg, false);
// Walk over the tree and apply 'over' to all agg functions. This is
// necessary because the returned expression is not necessarily a call
// to an agg function. For example, AVG(x) becomes SUM(x) / COUNT(x).
final SqlLiteral q = aggCall.getFunctionQuantifier();
final boolean isDistinct = q != null && q.getValue() == SqlSelectKeyword.DISTINCT;
final RexShuttle visitor = new HistogramShuttle(partitionKeys.build(), orderKeys.build(), RexWindowBound.create(window.getLowerBound(), lowerBound), RexWindowBound.create(window.getUpperBound(), upperBound), window, isDistinct);
RexNode overNode = rexAgg.accept(visitor);
return overNode;
} finally {
bb.window = null;
}
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.sql.SqlKind in project calcite by apache.
the class SqlValidatorImpl method registerFrom.
/**
* Registers scopes and namespaces implied a relational expression in the
* FROM clause.
*
* <p>{@code parentScope} and {@code usingScope} are often the same. They
* differ when the namespace are not visible within the parent. (Example
* needed.)
*
* <p>Likewise, {@code enclosingNode} and {@code node} are often the same.
* {@code enclosingNode} is the topmost node within the FROM clause, from
* which any decorations like an alias (<code>AS alias</code>) or a table
* sample clause are stripped away to get {@code node}. Both are recorded in
* the namespace.
*
* @param parentScope Parent scope which this scope turns to in order to
* resolve objects
* @param usingScope Scope whose child list this scope should add itself to
* @param node Node which namespace is based on
* @param enclosingNode Outermost node for namespace, including decorations
* such as alias and sample clause
* @param alias Alias
* @param extendList Definitions of extended columns
* @param forceNullable Whether to force the type of namespace to be
* nullable because it is in an outer join
* @return registered node, usually the same as {@code node}
*/
private SqlNode registerFrom(SqlValidatorScope parentScope, SqlValidatorScope usingScope, final SqlNode node, SqlNode enclosingNode, String alias, SqlNodeList extendList, boolean forceNullable) {
final SqlKind kind = node.getKind();
SqlNode expr;
SqlNode newExpr;
// Add an alias if necessary.
SqlNode newNode = node;
if (alias == null) {
switch(kind) {
case IDENTIFIER:
case OVER:
alias = deriveAlias(node, -1);
if (alias == null) {
alias = deriveAlias(node, nextGeneratedId++);
}
if (shouldExpandIdentifiers()) {
newNode = SqlValidatorUtil.addAlias(node, alias);
}
break;
case SELECT:
case UNION:
case INTERSECT:
case EXCEPT:
case VALUES:
case UNNEST:
case OTHER_FUNCTION:
case COLLECTION_TABLE:
case MATCH_RECOGNIZE:
// give this anonymous construct a name since later
// query processing stages rely on it
alias = deriveAlias(node, nextGeneratedId++);
if (shouldExpandIdentifiers()) {
// Since we're expanding identifiers, we should make the
// aliases explicit too, otherwise the expanded query
// will not be consistent if we convert back to SQL, e.g.
// "select EXPR$1.EXPR$2 from values (1)".
newNode = SqlValidatorUtil.addAlias(node, alias);
}
break;
}
}
SqlCall call;
SqlNode operand;
SqlNode newOperand;
switch(kind) {
case AS:
call = (SqlCall) node;
if (alias == null) {
alias = call.operand(1).toString();
}
SqlValidatorScope usingScope2 = usingScope;
if (call.operandCount() > 2) {
usingScope2 = null;
}
expr = call.operand(0);
newExpr = registerFrom(parentScope, usingScope2, expr, enclosingNode, alias, extendList, forceNullable);
if (newExpr != expr) {
call.setOperand(0, newExpr);
}
// column names.
if (call.operandCount() > 2) {
registerNamespace(usingScope, alias, new AliasNamespace(this, call, enclosingNode), forceNullable);
}
return node;
case MATCH_RECOGNIZE:
registerMatchRecognize(parentScope, usingScope, (SqlMatchRecognize) node, enclosingNode, alias, forceNullable);
return node;
case TABLESAMPLE:
call = (SqlCall) node;
expr = call.operand(0);
newExpr = registerFrom(parentScope, usingScope, expr, enclosingNode, alias, extendList, forceNullable);
if (newExpr != expr) {
call.setOperand(0, newExpr);
}
return node;
case JOIN:
final SqlJoin join = (SqlJoin) node;
final JoinScope joinScope = new JoinScope(parentScope, usingScope, join);
scopes.put(join, joinScope);
final SqlNode left = join.getLeft();
final SqlNode right = join.getRight();
final boolean rightIsLateral = isLateral(right);
boolean forceLeftNullable = forceNullable;
boolean forceRightNullable = forceNullable;
switch(join.getJoinType()) {
case LEFT:
forceRightNullable = true;
break;
case RIGHT:
forceLeftNullable = true;
break;
case FULL:
forceLeftNullable = true;
forceRightNullable = true;
break;
}
final SqlNode newLeft = registerFrom(parentScope, joinScope, left, left, null, null, forceLeftNullable);
if (newLeft != left) {
join.setLeft(newLeft);
}
final SqlValidatorScope rightParentScope;
if (rightIsLateral) {
rightParentScope = joinScope;
} else {
rightParentScope = parentScope;
}
final SqlNode newRight = registerFrom(rightParentScope, joinScope, right, right, null, null, forceRightNullable);
if (newRight != right) {
join.setRight(newRight);
}
registerSubQueries(joinScope, join.getCondition());
final JoinNamespace joinNamespace = new JoinNamespace(this, join);
registerNamespace(null, null, joinNamespace, forceNullable);
return join;
case IDENTIFIER:
final SqlIdentifier id = (SqlIdentifier) node;
final IdentifierNamespace newNs = new IdentifierNamespace(this, id, extendList, enclosingNode, parentScope);
registerNamespace(usingScope, alias, newNs, forceNullable);
if (tableScope == null) {
tableScope = new TableScope(parentScope, node);
}
tableScope.addChild(newNs, alias, forceNullable);
if (extendList != null && extendList.size() != 0) {
return enclosingNode;
}
return newNode;
case LATERAL:
if (tableScope != null) {
tableScope.meetLateral();
}
return registerFrom(parentScope, usingScope, ((SqlCall) node).operand(0), enclosingNode, alias, extendList, forceNullable);
case COLLECTION_TABLE:
call = (SqlCall) node;
operand = call.operand(0);
newOperand = registerFrom(tableScope == null ? parentScope : tableScope, usingScope, operand, enclosingNode, alias, extendList, forceNullable);
if (newOperand != operand) {
call.setOperand(0, newOperand);
}
scopes.put(node, parentScope);
return newNode;
case SELECT:
case UNION:
case INTERSECT:
case EXCEPT:
case VALUES:
case WITH:
case UNNEST:
case OTHER_FUNCTION:
if (alias == null) {
alias = deriveAlias(node, nextGeneratedId++);
}
registerQuery(parentScope, usingScope, node, enclosingNode, alias, forceNullable);
return newNode;
case OVER:
if (!shouldAllowOverRelation()) {
throw Util.unexpected(kind);
}
call = (SqlCall) node;
final OverScope overScope = new OverScope(usingScope, call);
scopes.put(call, overScope);
operand = call.operand(0);
newOperand = registerFrom(parentScope, overScope, operand, enclosingNode, alias, extendList, forceNullable);
if (newOperand != operand) {
call.setOperand(0, newOperand);
}
for (ScopeChild child : overScope.children) {
registerNamespace(usingScope, child.name, child.namespace, forceNullable);
}
return newNode;
case EXTEND:
final SqlCall extend = (SqlCall) node;
return registerFrom(parentScope, usingScope, extend.getOperandList().get(0), extend, alias, (SqlNodeList) extend.getOperandList().get(1), forceNullable);
default:
throw Util.unexpected(kind);
}
}
Aggregations