use of org.apache.calcite.rex.RexInputRef in project calcite by apache.
the class RelMdColumnUniqueness method simplyProjects.
private boolean simplyProjects(RelNode rel, ImmutableBitSet columns) {
if (!(rel instanceof Project)) {
return false;
}
Project project = (Project) rel;
final List<RexNode> projects = project.getProjects();
for (int column : columns) {
if (column >= projects.size()) {
return false;
}
if (!(projects.get(column) instanceof RexInputRef)) {
return false;
}
final RexInputRef ref = (RexInputRef) projects.get(column);
if (ref.getIndex() != column) {
return false;
}
}
return true;
}
use of org.apache.calcite.rex.RexInputRef in project calcite by apache.
the class RelMdColumnUniqueness method areColumnsUnique.
public Boolean areColumnsUnique(Project rel, RelMetadataQuery mq, ImmutableBitSet columns, boolean ignoreNulls) {
// LogicalProject maps a set of rows to a different set;
// Without knowledge of the mapping function(whether it
// preserves uniqueness), it is only safe to derive uniqueness
// info from the child of a project when the mapping is f(a) => a.
//
// Also need to map the input column set to the corresponding child
// references
List<RexNode> projExprs = rel.getProjects();
ImmutableBitSet.Builder childColumns = ImmutableBitSet.builder();
for (int bit : columns) {
RexNode projExpr = projExprs.get(bit);
if (projExpr instanceof RexInputRef) {
childColumns.set(((RexInputRef) projExpr).getIndex());
} else if (projExpr instanceof RexCall && ignoreNulls) {
// If the expression is a cast such that the types are the same
// except for the nullability, then if we're ignoring nulls,
// it doesn't matter whether the underlying column reference
// is nullable. Check that the types are the same by making a
// nullable copy of both types and then comparing them.
RexCall call = (RexCall) projExpr;
if (call.getOperator() != SqlStdOperatorTable.CAST) {
continue;
}
RexNode castOperand = call.getOperands().get(0);
if (!(castOperand instanceof RexInputRef)) {
continue;
}
RelDataTypeFactory typeFactory = rel.getCluster().getTypeFactory();
RelDataType castType = typeFactory.createTypeWithNullability(projExpr.getType(), true);
RelDataType origType = typeFactory.createTypeWithNullability(castOperand.getType(), true);
if (castType.equals(origType)) {
childColumns.set(((RexInputRef) castOperand).getIndex());
}
} else {
// projection, then skip it.
continue;
}
}
// If no columns can affect uniqueness, then return unknown
if (childColumns.cardinality() == 0) {
return null;
}
return mq.areColumnsUnique(rel.getInput(), childColumns.build(), ignoreNulls);
}
use of org.apache.calcite.rex.RexInputRef in project calcite by apache.
the class RelMdExpressionLineage method getExpressionLineage.
/**
* Expression lineage from {@link Join}.
*
* <p>We only extract the lineage for INNER joins.
*/
public Set<RexNode> getExpressionLineage(Join rel, RelMetadataQuery mq, RexNode outputExpression) {
if (rel.getJoinType() != JoinRelType.INNER) {
// We cannot map origin of this expression.
return null;
}
final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
final RelNode leftInput = rel.getLeft();
final RelNode rightInput = rel.getRight();
final int nLeftColumns = leftInput.getRowType().getFieldList().size();
// Infer column origin expressions for given references
final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = HashMultimap.create();
final Map<RelTableRef, RelTableRef> currentTablesMapping = new HashMap<>();
final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
for (int idx = 0; idx < rel.getRowType().getFieldList().size(); idx++) {
if (idx < nLeftColumns) {
final RexInputRef inputRef = RexInputRef.of(idx, leftInput.getRowType().getFieldList());
final Set<RexNode> originalExprs = mq.getExpressionLineage(leftInput, inputRef);
if (originalExprs == null) {
// Bail out
return null;
}
// Gather table references, left input references remain unchanged
final Set<RelTableRef> tableRefs = RexUtil.gatherTableReferences(Lists.newArrayList(originalExprs));
for (RelTableRef leftRef : tableRefs) {
qualifiedNamesToRefs.put(leftRef.getQualifiedName(), leftRef);
}
mapping.put(RexInputRef.of(idx, rel.getRowType().getFieldList()), originalExprs);
} else {
// Right input.
final RexInputRef inputRef = RexInputRef.of(idx - nLeftColumns, rightInput.getRowType().getFieldList());
final Set<RexNode> originalExprs = mq.getExpressionLineage(rightInput, inputRef);
if (originalExprs == null) {
// Bail out
return null;
}
// Gather table references, right input references might need to be
// updated if there are table names clashes with left input
final Set<RelTableRef> tableRefs = RexUtil.gatherTableReferences(Lists.newArrayList(originalExprs));
for (RelTableRef rightRef : tableRefs) {
int shift = 0;
Collection<RelTableRef> lRefs = qualifiedNamesToRefs.get(rightRef.getQualifiedName());
if (lRefs != null) {
shift = lRefs.size();
}
currentTablesMapping.put(rightRef, RelTableRef.of(rightRef.getTable(), shift + rightRef.getEntityNumber()));
}
final Set<RexNode> updatedExprs = Sets.newHashSet(Iterables.transform(originalExprs, new Function<RexNode, RexNode>() {
@Override
public RexNode apply(RexNode e) {
return RexUtil.swapTableReferences(rexBuilder, e, currentTablesMapping);
}
}));
mapping.put(RexInputRef.of(idx, rel.getRowType().getFieldList()), updatedExprs);
}
}
// Return result
return createAllPossibleExpressions(rexBuilder, outputExpression, mapping);
}
use of org.apache.calcite.rex.RexInputRef in project calcite by apache.
the class RelMdExpressionLineage method getExpressionLineage.
/**
* Expression lineage from {@link Union}.
*
* <p>For Union operator, we might be able to extract multiple origins for the
* references in the given expression.
*/
public Set<RexNode> getExpressionLineage(Union rel, RelMetadataQuery mq, RexNode outputExpression) {
final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
// Infer column origin expressions for given references
final Multimap<List<String>, RelTableRef> qualifiedNamesToRefs = HashMultimap.create();
final Map<RexInputRef, Set<RexNode>> mapping = new LinkedHashMap<>();
for (RelNode input : rel.getInputs()) {
final Map<RelTableRef, RelTableRef> currentTablesMapping = new HashMap<>();
for (int idx = 0; idx < input.getRowType().getFieldList().size(); idx++) {
final RexInputRef inputRef = RexInputRef.of(idx, input.getRowType().getFieldList());
final Set<RexNode> originalExprs = mq.getExpressionLineage(input, inputRef);
if (originalExprs == null) {
// Bail out
return null;
}
final RexInputRef ref = RexInputRef.of(idx, rel.getRowType().getFieldList());
// Gather table references, references might need to be
// updated
final Set<RelTableRef> tableRefs = RexUtil.gatherTableReferences(Lists.newArrayList(originalExprs));
for (RelTableRef tableRef : tableRefs) {
int shift = 0;
Collection<RelTableRef> lRefs = qualifiedNamesToRefs.get(tableRef.getQualifiedName());
if (lRefs != null) {
shift = lRefs.size();
}
currentTablesMapping.put(tableRef, RelTableRef.of(tableRef.getTable(), shift + tableRef.getEntityNumber()));
}
final Set<RexNode> updatedExprs = Sets.newHashSet(Iterables.transform(originalExprs, new Function<RexNode, RexNode>() {
@Override
public RexNode apply(RexNode e) {
return RexUtil.swapTableReferences(rexBuilder, e, currentTablesMapping);
}
}));
final Set<RexNode> set = mapping.get(ref);
if (set != null) {
set.addAll(updatedExprs);
} else {
mapping.put(ref, updatedExprs);
}
}
// Add to existing qualified names
for (RelTableRef newRef : currentTablesMapping.values()) {
qualifiedNamesToRefs.put(newRef.getQualifiedName(), newRef);
}
}
// Return result
return createAllPossibleExpressions(rexBuilder, outputExpression, mapping);
}
use of org.apache.calcite.rex.RexInputRef in project calcite by apache.
the class LogicalWindow method toInputRefs.
private static List<RexNode> toInputRefs(final List<? extends RexNode> operands) {
return new AbstractList<RexNode>() {
public int size() {
return operands.size();
}
public RexNode get(int index) {
final RexNode operand = operands.get(index);
if (operand instanceof RexInputRef) {
return operand;
}
assert operand instanceof RexLocalRef;
final RexLocalRef ref = (RexLocalRef) operand;
return new RexInputRef(ref.getIndex(), ref.getType());
}
};
}
Aggregations