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 0ab7543beaa Fix firebird blob registry actual table name (#40099)
0ab7543beaa is described below

commit 0ab7543beaa5c9ee4b30c56a54703cee5f485f3b
Author: Maxim Igoshin <[email protected]>
AuthorDate: Thu Oct 15 18:05:29 2026 +0300

    Fix firebird blob registry actual table name (#40099)
    
    * Key Firebird BLOB column registry by actual table name
    
    Tables whose names differ only by trailing digits shared one registry 
entry, so BLOB columns of one table were described with the sub type of another 
or lost. Store BLOB columns by the actual table name loaded from the database 
and look up the actual table of a logic table through the data node rule 
attributes.
    
    * Mark Firebird actual table name lookup as high frequency invocation
    
    Name the described column packet in the sharding table test 
actualColumnPacket.
    
    * Trigger CI
---
 .../metadata/data/FirebirdBlobInfoRegistry.java      | 17 ++++-------------
 .../metadata/data/FirebirdBlobInfoRegistryTest.java  |  9 ++++++++-
 .../FirebirdPrepareStatementCommandExecutor.java     | 19 +++++++++++++++++--
 .../FirebirdPrepareStatementCommandExecutorTest.java | 20 ++++++++++++++++++++
 4 files changed, 49 insertions(+), 16 deletions(-)

diff --git 
a/database/connector/dialect/firebird/src/main/java/org/apache/shardingsphere/database/connector/firebird/metadata/data/FirebirdBlobInfoRegistry.java
 
b/database/connector/dialect/firebird/src/main/java/org/apache/shardingsphere/database/connector/firebird/metadata/data/FirebirdBlobInfoRegistry.java
index 13987445e04..53a6384f31a 100644
--- 
a/database/connector/dialect/firebird/src/main/java/org/apache/shardingsphere/database/connector/firebird/metadata/data/FirebirdBlobInfoRegistry.java
+++ 
b/database/connector/dialect/firebird/src/main/java/org/apache/shardingsphere/database/connector/firebird/metadata/data/FirebirdBlobInfoRegistry.java
@@ -40,7 +40,7 @@ public final class FirebirdBlobInfoRegistry {
      * Refresh blob column metadata for a table.
      *
      * @param schemaName schema name
-     * @param tableName table name
+     * @param tableName actual table name
      * @param blobColumns blob column name to subtype mapping
      */
     public static void refreshTable(final String schemaName, final String 
tableName, final Map<String, Integer> blobColumns) {
@@ -69,7 +69,7 @@ public final class FirebirdBlobInfoRegistry {
      * Determine whether column is a Firebird blob column.
      *
      * @param schemaName schema name
-     * @param tableName table name
+     * @param tableName actual table name
      * @param columnName column name
      * @return whether column is a blob column
      */
@@ -85,7 +85,7 @@ public final class FirebirdBlobInfoRegistry {
      * Find blob subtype for a column.
      *
      * @param schemaName schema name
-     * @param tableName table name
+     * @param tableName actual table name
      * @param columnName column name
      * @return blob subtype if present
      */
@@ -103,16 +103,7 @@ public final class FirebirdBlobInfoRegistry {
     
     private static String buildTableKey(final String schemaName, final String 
tableName) {
         String schemaKey = null == schemaName ? "" : toKey(schemaName);
-        String logicTable = trimToLogicTableName(tableName);
-        return schemaKey + "." + toKey(logicTable);
-    }
-    
-    private static String trimToLogicTableName(final String tableName) {
-        int end = tableName.length() - 1;
-        while (end >= 0 && !Character.isLetter(tableName.charAt(end))) {
-            end--;
-        }
-        return end < 0 ? tableName : tableName.substring(0, end + 1);
+        return schemaKey + "." + toKey(tableName);
     }
     
     private static String toKey(final String value) {
diff --git 
a/database/connector/dialect/firebird/src/test/java/org/apache/shardingsphere/database/connector/firebird/metadata/data/FirebirdBlobInfoRegistryTest.java
 
b/database/connector/dialect/firebird/src/test/java/org/apache/shardingsphere/database/connector/firebird/metadata/data/FirebirdBlobInfoRegistryTest.java
index 2d2d493122c..01cc62e291b 100644
--- 
a/database/connector/dialect/firebird/src/test/java/org/apache/shardingsphere/database/connector/firebird/metadata/data/FirebirdBlobInfoRegistryTest.java
+++ 
b/database/connector/dialect/firebird/src/test/java/org/apache/shardingsphere/database/connector/firebird/metadata/data/FirebirdBlobInfoRegistryTest.java
@@ -69,11 +69,18 @@ class FirebirdBlobInfoRegistryTest {
         assertThat(blobColumns.get("SENTINEL").get("EXISTING_COL"), is(9));
     }
     
+    @Test
+    void assertRefreshTableWhenOtherTableDiffersOnlyBySuffix() {
+        FirebirdBlobInfoRegistry.refreshTable("schema_a", "t1", 
Collections.singletonMap("blob_col", 1));
+        FirebirdBlobInfoRegistry.refreshTable("schema_a", "t2", 
Collections.emptyMap());
+        assertTrue(FirebirdBlobInfoRegistry.isBlobColumn("schema_a", "t1", 
"blob_col"));
+    }
+    
     @Test
     void assertRefreshTable() {
         Map<String, Integer> newColumns = createColumnsWithMixedNames();
         FirebirdBlobInfoRegistry.refreshTable(null, "table_1", newColumns);
-        Map<String, Integer> actual = blobColumns.get(".TABLE");
+        Map<String, Integer> actual = blobColumns.get(".TABLE_1");
         assertTrue(actual.containsKey("BLOB_COL"));
         assertThat(actual.get("BLOB_COL"), is(2));
         assertThat(actual.size(), is(1));
diff --git 
a/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
 
b/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
index e06ad8a3cb0..697066b8e60 100644
--- 
a/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
+++ 
b/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutor.java
@@ -30,6 +30,7 @@ import 
org.apache.shardingsphere.database.protocol.firebird.packet.command.query
 import 
org.apache.shardingsphere.database.protocol.firebird.packet.command.query.statement.prepare.FirebirdReturnColumnPacket;
 import 
org.apache.shardingsphere.database.protocol.firebird.packet.generic.FirebirdGenericResponsePacket;
 import org.apache.shardingsphere.database.protocol.packet.DatabasePacket;
+import org.apache.shardingsphere.infra.annotation.HighFrequencyInvocation;
 import 
org.apache.shardingsphere.infra.binder.context.available.WhereContextAvailable;
 import 
org.apache.shardingsphere.infra.binder.context.segment.insert.values.InsertValueContext;
 import 
org.apache.shardingsphere.infra.binder.context.segment.select.projection.Projection;
@@ -51,6 +52,7 @@ import 
org.apache.shardingsphere.infra.metadata.database.ShardingSphereDatabase;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereColumn;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereSchema;
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
+import 
org.apache.shardingsphere.infra.rule.attribute.datanode.DataNodeRuleAttribute;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
 import org.apache.shardingsphere.parser.rule.SQLParserRule;
@@ -95,6 +97,7 @@ import java.util.Collections;
 import java.util.LinkedList;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.OptionalInt;
 
 /**
@@ -489,17 +492,29 @@ public final class 
FirebirdPrepareStatementCommandExecutor implements CommandExe
         if (null == table || null == column) {
             return false;
         }
-        if 
(FirebirdBlobInfoRegistry.isBlobColumn(connectionSession.getCurrentDatabaseName(),
 table.getName(), column.getName())) {
+        if (null != table.getName() && 
FirebirdBlobInfoRegistry.isBlobColumn(connectionSession.getCurrentDatabaseName(),
 getActualTableName(table.getName()), column.getName())) {
             return true;
         }
         return Types.BLOB == column.getDataType();
     }
     
+    @HighFrequencyInvocation
+    private String getActualTableName(final String logicTableName) {
+        ShardingSphereDatabase database = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getDatabase(connectionSession.getCurrentDatabaseName());
+        for (DataNodeRuleAttribute each : 
database.getRuleMetaData().getAttributes(DataNodeRuleAttribute.class)) {
+            Optional<String> actualTableName = 
each.findFirstActualTable(logicTableName);
+            if (actualTableName.isPresent()) {
+                return actualTableName.get();
+            }
+        }
+        return logicTableName;
+    }
+    
     private Integer resolveBlobSubtype(final ShardingSphereTable table, final 
ShardingSphereColumn column, final boolean blobColumn) {
         if (!blobColumn) {
             return null;
         }
-        OptionalInt subtype = 
FirebirdBlobInfoRegistry.findBlobSubtype(connectionSession.getCurrentDatabaseName(),
 table.getName(), column.getName());
+        OptionalInt subtype = 
FirebirdBlobInfoRegistry.findBlobSubtype(connectionSession.getCurrentDatabaseName(),
 getActualTableName(table.getName()), column.getName());
         return subtype.isPresent() ? subtype.getAsInt() : null;
     }
     
diff --git 
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
 
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
index f1145d48038..45829f65c58 100644
--- 
a/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
+++ 
b/proxy/frontend/dialect/firebird/src/test/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/prepare/FirebirdPrepareStatementCommandExecutorTest.java
@@ -41,6 +41,9 @@ import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSp
 import 
org.apache.shardingsphere.infra.metadata.database.schema.model.ShardingSphereTable;
 import 
org.apache.shardingsphere.infra.metadata.statistics.ShardingSphereStatistics;
 import org.apache.shardingsphere.infra.metadata.user.Grantee;
+import org.apache.shardingsphere.infra.rule.ShardingSphereRule;
+import org.apache.shardingsphere.infra.rule.attribute.RuleAttributes;
+import 
org.apache.shardingsphere.infra.rule.attribute.datanode.DataNodeRuleAttribute;
 import org.apache.shardingsphere.infra.session.connection.ConnectionContext;
 import org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader;
 import org.apache.shardingsphere.mode.metadata.MetaDataContexts;
@@ -133,6 +136,7 @@ class FirebirdPrepareStatementCommandExecutorTest {
         
FirebirdFetchStatementCache.getInstance().unregisterStatement(CONNECTION_ID, 1);
         
FirebirdFetchStatementCache.getInstance().unregisterConnection(CONNECTION_ID);
         FirebirdBlobInfoRegistry.refreshTable("foo_db", "foo_tbl", 
Collections.emptyMap());
+        FirebirdBlobInfoRegistry.refreshTable("foo_db", "foo_tbl_0", 
Collections.emptyMap());
     }
     
     private MetaDataContexts createMetaDataContexts() {
@@ -217,6 +221,22 @@ class FirebirdPrepareStatementCommandExecutorTest {
         verify(payload).writeInt4LE(7);
     }
     
+    @Test
+    void assertDescribeBlobColumnOfShardingTable() throws Exception {
+        DataNodeRuleAttribute dataNodeRuleAttribute = 
mock(DataNodeRuleAttribute.class);
+        
when(dataNodeRuleAttribute.findFirstActualTable("foo_tbl")).thenReturn(Optional.of("foo_tbl_0"));
+        ShardingSphereRule rule = mock(ShardingSphereRule.class);
+        when(rule.getAttributes()).thenReturn(new 
RuleAttributes(dataNodeRuleAttribute));
+        ShardingSphereDatabase database = 
ProxyContext.getInstance().getContextManager().getMetaDataContexts().getMetaData().getDatabase("foo_db");
+        doReturn(new 
RuleMetaData(Collections.singleton(rule))).when(database).getRuleMetaData();
+        FirebirdBlobInfoRegistry.refreshTable("foo_db", "foo_tbl_0", 
Collections.singletonMap("id", 7));
+        FirebirdReturnColumnPacket actualColumnPacket = 
describeSingleColumn("SELECT id FROM foo_tbl");
+        FirebirdPacketPayload payload = mock(FirebirdPacketPayload.class, 
RETURNS_DEEP_STUBS);
+        actualColumnPacket.write(payload);
+        verify(payload).writeInt4LE(FirebirdBinaryColumnType.BLOB.getValue() + 
1);
+        verify(payload).writeInt4LE(7);
+    }
+    
     @Test
     void 
assertDescribeBlobTypeColumnWithoutRegistryEntryReturnsBlobTypeAndDefaultSubtype()
 throws Exception {
         FirebirdReturnColumnPacket columnPacket = describeSingleColumn("SELECT 
content FROM foo_tbl");

Reply via email to