This is an automated email from the ASF dual-hosted git repository.
jianbin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push:
new 7daf5b0c9e bugfix: different element order in two lists causes failure
to set the index as primary key index (#7965)
7daf5b0c9e is described below
commit 7daf5b0c9e3b81550e3c1481364fbb2321baabe5
Author: funkye <[email protected]>
AuthorDate: Tue Jan 27 21:52:31 2026 +0800
bugfix: different element order in two lists causes failure to set the
index as primary key index (#7965)
---
changes/en-us/2.6.0.md | 1 +
changes/en-us/2.x.md | 1 +
changes/zh-cn/2.6.0.md | 1 +
changes/zh-cn/2.x.md | 2 +
.../seata/namingserver/config/WebConfig.java | 2 +-
.../namingserver/contants/NamingConstant.java | 2 +-
.../sql/struct/cache/DmTableMetaCache.java | 70 ++++++++++++----
.../sql/struct/cache/KingbaseTableMetaCache.java | 61 ++++++++++----
.../sql/struct/cache/DmTableMetaCacheTest.java | 98 ++++++++++++++++++++++
.../struct/cache/KingbaseTableMetaCacheTest.java | 98 ++++++++++++++++++++++
10 files changed, 300 insertions(+), 36 deletions(-)
diff --git a/changes/en-us/2.6.0.md b/changes/en-us/2.6.0.md
index 4a919af909..c0e4aa0c75 100644
--- a/changes/en-us/2.6.0.md
+++ b/changes/en-us/2.6.0.md
@@ -75,6 +75,7 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#7908](https://github.com/apache/incubator-seata/pull/7908)] handle
timestamp with time zone in postgresql primary key
- [[#7938](https://github.com/apache/incubator-seata/pull/7938)] ensure the
Jakarta-related package paths are correct.
- [[#7959](https://github.com/apache/incubator-seata/pull/7959)] fix
consoleApiService bean that could not be found
+- [[#7966](https://github.com/apache/incubator-seata/pull/7966)] Fix the issue
where different element orders in two lists cause failure to set the index as
the primary key
### optimize:
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 80d8165e99..29af662ab9 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -30,6 +30,7 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#7940](https://github.com/apache/incubator-seata/pull/7940)] ensure the
Jakarta-related package paths are correct
- [[#7960](https://github.com/apache/incubator-seata/pull/7960)] fix
consoleApiService bean that could not be found
- [[#7956](https://github.com/apache/incubator-seata/pull/7956)] fix empty
jacoco report on local when jdk above 17
+- [[#7965](https://github.com/apache/incubator-seata/pull/7965)] fix the issue
where different element order in two lists causes failure to set the index as
the primary key
### optimize:
diff --git a/changes/zh-cn/2.6.0.md b/changes/zh-cn/2.6.0.md
index 1935426983..90503ce7d2 100644
--- a/changes/zh-cn/2.6.0.md
+++ b/changes/zh-cn/2.6.0.md
@@ -75,6 +75,7 @@
- [[#7908](https://github.com/apache/incubator-seata/pull/7908)] 在 PostgreSQL
主键中处理带时区的时间戳
- [[#7938](https://github.com/apache/incubator-seata/pull/7938)]
保证Jakarta相关包路径正确
- [[#7959](https://github.com/apache/incubator-seata/pull/7959)]
修复consoleApiService bean未加载的问题
+- [[#7966](https://github.com/apache/incubator-seata/pull/7966)] 修复在 dm 和
kingbase 中当没有将索引设置为主键索引的问题
### optimize:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 90da8bc393..1855319521 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -30,6 +30,8 @@
- [[#7940](https://github.com/apache/incubator-seata/pull/7940)]
保证Jakarta相关包路径正确
- [[#7960](https://github.com/apache/incubator-seata/pull/7960)]
修复consoleApiService bean未加载的问题
- [[#7956](https://github.com/apache/incubator-seata/pull/7956)]
修复本地JDK17以上jacoco报告为空的问题
+- [[#7965](https://github.com/apache/incubator-seata/pull/7965)] 修复在 dm 和
kingbase 中当没有将索引设置为主键索引时出现的问题
+
### optimize:
diff --git
a/namingserver/src/main/java/org/apache/seata/namingserver/config/WebConfig.java
b/namingserver/src/main/java/org/apache/seata/namingserver/config/WebConfig.java
index 563a9b7c21..f7d0a79f08 100644
---
a/namingserver/src/main/java/org/apache/seata/namingserver/config/WebConfig.java
+++
b/namingserver/src/main/java/org/apache/seata/namingserver/config/WebConfig.java
@@ -50,7 +50,7 @@ public class WebConfig {
.readTimeout(DEFAULT_REQUEST_TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(DEFAULT_WRITE_TIMEOUT, TimeUnit.MILLISECONDS)
.build();
-
+
// Create and return a RestTemplate with the custom request factory
return new RestTemplate(new OkHttp3ClientHttpRequestFactory(client));
}
diff --git
a/namingserver/src/main/java/org/apache/seata/namingserver/contants/NamingConstant.java
b/namingserver/src/main/java/org/apache/seata/namingserver/contants/NamingConstant.java
index 6d0852a7df..c679b37200 100644
---
a/namingserver/src/main/java/org/apache/seata/namingserver/contants/NamingConstant.java
+++
b/namingserver/src/main/java/org/apache/seata/namingserver/contants/NamingConstant.java
@@ -21,7 +21,7 @@ public interface NamingConstant {
String CONSOLE_PATTERN = "^/api/.*/console/.*";
int DEFAULT_REQUEST_TIMEOUT = 5000;
-
+
int DEFAULT_WRITE_TIMEOUT = 5000;
int DEFAULT_CONNECTION_MAX_TOTAL = 100;
diff --git
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/DmTableMetaCache.java
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/DmTableMetaCache.java
index a9728e0b0f..4b99b558d9 100644
---
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/DmTableMetaCache.java
+++
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/DmTableMetaCache.java
@@ -28,8 +28,8 @@ import org.apache.seata.sqlparser.util.JdbcConstants;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.LinkedHashSet;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -124,25 +124,53 @@ public class DmTableMetaCache extends
OracleTableMetaCache {
}
protected void processPrimaries(TableMeta tableMeta, ResultSet rs) throws
SQLException {
- List<String> primaryKeyColumns = new ArrayList<>();
+ // Collect primary key column names that couldn't be matched directly
by PK_NAME
+ // In Oracle/DM: when primary key constraint name differs from unique
index name,
+ // we need to match by column names instead
+ Set<String> unmatchedPkColumns = new LinkedHashSet<>();
+
+ // Iterate through each row of getPrimaryKeys() result set
+ // For composite primary key, there will be multiple rows with same
PK_NAME
while (rs.next()) {
- String pkColName;
- try {
- pkColName = rs.getString("COLUMN_NAME");
- } catch (Exception e) {
- pkColName = rs.getString("PK_NAME");
+ String pkConstraintName = getStringSafely(rs, "PK_NAME");
+ String pkColName = getStringSafely(rs, "COLUMN_NAME");
+ if (StringUtils.isBlank(pkColName)) {
+ pkColName = pkConstraintName;
}
- primaryKeyColumns.add(pkColName);
- }
-
- for (IndexMeta index : tableMeta.getAllIndexes().values()) {
- List<String> indexColumns = index.getValues().stream()
- .filter(col -> col != null &&
StringUtils.isNotBlank(col.getColumnName()))
- .map(ColumnMeta::getColumnName)
- .collect(Collectors.toList());
- if (indexColumns.equals(primaryKeyColumns)) {
+ // Strategy 1: Try direct match by PK constraint name
+ // If the index name matches the primary key constraint name, mark
it as PRIMARY
+ if (StringUtils.isNotBlank(pkConstraintName)
+ &&
tableMeta.getAllIndexes().containsKey(pkConstraintName)) {
+ IndexMeta index =
tableMeta.getAllIndexes().get(pkConstraintName);
index.setIndextype(IndexType.PRIMARY);
+ } else {
+ // Save columns for Strategy 2: fallback column-based matching
+ if (StringUtils.isNotBlank(pkColName)) {
+ unmatchedPkColumns.add(pkColName.toUpperCase());
+ }
+ }
+ }
+
+ // Strategy 2: Fallback - find index whose columns match the primary
key columns
+ // This handles the case where PK constraint name differs from unique
index name
+ if (!unmatchedPkColumns.isEmpty()) {
+ for (IndexMeta index : tableMeta.getAllIndexes().values()) {
+ // Only check UNIQUE indexes as candidates (primary key is
always unique)
+ if (index.getIndextype().value() == IndexType.UNIQUE.value()) {
+ // Build index column set, normalized to uppercase and
deduplicated
+ Set<String> indexColsSet = index.getValues().stream()
+ .filter(col -> col != null &&
StringUtils.isNotBlank(col.getColumnName()))
+ .map(col -> col.getColumnName().toUpperCase())
+ .collect(Collectors.toSet());
+
+ // If sets are equal, this index exactly matches primary
key columns
+ if (indexColsSet.equals(unmatchedPkColumns)) {
+ index.setIndextype(IndexType.PRIMARY);
+ // Each table has only one primary key
+ break;
+ }
+ }
}
}
}
@@ -186,4 +214,12 @@ public class DmTableMetaCache extends OracleTableMetaCache
{
}
return result;
}
+
+ private static String getStringSafely(ResultSet rs, String columnLabel) {
+ try {
+ return rs.getString(columnLabel);
+ } catch (Exception e) {
+ return null;
+ }
+ }
}
diff --git
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/KingbaseTableMetaCache.java
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/KingbaseTableMetaCache.java
index 31a41743d6..64b513462b 100644
---
a/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/KingbaseTableMetaCache.java
+++
b/rm-datasource/src/main/java/org/apache/seata/rm/datasource/sql/struct/cache/KingbaseTableMetaCache.java
@@ -28,8 +28,8 @@ import org.apache.seata.sqlparser.util.JdbcConstants;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.LinkedHashSet;
+import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -123,25 +123,44 @@ public class KingbaseTableMetaCache extends
OracleTableMetaCache {
}
protected void processPrimaries(TableMeta tableMeta, ResultSet rs) throws
SQLException {
- List<String> primaryKeyColumns = new ArrayList<>();
+ // Collect primary key column names that couldn't be matched directly
by PK_NAME
+ Set<String> unmatchedPkColumns = new LinkedHashSet<>();
+
+ // Iterate through each row of getPrimaryKeys() result set
while (rs.next()) {
- String pkColName;
- try {
- pkColName = rs.getString("COLUMN_NAME");
- } catch (Exception e) {
- pkColName = rs.getString("PK_NAME");
+ String pkConstraintName = getStringSafely(rs, "PK_NAME");
+ String pkColName = getStringSafely(rs, "COLUMN_NAME");
+ if (StringUtils.isBlank(pkColName)) {
+ pkColName = pkConstraintName;
}
- primaryKeyColumns.add(pkColName);
- }
-
- for (IndexMeta index : tableMeta.getAllIndexes().values()) {
- List<String> indexColumns = index.getValues().stream()
- .filter(col -> col != null &&
StringUtils.isNotBlank(col.getColumnName()))
- .map(ColumnMeta::getColumnName)
- .collect(Collectors.toList());
- if (indexColumns.equals(primaryKeyColumns)) {
+ // Strategy 1: Try direct match by PK constraint name
+ if (StringUtils.isNotBlank(pkConstraintName)
+ &&
tableMeta.getAllIndexes().containsKey(pkConstraintName)) {
+ IndexMeta index =
tableMeta.getAllIndexes().get(pkConstraintName);
index.setIndextype(IndexType.PRIMARY);
+ } else {
+ // Save columns for fallback column-based matching
+ if (StringUtils.isNotBlank(pkColName)) {
+ unmatchedPkColumns.add(pkColName.toUpperCase());
+ }
+ }
+ }
+
+ // Strategy 2: fallback - match by column set equality
(order-insensitive, deduped)
+ if (!unmatchedPkColumns.isEmpty()) {
+ for (IndexMeta index : tableMeta.getAllIndexes().values()) {
+ if (index.getIndextype().value() == IndexType.UNIQUE.value()) {
+ Set<String> indexColsSet = index.getValues().stream()
+ .filter(col -> col != null &&
StringUtils.isNotBlank(col.getColumnName()))
+ .map(col -> col.getColumnName().toUpperCase())
+ .collect(Collectors.toSet());
+
+ if (indexColsSet.equals(unmatchedPkColumns)) {
+ index.setIndextype(IndexType.PRIMARY);
+ break;
+ }
+ }
}
}
}
@@ -185,4 +204,12 @@ public class KingbaseTableMetaCache extends
OracleTableMetaCache {
}
return result;
}
+
+ private static String getStringSafely(ResultSet rs, String columnLabel) {
+ try {
+ return rs.getString(columnLabel);
+ } catch (Exception e) {
+ return null;
+ }
+ }
}
diff --git
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/struct/cache/DmTableMetaCacheTest.java
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/struct/cache/DmTableMetaCacheTest.java
index 70d4987c64..04f7bc14e8 100644
---
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/struct/cache/DmTableMetaCacheTest.java
+++
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/struct/cache/DmTableMetaCacheTest.java
@@ -332,4 +332,102 @@ public class DmTableMetaCacheTest {
Assertions.assertNotNull(tableMeta);
Assertions.assertEquals(originalName,
tableMeta.getOriginalTableName());
}
+
+ @Test
+ public void testCompositeIndexWithDifferentColumnOrder() throws
SQLException {
+ // Regression test for a bug fix: different column order caused
List.equals to fail, which could lead to
+ // failing to recognize a primary key index.
+ // Scenario: composite primary key (ID, USER_ID) while a unique index
lists the same columns in reverse order
+ // (USER_ID, ID).
+ // Before the fix: List.equals returned FALSE because of the different
order, causing the primary key index to
+ // be unrecognized.
+ // After the fix: using Set.equals should return TRUE and correctly
identify the index as PRIMARY.
+
+ Object[][] compositeIndexDiffOrder = new Object[][] {
+ new Object[] {"idx_id_userid", "id", false, "", 3, 1, "A", 34}, //
column order 1
+ new Object[] {"idx_id_userid", "user_id", false, "", 3, 2, "A",
34} // column order 2
+ };
+ Object[][] compositePKMetas = new Object[][] {
+ new Object[] {"id"}, // PK column order 1
+ new Object[] {"user_id"} // PK column order 2
+ };
+ Object[][] compositeColumnMetas = new Object[][] {
+ new Object[] {"", "", "dt2", "id", Types.INTEGER, "INTEGER", 64,
0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"
+ },
+ new Object[] {
+ "", "", "dt2", "user_id", Types.INTEGER, "INTEGER", 64, 0, 10,
0, "", "", 0, 0, 64, 2, "YES", "NO"
+ }
+ };
+ Object[][] compositeTableMetas = new Object[][] {new Object[] {"",
"t", "dt2"}};
+
+ MockDriver mockDriver =
+ new MockDriver(compositeColumnMetas, compositeIndexDiffOrder,
compositePKMetas, compositeTableMetas);
+ DruidDataSource dataSource = new DruidDataSource();
+ dataSource.setUrl("jdbc:mock:dm");
+ dataSource.setDriver(mockDriver);
+
+ DataSourceProxy proxy =
DataSourceProxyTest.getDataSourceProxy(dataSource);
+ TableMetaCache tableMetaCache =
TableMetaCacheFactory.getTableMetaCache(JdbcConstants.DM);
+
+ TableMeta tableMeta =
tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.dt2",
proxy.getResourceId());
+
+ Assertions.assertNotNull(tableMeta);
+ IndexMeta compositeIndex =
tableMeta.getAllIndexes().get("idx_id_userid");
+ Assertions.assertNotNull(compositeIndex);
+ // Key assertion: should be recognized as PRIMARY (after the fix), not
mistakenly treated as UNIQUE
+ Assertions.assertEquals(
+ IndexType.PRIMARY,
+ compositeIndex.getIndextype(),
+ "Composite index with different column order should be
recognized as PRIMARY");
+ }
+
+ @Test
+ public void testCompositeIndexWithExtraColumnsNotMarkedAsPrimary() throws
SQLException {
+ // Regression test for a bug fix: a composite unique index that
contains primary key columns plus extra columns
+ // should NOT be marked as PRIMARY.
+ // Scenario: primary key (ID), unique index (ID, NAME) — unique index
contains PK column but has extra NAME.
+ // Before the fix: Oracle implementation matched by count (matchCols
== pkcol.size()) and could misidentify
+ // PRIMARY.
+ // After the fix: using Set equality ({ID, NAME} != {ID}) prevents the
index from being marked as PRIMARY
+
+ Object[][] mixedIndexMetas = new Object[][] {
+ new Object[] {"idx_id", "id", false, "", 3, 1, "A", 34},
+ new Object[] {"uk_id_name", "id", false, "", 3, 1, "A", 34}, //
unique index contains the primary key column
+ new Object[] {"uk_id_name", "name1", false, "", 3, 2, "A", 34} //
but it also has extra columns
+ };
+
+ // Use a dedicated table name to avoid cache hits from earlier tests
+ Object[][] extraColumnMetas = new Object[][] {
+ new Object[] {"", "", "dt3", "id", Types.INTEGER, "INTEGER", 64,
0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"
+ },
+ new Object[] {
+ "", "", "dt3", "name1", Types.VARCHAR, "VARCHAR", 64, 0, 10,
0, "", "", 0, 0, 64, 2, "YES", "NO"
+ }
+ };
+ Object[][] extraPkMetas = new Object[][] {new Object[] {"id"}};
+ Object[][] extraTableMetas = new Object[][] {new Object[] {"", "t",
"dt3"}};
+
+ MockDriver mockDriver = new MockDriver(extraColumnMetas,
mixedIndexMetas, extraPkMetas, extraTableMetas);
+ DruidDataSource dataSource = new DruidDataSource();
+ dataSource.setUrl("jdbc:mock:dm");
+ dataSource.setDriver(mockDriver);
+
+ DataSourceProxy proxy =
DataSourceProxyTest.getDataSourceProxy(dataSource);
+ TableMetaCache tableMetaCache =
TableMetaCacheFactory.getTableMetaCache(JdbcConstants.DM);
+
+ TableMeta tableMeta =
tableMetaCache.getTableMeta(proxy.getPlainConnection(), "t.dt3",
proxy.getResourceId());
+
+ Assertions.assertNotNull(tableMeta);
+ IndexMeta pkIndex = tableMeta.getAllIndexes().get("idx_id");
+ Assertions.assertNotNull(pkIndex);
+ Assertions.assertEquals(IndexType.PRIMARY, pkIndex.getIndextype(),
"Single column PK index should be PRIMARY");
+
+ IndexMeta mixedIndex = tableMeta.getAllIndexes().get("uk_id_name");
+ Assertions.assertNotNull(mixedIndex);
+ // Key assertion: should remain UNIQUE (should not be misidentified as
PRIMARY)
+ Assertions.assertEquals(
+ IndexType.UNIQUE,
+ mixedIndex.getIndextype(),
+ "Composite index with extra columns should NOT be marked as
PRIMARY");
+ }
}
diff --git
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/struct/cache/KingbaseTableMetaCacheTest.java
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/struct/cache/KingbaseTableMetaCacheTest.java
index 98850cd961..f3b4cee0cb 100644
---
a/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/struct/cache/KingbaseTableMetaCacheTest.java
+++
b/rm-datasource/src/test/java/org/apache/seata/rm/datasource/sql/struct/cache/KingbaseTableMetaCacheTest.java
@@ -332,4 +332,102 @@ public class KingbaseTableMetaCacheTest {
Assertions.assertNotNull(tableMeta);
Assertions.assertEquals(originalName,
tableMeta.getOriginalTableName());
}
+
+ @Test
+ public void testCompositeIndexWithDifferentColumnOrder() throws
SQLException {
+ // Regression test for a bug fix: different column order caused
List.equals to fail, which could lead to
+ // failing to recognize a primary key index.
+ // Scenario: composite primary key (ID, USER_ID) while a unique index
lists the same columns in reverse order
+ // (USER_ID, ID).
+ // Before the fix: List.equals returned FALSE because of the different
order, causing the primary key index to
+ // be unrecognized.
+ // After the fix: using Set.equals should return TRUE and correctly
identify the index as PRIMARY.
+
+ Object[][] compositeIndexDiffOrder = new Object[][] {
+ new Object[] {"idx_id_userid", "id", false, "", 3, 1, "A", 34}, //
column order 1
+ new Object[] {"idx_id_userid", "user_id", false, "", 3, 2, "A",
34} // column order 2
+ };
+ Object[][] compositePKMetas = new Object[][] {
+ new Object[] {"id"}, // PK column order 1
+ new Object[] {"user_id"} // PK column order 2
+ };
+ Object[][] compositeColumnMetas = new Object[][] {
+ new Object[] {"", "", "kt2", "id", Types.INTEGER, "INTEGER", 64,
0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"
+ },
+ new Object[] {
+ "", "", "kt2", "user_id", Types.INTEGER, "INTEGER", 64, 0, 10,
0, "", "", 0, 0, 64, 2, "YES", "NO"
+ }
+ };
+ Object[][] compositeTableMetas = new Object[][] {new Object[] {"",
"kb", "kt2"}};
+
+ MockDriver mockDriver =
+ new MockDriver(compositeColumnMetas, compositeIndexDiffOrder,
compositePKMetas, compositeTableMetas);
+ DruidDataSource dataSource = new DruidDataSource();
+ dataSource.setUrl("jdbc:mock:kingbase");
+ dataSource.setDriver(mockDriver);
+
+ DataSourceProxy proxy =
DataSourceProxyTest.getDataSourceProxy(dataSource);
+ TableMetaCache tableMetaCache =
TableMetaCacheFactory.getTableMetaCache(JdbcConstants.KINGBASE);
+
+ TableMeta tableMeta =
tableMetaCache.getTableMeta(proxy.getPlainConnection(), "kb.kt2",
proxy.getResourceId());
+
+ Assertions.assertNotNull(tableMeta);
+ IndexMeta compositeIndex =
tableMeta.getAllIndexes().get("idx_id_userid");
+ Assertions.assertNotNull(compositeIndex);
+ // Key assertion: should be recognized as PRIMARY (after the fix), not
mistakenly treated as UNIQUE
+ Assertions.assertEquals(
+ IndexType.PRIMARY,
+ compositeIndex.getIndextype(),
+ "Composite index with different column order should be
recognized as PRIMARY");
+ }
+
+ @Test
+ public void testCompositeIndexWithExtraColumnsNotMarkedAsPrimary() throws
SQLException {
+ // Regression test for a bug fix: a composite unique index that
contains primary key columns plus extra columns
+ // should NOT be marked as PRIMARY.
+ // Scenario: primary key (ID), unique index (ID, NAME) — unique index
contains PK column but has extra NAME.
+ // Before the fix: previous implementation matched by count (matchCols
== pkcol.size()) and could misidentify
+ // PRIMARY.
+ // After the fix: match by Set equality ({ID, NAME} != {ID}) so it
won't be marked as PRIMARY
+
+ Object[][] mixedIndexMetas = new Object[][] {
+ new Object[] {"idx_id", "id", false, "", 3, 1, "A", 34},
+ new Object[] {"uk_id_name", "id", false, "", 3, 1, "A", 34}, //
unique index contains the primary key column
+ new Object[] {"uk_id_name", "name1", false, "", 3, 2, "A", 34} //
but it also has extra columns
+ };
+
+ // Use a dedicated table name to avoid cache hits from earlier tests
+ Object[][] extraColumnMetas = new Object[][] {
+ new Object[] {"", "", "kt3", "id", Types.INTEGER, "INTEGER", 64,
0, 10, 1, "", "", 0, 0, 64, 1, "NO", "YES"
+ },
+ new Object[] {
+ "", "", "kt3", "name1", Types.VARCHAR, "VARCHAR", 64, 0, 10,
0, "", "", 0, 0, 64, 2, "YES", "NO"
+ }
+ };
+ Object[][] extraPkMetas = new Object[][] {new Object[] {"id"}};
+ Object[][] extraTableMetas = new Object[][] {new Object[] {"", "kb",
"kt3"}};
+
+ MockDriver mockDriver = new MockDriver(extraColumnMetas,
mixedIndexMetas, extraPkMetas, extraTableMetas);
+ DruidDataSource dataSource = new DruidDataSource();
+ dataSource.setUrl("jdbc:mock:kingbase");
+ dataSource.setDriver(mockDriver);
+
+ DataSourceProxy proxy =
DataSourceProxyTest.getDataSourceProxy(dataSource);
+ TableMetaCache tableMetaCache =
TableMetaCacheFactory.getTableMetaCache(JdbcConstants.KINGBASE);
+
+ TableMeta tableMeta =
tableMetaCache.getTableMeta(proxy.getPlainConnection(), "kb.kt3",
proxy.getResourceId());
+
+ Assertions.assertNotNull(tableMeta);
+ IndexMeta pkIndex = tableMeta.getAllIndexes().get("idx_id");
+ Assertions.assertNotNull(pkIndex);
+ Assertions.assertEquals(IndexType.PRIMARY, pkIndex.getIndextype(),
"Single column PK index should be PRIMARY");
+
+ IndexMeta mixedIndex = tableMeta.getAllIndexes().get("uk_id_name");
+ Assertions.assertNotNull(mixedIndex);
+ // Key assertion: should remain UNIQUE (should not be misidentified as
PRIMARY)
+ Assertions.assertEquals(
+ IndexType.UNIQUE,
+ mixedIndex.getIndextype(),
+ "Composite index with extra columns should NOT be marked as
PRIMARY");
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]