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

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


The following commit(s) were added to refs/heads/master by this push:
     new e7c1e5e0f3 [flink] Report which required argument is missing in action 
factories (#9059)
e7c1e5e0f3 is described below

commit e7c1e5e0f303a3b2e4aa3ca0fa3a1f844c78c551
Author: Eunbin Son <[email protected]>
AuthorDate: Fri Aug 7 14:15:20 2026 +0900

    [flink] Report which required argument is missing in action factories 
(#9059)
---
 .../CreateTagFromTimestampActionFactory.java       |  2 +-
 .../CreateTagFromWatermarkActionFactory.java       |  4 +-
 .../flink/action/MergeIntoActionFactory.java       |  2 +-
 .../CreateTagFromTimestampActionFactoryTest.java   | 70 ++++++++++++++++
 .../CreateTagFromWatermarkActionFactoryTest.java   | 89 ++++++++++++++++++++
 .../flink/action/MergeIntoActionFactoryTest.java   | 98 ++++++++++++++++++++++
 6 files changed, 261 insertions(+), 4 deletions(-)

diff --git 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateTagFromTimestampActionFactory.java
 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateTagFromTimestampActionFactory.java
index 658f3e03f0..639d5624bf 100644
--- 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateTagFromTimestampActionFactory.java
+++ 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateTagFromTimestampActionFactory.java
@@ -38,7 +38,7 @@ public class CreateTagFromTimestampActionFactory implements 
ActionFactory {
 
     @Override
     public Optional<Action> create(MultipleParameterToolAdapter params) {
-        Long timestamp = Long.parseLong(params.get(TIMESTAMP));
+        Long timestamp = Long.parseLong(params.getRequired(TIMESTAMP));
         String timeRetained = params.get(TIME_RETAINED);
         Map<String, String> catalogConfig = catalogConfigMap(params);
 
diff --git 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateTagFromWatermarkActionFactory.java
 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateTagFromWatermarkActionFactory.java
index 1f4e5b1f92..47ca8e461a 100644
--- 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateTagFromWatermarkActionFactory.java
+++ 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/CreateTagFromWatermarkActionFactory.java
@@ -39,8 +39,8 @@ public class CreateTagFromWatermarkActionFactory implements 
ActionFactory {
 
     @Override
     public Optional<Action> create(MultipleParameterToolAdapter params) {
-        String tag = params.get(TAG);
-        Long watermark = Long.parseLong(params.get(WATERMARK));
+        String tag = params.getRequired(TAG);
+        Long watermark = Long.parseLong(params.getRequired(WATERMARK));
         String timeRetained = params.get(TIME_RETAINED);
         Map<String, String> catalogConfig = catalogConfigMap(params);
 
diff --git 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/MergeIntoActionFactory.java
 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/MergeIntoActionFactory.java
index e39b6397c9..fab8865c50 100644
--- 
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/MergeIntoActionFactory.java
+++ 
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/action/MergeIntoActionFactory.java
@@ -80,7 +80,7 @@ public class MergeIntoActionFactory implements ActionFactory {
         action.withMergeCondition(params.getRequired(ON));
 
         List<String> actions =
-                Arrays.stream(params.get(MERGE_ACTIONS).split(","))
+                Arrays.stream(params.getRequired(MERGE_ACTIONS).split(","))
                         .map(String::trim)
                         .collect(Collectors.toList());
         if (actions.contains(MATCHED_UPSERT)) {
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/CreateTagFromTimestampActionFactoryTest.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/CreateTagFromTimestampActionFactoryTest.java
new file mode 100644
index 0000000000..a15091f7c6
--- /dev/null
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/CreateTagFromTimestampActionFactoryTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.paimon.flink.action;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+/** Tests for {@link CreateTagFromTimestampActionFactory#create}. */
+public class CreateTagFromTimestampActionFactoryTest extends ActionITCaseBase {
+
+    @Test
+    public void testMissingTimestampReportsRequiredArgument() {
+        assertThatThrownBy(
+                        () ->
+                                createAction(
+                                        CreateTagFromTimestampAction.class,
+                                        "create_tag_from_timestamp",
+                                        "--warehouse",
+                                        warehouse,
+                                        "--database",
+                                        database,
+                                        "--table",
+                                        tableName,
+                                        "--tag",
+                                        "tag_1"))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("Argument 'timestamp' is required");
+    }
+
+    @Test
+    public void testCreateWithTimestamp() {
+        assertThatCode(
+                        () ->
+                                assertThat(
+                                                createAction(
+                                                        
CreateTagFromTimestampAction.class,
+                                                        
"create_tag_from_timestamp",
+                                                        "--warehouse",
+                                                        warehouse,
+                                                        "--database",
+                                                        database,
+                                                        "--table",
+                                                        tableName,
+                                                        "--tag",
+                                                        "tag_1",
+                                                        "--timestamp",
+                                                        "1000"))
+                                        .isNotNull())
+                .doesNotThrowAnyException();
+    }
+}
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/CreateTagFromWatermarkActionFactoryTest.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/CreateTagFromWatermarkActionFactoryTest.java
new file mode 100644
index 0000000000..bac8b99076
--- /dev/null
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/CreateTagFromWatermarkActionFactoryTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.paimon.flink.action;
+
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+/** Tests for {@link CreateTagFromWatermarkActionFactory#create}. */
+public class CreateTagFromWatermarkActionFactoryTest extends ActionITCaseBase {
+
+    @Test
+    public void testMissingWatermarkReportsRequiredArgument() {
+        assertThatThrownBy(
+                        () ->
+                                createAction(
+                                        CreateTagFromWatermarkAction.class,
+                                        "create_tag_from_watermark",
+                                        "--warehouse",
+                                        warehouse,
+                                        "--database",
+                                        database,
+                                        "--table",
+                                        tableName,
+                                        "--tag",
+                                        "tag_1"))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("Argument 'watermark' is required");
+    }
+
+    @Test
+    public void testMissingTagReportsRequiredArgument() {
+        assertThatThrownBy(
+                        () ->
+                                createAction(
+                                        CreateTagFromWatermarkAction.class,
+                                        "create_tag_from_watermark",
+                                        "--warehouse",
+                                        warehouse,
+                                        "--database",
+                                        database,
+                                        "--table",
+                                        tableName,
+                                        "--watermark",
+                                        "1000"))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("Argument 'tag' is required");
+    }
+
+    @Test
+    public void testCreateWithTagAndWatermark() {
+        assertThatCode(
+                        () ->
+                                assertThat(
+                                                createAction(
+                                                        
CreateTagFromWatermarkAction.class,
+                                                        
"create_tag_from_watermark",
+                                                        "--warehouse",
+                                                        warehouse,
+                                                        "--database",
+                                                        database,
+                                                        "--table",
+                                                        tableName,
+                                                        "--tag",
+                                                        "tag_1",
+                                                        "--watermark",
+                                                        "1000"))
+                                        .isNotNull())
+                .doesNotThrowAnyException();
+    }
+}
diff --git 
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/MergeIntoActionFactoryTest.java
 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/MergeIntoActionFactoryTest.java
new file mode 100644
index 0000000000..266b3eec65
--- /dev/null
+++ 
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/action/MergeIntoActionFactoryTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.paimon.flink.action;
+
+import org.apache.paimon.types.DataType;
+import org.apache.paimon.types.DataTypes;
+import org.apache.paimon.types.RowType;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+/** Tests for {@link MergeIntoActionFactory#create}. */
+public class MergeIntoActionFactoryTest extends ActionITCaseBase {
+
+    @BeforeEach
+    public void setUp() throws Exception {
+        // merge_into loads the target table before parsing --merge_actions, 
so it must exist and
+        // must have primary keys
+        DataType[] fieldTypes = new DataType[] {DataTypes.INT(), 
DataTypes.STRING()};
+        RowType rowType = RowType.of(fieldTypes, new String[] {"k", "v"});
+        createFileStoreTable(
+                rowType,
+                Collections.emptyList(),
+                Collections.singletonList("k"),
+                Collections.emptyList(),
+                new HashMap<>());
+    }
+
+    @Test
+    public void testMissingMergeActionsReportsRequiredArgument() {
+        assertThatThrownBy(
+                        () ->
+                                createAction(
+                                        MergeIntoAction.class,
+                                        "merge_into",
+                                        "--warehouse",
+                                        warehouse,
+                                        "--database",
+                                        database,
+                                        "--table",
+                                        tableName,
+                                        "--source_table",
+                                        "S",
+                                        "--on",
+                                        "T.k = S.k"))
+                .isInstanceOf(IllegalArgumentException.class)
+                .hasMessageContaining("Argument 'merge_actions' is required");
+    }
+
+    @Test
+    public void testCreateWithMergeActions() {
+        assertThatCode(
+                        () ->
+                                assertThat(
+                                                createAction(
+                                                        MergeIntoAction.class,
+                                                        "merge_into",
+                                                        "--warehouse",
+                                                        warehouse,
+                                                        "--database",
+                                                        database,
+                                                        "--table",
+                                                        tableName,
+                                                        "--source_table",
+                                                        "S",
+                                                        "--on",
+                                                        "T.k = S.k",
+                                                        "--merge_actions",
+                                                        "matched-upsert",
+                                                        "--matched_upsert_set",
+                                                        "v = S.v"))
+                                        .isNotNull())
+                .doesNotThrowAnyException();
+    }
+}

Reply via email to