You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by fh...@apache.org on 2017/11/16 13:26:14 UTC
[5/5] flink git commit: [FLINK-7389] [table] Remove Calcite
PushProjector
[FLINK-7389] [table] Remove Calcite PushProjector
This closes #5022.
Project: http://git-wip-us.apache.org/repos/asf/flink/repo
Commit: http://git-wip-us.apache.org/repos/asf/flink/commit/fc3eebd1
Tree: http://git-wip-us.apache.org/repos/asf/flink/tree/fc3eebd1
Diff: http://git-wip-us.apache.org/repos/asf/flink/diff/fc3eebd1
Branch: refs/heads/master
Commit: fc3eebd1e46c680a99ac22f20adda40841713294
Parents: a63d2be
Author: twalthr <tw...@apache.org>
Authored: Thu Nov 16 10:20:16 2017 +0100
Committer: Fabian Hueske <fh...@apache.org>
Committed: Thu Nov 16 11:32:12 2017 +0100
----------------------------------------------------------------------
.../apache/calcite/rel/rules/PushProjector.java | 868 -------------------
.../table/runtime/batch/sql/CalcITCase.scala | 2 +-
.../table/runtime/batch/sql/JoinITCase.scala | 4 +-
3 files changed, 4 insertions(+), 870 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flink/blob/fc3eebd1/flink-libraries/flink-table/src/main/java/org/apache/calcite/rel/rules/PushProjector.java
----------------------------------------------------------------------
diff --git a/flink-libraries/flink-table/src/main/java/org/apache/calcite/rel/rules/PushProjector.java b/flink-libraries/flink-table/src/main/java/org/apache/calcite/rel/rules/PushProjector.java
deleted file mode 100644
index 0955aeb..0000000
--- a/flink-libraries/flink-table/src/main/java/org/apache/calcite/rel/rules/PushProjector.java
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to you under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.calcite.rel.rules;
-
-import org.apache.calcite.linq4j.Ord;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.plan.Strong;
-import org.apache.calcite.rel.RelNode;
-import org.apache.calcite.rel.core.Join;
-import org.apache.calcite.rel.core.Project;
-import org.apache.calcite.rel.core.SemiJoin;
-import org.apache.calcite.rel.core.SetOp;
-import org.apache.calcite.rel.type.RelDataTypeField;
-import org.apache.calcite.rex.RexBuilder;
-import org.apache.calcite.rex.RexCall;
-import org.apache.calcite.rex.RexInputRef;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.rex.RexUtil;
-import org.apache.calcite.rex.RexVisitorImpl;
-import org.apache.calcite.runtime.PredicateImpl;
-import org.apache.calcite.sql.SqlOperator;
-import org.apache.calcite.tools.RelBuilder;
-import org.apache.calcite.util.BitSets;
-import org.apache.calcite.util.ImmutableBitSet;
-import org.apache.calcite.util.Pair;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.List;
-import java.util.Set;
-
-// This class is copied from Apache Calcite except that it does not
-// automatically name the field using the name of the operators
-// as the Table API rejects special characters like '-' in the field names.
-
-/**
- * PushProjector is a utility class used to perform operations used in push
- * projection rules.
- *
- * <p>Pushing is particularly interesting in the case of join, because there
- * are multiple inputs. Generally an expression can be pushed down to a
- * particular input if it depends upon no other inputs. If it can be pushed
- * down to both sides, it is pushed down to the left.
- *
- * <p>Sometimes an expression needs to be split before it can be pushed down.
- * To flag that an expression cannot be split, specify a rule that it must be
- * <dfn>preserved</dfn>. Such an expression will be pushed down intact to one
- * of the inputs, or not pushed down at all.</p>
- */
-public class PushProjector {
- //~ Instance fields --------------------------------------------------------
-
- private final Project origProj;
- private final RexNode origFilter;
- private final RelNode childRel;
- private final ExprCondition preserveExprCondition;
- private final RelBuilder relBuilder;
-
- /**
- * Original projection expressions
- */
- final List<RexNode> origProjExprs;
-
- /**
- * Fields from the RelNode that the projection is being pushed past
- */
- final List<RelDataTypeField> childFields;
-
- /**
- * Number of fields in the RelNode that the projection is being pushed past
- */
- final int nChildFields;
-
- /**
- * Bitmap containing the references in the original projection
- */
- final BitSet projRefs;
-
- /**
- * Bitmap containing the fields in the RelNode that the projection is being
- * pushed past, if the RelNode is not a join. If the RelNode is a join, then
- * the fields correspond to the left hand side of the join.
- */
- final ImmutableBitSet childBitmap;
-
- /**
- * Bitmap containing the fields in the right hand side of a join, in the
- * case where the projection is being pushed past a join. Not used
- * otherwise.
- */
- final ImmutableBitSet rightBitmap;
-
- /**
- * Bitmap containing the fields that should be strong, i.e. when preserving expressions
- * we can only preserve them if the expressions if it is null when these fields are null.
- */
- final ImmutableBitSet strongBitmap;
-
- /**
- * Number of fields in the RelNode that the projection is being pushed past,
- * if the RelNode is not a join. If the RelNode is a join, then this is the
- * number of fields in the left hand side of the join.
- *
- * <p>The identity
- * {@code nChildFields == nSysFields + nFields + nFieldsRight}
- * holds. {@code nFields} does not include {@code nSysFields}.
- * The output of a join looks like this:
- *
- * <blockquote><pre>
- * | nSysFields | nFields | nFieldsRight |
- * </pre></blockquote>
- *
- * <p>The output of a single-input rel looks like this:
- *
- * <blockquote><pre>
- * | nSysFields | nFields |
- * </pre></blockquote>
- */
- final int nFields;
-
- /**
- * Number of fields in the right hand side of a join, in the case where the
- * projection is being pushed past a join. Always 0 otherwise.
- */
- final int nFieldsRight;
-
- /**
- * Number of system fields. System fields appear at the start of a join,
- * before the first field from the left input.
- */
- private final int nSysFields;
-
- /**
- * Expressions referenced in the projection/filter that should be preserved.
- * In the case where the projection is being pushed past a join, then the
- * list only contains the expressions corresponding to the left hand side of
- * the join.
- */
- final List<RexNode> childPreserveExprs;
-
- /**
- * Expressions referenced in the projection/filter that should be preserved,
- * corresponding to expressions on the right hand side of the join, if the
- * projection is being pushed past a join. Empty list otherwise.
- */
- final List<RexNode> rightPreserveExprs;
-
- /**
- * Number of system fields being projected.
- */
- int nSystemProject;
-
- /**
- * Number of fields being projected. In the case where the projection is
- * being pushed past a join, the number of fields being projected from the
- * left hand side of the join.
- */
- int nProject;
-
- /**
- * Number of fields being projected from the right hand side of a join, in
- * the case where the projection is being pushed past a join. 0 otherwise.
- */
- int nRightProject;
-
- /**
- * Rex builder used to create new expressions.
- */
- final RexBuilder rexBuilder;
-
- //~ Constructors -----------------------------------------------------------
-
- /**
- * Creates a PushProjector object for pushing projects past a RelNode.
- *
- * @param origProj the original projection that is being pushed;
- * may be null if the projection is implied as a
- * result of a projection having been trivially
- * removed
- * @param origFilter the filter that the projection must also be
- * pushed past, if applicable
- * @param childRel the RelNode that the projection is being
- * pushed past
- * @param preserveExprCondition condition for whether an expression should
- * be preserved in the projection
- */
- public PushProjector(
- Project origProj,
- RexNode origFilter,
- RelNode childRel,
- ExprCondition preserveExprCondition,
- RelBuilder relBuilder) {
- this.origProj = origProj;
- this.origFilter = origFilter;
- this.childRel = childRel;
- this.preserveExprCondition = preserveExprCondition;
- this.relBuilder = Preconditions.checkNotNull(relBuilder);
- if (origProj == null) {
- origProjExprs = ImmutableList.of();
- } else {
- origProjExprs = origProj.getProjects();
- }
-
- childFields = childRel.getRowType().getFieldList();
- nChildFields = childFields.size();
-
- projRefs = new BitSet(nChildFields);
- if (childRel instanceof Join) {
- Join joinRel = (Join) childRel;
- List<RelDataTypeField> leftFields =
- joinRel.getLeft().getRowType().getFieldList();
- List<RelDataTypeField> rightFields =
- joinRel.getRight().getRowType().getFieldList();
- nFields = leftFields.size();
- nFieldsRight = childRel instanceof SemiJoin ? 0 : rightFields.size();
- nSysFields = joinRel.getSystemFieldList().size();
- childBitmap =
- ImmutableBitSet.range(nSysFields, nFields + nSysFields);
- rightBitmap =
- ImmutableBitSet.range(nFields + nSysFields, nChildFields);
-
- switch (joinRel.getJoinType()) {
- case INNER:
- strongBitmap = ImmutableBitSet.of();
- break;
- case RIGHT: // All the left-input's columns must be strong
- strongBitmap = ImmutableBitSet.range(nSysFields, nFields + nSysFields);
- break;
- case LEFT: // All the right-input's columns must be strong
- strongBitmap = ImmutableBitSet.range(nFields + nSysFields, nChildFields);
- break;
- case FULL:
- default:
- strongBitmap = ImmutableBitSet.range(nSysFields, nChildFields);
- }
-
- } else {
- nFields = nChildFields;
- nFieldsRight = 0;
- childBitmap = ImmutableBitSet.range(nChildFields);
- rightBitmap = null;
- nSysFields = 0;
- strongBitmap = ImmutableBitSet.of();
- }
- assert nChildFields == nSysFields + nFields + nFieldsRight;
-
- childPreserveExprs = new ArrayList<RexNode>();
- rightPreserveExprs = new ArrayList<RexNode>();
-
- rexBuilder = childRel.getCluster().getRexBuilder();
- }
-
- //~ Methods ----------------------------------------------------------------
-
- /**
- * Decomposes a projection to the input references referenced by a
- * projection and a filter, either of which is optional. If both are
- * provided, the filter is underneath the project.
- *
- * <p>Creates a projection containing all input references as well as
- * preserving any special expressions. Converts the original projection
- * and/or filter to reference the new projection. Then, finally puts on top,
- * a final projection corresponding to the original projection.
- *
- * @param defaultExpr expression to be used in the projection if no fields
- * or special columns are selected
- * @return the converted projection if it makes sense to push elements of
- * the projection; otherwise returns null
- */
- public RelNode convertProject(RexNode defaultExpr) {
- // locate all fields referenced in the projection and filter
- locateAllRefs();
-
- // if all columns are being selected (either explicitly in the
- // projection) or via a "select *", then there needs to be some
- // special expressions to preserve in the projection; otherwise,
- // there's no point in proceeding any further
- if (origProj == null) {
- if (childPreserveExprs.size() == 0) {
- return null;
- }
-
- // even though there is no projection, this is the same as
- // selecting all fields
- if (nChildFields > 0) {
- // Calling with nChildFields == 0 should be safe but hits
- // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6222207
- projRefs.set(0, nChildFields);
- }
- nProject = nChildFields;
- } else if (
- (projRefs.cardinality() == nChildFields)
- && (childPreserveExprs.size() == 0)) {
- return null;
- }
-
- // if nothing is being selected from the underlying rel, just
- // project the default expression passed in as a parameter or the
- // first column if there is no default expression
- if ((projRefs.cardinality() == 0) && (childPreserveExprs.size() == 0)) {
- if (defaultExpr != null) {
- childPreserveExprs.add(defaultExpr);
- } else if (nChildFields == 1) {
- return null;
- } else {
- projRefs.set(0);
- nProject = 1;
- }
- }
-
- // create a new projection referencing all fields referenced in
- // either the project or the filter
- RelNode newProject = createProjectRefsAndExprs(childRel, false, false);
-
- int[] adjustments = getAdjustments();
-
- // if a filter was passed in, convert it to reference the projected
- // columns, placing it on top of the project just created
- RelNode projChild;
- if (origFilter != null) {
- RexNode newFilter =
- convertRefsAndExprs(
- origFilter,
- newProject.getRowType().getFieldList(),
- adjustments);
- relBuilder.push(newProject);
- relBuilder.filter(newFilter);
- projChild = relBuilder.build();
- } else {
- projChild = newProject;
- }
-
- // put the original project on top of the filter/project, converting
- // it to reference the modified projection list; otherwise, create
- // a projection that essentially selects all fields
- return createNewProject(projChild, adjustments);
- }
-
- /**
- * Locates all references found in either the projection expressions a
- * filter, as well as references to expressions that should be preserved.
- * Based on that, determines whether pushing the projection makes sense.
- *
- * @return true if all inputs from the child that the projection is being
- * pushed past are referenced in the projection/filter and no special
- * preserve expressions are referenced; in that case, it does not make sense
- * to push the projection
- */
- public boolean locateAllRefs() {
- RexUtil.apply(
- new InputSpecialOpFinder(
- projRefs,
- childBitmap,
- rightBitmap,
- strongBitmap,
- preserveExprCondition,
- childPreserveExprs,
- rightPreserveExprs),
- origProjExprs,
- origFilter);
-
- // The system fields of each child are always used by the join, even if
- // they are not projected out of it.
- projRefs.set(
- nSysFields,
- nSysFields + nSysFields,
- true);
- projRefs.set(
- nSysFields + nFields,
- nSysFields + nFields + nSysFields,
- true);
-
- // Count how many fields are projected.
- nSystemProject = 0;
- nProject = 0;
- nRightProject = 0;
- for (int bit : BitSets.toIter(projRefs)) {
- if (bit < nSysFields) {
- nSystemProject++;
- } else if (bit < nSysFields + nFields) {
- nProject++;
- } else {
- nRightProject++;
- }
- }
-
- assert nSystemProject + nProject + nRightProject
- == projRefs.cardinality();
-
- if ((childRel instanceof Join)
- || (childRel instanceof SetOp)) {
- // if nothing is projected from the children, arbitrarily project
- // the first columns; this is necessary since Fennel doesn't
- // handle 0-column projections
- if ((nProject == 0) && (childPreserveExprs.size() == 0)) {
- projRefs.set(0);
- nProject = 1;
- }
- if (childRel instanceof Join) {
- if ((nRightProject == 0) && (rightPreserveExprs.size() == 0)) {
- projRefs.set(nFields);
- nRightProject = 1;
- }
- }
- }
-
- // no need to push projections if all children fields are being
- // referenced and there are no special preserve expressions; note
- // that we need to do this check after we've handled the 0-column
- // project cases
- if (projRefs.cardinality() == nChildFields
- && childPreserveExprs.size() == 0
- && rightPreserveExprs.size() == 0) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Creates a projection based on the inputs specified in a bitmap and the
- * expressions that need to be preserved. The expressions are appended after
- * the input references.
- *
- * @param projChild child that the projection will be created on top of
- * @param adjust if true, need to create new projection expressions;
- * otherwise, the existing ones are reused
- * @param rightSide if true, creating a projection for the right hand side
- * of a join
- * @return created projection
- */
- public Project createProjectRefsAndExprs(
- RelNode projChild,
- boolean adjust,
- boolean rightSide) {
- List<RexNode> preserveExprs;
- int nInputRefs;
- int offset;
-
- if (rightSide) {
- preserveExprs = rightPreserveExprs;
- nInputRefs = nRightProject;
- offset = nSysFields + nFields;
- } else {
- preserveExprs = childPreserveExprs;
- nInputRefs = nProject;
- offset = nSysFields;
- }
- int refIdx = offset - 1;
- List<Pair<RexNode, String>> newProjects =
- new ArrayList<Pair<RexNode, String>>();
- List<RelDataTypeField> destFields =
- projChild.getRowType().getFieldList();
-
- // add on the input references
- for (int i = 0; i < nInputRefs; i++) {
- refIdx = projRefs.nextSetBit(refIdx + 1);
- assert refIdx >= 0;
- final RelDataTypeField destField = destFields.get(refIdx - offset);
- newProjects.add(
- Pair.of(
- (RexNode) rexBuilder.makeInputRef(
- destField.getType(), refIdx - offset),
- destField.getName()));
- }
-
- // add on the expressions that need to be preserved, converting the
- // arguments to reference the projected columns (if necessary)
- int[] adjustments = {};
- if ((preserveExprs.size() > 0) && adjust) {
- adjustments = new int[childFields.size()];
- for (int idx = offset; idx < childFields.size(); idx++) {
- adjustments[idx] = -offset;
- }
- }
- for (RexNode projExpr : preserveExprs) {
- RexNode newExpr;
- if (adjust) {
- newExpr =
- projExpr.accept(
- new RelOptUtil.RexInputConverter(
- rexBuilder,
- childFields,
- destFields,
- adjustments));
- } else {
- newExpr = projExpr;
- }
- newProjects.add(
- Pair.of(
- newExpr,
- null));
- }
-
- return (Project) RelOptUtil.createProject(
- projChild,
- Pair.left(newProjects),
- Pair.right(newProjects),
- false,
- relBuilder);
- }
-
- /**
- * Determines how much each input reference needs to be adjusted as a result
- * of projection
- *
- * @return array indicating how much each input needs to be adjusted by
- */
- public int[] getAdjustments() {
- int[] adjustments = new int[nChildFields];
- int newIdx = 0;
- int rightOffset = childPreserveExprs.size();
- for (int pos : BitSets.toIter(projRefs)) {
- adjustments[pos] = -(pos - newIdx);
- if (pos >= nSysFields + nFields) {
- adjustments[pos] += rightOffset;
- }
- newIdx++;
- }
- return adjustments;
- }
-
- /**
- * Clones an expression tree and walks through it, adjusting each
- * RexInputRef index by some amount, and converting expressions that need to
- * be preserved to field references.
- *
- * @param rex the expression
- * @param destFields fields that the new expressions will be referencing
- * @param adjustments the amount each input reference index needs to be
- * adjusted by
- * @return modified expression tree
- */
- public RexNode convertRefsAndExprs(
- RexNode rex,
- List<RelDataTypeField> destFields,
- int[] adjustments) {
- return rex.accept(
- new RefAndExprConverter(
- rexBuilder,
- childFields,
- destFields,
- adjustments,
- childPreserveExprs,
- nProject,
- rightPreserveExprs,
- nProject + childPreserveExprs.size() + nRightProject));
- }
-
- /**
- * Creates a new projection based on the original projection, adjusting all
- * input refs using an adjustment array passed in. If there was no original
- * projection, create a new one that selects every field from the underlying
- * rel.
- *
- * <p>If the resulting projection would be trivial, return the child.
- *
- * @param projChild child of the new project
- * @param adjustments array indicating how much each input reference should
- * be adjusted by
- * @return the created projection
- */
- public RelNode createNewProject(RelNode projChild, int[] adjustments) {
- final List<Pair<RexNode, String>> projects = Lists.newArrayList();
-
- if (origProj != null) {
- for (Pair<RexNode, String> p : origProj.getNamedProjects()) {
- projects.add(
- Pair.of(
- convertRefsAndExprs(
- p.left,
- projChild.getRowType().getFieldList(),
- adjustments),
- p.right));
- }
- } else {
- for (Ord<RelDataTypeField> field : Ord.zip(childFields)) {
- projects.add(
- Pair.of(
- (RexNode) rexBuilder.makeInputRef(
- field.e.getType(), field.i), field.e.getName()));
- }
- }
- return RelOptUtil.createProject(
- projChild,
- Pair.left(projects),
- Pair.right(projects),
- true /* optimize to avoid trivial projections, as per javadoc */,
- relBuilder);
- }
-
- //~ Inner Classes ----------------------------------------------------------
-
- /**
- * Visitor which builds a bitmap of the inputs used by an expressions, as
- * well as locating expressions corresponding to special operators.
- */
- private class InputSpecialOpFinder extends RexVisitorImpl<Void> {
- private final BitSet rexRefs;
- private final ImmutableBitSet leftFields;
- private final ImmutableBitSet rightFields;
- private final ImmutableBitSet strongFields;
- private final ExprCondition preserveExprCondition;
- private final List<RexNode> preserveLeft;
- private final List<RexNode> preserveRight;
- private final Strong strong;
-
- public InputSpecialOpFinder(
- BitSet rexRefs,
- ImmutableBitSet leftFields,
- ImmutableBitSet rightFields,
- final ImmutableBitSet strongFields,
- ExprCondition preserveExprCondition,
- List<RexNode> preserveLeft,
- List<RexNode> preserveRight) {
- super(true);
- this.rexRefs = rexRefs;
- this.leftFields = leftFields;
- this.rightFields = rightFields;
- this.preserveExprCondition = preserveExprCondition;
- this.preserveLeft = preserveLeft;
- this.preserveRight = preserveRight;
-
- this.strongFields = strongFields;
- this.strong = Strong.of(strongFields);
- }
-
- public Void visitCall(RexCall call) {
- if (preserve(call)) {
- return null;
- }
- super.visitCall(call);
- return null;
- }
-
- private boolean isStrong(final ImmutableBitSet exprArgs, final RexNode call) {
- // If the expressions do not use any of the inputs that require output to be null,
- // no need to check. Otherwise, check that the expression is null.
- // For example, in an "left outer join", we don't require that expressions
- // pushed down into the left input to be strong. On the other hand,
- // expressions pushed into the right input must be. In that case,
- // strongFields == right input fields.
- return !strongFields.intersects(exprArgs) || strong.isNull(call);
- }
-
- private boolean preserve(RexNode call) {
- if (preserveExprCondition.test(call)) {
- // if the arguments of the expression only reference the
- // left hand side, preserve it on the left; similarly, if
- // it only references expressions on the right
- final ImmutableBitSet exprArgs = RelOptUtil.InputFinder.bits(call);
- if (exprArgs.cardinality() > 0) {
- if (leftFields.contains(exprArgs) && isStrong(exprArgs, call)) {
- addExpr(preserveLeft, call);
- return true;
- } else if (rightFields.contains(exprArgs) && isStrong(exprArgs, call)) {
- assert preserveRight != null;
- addExpr(preserveRight, call);
- return true;
- }
- }
- // if the expression arguments reference both the left and
- // right, fall through and don't attempt to preserve the
- // expression, but instead locate references and special
- // ops in the call operands
- }
- return false;
- }
-
- public Void visitInputRef(RexInputRef inputRef) {
- rexRefs.set(inputRef.getIndex());
- return null;
- }
-
- /**
- * Adds an expression to a list if the same expression isn't already in
- * the list. Expressions are identical if their digests are the same.
- *
- * @param exprList current list of expressions
- * @param newExpr new expression to be added
- */
- private void addExpr(List<RexNode> exprList, RexNode newExpr) {
- String newExprString = newExpr.toString();
- for (RexNode expr : exprList) {
- if (newExprString.compareTo(expr.toString()) == 0) {
- return;
- }
- }
- exprList.add(newExpr);
- }
- }
-
- /**
- * Walks an expression tree, replacing input refs with new values to reflect
- * projection and converting special expressions to field references.
- */
- private class RefAndExprConverter extends RelOptUtil.RexInputConverter {
- private final List<RexNode> preserveLeft;
- private final int firstLeftRef;
- private final List<RexNode> preserveRight;
- private final int firstRightRef;
-
- public RefAndExprConverter(
- RexBuilder rexBuilder,
- List<RelDataTypeField> srcFields,
- List<RelDataTypeField> destFields,
- int[] adjustments,
- List<RexNode> preserveLeft,
- int firstLeftRef,
- List<RexNode> preserveRight,
- int firstRightRef) {
- super(rexBuilder, srcFields, destFields, adjustments);
- this.preserveLeft = preserveLeft;
- this.firstLeftRef = firstLeftRef;
- this.preserveRight = preserveRight;
- this.firstRightRef = firstRightRef;
- }
-
- public RexNode visitCall(RexCall call) {
- // if the expression corresponds to one that needs to be preserved,
- // convert it to a field reference; otherwise, convert the entire
- // expression
- int match =
- findExprInLists(
- call,
- preserveLeft,
- firstLeftRef,
- preserveRight,
- firstRightRef);
- if (match >= 0) {
- return rexBuilder.makeInputRef(
- destFields.get(match).getType(),
- match);
- }
- return super.visitCall(call);
- }
-
- /**
- * Looks for a matching RexNode from among two lists of RexNodes and
- * returns the offset into the list corresponding to the match, adjusted
- * by an amount, depending on whether the match was from the first or
- * second list.
- *
- * @param rex RexNode that is being matched against
- * @param rexList1 first list of RexNodes
- * @param adjust1 adjustment if match occurred in first list
- * @param rexList2 second list of RexNodes
- * @param adjust2 adjustment if match occurred in the second list
- * @return index in the list corresponding to the matching RexNode; -1
- * if no match
- */
- private int findExprInLists(
- RexNode rex,
- List<RexNode> rexList1,
- int adjust1,
- List<RexNode> rexList2,
- int adjust2) {
- int match = findExprInList(rex, rexList1);
- if (match >= 0) {
- return match + adjust1;
- }
-
- if (rexList2 != null) {
- match = findExprInList(rex, rexList2);
- if (match >= 0) {
- return match + adjust2;
- }
- }
-
- return -1;
- }
-
- private int findExprInList(RexNode rex, List<RexNode> rexList) {
- int match = 0;
- for (RexNode rexElement : rexList) {
- if (rexElement.toString().compareTo(rex.toString()) == 0) {
- return match;
- }
- match++;
- }
- return -1;
- }
- }
-
- /**
- * A functor that replies true or false for a given expression.
- *
- * @see org.apache.calcite.rel.rules.PushProjector.OperatorExprCondition
- */
- public interface ExprCondition extends Predicate<RexNode> {
- /**
- * Evaluates a condition for a given expression.
- *
- * @param expr Expression
- * @return result of evaluating the condition
- */
- boolean test(RexNode expr);
-
- /**
- * Constant condition that replies {@code false} for all expressions.
- */
- ExprCondition FALSE =
- new ExprConditionImpl() {
- @Override public boolean test(RexNode expr) {
- return false;
- }
- };
-
- /**
- * Constant condition that replies {@code true} for all expressions.
- */
- ExprCondition TRUE =
- new ExprConditionImpl() {
- @Override public boolean test(RexNode expr) {
- return true;
- }
- };
- }
-
- /** Implementation of {@link ExprCondition}. */
- abstract static class ExprConditionImpl extends PredicateImpl<RexNode>
- implements ExprCondition {
- }
-
- /**
- * An expression condition that evaluates to true if the expression is
- * a call to one of a set of operators.
- */
- class OperatorExprCondition extends ExprConditionImpl {
- private final Set<SqlOperator> operatorSet;
-
- /**
- * Creates an OperatorExprCondition.
- *
- * @param operatorSet Set of operators
- */
- public OperatorExprCondition(Iterable<? extends SqlOperator> operatorSet) {
- this.operatorSet = ImmutableSet.copyOf(operatorSet);
- }
-
- public boolean test(RexNode expr) {
- return expr instanceof RexCall
- && operatorSet.contains(((RexCall) expr).getOperator());
- }
- }
-}
-
-// End PushProjector.java
http://git-wip-us.apache.org/repos/asf/flink/blob/fc3eebd1/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/CalcITCase.scala
----------------------------------------------------------------------
diff --git a/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/CalcITCase.scala b/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/CalcITCase.scala
index 7ca3e9c..71df4e6 100644
--- a/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/CalcITCase.scala
+++ b/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/CalcITCase.scala
@@ -139,7 +139,7 @@ class CalcITCase(
val env = ExecutionEnvironment.getExecutionEnvironment
val tEnv = TableEnvironment.getTableEnvironment(env, config)
- val sqlQuery = "SELECT _1 as a, _2 as b FROM MyTable"
+ val sqlQuery = "SELECT `1-_./Ü`, b FROM (SELECT _1 as `1-_./Ü`, _2 as b FROM MyTable)"
val ds = CollectionDataSets.get3TupleDataSet(env).toTable(tEnv)
tEnv.registerTable("MyTable", ds)
http://git-wip-us.apache.org/repos/asf/flink/blob/fc3eebd1/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/JoinITCase.scala
----------------------------------------------------------------------
diff --git a/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/JoinITCase.scala b/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/JoinITCase.scala
index 6a17cb4..14c9859 100644
--- a/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/JoinITCase.scala
+++ b/flink-libraries/flink-table/src/test/scala/org/apache/flink/table/runtime/batch/sql/JoinITCase.scala
@@ -123,7 +123,9 @@ class JoinITCase(
val env = ExecutionEnvironment.getExecutionEnvironment
val tEnv = TableEnvironment.getTableEnvironment(env, config)
- val sqlQuery = "SELECT Table5.c, Table3.c FROM Table3, Table5 WHERE a = d AND a < 4"
+ val sqlQuery =
+ "SELECT Table5.c, T.`1-_./Ü` FROM (SELECT a, b, c AS `1-_./Ü` FROM Table3) AS T, Table5 " +
+ "WHERE a = d AND a < 4"
val ds1 = CollectionDataSets.get3TupleDataSet(env).toTable(tEnv).as('a, 'b, 'c)
val ds2 = CollectionDataSets.get5TupleDataSet(env).toTable(tEnv).as('d, 'e, 'f, 'g, 'c)