[CALCITE-6321] Add copy(List<RexLiteral>) method to Window class
diff --git a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java
index 8b00799..3ee72a3 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/EnumerableWindow.java
@@ -85,6 +85,11 @@
         constants, getRowType(), groups);
   }
 
+  @Override public Window copy(List<RexLiteral> constants) {
+    return new EnumerableWindow(getCluster(), getTraitSet(), getInput(),
+        constants, getRowType(), groups);
+  }
+
   @Override public @Nullable RelOptCost computeSelfCost(RelOptPlanner planner,
       RelMetadataQuery mq) {
     RelOptCost cost = super.computeSelfCost(planner, mq);
diff --git a/core/src/main/java/org/apache/calcite/interpreter/Bindables.java b/core/src/main/java/org/apache/calcite/interpreter/Bindables.java
index cc52e7c..8d622dd 100644
--- a/core/src/main/java/org/apache/calcite/interpreter/Bindables.java
+++ b/core/src/main/java/org/apache/calcite/interpreter/Bindables.java
@@ -836,6 +836,11 @@
           constants, getRowType(), groups);
     }
 
+    @Override public Window copy(List<RexLiteral> constants) {
+      return new BindableWindow(getCluster(), traitSet, getInput(),
+          constants, getRowType(), groups);
+    }
+
     @Override public @Nullable RelOptCost computeSelfCost(RelOptPlanner planner,
         RelMetadataQuery mq) {
       RelOptCost cost = super.computeSelfCost(planner, mq);
diff --git a/core/src/main/java/org/apache/calcite/rel/core/Window.java b/core/src/main/java/org/apache/calcite/rel/core/Window.java
index 8cdaa90..4f76256 100644
--- a/core/src/main/java/org/apache/calcite/rel/core/Window.java
+++ b/core/src/main/java/org/apache/calcite/rel/core/Window.java
@@ -111,6 +111,14 @@
     this(cluster, traitSet, Collections.emptyList(), input, constants, rowType, groups);
   }
 
+  /**
+   * Creates a copy of this {@code Window}.
+   *
+   * @param constants Replaces the list of constants in the returned copy
+   * @return New {@code Window}
+   */
+  public abstract Window copy(List<RexLiteral> constants);
+
   @Override public boolean isValid(Litmus litmus, @Nullable Context context) {
     // In the window specifications, an aggregate call such as
     // 'SUM(RexInputRef #10)' refers to expression #10 of inputProgram.
diff --git a/core/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java b/core/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java
index 7a1253b..3bc23b3 100644
--- a/core/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java
+++ b/core/src/main/java/org/apache/calcite/rel/logical/LogicalWindow.java
@@ -103,6 +103,11 @@
       getRowType(), groups);
   }
 
+  @Override public Window copy(List<RexLiteral> constants) {
+    return new LogicalWindow(getCluster(), getTraitSet(), getInput(),
+        constants, getRowType(), groups);
+  }
+
   /**
    * Creates a LogicalWindow.
    *
diff --git a/core/src/test/java/org/apache/calcite/adapter/enumerable/EnumerableWindowTest.java b/core/src/test/java/org/apache/calcite/adapter/enumerable/EnumerableWindowTest.java
new file mode 100644
index 0000000..781f8fa
--- /dev/null
+++ b/core/src/test/java/org/apache/calcite/adapter/enumerable/EnumerableWindowTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.adapter.enumerable;
+
+import org.apache.calcite.plan.Contexts;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.AbstractRelNode;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Window;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.sql.type.BasicSqlType;
+import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.test.MockRelOptPlanner;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+/**
+ * Test for {@link org.apache.calcite.adapter.enumerable.EnumerableWindow}.
+ */
+public class EnumerableWindowTest {
+  @Test void testCopyWithConstants() {
+    final MockRelOptPlanner planner = new MockRelOptPlanner(Contexts.empty());
+    final RelDataTypeFactory typeFactory =
+        new SqlTypeFactoryImpl(org.apache.calcite.rel.type.RelDataTypeSystem.DEFAULT);
+    final RelOptCluster cluster = RelOptCluster.create(planner, new RexBuilder(typeFactory));
+    final RelTraitSet traitSet = RelTraitSet.createEmpty();
+    final RelNode relNode = new AbstractRelNode(cluster, traitSet) {
+    };
+    final RelDataTypeSystem dataTypeSystem = new RelDataTypeSystemImpl() {
+    };
+
+    final RelDataType dataType = new BasicSqlType(dataTypeSystem, SqlTypeName.BOOLEAN);
+    final List<RexLiteral> constants =
+        Collections.singletonList(
+            RexLiteral.fromJdbcString(dataType,
+                SqlTypeName.BOOLEAN,
+                "TRUE"));
+    final RelDataType rowDataType = new BasicSqlType(dataTypeSystem, SqlTypeName.ROW);
+    final List<Window.Group> groups = Collections.emptyList();
+
+    final EnumerableWindow original =
+        new EnumerableWindow(cluster, traitSet, relNode, constants, rowDataType, groups);
+    final List<RexLiteral> newConstants =
+        Collections.singletonList(
+            RexLiteral.fromJdbcString(dataType,
+                SqlTypeName.BOOLEAN,
+                "FALSE"));
+    final Window updated = original.copy(newConstants);
+
+    assertNotSame(original, updated);
+    assertEquals(1, original.getConstants().size());
+    assertSame(constants.get(0), original.getConstants().get(0));
+    assertEquals(1, updated.getConstants().size());
+    assertSame(newConstants.get(0), updated.getConstants().get(0));
+  }
+}
diff --git a/core/src/test/java/org/apache/calcite/interpreter/BindableWindowTest.java b/core/src/test/java/org/apache/calcite/interpreter/BindableWindowTest.java
new file mode 100644
index 0000000..3d28b3a
--- /dev/null
+++ b/core/src/test/java/org/apache/calcite/interpreter/BindableWindowTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.interpreter;
+
+import org.apache.calcite.plan.Contexts;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.AbstractRelNode;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Window;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.sql.type.BasicSqlType;
+import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.test.MockRelOptPlanner;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+/**
+ * Test for {@link org.apache.calcite.interpreter.Bindables.BindableWindow}.
+ */
+public class BindableWindowTest {
+  @Test void testCopyWithConstants() {
+    final MockRelOptPlanner planner = new MockRelOptPlanner(Contexts.empty());
+    final RelDataTypeFactory typeFactory =
+        new SqlTypeFactoryImpl(org.apache.calcite.rel.type.RelDataTypeSystem.DEFAULT);
+    final RelOptCluster cluster = RelOptCluster.create(planner, new RexBuilder(typeFactory));
+    final RelTraitSet traitSet = RelTraitSet.createEmpty();
+    final RelNode relNode = new AbstractRelNode(cluster, traitSet) {
+    };
+    final RelDataTypeSystem dataTypeSystem = new RelDataTypeSystemImpl() {
+    };
+
+    final RelDataType dataType = new BasicSqlType(dataTypeSystem, SqlTypeName.BOOLEAN);
+    final List<RexLiteral> constants =
+        Collections.singletonList(
+            RexLiteral.fromJdbcString(dataType,
+                SqlTypeName.BOOLEAN,
+                "TRUE"));
+    final RelDataType rowDataType = new BasicSqlType(dataTypeSystem, SqlTypeName.ROW);
+    final List<Window.Group> groups = Collections.emptyList();
+
+    final Bindables.BindableWindow original =
+        new Bindables.BindableWindow(cluster, traitSet, relNode, constants, rowDataType, groups);
+    final List<RexLiteral> newConstants =
+        Collections.singletonList(
+            RexLiteral.fromJdbcString(dataType,
+                SqlTypeName.BOOLEAN,
+                "FALSE"));
+    final Window updated = original.copy(newConstants);
+
+    assertNotSame(original, updated);
+    assertEquals(1, original.getConstants().size());
+    assertSame(constants.get(0), original.getConstants().get(0));
+    assertEquals(1, updated.getConstants().size());
+    assertSame(newConstants.get(0), updated.getConstants().get(0));
+  }
+}
diff --git a/core/src/test/java/org/apache/calcite/rel/logical/LogicalWindowTest.java b/core/src/test/java/org/apache/calcite/rel/logical/LogicalWindowTest.java
new file mode 100644
index 0000000..9da4865
--- /dev/null
+++ b/core/src/test/java/org/apache/calcite/rel/logical/LogicalWindowTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.logical;
+
+import org.apache.calcite.plan.Contexts;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.AbstractRelNode;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.Window;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexLiteral;
+import org.apache.calcite.sql.type.BasicSqlType;
+import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.apache.calcite.test.MockRelOptPlanner;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.List;
+
+import static org.apache.calcite.rel.core.Window.Group;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+/**
+ * Test for {@link org.apache.calcite.rel.logical.LogicalWindow}.
+ */
+public class LogicalWindowTest {
+  @Test void testCopyWithConstants() {
+    final MockRelOptPlanner planner = new MockRelOptPlanner(Contexts.empty());
+    final RelDataTypeFactory typeFactory =
+        new SqlTypeFactoryImpl(org.apache.calcite.rel.type.RelDataTypeSystem.DEFAULT);
+    final RelOptCluster cluster = RelOptCluster.create(planner, new RexBuilder(typeFactory));
+    final RelTraitSet traitSet = RelTraitSet.createEmpty();
+    final RelNode relNode = new AbstractRelNode(cluster, traitSet) {
+    };
+    final RelDataTypeSystem dataTypeSystem = new RelDataTypeSystemImpl() {
+    };
+
+    final RelDataType dataType = new BasicSqlType(dataTypeSystem, SqlTypeName.BOOLEAN);
+    final List<RexLiteral> constants =
+        Collections.singletonList(
+            RexLiteral.fromJdbcString(dataType,
+                SqlTypeName.BOOLEAN,
+                "TRUE"));
+    final RelDataType rowDataType = new BasicSqlType(dataTypeSystem, SqlTypeName.ROW);
+    final List<Group> groups = Collections.emptyList();
+
+    final LogicalWindow original =
+        new LogicalWindow(cluster, traitSet, relNode, constants, rowDataType, groups);
+    final List<RexLiteral> newConstants =
+        Collections.singletonList(
+            RexLiteral.fromJdbcString(dataType,
+                SqlTypeName.BOOLEAN,
+                "FALSE"));
+    final Window updated = original.copy(newConstants);
+
+    assertNotSame(original, updated);
+    assertEquals(1, original.getConstants().size());
+    assertSame(constants.get(0), original.getConstants().get(0));
+    assertEquals(1, updated.getConstants().size());
+    assertSame(newConstants.get(0), updated.getConstants().get(0));
+  }
+}
diff --git a/site/_docs/history.md b/site/_docs/history.md
index f3140e7..2e2b8c7 100644
--- a/site/_docs/history.md
+++ b/site/_docs/history.md
@@ -46,6 +46,8 @@
 * In the context of [CALCITE-6015] the visibility of the method
 `SqlCall.getCallSignature` has been converted from `protected` to `public`.
  Any subclass overriding it will need to be adjusted accordingly.
+* [<a href="https://issues.apache.org/jira/browse/CALCITE-6321">CALCITE-6321</a>]
+ Add `copy(List<RexLiteral>)` method to `Window` class
 
 Compatibility: This release is tested on Linux, macOS, Microsoft Windows;
 using JDK/OpenJDK versions 8 to 19;