use of org.apache.calcite.sql.validate.SqlValidatorNamespace in project calcite by apache.
the class SqlTesterImpl method checkMonotonic.
public void checkMonotonic(String query, SqlMonotonicity expectedMonotonicity) {
SqlValidator validator = getValidator();
SqlNode n = parseAndValidate(validator, query);
final RelDataType rowType = validator.getValidatedNodeType(n);
final SqlValidatorNamespace selectNamespace = validator.getNamespace(n);
final String field0 = rowType.getFieldList().get(0).getName();
final SqlMonotonicity monotonicity = selectNamespace.getMonotonicity(field0);
assertThat(monotonicity, equalTo(expectedMonotonicity));
}
use of org.apache.calcite.sql.validate.SqlValidatorNamespace in project calcite by apache.
the class SqlCallBinding method getOperandType.
@Override
public RelDataType getOperandType(int ordinal) {
final SqlNode operand = call.operand(ordinal);
final RelDataType type = validator.deriveType(scope, operand);
final SqlValidatorNamespace namespace = validator.getNamespace(operand);
if (namespace != null) {
return namespace.getType();
}
return type;
}
use of org.apache.calcite.sql.validate.SqlValidatorNamespace in project flink by apache.
the class TypeInferenceOperandChecker method updateInferredType.
/**
* Adopted from {@link org.apache.calcite.sql.validate.implicit.AbstractTypeCoercion}.
*/
private void updateInferredType(SqlValidator validator, SqlNode node, RelDataType type) {
validator.setValidatedNodeType(node, type);
final SqlValidatorNamespace namespace = validator.getNamespace(node);
if (namespace != null) {
namespace.setType(type);
}
}
use of org.apache.calcite.sql.validate.SqlValidatorNamespace in project calcite by apache.
the class SqlToRelConverter method getCorrelationUse.
private CorrelationUse getCorrelationUse(Blackboard bb, final RelNode r0) {
final Set<CorrelationId> correlatedVariables = RelOptUtil.getVariablesUsed(r0);
if (correlatedVariables.isEmpty()) {
return null;
}
final ImmutableBitSet.Builder requiredColumns = ImmutableBitSet.builder();
final List<CorrelationId> correlNames = Lists.newArrayList();
// All correlations must refer the same namespace since correlation
// produces exactly one correlation source.
// The same source might be referenced by different variables since
// DeferredLookups are not de-duplicated at create time.
SqlValidatorNamespace prevNs = null;
for (CorrelationId correlName : correlatedVariables) {
DeferredLookup lookup = mapCorrelToDeferred.get(correlName);
RexFieldAccess fieldAccess = lookup.getFieldAccess(correlName);
String originalRelName = lookup.getOriginalRelName();
String originalFieldName = fieldAccess.getField().getName();
final SqlNameMatcher nameMatcher = lookup.bb.scope.getValidator().getCatalogReader().nameMatcher();
final SqlValidatorScope.ResolvedImpl resolved = new SqlValidatorScope.ResolvedImpl();
lookup.bb.scope.resolve(ImmutableList.of(originalRelName), nameMatcher, false, resolved);
assert resolved.count() == 1;
final SqlValidatorScope.Resolve resolve = resolved.only();
final SqlValidatorNamespace foundNs = resolve.namespace;
final RelDataType rowType = resolve.rowType();
final int childNamespaceIndex = resolve.path.steps().get(0).i;
final SqlValidatorScope ancestorScope = resolve.scope;
boolean correlInCurrentScope = ancestorScope == bb.scope;
if (!correlInCurrentScope) {
continue;
}
if (prevNs == null) {
prevNs = foundNs;
} else {
assert prevNs == foundNs : "All correlation variables should resolve" + " to the same namespace." + " Prev ns=" + prevNs + ", new ns=" + foundNs;
}
int namespaceOffset = 0;
if (childNamespaceIndex > 0) {
// of output types from all the preceding namespaces
assert ancestorScope instanceof ListScope;
List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren();
for (int i = 0; i < childNamespaceIndex; i++) {
SqlValidatorNamespace child = children.get(i);
namespaceOffset += child.getRowType().getFieldCount();
}
}
RexFieldAccess topLevelFieldAccess = fieldAccess;
while (topLevelFieldAccess.getReferenceExpr() instanceof RexFieldAccess) {
topLevelFieldAccess = (RexFieldAccess) topLevelFieldAccess.getReferenceExpr();
}
final RelDataTypeField field = rowType.getFieldList().get(topLevelFieldAccess.getField().getIndex() - namespaceOffset);
int pos = namespaceOffset + field.getIndex();
assert field.getType() == topLevelFieldAccess.getField().getType();
assert pos != -1;
if (bb.mapRootRelToFieldProjection.containsKey(bb.root)) {
// bb.root is an aggregate and only projects group by
// keys.
Map<Integer, Integer> exprProjection = bb.mapRootRelToFieldProjection.get(bb.root);
// the root of the outer relation.
if (exprProjection.containsKey(pos)) {
pos = exprProjection.get(pos);
} else {
// correl not grouped
throw new AssertionError("Identifier '" + originalRelName + "." + originalFieldName + "' is not a group expr");
}
}
requiredColumns.set(pos);
correlNames.add(correlName);
}
if (correlNames.isEmpty()) {
// None of the correlating variables originated in this scope.
return null;
}
RelNode r = r0;
if (correlNames.size() > 1) {
// The same table was referenced more than once.
// So we deduplicate.
r = DeduplicateCorrelateVariables.go(rexBuilder, correlNames.get(0), Util.skip(correlNames), r0);
// Add new node to leaves.
leaves.add(r);
}
return new CorrelationUse(correlNames.get(0), requiredColumns.build(), r);
}
use of org.apache.calcite.sql.validate.SqlValidatorNamespace in project calcite by apache.
the class SqlToRelConverter method createAggImpl.
protected final void createAggImpl(Blackboard bb, final AggConverter aggConverter, SqlNodeList selectList, SqlNodeList groupList, SqlNode having, List<SqlNode> orderExprList) {
// Find aggregate functions in SELECT and HAVING clause
final AggregateFinder aggregateFinder = new AggregateFinder();
selectList.accept(aggregateFinder);
if (having != null) {
having.accept(aggregateFinder);
}
// first replace the sub-queries inside the aggregates
// because they will provide input rows to the aggregates.
replaceSubQueries(bb, aggregateFinder.list, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
// also replace sub-queries inside filters in the aggregates
replaceSubQueries(bb, aggregateFinder.filterList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
// If group-by clause is missing, pretend that it has zero elements.
if (groupList == null) {
groupList = SqlNodeList.EMPTY;
}
replaceSubQueries(bb, groupList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
// register the group exprs
// build a map to remember the projections from the top scope to the
// output of the current root.
//
// Calcite allows expressions, not just column references in
// group by list. This is not SQL 2003 compliant, but hey.
final AggregatingSelectScope scope = aggConverter.aggregatingSelectScope;
final AggregatingSelectScope.Resolved r = scope.resolved.get();
for (SqlNode groupExpr : r.groupExprList) {
aggConverter.addGroupExpr(groupExpr);
}
final RexNode havingExpr;
final List<Pair<RexNode, String>> projects = Lists.newArrayList();
try {
Preconditions.checkArgument(bb.agg == null, "already in agg mode");
bb.agg = aggConverter;
// convert the select and having expressions, so that the
// agg converter knows which aggregations are required
selectList.accept(aggConverter);
// Assert we don't have dangling items left in the stack
assert !aggConverter.inOver;
for (SqlNode expr : orderExprList) {
expr.accept(aggConverter);
assert !aggConverter.inOver;
}
if (having != null) {
having.accept(aggConverter);
assert !aggConverter.inOver;
}
// compute inputs to the aggregator
List<Pair<RexNode, String>> preExprs = aggConverter.getPreExprs();
if (preExprs.size() == 0) {
// Special case for COUNT(*), where we can end up with no inputs
// at all. The rest of the system doesn't like 0-tuples, so we
// select a dummy constant here.
final RexNode zero = rexBuilder.makeExactLiteral(BigDecimal.ZERO);
preExprs = ImmutableList.of(Pair.of(zero, (String) null));
}
final RelNode inputRel = bb.root;
// Project the expressions required by agg and having.
bb.setRoot(relBuilder.push(inputRel).projectNamed(Pair.left(preExprs), Pair.right(preExprs), false).build(), false);
bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
// REVIEW jvs 31-Oct-2007: doesn't the declaration of
// monotonicity here assume sort-based aggregation at
// the physical level?
// Tell bb which of group columns are sorted.
bb.columnMonotonicities.clear();
for (SqlNode groupItem : groupList) {
bb.columnMonotonicities.add(bb.scope.getMonotonicity(groupItem));
}
// Add the aggregator
bb.setRoot(createAggregate(bb, r.groupSet, r.groupSets, aggConverter.getAggCalls()), false);
bb.mapRootRelToFieldProjection.put(bb.root, r.groupExprProjection);
// the replaced expressions
if (having != null) {
SqlNode newHaving = pushDownNotForIn(bb.scope, having);
replaceSubQueries(bb, newHaving, RelOptUtil.Logic.UNKNOWN_AS_FALSE);
havingExpr = bb.convertExpression(newHaving);
} else {
havingExpr = relBuilder.literal(true);
}
// Now convert the other sub-queries in the select list.
// This needs to be done separately from the sub-query inside
// any aggregate in the select list, and after the aggregate rel
// is allocated.
replaceSubQueries(bb, selectList, RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
// Now sub-queries in the entire select list have been converted.
// Convert the select expressions to get the final list to be
// projected.
int k = 0;
// For select expressions, use the field names previously assigned
// by the validator. If we derive afresh, we might generate names
// like "EXPR$2" that don't match the names generated by the
// validator. This is especially the case when there are system
// fields; system fields appear in the relnode's rowtype but do not
// (yet) appear in the validator type.
final SelectScope selectScope = SqlValidatorUtil.getEnclosingSelectScope(bb.scope);
assert selectScope != null;
final SqlValidatorNamespace selectNamespace = validator.getNamespace(selectScope.getNode());
final List<String> names = selectNamespace.getRowType().getFieldNames();
int sysFieldCount = selectList.size() - names.size();
for (SqlNode expr : selectList) {
projects.add(Pair.of(bb.convertExpression(expr), k < sysFieldCount ? validator.deriveAlias(expr, k++) : names.get(k++ - sysFieldCount)));
}
for (SqlNode expr : orderExprList) {
projects.add(Pair.of(bb.convertExpression(expr), validator.deriveAlias(expr, k++)));
}
} finally {
bb.agg = null;
}
// implement HAVING (we have already checked that it is non-trivial)
relBuilder.push(bb.root);
if (havingExpr != null) {
relBuilder.filter(havingExpr);
}
// implement the SELECT list
relBuilder.project(Pair.left(projects), Pair.right(projects)).rename(Pair.right(projects));
bb.setRoot(relBuilder.build(), false);
// Tell bb which of group columns are sorted.
bb.columnMonotonicities.clear();
for (SqlNode selectItem : selectList) {
bb.columnMonotonicities.add(bb.scope.getMonotonicity(selectItem));
}
}
Aggregations