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

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


The following commit(s) were added to refs/heads/master by this push:
     new ea9c85c26a3 Refine MCP architecture boundary and sharding request 
merge (#39036)
ea9c85c26a3 is described below

commit ea9c85c26a3b6773b574f6f5e8ac8a44dceae0ce
Author: Liang Zhang <[email protected]>
AuthorDate: Tue Jul 7 20:05:10 2026 +0800

    Refine MCP architecture boundary and sharding request merge (#39036)
    
    - cover all MCP feature packages in the generic module boundary test
    - preserve generic workflow request fields when merging sharding requests
    - reuse descriptor resource swap construction for fixed and template 
resources
---
 .../core/workflow/WorkflowProxyQueryService.java   |   4 +-
 .../capability/MCPDatabaseCapabilityOption.java    |  61 ++++++++
 .../database/capability/MCPDatabaseDialect.java    | 160 +++++++++++++++++++++
 .../ClickHouseMCPDatabaseCapabilityOption.java     |   8 ++
 .../FirebirdMCPDatabaseCapabilityOption.java       |  17 +++
 .../dialect/HiveMCPDatabaseCapabilityOption.java   |  14 ++
 .../MariaDBMCPDatabaseCapabilityOption.java        |  35 +++++
 .../dialect/MySQLMCPDatabaseCapabilityOption.java  |  26 ++++
 .../OpenGaussMCPDatabaseCapabilityOption.java      |  34 +++++
 .../dialect/OracleMCPDatabaseCapabilityOption.java |  16 +++
 .../PostgreSQLMCPDatabaseCapabilityOption.java     |  34 +++++
 .../dialect/PrestoMCPDatabaseCapabilityOption.java |   8 ++
 .../SQLServerMCPDatabaseCapabilityOption.java      |  23 +++
 .../metadata/jdbc/MCPJdbcMetadataLoader.java       |  78 ++--------
 .../support/workflow/service/WorkflowSQLUtils.java |  70 +++------
 .../service/WorkflowValidationSupport.java         |  10 --
 .../capability/MCPDatabaseDialectTest.java         | 147 +++++++++++++++++++
 .../jdbc/AbstractMCPJdbcMetadataLoaderTest.java    |  17 +--
 .../workflow/service/WorkflowSQLUtilsTest.java     |  17 ++-
 .../service/WorkflowValidationSupportTest.java     |   4 +-
 20 files changed, 641 insertions(+), 142 deletions(-)

diff --git 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowProxyQueryService.java
 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowProxyQueryService.java
index a7b42b97770..47ca1992957 100644
--- 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowProxyQueryService.java
+++ 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowProxyQueryService.java
@@ -23,6 +23,7 @@ import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPUnavailableExcept
 import org.apache.shardingsphere.mcp.core.session.MCPSessionManager;
 import 
org.apache.shardingsphere.mcp.support.database.capability.MCPDatabaseCapability;
 import 
org.apache.shardingsphere.mcp.support.database.capability.MCPDatabaseCapabilityProvider;
+import 
org.apache.shardingsphere.mcp.support.database.capability.MCPDatabaseDialect;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConfiguration;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowSQLUtils;
@@ -147,8 +148,7 @@ public final class WorkflowProxyQueryService implements 
MCPFeatureQueryFacade {
             return false;
         }
         String databaseType = 
databaseCapabilityProvider.provide(databaseName).map(MCPDatabaseCapability::getDatabaseType).orElse("");
-        return "MySQL".equalsIgnoreCase(databaseType) || 
"MariaDB".equalsIgnoreCase(databaseType)
-                || "PostgreSQL".equalsIgnoreCase(databaseType) || 
"openGauss".equalsIgnoreCase(databaseType);
+        return 
MCPDatabaseDialect.of(databaseType).isInformationSchemaColumnSchemaFilterRequired();
     }
     
     private Connection openConnection(final String databaseName) throws 
SQLException {
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityOption.java
index f51155d9d8b..df833532134 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityOption.java
@@ -17,9 +17,16 @@
 
 package org.apache.shardingsphere.mcp.support.database.capability;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
 import org.apache.shardingsphere.infra.spi.annotation.SingletonSPI;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPI;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
 /**
  * MCP database capability option.
  */
@@ -76,6 +83,60 @@ public interface MCPDatabaseCapabilityOption extends 
TypedSPI {
      */
     boolean isSequenceSupported();
     
+    /**
+     * Get identifier quote character.
+     *
+     * @return identifier quote character
+     */
+    default QuoteCharacter getIdentifierQuoteCharacter() {
+        return QuoteCharacter.QUOTE;
+    }
+    
+    /**
+     * Get identifier case policy set.
+     *
+     * @return identifier case policy set
+     */
+    default IdentifierCasePolicySet getIdentifierCasePolicySet() {
+        return IdentifierCasePolicyFactory.newSensitivePolicySet();
+    }
+    
+    /**
+     * Judge whether unquoted identifiers are folded by database metadata 
lookup.
+     *
+     * @return whether unquoted identifiers are folded
+     */
+    default boolean isUnquotedIdentifierCaseFolded() {
+        return false;
+    }
+    
+    /**
+     * Get system schemas.
+     *
+     * @return system schemas
+     */
+    default Collection<String> getSystemSchemas() {
+        return List.of();
+    }
+    
+    /**
+     * Get sequence metadata query.
+     *
+     * @return sequence metadata query
+     */
+    default Optional<String> getSequenceQuery() {
+        return Optional.empty();
+    }
+    
+    /**
+     * Judge whether information_schema column lookup should filter 
table_schema.
+     *
+     * @return whether information_schema column lookup should filter 
table_schema
+     */
+    default boolean isInformationSchemaColumnSchemaFilterRequired() {
+        return false;
+    }
+    
     @Override
     String getType();
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseDialect.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseDialect.java
new file mode 100644
index 00000000000..be92283c0d8
--- /dev/null
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseDialect.java
@@ -0,0 +1,160 @@
+/*
+ * 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.shardingsphere.mcp.support.database.capability;
+
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicy;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
+import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * MCP database dialect capabilities.
+ */
+public final class MCPDatabaseDialect {
+    
+    private static final Collection<String> LEGACY_SYSTEM_SCHEMAS = List.of(
+            "information_schema", "mysql", "performance_schema", "pg_catalog", 
"shardingsphere", "sys", "system_lobs");
+    
+    private final String databaseType;
+    
+    private final Optional<MCPDatabaseCapabilityOption> option;
+    
+    private MCPDatabaseDialect(final String databaseType, final 
Optional<MCPDatabaseCapabilityOption> option) {
+        this.databaseType = databaseType;
+        this.option = option;
+    }
+    
+    /**
+     * Create MCP database dialect capabilities.
+     *
+     * @param databaseType database type
+     * @return MCP database dialect capabilities
+     */
+    public static MCPDatabaseDialect of(final String databaseType) {
+        String actualDatabaseType = trimToEmpty(databaseType);
+        Optional<MCPDatabaseCapabilityOption> option = 
actualDatabaseType.isEmpty()
+                ? Optional.empty()
+                : 
TypedSPILoader.findService(MCPDatabaseCapabilityOption.class, 
actualDatabaseType);
+        return new MCPDatabaseDialect(actualDatabaseType, option);
+    }
+    
+    /**
+     * Get identifier quote character.
+     *
+     * @return identifier quote character
+     */
+    public QuoteCharacter getIdentifierQuoteCharacter() {
+        return 
option.map(MCPDatabaseCapabilityOption::getIdentifierQuoteCharacter).orElseGet(this::getFallbackIdentifierQuoteCharacter);
+    }
+    
+    /**
+     * Get identifier case policy.
+     *
+     * @param identifierScope identifier scope
+     * @return identifier case policy
+     */
+    public IdentifierCasePolicy getIdentifierCasePolicy(final IdentifierScope 
identifierScope) {
+        return 
option.map(MCPDatabaseCapabilityOption::getIdentifierCasePolicySet)
+                
.orElseGet(IdentifierCasePolicyFactory::newSensitivePolicySet).getPolicy(identifierScope);
+    }
+    
+    /**
+     * Get default schema semantics.
+     *
+     * @return default schema semantics
+     */
+    public SchemaSemantics getDefaultSchemaSemantics() {
+        return 
option.map(MCPDatabaseCapabilityOption::getDefaultSchemaSemantics).orElse(SchemaSemantics.NATIVE_SCHEMA);
+    }
+    
+    /**
+     * Judge whether unquoted identifiers are folded by database metadata 
lookup.
+     *
+     * @return whether unquoted identifiers are folded
+     */
+    public boolean isUnquotedIdentifierCaseFolded() {
+        return 
option.map(MCPDatabaseCapabilityOption::isUnquotedIdentifierCaseFolded).orElse(false);
+    }
+    
+    /**
+     * Get sequence metadata query.
+     *
+     * @return sequence metadata query
+     */
+    public Optional<String> getSequenceQuery() {
+        return option.flatMap(MCPDatabaseCapabilityOption::getSequenceQuery);
+    }
+    
+    /**
+     * Judge whether information_schema column lookup should filter 
table_schema.
+     *
+     * @return whether information_schema column lookup should filter 
table_schema
+     */
+    public boolean isInformationSchemaColumnSchemaFilterRequired() {
+        return 
option.map(MCPDatabaseCapabilityOption::isInformationSchemaColumnSchemaFilterRequired).orElse(false);
+    }
+    
+    /**
+     * Judge whether schema is a system schema.
+     *
+     * @param schemaName schema name
+     * @return whether schema is a system schema
+     */
+    public boolean isSystemSchema(final String schemaName) {
+        String actualSchemaName = trimToEmpty(schemaName);
+        if (actualSchemaName.isEmpty()) {
+            return false;
+        }
+        Collection<String> systemSchemas = 
option.map(MCPDatabaseCapabilityOption::getSystemSchemas).orElseGet(List::of);
+        return containsSystemSchema(systemSchemas, actualSchemaName) || 
containsSystemSchema(LEGACY_SYSTEM_SCHEMAS, actualSchemaName);
+    }
+    
+    /**
+     * Judge whether schema or catalog is a system schema.
+     *
+     * @param schemaName schema name
+     * @param catalogName catalog name
+     * @param defaultSchemaSemantics default schema semantics
+     * @return whether schema or catalog is a system schema
+     */
+    public boolean isSystemSchema(final String schemaName, final String 
catalogName, final SchemaSemantics defaultSchemaSemantics) {
+        return isSystemSchema(schemaName) || 
SchemaSemantics.DATABASE_AS_SCHEMA == defaultSchemaSemantics && 
isSystemSchema(catalogName);
+    }
+    
+    private QuoteCharacter getFallbackIdentifierQuoteCharacter() {
+        return databaseType.isEmpty() ? QuoteCharacter.BACK_QUOTE : 
QuoteCharacter.QUOTE;
+    }
+    
+    private static boolean containsSystemSchema(final Collection<String> 
systemSchemas, final String schemaName) {
+        for (String each : systemSchemas) {
+            if (schemaName.equalsIgnoreCase(each)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    private static String trimToEmpty(final String value) {
+        return null == value ? "" : value.trim();
+    }
+}
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/ClickHouseMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/ClickHouseMCPDatabaseCapabilityOption.java
index 5a7f9c01ad6..42e58afaac6 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/ClickHouseMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/ClickHouseMCPDatabaseCapabilityOption.java
@@ -21,6 +21,9 @@ import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecution
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+
 /**
  * MCP database capability option for ClickHouse.
  */
@@ -29,4 +32,9 @@ public final class ClickHouseMCPDatabaseCapabilityOption 
extends AbstractMCPData
     public ClickHouseMCPDatabaseCapabilityOption() {
         super("ClickHouse", TransactionCapability.NONE, false, 
SchemaSemantics.DATABASE_AS_SCHEMA, SchemaExecutionSemantics.FIXED_TO_DATABASE, 
false, false);
     }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("information_schema");
+    }
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/FirebirdMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/FirebirdMCPDatabaseCapabilityOption.java
index 1a91af22408..6b3de8ff60f 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/FirebirdMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/FirebirdMCPDatabaseCapabilityOption.java
@@ -21,13 +21,30 @@ import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecution
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
 /**
  * MCP database capability option for Firebird.
  */
 public final class FirebirdMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCapabilityOption {
     
+    private static final String SEQUENCE_QUERY =
+            "SELECT '' AS SEQUENCE_SCHEMA, TRIM(RDB$GENERATOR_NAME) AS 
SEQUENCE_NAME FROM RDB$GENERATORS WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0";
+    
     public FirebirdMCPDatabaseCapabilityOption() {
         super("Firebird", TransactionCapability.LOCAL_WITH_SAVEPOINT, true,
                 SchemaSemantics.NATIVE_SCHEMA, 
SchemaExecutionSemantics.BEST_EFFORT, true, true);
     }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("system_lobs", "system_tables");
+    }
+    
+    @Override
+    public Optional<String> getSequenceQuery() {
+        return Optional.of(SEQUENCE_QUERY);
+    }
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/HiveMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/HiveMCPDatabaseCapabilityOption.java
index 16e4a979a1e..3a1d6667d1b 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/HiveMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/HiveMCPDatabaseCapabilityOption.java
@@ -17,10 +17,14 @@
 
 package org.apache.shardingsphere.mcp.support.database.capability.dialect;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecutionSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+
 /**
  * MCP database capability option for Hive.
  */
@@ -29,4 +33,14 @@ public final class HiveMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCa
     public HiveMCPDatabaseCapabilityOption() {
         super("Hive", TransactionCapability.NONE, false, 
SchemaSemantics.DATABASE_AS_SCHEMA, SchemaExecutionSemantics.FIXED_TO_DATABASE, 
false, false);
     }
+    
+    @Override
+    public QuoteCharacter getIdentifierQuoteCharacter() {
+        return QuoteCharacter.BACK_QUOTE;
+    }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("information_schema", "sys");
+    }
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/MariaDBMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/MariaDBMCPDatabaseCapabilityOption.java
index 39cd4ce4d88..f7c73d5b3e3 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/MariaDBMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/MariaDBMCPDatabaseCapabilityOption.java
@@ -17,17 +17,52 @@
 
 package org.apache.shardingsphere.mcp.support.database.capability.dialect;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecutionSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
 /**
  * MCP database capability option for MariaDB.
  */
 public final class MariaDBMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCapabilityOption {
     
+    private static final String SEQUENCE_QUERY =
+            "SELECT TABLE_SCHEMA AS SEQUENCE_SCHEMA, TABLE_NAME AS 
SEQUENCE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'SEQUENCE'";
+    
     public MariaDBMCPDatabaseCapabilityOption() {
         super("MariaDB", TransactionCapability.LOCAL_WITH_SAVEPOINT, true,
                 SchemaSemantics.DATABASE_AS_SCHEMA, 
SchemaExecutionSemantics.FIXED_TO_DATABASE, false, true);
     }
+    
+    @Override
+    public QuoteCharacter getIdentifierQuoteCharacter() {
+        return QuoteCharacter.BACK_QUOTE;
+    }
+    
+    @Override
+    public IdentifierCasePolicySet getIdentifierCasePolicySet() {
+        return IdentifierCasePolicyFactory.newMySQLInsensitivePolicySet();
+    }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("information_schema", "mysql", "performance_schema", 
"shardingsphere", "sys");
+    }
+    
+    @Override
+    public Optional<String> getSequenceQuery() {
+        return Optional.of(SEQUENCE_QUERY);
+    }
+    
+    @Override
+    public boolean isInformationSchemaColumnSchemaFilterRequired() {
+        return true;
+    }
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/MySQLMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/MySQLMCPDatabaseCapabilityOption.java
index 40e5d27aaff..e49bcbc7b2c 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/MySQLMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/MySQLMCPDatabaseCapabilityOption.java
@@ -17,11 +17,17 @@
 
 package org.apache.shardingsphere.mcp.support.database.capability.dialect;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
 import 
org.apache.shardingsphere.mcp.support.database.capability.DatabaseVersionUtil;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecutionSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+
 /**
  * MCP database capability option for MySQL.
  */
@@ -32,6 +38,26 @@ public final class MySQLMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseC
                 SchemaSemantics.DATABASE_AS_SCHEMA, 
SchemaExecutionSemantics.FIXED_TO_DATABASE, false, false);
     }
     
+    @Override
+    public QuoteCharacter getIdentifierQuoteCharacter() {
+        return QuoteCharacter.BACK_QUOTE;
+    }
+    
+    @Override
+    public IdentifierCasePolicySet getIdentifierCasePolicySet() {
+        return IdentifierCasePolicyFactory.newMySQLInsensitivePolicySet();
+    }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("information_schema", "mysql", "performance_schema", 
"shardingsphere", "sys");
+    }
+    
+    @Override
+    public boolean isInformationSchemaColumnSchemaFilterRequired() {
+        return true;
+    }
+    
     @Override
     public boolean isExplainAnalyzeSupported(final String databaseVersion) {
         return DatabaseVersionUtil.isVersionAtLeast(databaseVersion, 8, 0, 18);
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/OpenGaussMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/OpenGaussMCPDatabaseCapabilityOption.java
index b3954a5c988..51acb294d60 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/OpenGaussMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/OpenGaussMCPDatabaseCapabilityOption.java
@@ -17,20 +17,54 @@
 
 package org.apache.shardingsphere.mcp.support.database.capability.dialect;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecutionSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
 /**
  * MCP database capability option for openGauss.
  */
 public final class OpenGaussMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCapabilityOption {
     
+    private static final String SEQUENCE_QUERY =
+            "SELECT sequence_schema AS SEQUENCE_SCHEMA, sequence_name AS 
SEQUENCE_NAME FROM information_schema.sequences";
+    
     public OpenGaussMCPDatabaseCapabilityOption() {
         super("openGauss", TransactionCapability.LOCAL_WITH_SAVEPOINT, true,
                 SchemaSemantics.NATIVE_SCHEMA, 
SchemaExecutionSemantics.BEST_EFFORT, true, true);
     }
     
+    @Override
+    public IdentifierCasePolicySet getIdentifierCasePolicySet() {
+        return IdentifierCasePolicyFactory.newLowerCasePolicySet();
+    }
+    
+    @Override
+    public boolean isUnquotedIdentifierCaseFolded() {
+        return true;
+    }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("information_schema", "pg_catalog", "shardingsphere");
+    }
+    
+    @Override
+    public Optional<String> getSequenceQuery() {
+        return Optional.of(SEQUENCE_QUERY);
+    }
+    
+    @Override
+    public boolean isInformationSchemaColumnSchemaFilterRequired() {
+        return true;
+    }
+    
     @Override
     public boolean isExplainAnalyzeSupported(final String databaseVersion) {
         return true;
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/OracleMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/OracleMCPDatabaseCapabilityOption.java
index 7a8b0addb9d..86376c36937 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/OracleMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/OracleMCPDatabaseCapabilityOption.java
@@ -21,13 +21,29 @@ import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecution
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
 /**
  * MCP database capability option for Oracle.
  */
 public final class OracleMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCapabilityOption {
     
+    private static final String SEQUENCE_QUERY = "SELECT USER AS 
SEQUENCE_SCHEMA, sequence_name AS SEQUENCE_NAME FROM USER_SEQUENCES";
+    
     public OracleMCPDatabaseCapabilityOption() {
         super("Oracle", TransactionCapability.LOCAL_WITH_SAVEPOINT, true,
                 SchemaSemantics.NATIVE_SCHEMA, 
SchemaExecutionSemantics.BEST_EFFORT, true, true);
     }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("sys", "system_lobs");
+    }
+    
+    @Override
+    public Optional<String> getSequenceQuery() {
+        return Optional.of(SEQUENCE_QUERY);
+    }
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/PostgreSQLMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/PostgreSQLMCPDatabaseCapabilityOption.java
index 8c40f55cc14..f4944824123 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/PostgreSQLMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/PostgreSQLMCPDatabaseCapabilityOption.java
@@ -17,20 +17,54 @@
 
 package org.apache.shardingsphere.mcp.support.database.capability.dialect;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecutionSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
 /**
  * MCP database capability option for PostgreSQL.
  */
 public final class PostgreSQLMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCapabilityOption {
     
+    private static final String SEQUENCE_QUERY =
+            "SELECT sequence_schema AS SEQUENCE_SCHEMA, sequence_name AS 
SEQUENCE_NAME FROM information_schema.sequences";
+    
     public PostgreSQLMCPDatabaseCapabilityOption() {
         super("PostgreSQL", TransactionCapability.LOCAL_WITH_SAVEPOINT, true,
                 SchemaSemantics.NATIVE_SCHEMA, 
SchemaExecutionSemantics.BEST_EFFORT, true, true);
     }
     
+    @Override
+    public IdentifierCasePolicySet getIdentifierCasePolicySet() {
+        return IdentifierCasePolicyFactory.newLowerCasePolicySet();
+    }
+    
+    @Override
+    public boolean isUnquotedIdentifierCaseFolded() {
+        return true;
+    }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("information_schema", "pg_catalog", "shardingsphere");
+    }
+    
+    @Override
+    public Optional<String> getSequenceQuery() {
+        return Optional.of(SEQUENCE_QUERY);
+    }
+    
+    @Override
+    public boolean isInformationSchemaColumnSchemaFilterRequired() {
+        return true;
+    }
+    
     @Override
     public boolean isExplainAnalyzeSupported(final String databaseVersion) {
         return true;
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/PrestoMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/PrestoMCPDatabaseCapabilityOption.java
index 5ec547121df..621d2aff804 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/PrestoMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/PrestoMCPDatabaseCapabilityOption.java
@@ -21,6 +21,9 @@ import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecution
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+
 /**
  * MCP database capability option for Presto.
  */
@@ -30,6 +33,11 @@ public final class PrestoMCPDatabaseCapabilityOption extends 
AbstractMCPDatabase
         super("Presto", TransactionCapability.LOCAL, false, 
SchemaSemantics.NATIVE_SCHEMA, SchemaExecutionSemantics.BEST_EFFORT, true, 
false);
     }
     
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("information_schema");
+    }
+    
     @Override
     public boolean isExplainAnalyzeSupported(final String databaseVersion) {
         return true;
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/SQLServerMCPDatabaseCapabilityOption.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/SQLServerMCPDatabaseCapabilityOption.java
index bb4d3afa089..acae8ac004c 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/SQLServerMCPDatabaseCapabilityOption.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/dialect/SQLServerMCPDatabaseCapabilityOption.java
@@ -17,17 +17,40 @@
 
 package org.apache.shardingsphere.mcp.support.database.capability.dialect;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaExecutionSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.capability.TransactionCapability;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+
 /**
  * MCP database capability option for SQLServer.
  */
 public final class SQLServerMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCapabilityOption {
     
+    private static final String SEQUENCE_QUERY =
+            "SELECT schemas.name AS SEQUENCE_SCHEMA, seq.name AS SEQUENCE_NAME 
FROM sys.sequences seq INNER JOIN sys.schemas schemas ON seq.schema_id = 
schemas.schema_id";
+    
     public SQLServerMCPDatabaseCapabilityOption() {
         super("SQLServer", TransactionCapability.LOCAL_WITH_SAVEPOINT, true,
                 SchemaSemantics.NATIVE_SCHEMA, 
SchemaExecutionSemantics.BEST_EFFORT, true, true);
     }
+    
+    @Override
+    public QuoteCharacter getIdentifierQuoteCharacter() {
+        return QuoteCharacter.BRACKETS;
+    }
+    
+    @Override
+    public Collection<String> getSystemSchemas() {
+        return List.of("information_schema", "sys");
+    }
+    
+    @Override
+    public Optional<String> getSequenceQuery() {
+        return Optional.of(SEQUENCE_QUERY);
+    }
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcMetadataLoader.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcMetadataLoader.java
index 41a5f5f5a8e..1c3b2e62d67 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcMetadataLoader.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcMetadataLoader.java
@@ -19,8 +19,7 @@ package 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc;
 
 import lombok.AccessLevel;
 import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
-import 
org.apache.shardingsphere.mcp.support.database.capability.MCPDatabaseCapabilityOption;
+import 
org.apache.shardingsphere.mcp.support.database.capability.MCPDatabaseDialect;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SchemaSemantics;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.model.MCPColumnMetadata;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.model.MCPDatabaseMetadata;
@@ -39,7 +38,6 @@ import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
@@ -50,22 +48,6 @@ import java.util.Set;
  */
 public final class MCPJdbcMetadataLoader {
     
-    private static final Set<String> SYSTEM_SCHEMAS = 
Set.of("INFORMATION_SCHEMA", "MYSQL", "PERFORMANCE_SCHEMA", "PG_CATALOG", 
"SHARDINGSPHERE", "SYS", "SYSTEM_LOBS");
-    
-    private static final String INFORMATION_SCHEMA_SEQUENCE_QUERY =
-            "SELECT sequence_schema AS SEQUENCE_SCHEMA, sequence_name AS 
SEQUENCE_NAME FROM information_schema.sequences";
-    
-    private static final String SQL_SERVER_SEQUENCE_QUERY =
-            "SELECT schemas.name AS SEQUENCE_SCHEMA, seq.name AS SEQUENCE_NAME 
FROM sys.sequences seq INNER JOIN sys.schemas schemas ON seq.schema_id = 
schemas.schema_id";
-    
-    private static final String ORACLE_SEQUENCE_QUERY = "SELECT USER AS 
SEQUENCE_SCHEMA, sequence_name AS SEQUENCE_NAME FROM USER_SEQUENCES";
-    
-    private static final String MARIADB_SEQUENCE_QUERY =
-            "SELECT TABLE_SCHEMA AS SEQUENCE_SCHEMA, TABLE_NAME AS 
SEQUENCE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'SEQUENCE'";
-    
-    private static final String FIREBIRD_SEQUENCE_QUERY =
-            "SELECT '' AS SEQUENCE_SCHEMA, TRIM(RDB$GENERATOR_NAME) AS 
SEQUENCE_NAME FROM RDB$GENERATORS WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0";
-    
     /**
      * Load database metadata.
      *
@@ -85,21 +67,22 @@ public final class MCPJdbcMetadataLoader {
     
     private MCPDatabaseMetadata loadDatabaseMetadata(final String 
databaseName, final RuntimeDatabaseProfile databaseProfile,
                                                      final Connection 
connection, final DatabaseMetaData databaseMetaData) throws SQLException {
-        SchemaSemantics defaultSchemaSemantics = 
getDefaultSchemaSemantics(databaseProfile.getDatabaseType());
+        MCPDatabaseDialect databaseDialect = 
MCPDatabaseDialect.of(databaseProfile.getDatabaseType());
+        SchemaSemantics defaultSchemaSemantics = 
databaseDialect.getDefaultSchemaSemantics();
         DatabaseMetadataAccumulator accumulator = new 
DatabaseMetadataAccumulator(databaseName, databaseProfile.getDatabaseType(), 
databaseProfile.getDatabaseVersion());
-        loadTables(databaseName, defaultSchemaSemantics, accumulator, 
databaseMetaData);
-        loadViews(databaseName, defaultSchemaSemantics, accumulator, 
databaseMetaData);
-        loadSequences(databaseName, defaultSchemaSemantics, 
databaseProfile.getDatabaseType(), accumulator, connection);
+        loadTables(databaseName, defaultSchemaSemantics, databaseDialect, 
accumulator, databaseMetaData);
+        loadViews(databaseName, defaultSchemaSemantics, databaseDialect, 
accumulator, databaseMetaData);
+        loadSequences(databaseName, defaultSchemaSemantics, databaseDialect, 
accumulator, connection);
         return accumulator.build();
     }
     
-    private void loadTables(final String databaseName, final SchemaSemantics 
defaultSchemaSemantics,
+    private void loadTables(final String databaseName, final SchemaSemantics 
defaultSchemaSemantics, final MCPDatabaseDialect databaseDialect,
                             final DatabaseMetadataAccumulator accumulator, 
final DatabaseMetaData databaseMetaData) throws SQLException {
         try (ResultSet tables = databaseMetaData.getTables(null, null, "%", 
new String[]{"TABLE"})) {
             while (tables.next()) {
                 String schemaName = 
Objects.toString(tables.getString("TABLE_SCHEM"), "").trim();
                 String catalogName = 
Objects.toString(tables.getString("TABLE_CAT"), "").trim();
-                if (isSystemSchema(defaultSchemaSemantics, schemaName, 
catalogName)) {
+                if (databaseDialect.isSystemSchema(schemaName, catalogName, 
defaultSchemaSemantics)) {
                     continue;
                 }
                 String normalizedSchemaName = 
normalizeSchemaName(databaseName, defaultSchemaSemantics, schemaName);
@@ -118,13 +101,13 @@ public final class MCPJdbcMetadataLoader {
         }
     }
     
-    private void loadViews(final String databaseName, final SchemaSemantics 
defaultSchemaSemantics,
+    private void loadViews(final String databaseName, final SchemaSemantics 
defaultSchemaSemantics, final MCPDatabaseDialect databaseDialect,
                            final DatabaseMetadataAccumulator accumulator, 
final DatabaseMetaData databaseMetaData) throws SQLException {
         try (ResultSet views = databaseMetaData.getTables(null, null, "%", new 
String[]{"VIEW"})) {
             while (views.next()) {
                 String schemaName = 
Objects.toString(views.getString("TABLE_SCHEM"), "").trim();
                 String catalogName = 
Objects.toString(views.getString("TABLE_CAT"), "").trim();
-                if (isSystemSchema(defaultSchemaSemantics, schemaName, 
catalogName)) {
+                if (databaseDialect.isSystemSchema(schemaName, catalogName, 
defaultSchemaSemantics)) {
                     continue;
                 }
                 String normalizedSchemaName = 
normalizeSchemaName(databaseName, defaultSchemaSemantics, schemaName);
@@ -140,16 +123,16 @@ public final class MCPJdbcMetadataLoader {
         }
     }
     
-    private void loadSequences(final String databaseName, final 
SchemaSemantics defaultSchemaSemantics, final String databaseType,
+    private void loadSequences(final String databaseName, final 
SchemaSemantics defaultSchemaSemantics, final MCPDatabaseDialect 
databaseDialect,
                                final DatabaseMetadataAccumulator accumulator, 
final Connection connection) throws SQLException {
-        Optional<String> sequenceQuery = getSequenceQuery(databaseType);
+        Optional<String> sequenceQuery = databaseDialect.getSequenceQuery();
         if (sequenceQuery.isEmpty()) {
             return;
         }
         try (Statement statement = connection.createStatement(); ResultSet 
sequences = statement.executeQuery(sequenceQuery.get())) {
             while (sequences.next()) {
                 String schemaName = 
Objects.toString(sequences.getString("SEQUENCE_SCHEMA"), "").trim();
-                if (isSystemSchema(schemaName)) {
+                if (databaseDialect.isSystemSchema(schemaName)) {
                     continue;
                 }
                 String normalizedSchemaName = 
normalizeSchemaName(databaseName, defaultSchemaSemantics, schemaName);
@@ -161,35 +144,6 @@ public final class MCPJdbcMetadataLoader {
         }
     }
     
-    private Optional<String> getSequenceQuery(final String databaseType) {
-        if (null == databaseType || databaseType.isBlank()) {
-            return Optional.empty();
-        }
-        switch (databaseType.toUpperCase(Locale.ENGLISH)) {
-            case "POSTGRESQL":
-            case "OPENGAUSS":
-                return Optional.of(INFORMATION_SCHEMA_SEQUENCE_QUERY);
-            case "SQLSERVER":
-                return Optional.of(SQL_SERVER_SEQUENCE_QUERY);
-            case "ORACLE":
-                return Optional.of(ORACLE_SEQUENCE_QUERY);
-            case "MARIADB":
-                return Optional.of(MARIADB_SEQUENCE_QUERY);
-            case "FIREBIRD":
-                return Optional.of(FIREBIRD_SEQUENCE_QUERY);
-            default:
-                return Optional.empty();
-        }
-    }
-    
-    private boolean isSystemSchema(final String schemaName) {
-        return SYSTEM_SCHEMAS.contains(schemaName.toUpperCase(Locale.ENGLISH));
-    }
-    
-    private boolean isSystemSchema(final SchemaSemantics 
defaultSchemaSemantics, final String schemaName, final String catalogName) {
-        return isSystemSchema(schemaName) || 
SchemaSemantics.DATABASE_AS_SCHEMA == defaultSchemaSemantics && 
isSystemSchema(catalogName);
-    }
-    
     private List<String> loadColumns(final DatabaseMetaData databaseMetaData, 
final String catalogName, final String schemaName, final String objectName) 
throws SQLException {
         List<String> result = new LinkedList<>();
         try (ResultSet columns = 
databaseMetaData.getColumns(getPattern(catalogName), getPattern(schemaName), 
objectName, "%")) {
@@ -222,12 +176,6 @@ public final class MCPJdbcMetadataLoader {
         return result.isEmpty() ? null : result;
     }
     
-    private SchemaSemantics getDefaultSchemaSemantics(final String 
databaseType) {
-        return TypedSPILoader.findService(MCPDatabaseCapabilityOption.class, 
databaseType)
-                .map(MCPDatabaseCapabilityOption::getDefaultSchemaSemantics)
-                .orElse(SchemaSemantics.NATIVE_SCHEMA);
-    }
-    
     private String normalizeSchemaName(final String databaseName, final 
SchemaSemantics defaultSchemaSemantics, final String schemaName) {
         String result = Objects.toString(schemaName, "").trim();
         if (!result.isEmpty()) {
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSQLUtils.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSQLUtils.java
index 159369bb4aa..dce598d0e92 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSQLUtils.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSQLUtils.java
@@ -19,8 +19,12 @@ package 
org.apache.shardingsphere.mcp.support.workflow.service;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicy;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
 import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPInvalidRequestException;
+import 
org.apache.shardingsphere.mcp.support.database.capability.MCPDatabaseDialect;
 
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -81,8 +85,12 @@ public final class WorkflowSQLUtils {
     public static String canonicalizeIdentifier(final String databaseType, 
final String identifier) {
         String rawIdentifier = trimToEmpty(identifier);
         String result = normalizeIdentifier(rawIdentifier);
-        return !isDelimitedIdentifier(rawIdentifier) && 
isLowerCaseFoldedIdentifierDatabase(databaseType) && 
!isSpecialSQLIdentifier(result)
-                ? result.toLowerCase(Locale.ENGLISH)
+        if (isDelimitedIdentifier(rawIdentifier) || 
isSpecialSQLIdentifier(result)) {
+            return result;
+        }
+        MCPDatabaseDialect databaseDialect = 
MCPDatabaseDialect.of(databaseType);
+        return databaseDialect.isUnquotedIdentifierCaseFolded()
+                ? 
databaseDialect.getIdentifierCasePolicy(IdentifierScope.TABLE).normalize(result)
                 : result;
     }
     
@@ -122,7 +130,7 @@ public final class WorkflowSQLUtils {
         checkSupportedIdentifier("identifier", actualIdentifier);
         return actualIdentifier.isEmpty() || 
!isSpecialDistSQLIdentifier(actualIdentifier) && 
!isDelimitedIdentifier(rawIdentifier)
                 ? actualIdentifier
-                : IdentifierQuoteStyle.BACK_QUOTE.wrap(actualIdentifier);
+                : wrapIdentifier(QuoteCharacter.BACK_QUOTE, actualIdentifier);
     }
     
     /**
@@ -134,7 +142,7 @@ public final class WorkflowSQLUtils {
     public static String formatGeneratedRuleDistSQLIdentifier(final String 
identifier) {
         String actualIdentifier = normalizeIdentifier(trimToEmpty(identifier));
         checkSupportedIdentifier("identifier", actualIdentifier);
-        return actualIdentifier.isEmpty() ? actualIdentifier : 
IdentifierQuoteStyle.BACK_QUOTE.wrap(actualIdentifier);
+        return actualIdentifier.isEmpty() ? actualIdentifier : 
wrapIdentifier(QuoteCharacter.BACK_QUOTE, actualIdentifier);
     }
     
     /**
@@ -150,7 +158,7 @@ public final class WorkflowSQLUtils {
         checkSupportedIdentifier("identifier", actualIdentifier);
         return actualIdentifier.isEmpty() || 
!isSpecialSQLIdentifier(actualIdentifier) && 
!isDelimitedIdentifier(rawIdentifier)
                 ? actualIdentifier
-                : 
getSQLIdentifierQuoteStyle(databaseType).wrap(actualIdentifier);
+                : 
wrapIdentifier(MCPDatabaseDialect.of(databaseType).getIdentifierQuoteCharacter(),
 actualIdentifier);
     }
     
     /**
@@ -164,12 +172,8 @@ public final class WorkflowSQLUtils {
     public static boolean isSameIdentifier(final String databaseType, final 
String identifier, final String existingIdentifier) {
         String actualIdentifier = normalizeIdentifier(identifier);
         String actualExistingIdentifier = 
normalizeIdentifier(existingIdentifier);
-        if (isCaseInsensitiveIdentifierDatabase(databaseType)) {
-            return actualIdentifier.equalsIgnoreCase(actualExistingIdentifier);
-        }
-        return isLowerCaseFoldedIdentifierDatabase(databaseType)
-                ? canonicalizeIdentifier(databaseType, 
identifier).equals(actualExistingIdentifier)
-                : actualIdentifier.equals(actualExistingIdentifier);
+        IdentifierCasePolicy identifierCasePolicy = 
MCPDatabaseDialect.of(databaseType).getIdentifierCasePolicy(IdentifierScope.TABLE);
+        return identifierCasePolicy.matches(actualExistingIdentifier, 
actualIdentifier, getQuoteCharacter(identifier));
     }
     
     /**
@@ -294,44 +298,16 @@ public final class WorkflowSQLUtils {
         return !identifier.matches(UNQUOTED_IDENTIFIER_PATTERN);
     }
     
-    private static boolean isCaseInsensitiveIdentifierDatabase(final String 
databaseType) {
-        String actualDatabaseType = 
trimToEmpty(databaseType).toLowerCase(Locale.ENGLISH);
-        return "mysql".equals(actualDatabaseType) || 
"mariadb".equals(actualDatabaseType);
+    private static QuoteCharacter getQuoteCharacter(final String identifier) {
+        String actualIdentifier = trimToEmpty(identifier);
+        return isDelimitedIdentifier(actualIdentifier) ? 
QuoteCharacter.getQuoteCharacter(actualIdentifier) : QuoteCharacter.NONE;
     }
     
-    private static boolean isLowerCaseFoldedIdentifierDatabase(final String 
databaseType) {
-        String actualDatabaseType = 
trimToEmpty(databaseType).toLowerCase(Locale.ENGLISH);
-        return "postgresql".equals(actualDatabaseType) || 
"opengauss".equals(actualDatabaseType);
-    }
-    
-    private static IdentifierQuoteStyle getSQLIdentifierQuoteStyle(final 
String databaseType) {
-        String actualDatabaseType = 
trimToEmpty(databaseType).toLowerCase(Locale.ENGLISH);
-        if (actualDatabaseType.isEmpty() || "mysql".equals(actualDatabaseType) 
|| "mariadb".equals(actualDatabaseType) || "hive".equals(actualDatabaseType)) {
-            return IdentifierQuoteStyle.BACK_QUOTE;
-        }
-        return "sqlserver".equals(actualDatabaseType) ? 
IdentifierQuoteStyle.BRACKETS : IdentifierQuoteStyle.DOUBLE_QUOTE;
-    }
-    
-    private enum IdentifierQuoteStyle {
-        
-        BACK_QUOTE("`", "`"),
-        
-        DOUBLE_QUOTE("\"", "\""),
-        
-        BRACKETS("[", "]");
-        
-        private final String startDelimiter;
-        
-        private final String endDelimiter;
-        
-        IdentifierQuoteStyle(final String startDelimiter, final String 
endDelimiter) {
-            this.startDelimiter = startDelimiter;
-            this.endDelimiter = endDelimiter;
-        }
-        
-        private String wrap(final String value) {
-            return startDelimiter + value.replace(endDelimiter, endDelimiter + 
endDelimiter) + endDelimiter;
-        }
+    private static String wrapIdentifier(final QuoteCharacter quoteCharacter, 
final String value) {
+        return QuoteCharacter.NONE == quoteCharacter
+                ? value
+                : quoteCharacter.getStartDelimiter() + 
value.replace(quoteCharacter.getEndDelimiter(), 
quoteCharacter.getEndDelimiter() + quoteCharacter.getEndDelimiter())
+                        + quoteCharacter.getEndDelimiter();
     }
     
     private static Map<String, String> parsePropertyString(final String value) 
{
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowValidationSupport.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowValidationSupport.java
index 93130497533..b412bdd8782 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowValidationSupport.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowValidationSupport.java
@@ -95,16 +95,6 @@ public final class WorkflowValidationSupport {
         return WorkflowLifecycle.STATUS_PASSED;
     }
     
-    /**
-     * Create the baseline projection SQL used by workflow validation.
-     *
-     * @param snapshot workflow snapshot
-     * @return projection validation SQL
-     */
-    public String createProjectionValidationSql(final WorkflowContextSnapshot 
snapshot) {
-        return createProjectionValidationSql(snapshot, "MySQL");
-    }
-    
     /**
      * Create the baseline projection SQL used by workflow validation.
      *
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseDialectTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseDialectTest.java
new file mode 100644
index 00000000000..dc1a75b0923
--- /dev/null
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseDialectTest.java
@@ -0,0 +1,147 @@
+/*
+ * 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.shardingsphere.mcp.support.database.capability;
+
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicy;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.util.stream.Stream;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class MCPDatabaseDialectTest {
+    
+    @Test
+    void assertOf() {
+        MCPDatabaseDialect actual = MCPDatabaseDialect.of("");
+        assertThat(actual.getIdentifierQuoteCharacter(), 
is(QuoteCharacter.BACK_QUOTE));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("getIdentifierQuoteCharacterArguments")
+    void assertGetIdentifierQuoteCharacter(final String name, final String 
databaseType, final QuoteCharacter expected) {
+        QuoteCharacter actual = 
MCPDatabaseDialect.of(databaseType).getIdentifierQuoteCharacter();
+        assertThat(actual, is(expected));
+    }
+    
+    @Test
+    void assertGetIdentifierCasePolicyWithCaseInsensitiveIdentifier() {
+        IdentifierCasePolicy actual = 
MCPDatabaseDialect.of("MySQL").getIdentifierCasePolicy(IdentifierScope.TABLE);
+        assertTrue(actual.matches("phone", "Phone", QuoteCharacter.QUOTE));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("getDefaultSchemaSemanticsArguments")
+    void assertGetDefaultSchemaSemantics(final String name, final String 
databaseType, final SchemaSemantics expected) {
+        SchemaSemantics actual = 
MCPDatabaseDialect.of(databaseType).getDefaultSchemaSemantics();
+        assertThat(actual, is(expected));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("isUnquotedIdentifierCaseFoldedArguments")
+    void assertIsUnquotedIdentifierCaseFolded(final String name, final String 
databaseType, final boolean expected) {
+        boolean actual = 
MCPDatabaseDialect.of(databaseType).isUnquotedIdentifierCaseFolded();
+        assertThat(actual, is(expected));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("getSequenceQueryArguments")
+    void assertGetSequenceQuery(final String name, final String databaseType, 
final String expected) {
+        String actual = 
MCPDatabaseDialect.of(databaseType).getSequenceQuery().orElse("");
+        assertThat(actual, is(expected));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("isInformationSchemaColumnSchemaFilterRequiredArguments")
+    void assertIsInformationSchemaColumnSchemaFilterRequired(final String 
name, final String databaseType, final boolean expected) {
+        boolean actual = 
MCPDatabaseDialect.of(databaseType).isInformationSchemaColumnSchemaFilterRequired();
+        assertThat(actual, is(expected));
+    }
+    
+    @Test
+    void assertIsSystemSchema() {
+        boolean actual = 
MCPDatabaseDialect.of("PostgreSQL").isSystemSchema("PG_CATALOG");
+        assertTrue(actual);
+    }
+    
+    @Test
+    void assertIsSystemSchemaWithCatalog() {
+        boolean actual = MCPDatabaseDialect.of("MySQL").isSystemSchema("", 
"information_schema", SchemaSemantics.DATABASE_AS_SCHEMA);
+        assertTrue(actual);
+    }
+    
+    @Test
+    void assertIsSystemSchemaWithUserSchema() {
+        boolean actual = 
MCPDatabaseDialect.of("MySQL").isSystemSchema("orders");
+        assertFalse(actual);
+    }
+    
+    @Test
+    void assertIsSystemSchemaWithUnknownDatabaseType() {
+        boolean actual = 
MCPDatabaseDialect.of("FixtureDB").isSystemSchema("INFORMATION_SCHEMA");
+        assertTrue(actual);
+    }
+    
+    private static Stream<Arguments> getIdentifierQuoteCharacterArguments() {
+        return Stream.of(
+                Arguments.of("mysql", "MySQL", QuoteCharacter.BACK_QUOTE),
+                Arguments.of("hive", "Hive", QuoteCharacter.BACK_QUOTE),
+                Arguments.of("sql server", "SQLServer", 
QuoteCharacter.BRACKETS),
+                Arguments.of("postgresql", "PostgreSQL", QuoteCharacter.QUOTE),
+                Arguments.of("unknown", "FixtureDB", QuoteCharacter.QUOTE));
+    }
+    
+    private static Stream<Arguments> isUnquotedIdentifierCaseFoldedArguments() 
{
+        return Stream.of(
+                Arguments.of("postgresql", "PostgreSQL", true),
+                Arguments.of("open gauss", "openGauss", true),
+                Arguments.of("mysql", "MySQL", false),
+                Arguments.of("unknown", "FixtureDB", false));
+    }
+    
+    private static Stream<Arguments> getDefaultSchemaSemanticsArguments() {
+        return Stream.of(
+                Arguments.of("mysql", "MySQL", 
SchemaSemantics.DATABASE_AS_SCHEMA),
+                Arguments.of("postgresql", "PostgreSQL", 
SchemaSemantics.NATIVE_SCHEMA),
+                Arguments.of("unknown", "FixtureDB", 
SchemaSemantics.NATIVE_SCHEMA));
+    }
+    
+    private static Stream<Arguments> getSequenceQueryArguments() {
+        return Stream.of(
+                Arguments.of("postgresql", "PostgreSQL", "SELECT 
sequence_schema AS SEQUENCE_SCHEMA, sequence_name AS SEQUENCE_NAME FROM 
information_schema.sequences"),
+                Arguments.of("sql server", "SQLServer",
+                        "SELECT schemas.name AS SEQUENCE_SCHEMA, seq.name AS 
SEQUENCE_NAME FROM sys.sequences seq INNER JOIN sys.schemas schemas ON 
seq.schema_id = schemas.schema_id"),
+                Arguments.of("mysql", "MySQL", ""));
+    }
+    
+    private static Stream<Arguments> 
isInformationSchemaColumnSchemaFilterRequiredArguments() {
+        return Stream.of(
+                Arguments.of("mysql", "MySQL", true),
+                Arguments.of("postgresql", "PostgreSQL", true),
+                Arguments.of("sql server", "SQLServer", false),
+                Arguments.of("unknown", "FixtureDB", false));
+    }
+}
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/AbstractMCPJdbcMetadataLoaderTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/AbstractMCPJdbcMetadataLoaderTest.java
index 0c025bd7af2..51d49d4f9b3 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/AbstractMCPJdbcMetadataLoaderTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/AbstractMCPJdbcMetadataLoaderTest.java
@@ -22,6 +22,7 @@ import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import 
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeFactory;
+import 
org.apache.shardingsphere.mcp.support.database.capability.MCPDatabaseDialect;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SupportedMCPMetadataObjectType;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.model.MCPColumnMetadata;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.model.MCPDatabaseMetadata;
@@ -251,21 +252,7 @@ abstract class AbstractMCPJdbcMetadataLoaderTest {
     }
     
     protected String getSequenceQuery(final String databaseType) {
-        switch (databaseType) {
-            case "PostgreSQL":
-            case "openGauss":
-                return "SELECT sequence_schema AS SEQUENCE_SCHEMA, 
sequence_name AS SEQUENCE_NAME FROM information_schema.sequences";
-            case "SQLServer":
-                return "SELECT schemas.name AS SEQUENCE_SCHEMA, seq.name AS 
SEQUENCE_NAME FROM sys.sequences seq INNER JOIN sys.schemas schemas ON 
seq.schema_id = schemas.schema_id";
-            case "Oracle":
-                return "SELECT USER AS SEQUENCE_SCHEMA, sequence_name AS 
SEQUENCE_NAME FROM USER_SEQUENCES";
-            case "MariaDB":
-                return "SELECT TABLE_SCHEMA AS SEQUENCE_SCHEMA, TABLE_NAME AS 
SEQUENCE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'SEQUENCE'";
-            case "Firebird":
-                return "SELECT '' AS SEQUENCE_SCHEMA, TRIM(RDB$GENERATOR_NAME) 
AS SEQUENCE_NAME FROM RDB$GENERATORS WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0";
-            default:
-                return "";
-        }
+        return 
MCPDatabaseDialect.of(databaseType).getSequenceQuery().orElse("");
     }
     
     protected ResultSet mockResultSet(final String columnName, final String... 
values) throws SQLException {
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSQLUtilsTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSQLUtilsTest.java
index 4ad58fde79c..eae4d10de2e 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSQLUtilsTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSQLUtilsTest.java
@@ -70,6 +70,11 @@ class WorkflowSQLUtilsTest {
         assertThat(WorkflowSQLUtils.canonicalizeIdentifier("openGauss", 
"Phone"), is("phone"));
     }
     
+    @Test
+    void assertCanonicalizeIdentifierKeepsMySQLUnquotedIdentifier() {
+        assertThat(WorkflowSQLUtils.canonicalizeIdentifier("MySQL", "Phone"), 
is("Phone"));
+    }
+    
     @Test
     void assertCanonicalizeIdentifierPreservesSpecialIdentifier() {
         assertThat(WorkflowSQLUtils.canonicalizeIdentifier("PostgreSQL", 
"Phone Number"), is("Phone Number"));
@@ -184,6 +189,12 @@ class WorkflowSQLUtilsTest {
         assertThat(actualValue, is("\"order detail\""));
     }
     
+    @Test
+    void assertFormatSQLIdentifierUsesSQLServerQuoteStyle() {
+        String actualValue = WorkflowSQLUtils.formatSQLIdentifier("SQLServer", 
"order detail");
+        assertThat(actualValue, is("[order detail]"));
+    }
+    
     @Test
     void assertFormatSQLIdentifierPreservesDelimitedSafeIdentifier() {
         String actualValue = 
WorkflowSQLUtils.formatSQLIdentifier("PostgreSQL", "\"orders\"");
@@ -206,8 +217,12 @@ class WorkflowSQLUtilsTest {
     }
     
     @Test
-    void 
assertIsSameIdentifierKeepsPostgreSQLExistingQuotedIdentifierDistinct() {
+    void assertIsSameIdentifierRejectsUnquotedPostgreSQLQuotedName() {
         assertFalse(WorkflowSQLUtils.isSameIdentifier("PostgreSQL", "Phone", 
"Phone"));
+    }
+    
+    @Test
+    void assertIsSameIdentifierMatchesQuotedPostgreSQLName() {
         assertTrue(WorkflowSQLUtils.isSameIdentifier("PostgreSQL", 
"\"Phone\"", "Phone"));
     }
     
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowValidationSupportTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowValidationSupportTest.java
index 341fcfc7737..9069ae36af6 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowValidationSupportTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowValidationSupportTest.java
@@ -123,7 +123,7 @@ class WorkflowValidationSupportTest {
     
     @Test
     void assertCreateProjectionValidationSql() {
-        
assertThat(validationSupport.createProjectionValidationSql(createSnapshot()), 
is("SELECT phone FROM orders"));
+        
assertThat(validationSupport.createProjectionValidationSql(createSnapshot(), 
"MySQL"), is("SELECT phone FROM orders"));
     }
     
     @Test
@@ -131,7 +131,7 @@ class WorkflowValidationSupportTest {
         WorkflowContextSnapshot snapshot = createSnapshot();
         snapshot.getRequest().setTable("order detail");
         snapshot.getRequest().setColumn("Phone Number");
-        assertThat(validationSupport.createProjectionValidationSql(snapshot), 
is("SELECT `Phone Number` FROM `order detail`"));
+        assertThat(validationSupport.createProjectionValidationSql(snapshot, 
"MySQL"), is("SELECT `Phone Number` FROM `order detail`"));
     }
     
     @Test

Reply via email to