You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flink.apache.org by go...@apache.org on 2022/08/08 03:56:19 UTC

[flink] 02/04: [FLINK-28678][table-planner] Support SQL hint for Filter, SetOp, and etc. Mainly cherry-pick from [calcite-5107]

This is an automated email from the ASF dual-hosted git repository.

godfrey pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/flink.git

commit 4e46602342f3e3e45716f3adf8e29f7531cb9ca5
Author: xuyang <xy...@163.com>
AuthorDate: Tue Jul 26 14:25:40 2022 +0800

    [FLINK-28678][table-planner] Support SQL hint for Filter, SetOp, and etc. Mainly cherry-pick from [calcite-5107]
    
    Since currently the feat [CALCITE-5107] is not introduced to the calcite version flink used, so just temporarily cherry-pick this feat to copied files directly. When the calcite upgrades to 1.31, these classes should be deleted.
    
    This closes #20359
---
 .../org/apache/calcite/rel/core/Correlate.java     | 46 ++++++++++++-
 .../java/org/apache/calcite/rel/core/Filter.java   | 38 ++++++++++-
 .../org/apache/calcite/rel/core/Intersect.java     | 17 ++++-
 .../java/org/apache/calcite/rel/core/Minus.java    | 17 ++++-
 .../java/org/apache/calcite/rel/core/SetOp.java    | 27 +++++++-
 .../java/org/apache/calcite/rel/core/Sort.java     | 39 ++++++++++-
 .../java/org/apache/calcite/rel/core/Union.java    | 16 ++++-
 .../java/org/apache/calcite/rel/core/Values.java   | 43 +++++++++++-
 .../java/org/apache/calcite/rel/core/Window.java   | 50 ++++++++++++--
 .../apache/calcite/rel/hint/HintPredicates.java    | 49 +++++++++++++-
 .../calcite/rel/hint/NodeTypeHintPredicate.java    | 29 +++++++-
 .../calcite/rel/logical/LogicalCorrelate.java      | 78 +++++++++++++++++++++-
 .../apache/calcite/rel/logical/LogicalFilter.java  | 36 +++++++++-
 .../calcite/rel/logical/LogicalIntersect.java      | 25 ++++++-
 .../apache/calcite/rel/logical/LogicalMinus.java   | 33 ++++++++-
 .../apache/calcite/rel/logical/LogicalSort.java    | 33 ++++++++-
 .../apache/calcite/rel/logical/LogicalUnion.java   | 33 ++++++++-
 .../apache/calcite/rel/logical/LogicalValues.java  | 39 ++++++++++-
 .../apache/calcite/rel/logical/LogicalWindow.java  | 44 ++++++++++--
 19 files changed, 646 insertions(+), 46 deletions(-)

diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Correlate.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Correlate.java
index 2d5e6fe554f..8df4da8b823 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Correlate.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Correlate.java
@@ -27,12 +27,15 @@ import org.apache.calcite.rel.BiRel;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.hint.Hintable;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Litmus;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 import java.util.Set;
@@ -40,6 +43,9 @@ import java.util.Set;
 /**
  * A relational operator that performs nested-loop joins.
  *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ *
  * <p>It behaves like a kind of {@link org.apache.calcite.rel.core.Join}, but works by setting
  * variables in its environment and restarting its right-hand input.
  *
@@ -63,12 +69,13 @@ import java.util.Set;
  *
  * @see CorrelationId
  */
-public abstract class Correlate extends BiRel {
+public abstract class Correlate extends BiRel implements Hintable {
     // ~ Instance fields --------------------------------------------------------
 
     protected final CorrelationId correlationId;
     protected final ImmutableBitSet requiredColumns;
     protected final JoinRelType joinType;
+    protected final com.google.common.collect.ImmutableList<RelHint> hints;
 
     // ~ Constructors -----------------------------------------------------------
 
@@ -76,6 +83,7 @@ public abstract class Correlate extends BiRel {
      * Creates a Correlate.
      *
      * @param cluster Cluster this relational expression belongs to
+     * @param hints Hints for this node
      * @param left Left input relational expression
      * @param right Right input relational expression
      * @param correlationId Variable name for the row of left input
@@ -85,6 +93,7 @@ public abstract class Correlate extends BiRel {
     protected Correlate(
             RelOptCluster cluster,
             RelTraitSet traitSet,
+            List<RelHint> hints,
             RelNode left,
             RelNode right,
             CorrelationId correlationId,
@@ -95,6 +104,36 @@ public abstract class Correlate extends BiRel {
         this.joinType = Objects.requireNonNull(joinType);
         this.correlationId = Objects.requireNonNull(correlationId);
         this.requiredColumns = Objects.requireNonNull(requiredColumns);
+        this.hints = com.google.common.collect.ImmutableList.copyOf(hints);
+    }
+
+    /**
+     * Creates a Correlate.
+     *
+     * @param cluster Cluster this relational expression belongs to
+     * @param left Left input relational expression
+     * @param right Right input relational expression
+     * @param correlationId Variable name for the row of left input
+     * @param requiredColumns Set of columns that are used by correlation
+     * @param joinType Join type
+     */
+    protected Correlate(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            RelNode left,
+            RelNode right,
+            CorrelationId correlationId,
+            ImmutableBitSet requiredColumns,
+            JoinRelType joinType) {
+        this(
+                cluster,
+                traitSet,
+                Collections.emptyList(),
+                left,
+                right,
+                correlationId,
+                requiredColumns,
+                joinType);
     }
 
     /**
@@ -231,4 +270,9 @@ public abstract class Correlate extends BiRel {
                         0)
                 .plus(rescanCost);
     }
+
+    @Override
+    public com.google.common.collect.ImmutableList<RelHint> getHints() {
+        return hints;
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Filter.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Filter.java
index 2fc9f0c1240..34a28def16b 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Filter.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Filter.java
@@ -27,6 +27,8 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.SingleRel;
+import org.apache.calcite.rel.hint.Hintable;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMdUtil;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rex.RexChecker;
@@ -44,15 +46,20 @@ import java.util.Objects;
  * Relational expression that iterates over its input and returns elements for which <code>condition
  * </code> evaluates to <code>true</code>.
  *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ *
  * <p>If the condition allows nulls, then a null value is treated the same as false.
  *
  * @see org.apache.calcite.rel.logical.LogicalFilter
  */
-public abstract class Filter extends SingleRel {
+public abstract class Filter extends SingleRel implements Hintable {
     // ~ Instance fields --------------------------------------------------------
 
     protected final RexNode condition;
 
+    protected final com.google.common.collect.ImmutableList<RelHint> hints;
+
     // ~ Constructors -----------------------------------------------------------
 
     /**
@@ -60,16 +67,35 @@ public abstract class Filter extends SingleRel {
      *
      * @param cluster Cluster that this relational expression belongs to
      * @param traits the traits of this rel
+     * @param hints Hints for this node
      * @param child input relational expression
      * @param condition boolean expression which determines whether a row is allowed to pass
      */
-    protected Filter(RelOptCluster cluster, RelTraitSet traits, RelNode child, RexNode condition) {
+    protected Filter(
+            RelOptCluster cluster,
+            RelTraitSet traits,
+            List<RelHint> hints,
+            RelNode child,
+            RexNode condition) {
         super(cluster, traits, child);
         assert condition != null;
         assert RexUtil.isFlat(condition) : condition;
         this.condition = condition;
         // Too expensive for everyday use:
         assert !CalciteSystemProperty.DEBUG.value() || isValid(Litmus.THROW, null);
+        this.hints = com.google.common.collect.ImmutableList.copyOf(hints);
+    }
+
+    /**
+     * Creates a filter.
+     *
+     * @param cluster Cluster that this relational expression belongs to
+     * @param traits the traits of this rel
+     * @param child input relational expression
+     * @param condition boolean expression which determines whether a row is allowed to pass
+     */
+    protected Filter(RelOptCluster cluster, RelTraitSet traits, RelNode child, RexNode condition) {
+        this(cluster, traits, com.google.common.collect.ImmutableList.of(), child, condition);
     }
 
     /** Creates a Filter by parsing serialized output. */
@@ -158,12 +184,18 @@ public abstract class Filter extends SingleRel {
         }
         Filter o = (Filter) obj;
         return traitSet.equals(o.traitSet)
+                && hints.equals(o.hints)
                 && input.deepEquals(o.input)
                 && condition.equals(o.condition)
                 && getRowType().equalsSansFieldNames(o.getRowType());
     }
 
     protected int deepHashCode0() {
-        return Objects.hash(traitSet, input.deepHashCode(), condition);
+        return Objects.hash(traitSet, hints, input.deepHashCode(), condition);
+    }
+
+    @Override
+    public com.google.common.collect.ImmutableList<RelHint> getHints() {
+        return hints;
     }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Intersect.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Intersect.java
index c923692275b..ad20e66fe37 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Intersect.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Intersect.java
@@ -22,21 +22,36 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.sql.SqlKind;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
  * Relational expression that returns the intersection of the rows of its inputs.
  *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ *
  * <p>If "all" is true, performs then multiset intersection; otherwise, performs set set
  * intersection (implying no duplicates in the results).
  */
 public abstract class Intersect extends SetOp {
+    /** Creates an Intersect. */
+    public Intersect(
+            RelOptCluster cluster,
+            RelTraitSet traits,
+            List<RelHint> hints,
+            List<RelNode> inputs,
+            boolean all) {
+        super(cluster, traits, hints, inputs, SqlKind.INTERSECT, all);
+    }
+
     /** Creates an Intersect. */
     public Intersect(RelOptCluster cluster, RelTraitSet traits, List<RelNode> inputs, boolean all) {
-        super(cluster, traits, inputs, SqlKind.INTERSECT, all);
+        this(cluster, traits, Collections.emptyList(), inputs, all);
     }
 
     /** Creates an Intersect by parsing serialized output. */
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Minus.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Minus.java
index 035581e4150..ae3cb8c6d23 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Minus.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Minus.java
@@ -22,24 +22,39 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMdUtil;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.sql.SqlKind;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
  * Relational expression that returns the rows of its first input minus any matching rows from its
  * other inputs.
  *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ *
  * <p>Corresponds to the SQL {@code EXCEPT} operator.
  *
  * <p>If "all" is true, then multiset subtraction is performed; otherwise, set subtraction is
  * performed (implying no duplicates in the results).
  */
 public abstract class Minus extends SetOp {
+
+    public Minus(
+            RelOptCluster cluster,
+            RelTraitSet traits,
+            List<RelHint> hints,
+            List<RelNode> inputs,
+            boolean all) {
+        super(cluster, traits, hints, inputs, SqlKind.EXCEPT, all);
+    }
+
     public Minus(RelOptCluster cluster, RelTraitSet traits, List<RelNode> inputs, boolean all) {
-        super(cluster, traits, inputs, SqlKind.EXCEPT, all);
+        this(cluster, traits, Collections.emptyList(), inputs, all);
     }
 
     /** Creates a Minus by parsing serialized output. */
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/SetOp.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/SetOp.java
index 2e323031102..710fcaed874 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/SetOp.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/SetOp.java
@@ -26,23 +26,30 @@ import org.apache.calcite.rel.AbstractRelNode;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.hint.Hintable;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.util.Util;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
  * <code>SetOp</code> is an abstract base for relational set operators such as UNION, MINUS (aka
  * EXCEPT), and INTERSECT.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
  */
-public abstract class SetOp extends AbstractRelNode {
+public abstract class SetOp extends AbstractRelNode implements Hintable {
     // ~ Instance fields --------------------------------------------------------
 
     protected com.google.common.collect.ImmutableList<RelNode> inputs;
     public final SqlKind kind;
     public final boolean all;
+    protected final com.google.common.collect.ImmutableList<RelHint> hints;
 
     // ~ Constructors -----------------------------------------------------------
 
@@ -50,6 +57,7 @@ public abstract class SetOp extends AbstractRelNode {
     protected SetOp(
             RelOptCluster cluster,
             RelTraitSet traits,
+            List<RelHint> hints,
             List<RelNode> inputs,
             SqlKind kind,
             boolean all) {
@@ -59,6 +67,17 @@ public abstract class SetOp extends AbstractRelNode {
         this.kind = kind;
         this.inputs = com.google.common.collect.ImmutableList.copyOf(inputs);
         this.all = all;
+        this.hints = com.google.common.collect.ImmutableList.copyOf(hints);
+    }
+
+    /** Creates a SetOp. */
+    protected SetOp(
+            RelOptCluster cluster,
+            RelTraitSet traits,
+            List<RelNode> inputs,
+            SqlKind kind,
+            boolean all) {
+        this(cluster, traits, Collections.emptyList(), inputs, kind, all);
     }
 
     /** Creates a SetOp by parsing serialized output. */
@@ -66,6 +85,7 @@ public abstract class SetOp extends AbstractRelNode {
         this(
                 input.getCluster(),
                 input.getTraitSet(),
+                Collections.emptyList(),
                 input.getInputs(),
                 SqlKind.UNION,
                 input.getBoolean("all", false));
@@ -130,4 +150,9 @@ public abstract class SetOp extends AbstractRelNode {
         }
         return true;
     }
+
+    @Override
+    public com.google.common.collect.ImmutableList<RelHint> getHints() {
+        return hints;
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Sort.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Sort.java
index 8ebab6e03be..93c38fbdd44 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Sort.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Sort.java
@@ -30,24 +30,31 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.SingleRel;
+import org.apache.calcite.rel.hint.Hintable;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexShuttle;
 import org.apache.calcite.util.Util;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
 /**
  * Relational expression that imposes a particular sort order on its input without otherwise
  * changing its content.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
  */
-public abstract class Sort extends SingleRel {
+public abstract class Sort extends SingleRel implements Hintable {
     // ~ Instance fields --------------------------------------------------------
 
     public final RelCollation collation;
     public final RexNode offset;
     public final RexNode fetch;
+    protected final com.google.common.collect.ImmutableList<RelHint> hints;
 
     // ~ Constructors -----------------------------------------------------------
 
@@ -60,7 +67,7 @@ public abstract class Sort extends SingleRel {
      * @param collation array of sort specifications
      */
     public Sort(RelOptCluster cluster, RelTraitSet traits, RelNode child, RelCollation collation) {
-        this(cluster, traits, child, collation, null, null);
+        this(cluster, traits, Collections.emptyList(), child, collation, null, null);
     }
 
     /**
@@ -80,10 +87,33 @@ public abstract class Sort extends SingleRel {
             RelCollation collation,
             RexNode offset,
             RexNode fetch) {
+        this(cluster, traits, Collections.emptyList(), child, collation, offset, fetch);
+    }
+
+    /**
+     * Creates a Sort.
+     *
+     * @param cluster Cluster this relational expression belongs to
+     * @param traits Traits
+     * @param hints Hints for this node
+     * @param child input relational expression
+     * @param collation array of sort specifications
+     * @param offset Expression for number of rows to discard before returning first row
+     * @param fetch Expression for number of rows to fetch
+     */
+    public Sort(
+            RelOptCluster cluster,
+            RelTraitSet traits,
+            List<RelHint> hints,
+            RelNode child,
+            RelCollation collation,
+            RexNode offset,
+            RexNode fetch) {
         super(cluster, traits, child);
         this.collation = collation;
         this.offset = offset;
         this.fetch = fetch;
+        this.hints = com.google.common.collect.ImmutableList.copyOf(hints);
 
         assert traits.containsIfApplicable(collation)
                 : "traits=" + traits + ", collation=" + collation;
@@ -194,4 +224,9 @@ public abstract class Sort extends SingleRel {
         pw.itemIf("fetch", fetch, fetch != null);
         return pw;
     }
+
+    @Override
+    public com.google.common.collect.ImmutableList<RelHint> getHints() {
+        return hints;
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Union.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Union.java
index f79538b45e7..f4099ae1f9a 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Union.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Union.java
@@ -22,23 +22,37 @@ import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMdUtil;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.sql.SqlKind;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
  * Relational expression that returns the union of the rows of its inputs, optionally eliminating
  * duplicates.
  *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ *
  * <p>Corresponds to SQL {@code UNION} and {@code UNION ALL}.
  */
 public abstract class Union extends SetOp {
     // ~ Constructors -----------------------------------------------------------
 
+    protected Union(
+            RelOptCluster cluster,
+            RelTraitSet traits,
+            List<RelHint> hints,
+            List<RelNode> inputs,
+            boolean all) {
+        super(cluster, traits, hints, inputs, SqlKind.UNION, all);
+    }
+
     protected Union(RelOptCluster cluster, RelTraitSet traits, List<RelNode> inputs, boolean all) {
-        super(cluster, traits, inputs, SqlKind.UNION, all);
+        super(cluster, traits, Collections.emptyList(), inputs, SqlKind.UNION, all);
     }
 
     /** Creates a Union by parsing serialized output. */
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Values.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Values.java
index 7aa0d0cafb0..e4a6eba4785 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Values.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Values.java
@@ -26,6 +26,8 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.AbstractRelNode;
 import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelWriter;
+import org.apache.calcite.rel.hint.Hintable;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeField;
@@ -35,15 +37,23 @@ import org.apache.calcite.sql.SqlExplainLevel;
 import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.calcite.util.Pair;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
-/** Relational expression whose value is a sequence of zero or more literal row values. */
-public abstract class Values extends AbstractRelNode {
+/**
+ * Relational expression whose value is a sequence of zero or more literal row values.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ */
+public abstract class Values extends AbstractRelNode implements Hintable {
 
     public static final Predicate<? super Values> IS_EMPTY_J = Values::isEmpty;
 
+    protected final com.google.common.collect.ImmutableList<RelHint> hints;
+
     @SuppressWarnings("Guava")
     @Deprecated // to be removed before 2.0
     public static final com.google.common.base.Predicate<? super Values> IS_EMPTY = Values::isEmpty;
@@ -68,12 +78,14 @@ public abstract class Values extends AbstractRelNode {
      * not modify them after this call, otherwise bad things will happen.
      *
      * @param cluster Cluster that this relational expression belongs to
+     * @param hints Hints for this node
      * @param rowType Row type for tuples produced by this rel
      * @param tuples 2-dimensional array of tuple values to be produced; outer list contains tuples;
      *     each inner list is one tuple; all tuples must be of same length, conforming to rowType
      */
     protected Values(
             RelOptCluster cluster,
+            List<RelHint> hints,
             RelDataType rowType,
             com.google.common.collect.ImmutableList<
                             com.google.common.collect.ImmutableList<RexLiteral>>
@@ -82,9 +94,31 @@ public abstract class Values extends AbstractRelNode {
         super(cluster, traits);
         this.rowType = rowType;
         this.tuples = tuples;
+        this.hints = com.google.common.collect.ImmutableList.copyOf(hints);
         assert assertRowType();
     }
 
+    /**
+     * Creates a new Values.
+     *
+     * <p>Note that tuples passed in become owned by this rel (without a deep copy), so caller must
+     * not modify them after this call, otherwise bad things will happen.
+     *
+     * @param cluster Cluster that this relational expression belongs to
+     * @param rowType Row type for tuples produced by this rel
+     * @param tuples 2-dimensional array of tuple values to be produced; outer list contains tuples;
+     *     each inner list is one tuple; all tuples must be of same length, conforming to rowType
+     */
+    protected Values(
+            RelOptCluster cluster,
+            RelDataType rowType,
+            com.google.common.collect.ImmutableList<
+                            com.google.common.collect.ImmutableList<RexLiteral>>
+                    tuples,
+            RelTraitSet traits) {
+        this(cluster, Collections.emptyList(), rowType, tuples, traits);
+    }
+
     /** Creates a Values by parsing serialized output. */
     public Values(RelInput input) {
         this(
@@ -207,4 +241,9 @@ public abstract class Values extends AbstractRelNode {
         }
         return relWriter;
     }
+
+    @Override
+    public com.google.common.collect.ImmutableList<RelHint> getHints() {
+        return hints;
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Window.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Window.java
index 26f4de75f9e..7784dd8364c 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Window.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/core/Window.java
@@ -29,6 +29,8 @@ import org.apache.calcite.rel.RelFieldCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.SingleRel;
+import org.apache.calcite.rel.hint.Hintable;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexCall;
@@ -46,30 +48,36 @@ import org.apache.calcite.util.Litmus;
 import org.apache.calcite.util.Util;
 
 import java.util.AbstractList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
 /**
  * A relational expression representing a set of window aggregates.
  *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ *
  * <p>A Window can handle several window aggregate functions, over several partitions, with pre- and
  * post-expressions, and an optional post-filter. Each of the partitions is defined by a partition
  * key (zero or more columns) and a range (logical or physical). The partitions expect the data to
  * be sorted correctly on input to the relational expression.
  *
- * <p>Each {@link Group} has a set of {@link org.apache.calcite.rex.RexOver} objects.
+ * <p>Each {@link Window.Group} has a set of {@link org.apache.calcite.rex.RexOver} objects.
  *
  * <p>Created by {@link org.apache.calcite.rel.rules.ProjectToWindowRule}.
  */
-public abstract class Window extends SingleRel {
+public abstract class Window extends SingleRel implements Hintable {
     public final com.google.common.collect.ImmutableList<Group> groups;
     public final com.google.common.collect.ImmutableList<RexLiteral> constants;
+    protected final com.google.common.collect.ImmutableList<RelHint> hints;
 
     /**
      * Creates a window relational expression.
      *
      * @param cluster Cluster
      * @param traitSet Trait set
+     * @param hints Hints for this node
      * @param input Input relational expression
      * @param constants List of constants that are additional inputs
      * @param rowType Output row type
@@ -78,6 +86,7 @@ public abstract class Window extends SingleRel {
     public Window(
             RelOptCluster cluster,
             RelTraitSet traitSet,
+            List<RelHint> hints,
             RelNode input,
             List<RexLiteral> constants,
             RelDataType rowType,
@@ -87,6 +96,27 @@ public abstract class Window extends SingleRel {
         assert rowType != null;
         this.rowType = rowType;
         this.groups = com.google.common.collect.ImmutableList.copyOf(groups);
+        this.hints = com.google.common.collect.ImmutableList.copyOf(hints);
+    }
+
+    /**
+     * Creates a window relational expression.
+     *
+     * @param cluster Cluster
+     * @param traitSet Trait set
+     * @param input Input relational expression
+     * @param constants List of constants that are additional inputs
+     * @param rowType Output row type
+     * @param groups Windows
+     */
+    public Window(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            RelNode input,
+            List<RexLiteral> constants,
+            RelDataType rowType,
+            List<Group> groups) {
+        this(cluster, traitSet, Collections.emptyList(), input, constants, rowType, groups);
     }
 
     @Override
@@ -223,8 +253,8 @@ public abstract class Window extends SingleRel {
         private final String digest;
 
         /**
-         * List of {@link RexWinAggCall} objects, each of which is a call to a {@link
-         * SqlAggFunction}.
+         * List of {@link Window.RexWinAggCall} objects, each of which is a call to a {@link
+         * org.apache.calcite.sql.SqlAggFunction}.
          */
         public final com.google.common.collect.ImmutableList<RexWinAggCall> aggCalls;
 
@@ -355,10 +385,11 @@ public abstract class Window extends SingleRel {
     /**
      * A call to a windowed aggregate function.
      *
-     * <p>Belongs to a {@link Group}.
+     * <p>Belongs to a {@link Window.Group}.
      *
-     * <p>It's a bastard son of a {@link RexCall}; similar enough that it gets visited by a {@link
-     * org.apache.calcite.rex.RexVisitor}, but it also has some extra data members.
+     * <p>It's a bastard son of a {@link org.apache.calcite.rex.RexCall}; similar enough that it
+     * gets visited by a {@link org.apache.calcite.rex.RexVisitor}, but it also has some extra data
+     * members.
      */
     public static class RexWinAggCall extends RexCall {
         /** Ordinal of this aggregate within its partition. */
@@ -432,4 +463,9 @@ public abstract class Window extends SingleRel {
             return super.clone(type, operands);
         }
     }
+
+    @Override
+    public com.google.common.collect.ImmutableList<RelHint> getHints() {
+        return hints;
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/hint/HintPredicates.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/hint/HintPredicates.java
index 59b53e3e089..a38ad2e141e 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/hint/HintPredicates.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/hint/HintPredicates.java
@@ -18,7 +18,12 @@
 
 package org.apache.calcite.rel.hint;
 
-/** A collection of hint predicates. */
+/**
+ * A collection of hint predicates.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade *
+ * the latest calcite.
+ */
 public abstract class HintPredicates {
     /**
      * A hint predicate that indicates a hint can only be used to the whole query(no specific
@@ -41,6 +46,13 @@ public abstract class HintPredicates {
     public static final HintPredicate TABLE_SCAN =
             new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.TABLE_SCAN);
 
+    /**
+     * A hint predicate that indicates a hint can only be used to {@link
+     * org.apache.calcite.rel.core.Filter} nodes.
+     */
+    public static final HintPredicate FILTER =
+            new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.FILTER);
+
     /**
      * A hint predicate that indicates a hint can only be used to {@link
      * org.apache.calcite.rel.core.Project} nodes.
@@ -48,6 +60,27 @@ public abstract class HintPredicates {
     public static final HintPredicate PROJECT =
             new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.PROJECT);
 
+    /**
+     * A hint predicate that indicates a hint can only be used to {@link
+     * org.apache.calcite.rel.core.Correlate} nodes.
+     */
+    public static final HintPredicate CORRELATE =
+            new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.CORRELATE);
+
+    /**
+     * A hint predicate that indicates a hint can only be used to {@link
+     * org.apache.calcite.rel.core.SetOp} nodes.
+     */
+    public static final HintPredicate SETOP =
+            new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.SETOP);
+
+    /**
+     * A hint predicate that indicates a hint can only be used to {@link
+     * org.apache.calcite.rel.core.Sort} nodes.
+     */
+    public static final HintPredicate SORT =
+            new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.SORT);
+
     /**
      * A hint predicate that indicates a hint can only be used to {@link
      * org.apache.calcite.rel.core.Aggregate} nodes.
@@ -62,6 +95,20 @@ public abstract class HintPredicates {
     public static final HintPredicate CALC =
             new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.CALC);
 
+    /**
+     * A hint predicate that indicates a hint can only be used to {@link
+     * org.apache.calcite.rel.core.Values} nodes.
+     */
+    public static final HintPredicate VALUES =
+            new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.VALUES);
+
+    /**
+     * A hint predicate that indicates a hint can only be used to {@link
+     * org.apache.calcite.rel.core.Window} nodes.
+     */
+    public static final HintPredicate WINDOW =
+            new NodeTypeHintPredicate(NodeTypeHintPredicate.NodeType.WINDOW);
+
     /**
      * Returns a composed hint predicate that represents a short-circuiting logical AND of an array
      * of hint predicates {@code hintPredicates}. When evaluating the composed predicate, if a
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/hint/NodeTypeHintPredicate.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/hint/NodeTypeHintPredicate.java
index 9a5bbff528b..4ed6d117c09 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/hint/NodeTypeHintPredicate.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/hint/NodeTypeHintPredicate.java
@@ -21,12 +21,21 @@ package org.apache.calcite.rel.hint;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Aggregate;
 import org.apache.calcite.rel.core.Calc;
+import org.apache.calcite.rel.core.Correlate;
+import org.apache.calcite.rel.core.Filter;
 import org.apache.calcite.rel.core.Join;
 import org.apache.calcite.rel.core.Project;
+import org.apache.calcite.rel.core.SetOp;
+import org.apache.calcite.rel.core.Sort;
 import org.apache.calcite.rel.core.TableScan;
+import org.apache.calcite.rel.core.Values;
+import org.apache.calcite.rel.core.Window;
 
 /**
  * A hint predicate that specifies which kind of relational expression the hint can be applied to.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
  */
 public class NodeTypeHintPredicate implements HintPredicate {
 
@@ -44,14 +53,32 @@ public class NodeTypeHintPredicate implements HintPredicate {
         /** The hint would be propagated to the TableScan nodes. */
         TABLE_SCAN(TableScan.class),
 
+        /** The hint would be propagated to the Filter nodes. */
+        FILTER(Filter.class),
+
         /** The hint would be propagated to the Project nodes. */
         PROJECT(Project.class),
 
+        /** The hint would be propagated to the Correlate nodes. */
+        CORRELATE(Correlate.class),
+
         /** The hint would be propagated to the Aggregate nodes. */
         AGGREGATE(Aggregate.class),
 
         /** The hint would be propagated to the Calc nodes. */
-        CALC(Calc.class);
+        CALC(Calc.class),
+
+        /** The hint would be propagated to the SetOp(Union, Intersect, Minus) nodes. */
+        SETOP(SetOp.class),
+
+        /** The hint would be propagated to the Sort nodes. */
+        SORT(Sort.class),
+
+        /** The hint would be propagated to the Values nodes. */
+        VALUES(Values.class),
+
+        /** The hint would be propagated to the Window nodes. */
+        WINDOW(Window.class);
 
         /** Relational expression clazz that the hint can apply to. */
         private Class<?> relClazz;
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java
index 01f00b945f9..2c0703c5487 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalCorrelate.java
@@ -28,19 +28,26 @@ import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.core.Correlate;
 import org.apache.calcite.rel.core.CorrelationId;
 import org.apache.calcite.rel.core.JoinRelType;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.util.ImmutableBitSet;
 import org.apache.calcite.util.Litmus;
 
+import java.util.Collections;
+import java.util.List;
+
 /**
  * A relational operator that performs nested-loop joins.
  *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ *
  * <p>It behaves like a kind of {@link org.apache.calcite.rel.core.Join}, but works by setting
  * variables in its environment and restarting its right-hand input.
  *
  * <p>A LogicalCorrelate is used to represent a correlated query. One implementation strategy is to
  * de-correlate the expression.
  *
- * @see CorrelationId
+ * @see org.apache.calcite.rel.core.CorrelationId
  */
 public final class LogicalCorrelate extends Correlate {
     // ~ Instance fields --------------------------------------------------------
@@ -51,6 +58,7 @@ public final class LogicalCorrelate extends Correlate {
      * Creates a LogicalCorrelate.
      *
      * @param cluster cluster this relational expression belongs to
+     * @param hints hints for this node
      * @param left left input relational expression
      * @param right right input relational expression
      * @param correlationId variable name for the row of left input
@@ -60,15 +68,45 @@ public final class LogicalCorrelate extends Correlate {
     public LogicalCorrelate(
             RelOptCluster cluster,
             RelTraitSet traitSet,
+            List<RelHint> hints,
             RelNode left,
             RelNode right,
             CorrelationId correlationId,
             ImmutableBitSet requiredColumns,
             JoinRelType joinType) {
-        super(cluster, traitSet, left, right, correlationId, requiredColumns, joinType);
+        super(cluster, traitSet, hints, left, right, correlationId, requiredColumns, joinType);
         assert !CalciteSystemProperty.DEBUG.value() || isValid(Litmus.THROW, null);
     }
 
+    /**
+     * Creates a LogicalCorrelate.
+     *
+     * @param cluster cluster this relational expression belongs to
+     * @param left left input relational expression
+     * @param right right input relational expression
+     * @param correlationId variable name for the row of left input
+     * @param requiredColumns Required columns
+     * @param joinType join type
+     */
+    public LogicalCorrelate(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            RelNode left,
+            RelNode right,
+            CorrelationId correlationId,
+            ImmutableBitSet requiredColumns,
+            JoinRelType joinType) {
+        this(
+                cluster,
+                traitSet,
+                Collections.emptyList(),
+                left,
+                right,
+                correlationId,
+                requiredColumns,
+                joinType);
+    }
+
     /** Creates a LogicalCorrelate by parsing serialized output. */
     public LogicalCorrelate(RelInput input) {
         this(
@@ -81,6 +119,20 @@ public final class LogicalCorrelate extends Correlate {
                 input.getEnum("joinType", JoinRelType.class));
     }
 
+    /** Creates a LogicalCorrelate. */
+    public static LogicalCorrelate create(
+            RelNode left,
+            RelNode right,
+            List<RelHint> hints,
+            CorrelationId correlationId,
+            ImmutableBitSet requiredColumns,
+            JoinRelType joinType) {
+        final RelOptCluster cluster = left.getCluster();
+        final RelTraitSet traitSet = cluster.traitSetOf(Convention.NONE);
+        return new LogicalCorrelate(
+                cluster, traitSet, hints, left, right, correlationId, requiredColumns, joinType);
+    }
+
     /** Creates a LogicalCorrelate. */
     public static LogicalCorrelate create(
             RelNode left,
@@ -106,11 +158,31 @@ public final class LogicalCorrelate extends Correlate {
             JoinRelType joinType) {
         assert traitSet.containsIfApplicable(Convention.NONE);
         return new LogicalCorrelate(
-                getCluster(), traitSet, left, right, correlationId, requiredColumns, joinType);
+                getCluster(),
+                traitSet,
+                hints,
+                left,
+                right,
+                correlationId,
+                requiredColumns,
+                joinType);
     }
 
     @Override
     public RelNode accept(RelShuttle shuttle) {
         return shuttle.visit(this);
     }
+
+    @Override
+    public RelNode withHints(List<RelHint> hintList) {
+        return new LogicalCorrelate(
+                getCluster(),
+                traitSet,
+                hintList,
+                left,
+                right,
+                correlationId,
+                requiredColumns,
+                joinType);
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java
index 93f3e61bcbd..05852df6926 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalFilter.java
@@ -29,16 +29,24 @@ import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.RelWriter;
 import org.apache.calcite.rel.core.CorrelationId;
 import org.apache.calcite.rel.core.Filter;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMdCollation;
 import org.apache.calcite.rel.metadata.RelMdDistribution;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.util.Litmus;
 
+import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 
-/** Sub-class of {@link Filter} not targeted at any particular engine or calling convention. */
+/**
+ * Sub-class of {@link org.apache.calcite.rel.core.Filter} not targeted at any particular engine or
+ * calling convention.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ */
 public final class LogicalFilter extends Filter {
     private final com.google.common.collect.ImmutableSet<CorrelationId> variablesSet;
 
@@ -50,6 +58,7 @@ public final class LogicalFilter extends Filter {
      * <p>Use {@link #create} unless you know what you're doing.
      *
      * @param cluster Cluster that this relational expression belongs to
+     * @param hints Hints for this node
      * @param child Input relational expression
      * @param condition Boolean expression which determines whether a row is allowed to pass
      * @param variablesSet Correlation variables set by this relational expression to be used by
@@ -58,14 +67,30 @@ public final class LogicalFilter extends Filter {
     public LogicalFilter(
             RelOptCluster cluster,
             RelTraitSet traitSet,
+            List<RelHint> hints,
             RelNode child,
             RexNode condition,
             com.google.common.collect.ImmutableSet<CorrelationId> variablesSet) {
-        super(cluster, traitSet, child, condition);
+        super(cluster, traitSet, hints, child, condition);
         this.variablesSet = Objects.requireNonNull(variablesSet);
         assert isValid(Litmus.THROW, null);
     }
 
+    public LogicalFilter(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            RelNode child,
+            RexNode condition,
+            com.google.common.collect.ImmutableSet<CorrelationId> variablesSet) {
+        this(
+                cluster,
+                traitSet,
+                com.google.common.collect.ImmutableList.of(),
+                child,
+                condition,
+                variablesSet);
+    }
+
     @Deprecated // to be removed before 2.0
     public LogicalFilter(
             RelOptCluster cluster, RelTraitSet traitSet, RelNode child, RexNode condition) {
@@ -120,7 +145,7 @@ public final class LogicalFilter extends Filter {
 
     public LogicalFilter copy(RelTraitSet traitSet, RelNode input, RexNode condition) {
         assert traitSet.containsIfApplicable(Convention.NONE);
-        return new LogicalFilter(getCluster(), traitSet, input, condition, variablesSet);
+        return new LogicalFilter(getCluster(), traitSet, hints, input, condition, variablesSet);
     }
 
     @Override
@@ -142,4 +167,9 @@ public final class LogicalFilter extends Filter {
     public int deepHashCode() {
         return Objects.hash(deepHashCode0(), variablesSet);
     }
+
+    @Override
+    public RelNode withHints(List<RelHint> hintList) {
+        return new LogicalFilter(getCluster(), traitSet, hintList, input, condition, variablesSet);
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalIntersect.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalIntersect.java
index ff5ef05c3e3..b3975937604 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalIntersect.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalIntersect.java
@@ -25,7 +25,9 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.core.Intersect;
+import org.apache.calcite.rel.hint.RelHint;
 
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -35,6 +37,20 @@ import java.util.List;
 public final class LogicalIntersect extends Intersect {
     // ~ Constructors -----------------------------------------------------------
 
+    /**
+     * Creates a LogicalIntersect.
+     *
+     * <p>Use {@link #create} unless you know what you're doing.
+     */
+    public LogicalIntersect(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            List<RelHint> hints,
+            List<RelNode> inputs,
+            boolean all) {
+        super(cluster, traitSet, hints, inputs, all);
+    }
+
     /**
      * Creates a LogicalIntersect.
      *
@@ -42,7 +58,7 @@ public final class LogicalIntersect extends Intersect {
      */
     public LogicalIntersect(
             RelOptCluster cluster, RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
-        super(cluster, traitSet, inputs, all);
+        this(cluster, traitSet, Collections.emptyList(), inputs, all);
     }
 
     @Deprecated // to be removed before 2.0
@@ -66,11 +82,16 @@ public final class LogicalIntersect extends Intersect {
 
     @Override
     public LogicalIntersect copy(RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
-        return new LogicalIntersect(getCluster(), traitSet, inputs, all);
+        return new LogicalIntersect(getCluster(), traitSet, hints, inputs, all);
     }
 
     @Override
     public RelNode accept(RelShuttle shuttle) {
         return shuttle.visit(this);
     }
+
+    @Override
+    public RelNode withHints(List<RelHint> hintList) {
+        return new LogicalIntersect(getCluster(), traitSet, hintList, inputs, all);
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalMinus.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalMinus.java
index ea2eb044156..cf04c1720da 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalMinus.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalMinus.java
@@ -25,13 +25,35 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.core.Minus;
+import org.apache.calcite.rel.hint.RelHint;
 
+import java.util.Collections;
 import java.util.List;
 
-/** Sub-class of {@link Minus} not targeted at any particular engine or calling convention. */
+/**
+ * Sub-class of {@link org.apache.calcite.rel.core.Minus} not targeted at any particular engine or
+ * calling convention.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ */
 public final class LogicalMinus extends Minus {
     // ~ Constructors -----------------------------------------------------------
 
+    /**
+     * Creates a LogicalMinus.
+     *
+     * <p>Use {@link #create} unless you know what you're doing.
+     */
+    public LogicalMinus(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            List<RelHint> hints,
+            List<RelNode> inputs,
+            boolean all) {
+        super(cluster, traitSet, hints, inputs, all);
+    }
+
     /**
      * Creates a LogicalMinus.
      *
@@ -39,7 +61,7 @@ public final class LogicalMinus extends Minus {
      */
     public LogicalMinus(
             RelOptCluster cluster, RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
-        super(cluster, traitSet, inputs, all);
+        this(cluster, traitSet, Collections.emptyList(), inputs, all);
     }
 
     @Deprecated // to be removed before 2.0
@@ -64,11 +86,16 @@ public final class LogicalMinus extends Minus {
     @Override
     public LogicalMinus copy(RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
         assert traitSet.containsIfApplicable(Convention.NONE);
-        return new LogicalMinus(getCluster(), traitSet, inputs, all);
+        return new LogicalMinus(getCluster(), traitSet, hints, inputs, all);
     }
 
     @Override
     public RelNode accept(RelShuttle shuttle) {
         return shuttle.visit(this);
     }
+
+    @Override
+    public RelNode withHints(List<RelHint> hintList) {
+        return new LogicalMinus(getCluster(), traitSet, hintList, inputs, all);
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java
index 437744ee039..e0eda26b83a 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalSort.java
@@ -27,9 +27,19 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.core.Sort;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rex.RexNode;
 
-/** Sub-class of {@link Sort} not targeted at any particular engine or calling convention. */
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Sub-class of {@link org.apache.calcite.rel.core.Sort} not targeted at any particular engine or
+ * calling convention.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ */
 public final class LogicalSort extends Sort {
     private LogicalSort(
             RelOptCluster cluster,
@@ -38,7 +48,18 @@ public final class LogicalSort extends Sort {
             RelCollation collation,
             RexNode offset,
             RexNode fetch) {
-        super(cluster, traitSet, input, collation, offset, fetch);
+        this(cluster, traitSet, Collections.emptyList(), input, collation, offset, fetch);
+    }
+
+    private LogicalSort(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            List<RelHint> hints,
+            RelNode input,
+            RelCollation collation,
+            RexNode offset,
+            RexNode fetch) {
+        super(cluster, traitSet, hints, input, collation, offset, fetch);
         assert traitSet.containsIfApplicable(Convention.NONE);
     }
 
@@ -72,11 +93,17 @@ public final class LogicalSort extends Sort {
             RelCollation newCollation,
             RexNode offset,
             RexNode fetch) {
-        return new LogicalSort(getCluster(), traitSet, newInput, newCollation, offset, fetch);
+        return new LogicalSort(
+                getCluster(), traitSet, hints, newInput, newCollation, offset, fetch);
     }
 
     @Override
     public RelNode accept(RelShuttle shuttle) {
         return shuttle.visit(this);
     }
+
+    @Override
+    public RelNode withHints(List<RelHint> hintList) {
+        return new LogicalSort(getCluster(), traitSet, hintList, input, collation, offset, fetch);
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalUnion.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalUnion.java
index 25b4420c188..24de518359b 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalUnion.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalUnion.java
@@ -25,13 +25,35 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.core.Union;
+import org.apache.calcite.rel.hint.RelHint;
 
+import java.util.Collections;
 import java.util.List;
 
-/** Sub-class of {@link Union} not targeted at any particular engine or calling convention. */
+/**
+ * Sub-class of {@link org.apache.calcite.rel.core.Union} not targeted at any particular engine or
+ * calling convention.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ */
 public final class LogicalUnion extends Union {
     // ~ Constructors -----------------------------------------------------------
 
+    /**
+     * Creates a LogicalUnion.
+     *
+     * <p>Use {@link #create} unless you know what you're doing.
+     */
+    public LogicalUnion(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            List<RelHint> hints,
+            List<RelNode> inputs,
+            boolean all) {
+        super(cluster, traitSet, hints, inputs, all);
+    }
+
     /**
      * Creates a LogicalUnion.
      *
@@ -39,7 +61,7 @@ public final class LogicalUnion extends Union {
      */
     public LogicalUnion(
             RelOptCluster cluster, RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
-        super(cluster, traitSet, inputs, all);
+        this(cluster, traitSet, Collections.emptyList(), inputs, all);
     }
 
     @Deprecated // to be removed before 2.0
@@ -63,11 +85,16 @@ public final class LogicalUnion extends Union {
 
     public LogicalUnion copy(RelTraitSet traitSet, List<RelNode> inputs, boolean all) {
         assert traitSet.containsIfApplicable(Convention.NONE);
-        return new LogicalUnion(getCluster(), traitSet, inputs, all);
+        return new LogicalUnion(getCluster(), traitSet, hints, inputs, all);
     }
 
     @Override
     public RelNode accept(RelShuttle shuttle) {
         return shuttle.visit(this);
     }
+
+    @Override
+    public RelNode withHints(List<RelHint> hintList) {
+        return new LogicalUnion(getCluster(), traitSet, hintList, inputs, all);
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java
index c8ff3179c7f..7dd2c6b66c4 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalValues.java
@@ -27,6 +27,7 @@ import org.apache.calcite.rel.RelInput;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelShuttle;
 import org.apache.calcite.rel.core.Values;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.metadata.RelMdCollation;
 import org.apache.calcite.rel.metadata.RelMdDistribution;
 import org.apache.calcite.rel.metadata.RelMetadataQuery;
@@ -35,12 +36,41 @@ import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.sql.type.SqlTypeName;
 
 import java.math.BigDecimal;
+import java.util.Collections;
 import java.util.List;
 
-/** Sub-class of {@link Values} not targeted at any particular engine or calling convention. */
+/**
+ * Sub-class of {@link org.apache.calcite.rel.core.Values} not targeted at any particular engine or
+ * calling convention.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ */
 public class LogicalValues extends Values {
     // ~ Constructors -----------------------------------------------------------
 
+    /**
+     * Creates a LogicalValues.
+     *
+     * <p>Use {@link #create} unless you know what you're doing.
+     *
+     * @param cluster Cluster that this relational expression belongs to
+     * @param hints Hints for this node
+     * @param rowType Row type for tuples produced by this rel
+     * @param tuples 2-dimensional array of tuple values to be produced; outer list contains tuples;
+     *     each inner list is one tuple; all tuples must be of same length, conforming to rowType
+     */
+    public LogicalValues(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            List<RelHint> hints,
+            RelDataType rowType,
+            com.google.common.collect.ImmutableList<
+                            com.google.common.collect.ImmutableList<RexLiteral>>
+                    tuples) {
+        super(cluster, hints, rowType, tuples, traitSet);
+    }
+
     /**
      * Creates a LogicalValues.
      *
@@ -58,7 +88,7 @@ public class LogicalValues extends Values {
             com.google.common.collect.ImmutableList<
                             com.google.common.collect.ImmutableList<RexLiteral>>
                     tuples) {
-        super(cluster, rowType, tuples, traitSet);
+        this(cluster, traitSet, Collections.emptyList(), rowType, tuples);
     }
 
     @Deprecated // to be removed before 2.0
@@ -131,4 +161,9 @@ public class LogicalValues extends Values {
     public RelNode accept(RelShuttle shuttle) {
         return shuttle.visit(this);
     }
+
+    @Override
+    public RelNode withHints(List<RelHint> hintList) {
+        return new LogicalValues(getCluster(), traitSet, hintList, rowType, tuples);
+    }
 }
diff --git a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java
index ef5f87092c0..6c9cc5a1c5e 100644
--- a/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java
+++ b/flink-table/flink-table-planner/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java
@@ -25,6 +25,7 @@ import org.apache.calcite.plan.RelTraitSet;
 import org.apache.calcite.rel.RelCollation;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.core.Window;
+import org.apache.calcite.rel.hint.RelHint;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rex.RexInputRef;
 import org.apache.calcite.rex.RexLiteral;
@@ -44,13 +45,20 @@ import org.apache.calcite.util.Util;
 import java.util.AbstractList;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
-/** Sub-class of {@link Window} not targeted at any particular engine or calling convention. */
+/**
+ * Sub-class of {@link org.apache.calcite.rel.core.Window} not targeted at any particular engine or
+ * calling convention.
+ *
+ * <p>Temporarily copy from calcite to cherry-pick [CALCITE-5107] and will be removed when upgrade
+ * the latest calcite.
+ */
 public final class LogicalWindow extends Window {
     /**
      * Creates a LogicalWindow.
@@ -59,6 +67,7 @@ public final class LogicalWindow extends Window {
      *
      * @param cluster Cluster
      * @param traitSet Trait set
+     * @param hints hints for this node
      * @param input Input relational expression
      * @param constants List of constants that are additional inputs
      * @param rowType Output row type
@@ -67,16 +76,33 @@ public final class LogicalWindow extends Window {
     public LogicalWindow(
             RelOptCluster cluster,
             RelTraitSet traitSet,
+            List<RelHint> hints,
             RelNode input,
             List<RexLiteral> constants,
             RelDataType rowType,
             List<Group> groups) {
-        super(cluster, traitSet, input, constants, rowType, groups);
+        super(cluster, traitSet, hints, input, constants, rowType, groups);
+    }
+
+    /**
+     * Creates a LogicalWindow.
+     *
+     * <p>Use {@link #create} unless you know what you're doing.
+     */
+    public LogicalWindow(
+            RelOptCluster cluster,
+            RelTraitSet traitSet,
+            RelNode input,
+            List<RexLiteral> constants,
+            RelDataType rowType,
+            List<Group> groups) {
+        this(cluster, traitSet, Collections.emptyList(), input, constants, rowType, groups);
     }
 
     @Override
     public LogicalWindow copy(RelTraitSet traitSet, List<RelNode> inputs) {
-        return new LogicalWindow(getCluster(), traitSet, sole(inputs), constants, rowType, groups);
+        return new LogicalWindow(
+                getCluster(), traitSet, hints, sole(inputs), constants, rowType, groups);
     }
 
     /**
@@ -147,7 +173,7 @@ public final class LogicalWindow extends Window {
             }
         }
 
-        final Map<RexOver, RexWinAggCall> aggMap = new HashMap<>();
+        final Map<RexOver, Window.RexWinAggCall> aggMap = new HashMap<>();
         List<Group> groups = new ArrayList<>();
         for (Map.Entry<WindowKey, Collection<RexOver>> entry : windowMap.asMap().entrySet()) {
             final WindowKey windowKey = entry.getKey();
@@ -184,7 +210,7 @@ public final class LogicalWindow extends Window {
         // Figure out the type of the inputs to the output program.
         // They are: the inputs to this rel, followed by the outputs of
         // each window.
-        final List<RexWinAggCall> flattenedAggCallList = new ArrayList<>();
+        final List<Window.RexWinAggCall> flattenedAggCallList = new ArrayList<>();
         final List<Map.Entry<String, RelDataType>> fieldList =
                 new ArrayList<>(child.getRowType().getFieldList());
         final int offset = fieldList.size();
@@ -219,7 +245,7 @@ public final class LogicalWindow extends Window {
                 new RexShuttle() {
                     public RexNode visitOver(RexOver over) {
                         // Look up the aggCall which this expr was translated to.
-                        final RexWinAggCall aggCall = aggMap.get(origToNewOver.get(over));
+                        final Window.RexWinAggCall aggCall = aggMap.get(origToNewOver.get(over));
                         assert aggCall != null;
                         assert RelOptUtil.eq(
                                 "over", over.getType(), "aggCall", aggCall.getType(), Litmus.THROW);
@@ -364,4 +390,10 @@ public final class LogicalWindow extends Window {
                         aggWindow.getUpperBound());
         windowMap.put(windowKey, over);
     }
+
+    @Override
+    public RelNode withHints(List<RelHint> hintList) {
+        return new LogicalWindow(
+                getCluster(), traitSet, hintList, input, constants, rowType, groups);
+    }
 }