fix: 修复 Kingbase 普通索引展示不全

This commit is contained in:
zipg 2026-06-29 20:02:30 +08:00 committed by GitHub
parent 7091615f8a
commit 41ed5e000a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 62 additions and 21 deletions

View File

@ -303,26 +303,32 @@ public final class KingbaseAgent extends PostgresLikeAgent {
@Override
public List<IndexInfo> listIndexes(String schema, String table) {
return unchecked(() -> {
Map<String, ConstraintIndexBuilder> indexes = new LinkedHashMap<>();
String sql = "SELECT tc.constraint_name, tc.constraint_type, kcu.column_name " +
"FROM information_schema.table_constraints tc " +
"JOIN information_schema.key_column_usage kcu " +
"ON kcu.constraint_schema = tc.constraint_schema " +
"AND kcu.constraint_name = tc.constraint_name " +
"AND kcu.table_schema = tc.table_schema " +
"AND kcu.table_name = tc.table_name " +
"WHERE tc.table_schema = " + sqlString(effectiveSchema(schema)) +
" AND tc.table_name = " + sqlString(table) + " " +
"AND tc.constraint_type IN ('PRIMARY KEY', 'UNIQUE') " +
"ORDER BY tc.constraint_name, kcu.ordinal_position";
Map<String, CatalogIndexBuilder> indexes = new LinkedHashMap<>();
String sql = "SELECT i.relname AS index_name, am.amname AS index_type, " +
"ix.indisunique AS is_unique, ix.indisprimary AS is_primary, " +
"a.attname AS column_name, pos.n AS ordinal_position " +
"FROM SYS_CATALOG.SYS_INDEX ix " +
"JOIN SYS_CATALOG.SYS_CLASS t ON t.oid = ix.indrelid " +
"JOIN SYS_CATALOG.SYS_CLASS i ON i.oid = ix.indexrelid " +
"JOIN SYS_CATALOG.SYS_NAMESPACE n ON n.oid = t.relnamespace " +
"JOIN SYS_CATALOG.SYS_AM am ON am.oid = i.relam " +
"JOIN generate_series(1, 64) AS pos(n) ON pos.n <= array_length(string_to_array(ix.indkey::text, ' '), 1) " +
"JOIN SYS_CATALOG.SYS_ATTRIBUTE a ON a.attrelid = t.oid AND a.attnum = (string_to_array(ix.indkey::text, ' '))[pos.n]::int2 " +
"WHERE n.nspname = " + sqlString(effectiveSchema(schema)) +
" AND t.relname = " + sqlString(table) + " " +
"ORDER BY i.relname, pos.n";
try (Statement stmt = requireConnected().createStatement()) {
try (ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
String name = rs.getString("constraint_name");
String type = rs.getString("constraint_type");
ConstraintIndexBuilder builder = indexes.get(name);
String name = rs.getString("index_name");
CatalogIndexBuilder builder = indexes.get(name);
if (builder == null) {
builder = new ConstraintIndexBuilder(name, "PRIMARY KEY".equalsIgnoreCase(type));
builder = new CatalogIndexBuilder(
name,
rs.getBoolean("is_unique"),
rs.getBoolean("is_primary"),
rs.getString("index_type")
);
indexes.put(name, builder);
}
builder.columns.add(rs.getString("column_name"));
@ -330,8 +336,8 @@ public final class KingbaseAgent extends PostgresLikeAgent {
}
}
List<IndexInfo> result = new ArrayList<>();
for (ConstraintIndexBuilder index : indexes.values()) {
result.add(new IndexInfo(index.name, index.columns, true, index.primary, null, index.primary ? "PRIMARY KEY" : "UNIQUE", null, null));
for (CatalogIndexBuilder index : indexes.values()) {
result.add(new IndexInfo(index.name, index.columns, index.unique, index.primary, null, index.indexType, null, null));
}
return result;
});
@ -485,14 +491,18 @@ public final class KingbaseAgent extends PostgresLikeAgent {
return "'" + coalesce(value).replace("'", "''") + "'";
}
private static final class ConstraintIndexBuilder {
private static final class CatalogIndexBuilder {
final String name;
final List<String> columns = new ArrayList<>();
final boolean unique;
final boolean primary;
final String indexType;
final List<String> columns = new ArrayList<>();
ConstraintIndexBuilder(String name, boolean primary) {
CatalogIndexBuilder(String name, boolean unique, boolean primary, String indexType) {
this.name = name;
this.unique = unique;
this.primary = primary;
this.indexType = indexType;
}
}

View File

@ -3,6 +3,7 @@ package com.dbx.agent.kingbase;
import com.dbx.agent.ColumnInfo;
import com.dbx.agent.DatabaseAgent;
import com.dbx.agent.DatabaseInfo;
import com.dbx.agent.IndexInfo;
import com.dbx.agent.ObjectInfo;
import com.dbx.agent.ObjectSource;
import com.dbx.agent.TableInfo;
@ -240,6 +241,36 @@ class KingbaseAgentTest extends JdbcFakeExecutionBehaviorTest {
Assertions.assertTrue(sql.get(1).contains("FROM information_schema.columns"), sql.get(1));
}
@Test
void regularListIndexesIncludesPrimaryUniqueAndSecondaryIndexes() {
List<String> sql = new ArrayList<>();
KingbaseAgent agent = new KingbaseAgent();
TestSupport.setPrivateConnection(agent, preparedConnection(sql, resultSet(
new String[]{"index_name", "index_type", "is_unique", "is_primary", "column_name", "ordinal_position"},
new Object[][]{
{"orders_pkey", "btree", true, true, "id", 1},
{"idx_orders_created", "btree", false, false, "created", 1},
{"idx_orders_name_created", "btree", false, false, "name", 1},
{"idx_orders_name_created", "btree", false, false, "created", 2}
}
)));
List<IndexInfo> indexes = agent.listIndexes("public", "orders");
Assertions.assertEquals(3, indexes.size());
Assertions.assertEquals("orders_pkey", indexes.get(0).getName());
Assertions.assertEquals(Arrays.asList("id"), indexes.get(0).getColumns());
Assertions.assertTrue(indexes.get(0).getIs_unique());
Assertions.assertTrue(indexes.get(0).getIs_primary());
Assertions.assertEquals("idx_orders_created", indexes.get(1).getName());
Assertions.assertEquals(Arrays.asList("created"), indexes.get(1).getColumns());
Assertions.assertFalse(indexes.get(1).getIs_unique());
Assertions.assertFalse(indexes.get(1).getIs_primary());
Assertions.assertEquals(Arrays.asList("name", "created"), indexes.get(2).getColumns());
Assertions.assertTrue(sql.get(0).contains("FROM SYS_CATALOG.SYS_INDEX"), sql.get(0));
Assertions.assertFalse(sql.get(0).contains("information_schema.table_constraints"), sql.get(0));
}
@Test
void mysqlCompatTimestampTypeNameIsReadAsTimestampText() throws Exception {
Timestamp timestamp = Timestamp.valueOf("2026-06-22 11:29:00");