mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-21 03:33:35 +00:00
fix(kingbase): fallback database list catalog
This commit is contained in:
@@ -49,21 +49,36 @@ public final class KingbaseAgent extends PostgresLikeAgent {
|
||||
@Override
|
||||
public List<DatabaseInfo> listDatabases() {
|
||||
return unchecked(() -> {
|
||||
String sql = isMysqlCompatMode()
|
||||
? "SELECT current_database() AS database_name"
|
||||
: "SELECT datname AS database_name FROM sys_database WHERE datistemplate = false ORDER BY datname";
|
||||
try (PreparedStatement stmt = requireConnected().prepareStatement(sql);
|
||||
ResultSet rs = stmt.executeQuery()) {
|
||||
List<DatabaseInfo> result = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
result.add(new DatabaseInfo(rs.getString("database_name")));
|
||||
}
|
||||
if (isMysqlCompatMode()) {
|
||||
List<DatabaseInfo> result = queryDatabases("SELECT current_database() AS database_name");
|
||||
if (!result.isEmpty()) return result;
|
||||
}
|
||||
for (String sql : List.of(
|
||||
"SELECT datname AS database_name FROM sys_catalog.sys_database WHERE datistemplate = false ORDER BY datname",
|
||||
"SELECT datname AS database_name FROM pg_database WHERE datistemplate = false ORDER BY datname"
|
||||
)) {
|
||||
try {
|
||||
List<DatabaseInfo> result = queryDatabases(sql);
|
||||
if (!result.isEmpty()) return result;
|
||||
} catch (Exception ignored) {
|
||||
// Kingbase catalog names differ across compatibility modes and versions.
|
||||
}
|
||||
}
|
||||
return Collections.singletonList(new DatabaseInfo(getConfiguredDatabase()));
|
||||
});
|
||||
}
|
||||
|
||||
private List<DatabaseInfo> queryDatabases(String sql) throws Exception {
|
||||
try (PreparedStatement stmt = requireConnected().prepareStatement(sql);
|
||||
ResultSet rs = stmt.executeQuery()) {
|
||||
List<DatabaseInfo> result = new ArrayList<>();
|
||||
while (rs.next()) {
|
||||
result.add(new DatabaseInfo(rs.getString("database_name")));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> listSchemas() {
|
||||
return unchecked(() -> {
|
||||
|
||||
+44
-1
@@ -19,6 +19,7 @@ import java.lang.reflect.Proxy;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
@@ -80,7 +81,24 @@ class KingbaseAgentTest extends JdbcFakeExecutionBehaviorTest {
|
||||
Assertions.assertEquals(2, databases.size());
|
||||
Assertions.assertEquals("app", databases.get(0).getName());
|
||||
Assertions.assertEquals("analytics", databases.get(1).getName());
|
||||
Assertions.assertTrue(sql.get(0).contains("FROM sys_database"), sql.get(0));
|
||||
Assertions.assertTrue(sql.get(0).contains("FROM sys_catalog.sys_database"), sql.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
void regularListDatabasesFallsBackToPostgresCatalog() {
|
||||
List<String> sql = new ArrayList<>();
|
||||
KingbaseAgent agent = new KingbaseAgent();
|
||||
TestSupport.setPrivateConnection(agent, preparedConnectionWithFailure(sql, "sys_catalog.sys_database", resultSet(
|
||||
new String[]{"database_name"},
|
||||
new Object[][]{{"test"}}
|
||||
)));
|
||||
|
||||
List<DatabaseInfo> databases = agent.listDatabases();
|
||||
|
||||
Assertions.assertEquals(1, databases.size());
|
||||
Assertions.assertEquals("test", databases.get(0).getName());
|
||||
Assertions.assertTrue(sql.get(0).contains("FROM sys_catalog.sys_database"), sql.get(0));
|
||||
Assertions.assertTrue(sql.get(1).contains("FROM pg_database"), sql.get(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -390,6 +408,31 @@ class KingbaseAgentTest extends JdbcFakeExecutionBehaviorTest {
|
||||
});
|
||||
}
|
||||
|
||||
private static Connection preparedConnectionWithFailure(List<String> sql, String failingSqlFragment, ResultSet fallback) {
|
||||
return proxy(Connection.class, (method, args) -> {
|
||||
if ("prepareStatement".equals(method.getName())) {
|
||||
String preparedSql = String.valueOf(args[0]);
|
||||
sql.add(preparedSql);
|
||||
return proxy(PreparedStatement.class, (statementMethod, statementArgs) -> {
|
||||
if ("executeQuery".equals(statementMethod.getName())) {
|
||||
if (preparedSql.contains(failingSqlFragment)) {
|
||||
throw new SQLException("relation does not exist: " + failingSqlFragment);
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
if ("close".equals(statementMethod.getName())) {
|
||||
return null;
|
||||
}
|
||||
return defaultValue(statementMethod.getReturnType());
|
||||
});
|
||||
}
|
||||
if ("isClosed".equals(method.getName())) {
|
||||
return false;
|
||||
}
|
||||
return defaultValue(method.getReturnType());
|
||||
});
|
||||
}
|
||||
|
||||
private static ResultSet resultSet(String[] columns, Object[][] rows) {
|
||||
int[] index = {-1};
|
||||
return proxy(ResultSet.class, (method, args) -> {
|
||||
|
||||
Reference in New Issue
Block a user