use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.
the class RelFieldTrimmer method trimFields.
/**
* Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
* {@link org.apache.calcite.rel.logical.LogicalFilter}.
*/
public TrimResult trimFields(Filter filter, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
final RelDataType rowType = filter.getRowType();
final int fieldCount = rowType.getFieldCount();
final RexNode conditionExpr = filter.getCondition();
final RelNode input = filter.getInput();
// We use the fields used by the consumer, plus any fields used in the
// filter.
final Set<RelDataTypeField> inputExtraFields = new LinkedHashSet<>(extraFields);
RelOptUtil.InputFinder inputFinder = new RelOptUtil.InputFinder(inputExtraFields);
inputFinder.inputBitSet.addAll(fieldsUsed);
conditionExpr.accept(inputFinder);
final ImmutableBitSet inputFieldsUsed = inputFinder.inputBitSet.build();
// Create input with trimmed columns.
TrimResult trimResult = trimChild(filter, input, inputFieldsUsed, inputExtraFields);
RelNode newInput = trimResult.left;
final Mapping inputMapping = trimResult.right;
// there's nothing we can do.
if (newInput == input && fieldsUsed.cardinality() == fieldCount) {
return result(filter, Mappings.createIdentity(fieldCount));
}
// Build new project expressions, and populate the mapping.
final RexVisitor<RexNode> shuttle = new RexPermuteInputsShuttle(inputMapping, newInput);
RexNode newConditionExpr = conditionExpr.accept(shuttle);
// Use copy rather than relBuilder so that correlating variables get set.
relBuilder.push(filter.copy(filter.getTraitSet(), newInput, newConditionExpr));
// needs them for its condition.
return result(relBuilder.build(), inputMapping);
}
use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.
the class RelFieldTrimmer method trimFields.
/**
* Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for
* {@link org.apache.calcite.rel.core.Sort}.
*/
public TrimResult trimFields(Sort sort, ImmutableBitSet fieldsUsed, Set<RelDataTypeField> extraFields) {
final RelDataType rowType = sort.getRowType();
final int fieldCount = rowType.getFieldCount();
final RelCollation collation = sort.getCollation();
final RelNode input = sort.getInput();
// We use the fields used by the consumer, plus any fields used as sort
// keys.
final ImmutableBitSet.Builder inputFieldsUsed = fieldsUsed.rebuild();
for (RelFieldCollation field : collation.getFieldCollations()) {
inputFieldsUsed.set(field.getFieldIndex());
}
// Create input with trimmed columns.
final Set<RelDataTypeField> inputExtraFields = Collections.emptySet();
TrimResult trimResult = trimChild(sort, input, inputFieldsUsed.build(), inputExtraFields);
RelNode newInput = trimResult.left;
final Mapping inputMapping = trimResult.right;
// there's nothing we can do.
if (newInput == input && inputMapping.isIdentity() && fieldsUsed.cardinality() == fieldCount) {
return result(sort, Mappings.createIdentity(fieldCount));
}
// leave the Sort unchanged in case we have dynamic limits
if (sort.offset instanceof RexDynamicParam || sort.fetch instanceof RexDynamicParam) {
return result(sort, inputMapping);
}
relBuilder.push(newInput);
final int offset = sort.offset == null ? 0 : RexLiteral.intValue(sort.offset);
final int fetch = sort.fetch == null ? -1 : RexLiteral.intValue(sort.fetch);
final ImmutableList<RexNode> fields = relBuilder.fields(RexUtil.apply(inputMapping, collation));
relBuilder.sortLimit(offset, fetch, fields);
// needs them for its condition.
return result(relBuilder.build(), inputMapping);
}
use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.
the class RelStructuredTypeFlattener method calculateFlattenedOffset.
private int calculateFlattenedOffset(RelDataType rowType, int ordinal) {
int offset = 0;
if (SqlTypeUtil.needsNullIndicator(rowType)) {
// skip null indicator
++offset;
}
List<RelDataTypeField> oldFields = rowType.getFieldList();
for (int i = 0; i < ordinal; ++i) {
RelDataType oldFieldType = oldFields.get(i).getType();
if (oldFieldType.isStruct()) {
// TODO jvs 10-Feb-2005: this isn't terribly efficient;
// keep a mapping somewhere
RelDataType flattened = SqlTypeUtil.flattenRecordType(rexBuilder.getTypeFactory(), oldFieldType, null);
final List<RelDataTypeField> fields = flattened.getFieldList();
offset += fields.size();
} else {
++offset;
}
}
return offset;
}
use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.
the class RelStructuredTypeFlattener method flattenProjection.
private void flattenProjection(RewriteRexShuttle shuttle, RexNode exp, String fieldName, List<Pair<RexNode, String>> flattenedExps) {
if (exp.getType().isStruct()) {
if (exp instanceof RexInputRef) {
RexInputRef inputRef = (RexInputRef) exp;
int newOffset = getNewForOldInput(inputRef.getIndex());
// expand to range
RelDataType flattenedType = SqlTypeUtil.flattenRecordType(rexBuilder.getTypeFactory(), exp.getType(), null);
List<RelDataTypeField> fieldList = flattenedType.getFieldList();
int n = fieldList.size();
for (int j = 0; j < n; ++j) {
RelDataTypeField field = fieldList.get(j);
flattenedExps.add(Pair.<RexNode, String>of(new RexInputRef(newOffset + j, field.getType()), fieldName));
}
} else if (isConstructor(exp) || exp.isA(SqlKind.CAST)) {
// REVIEW jvs 27-Feb-2005: for cast, see corresponding note
// in RewriteRexShuttle
RexCall call = (RexCall) exp;
if (exp.isA(SqlKind.NEW_SPECIFICATION)) {
// For object constructors, prepend a FALSE null
// indicator.
flattenedExps.add(Pair.<RexNode, String>of(rexBuilder.makeLiteral(false), fieldName));
} else if (exp.isA(SqlKind.CAST)) {
if (RexLiteral.isNullLiteral(((RexCall) exp).operands.get(0))) {
// Translate CAST(NULL AS UDT) into
// the correct number of null fields.
flattenNullLiteral(exp.getType(), flattenedExps);
return;
}
}
flattenProjections(new RewriteRexShuttle(), call.getOperands(), Collections.<String>nCopies(call.getOperands().size(), null), fieldName, flattenedExps);
} else if (exp instanceof RexCall) {
// NOTE jvs 10-Feb-2005: This is a lame hack to keep special
// functions which return row types working.
int j = 0;
RexNode newExp = exp;
List<RexNode> oldOperands = ((RexCall) exp).getOperands();
if (oldOperands.get(0) instanceof RexInputRef) {
RexInputRef inputRef = (RexInputRef) oldOperands.get(0);
int newOffset = getNewForOldInput(inputRef.getIndex());
newExp = rexBuilder.makeCall(exp.getType(), ((RexCall) exp).getOperator(), ImmutableList.of(rexBuilder.makeInputRef(inputRef.getType(), newOffset), oldOperands.get(1)));
}
for (RelDataTypeField field : newExp.getType().getFieldList()) {
flattenedExps.add(Pair.of(rexBuilder.makeFieldAccess(newExp, field.getIndex()), fieldName + "$" + (j++)));
}
} else {
throw Util.needToImplement(exp);
}
} else {
flattenedExps.add(Pair.of(exp.accept(shuttle), fieldName));
}
}
use of org.apache.calcite.rel.type.RelDataTypeField in project calcite by apache.
the class SqlValidatorUtil method analyzeGroupExpr.
/**
* Analyzes a component of a tuple in a GROUPING SETS clause.
*/
private static ImmutableBitSet analyzeGroupExpr(SqlValidatorScope scope, GroupAnalyzer groupAnalyzer, SqlNode groupExpr) {
final SqlNode expandedGroupExpr = scope.getValidator().expand(groupExpr, scope);
switch(expandedGroupExpr.getKind()) {
case ROW:
return ImmutableBitSet.union(analyzeGroupTuple(scope, groupAnalyzer, ((SqlCall) expandedGroupExpr).getOperandList()));
case OTHER:
if (expandedGroupExpr instanceof SqlNodeList && ((SqlNodeList) expandedGroupExpr).size() == 0) {
return ImmutableBitSet.of();
}
}
final int ref = lookupGroupExpr(groupAnalyzer, groupExpr);
if (expandedGroupExpr instanceof SqlIdentifier) {
// SQL 2003 does not allow expressions of column references
SqlIdentifier expr = (SqlIdentifier) expandedGroupExpr;
// column references should be fully qualified.
assert expr.names.size() == 2;
String originalRelName = expr.names.get(0);
String originalFieldName = expr.names.get(1);
final SqlNameMatcher nameMatcher = scope.getValidator().getCatalogReader().nameMatcher();
final SqlValidatorScope.ResolvedImpl resolved = new SqlValidatorScope.ResolvedImpl();
scope.resolve(ImmutableList.of(originalRelName), nameMatcher, false, resolved);
assert resolved.count() == 1;
final SqlValidatorScope.Resolve resolve = resolved.only();
final RelDataType rowType = resolve.rowType();
final int childNamespaceIndex = resolve.path.steps().get(0).i;
int namespaceOffset = 0;
if (childNamespaceIndex > 0) {
// If not the first child, need to figure out the width of
// output types from all the preceding namespaces
final SqlValidatorScope ancestorScope = resolve.scope;
assert ancestorScope instanceof ListScope;
List<SqlValidatorNamespace> children = ((ListScope) ancestorScope).getChildren();
for (int j = 0; j < childNamespaceIndex; j++) {
namespaceOffset += children.get(j).getRowType().getFieldCount();
}
}
RelDataTypeField field = nameMatcher.field(rowType, originalFieldName);
int origPos = namespaceOffset + field.getIndex();
groupAnalyzer.groupExprProjection.put(origPos, ref);
}
return ImmutableBitSet.of(ref);
}
Aggregations