fix(gbase8a): preserve native table DDL

This commit is contained in:
zipg
2026-07-17 00:06:37 +08:00
committed by GitHub
parent dfd47bc54c
commit 5c7832720e
2 changed files with 52 additions and 21 deletions
@@ -170,37 +170,49 @@ public final class Gbase8aAgent extends ConfiguredJdbcAgent {
}
}
@Override
public String getTableDdl(String schema, String table) {
try {
String ddl = showCreateDefinition("TABLE", schema, table);
if (!ddl.isEmpty()) {
return ddl;
}
} catch (RuntimeException ignored) {
// Keep metadata-based DDL available for servers that restrict SHOW CREATE TABLE.
}
return super.getTableDdl(schema, table);
}
@Override
public ObjectSource getObjectSource(String schema, String name, String objectType) {
String normalizedType = objectType.toUpperCase(Locale.ROOT);
if (!List.of("VIEW", "PROCEDURE", "FUNCTION").contains(normalizedType)) {
throw new IllegalArgumentException("Unsupported object type: " + objectType);
}
return new ObjectSource(name, normalizedType, schema, showCreateDefinition(normalizedType, schema, name));
}
private String showCreateDefinition(String objectType, String schema, String name) {
return unchecked(() -> {
String normalizedType = objectType.toUpperCase(Locale.ROOT);
String sql = switch (normalizedType) {
case "VIEW" -> "SHOW CREATE VIEW ";
case "PROCEDURE" -> "SHOW CREATE PROCEDURE ";
case "FUNCTION" -> "SHOW CREATE FUNCTION ";
default -> throw new IllegalArgumentException("Unsupported object type: " + objectType);
};
String qualifiedName = hasSchema(schema)
? JdbcIdentifiers.INSTANCE.backtick(schema) + "." + JdbcIdentifiers.INSTANCE.backtick(name)
: JdbcIdentifiers.INSTANCE.backtick(name);
String source = "";
try (Statement stmt = requireConnection().createStatement();
ResultSet rs = stmt.executeQuery(sql + qualifiedName)) {
if (rs.next()) {
// SHOW CREATE result layouts vary by GBase driver version, so locate the definition column by label.
ResultSetMetaData metadata = rs.getMetaData();
for (int index = 1; index <= metadata.getColumnCount(); index++) {
String label = metadata.getColumnLabel(index);
if (label != null && label.toUpperCase(Locale.ROOT).startsWith("CREATE ")) {
String value = rs.getString(index);
source = value == null ? "" : value;
break;
}
ResultSet rs = stmt.executeQuery("SHOW CREATE " + objectType + " " + qualifiedName)) {
if (!rs.next()) {
return "";
}
// SHOW CREATE result layouts vary by GBase driver version, so locate the definition column by label.
ResultSetMetaData metadata = rs.getMetaData();
for (int index = 1; index <= metadata.getColumnCount(); index++) {
String label = metadata.getColumnLabel(index);
if (label != null && label.toUpperCase(Locale.ROOT).startsWith("CREATE ")) {
String value = rs.getString(index);
return value == null ? "" : value;
}
}
return "";
}
return new ObjectSource(name, normalizedType, schema, source);
});
}
@@ -98,6 +98,25 @@ class Gbase8aAgentTest {
Assertions.assertTrue(sql.get(0).contains("LIMIT ?"), sql.get(0));
}
@Test
void getTableDdlUsesShowCreateToPreserveNativeColumnClauses() {
List<String> sql = new ArrayList<>();
String nativeDdl = "CREATE TABLE \"orders`archive\" (\n" +
" \"UPDATE_TIME\" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'updated at'\n" +
") ENGINE=EXPRESS DEFAULT CHARSET=utf8";
Gbase8aAgent agent = new Gbase8aAgent();
TestSupport.setPrivateConnection(agent, statementConnection(sql, resultSet(
new String[]{"Table", "Create Table"},
new Object[][]{{"orders`archive", nativeDdl}}
)));
String ddl = agent.getTableDdl("app`prod", "orders`archive");
Assertions.assertEquals(nativeDdl, ddl);
Assertions.assertTrue(ddl.contains("ON UPDATE CURRENT_TIMESTAMP"), ddl);
Assertions.assertEquals("SHOW CREATE TABLE `app``prod`.`orders``archive`", sql.get(0));
}
@Test
void getObjectSourceUsesShowCreateForRoutines() {
List<String> sql = new ArrayList<>();