use of org.apache.calcite.sql.validate.ListScope 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.ListScope in project calcite by apache.
the class SqlToRelConverter method convertMultisets.
private RelNode convertMultisets(final List<SqlNode> operands, Blackboard bb) {
// NOTE: Wael 2/04/05: this implementation is not the most efficient in
// terms of planning since it generates XOs that can be reduced.
final List<Object> joinList = new ArrayList<>();
List<SqlNode> lastList = new ArrayList<>();
for (int i = 0; i < operands.size(); i++) {
SqlNode operand = operands.get(i);
if (!(operand instanceof SqlCall)) {
lastList.add(operand);
continue;
}
final SqlCall call = (SqlCall) operand;
final RelNode input;
switch(call.getKind()) {
case MULTISET_VALUE_CONSTRUCTOR:
case ARRAY_VALUE_CONSTRUCTOR:
final SqlNodeList list = new SqlNodeList(call.getOperandList(), call.getParserPosition());
CollectNamespace nss = (CollectNamespace) validator.getNamespace(call);
Blackboard usedBb;
if (null != nss) {
usedBb = createBlackboard(nss.getScope(), null, false);
} else {
usedBb = createBlackboard(new ListScope(bb.scope) {
public SqlNode getNode() {
return call;
}
}, null, false);
}
RelDataType multisetType = validator.getValidatedNodeType(call);
((SqlValidatorImpl) validator).setValidatedNodeType(list, multisetType.getComponentType());
input = convertQueryOrInList(usedBb, list, null);
break;
case MULTISET_QUERY_CONSTRUCTOR:
case ARRAY_QUERY_CONSTRUCTOR:
final RelRoot root = convertQuery(call.operand(0), false, true);
input = root.rel;
break;
default:
lastList.add(operand);
continue;
}
if (lastList.size() > 0) {
joinList.add(lastList);
}
lastList = new ArrayList<>();
Collect collect = new Collect(cluster, cluster.traitSetOf(Convention.NONE), input, validator.deriveAlias(call, i));
joinList.add(collect);
}
if (joinList.size() == 0) {
joinList.add(lastList);
}
for (int i = 0; i < joinList.size(); i++) {
Object o = joinList.get(i);
if (o instanceof List) {
@SuppressWarnings("unchecked") List<SqlNode> projectList = (List<SqlNode>) o;
final List<RexNode> selectList = new ArrayList<>();
final List<String> fieldNameList = new ArrayList<>();
for (int j = 0; j < projectList.size(); j++) {
SqlNode operand = projectList.get(j);
selectList.add(bb.convertExpression(operand));
// REVIEW angel 5-June-2005: Use deriveAliasFromOrdinal
// instead of deriveAlias to match field names from
// SqlRowOperator. Otherwise, get error Type
// 'RecordType(INTEGER EMPNO)' has no field 'EXPR$0' when
// doing select * from unnest( select multiset[empno]
// from sales.emps);
fieldNameList.add(SqlUtil.deriveAliasFromOrdinal(j));
}
relBuilder.push(LogicalValues.createOneRow(cluster)).projectNamed(selectList, fieldNameList, true);
joinList.set(i, relBuilder.build());
}
}
RelNode ret = (RelNode) joinList.get(0);
for (int i = 1; i < joinList.size(); i++) {
RelNode relNode = (RelNode) joinList.get(i);
ret = RelFactories.DEFAULT_JOIN_FACTORY.createJoin(ret, relNode, rexBuilder.makeLiteral(true), ImmutableSet.<CorrelationId>of(), JoinRelType.INNER, false);
}
return ret;
}
Aggregations