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

davidzollo pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 2e530b82be [Improve][Connector-V2] Migrate IoTDBv2 SQL dialect 
validation to OptionRule (#11839)
2e530b82be is described below

commit 2e530b82beac2ed38a5d16f12068b087066b2a88
Author: liziing <[email protected]>
AuthorDate: Tue Aug 18 11:31:09 2026 +0800

    [Improve][Connector-V2] Migrate IoTDBv2 SQL dialect validation to 
OptionRule (#11839)
---
 .../seatunnel/iotdbv2/sink/IoTDBv2SinkFactory.java | 26 ++-----
 .../iotdbv2/source/IoTDBv2SourceFactory.java       | 26 ++-----
 .../seatunnel/iotdbv2/IoTDBFactoryTest.java        | 85 +++++++++++++++++++++-
 3 files changed, 99 insertions(+), 38 deletions(-)

diff --git 
a/seatunnel-connectors-v2/connector-iotdb-v2/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/sink/IoTDBv2SinkFactory.java
 
b/seatunnel-connectors-v2/connector-iotdb-v2/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/sink/IoTDBv2SinkFactory.java
index ed8e964187..e0aad1ef99 100644
--- 
a/seatunnel-connectors-v2/connector-iotdb-v2/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/sink/IoTDBv2SinkFactory.java
+++ 
b/seatunnel-connectors-v2/connector-iotdb-v2/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/sink/IoTDBv2SinkFactory.java
@@ -18,15 +18,14 @@
 package org.apache.seatunnel.connectors.seatunnel.iotdbv2.sink;
 
 import org.apache.seatunnel.api.configuration.ReadonlyConfig;
+import org.apache.seatunnel.api.configuration.util.Conditions;
 import org.apache.seatunnel.api.configuration.util.OptionRule;
 import org.apache.seatunnel.api.table.connector.TableSink;
 import org.apache.seatunnel.api.table.factory.Factory;
 import org.apache.seatunnel.api.table.factory.TableSinkFactory;
 import org.apache.seatunnel.api.table.factory.TableSinkFactoryContext;
-import org.apache.seatunnel.common.exception.CommonErrorCode;
 import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.config.IoTDBv2SinkOptions;
 import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.constant.SinkConstants;
-import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.exception.IotdbConnectorException;
 
 import com.google.auto.service.AutoService;
 import lombok.extern.slf4j.Slf4j;
@@ -50,6 +49,8 @@ public class IoTDBv2SinkFactory implements TableSinkFactory {
                         IoTDBv2SinkOptions.KEY_DEVICE)
                 .optional(
                         IoTDBv2SinkOptions.SQL_DIALECT,
+                        Conditions.matches(IoTDBv2SinkOptions.SQL_DIALECT, 
"(?i)^(tree|table)$"))
+                .optional(
                         IoTDBv2SinkOptions.KEY_TIMESTAMP,
                         IoTDBv2SinkOptions.KEY_TAG_FIELDS,
                         IoTDBv2SinkOptions.KEY_ATTRIBUTE_FIELDS,
@@ -69,22 +70,11 @@ public class IoTDBv2SinkFactory implements TableSinkFactory 
{
     @Override
     public TableSink createSink(TableSinkFactoryContext context) {
         ReadonlyConfig conf = context.getOptions();
-        String targetSqlDialect;
-        if (conf.get(IoTDBv2SinkOptions.SQL_DIALECT) != null) {
-            String sqlDialect = conf.get(IoTDBv2SinkOptions.SQL_DIALECT);
-            if (SinkConstants.TABLE.equalsIgnoreCase(sqlDialect)) {
-                targetSqlDialect = SinkConstants.TABLE;
-            } else {
-                if (SinkConstants.TREE.equalsIgnoreCase(sqlDialect)) {
-                    targetSqlDialect = SinkConstants.TREE;
-                } else {
-                    throw new IotdbConnectorException(
-                            CommonErrorCode.ILLEGAL_ARGUMENT, "Sql dialect not 
supported");
-                }
-            }
-        } else {
-            targetSqlDialect = SinkConstants.TREE;
-        }
+        String sqlDialect = conf.get(IoTDBv2SinkOptions.SQL_DIALECT);
+        String targetSqlDialect =
+                SinkConstants.TABLE.equalsIgnoreCase(sqlDialect)
+                        ? SinkConstants.TABLE
+                        : SinkConstants.TREE;
         return () ->
                 new IoTDBv2Sink(context.getOptions(), 
context.getCatalogTable(), targetSqlDialect);
     }
diff --git 
a/seatunnel-connectors-v2/connector-iotdb-v2/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/source/IoTDBv2SourceFactory.java
 
b/seatunnel-connectors-v2/connector-iotdb-v2/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/source/IoTDBv2SourceFactory.java
index 6580201fba..6019f30ed1 100644
--- 
a/seatunnel-connectors-v2/connector-iotdb-v2/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/source/IoTDBv2SourceFactory.java
+++ 
b/seatunnel-connectors-v2/connector-iotdb-v2/src/main/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/source/IoTDBv2SourceFactory.java
@@ -18,6 +18,7 @@
 package org.apache.seatunnel.connectors.seatunnel.iotdbv2.source;
 
 import org.apache.seatunnel.api.configuration.ReadonlyConfig;
+import org.apache.seatunnel.api.configuration.util.Conditions;
 import org.apache.seatunnel.api.configuration.util.OptionRule;
 import org.apache.seatunnel.api.options.ConnectorCommonOptions;
 import org.apache.seatunnel.api.source.SeaTunnelSource;
@@ -28,10 +29,8 @@ import org.apache.seatunnel.api.table.connector.TableSource;
 import org.apache.seatunnel.api.table.factory.Factory;
 import org.apache.seatunnel.api.table.factory.TableSourceFactory;
 import org.apache.seatunnel.api.table.factory.TableSourceFactoryContext;
-import org.apache.seatunnel.common.exception.CommonErrorCode;
 import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.config.IoTDBv2SourceOptions;
 import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.constant.SourceConstants;
-import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.exception.IotdbConnectorException;
 
 import com.google.auto.service.AutoService;
 
@@ -55,6 +54,8 @@ public class IoTDBv2SourceFactory implements 
TableSourceFactory {
                         ConnectorCommonOptions.SCHEMA)
                 .optional(
                         IoTDBv2SourceOptions.SQL_DIALECT,
+                        Conditions.matches(IoTDBv2SourceOptions.SQL_DIALECT, 
"(?i)^(tree|table)$"))
+                .optional(
                         IoTDBv2SourceOptions.DATABASE,
                         IoTDBv2SourceOptions.FETCH_SIZE,
                         IoTDBv2SourceOptions.DEFAULT_THRIFT_BUFFER_SIZE,
@@ -71,22 +72,11 @@ public class IoTDBv2SourceFactory implements 
TableSourceFactory {
             TableSource<T, SplitT, StateT> 
createSource(TableSourceFactoryContext context) {
         CatalogTable catalogTable = 
CatalogTableUtil.buildWithConfig(context.getOptions());
         ReadonlyConfig conf = context.getOptions();
-        String targetSqlDialect;
-        if (conf.get(IoTDBv2SourceOptions.SQL_DIALECT) != null) {
-            String sqlDialect = conf.get(IoTDBv2SourceOptions.SQL_DIALECT);
-            if (SourceConstants.TABLE.equalsIgnoreCase(sqlDialect)) {
-                targetSqlDialect = SourceConstants.TABLE;
-            } else {
-                if (SourceConstants.TREE.equalsIgnoreCase(sqlDialect)) {
-                    targetSqlDialect = SourceConstants.TREE;
-                } else {
-                    throw new IotdbConnectorException(
-                            CommonErrorCode.ILLEGAL_ARGUMENT, "Sql dialect not 
supported");
-                }
-            }
-        } else {
-            targetSqlDialect = SourceConstants.TREE;
-        }
+        String sqlDialect = conf.get(IoTDBv2SourceOptions.SQL_DIALECT);
+        String targetSqlDialect =
+                SourceConstants.TABLE.equalsIgnoreCase(sqlDialect)
+                        ? SourceConstants.TABLE
+                        : SourceConstants.TREE;
         return () ->
                 (SeaTunnelSource<T, SplitT, StateT>)
                         new IoTDBv2Source(catalogTable, context.getOptions(), 
targetSqlDialect);
diff --git 
a/seatunnel-connectors-v2/connector-iotdb-v2/src/test/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/IoTDBFactoryTest.java
 
b/seatunnel-connectors-v2/connector-iotdb-v2/src/test/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/IoTDBFactoryTest.java
index 23f3824080..2004c910b5 100644
--- 
a/seatunnel-connectors-v2/connector-iotdb-v2/src/test/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/IoTDBFactoryTest.java
+++ 
b/seatunnel-connectors-v2/connector-iotdb-v2/src/test/java/org/apache/seatunnel/connectors/seatunnel/iotdbv2/IoTDBFactoryTest.java
@@ -17,17 +17,98 @@
 
 package org.apache.seatunnel.connectors.seatunnel.iotdbv2;
 
+import org.apache.seatunnel.api.configuration.ReadonlyConfig;
+import org.apache.seatunnel.api.configuration.util.ConfigValidator;
+import org.apache.seatunnel.api.configuration.util.OptionRule;
+import org.apache.seatunnel.api.configuration.util.OptionValidationException;
+import org.apache.seatunnel.api.options.ConnectorCommonOptions;
+import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.config.IoTDBv2CommonOptions;
+import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.config.IoTDBv2SinkOptions;
+import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.config.IoTDBv2SourceOptions;
 import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.sink.IoTDBv2SinkFactory;
 import 
org.apache.seatunnel.connectors.seatunnel.iotdbv2.source.IoTDBv2SourceFactory;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 class IoTDBFactoryTest {
 
+    private final OptionRule sourceRule = new 
IoTDBv2SourceFactory().optionRule();
+    private final OptionRule sinkRule = new IoTDBv2SinkFactory().optionRule();
+
     @Test
     void optionRule() {
-        Assertions.assertNotNull((new IoTDBv2SourceFactory()).optionRule());
-        Assertions.assertNotNull((new IoTDBv2SinkFactory()).optionRule());
+        Assertions.assertNotNull(sourceRule);
+        Assertions.assertNotNull(sinkRule);
+    }
+
+    @Test
+    void omittedSqlDialectIsAccepted() {
+        Assertions.assertDoesNotThrow(() -> validate(validSourceConfig(), 
sourceRule));
+        Assertions.assertDoesNotThrow(() -> validate(validSinkConfig(), 
sinkRule));
+    }
+
+    @Test
+    void supportedSqlDialectsAreAcceptedCaseInsensitively() {
+        for (String dialect : Arrays.asList("tree", "table", "TrEe", "TaBlE")) 
{
+            Map<String, Object> sourceConfig = validSourceConfig();
+            sourceConfig.put(IoTDBv2CommonOptions.SQL_DIALECT.key(), dialect);
+            Assertions.assertDoesNotThrow(() -> validate(sourceConfig, 
sourceRule));
+
+            Map<String, Object> sinkConfig = validSinkConfig();
+            sinkConfig.put(IoTDBv2CommonOptions.SQL_DIALECT.key(), dialect);
+            Assertions.assertDoesNotThrow(() -> validate(sinkConfig, 
sinkRule));
+        }
+    }
+
+    @Test
+    void unsupportedSqlDialectIsRejected() {
+        Map<String, Object> sourceConfig = validSourceConfig();
+        sourceConfig.put(IoTDBv2CommonOptions.SQL_DIALECT.key(), 
"unsupported");
+        OptionValidationException sourceException =
+                Assertions.assertThrows(
+                        OptionValidationException.class, () -> 
validate(sourceConfig, sourceRule));
+        Assertions.assertTrue(
+                
sourceException.getMessage().contains(IoTDBv2CommonOptions.SQL_DIALECT.key()));
+
+        Map<String, Object> sinkConfig = validSinkConfig();
+        sinkConfig.put(IoTDBv2CommonOptions.SQL_DIALECT.key(), "unsupported");
+        OptionValidationException sinkException =
+                Assertions.assertThrows(
+                        OptionValidationException.class, () -> 
validate(sinkConfig, sinkRule));
+        Assertions.assertTrue(
+                
sinkException.getMessage().contains(IoTDBv2CommonOptions.SQL_DIALECT.key()));
+    }
+
+    private void validate(Map<String, Object> config, OptionRule rule) {
+        ConfigValidator.of(ReadonlyConfig.fromMap(config)).validate(rule);
+    }
+
+    private Map<String, Object> validSourceConfig() {
+        Map<String, Object> config = commonConfig();
+        config.put(IoTDBv2SourceOptions.SQL.key(), "select * from root.test");
+        config.put(ConnectorCommonOptions.SCHEMA.key(), 
Collections.emptyMap());
+        return config;
+    }
+
+    private Map<String, Object> validSinkConfig() {
+        Map<String, Object> config = commonConfig();
+        config.put(IoTDBv2SinkOptions.STORAGE_GROUP.key(), "root.test");
+        config.put(IoTDBv2SinkOptions.KEY_DEVICE.key(), "device");
+        return config;
+    }
+
+    private Map<String, Object> commonConfig() {
+        Map<String, Object> config = new HashMap<>();
+        config.put(
+                IoTDBv2CommonOptions.NODE_URLS.key(), 
Collections.singletonList("127.0.0.1:6667"));
+        config.put(IoTDBv2CommonOptions.USERNAME.key(), "root");
+        config.put(IoTDBv2CommonOptions.PASSWORD.key(), "root");
+        return config;
     }
 }

Reply via email to