fix(db2): read view source from SYSCAT.VIEWS

This commit is contained in:
hb authored and GitHub committed 2026-09-08 01:21:08 +08:00
1 parent 7961e688f2
commit b4d807b818
2 files changed
+69 -1

No files matched your search

@@ -218,7 +218,11 @@ public final class Db2Agent extends AbstractJdbcAgent {
@Override
public ObjectSource getObjectSource(String schema, String name, String objectType) {
return unchecked(() -> {
String sql = "SELECT TEXT FROM SYSCAT.ROUTINES WHERE ROUTINESCHEMA = ? AND ROUTINENAME = ?";
String normalizedType = objectType == null ? "" : objectType.trim().toUpperCase(Locale.ROOT);
// View definitions live in SYSCAT.VIEWS; SYSCAT.ROUTINES only covers procedures and functions.
String sql = "VIEW".equals(normalizedType)
? "SELECT TEXT FROM SYSCAT.VIEWS WHERE VIEWSCHEMA = ? AND VIEWNAME = ?"
: "SELECT TEXT FROM SYSCAT.ROUTINES WHERE ROUTINESCHEMA = ? AND ROUTINENAME = ?";
String source;
try (PreparedStatement stmt = requireConnected().prepareStatement(sql)) {
stmt.setString(1, schema);
@@ -4,6 +4,7 @@ import com.dbx.agent.DatabaseAgent;
import com.dbx.agent.ConnectParams;
import com.dbx.agent.MetadataListConstraints;
import com.dbx.agent.ObjectInfo;
import com.dbx.agent.ObjectSource;
import com.dbx.agent.TableInfo;
import com.dbx.agent.test.JdbcFakeExecutionBehaviorTest;
import com.dbx.agent.test.JdbcMetadataSqlFake;
@@ -126,6 +127,69 @@ class Db2AgentTest extends JdbcFakeExecutionBehaviorTest {
assertEquals("Test view comment", objects.get(0).getComment());
}
@Test
void viewObjectSourceReadsDefinitionFromSyscatViews() {
Db2Agent agent = new Db2Agent();
AtomicReference<String> executedSql = new AtomicReference<>();
TestSupport.setPrivateConnection(agent, preparedConnection(
executedSql,
row("TEXT", "CREATE VIEW APP.EMP_VIEW AS SELECT ID, NAME FROM APP.EMPLOYEE")
));
ObjectSource source = agent.getObjectSource("APP", "EMP_VIEW", "VIEW");
assertEquals("CREATE VIEW APP.EMP_VIEW AS SELECT ID, NAME FROM APP.EMPLOYEE", source.getSource());
assertEquals("SELECT TEXT FROM SYSCAT.VIEWS WHERE VIEWSCHEMA = ? AND VIEWNAME = ?", executedSql.get());
}
@Test
void routineObjectSourceStillReadsSyscatRoutines() {
Db2Agent agent = new Db2Agent();
AtomicReference<String> executedSql = new AtomicReference<>();
TestSupport.setPrivateConnection(agent, preparedConnection(
executedSql,
row("TEXT", "BEGIN SELECT 1 FROM SYSIBM.SYSDUMMY1; END")
));
ObjectSource source = agent.getObjectSource("APP", "MY_PROC", "PROCEDURE");
assertEquals("BEGIN SELECT 1 FROM SYSIBM.SYSDUMMY1; END", source.getSource());
assertEquals("SELECT TEXT FROM SYSCAT.ROUTINES WHERE ROUTINESCHEMA = ? AND ROUTINENAME = ?", executedSql.get());
}
private static Connection preparedConnection(AtomicReference<String> executedSql, Map<String, Object>... rows) {
final ResultSet resultSet = rows(rows);
return proxy(Connection.class, new MethodHandler() {
@Override
public Object handle(Method method, Object[] args) {
String name = method.getName();
if ("prepareStatement".equals(name)) {
executedSql.set(String.valueOf(args[0]));
return proxy(PreparedStatement.class, new MethodHandler() {
@Override
public Object handle(Method stmtMethod, Object[] stmtArgs) {
String m = stmtMethod.getName();
if ("setString".equals(m) || "setObject".equals(m) || "setInt".equals(m)) {
return null;
}
if ("executeQuery".equals(m)) {
return resultSet;
}
if ("close".equals(m)) {
return null;
}
return defaultValue(stmtMethod.getReturnType());
}
});
}
if ("isClosed".equals(name)) {
return false;
}
return defaultValue(method.getReturnType());
}
});
}
private static Connection preparedConnection(Map<String, Object>... rows) {
final ResultSet resultSet = rows(rows);
return proxy(Connection.class, new MethodHandler() {