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 e638c97826a Refine MCP identifier policies and EXPLAIN support (#39083)
e638c97826a is described below

commit e638c97826ae600f08886da12356b33a97bf2568
Author: Liang Zhang <[email protected]>
AuthorDate: Mon Jul 13 15:15:11 2026 +0800

    Refine MCP identifier policies and EXPLAIN support (#39083)
---
 .../MCPCompletionSpecificationFactoryTest.java     |   5 +-
 .../tool/handler/execute/ClassificationResult.java |  29 +++-
 .../execute/ExplainSQLCandidateValidator.java      |   3 +-
 .../handler/execute/MCPSQLExecutionFacade.java     |  24 ++--
 .../handler/execute/SQLStatementObjectName.java    |  27 ++++
 .../execute/SQLStatementObjectNameReader.java      |  15 ++-
 .../execute/SQLStatementTargetResolver.java        |  62 +++++----
 .../tool/handler/execute/StatementClassifier.java  |   3 +-
 .../core/completion/MCPCompletionServiceTest.java  |   5 +-
 .../provider/MetadataCompletionProviderTest.java   |   5 +-
 .../metadata/MetadataResourceHandlerTest.java      |  10 +-
 .../MetadataResourcePayloadMapperTest.java         |   4 +-
 .../execute/ExplainSQLCandidateValidatorTest.java  |   6 +
 .../handler/execute/MCPSQLExecutionFacadeTest.java |  54 ++++++--
 .../metadata/SearchMetadataPayloadBuilderTest.java |   4 +-
 .../EncryptWorkflowPlanningServiceTest.java        |   3 +-
 .../service/MaskWorkflowPlanningServiceTest.java   |   3 +-
 .../database/capability/MCPDatabaseCapability.java |  10 +-
 .../capability/MCPDatabaseCapabilityProvider.java  |  90 +------------
 .../ClickHouseMCPDatabaseCapabilityOption.java     |   2 +-
 .../dialect/HiveMCPDatabaseCapabilityOption.java   |   2 +-
 .../jdbc/MCPJdbcDatabaseProfileLoader.java         |  92 ++++++++++++-
 .../metadata/jdbc/RuntimeDatabaseProfile.java      |   3 +
 .../service/RuntimeDatabaseValidationService.java  |  42 +++---
 .../MCPDatabaseCapabilityProviderTest.java         | 148 ++++-----------------
 .../jdbc/MCPJdbcDatabaseProfileLoaderTest.java     |  83 +++++++++++-
 .../jdbc/MCPJdbcMetadataLoaderFailureTest.java     |   4 +-
 .../RuntimeDatabaseValidationServiceTest.java      |  36 ++++-
 .../WorkflowPlanningContextValidatorTest.java      |   3 +-
 .../service/WorkflowPlanningSupportTest.java       |   3 +-
 30 files changed, 458 insertions(+), 322 deletions(-)

diff --git 
a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/completion/MCPCompletionSpecificationFactoryTest.java
 
b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/completion/MCPCompletionSpecificationFactoryTest.java
index f19438b2cd1..93239f3ff38 100644
--- 
a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/completion/MCPCompletionSpecificationFactoryTest.java
+++ 
b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/completion/MCPCompletionSpecificationFactoryTest.java
@@ -17,6 +17,7 @@
 
 package 
org.apache.shardingsphere.mcp.bootstrap.transport.capability.completion;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import 
io.modelcontextprotocol.server.McpServerFeatures.SyncCompletionSpecification;
 import io.modelcontextprotocol.server.McpSyncServerExchange;
 import io.modelcontextprotocol.spec.McpError;
@@ -198,8 +199,8 @@ class MCPCompletionSpecificationFactoryTest {
     private MCPRuntimeContext createRuntimeContext(final 
WorkflowSessionContext workflowSessionContext) {
         MCPDatabaseCapabilityProvider databaseCapabilityProvider = 
mock(MCPDatabaseCapabilityProvider.class);
         
when(databaseCapabilityProvider.getDatabaseProfiles()).thenReturn(List.of(
-                new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true),
-                new RuntimeDatabaseProfile("warehouse", "FixtureWarehouseDB", 
"2.0", true, true)));
+                new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet()),
+                new RuntimeDatabaseProfile("warehouse", "FixtureWarehouseDB", 
"2.0", true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet())));
         MCPRuntimeContext result = mock(MCPRuntimeContext.class, 
RETURNS_DEEP_STUBS);
         
when(result.getDatabaseCapabilityProvider()).thenReturn(databaseCapabilityProvider);
         
when(result.getWorkflowSessionContext()).thenReturn(workflowSessionContext);
diff --git 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ClassificationResult.java
 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ClassificationResult.java
index 20a0d471842..f1cf58c8498 100644
--- 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ClassificationResult.java
+++ 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ClassificationResult.java
@@ -17,10 +17,12 @@
 
 package org.apache.shardingsphere.mcp.core.tool.handler.execute;
 
+import lombok.AccessLevel;
 import lombok.Getter;
 import 
org.apache.shardingsphere.mcp.support.database.capability.SupportedMCPStatement;
 
 import java.util.Collection;
+import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Optional;
@@ -51,22 +53,39 @@ public final class ClassificationResult {
     
     private final Collection<String> referencedObjectNames;
     
+    @Getter(AccessLevel.NONE)
+    private final Collection<SQLStatementObjectName> referencedObjects;
+    
     private final String savepointName;
     
     public ClassificationResult(final SupportedMCPStatement statementClass, 
final String statementType, final String normalizedSql, final String 
targetObjectName, final String savepointName) {
-        this(statementClass, statementType, normalizedSql, targetObjectName, 
savepointName, targetObjectName.isEmpty() ? List.of() : 
List.of(targetObjectName));
+        this(statementClass, statementType, normalizedSql, savepointName,
+                targetObjectName.isEmpty() ? List.of() : 
List.of(SQLStatementObjectName.fromNormalizedName(targetObjectName)));
     }
     
-    ClassificationResult(final SupportedMCPStatement statementClass, final 
String statementType, final String normalizedSql, final String 
targetObjectName, final String savepointName,
-                         final Collection<String> referencedObjectNames) {
+    ClassificationResult(final SupportedMCPStatement statementClass, final 
String statementType, final String normalizedSql, final String savepointName,
+                         final Collection<SQLStatementObjectName> 
referencedObjects) {
         this.statementClass = statementClass;
         this.statementType = statementType;
         this.normalizedSql = normalizedSql;
-        this.targetObjectName = targetObjectName;
-        this.referencedObjectNames = referencedObjectNames;
+        targetObjectName = referencedObjects.isEmpty() ? "" : 
referencedObjects.iterator().next().objectName();
+        referencedObjectNames = createReferencedObjectNames(referencedObjects);
+        this.referencedObjects = referencedObjects;
         this.savepointName = savepointName;
     }
     
+    private Collection<String> createReferencedObjectNames(final 
Collection<SQLStatementObjectName> referencedObjects) {
+        Collection<String> result = new 
LinkedHashSet<>(referencedObjects.size(), 1F);
+        for (SQLStatementObjectName each : referencedObjects) {
+            result.add(each.objectName());
+        }
+        return result;
+    }
+    
+    Collection<SQLStatementObjectName> getReferencedObjects() {
+        return referencedObjects;
+    }
+    
     /**
      * Get the target object name when one exists.
      *
diff --git 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExplainSQLCandidateValidator.java
 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExplainSQLCandidateValidator.java
index 1e624dc04e8..faf6024e166 100644
--- 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExplainSQLCandidateValidator.java
+++ 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExplainSQLCandidateValidator.java
@@ -46,8 +46,7 @@ final class ExplainSQLCandidateValidator {
                 () -> new MCPInvalidRequestException("Executable comments are 
not supported by the MCP explain query tool."));
         List<SQLStatementToken> tokens = scanner.tokenize(actualExplainSql);
         checkExplainCandidate(tokens, explainedStatement.getNormalizedSql(), 
actualExplainSql);
-        return new ClassificationResult(SupportedMCPStatement.EXPLAIN, 
"EXPLAIN", actualExplainSql, 
explainedStatement.getTargetObjectName().orElse(""), "",
-                explainedStatement.getReferencedObjectNames());
+        return new ClassificationResult(SupportedMCPStatement.EXPLAIN, 
"EXPLAIN", actualExplainSql, "", explainedStatement.getReferencedObjects());
     }
     
     private void checkExplainCandidate(final List<SQLStatementToken> tokens, 
final String sql, final String explainSql) {
diff --git 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPSQLExecutionFacade.java
 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPSQLExecutionFacade.java
index a0216a082ee..1b8d03dd74a 100644
--- 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPSQLExecutionFacade.java
+++ 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPSQLExecutionFacade.java
@@ -20,6 +20,8 @@ package 
org.apache.shardingsphere.mcp.core.tool.handler.execute;
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
 import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicy;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPInvalidRequestException;
 import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPQueryFailedException;
 import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPUnsupportedException;
@@ -161,24 +163,26 @@ public final class MCPSQLExecutionFacade implements 
MCPFeatureExecutionFacade {
         if (SchemaExecutionSemantics.BEST_EFFORT == 
databaseCapability.getSchemaExecutionSemantics()) {
             return;
         }
-        for (String each : classificationResult.getReferencedObjectNames()) {
-            if (isCrossSchemaReference(each, executionRequest.getDatabase(), 
classificationResult)) {
+        IdentifierCasePolicy identifierCasePolicy = 
databaseCapability.getIdentifierCasePolicySet().getPolicy(IdentifierScope.SCHEMA);
+        for (SQLStatementObjectName each : 
classificationResult.getReferencedObjects()) {
+            if (isCrossSchemaReference(each, executionRequest.getDatabase(), 
classificationResult, identifierCasePolicy)) {
                 throw recordFailure(executionRequest, 
classificationResult.getTraceStatementMarker(), new MCPInvalidRequestException(
-                        String.format("Cross-schema SQL is not supported for 
database `%s`: `%s`.", executionRequest.getDatabase(), each)));
+                        String.format("Cross-schema SQL is not supported for 
database `%s`: `%s`.", executionRequest.getDatabase(), each.objectName())));
             }
         }
     }
     
-    private boolean isCrossSchemaReference(final String objectName, final 
String databaseName, final ClassificationResult classificationResult) {
-        int qualifierSeparatorIndex = objectName.indexOf('.');
-        if (-1 != qualifierSeparatorIndex) {
-            return !objectName.substring(0, 
qualifierSeparatorIndex).equalsIgnoreCase(databaseName);
+    private boolean isCrossSchemaReference(final SQLStatementObjectName 
objectName, final String databaseName, final ClassificationResult 
classificationResult,
+                                           final IdentifierCasePolicy 
identifierCasePolicy) {
+        if (objectName.qualified()) {
+            return !identifierCasePolicy.matches(databaseName, 
objectName.firstIdentifier(), objectName.firstIdentifierQuoteCharacter());
         }
-        return isDatabaseOrSchemaBoundaryReference(objectName, databaseName, 
classificationResult);
+        return isDatabaseOrSchemaBoundaryReference(objectName, databaseName, 
classificationResult, identifierCasePolicy);
     }
     
-    private boolean isDatabaseOrSchemaBoundaryReference(final String 
objectName, final String databaseName, final ClassificationResult 
classificationResult) {
-        if (objectName.equalsIgnoreCase(databaseName)) {
+    private boolean isDatabaseOrSchemaBoundaryReference(final 
SQLStatementObjectName objectName, final String databaseName, final 
ClassificationResult classificationResult,
+                                                        final 
IdentifierCasePolicy identifierCasePolicy) {
+        if (identifierCasePolicy.matches(databaseName, 
objectName.firstIdentifier(), objectName.firstIdentifierQuoteCharacter())) {
             return false;
         }
         String actualSql = classificationResult.getNormalizedSql();
diff --git 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectName.java
 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectName.java
index 3f586cc779e..0f8f97f4bc7 100644
--- 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectName.java
+++ 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectName.java
@@ -19,18 +19,45 @@ package 
org.apache.shardingsphere.mcp.core.tool.handler.execute;
 
 import lombok.AccessLevel;
 import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
 
 @AllArgsConstructor(access = AccessLevel.PACKAGE)
+@EqualsAndHashCode(exclude = "nextIndex")
 final class SQLStatementObjectName {
     
     private final String objectName;
     
+    private final String firstIdentifier;
+    
+    private final QuoteCharacter firstIdentifierQuoteCharacter;
+    
+    private final boolean qualified;
+    
     private final int nextIndex;
     
+    static SQLStatementObjectName fromNormalizedName(final String objectName) {
+        int qualifierSeparatorIndex = objectName.indexOf('.');
+        return new SQLStatementObjectName(objectName, -1 == 
qualifierSeparatorIndex ? objectName : objectName.substring(0, 
qualifierSeparatorIndex),
+                QuoteCharacter.NONE, -1 != qualifierSeparatorIndex, 0);
+    }
+    
     String objectName() {
         return objectName;
     }
     
+    String firstIdentifier() {
+        return firstIdentifier;
+    }
+    
+    QuoteCharacter firstIdentifierQuoteCharacter() {
+        return firstIdentifierQuoteCharacter;
+    }
+    
+    boolean qualified() {
+        return qualified;
+    }
+    
     int nextIndex() {
         return nextIndex;
     }
diff --git 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectNameReader.java
 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectNameReader.java
index 80c7c43b9c3..0a8b64938c1 100644
--- 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectNameReader.java
+++ 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectNameReader.java
@@ -19,6 +19,7 @@ package 
org.apache.shardingsphere.mcp.core.tool.handler.execute;
 
 import lombok.AccessLevel;
 import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.QuoteCharacter;
 
 import java.util.List;
 
@@ -39,24 +40,28 @@ final class SQLStatementObjectNameReader {
                 continue;
             }
             if ("(".equals(token.text())) {
-                return new SQLStatementObjectName("", currentIndex);
+                return new SQLStatementObjectName("", "", QuoteCharacter.NONE, 
false, currentIndex);
             }
             return readQualifiedName(tokens, currentIndex);
         }
-        return new SQLStatementObjectName("", currentIndex);
+        return new SQLStatementObjectName("", "", QuoteCharacter.NONE, false, 
currentIndex);
     }
     
     SQLStatementObjectName readQualifiedName(final List<SQLStatementToken> 
tokens, final int startIndex) {
         if (startIndex >= tokens.size() || 
!isObjectNameSegment(tokens.get(startIndex))) {
-            return new SQLStatementObjectName("", startIndex);
+            return new SQLStatementObjectName("", "", QuoteCharacter.NONE, 
false, startIndex);
         }
-        StringBuilder result = new 
StringBuilder(scanner.normalizeIdentifier(tokens.get(startIndex).text()));
+        SQLStatementToken firstToken = tokens.get(startIndex);
+        String firstIdentifier = 
scanner.normalizeIdentifier(firstToken.text());
+        StringBuilder result = new StringBuilder(firstIdentifier);
         int currentIndex = startIndex + 1;
+        boolean qualified = false;
         while (currentIndex + 1 < tokens.size() && 
".".equals(tokens.get(currentIndex).text()) && 
isObjectNameSegment(tokens.get(currentIndex + 1))) {
             
result.append('.').append(scanner.normalizeIdentifier(tokens.get(currentIndex + 
1).text()));
             currentIndex += 2;
+            qualified = true;
         }
-        return new SQLStatementObjectName(result.toString(), currentIndex);
+        return new SQLStatementObjectName(result.toString(), firstIdentifier, 
QuoteCharacter.getQuoteCharacter(firstToken.text()), qualified, currentIndex);
     }
     
     int skipObjectTail(final List<SQLStatementToken> tokens, final int 
startIndex) {
diff --git 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementTargetResolver.java
 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementTargetResolver.java
index 95fd5652350..5a34c7895b0 100644
--- 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementTargetResolver.java
+++ 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementTargetResolver.java
@@ -43,18 +43,13 @@ final class SQLStatementTargetResolver {
         objectNameReader = new SQLStatementObjectNameReader(scanner);
     }
     
-    String resolve(final SQLStatementStructure statementStructure) {
-        Collection<String> objectNames = resolveAll(statementStructure);
-        return objectNames.isEmpty() ? "" : objectNames.iterator().next();
-    }
-    
-    Collection<String> resolveAll(final SQLStatementStructure 
statementStructure) {
-        Set<String> result = new LinkedHashSet<>(16, 1F);
+    Collection<SQLStatementObjectName> resolveAll(final SQLStatementStructure 
statementStructure) {
+        Set<SQLStatementObjectName> result = new LinkedHashSet<>(16, 1F);
         collect(statementStructure, new LinkedList<>(), result);
         return result;
     }
     
-    private void collect(final SQLStatementStructure statementStructure, final 
Collection<String> visitedAliases, final Collection<String> objectNames) {
+    private void collect(final SQLStatementStructure statementStructure, final 
Collection<String> visitedAliases, final Collection<SQLStatementObjectName> 
objectNames) {
         if ("SELECT".equals(statementStructure.statementType())) {
             collectCommonTableExpressionObjectNames(statementStructure, 
visitedAliases, objectNames);
             collectSelectTargetObjectNames(statementStructure, visitedAliases, 
objectNames);
@@ -65,7 +60,8 @@ final class SQLStatementTargetResolver {
         collectCommonTableExpressionObjectNames(statementStructure, 
visitedAliases, objectNames);
     }
     
-    private void collectCommonTableExpressionObjectNames(final 
SQLStatementStructure statementStructure, final Collection<String> 
visitedAliases, final Collection<String> objectNames) {
+    private void collectCommonTableExpressionObjectNames(final 
SQLStatementStructure statementStructure, final Collection<String> 
visitedAliases,
+                                                         final 
Collection<SQLStatementObjectName> objectNames) {
         for (SQLCommonTableExpression each : 
statementStructure.commonTableExpressions()) {
             String normalizedAliasName = 
scanner.normalizeIdentifierForComparison(each.aliasName());
             if (visitedAliases.contains(normalizedAliasName)) {
@@ -75,11 +71,13 @@ final class SQLStatementTargetResolver {
         }
     }
     
-    private void collectSelectTargetObjectNames(final SQLStatementStructure 
statementStructure, final Collection<String> visitedAliases, final 
Collection<String> objectNames) {
+    private void collectSelectTargetObjectNames(final SQLStatementStructure 
statementStructure, final Collection<String> visitedAliases,
+                                                final 
Collection<SQLStatementObjectName> objectNames) {
         collectClauseObjectNames(statementStructure, visitedAliases, 
objectNames, "FROM", "JOIN");
     }
     
-    private void collectClauseObjectNames(final SQLStatementStructure 
statementStructure, final Collection<String> visitedAliases, final 
Collection<String> objectNames, final String... keywords) {
+    private void collectClauseObjectNames(final SQLStatementStructure 
statementStructure, final Collection<String> visitedAliases,
+                                          final 
Collection<SQLStatementObjectName> objectNames, final String... keywords) {
         List<SQLStatementToken> tokens = 
scanner.tokenize(statementStructure.mainSql());
         for (int each : findKeywordIndexes(tokens, keywords)) {
             collectObjectNamesFromClause(statementStructure, tokens, each, 
visitedAliases, objectNames);
@@ -89,7 +87,7 @@ final class SQLStatementTargetResolver {
     }
     
     private void collectObjectNamesFromClause(final SQLStatementStructure 
statementStructure, final List<SQLStatementToken> tokens, final int 
keywordIndex,
-                                              final Collection<String> 
visitedAliases, final Collection<String> objectNames) {
+                                              final Collection<String> 
visitedAliases, final Collection<SQLStatementObjectName> objectNames) {
         int objectStartIndex = keywordIndex + 1;
         if (scanner.isKeyword(tokens.get(keywordIndex), "INHERITS") && 
objectStartIndex < tokens.size() && 
"(".equals(tokens.get(objectStartIndex).text())) {
             objectStartIndex++;
@@ -97,7 +95,8 @@ final class SQLStatementTargetResolver {
         collectObjectNamesFromList(statementStructure, tokens, 
objectStartIndex, visitedAliases, objectNames, "ONLY", "LATERAL");
     }
     
-    private void collectNestedQueryObjectNames(final List<SQLStatementToken> 
tokens, final Collection<String> visitedAliases, final Collection<String> 
objectNames) {
+    private void collectNestedQueryObjectNames(final List<SQLStatementToken> 
tokens, final Collection<String> visitedAliases,
+                                               final 
Collection<SQLStatementObjectName> objectNames) {
         int index = 0;
         while (index < tokens.size()) {
             if (!"(".equals(tokens.get(index).text())) {
@@ -115,7 +114,8 @@ final class SQLStatementTargetResolver {
         }
     }
     
-    private void collectObjectName(final SQLStatementStructure 
statementStructure, final String objectName, final Collection<String> 
visitedAliases, final Collection<String> objectNames) {
+    private void collectObjectName(final SQLStatementStructure 
statementStructure, final SQLStatementObjectName objectName, final 
Collection<String> visitedAliases,
+                                   final Collection<SQLStatementObjectName> 
objectNames) {
         Optional<SQLCommonTableExpression> commonTableExpression = 
findCommonTableExpression(statementStructure, objectName);
         if (commonTableExpression.isEmpty()) {
             addObjectName(objectNames, objectName);
@@ -128,7 +128,8 @@ final class SQLStatementTargetResolver {
         }
     }
     
-    private void collectDirectTargetObjectNames(final SQLStatementStructure 
statementStructure, final Collection<String> visitedAliases, final 
Collection<String> objectNames) {
+    private void collectDirectTargetObjectNames(final SQLStatementStructure 
statementStructure, final Collection<String> visitedAliases,
+                                                final 
Collection<SQLStatementObjectName> objectNames) {
         List<SQLStatementToken> tokens = 
scanner.tokenize(statementStructure.mainSql());
         String statementType = statementStructure.statementType();
         if ("INSERT".equals(statementType) || "MERGE".equals(statementType)) {
@@ -170,7 +171,7 @@ final class SQLStatementTargetResolver {
     }
     
     private void collectDeleteTargetObjectNames(final SQLStatementStructure 
statementStructure, final List<SQLStatementToken> tokens, final 
Collection<String> visitedAliases,
-                                                final Collection<String> 
objectNames) {
+                                                final 
Collection<SQLStatementObjectName> objectNames) {
         int deleteTargetStartIndex = skipDeleteModifierKeywords(tokens, 1);
         if (deleteTargetStartIndex < tokens.size() && 
!scanner.isKeyword(tokens.get(deleteTargetStartIndex), "FROM", "USING")) {
             collectObjectNamesFromList(statementStructure, tokens, 
deleteTargetStartIndex, visitedAliases, objectNames);
@@ -197,7 +198,7 @@ final class SQLStatementTargetResolver {
     }
     
     private void collectCreateSourceObjectNames(final SQLStatementStructure 
statementStructure, final List<SQLStatementToken> tokens, final 
Collection<String> visitedAliases,
-                                                final Collection<String> 
objectNames) {
+                                                final 
Collection<SQLStatementObjectName> objectNames) {
         if (isStatementObjectType(tokens, "INDEX", "TRIGGER", "POLICY")) {
             collectObjectNamesAfterKeyword(statementStructure, tokens, "ON", 
visitedAliases, objectNames);
         }
@@ -207,14 +208,14 @@ final class SQLStatementTargetResolver {
     }
     
     private void collectDropSourceObjectNames(final SQLStatementStructure 
statementStructure, final List<SQLStatementToken> tokens, final 
Collection<String> visitedAliases,
-                                              final Collection<String> 
objectNames) {
+                                              final 
Collection<SQLStatementObjectName> objectNames) {
         if (isStatementObjectType(tokens, "INDEX")) {
             collectObjectNamesAfterKeyword(statementStructure, tokens, "ON", 
visitedAliases, objectNames);
         }
     }
     
     private void collectAlterDestinationObjectNames(final 
SQLStatementStructure statementStructure, final List<SQLStatementToken> tokens, 
final Collection<String> visitedAliases,
-                                                    final Collection<String> 
objectNames) {
+                                                    final 
Collection<SQLStatementObjectName> objectNames) {
         for (int index = 0; index < tokens.size(); index++) {
             if (isRenameToDestination(tokens, index)) {
                 collectObjectNamesFromList(statementStructure, tokens, index + 
2, visitedAliases, objectNames);
@@ -251,8 +252,11 @@ final class SQLStatementTargetResolver {
         return result;
     }
     
-    private Optional<SQLCommonTableExpression> findCommonTableExpression(final 
SQLStatementStructure statementStructure, final String aliasName) {
-        String normalizedAliasName = 
scanner.normalizeIdentifierForComparison(aliasName);
+    private Optional<SQLCommonTableExpression> findCommonTableExpression(final 
SQLStatementStructure statementStructure, final SQLStatementObjectName 
objectName) {
+        if (objectName.qualified()) {
+            return Optional.empty();
+        }
+        String normalizedAliasName = 
scanner.normalizeIdentifierForComparison(objectName.objectName());
         for (SQLCommonTableExpression each : 
statementStructure.commonTableExpressions()) {
             if 
(scanner.normalizeIdentifierForComparison(each.aliasName()).equals(normalizedAliasName))
 {
                 return Optional.of(each);
@@ -262,7 +266,7 @@ final class SQLStatementTargetResolver {
     }
     
     private void collectObjectNamesAfterTypeKeyword(final 
SQLStatementStructure statementStructure, final List<SQLStatementToken> tokens, 
final Collection<String> visitedAliases,
-                                                    final Collection<String> 
objectNames, final String... optionalKeywords) {
+                                                    final 
Collection<SQLStatementObjectName> objectNames, final String... 
optionalKeywords) {
         for (int index = 0; index < tokens.size(); index++) {
             if 
(SQL_OBJECT_TYPE_KEYWORDS.contains(tokens.get(index).upperText())) {
                 collectObjectNamesFromList(statementStructure, tokens, index + 
1, visitedAliases, objectNames, optionalKeywords);
@@ -272,7 +276,7 @@ final class SQLStatementTargetResolver {
     }
     
     private boolean collectObjectNamesAfterKeyword(final SQLStatementStructure 
statementStructure, final List<SQLStatementToken> tokens, final String keyword,
-                                                   final Collection<String> 
visitedAliases, final Collection<String> objectNames, final String... 
optionalKeywords) {
+                                                   final Collection<String> 
visitedAliases, final Collection<SQLStatementObjectName> objectNames, final 
String... optionalKeywords) {
         for (int index = 0; index < tokens.size(); index++) {
             if (scanner.isKeyword(tokens.get(index), keyword)) {
                 collectObjectNamesFromList(statementStructure, tokens, index + 
1, visitedAliases, objectNames, optionalKeywords);
@@ -283,14 +287,14 @@ final class SQLStatementTargetResolver {
     }
     
     private void collectObjectNamesFromList(final SQLStatementStructure 
statementStructure, final List<SQLStatementToken> tokens, final int startIndex,
-                                            final Collection<String> 
visitedAliases, final Collection<String> objectNames, final String... 
optionalKeywords) {
+                                            final Collection<String> 
visitedAliases, final Collection<SQLStatementObjectName> objectNames, final 
String... optionalKeywords) {
         int currentIndex = startIndex;
         while (currentIndex < tokens.size()) {
             SQLStatementObjectName objectName = 
objectNameReader.readObjectName(tokens, currentIndex, optionalKeywords);
             if (objectName.objectName().isEmpty()) {
                 return;
             }
-            collectObjectName(statementStructure, objectName.objectName(), 
visitedAliases, objectNames);
+            collectObjectName(statementStructure, objectName, visitedAliases, 
objectNames);
             currentIndex = objectNameReader.skipObjectTail(tokens, 
objectName.nextIndex());
             if (currentIndex >= tokens.size() || 
!",".equals(tokens.get(currentIndex).text())) {
                 return;
@@ -299,12 +303,12 @@ final class SQLStatementTargetResolver {
         }
     }
     
-    private void collectQualifiedFunctionNames(final List<SQLStatementToken> 
tokens, final Collection<String> objectNames) {
+    private void collectQualifiedFunctionNames(final List<SQLStatementToken> 
tokens, final Collection<SQLStatementObjectName> objectNames) {
         int index = 0;
         while (index < tokens.size()) {
             SQLStatementObjectName objectName = 
objectNameReader.readQualifiedName(tokens, index);
             if (isQualifiedFunctionName(tokens, objectName)) {
-                addObjectName(objectNames, objectName.objectName());
+                addObjectName(objectNames, objectName);
                 index = objectName.nextIndex() - 1;
             }
             index++;
@@ -316,8 +320,8 @@ final class SQLStatementTargetResolver {
                 && "(".equals(tokens.get(objectName.nextIndex()).text());
     }
     
-    private void addObjectName(final Collection<String> objectNames, final 
String objectName) {
-        if (!objectName.isEmpty()) {
+    private void addObjectName(final Collection<SQLStatementObjectName> 
objectNames, final SQLStatementObjectName objectName) {
+        if (!objectName.objectName().isEmpty()) {
             objectNames.add(objectName);
         }
     }
diff --git 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/StatementClassifier.java
 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/StatementClassifier.java
index db4a778ac8e..94dbec4bb2b 100644
--- 
a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/StatementClassifier.java
+++ 
b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/StatementClassifier.java
@@ -60,8 +60,7 @@ public final class StatementClassifier {
         SQLStatementStructure statementStructure = 
structureResolver.resolve(actualSql);
         SupportedMCPStatement statementClass = 
statementClassResolver.resolve(statementStructure);
         safetyValidator.checkStructuredStatement(statementClass, 
statementStructure);
-        return new ClassificationResult(statementClass, 
statementStructure.statementType(), actualSql, 
targetResolver.resolve(statementStructure), "",
-                targetResolver.resolveAll(statementStructure));
+        return new ClassificationResult(statementClass, 
statementStructure.statementType(), actualSql, "", 
targetResolver.resolveAll(statementStructure));
     }
     
     private boolean isTransactionControlStatement(final String upperSql) {
diff --git 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/MCPCompletionServiceTest.java
 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/MCPCompletionServiceTest.java
index a92d116858c..b87e625318c 100644
--- 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/MCPCompletionServiceTest.java
+++ 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/MCPCompletionServiceTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.core.completion;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import org.apache.shardingsphere.infra.spi.ShardingSphereServiceLoader;
 import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPInvalidRequestException;
 import 
org.apache.shardingsphere.mcp.core.completion.provider.MetadataCompletionProvider;
@@ -144,8 +145,8 @@ class MCPCompletionServiceTest {
     private MCPRuntimeContext createRuntimeContext(final 
WorkflowSessionContext workflowSessionContext) {
         MCPDatabaseCapabilityProvider databaseCapabilityProvider = 
mock(MCPDatabaseCapabilityProvider.class);
         
when(databaseCapabilityProvider.getDatabaseProfiles()).thenReturn(List.of(
-                new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true),
-                new RuntimeDatabaseProfile("warehouse", "FixtureWarehouseDB", 
"2.0", true, true)));
+                new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet()),
+                new RuntimeDatabaseProfile("warehouse", "FixtureWarehouseDB", 
"2.0", true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet())));
         MCPRuntimeContext result = mock(MCPRuntimeContext.class, 
RETURNS_DEEP_STUBS);
         
when(result.getDatabaseCapabilityProvider()).thenReturn(databaseCapabilityProvider);
         
when(result.getWorkflowSessionContext()).thenReturn(workflowSessionContext);
diff --git 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/provider/MetadataCompletionProviderTest.java
 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/provider/MetadataCompletionProviderTest.java
index 94de6294c26..48a44a21857 100644
--- 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/provider/MetadataCompletionProviderTest.java
+++ 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/provider/MetadataCompletionProviderTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.core.completion.provider;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.TableType;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
@@ -260,11 +261,11 @@ class MetadataCompletionProviderTest {
     }
     
     private RuntimeDatabaseProfile createDatabaseProfile(final String 
database) {
-        return new RuntimeDatabaseProfile(database, "FixtureDB", "1.0", true, 
true);
+        return new RuntimeDatabaseProfile(database, "FixtureDB", "1.0", true, 
true, IdentifierCasePolicyFactory.newInsensitivePolicySet());
     }
     
     private RuntimeDatabaseProfile createDatabaseMetadata() {
-        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true);
+        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet());
     }
     
     private ShardingSphereSchema createSchemaMetadata() {
diff --git 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourceHandlerTest.java
 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourceHandlerTest.java
index df4ff8adb29..aa169fdbcd1 100644
--- 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourceHandlerTest.java
+++ 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourceHandlerTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.core.resource.handler.metadata;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import org.apache.shardingsphere.mcp.api.protocol.response.MCPResponse;
 import org.apache.shardingsphere.mcp.api.resource.MCPUriVariables;
 import 
org.apache.shardingsphere.mcp.api.resource.descriptor.MCPResourceDescriptor;
@@ -113,7 +114,8 @@ class MetadataResourceHandlerTest {
     @Test
     void assertHandleListResourceWithEmptyScope() {
         MetadataResourceHandler handler = new 
MetadataResourceHandler("shardingsphere://databases/{database}/schemas", 
(requestContext, uriVariables) -> List.of());
-        MCPResponse actual = 
handler.handle(createDatabaseContext(Optional.of(new 
RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", true, true))),
+        MCPResponse actual = handler.handle(createDatabaseContext(Optional.of(
+                new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet()))),
                 new MCPUriVariables(Map.of("database", "logic_db")));
         Map<?, ?> actualEmptyState = (Map<?, ?>) 
actual.toPayload().get("empty_state");
         assertThat(actualEmptyState.get("category"), is("empty_scope"));
@@ -124,7 +126,8 @@ class MetadataResourceHandlerTest {
     @Test
     void assertHandleSchemaDetailResourceNotVisible() {
         MetadataResourceHandler handler = new 
MetadataResourceHandler("shardingsphere://databases/{database}/schemas/{schema}",
 (requestContext, uriVariables) -> List.of());
-        MCPResponse actual = 
handler.handle(createDatabaseContext(Optional.of(new 
RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", true, true))),
+        MCPResponse actual = handler.handle(createDatabaseContext(Optional.of(
+                new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet()))),
                 new MCPUriVariables(Map.of("database", "logic_db", "schema", 
"missing_schema")));
         Map<?, ?> actualEmptyState = (Map<?, ?>) 
actual.toPayload().get("empty_state");
         assertThat(actualEmptyState.get("category"), is("schema_not_visible"));
@@ -136,7 +139,8 @@ class MetadataResourceHandlerTest {
     @Test
     void assertHandleObjectDetailResourceNotVisible() {
         MetadataResourceHandler handler = new 
MetadataResourceHandler("shardingsphere://databases/{database}/schemas/{schema}/tables/{table}",
 (requestContext, uriVariables) -> List.of());
-        MCPResponse actual = 
handler.handle(createDatabaseContext(Optional.of(new 
RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", true, true))),
+        MCPResponse actual = handler.handle(createDatabaseContext(Optional.of(
+                new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet()))),
                 new MCPUriVariables(Map.of("database", "logic_db", "schema", 
"public", "table", "missing_table")));
         Map<?, ?> actualEmptyState = (Map<?, ?>) 
actual.toPayload().get("empty_state");
         assertThat(actualEmptyState.get("category"), is("object_not_visible"));
diff --git 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourcePayloadMapperTest.java
 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourcePayloadMapperTest.java
index 0c2ee4ba367..fdf2505fe88 100644
--- 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourcePayloadMapperTest.java
+++ 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourcePayloadMapperTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.core.resource.handler.metadata;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.TableType;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
@@ -46,7 +47,8 @@ class MetadataResourcePayloadMapperTest {
         MCPMetadataQueryFacade metadataQueryFacade = 
mock(MCPMetadataQueryFacade.class);
         
when(metadataQueryFacade.querySchemas("logic_db")).thenReturn(List.of(createSchemaMetadata()));
         List<?> actual = new 
MetadataResourcePayloadMapper(metadataQueryFacade, new 
MCPUriVariables(Map.of()), true)
-                .map(createMetadata("logical-database"), List.of(new 
RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", true, true)));
+                .map(createMetadata("logical-database"), List.of(
+                        new RuntimeDatabaseProfile("logic_db", "FixtureDB", 
"1.0", true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet())));
         Map<?, ?> actualDatabase = (Map<?, ?>) actual.getFirst();
         assertThat(actualDatabase.get("database"), is("logic_db"));
         assertThat(actualDatabase.get("databaseType"), is("FixtureDB"));
diff --git 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExplainSQLCandidateValidatorTest.java
 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExplainSQLCandidateValidatorTest.java
index cec31a884ce..e7c217ab0e6 100644
--- 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExplainSQLCandidateValidatorTest.java
+++ 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/ExplainSQLCandidateValidatorTest.java
@@ -51,6 +51,12 @@ class ExplainSQLCandidateValidatorTest {
         assertThat(actual.getNormalizedSql(), is("EXPLAIN QUERY TREE SELECT * 
FROM foo_orders WHERE status = 'READY  TO SHIP'"));
     }
     
+    @Test
+    void assertValidateHiveCBO() {
+        ClassificationResult actual = validator.validate("SELECT * FROM 
foo_orders", "EXPLAIN CBO SELECT * FROM foo_orders");
+        assertThat(actual.getNormalizedSql(), is("EXPLAIN CBO SELECT * FROM 
foo_orders"));
+    }
+    
     @Test
     void assertValidateWithNonExecutableComments() {
         ClassificationResult actual = validator.validate("SELECT '/*!80018 
ANALYZE */' FROM foo_orders",
diff --git 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPSQLExecutionFacadeTest.java
 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPSQLExecutionFacadeTest.java
index 27c2dc8c221..10f9c2ef0e9 100644
--- 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPSQLExecutionFacadeTest.java
+++ 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPSQLExecutionFacadeTest.java
@@ -17,6 +17,8 @@
 
 package org.apache.shardingsphere.mcp.core.tool.handler.execute;
 
+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.api.protocol.exception.MCPInvalidRequestException;
 import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPQueryFailedException;
 import 
org.apache.shardingsphere.mcp.core.protocol.exception.MCPBannedSQLStatementException;
@@ -40,7 +42,6 @@ import org.mockito.ArgumentCaptor;
 import java.sql.SQLException;
 import java.sql.SQLSyntaxErrorException;
 import java.util.Collections;
-import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Supplier;
@@ -214,8 +215,7 @@ class MCPSQLExecutionFacadeTest {
         SQLExecutionTraceFactory traceFactory = 
mock(SQLExecutionTraceFactory.class);
         MCPDatabaseCapability capability = 
createCapability(Set.of(SupportedMCPStatement.QUERY));
         SQLExecutionRequest request = createExecutionRequest("SELECT * FROM 
other_db.orders");
-        ClassificationResult classification = new 
ClassificationResult(SupportedMCPStatement.QUERY, "SELECT", "SELECT * FROM 
other_db.orders", "other_db.orders", "",
-                List.of("other_db.orders"));
+        ClassificationResult classification = new 
ClassificationResult(SupportedMCPStatement.QUERY, "SELECT", "SELECT * FROM 
other_db.orders", "other_db.orders", "");
         MCPSQLExecutionFacade facade = createFacade(capabilityProvider, 
coordinator, transactionExecutor, statementExecutor, traceFactory, 
createStatementClassifier(classification));
         mockSessionLock(coordinator);
         
when(capabilityProvider.provide("logic_db")).thenReturn(Optional.of(capability));
@@ -271,8 +271,7 @@ class MCPSQLExecutionFacadeTest {
         SQLExecutionTraceFactory traceFactory = 
mock(SQLExecutionTraceFactory.class);
         MCPDatabaseCapability capability = 
createCapability(Set.of(SupportedMCPStatement.DML));
         SQLExecutionRequest request = createExecutionRequest("UPDATE 
other_db.orders SET status = 'DONE'");
-        ClassificationResult classification = new 
ClassificationResult(SupportedMCPStatement.DML, "UPDATE", "UPDATE 
other_db.orders SET status = 'DONE'", "other_db.orders", "",
-                List.of("other_db.orders"));
+        ClassificationResult classification = new 
ClassificationResult(SupportedMCPStatement.DML, "UPDATE", "UPDATE 
other_db.orders SET status = 'DONE'", "other_db.orders", "");
         MCPSQLExecutionFacade facade = createFacade(capabilityProvider, 
coordinator, transactionExecutor, statementExecutor, traceFactory, 
createStatementClassifier(classification));
         mockSessionLock(coordinator);
         
when(capabilityProvider.provide("logic_db")).thenReturn(Optional.of(capability));
@@ -288,8 +287,7 @@ class MCPSQLExecutionFacadeTest {
         MCPSessionExecutionCoordinator coordinator = 
mock(MCPSessionExecutionCoordinator.class);
         MCPJdbcStatementExecutor statementExecutor = 
mock(MCPJdbcStatementExecutor.class);
         MCPDatabaseCapability capability = 
createCapability(Set.of(SupportedMCPStatement.QUERY));
-        ClassificationResult classification = new 
ClassificationResult(SupportedMCPStatement.QUERY, "SELECT", "SELECT * FROM 
logic_db.orders", "logic_db.orders", "",
-                List.of("logic_db.orders"));
+        ClassificationResult classification = new 
ClassificationResult(SupportedMCPStatement.QUERY, "SELECT", "SELECT * FROM 
logic_db.orders", "logic_db.orders", "");
         SQLExecutionResponse response = 
SQLExecutionResponse.resultSet(SupportedMCPStatement.QUERY, "SELECT", 
Collections.emptyList(), Collections.emptyList(), false);
         mockSessionLock(coordinator);
         
when(capabilityProvider.provide("logic_db")).thenReturn(Optional.of(capability));
@@ -305,14 +303,44 @@ class MCPSQLExecutionFacadeTest {
         verifyNoInteractions(transactionExecutor);
     }
     
+    @Test
+    void assertExecuteWithCaseInsensitiveQualifiedCurrentDatabase() {
+        MCPDatabaseCapabilityProvider capabilityProvider = 
mock(MCPDatabaseCapabilityProvider.class);
+        MCPSessionExecutionCoordinator coordinator = 
mock(MCPSessionExecutionCoordinator.class);
+        MCPJdbcStatementExecutor statementExecutor = 
mock(MCPJdbcStatementExecutor.class);
+        MCPDatabaseCapability capability = 
createCapability(Set.of(SupportedMCPStatement.QUERY));
+        SQLExecutionResponse response = 
SQLExecutionResponse.resultSet(SupportedMCPStatement.QUERY, "SELECT", 
Collections.emptyList(), Collections.emptyList(), false);
+        mockSessionLock(coordinator);
+        
when(capabilityProvider.provide("logic_db")).thenReturn(Optional.of(capability));
+        SQLExecutionRequest request = createExecutionRequest("SELECT * FROM 
Logic_DB.orders");
+        when(statementExecutor.execute(eq(request), any(), 
eq(capability))).thenReturn(response);
+        MCPSQLExecutionFacade facade = createFacade(capabilityProvider, 
coordinator, mock(MCPJdbcTransactionStatementExecutor.class), statementExecutor,
+                mock(SQLExecutionTraceFactory.class));
+        assertThat(facade.execute(request), is(response));
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("assertExecuteWithNonMatchingCurrentDatabaseIdentifierCases")
+    void assertExecuteWithNonMatchingCurrentDatabaseIdentifier(final String 
name, final String sql, final IdentifierCasePolicySet identifierCasePolicySet) {
+        MCPDatabaseCapabilityProvider capabilityProvider = 
mock(MCPDatabaseCapabilityProvider.class);
+        MCPSessionExecutionCoordinator coordinator = 
mock(MCPSessionExecutionCoordinator.class);
+        MCPDatabaseCapability capability = 
createCapability(Set.of(SupportedMCPStatement.QUERY));
+        
when(capability.getIdentifierCasePolicySet()).thenReturn(identifierCasePolicySet);
+        mockSessionLock(coordinator);
+        
when(capabilityProvider.provide("logic_db")).thenReturn(Optional.of(capability));
+        MCPSQLExecutionFacade facade = createFacade(capabilityProvider, 
coordinator, mock(MCPJdbcTransactionStatementExecutor.class), 
mock(MCPJdbcStatementExecutor.class),
+                mock(SQLExecutionTraceFactory.class));
+        MCPInvalidRequestException actual = 
assertThrows(MCPInvalidRequestException.class, () -> 
facade.execute(createExecutionRequest(sql)));
+        assertThat(actual.getMessage(), is("Cross-schema SQL is not supported 
for database `logic_db`: `Logic_DB.orders`."));
+    }
+    
     @Test
     void assertExecuteWithCrossSchemaSqlEnabled() {
         MCPDatabaseCapabilityProvider capabilityProvider = 
mock(MCPDatabaseCapabilityProvider.class);
         MCPSessionExecutionCoordinator coordinator = 
mock(MCPSessionExecutionCoordinator.class);
         MCPJdbcStatementExecutor statementExecutor = 
mock(MCPJdbcStatementExecutor.class);
         MCPDatabaseCapability capability = 
createCapability(Set.of(SupportedMCPStatement.QUERY), 
SchemaExecutionSemantics.BEST_EFFORT);
-        ClassificationResult classification = new 
ClassificationResult(SupportedMCPStatement.QUERY, "SELECT", "SELECT * FROM 
other_db.orders", "other_db.orders", "",
-                List.of("other_db.orders"));
+        ClassificationResult classification = new 
ClassificationResult(SupportedMCPStatement.QUERY, "SELECT", "SELECT * FROM 
other_db.orders", "other_db.orders", "");
         SQLExecutionResponse response = 
SQLExecutionResponse.resultSet(SupportedMCPStatement.QUERY, "SELECT", 
Collections.emptyList(), Collections.emptyList(), false);
         mockSessionLock(coordinator);
         
when(capabilityProvider.provide("logic_db")).thenReturn(Optional.of(capability));
@@ -434,6 +462,7 @@ class MCPSQLExecutionFacadeTest {
         MCPDatabaseCapability result = mock(MCPDatabaseCapability.class);
         
when(result.getSupportedStatementClasses()).thenReturn(supportedStatementClasses);
         
when(result.getSchemaExecutionSemantics()).thenReturn(schemaExecutionSemantics);
+        
when(result.getIdentifierCasePolicySet()).thenReturn(IdentifierCasePolicyFactory.newInsensitivePolicySet());
         return result;
     }
     
@@ -449,6 +478,7 @@ class MCPSQLExecutionFacadeTest {
                 Arguments.of("query aliased object list", "SELECT * FROM 
logic_db.orders o, other_db.items i", "other_db.items", "QUERY"),
                 Arguments.of("query partitioned object list", "SELECT * FROM 
logic_db.orders PARTITION (p0) o, other_db.items i", "other_db.items", "QUERY"),
                 Arguments.of("cte object list", "WITH query_result AS (SELECT 
* FROM logic_db.orders, other_db.items) SELECT * FROM query_result", 
"other_db.items", "QUERY"),
+                Arguments.of("qualified object distinct from quoted cte 
alias", "WITH \"other_db.items\" AS (SELECT 1) SELECT * FROM other_db.items", 
"other_db.items", "QUERY"),
                 Arguments.of("unused cte reference", "WITH unused_result AS 
(SELECT * FROM other_db.items) SELECT * FROM logic_db.orders", 
"other_db.items", "QUERY"),
                 Arguments.of("insert select object list", "INSERT INTO 
logic_db.orders_archive SELECT * FROM logic_db.orders, other_db.items", 
"other_db.items", "DML"),
                 Arguments.of("update target object list", "UPDATE 
logic_db.orders o, other_db.items i SET o.status = 'DONE'", "other_db.items", 
"DML"),
@@ -479,6 +509,12 @@ class MCPSQLExecutionFacadeTest {
                 Arguments.of("qualified function", "SELECT 
other_db.refresh_orders()", "other_db.refresh_orders", "QUERY"));
     }
     
+    private static Stream<Arguments> 
assertExecuteWithNonMatchingCurrentDatabaseIdentifierCases() {
+        return Stream.of(
+                Arguments.of("case-sensitive unquoted identifier", "SELECT * 
FROM Logic_DB.orders", IdentifierCasePolicyFactory.newSensitivePolicySet()),
+                Arguments.of("quoted identifier exact match", "SELECT * FROM 
\"Logic_DB\".orders", IdentifierCasePolicyFactory.newInsensitivePolicySet()));
+    }
+    
     private static Stream<Arguments> 
assertExecuteExplainWithSyntaxFailureCases() {
         return Stream.of(
                 Arguments.of("JDBC syntax exception", new 
MCPInvalidRequestException("bad explain", new SQLSyntaxErrorException("bad 
explain"))),
diff --git 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/metadata/SearchMetadataPayloadBuilderTest.java
 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/metadata/SearchMetadataPayloadBuilderTest.java
index 3e2c8b01ea9..e1c659c32aa 100644
--- 
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/metadata/SearchMetadataPayloadBuilderTest.java
+++ 
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/metadata/SearchMetadataPayloadBuilderTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.core.tool.handler.metadata;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import org.apache.shardingsphere.mcp.core.tool.request.MetadataSearchRequest;
 import org.apache.shardingsphere.mcp.core.tool.response.MetadataSearchHit;
@@ -101,7 +102,8 @@ class SearchMetadataPayloadBuilderTest {
         MCPFeatureCapabilityFacade capabilityFacade = 
mock(MCPFeatureCapabilityFacade.class);
         when(result.getMetadataQueryFacade()).thenReturn(metadataQueryFacade);
         when(result.getCapabilityFacade()).thenReturn(capabilityFacade);
-        when(metadataQueryFacade.queryDatabases()).thenReturn(List.of(new 
RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", true, true)));
+        when(metadataQueryFacade.queryDatabases()).thenReturn(
+                List.of(new RuntimeDatabaseProfile("logic_db", "FixtureDB", 
"1.0", true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet())));
         when(metadataQueryFacade.querySchema("logic_db", 
"public")).thenReturn(Optional.of(mock(ShardingSphereSchema.class)));
         
when(capabilityFacade.findDatabaseProfile("logic_db")).thenReturn(Optional.of(mock(RuntimeDatabaseProfile.class)));
         return result;
diff --git 
a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowPlanningServiceTest.java
 
b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowPlanningServiceTest.java
index c291187da7e..b80d9c1ddb0 100644
--- 
a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowPlanningServiceTest.java
+++ 
b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowPlanningServiceTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.feature.encrypt.tool.service;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.TableType;
 import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
@@ -373,7 +374,7 @@ class EncryptWorkflowPlanningServiceTest {
     }
     
     private RuntimeDatabaseProfile createDatabaseMetadata() {
-        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true);
+        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet());
     }
     
     private ShardingSphereSchema createSchemaMetadata() {
diff --git 
a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/tool/service/MaskWorkflowPlanningServiceTest.java
 
b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/tool/service/MaskWorkflowPlanningServiceTest.java
index 4d838b885fa..0d6f99cf9e7 100644
--- 
a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/tool/service/MaskWorkflowPlanningServiceTest.java
+++ 
b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/tool/service/MaskWorkflowPlanningServiceTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.feature.mask.tool.service;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.TableType;
 import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
@@ -302,7 +303,7 @@ class MaskWorkflowPlanningServiceTest {
     }
     
     private RuntimeDatabaseProfile createDatabaseMetadata() {
-        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true);
+        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet());
     }
     
     private ShardingSphereSchema createSchemaMetadata() {
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapability.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapability.java
index 3723706f94e..fa22b11ba3a 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapability.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapability.java
@@ -20,6 +20,7 @@ package 
org.apache.shardingsphere.mcp.support.database.capability;
 import lombok.Getter;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.metadata.option.schema.DialectSchemaSemantics;
 import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
+import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseProfile;
 
 import java.util.LinkedHashSet;
 import java.util.Set;
@@ -46,17 +47,16 @@ public final class MCPDatabaseCapability {
     
     private final IdentifierCasePolicySet identifierCasePolicySet;
     
-    public MCPDatabaseCapability(final String databaseName, final boolean 
supportsTransaction, final boolean supportsSavepoint,
-                                 final IdentifierCasePolicySet 
identifierCasePolicySet, final MCPDatabaseCapabilityOption option) {
-        this.databaseName = databaseName;
+    MCPDatabaseCapability(final RuntimeDatabaseProfile databaseProfile, final 
MCPDatabaseCapabilityOption option) {
+        databaseName = databaseProfile.getDatabase();
         databaseType = option.getType();
         MCPDatabaseDialect databaseDialect = 
MCPDatabaseDialect.of(option.getType());
         supportedMetadataObjectTypes = 
createSupportedMetadataObjectTypes(databaseDialect);
-        transactionCapability = 
databaseDialect.getTransactionCapability(supportsTransaction, 
supportsSavepoint);
+        transactionCapability = 
databaseDialect.getTransactionCapability(databaseProfile.isSupportsTransaction(),
 databaseProfile.isSupportsSavepoint());
         supportedStatementClasses = 
createSupportedStatementClasses(transactionCapability, 
option.isExplainSupported());
         defaultSchemaSemantics = databaseDialect.getDefaultSchemaSemantics();
         schemaExecutionSemantics = 
createSchemaExecutionSemantics(defaultSchemaSemantics);
-        this.identifierCasePolicySet = identifierCasePolicySet;
+        identifierCasePolicySet = databaseProfile.getIdentifierCasePolicySet();
     }
     
     private static SchemaExecutionSemantics 
createSchemaExecutionSemantics(final DialectSchemaSemantics 
defaultSchemaSemantics) {
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityProvider.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityProvider.java
index 8e7079dcc37..d4f832bc55d 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityProvider.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityProvider.java
@@ -17,30 +17,17 @@
 
 package org.apache.shardingsphere.mcp.support.database.capability;
 
-import lombok.RequiredArgsConstructor;
-import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
-import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
-import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
-import 
org.apache.shardingsphere.infra.metadata.identifier.IdentifierCasePolicyResolver;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.MCPJdbcDatabaseProfileLoader;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConfiguration;
-import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConnectionException;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseProfile;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureCapabilityFacade;
 
-import javax.sql.DataSource;
-import java.io.PrintWriter;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.SQLFeatureNotSupportedException;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.Properties;
-import java.util.logging.Logger;
 
 /**
  * MCP database capability provider.
@@ -53,7 +40,7 @@ public final class MCPDatabaseCapabilityProvider implements 
MCPFeatureCapability
     
     public MCPDatabaseCapabilityProvider(final Map<String, 
RuntimeDatabaseConfiguration> runtimeDatabases) {
         databaseProfiles = new 
MCPJdbcDatabaseProfileLoader().load(runtimeDatabases);
-        databaseCapabilities = createDatabaseCapabilities(databaseProfiles, 
runtimeDatabases);
+        databaseCapabilities = createDatabaseCapabilities(databaseProfiles);
     }
     
     @Override
@@ -71,83 +58,12 @@ public final class MCPDatabaseCapabilityProvider implements 
MCPFeatureCapability
         return new LinkedList<>(databaseProfiles.values());
     }
     
-    private Map<String, MCPDatabaseCapability> 
createDatabaseCapabilities(final Map<String, RuntimeDatabaseProfile> 
databaseProfiles,
-                                                                          
final Map<String, RuntimeDatabaseConfiguration> runtimeDatabases) {
+    private Map<String, MCPDatabaseCapability> 
createDatabaseCapabilities(final Map<String, RuntimeDatabaseProfile> 
databaseProfiles) {
         Map<String, MCPDatabaseCapability> result = new 
LinkedHashMap<>(databaseProfiles.size(), 1F);
         for (RuntimeDatabaseProfile each : databaseProfiles.values()) {
             TypedSPILoader.findService(MCPDatabaseCapabilityOption.class, 
each.getDatabaseType())
-                    .ifPresent(option -> result.put(each.getDatabase(), new 
MCPDatabaseCapability(each.getDatabase(), each.isSupportsTransaction(), 
each.isSupportsSavepoint(),
-                            resolveIdentifierCasePolicySet(each, 
runtimeDatabases.get(each.getDatabase())), option)));
+                    .ifPresent(option -> result.put(each.getDatabase(), new 
MCPDatabaseCapability(each, option)));
         }
         return result;
     }
-    
-    private IdentifierCasePolicySet resolveIdentifierCasePolicySet(final 
RuntimeDatabaseProfile databaseProfile, final RuntimeDatabaseConfiguration 
runtimeDatabaseConfig) {
-        DatabaseType databaseType = 
TypedSPILoader.getService(DatabaseType.class, 
databaseProfile.getDatabaseType());
-        return new IdentifierCasePolicyResolver().resolve(databaseType, new 
ConfigurationProperties(new Properties()),
-                new RuntimeDatabaseDataSource(databaseProfile.getDatabase(), 
runtimeDatabaseConfig));
-    }
-    
-    @RequiredArgsConstructor
-    private static final class RuntimeDatabaseDataSource implements DataSource 
{
-        
-        private final String databaseName;
-        
-        private final RuntimeDatabaseConfiguration runtimeDatabaseConfig;
-        
-        @Override
-        public Connection getConnection() throws SQLException {
-            try {
-                return runtimeDatabaseConfig.openConnection(databaseName);
-            } catch (final RuntimeDatabaseConnectionException ex) {
-                if (ex.getCause() instanceof SQLException cause) {
-                    throw cause;
-                }
-                throw new SQLException(ex);
-            }
-        }
-        
-        @Override
-        public Connection getConnection(final String username, final String 
password) throws SQLException {
-            throw new SQLFeatureNotSupportedException();
-        }
-        
-        @Override
-        public PrintWriter getLogWriter() throws SQLException {
-            throw new SQLFeatureNotSupportedException();
-        }
-        
-        @Override
-        public void setLogWriter(final PrintWriter out) throws SQLException {
-            throw new SQLFeatureNotSupportedException();
-        }
-        
-        @Override
-        public void setLoginTimeout(final int seconds) throws SQLException {
-            throw new SQLFeatureNotSupportedException();
-        }
-        
-        @Override
-        public int getLoginTimeout() throws SQLException {
-            throw new SQLFeatureNotSupportedException();
-        }
-        
-        @Override
-        public Logger getParentLogger() throws SQLFeatureNotSupportedException 
{
-            throw new SQLFeatureNotSupportedException();
-        }
-        
-        @Override
-        public <T> T unwrap(final Class<T> iface) throws SQLException {
-            if (iface.isInstance(this)) {
-                return iface.cast(this);
-            }
-            throw new SQLException(String.format("Unable to unwrap runtime 
database data source to `%s`.", iface.getName()));
-        }
-        
-        @Override
-        public boolean isWrapperFor(final Class<?> iface) {
-            return iface.isInstance(this);
-        }
-    }
 }
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 11619244bf5..e86713afa7f 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
@@ -23,6 +23,6 @@ package 
org.apache.shardingsphere.mcp.support.database.capability.dialect;
 public final class ClickHouseMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCapabilityOption {
     
     public ClickHouseMCPDatabaseCapabilityOption() {
-        super("ClickHouse", false);
+        super("ClickHouse", true);
     }
 }
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 2665add48fe..216b534ef24 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
@@ -23,6 +23,6 @@ package 
org.apache.shardingsphere.mcp.support.database.capability.dialect;
 public final class HiveMCPDatabaseCapabilityOption extends 
AbstractMCPDatabaseCapabilityOption {
     
     public HiveMCPDatabaseCapabilityOption() {
-        super("Hive", false);
+        super("Hive", true);
     }
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoader.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoader.java
index df1476994a0..2d4d73a44ce 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoader.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoader.java
@@ -17,17 +17,26 @@
 
 package org.apache.shardingsphere.mcp.support.database.metadata.jdbc;
 
+import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeFactory;
+import org.apache.shardingsphere.infra.config.props.ConfigurationProperties;
 import 
org.apache.shardingsphere.infra.exception.external.ShardingSphereExternalException;
+import 
org.apache.shardingsphere.infra.metadata.identifier.IdentifierCasePolicyResolver;
 
+import javax.sql.DataSource;
+import java.io.PrintWriter;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Properties;
+import java.util.logging.Logger;
 
 /**
  * MCP JDBC database profile loader.
@@ -58,15 +67,27 @@ public final class MCPJdbcDatabaseProfileLoader {
      * @throws RuntimeDatabaseConnectionException when profile metadata 
loading fails
      */
     public RuntimeDatabaseProfile load(final String databaseName, final 
RuntimeDatabaseConfiguration runtimeDatabaseConfig) {
+        DatabaseType databaseType;
+        String databaseVersion;
+        boolean supportsTransaction;
+        boolean supportsSavepoint;
         try (Connection connection = 
runtimeDatabaseConfig.openConnection(databaseName)) {
             DatabaseMetaData databaseMetaData = connection.getMetaData();
-            DatabaseType databaseType = loadDatabaseType(databaseName, 
databaseMetaData);
-            String databaseVersion = 
Objects.toString(databaseMetaData.getDatabaseProductVersion(), "").trim();
-            boolean supportsTransaction = 
databaseMetaData.supportsTransactions();
-            return new RuntimeDatabaseProfile(databaseName, 
databaseType.getType(), databaseVersion, supportsTransaction, 
supportsTransaction && databaseMetaData.supportsSavepoints());
+            databaseType = loadDatabaseType(databaseName, databaseMetaData);
+            databaseVersion = 
Objects.toString(databaseMetaData.getDatabaseProductVersion(), "").trim();
+            supportsTransaction = databaseMetaData.supportsTransactions();
+            supportsSavepoint = supportsTransaction && 
databaseMetaData.supportsSavepoints();
         } catch (final SQLException ex) {
             throw 
RuntimeDatabaseConnectionException.connectionFailed(databaseName, ex);
         }
+        return new RuntimeDatabaseProfile(databaseName, 
databaseType.getType(), databaseVersion, supportsTransaction, supportsSavepoint,
+                resolveIdentifierCasePolicySet(databaseName, databaseType, 
runtimeDatabaseConfig));
+    }
+    
+    private IdentifierCasePolicySet resolveIdentifierCasePolicySet(final 
String databaseName, final DatabaseType databaseType,
+                                                                   final 
RuntimeDatabaseConfiguration runtimeDatabaseConfig) {
+        return new IdentifierCasePolicyResolver().resolve(databaseType, new 
ConfigurationProperties(new Properties()),
+                new RuntimeDatabaseDataSource(databaseName, 
runtimeDatabaseConfig));
     }
     
     private DatabaseType loadDatabaseType(final String databaseName, final 
DatabaseMetaData databaseMetaData) throws SQLException {
@@ -76,4 +97,67 @@ public final class MCPJdbcDatabaseProfileLoader {
             throw 
RuntimeDatabaseConnectionException.invalidConfiguration(databaseName, ex);
         }
     }
+    
+    @RequiredArgsConstructor
+    private static final class RuntimeDatabaseDataSource implements DataSource 
{
+        
+        private final String databaseName;
+        
+        private final RuntimeDatabaseConfiguration runtimeDatabaseConfig;
+        
+        @Override
+        public Connection getConnection() throws SQLException {
+            try {
+                return runtimeDatabaseConfig.openConnection(databaseName);
+            } catch (final RuntimeDatabaseConnectionException ex) {
+                if (ex.getCause() instanceof SQLException cause) {
+                    throw cause;
+                }
+                throw new SQLException(ex);
+            }
+        }
+        
+        @Override
+        public Connection getConnection(final String username, final String 
password) throws SQLException {
+            throw new SQLFeatureNotSupportedException();
+        }
+        
+        @Override
+        public PrintWriter getLogWriter() throws SQLException {
+            throw new SQLFeatureNotSupportedException();
+        }
+        
+        @Override
+        public void setLogWriter(final PrintWriter out) throws SQLException {
+            throw new SQLFeatureNotSupportedException();
+        }
+        
+        @Override
+        public void setLoginTimeout(final int seconds) throws SQLException {
+            throw new SQLFeatureNotSupportedException();
+        }
+        
+        @Override
+        public int getLoginTimeout() throws SQLException {
+            throw new SQLFeatureNotSupportedException();
+        }
+        
+        @Override
+        public Logger getParentLogger() throws SQLFeatureNotSupportedException 
{
+            throw new SQLFeatureNotSupportedException();
+        }
+        
+        @Override
+        public <T> T unwrap(final Class<T> iface) throws SQLException {
+            if (iface.isInstance(this)) {
+                return iface.cast(this);
+            }
+            throw new SQLException(String.format("Unable to unwrap runtime 
database data source to `%s`.", iface.getName()));
+        }
+        
+        @Override
+        public boolean isWrapperFor(final Class<?> iface) {
+            return iface.isInstance(this);
+        }
+    }
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/RuntimeDatabaseProfile.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/RuntimeDatabaseProfile.java
index c7d041c2544..7033518c4fc 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/RuntimeDatabaseProfile.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/RuntimeDatabaseProfile.java
@@ -19,6 +19,7 @@ package 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc;
 
 import lombok.Getter;
 import lombok.RequiredArgsConstructor;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
 
 /**
  * Runtime database profile.
@@ -36,4 +37,6 @@ public final class RuntimeDatabaseProfile {
     private final boolean supportsTransaction;
     
     private final boolean supportsSavepoint;
+    
+    private final IdentifierCasePolicySet identifierCasePolicySet;
 }
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/tool/service/RuntimeDatabaseValidationService.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/tool/service/RuntimeDatabaseValidationService.java
index b6592b28126..454c9f3fb9c 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/tool/service/RuntimeDatabaseValidationService.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/database/tool/service/RuntimeDatabaseValidationService.java
@@ -17,6 +17,10 @@
 
 package org.apache.shardingsphere.mcp.support.database.tool.service;
 
+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.IdentifierCasePolicySet;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.MCPJdbcDatabaseProfileLoader;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.MCPJdbcMetadataLoader;
@@ -95,7 +99,7 @@ public final class RuntimeDatabaseValidationService {
             return createFailureResult(database, checks, ex, recoveryFactory);
         }
         try {
-            validateDatabaseVisibility(database, runtimeDatabaseConfig.get(), 
schemas);
+            validateDatabaseVisibility(database, runtimeDatabaseConfig.get(), 
schemas, databaseProfile.getIdentifierCasePolicySet());
             
checks.add(RuntimeDatabaseValidationCheckResult.passed("database_visibility", 
"Validated the requested database name against visible JDBC metadata and 
connection context."));
         } catch (final RuntimeDatabaseConnectionException ex) {
             
checks.add(RuntimeDatabaseValidationCheckResult.failed("database_visibility", 
ex.getCategory(), "The requested database name is not visible to the configured 
JDBC connection."));
@@ -133,12 +137,13 @@ public final class RuntimeDatabaseValidationService {
         return RuntimeDatabaseValidationResult.failed(database, checks, 
cause.getCategory(), recoveryFactory.apply(cause));
     }
     
-    private void validateDatabaseVisibility(final String database, final 
RuntimeDatabaseConfiguration runtimeDatabaseConfig, final 
Collection<ShardingSphereSchema> schemas) {
-        if (containsVisibleSchema(schemas, database)) {
+    private void validateDatabaseVisibility(final String database, final 
RuntimeDatabaseConfiguration runtimeDatabaseConfig, final 
Collection<ShardingSphereSchema> schemas,
+                                            final IdentifierCasePolicySet 
identifierCasePolicySet) {
+        if (containsVisibleSchema(schemas, database, 
identifierCasePolicySet.getPolicy(IdentifierScope.SCHEMA))) {
             return;
         }
         try (Connection connection = 
runtimeDatabaseConfig.openConnection(resolveExceptionDatabaseName(database))) {
-            if (isVisibleDatabase(connection, database)) {
+            if (isVisibleDatabase(connection, database, 
identifierCasePolicySet)) {
                 return;
             }
         } catch (final SQLException ex) {
@@ -148,26 +153,28 @@ public final class RuntimeDatabaseValidationService {
                 new IllegalStateException(String.format("Requested database 
`%s` is not visible to the configured JDBC connection.", database)));
     }
     
-    private boolean containsVisibleSchema(final 
Collection<ShardingSphereSchema> schemas, final String database) {
+    private boolean containsVisibleSchema(final 
Collection<ShardingSphereSchema> schemas, final String database, final 
IdentifierCasePolicy identifierCasePolicy) {
         for (ShardingSphereSchema each : schemas) {
-            if (database.equalsIgnoreCase(each.getName())) {
+            if (matches(each.getName(), database, identifierCasePolicy)) {
                 return true;
             }
         }
         return false;
     }
     
-    private boolean isVisibleDatabase(final Connection connection, final 
String database) throws SQLException {
-        return matches(connection.getCatalog(), database)
-                || matches(connection.getSchema(), database)
-                || containsCatalog(connection.getMetaData(), database)
-                || containsSchema(connection.getMetaData(), database);
+    private boolean isVisibleDatabase(final Connection connection, final 
String database, final IdentifierCasePolicySet identifierCasePolicySet) throws 
SQLException {
+        IdentifierCasePolicy databasePolicy = 
identifierCasePolicySet.getPolicy(IdentifierScope.DATABASE);
+        IdentifierCasePolicy schemaPolicy = 
identifierCasePolicySet.getPolicy(IdentifierScope.SCHEMA);
+        return matches(connection.getCatalog(), database, databasePolicy)
+                || matches(connection.getSchema(), database, schemaPolicy)
+                || containsCatalog(connection.getMetaData(), database, 
databasePolicy)
+                || containsSchema(connection.getMetaData(), database, 
schemaPolicy);
     }
     
-    private boolean containsCatalog(final DatabaseMetaData databaseMetaData, 
final String database) throws SQLException {
+    private boolean containsCatalog(final DatabaseMetaData databaseMetaData, 
final String database, final IdentifierCasePolicy identifierCasePolicy) throws 
SQLException {
         try (ResultSet resultSet = databaseMetaData.getCatalogs()) {
             while (resultSet.next()) {
-                if (matches(resultSet.getString(1), database)) {
+                if (matches(resultSet.getString(1), database, 
identifierCasePolicy)) {
                     return true;
                 }
             }
@@ -175,10 +182,10 @@ public final class RuntimeDatabaseValidationService {
         return false;
     }
     
-    private boolean containsSchema(final DatabaseMetaData databaseMetaData, 
final String database) throws SQLException {
+    private boolean containsSchema(final DatabaseMetaData databaseMetaData, 
final String database, final IdentifierCasePolicy identifierCasePolicy) throws 
SQLException {
         try (ResultSet resultSet = databaseMetaData.getSchemas()) {
             while (resultSet.next()) {
-                if (matches(resultSet.getString("TABLE_SCHEM"), database)) {
+                if (matches(resultSet.getString("TABLE_SCHEM"), database, 
identifierCasePolicy)) {
                     return true;
                 }
             }
@@ -186,8 +193,9 @@ public final class RuntimeDatabaseValidationService {
         return false;
     }
     
-    private boolean matches(final String actualValue, final String 
expectedValue) {
-        return !Objects.toString(actualValue, "").trim().isEmpty() && 
actualValue.trim().equalsIgnoreCase(expectedValue);
+    private boolean matches(final String storedName, final String identifier, 
final IdentifierCasePolicy identifierCasePolicy) {
+        String actualStoredName = Objects.toString(storedName, "").trim();
+        return !actualStoredName.isEmpty() && 
identifierCasePolicy.matches(actualStoredName, identifier, QuoteCharacter.NONE);
     }
     
     private String resolveExceptionDatabaseName(final String database) {
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityProviderTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityProviderTest.java
index 0ae8ace8025..54aaa387715 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityProviderTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/capability/MCPDatabaseCapabilityProviderTest.java
@@ -27,26 +27,17 @@ import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.Ide
 import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import 
org.apache.shardingsphere.database.connector.core.spi.DatabaseTypedSPILoader;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
-import 
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeFactory;
-import 
org.apache.shardingsphere.infra.metadata.identifier.IdentifierCasePolicyResolver;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
-import 
org.apache.shardingsphere.mcp.support.fixture.SupportDatabaseTypeFactoryMocker;
+import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.MCPJdbcDatabaseProfileLoader;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConfiguration;
-import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConnectionException;
+import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseProfile;
 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 org.mockito.MockedConstruction;
 import org.mockito.MockedStatic;
-import org.mockito.stubbing.Answer;
 
-import javax.sql.DataSource;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
 import java.util.EnumSet;
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -59,14 +50,10 @@ import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mockConstruction;
 import static org.mockito.Mockito.mockStatic;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 class MCPDatabaseCapabilityProviderTest {
@@ -105,37 +92,11 @@ class MCPDatabaseCapabilityProviderTest {
     
     @Test
     void assertProvideWithoutCapabilityOption() {
-        MCPDatabaseCapabilityProvider provider = 
createCapabilityProvider("FixtureDB", "",
-                new CapabilityFixture(false, false, false, 
DialectSchemaSemantics.NATIVE_SCHEMA));
+        MCPDatabaseCapabilityProvider provider = 
createCapabilityProvider("FixtureDB", new CapabilityFixture(false, false, 
false, DialectSchemaSemantics.NATIVE_SCHEMA));
         
assertThat(provider.findDatabaseProfile("logic_db").orElseThrow().getDatabaseType(),
 is("FixtureDB"));
         assertFalse(provider.provide("logic_db").isPresent());
     }
     
-    @Test
-    void assertResolveIdentifierCasePolicyPerDatabase() throws SQLException {
-        Connection firstConnection = mock(Connection.class);
-        Connection secondConnection = mock(Connection.class);
-        RuntimeDatabaseConfiguration firstRuntimeDatabase = 
createRuntimeDatabaseConfiguration("first_db", "MySQL", "", true, true, 
firstConnection);
-        RuntimeDatabaseConfiguration secondRuntimeDatabase = 
createRuntimeDatabaseConfiguration("second_db", "MySQL", "", true, true, 
secondConnection);
-        Map<String, RuntimeDatabaseConfiguration> runtimeDatabases = new 
LinkedHashMap<>(2, 1F);
-        runtimeDatabases.put("first_db", firstRuntimeDatabase);
-        runtimeDatabases.put("second_db", secondRuntimeDatabase);
-        Map<Connection, IdentifierCasePolicySet> policies = Map.of(
-                firstConnection, 
IdentifierCasePolicyFactory.newSensitivePolicySet(), secondConnection, 
IdentifierCasePolicyFactory.newInsensitivePolicySet());
-        MCPDatabaseCapabilityProvider provider = 
createCapabilityProvider(runtimeDatabases,
-                Map.of("MySQL", new CapabilityFixture(true, true, false, 
DialectSchemaSemantics.DATABASE_AS_SCHEMA)), invocation -> {
-                    try (Connection connection = invocation.getArgument(2, 
DataSource.class).getConnection()) {
-                        return policies.get(connection);
-                    }
-                });
-        
assertFalse(provider.provide("first_db").orElseThrow().getIdentifierCasePolicySet().getPolicy(IdentifierScope.TABLE).matches("phone",
 "Phone", QuoteCharacter.NONE));
-        
assertTrue(provider.provide("second_db").orElseThrow().getIdentifierCasePolicySet().getPolicy(IdentifierScope.TABLE).matches("phone",
 "Phone", QuoteCharacter.NONE));
-        verify(firstRuntimeDatabase, times(2)).openConnection("first_db");
-        verify(firstRuntimeDatabase, never()).openConnection("second_db");
-        verify(secondRuntimeDatabase, times(2)).openConnection("second_db");
-        verify(secondRuntimeDatabase, never()).openConnection("first_db");
-    }
-    
     @Test
     void assertPreserveScopedIdentifierCasePolicies() {
         IdentifierCasePolicySet insensitivePolicySet = 
IdentifierCasePolicyFactory.newInsensitivePolicySet();
@@ -143,34 +104,14 @@ class MCPDatabaseCapabilityProviderTest {
                 insensitivePolicySet.getPolicy(IdentifierScope.TABLE),
                 Map.of(IdentifierScope.TABLE, 
IdentifierCasePolicyFactory.newSensitivePolicySet().getPolicy(IdentifierScope.TABLE),
                         IdentifierScope.COLUMN, 
insensitivePolicySet.getPolicy(IdentifierScope.COLUMN)));
+        CapabilityFixture capabilityFixture = new CapabilityFixture(true, 
true, false, DialectSchemaSemantics.DATABASE_AS_SCHEMA);
         MCPDatabaseCapabilityProvider provider = createCapabilityProvider(
-                Map.of("logic_db", 
createRuntimeDatabaseConfiguration("logic_db", "MySQL", "", true, true)),
-                Map.of("MySQL", new CapabilityFixture(true, true, false, 
DialectSchemaSemantics.DATABASE_AS_SCHEMA)), invocation -> scopedPolicySet);
+                Map.of("logic_db", createDatabaseProfile("logic_db", "MySQL", 
capabilityFixture, scopedPolicySet)), Map.of("MySQL", capabilityFixture));
         IdentifierCasePolicySet actual = 
provider.provide("logic_db").orElseThrow().getIdentifierCasePolicySet();
         assertFalse(actual.getPolicy(IdentifierScope.TABLE).matches("phone", 
"Phone", QuoteCharacter.NONE));
         assertTrue(actual.getPolicy(IdentifierScope.COLUMN).matches("phone", 
"Phone", QuoteCharacter.NONE));
     }
     
-    @Test
-    void assertResolveIdentifierCasePolicyWhenRuntimeConnectionFails() throws 
SQLException {
-        SQLException connectionFailure = new SQLException("connection 
unavailable");
-        Connection profileConnection = mock(Connection.class);
-        RuntimeDatabaseConfiguration runtimeDatabase = 
createRuntimeDatabaseConfiguration("logic_db", "MySQL", "", true, true, 
profileConnection);
-        
when(runtimeDatabase.openConnection("logic_db")).thenReturn(profileConnection)
-                
.thenThrow(RuntimeDatabaseConnectionException.connectionFailed("logic_db", 
connectionFailure));
-        MCPDatabaseCapabilityProvider provider = 
createCapabilityProvider(Map.of("logic_db", runtimeDatabase),
-                Map.of("MySQL", new CapabilityFixture(true, true, false, 
DialectSchemaSemantics.DATABASE_AS_SCHEMA)), invocation -> {
-                    try (Connection ignored = invocation.getArgument(2, 
DataSource.class).getConnection()) {
-                        return 
IdentifierCasePolicyFactory.newSensitivePolicySet();
-                    } catch (final SQLException ex) {
-                        assertThat(ex, is(connectionFailure));
-                        return 
IdentifierCasePolicyFactory.newInsensitivePolicySet();
-                    }
-                });
-        
assertTrue(provider.provide("logic_db").orElseThrow().getIdentifierCasePolicySet().getPolicy(IdentifierScope.TABLE).matches("phone",
 "Phone", QuoteCharacter.NONE));
-        verify(runtimeDatabase, times(2)).openConnection("logic_db");
-    }
-    
     @ParameterizedTest(name = "{0}")
     @MethodSource("provideCapabilityMatrixArguments")
     void assertProvideWithCapabilityMatrix(final String name, final String 
databaseType, final boolean expectedTransactionControl,
@@ -178,7 +119,7 @@ class MCPDatabaseCapabilityProviderTest {
                                            final SchemaExecutionSemantics 
expectedSchemaExecutionSemantics, final boolean expectedExplainSupport) {
         CapabilityFixture capabilityFixture = new 
CapabilityFixture(expectedTransactionControl, expectedSavepoint, 
expectedSequenceSupport,
                 SchemaExecutionSemantics.FIXED_TO_DATABASE == 
expectedSchemaExecutionSemantics ? DialectSchemaSemantics.DATABASE_AS_SCHEMA : 
DialectSchemaSemantics.NATIVE_SCHEMA);
-        Optional<MCPDatabaseCapability> actual = 
createCapabilityProvider(databaseType, "", 
capabilityFixture).provide("logic_db");
+        Optional<MCPDatabaseCapability> actual = 
createCapabilityProvider(databaseType, capabilityFixture).provide("logic_db");
         assertTrue(actual.isPresent());
         assertThat(actual.get().isSupportsTransactionControl(), 
is(expectedTransactionControl));
         assertThat(actual.get().isSupportsSavepoint(), is(expectedSavepoint));
@@ -193,34 +134,29 @@ class MCPDatabaseCapabilityProviderTest {
         Map<String, CapabilityFixture> capabilityFixtures = Map.of(
                 "MySQL", new CapabilityFixture(true, true, false, 
DialectSchemaSemantics.DATABASE_AS_SCHEMA),
                 "Hive", new CapabilityFixture(false, false, false, 
DialectSchemaSemantics.DATABASE_AS_SCHEMA));
-        return 
createCapabilityProvider(createRuntimeDatabases(Map.of("logic_db", "MySQL", 
"warehouse", "Hive"), capabilityFixtures), capabilityFixtures);
+        Map<String, RuntimeDatabaseProfile> databaseProfiles = new 
LinkedHashMap<>(2, 1F);
+        databaseProfiles.put("logic_db", createDatabaseProfile("logic_db", 
"MySQL", capabilityFixtures.get("MySQL"), 
IdentifierCasePolicyFactory.newSensitivePolicySet()));
+        databaseProfiles.put("warehouse", createDatabaseProfile("warehouse", 
"Hive", capabilityFixtures.get("Hive"), 
IdentifierCasePolicyFactory.newSensitivePolicySet()));
+        return createCapabilityProvider(databaseProfiles, capabilityFixtures);
     }
     
-    private MCPDatabaseCapabilityProvider createCapabilityProvider(final 
String databaseType, final String databaseVersion, final CapabilityFixture 
capabilityFixture) {
-        return createCapabilityProvider(Map.of("logic_db", 
createRuntimeDatabaseConfiguration("logic_db", databaseType, databaseVersion,
-                capabilityFixture.transactionSupported, 
capabilityFixture.savepointSupported)),
+    private MCPDatabaseCapabilityProvider createCapabilityProvider(final 
String databaseType, final CapabilityFixture capabilityFixture) {
+        return createCapabilityProvider(Map.of("logic_db", 
createDatabaseProfile(
+                "logic_db", databaseType, capabilityFixture, 
IdentifierCasePolicyFactory.newSensitivePolicySet())),
                 Map.of(databaseType, capabilityFixture));
     }
     
-    private MCPDatabaseCapabilityProvider createCapabilityProvider(final 
Map<String, RuntimeDatabaseConfiguration> runtimeDatabases,
+    private MCPDatabaseCapabilityProvider createCapabilityProvider(final 
Map<String, RuntimeDatabaseProfile> databaseProfiles,
                                                                    final 
Map<String, CapabilityFixture> capabilityFixtures) {
-        return createCapabilityProvider(runtimeDatabases, capabilityFixtures, 
invocation -> {
-            try (Connection ignored = invocation.getArgument(2, 
DataSource.class).getConnection()) {
-                return IdentifierCasePolicyFactory.newSensitivePolicySet();
-            }
-        });
-    }
-    
-    private MCPDatabaseCapabilityProvider createCapabilityProvider(final 
Map<String, RuntimeDatabaseConfiguration> runtimeDatabases,
-                                                                   final 
Map<String, CapabilityFixture> capabilityFixtures,
-                                                                   final 
Answer<IdentifierCasePolicySet> identifierCasePolicyResolverAnswer) {
+        Map<String, RuntimeDatabaseConfiguration> runtimeDatabases = new 
LinkedHashMap<>(databaseProfiles.size(), 1F);
+        for (String each : databaseProfiles.keySet()) {
+            runtimeDatabases.put(each, 
mock(RuntimeDatabaseConfiguration.class));
+        }
         try (
-                MockedStatic<DatabaseTypeFactory> ignored = 
SupportDatabaseTypeFactoryMocker.mockByConnectionMetadata();
+                MockedConstruction<MCPJdbcDatabaseProfileLoader> ignored = 
mockConstruction(MCPJdbcDatabaseProfileLoader.class,
+                        (mock, context) -> 
when(mock.load(any())).thenReturn(databaseProfiles));
                 MockedStatic<TypedSPILoader> typedSPILoader = 
mockStatic(TypedSPILoader.class, CALLS_REAL_METHODS);
-                MockedStatic<DatabaseTypedSPILoader> databaseTypedSPILoader = 
mockStatic(DatabaseTypedSPILoader.class);
-                MockedConstruction<IdentifierCasePolicyResolver> 
ignoredResolver =
-                        mockConstruction(IdentifierCasePolicyResolver.class,
-                                (mock, context) -> when(mock.resolve(any(), 
any(), any())).thenAnswer(identifierCasePolicyResolverAnswer))) {
+                MockedStatic<DatabaseTypedSPILoader> databaseTypedSPILoader = 
mockStatic(DatabaseTypedSPILoader.class)) {
             for (Entry<String, CapabilityFixture> entry : 
capabilityFixtures.entrySet()) {
                 mockDatabaseType(entry.getKey(), entry.getValue(), 
typedSPILoader, databaseTypedSPILoader);
             }
@@ -242,41 +178,9 @@ class MCPDatabaseCapabilityProviderTest {
         databaseTypedSPILoader.when(() -> 
DatabaseTypedSPILoader.findService(DialectDatabaseMetaData.class, 
databaseTypeFromSPI)).thenReturn(Optional.of(dialectDatabaseMetaData));
     }
     
-    private Map<String, RuntimeDatabaseConfiguration> 
createRuntimeDatabases(final Map<String, String> databaseTypes, final 
Map<String, CapabilityFixture> capabilityFixtures) {
-        Map<String, RuntimeDatabaseConfiguration> result = new 
LinkedHashMap<>(databaseTypes.size(), 1F);
-        for (Entry<String, String> entry : databaseTypes.entrySet()) {
-            CapabilityFixture capabilityFixture = 
capabilityFixtures.get(entry.getValue());
-            result.put(entry.getKey(), 
createRuntimeDatabaseConfiguration(entry.getKey(), entry.getValue(), "",
-                    capabilityFixture.transactionSupported, 
capabilityFixture.savepointSupported));
-        }
-        return result;
-    }
-    
-    private RuntimeDatabaseConfiguration 
createRuntimeDatabaseConfiguration(final String databaseName, final String 
databaseType, final String databaseVersion,
-                                                                            
final boolean transactionSupported, final boolean savepointSupported) {
-        return createRuntimeDatabaseConfiguration(databaseName, databaseType, 
databaseVersion, transactionSupported, savepointSupported, 
mock(Connection.class));
-    }
-    
-    private RuntimeDatabaseConfiguration 
createRuntimeDatabaseConfiguration(final String databaseName, final String 
databaseType, final String databaseVersion,
-                                                                            
final boolean transactionSupported, final boolean savepointSupported, final 
Connection connection) {
-        RuntimeDatabaseConfiguration result = 
mock(RuntimeDatabaseConfiguration.class);
-        try {
-            DatabaseMetaData databaseMetaData = mock(DatabaseMetaData.class);
-            Statement statement = mock(Statement.class);
-            ResultSet scalarResultSet = mock(ResultSet.class);
-            when(result.openConnection(databaseName)).thenReturn(connection);
-            when(connection.getMetaData()).thenReturn(databaseMetaData);
-            when(connection.createStatement()).thenReturn(statement);
-            
when(statement.executeQuery(anyString())).thenReturn(scalarResultSet);
-            when(scalarResultSet.next()).thenReturn(false);
-            
when(databaseMetaData.getDatabaseProductVersion()).thenReturn(databaseVersion);
-            
when(databaseMetaData.supportsTransactions()).thenReturn(transactionSupported);
-            
when(databaseMetaData.supportsSavepoints()).thenReturn(savepointSupported);
-            
when(databaseMetaData.getURL()).thenReturn(SupportDatabaseTypeFactoryMocker.createJdbcUrl(databaseType));
-        } catch (final SQLException ex) {
-            throw new IllegalStateException(ex);
-        }
-        return result;
+    private RuntimeDatabaseProfile createDatabaseProfile(final String 
databaseName, final String databaseType, final CapabilityFixture 
capabilityFixture,
+                                                         final 
IdentifierCasePolicySet identifierCasePolicySet) {
+        return new RuntimeDatabaseProfile(databaseName, databaseType, "", 
capabilityFixture.transactionSupported, capabilityFixture.savepointSupported, 
identifierCasePolicySet);
     }
     
     private static Stream<Arguments> provideCapabilityMatrixArguments() {
@@ -287,8 +191,8 @@ class MCPDatabaseCapabilityProviderTest {
                 Arguments.of("sql server", "SQLServer", true, true, true, 
SchemaExecutionSemantics.BEST_EFFORT, false),
                 Arguments.of("mariadb", "MariaDB", true, true, true, 
SchemaExecutionSemantics.FIXED_TO_DATABASE, true),
                 Arguments.of("oracle", "Oracle", true, true, true, 
SchemaExecutionSemantics.BEST_EFFORT, false),
-                Arguments.of("clickhouse", "ClickHouse", false, false, false, 
SchemaExecutionSemantics.FIXED_TO_DATABASE, false),
-                Arguments.of("hive", "Hive", false, false, false, 
SchemaExecutionSemantics.FIXED_TO_DATABASE, false),
+                Arguments.of("clickhouse", "ClickHouse", false, false, false, 
SchemaExecutionSemantics.FIXED_TO_DATABASE, true),
+                Arguments.of("hive", "Hive", false, false, false, 
SchemaExecutionSemantics.FIXED_TO_DATABASE, true),
                 Arguments.of("presto", "Presto", true, false, false, 
SchemaExecutionSemantics.BEST_EFFORT, true),
                 Arguments.of("firebird", "Firebird", true, true, true, 
SchemaExecutionSemantics.BEST_EFFORT, false));
     }
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoaderTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoaderTest.java
index 169fda8e66a..2d6b539f87c 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoaderTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcDatabaseProfileLoaderTest.java
@@ -17,15 +17,24 @@
 
 package org.apache.shardingsphere.mcp.support.database.metadata.jdbc;
 
+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.database.connector.core.metadata.identifier.IdentifierScope;
 import 
org.apache.shardingsphere.database.connector.core.type.DatabaseTypeFactory;
 import 
org.apache.shardingsphere.infra.exception.external.ShardingSphereExternalException;
+import 
org.apache.shardingsphere.infra.metadata.identifier.IdentifierCasePolicyResolver;
 import 
org.apache.shardingsphere.mcp.support.fixture.SupportDatabaseTypeFactoryMocker;
 import org.junit.jupiter.api.Test;
+import org.mockito.MockedConstruction;
 import org.mockito.MockedStatic;
 
+import javax.sql.DataSource;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.SQLException;
+import java.util.LinkedHashMap;
+import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -35,14 +44,22 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockConstruction;
 import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 class MCPJdbcDatabaseProfileLoaderTest {
     
     @Test
     void assertLoad() throws SQLException {
-        try (MockedStatic<DatabaseTypeFactory> ignored = 
SupportDatabaseTypeFactoryMocker.mockByConnectionMetadata()) {
+        IdentifierCasePolicySet expectedIdentifierCasePolicySet = 
IdentifierCasePolicyFactory.newSensitivePolicySet();
+        try (
+                MockedStatic<DatabaseTypeFactory> ignored = 
SupportDatabaseTypeFactoryMocker.mockByConnectionMetadata();
+                MockedConstruction<IdentifierCasePolicyResolver> 
ignoredResolver = mockConstruction(IdentifierCasePolicyResolver.class,
+                        (mock, context) -> when(mock.resolve(any(), any(), 
any())).thenReturn(expectedIdentifierCasePolicySet))) {
             RuntimeDatabaseProfile actual =
                     new MCPJdbcDatabaseProfileLoader().load("logic_db", 
createRuntimeDatabaseConfiguration(SupportDatabaseTypeFactoryMocker.createJdbcUrl("FixtureDB"),
 "1.0", true, true));
             assertThat(actual.getDatabase(), is("logic_db"));
@@ -50,6 +67,7 @@ class MCPJdbcDatabaseProfileLoaderTest {
             assertThat(actual.getDatabaseVersion(), is("1.0"));
             assertTrue(actual.isSupportsTransaction());
             assertTrue(actual.isSupportsSavepoint());
+            assertThat(actual.getIdentifierCasePolicySet(), 
is(expectedIdentifierCasePolicySet));
         }
     }
     
@@ -63,6 +81,62 @@ class MCPJdbcDatabaseProfileLoaderTest {
         }
     }
     
+    @Test
+    void assertLoadIdentifierCasePolicyPerDatabase() throws SQLException {
+        Connection firstConnection = mock(Connection.class);
+        Connection secondConnection = mock(Connection.class);
+        RuntimeDatabaseConfiguration firstRuntimeDatabase = 
createRuntimeDatabaseConfiguration(
+                SupportDatabaseTypeFactoryMocker.createJdbcUrl("FixtureDB"), 
"1.0", true, true, firstConnection);
+        RuntimeDatabaseConfiguration secondRuntimeDatabase = 
createRuntimeDatabaseConfiguration(
+                SupportDatabaseTypeFactoryMocker.createJdbcUrl("FixtureDB"), 
"1.0", true, true, secondConnection);
+        Map<String, RuntimeDatabaseConfiguration> runtimeDatabases = new 
LinkedHashMap<>(2, 1F);
+        runtimeDatabases.put("first_db", firstRuntimeDatabase);
+        runtimeDatabases.put("second_db", secondRuntimeDatabase);
+        Map<Connection, IdentifierCasePolicySet> policies = Map.of(
+                firstConnection, 
IdentifierCasePolicyFactory.newSensitivePolicySet(), secondConnection, 
IdentifierCasePolicyFactory.newInsensitivePolicySet());
+        try (
+                MockedStatic<DatabaseTypeFactory> ignored = 
SupportDatabaseTypeFactoryMocker.mockByConnectionMetadata();
+                MockedConstruction<IdentifierCasePolicyResolver> 
ignoredResolver = mockConstruction(IdentifierCasePolicyResolver.class,
+                        (mock, context) -> when(mock.resolve(any(), any(), 
any())).thenAnswer(invocation -> {
+                            try (Connection connection = 
invocation.getArgument(2, DataSource.class).getConnection()) {
+                                return policies.get(connection);
+                            }
+                        }))) {
+            Map<String, RuntimeDatabaseProfile> actual = new 
MCPJdbcDatabaseProfileLoader().load(runtimeDatabases);
+            
assertFalse(actual.get("first_db").getIdentifierCasePolicySet().getPolicy(IdentifierScope.TABLE).matches("phone",
 "Phone", QuoteCharacter.NONE));
+            
assertTrue(actual.get("second_db").getIdentifierCasePolicySet().getPolicy(IdentifierScope.TABLE).matches("phone",
 "Phone", QuoteCharacter.NONE));
+            verify(firstRuntimeDatabase, times(2)).openConnection("first_db");
+            verify(firstRuntimeDatabase, never()).openConnection("second_db");
+            verify(secondRuntimeDatabase, 
times(2)).openConnection("second_db");
+            verify(secondRuntimeDatabase, never()).openConnection("first_db");
+        }
+    }
+    
+    @Test
+    void assertLoadWhenIdentifierCasePolicyConnectionFails() throws 
SQLException {
+        SQLException connectionFailure = new SQLException("connection 
unavailable");
+        Connection profileConnection = mock(Connection.class);
+        RuntimeDatabaseConfiguration runtimeDatabaseConfig = 
createRuntimeDatabaseConfiguration(
+                SupportDatabaseTypeFactoryMocker.createJdbcUrl("FixtureDB"), 
"1.0", true, true, profileConnection);
+        
when(runtimeDatabaseConfig.openConnection("logic_db")).thenReturn(profileConnection)
+                
.thenThrow(RuntimeDatabaseConnectionException.connectionFailed("logic_db", 
connectionFailure));
+        try (
+                MockedStatic<DatabaseTypeFactory> ignored = 
SupportDatabaseTypeFactoryMocker.mockByConnectionMetadata();
+                MockedConstruction<IdentifierCasePolicyResolver> 
ignoredResolver = mockConstruction(IdentifierCasePolicyResolver.class,
+                        (mock, context) -> when(mock.resolve(any(), any(), 
any())).thenAnswer(invocation -> {
+                            try (Connection ignoredConnection = 
invocation.getArgument(2, DataSource.class).getConnection()) {
+                                return 
IdentifierCasePolicyFactory.newSensitivePolicySet();
+                            } catch (final SQLException ex) {
+                                assertThat(ex, is(connectionFailure));
+                                return 
IdentifierCasePolicyFactory.newInsensitivePolicySet();
+                            }
+                        }))) {
+            RuntimeDatabaseProfile actual = new 
MCPJdbcDatabaseProfileLoader().load("logic_db", runtimeDatabaseConfig);
+            
assertTrue(actual.getIdentifierCasePolicySet().getPolicy(IdentifierScope.TABLE).matches("phone",
 "Phone", QuoteCharacter.NONE));
+            verify(runtimeDatabaseConfig, times(2)).openConnection("logic_db");
+        }
+    }
+    
     @Test
     void assertLoadWithInvalidJdbcUrl() {
         try (MockedStatic<DatabaseTypeFactory> mocked = 
mockStatic(DatabaseTypeFactory.class)) {
@@ -77,8 +151,13 @@ class MCPJdbcDatabaseProfileLoaderTest {
     
     private RuntimeDatabaseConfiguration 
createRuntimeDatabaseConfiguration(final String jdbcUrl, final String 
databaseVersion,
                                                                             
final boolean supportsTransaction, final boolean supportsSavepoint) throws 
SQLException {
+        return createRuntimeDatabaseConfiguration(jdbcUrl, databaseVersion, 
supportsTransaction, supportsSavepoint, mock(Connection.class));
+    }
+    
+    private RuntimeDatabaseConfiguration 
createRuntimeDatabaseConfiguration(final String jdbcUrl, final String 
databaseVersion,
+                                                                            
final boolean supportsTransaction, final boolean supportsSavepoint,
+                                                                            
final Connection connection) throws SQLException {
         RuntimeDatabaseConfiguration result = 
mock(RuntimeDatabaseConfiguration.class);
-        Connection connection = mock(Connection.class);
         DatabaseMetaData databaseMetaData = mock(DatabaseMetaData.class);
         when(result.openConnection(anyString())).thenReturn(connection);
         when(connection.getMetaData()).thenReturn(databaseMetaData);
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcMetadataLoaderFailureTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcMetadataLoaderFailureTest.java
index 6b0cd6b7f6c..d4e4334ea55 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcMetadataLoaderFailureTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/MCPJdbcMetadataLoaderFailureTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.support.database.metadata.jdbc;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import org.junit.jupiter.api.Test;
 
 import java.sql.SQLException;
@@ -36,7 +37,8 @@ class MCPJdbcMetadataLoaderFailureTest {
         
when(runtimeDatabaseConfiguration.openConnection("logic_db")).thenThrow(expected);
         MCPJdbcMetadataLoader metadataLoader = new MCPJdbcMetadataLoader();
         RuntimeDatabaseConnectionException actual = 
assertThrows(RuntimeDatabaseConnectionException.class,
-                () -> metadataLoader.load("logic_db", 
runtimeDatabaseConfiguration, new RuntimeDatabaseProfile("logic_db", 
"FixtureDB", "", true, true)));
+                () -> metadataLoader.load("logic_db", 
runtimeDatabaseConfiguration,
+                        new RuntimeDatabaseProfile("logic_db", "FixtureDB", 
"", true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet())));
         assertThat(actual.getMessage(), is("Runtime database `logic_db` 
connection failed: connection_failed."));
         assertThat(actual.getCause(), is(expected));
     }
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/tool/service/RuntimeDatabaseValidationServiceTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/tool/service/RuntimeDatabaseValidationServiceTest.java
index 54c895dd707..2a45094769e 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/tool/service/RuntimeDatabaseValidationServiceTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/tool/service/RuntimeDatabaseValidationServiceTest.java
@@ -17,6 +17,9 @@
 
 package org.apache.shardingsphere.mcp.support.database.tool.service;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicySet;
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.MCPJdbcDatabaseProfileLoader;
@@ -127,8 +130,12 @@ class RuntimeDatabaseValidationServiceTest {
         MCPJdbcDatabaseProfileLoader profileLoader = getProfileLoader();
         MCPJdbcMetadataLoader metadataLoader = getMetadataLoader();
         RuntimeDatabaseConfiguration runtimeDatabaseConfig = 
createRuntimeDatabaseConfiguration();
-        when(profileLoader.load(any(), 
any(RuntimeDatabaseConfiguration.class))).thenReturn(createProfile());
-        when(metadataLoader.load(any(), 
any(RuntimeDatabaseConfiguration.class), 
any(RuntimeDatabaseProfile.class))).thenReturn(createMetadata("logic_db"));
+        IdentifierCasePolicySet identifierCasePolicySet = new 
IdentifierCasePolicySet(
+                
IdentifierCasePolicyFactory.newSensitivePolicySet().getPolicy(IdentifierScope.TABLE),
+                Map.of(IdentifierScope.SCHEMA, 
IdentifierCasePolicyFactory.newInsensitivePolicySet().getPolicy(IdentifierScope.SCHEMA)));
+        when(profileLoader.load(any(), 
any(RuntimeDatabaseConfiguration.class)))
+                .thenReturn(new RuntimeDatabaseProfile("logic_db", 
"FixtureDB", "1.0", true, true, identifierCasePolicySet));
+        when(metadataLoader.load(any(), 
any(RuntimeDatabaseConfiguration.class), 
any(RuntimeDatabaseProfile.class))).thenReturn(createMetadata("Logic_DB"));
         RuntimeDatabaseValidationResult actual = service.validate(new 
RuntimeDatabaseValidationRequest("logic_db"),
                 ignored -> Optional.of(runtimeDatabaseConfig), 
RuntimeDatabaseValidationServiceTest::createRecoveryPayload);
         Map<String, Object> actualPayload = actual.toPayload();
@@ -142,8 +149,9 @@ class RuntimeDatabaseValidationServiceTest {
         MCPJdbcDatabaseProfileLoader profileLoader = getProfileLoader();
         MCPJdbcMetadataLoader metadataLoader = getMetadataLoader();
         RuntimeDatabaseConfiguration runtimeDatabaseConfig = new 
RuntimeDatabaseConfiguration(InvisibleDatabaseDriver.JDBC_URL, "demo", "", 
InvisibleDatabaseDriver.class.getName());
-        when(profileLoader.load(any(), 
any(RuntimeDatabaseConfiguration.class))).thenReturn(createProfile());
-        when(metadataLoader.load(any(), 
any(RuntimeDatabaseConfiguration.class), 
any(RuntimeDatabaseProfile.class))).thenReturn(createMetadata("public"));
+        when(profileLoader.load(any(), 
any(RuntimeDatabaseConfiguration.class))).thenReturn(
+                new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newSensitivePolicySet()));
+        when(metadataLoader.load(any(), 
any(RuntimeDatabaseConfiguration.class), 
any(RuntimeDatabaseProfile.class))).thenReturn(createMetadata("Logic_DB"));
         RuntimeDatabaseValidationResult actual = service.validate(new 
RuntimeDatabaseValidationRequest("logic_db"),
                 ignored -> Optional.of(runtimeDatabaseConfig), 
RuntimeDatabaseValidationServiceTest::createRecoveryPayload);
         Map<String, Object> actualPayload = actual.toPayload();
@@ -153,6 +161,24 @@ class RuntimeDatabaseValidationServiceTest {
         assertThat(((Map<?, ?>) ((List<?>) 
actualPayload.get("checks")).get(4)).get("status"), is("failed"));
     }
     
+    @Test
+    void assertValidateWithVisibleCatalog() throws SQLException {
+        RuntimeDatabaseValidationService service = new 
RuntimeDatabaseValidationService();
+        RuntimeDatabaseConfiguration runtimeDatabaseConfig = 
mock(RuntimeDatabaseConfiguration.class);
+        Connection connection = mock(Connection.class);
+        
when(runtimeDatabaseConfig.openConnection("logic_db")).thenReturn(connection);
+        when(connection.getCatalog()).thenReturn("Logic_DB");
+        IdentifierCasePolicySet identifierCasePolicySet = new 
IdentifierCasePolicySet(
+                
IdentifierCasePolicyFactory.newInsensitivePolicySet().getPolicy(IdentifierScope.TABLE),
+                Map.of(IdentifierScope.SCHEMA, 
IdentifierCasePolicyFactory.newSensitivePolicySet().getPolicy(IdentifierScope.SCHEMA)));
+        when(getProfileLoader().load(any(), 
any(RuntimeDatabaseConfiguration.class)))
+                .thenReturn(new RuntimeDatabaseProfile("logic_db", 
"FixtureDB", "1.0", true, true, identifierCasePolicySet));
+        when(getMetadataLoader().load(any(), 
any(RuntimeDatabaseConfiguration.class), 
any(RuntimeDatabaseProfile.class))).thenReturn(createMetadata("public"));
+        RuntimeDatabaseValidationResult actual = service.validate(new 
RuntimeDatabaseValidationRequest("logic_db"),
+                ignored -> Optional.of(runtimeDatabaseConfig), 
RuntimeDatabaseValidationServiceTest::createRecoveryPayload);
+        assertThat(actual.toPayload().get("status"), is("ready"));
+    }
+    
     @Test
     void assertValidateWithMetadataReadFailure() {
         RuntimeDatabaseValidationService service = new 
RuntimeDatabaseValidationService();
@@ -215,7 +241,7 @@ class RuntimeDatabaseValidationServiceTest {
     }
     
     private static RuntimeDatabaseProfile createProfile() {
-        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true);
+        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet());
     }
     
     private static RuntimeDatabaseConfiguration 
createRuntimeDatabaseConfiguration() {
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningContextValidatorTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningContextValidatorTest.java
index 90ee55038f1..c8388c9de89 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningContextValidatorTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningContextValidatorTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.support.workflow.service;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.TableType;
 import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
@@ -186,7 +187,7 @@ class WorkflowPlanningContextValidatorTest {
     }
     
     private RuntimeDatabaseProfile createDatabaseMetadata() {
-        return new RuntimeDatabaseProfile("logic_db", "Fixture", "1.0", true, 
true);
+        return new RuntimeDatabaseProfile("logic_db", "Fixture", "1.0", true, 
true, IdentifierCasePolicyFactory.newInsensitivePolicySet());
     }
     
     private ShardingSphereSchema createSchemaMetadata() {
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningSupportTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningSupportTest.java
index f90c078b005..2cd816f21a4 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningSupportTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningSupportTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.support.workflow.service;
 
+import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierCasePolicyFactory;
 import 
org.apache.shardingsphere.database.connector.core.metadata.database.enums.TableType;
 import 
org.apache.shardingsphere.database.connector.core.metadata.identifier.IdentifierScope;
 import org.apache.shardingsphere.database.connector.core.type.DatabaseType;
@@ -354,7 +355,7 @@ class WorkflowPlanningSupportTest {
     }
     
     private RuntimeDatabaseProfile createDatabaseMetadata() {
-        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true);
+        return new RuntimeDatabaseProfile("logic_db", "FixtureDB", "1.0", 
true, true, IdentifierCasePolicyFactory.newInsensitivePolicySet());
     }
     
     private ShardingSphereSchema createSchemaMetadata(final String schemaName, 
final String tableName, final String columnName) {

Reply via email to