use of org.apache.calcite.rel.logical.LogicalProject in project storm by apache.
the class TestRelNodeCompiler method testFilter.
@Test
public void testFilter() throws Exception {
String sql = "SELECT ID + 1 FROM FOO WHERE ID > 3";
TestCompilerUtils.CalciteState state = TestCompilerUtils.sqlOverDummyTable(sql);
JavaTypeFactory typeFactory = new JavaTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
LogicalProject project = (LogicalProject) state.tree();
LogicalFilter filter = (LogicalFilter) project.getInput();
try (StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw)) {
RelNodeCompiler compiler = new RelNodeCompiler(pw, typeFactory);
// standalone mode doesn't use inputstreams argument
compiler.visitFilter(filter, Collections.EMPTY_LIST);
pw.flush();
Assert.assertThat(sw.toString(), containsString("> 3"));
}
try (StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw)) {
RelNodeCompiler compiler = new RelNodeCompiler(pw, typeFactory);
// standalone mode doesn't use inputstreams argument
compiler.visitProject(project, Collections.EMPTY_LIST);
pw.flush();
Assert.assertThat(sw.toString(), containsString(" + 1"));
}
}
use of org.apache.calcite.rel.logical.LogicalProject in project calcite by apache.
the class SqlToRelConverter method convertMerge.
private RelNode convertMerge(SqlMerge call) {
RelOptTable targetTable = getTargetTable(call);
// convert update column list from SqlIdentifier to String
final List<String> targetColumnNameList = new ArrayList<>();
final RelDataType targetRowType = targetTable.getRowType();
SqlUpdate updateCall = call.getUpdateCall();
if (updateCall != null) {
for (SqlNode targetColumn : updateCall.getTargetColumnList()) {
SqlIdentifier id = (SqlIdentifier) targetColumn;
RelDataTypeField field = SqlValidatorUtil.getTargetField(targetRowType, typeFactory, id, catalogReader, targetTable);
assert field != null : "column " + id.toString() + " not found";
targetColumnNameList.add(field.getName());
}
}
// replace the projection of the source select with a
// projection that contains the following:
// 1) the expressions corresponding to the new insert row (if there is
// an insert)
// 2) all columns from the target table (if there is an update)
// 3) the set expressions in the update call (if there is an update)
// first, convert the merge's source select to construct the columns
// from the target table and the set expressions in the update call
RelNode mergeSourceRel = convertSelect(call.getSourceSelect(), false);
// then, convert the insert statement so we can get the insert
// values expressions
SqlInsert insertCall = call.getInsertCall();
int nLevel1Exprs = 0;
List<RexNode> level1InsertExprs = null;
List<RexNode> level2InsertExprs = null;
if (insertCall != null) {
RelNode insertRel = convertInsert(insertCall);
// if there are 2 level of projections in the insert source, combine
// them into a single project; level1 refers to the topmost project;
// the level1 projection contains references to the level2
// expressions, except in the case where no target expression was
// provided, in which case, the expression is the default value for
// the column; or if the expressions directly map to the source
// table
level1InsertExprs = ((LogicalProject) insertRel.getInput(0)).getProjects();
if (insertRel.getInput(0).getInput(0) instanceof LogicalProject) {
level2InsertExprs = ((LogicalProject) insertRel.getInput(0).getInput(0)).getProjects();
}
nLevel1Exprs = level1InsertExprs.size();
}
LogicalJoin join = (LogicalJoin) mergeSourceRel.getInput(0);
int nSourceFields = join.getLeft().getRowType().getFieldCount();
final List<RexNode> projects = new ArrayList<>();
for (int level1Idx = 0; level1Idx < nLevel1Exprs; level1Idx++) {
if ((level2InsertExprs != null) && (level1InsertExprs.get(level1Idx) instanceof RexInputRef)) {
int level2Idx = ((RexInputRef) level1InsertExprs.get(level1Idx)).getIndex();
projects.add(level2InsertExprs.get(level2Idx));
} else {
projects.add(level1InsertExprs.get(level1Idx));
}
}
if (updateCall != null) {
final LogicalProject project = (LogicalProject) mergeSourceRel;
projects.addAll(Util.skip(project.getProjects(), nSourceFields));
}
relBuilder.push(join).project(projects);
return LogicalTableModify.create(targetTable, catalogReader, relBuilder.build(), LogicalTableModify.Operation.MERGE, targetColumnNameList, null, false);
}
use of org.apache.calcite.rel.logical.LogicalProject in project calcite by apache.
the class SqlToRelConverter method distinctify.
/**
* Having translated 'SELECT ... FROM ... [GROUP BY ...] [HAVING ...]', adds
* a relational expression to make the results unique.
*
* <p>If the SELECT clause contains duplicate expressions, adds
* {@link org.apache.calcite.rel.logical.LogicalProject}s so that we are
* grouping on the minimal set of keys. The performance gain isn't huge, but
* it is difficult to detect these duplicate expressions later.
*
* @param bb Blackboard
* @param checkForDupExprs Check for duplicate expressions
*/
private void distinctify(Blackboard bb, boolean checkForDupExprs) {
// Look for duplicate expressions in the project.
// Say we have 'select x, y, x, z'.
// Then dups will be {[2, 0]}
// and oldToNew will be {[0, 0], [1, 1], [2, 0], [3, 2]}
RelNode rel = bb.root;
if (checkForDupExprs && (rel instanceof LogicalProject)) {
LogicalProject project = (LogicalProject) rel;
final List<RexNode> projectExprs = project.getProjects();
final List<Integer> origins = new ArrayList<>();
int dupCount = 0;
for (int i = 0; i < projectExprs.size(); i++) {
int x = findExpr(projectExprs.get(i), projectExprs, i);
if (x >= 0) {
origins.add(x);
++dupCount;
} else {
origins.add(i);
}
}
if (dupCount == 0) {
distinctify(bb, false);
return;
}
final Map<Integer, Integer> squished = Maps.newHashMap();
final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
final List<Pair<RexNode, String>> newProjects = Lists.newArrayList();
for (int i = 0; i < fields.size(); i++) {
if (origins.get(i) == i) {
squished.put(i, newProjects.size());
newProjects.add(RexInputRef.of2(i, fields));
}
}
rel = LogicalProject.create(rel, Pair.left(newProjects), Pair.right(newProjects));
bb.root = rel;
distinctify(bb, false);
rel = bb.root;
// Create the expressions to reverse the mapping.
// Project($0, $1, $0, $2).
final List<Pair<RexNode, String>> undoProjects = Lists.newArrayList();
for (int i = 0; i < fields.size(); i++) {
final int origin = origins.get(i);
RelDataTypeField field = fields.get(i);
undoProjects.add(Pair.of((RexNode) new RexInputRef(squished.get(origin), field.getType()), field.getName()));
}
rel = LogicalProject.create(rel, Pair.left(undoProjects), Pair.right(undoProjects));
bb.setRoot(rel, false);
return;
}
// Usual case: all of the expressions in the SELECT clause are
// different.
final ImmutableBitSet groupSet = ImmutableBitSet.range(rel.getRowType().getFieldCount());
rel = createAggregate(bb, groupSet, ImmutableList.of(groupSet), ImmutableList.<AggregateCall>of());
bb.setRoot(rel, false);
}
use of org.apache.calcite.rel.logical.LogicalProject in project calcite by apache.
the class RelOptUtil method permute.
/**
* Creates a relational expression which permutes the output fields of a
* relational expression according to a permutation.
*
* <p>Optimizations:</p>
*
* <ul>
* <li>If the relational expression is a
* {@link org.apache.calcite.rel.logical.LogicalCalc} or
* {@link org.apache.calcite.rel.logical.LogicalProject} that is already
* acting as a permutation, combines the new permutation with the old;</li>
*
* <li>If the permutation is the identity, returns the original relational
* expression.</li>
* </ul>
*
* <p>If a permutation is combined with its inverse, these optimizations
* would combine to remove them both.
*
* @param rel Relational expression
* @param permutation Permutation to apply to fields
* @param fieldNames Field names; if null, or if a particular entry is null,
* the name of the permuted field is used
* @return relational expression which permutes its input fields
*/
public static RelNode permute(RelNode rel, Permutation permutation, List<String> fieldNames) {
if (permutation.isIdentity()) {
return rel;
}
if (rel instanceof LogicalCalc) {
LogicalCalc calc = (LogicalCalc) rel;
Permutation permutation1 = calc.getProgram().getPermutation();
if (permutation1 != null) {
Permutation permutation2 = permutation.product(permutation1);
return permute(rel, permutation2, null);
}
}
if (rel instanceof LogicalProject) {
Permutation permutation1 = ((LogicalProject) rel).getPermutation();
if (permutation1 != null) {
Permutation permutation2 = permutation.product(permutation1);
return permute(rel, permutation2, null);
}
}
final List<RelDataType> outputTypeList = new ArrayList<>();
final List<String> outputNameList = new ArrayList<>();
final List<RexNode> exprList = new ArrayList<>();
final List<RexLocalRef> projectRefList = new ArrayList<>();
final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
final RelOptCluster cluster = rel.getCluster();
for (int i = 0; i < permutation.getTargetCount(); i++) {
int target = permutation.getTarget(i);
final RelDataTypeField targetField = fields.get(target);
outputTypeList.add(targetField.getType());
outputNameList.add(((fieldNames == null) || (fieldNames.size() <= i) || (fieldNames.get(i) == null)) ? targetField.getName() : fieldNames.get(i));
exprList.add(cluster.getRexBuilder().makeInputRef(fields.get(i).getType(), i));
final int source = permutation.getSource(i);
projectRefList.add(new RexLocalRef(source, fields.get(source).getType()));
}
final RelDataTypeFactory typeFactory = cluster.getTypeFactory();
final RexProgram program = new RexProgram(rel.getRowType(), exprList, projectRefList, null, typeFactory.createStructType(outputTypeList, outputNameList));
return LogicalCalc.create(rel, program);
}
use of org.apache.calcite.rel.logical.LogicalProject in project calcite by apache.
the class ProjectSetOpTransposeRule method onMatch.
// ~ Methods ----------------------------------------------------------------
// implement RelOptRule
public void onMatch(RelOptRuleCall call) {
LogicalProject origProj = call.rel(0);
SetOp setOp = call.rel(1);
// cannot push project past a distinct
if (!setOp.all) {
return;
}
// locate all fields referenced in the projection
PushProjector pushProject = new PushProjector(origProj, null, setOp, preserveExprCondition, call.builder());
pushProject.locateAllRefs();
List<RelNode> newSetOpInputs = new ArrayList<>();
int[] adjustments = pushProject.getAdjustments();
// and it is the only operator this rule currently acts on
for (RelNode input : setOp.getInputs()) {
// be lazy: produce two ProjectRels, and let another rule
// merge them (could probably just clone origProj instead?)
Project p = pushProject.createProjectRefsAndExprs(input, true, false);
newSetOpInputs.add(pushProject.createNewProject(p, adjustments));
}
// create a new setop whose children are the ProjectRels created above
SetOp newSetOp = setOp.copy(setOp.getTraitSet(), newSetOpInputs);
call.transformTo(newSetOp);
}
Aggregations