use of org.apache.calcite.rel.core.Match in project beam by apache.
the class BeamMatchRule method convert.
@Override
public RelNode convert(RelNode rel) {
Match match = (Match) rel;
final RelNode input = match.getInput();
return new BeamMatchRel(match.getCluster(), match.getTraitSet().replace(BeamLogicalConvention.INSTANCE), convert(input, input.getTraitSet().replace(BeamLogicalConvention.INSTANCE)), match.getRowType(), match.getPattern(), match.isStrictStart(), match.isStrictEnd(), match.getPatternDefinitions(), match.getMeasures(), match.getAfter(), match.getSubsets(), match.isAllRows(), match.getPartitionKeys(), match.getOrderKeys(), match.getInterval());
}
use of org.apache.calcite.rel.core.Match in project calcite by apache.
the class RelBuilder method unpivot.
/**
* Creates an Unpivot.
*
* <p>To achieve the same effect as the SQL
*
* <blockquote><pre>{@code
* SELECT *
* FROM (SELECT deptno, job, sal, comm FROM emp)
* UNPIVOT INCLUDE NULLS (remuneration
* FOR remuneration_type IN (comm AS 'commission',
* sal AS 'salary'))
* }</pre></blockquote>
*
* <p>use the builder as follows:
*
* <blockquote><pre>{@code
* RelBuilder b;
* b.scan("EMP");
* final List<String> measureNames = Arrays.asList("REMUNERATION");
* final List<String> axisNames = Arrays.asList("REMUNERATION_TYPE");
* final Map<List<RexLiteral>, List<RexNode>> axisMap =
* ImmutableMap.<List<RexLiteral>, List<RexNode>>builder()
* .put(Arrays.asList(b.literal("commission")),
* Arrays.asList(b.field("COMM")))
* .put(Arrays.asList(b.literal("salary")),
* Arrays.asList(b.field("SAL")))
* .build();
* b.unpivot(false, measureNames, axisNames, axisMap);
* }</pre></blockquote>
*
* <p>The query generates two columns: {@code remuneration_type} (an axis
* column) and {@code remuneration} (a measure column). Axis columns contain
* values to indicate the source of the row (in this case, {@code 'salary'}
* if the row came from the {@code sal} column, and {@code 'commission'}
* if the row came from the {@code comm} column).
*
* @param includeNulls Whether to include NULL values in the output
* @param measureNames Names of columns to be generated to hold pivoted
* measures
* @param axisNames Names of columns to be generated to hold qualifying values
* @param axisMap Mapping from the columns that hold measures to the values
* that the axis columns will hold in the generated rows
* @return This RelBuilder
*/
public RelBuilder unpivot(boolean includeNulls, Iterable<String> measureNames, Iterable<String> axisNames, Iterable<? extends Map.Entry<? extends List<? extends RexLiteral>, ? extends List<? extends RexNode>>> axisMap) {
// Make immutable copies of all arguments.
final List<String> measureNameList = ImmutableList.copyOf(measureNames);
final List<String> axisNameList = ImmutableList.copyOf(axisNames);
final List<Pair<List<RexLiteral>, List<RexNode>>> map = StreamSupport.stream(axisMap.spliterator(), false).map(pair -> Pair.<List<RexLiteral>, List<RexNode>>of(ImmutableList.<RexLiteral>copyOf(pair.getKey()), ImmutableList.<RexNode>copyOf(pair.getValue()))).collect(Util.toImmutableList());
// Check that counts match.
Pair.forEach(map, (valueList, inputMeasureList) -> {
if (inputMeasureList.size() != measureNameList.size()) {
throw new IllegalArgumentException("Number of measures (" + inputMeasureList.size() + ") must match number of measure names (" + measureNameList.size() + ")");
}
if (valueList.size() != axisNameList.size()) {
throw new IllegalArgumentException("Number of axis values (" + valueList.size() + ") match match number of axis names (" + axisNameList.size() + ")");
}
});
final RelDataType leftRowType = peek().getRowType();
final BitSet usedFields = new BitSet();
Pair.forEach(map, (aliases, nodes) -> nodes.forEach(node -> {
if (node instanceof RexInputRef) {
usedFields.set(((RexInputRef) node).getIndex());
}
}));
// Create "VALUES (('commission'), ('salary')) AS t (remuneration_type)"
values(ImmutableList.copyOf(Pair.left(map)), axisNameList);
join(JoinRelType.INNER);
final ImmutableBitSet unusedFields = ImmutableBitSet.range(leftRowType.getFieldCount()).except(ImmutableBitSet.fromBitSet(usedFields));
final List<RexNode> projects = new ArrayList<>(fields(unusedFields));
Ord.forEach(axisNameList, (dimensionName, d) -> projects.add(alias(field(leftRowType.getFieldCount() + d), dimensionName)));
final List<RexNode> conditions = new ArrayList<>();
Ord.forEach(measureNameList, (measureName, m) -> {
final List<RexNode> caseOperands = new ArrayList<>();
Pair.forEach(map, (literals, nodes) -> {
Ord.forEach(literals, (literal, d) -> conditions.add(equals(field(leftRowType.getFieldCount() + d), literal)));
caseOperands.add(and(conditions));
conditions.clear();
caseOperands.add(nodes.get(m));
});
caseOperands.add(literal(null));
projects.add(alias(call(SqlStdOperatorTable.CASE, caseOperands), measureName));
});
project(projects);
if (!includeNulls) {
// Add 'WHERE m1 IS NOT NULL OR m2 IS NOT NULL'
final BitSet notNullFields = new BitSet();
Ord.forEach(measureNameList, (measureName, m) -> {
final int f = unusedFields.cardinality() + axisNameList.size() + m;
conditions.add(isNotNull(field(f)));
notNullFields.set(f);
});
filter(or(conditions));
if (measureNameList.size() == 1) {
// If there is one field, EXCLUDE NULLS will have converted it to NOT
// NULL.
final RelDataTypeFactory.Builder builder = getTypeFactory().builder();
peek().getRowType().getFieldList().forEach(field -> {
final RelDataType type = field.getType();
builder.add(field.getName(), notNullFields.get(field.getIndex()) ? getTypeFactory().createTypeWithNullability(type, false) : type);
});
convert(builder.build(), false);
}
conditions.clear();
}
return this;
}
use of org.apache.calcite.rel.core.Match in project calcite by apache.
the class MutableRels method toMutable.
public static MutableRel toMutable(RelNode rel) {
if (rel instanceof HepRelVertex) {
return toMutable(((HepRelVertex) rel).getCurrentRel());
}
if (rel instanceof RelSubset) {
RelSubset subset = (RelSubset) rel;
RelNode best = subset.getBest();
if (best == null) {
best = requireNonNull(subset.getOriginal(), () -> "subset.getOriginal() is null for " + subset);
}
return toMutable(best);
}
if (rel instanceof TableScan) {
return MutableScan.of((TableScan) rel);
}
if (rel instanceof Values) {
return MutableValues.of((Values) rel);
}
if (rel instanceof Project) {
final Project project = (Project) rel;
final MutableRel input = toMutable(project.getInput());
return MutableProject.of(input, project.getProjects(), project.getRowType().getFieldNames());
}
if (rel instanceof Filter) {
final Filter filter = (Filter) rel;
final MutableRel input = toMutable(filter.getInput());
return MutableFilter.of(input, filter.getCondition());
}
if (rel instanceof Aggregate) {
final Aggregate aggregate = (Aggregate) rel;
final MutableRel input = toMutable(aggregate.getInput());
return MutableAggregate.of(input, aggregate.getGroupSet(), aggregate.getGroupSets(), aggregate.getAggCallList());
}
if (rel instanceof Sort) {
final Sort sort = (Sort) rel;
final MutableRel input = toMutable(sort.getInput());
return MutableSort.of(input, sort.getCollation(), sort.offset, sort.fetch);
}
if (rel instanceof Calc) {
final Calc calc = (Calc) rel;
final MutableRel input = toMutable(calc.getInput());
return MutableCalc.of(input, calc.getProgram());
}
if (rel instanceof Exchange) {
final Exchange exchange = (Exchange) rel;
final MutableRel input = toMutable(exchange.getInput());
return MutableExchange.of(input, exchange.getDistribution());
}
if (rel instanceof Collect) {
final Collect collect = (Collect) rel;
final MutableRel input = toMutable(collect.getInput());
return MutableCollect.of(collect.getRowType(), input, collect.getFieldName());
}
if (rel instanceof Uncollect) {
final Uncollect uncollect = (Uncollect) rel;
final MutableRel input = toMutable(uncollect.getInput());
return MutableUncollect.of(uncollect.getRowType(), input, uncollect.withOrdinality);
}
if (rel instanceof Window) {
final Window window = (Window) rel;
final MutableRel input = toMutable(window.getInput());
return MutableWindow.of(window.getRowType(), input, window.groups, window.getConstants());
}
if (rel instanceof Match) {
final Match match = (Match) rel;
final MutableRel input = toMutable(match.getInput());
return MutableMatch.of(match.getRowType(), input, match.getPattern(), match.isStrictStart(), match.isStrictEnd(), match.getPatternDefinitions(), match.getMeasures(), match.getAfter(), match.getSubsets(), match.isAllRows(), match.getPartitionKeys(), match.getOrderKeys(), match.getInterval());
}
if (rel instanceof TableModify) {
final TableModify modify = (TableModify) rel;
final MutableRel input = toMutable(modify.getInput());
return MutableTableModify.of(modify.getRowType(), input, modify.getTable(), modify.getCatalogReader(), modify.getOperation(), modify.getUpdateColumnList(), modify.getSourceExpressionList(), modify.isFlattened());
}
if (rel instanceof Sample) {
final Sample sample = (Sample) rel;
final MutableRel input = toMutable(sample.getInput());
return MutableSample.of(input, sample.getSamplingParameters());
}
if (rel instanceof TableFunctionScan) {
final TableFunctionScan tableFunctionScan = (TableFunctionScan) rel;
final List<MutableRel> inputs = toMutables(tableFunctionScan.getInputs());
return MutableTableFunctionScan.of(tableFunctionScan.getCluster(), tableFunctionScan.getRowType(), inputs, tableFunctionScan.getCall(), tableFunctionScan.getElementType(), tableFunctionScan.getColumnMappings());
}
// is a sub-class of Join.
if (rel instanceof Join) {
final Join join = (Join) rel;
final MutableRel left = toMutable(join.getLeft());
final MutableRel right = toMutable(join.getRight());
return MutableJoin.of(join.getRowType(), left, right, join.getCondition(), join.getJoinType(), join.getVariablesSet());
}
if (rel instanceof Correlate) {
final Correlate correlate = (Correlate) rel;
final MutableRel left = toMutable(correlate.getLeft());
final MutableRel right = toMutable(correlate.getRight());
return MutableCorrelate.of(correlate.getRowType(), left, right, correlate.getCorrelationId(), correlate.getRequiredColumns(), correlate.getJoinType());
}
if (rel instanceof Union) {
final Union union = (Union) rel;
final List<MutableRel> inputs = toMutables(union.getInputs());
return MutableUnion.of(union.getRowType(), inputs, union.all);
}
if (rel instanceof Minus) {
final Minus minus = (Minus) rel;
final List<MutableRel> inputs = toMutables(minus.getInputs());
return MutableMinus.of(minus.getRowType(), inputs, minus.all);
}
if (rel instanceof Intersect) {
final Intersect intersect = (Intersect) rel;
final List<MutableRel> inputs = toMutables(intersect.getInputs());
return MutableIntersect.of(intersect.getRowType(), inputs, intersect.all);
}
throw new RuntimeException("cannot translate " + rel + " to MutableRel");
}
Aggregations