fix(jdbc): send rowOffset for generic JDBC table pagination

This commit is contained in:
zipg authored and GitHub committed 2026-09-21 11:38:18 +08:00
1 parent 79d6ab64e9
commit 90ad995803
7 files changed
+119 -3

No files matched your search

@@ -20,6 +20,7 @@ import {
gaussdbIdentifierQuoteStyle,
gaussdbTargetServerType,
inferJdbcDialect,
jdbcConnectionUsesDriverRowOffset,
metadataSchemaForConnection,
objectListSchemaForConnection,
setGaussdbConnectionMode,
@@ -328,6 +329,29 @@ describe("jdbc dialect inference", () => {
});
});
describe("JDBC driver row offset", () => {
it("lets the driver skip rows for dialects without SQL offset pagination", () => {
// Unknown vendor dialects stay on the generic JDBC dialect, which emits a
// bare SELECT, so the page offset can only be applied by the driver (#9015).
expect(jdbcConnectionUsesDriverRowOffset({ db_type: "jdbc", connection_string: "jdbc:sybase:Tds:db.example.com:5000/app" }, "jdbc")).toBe(true);
expect(jdbcConnectionUsesDriverRowOffset({ db_type: "jdbc", connection_string: "jdbc:hsqldb:hsql://127.0.0.1:9001/probe" }, "jdbc")).toBe(true);
});
it("keeps the Caché/IRIS ResultSet offset behavior", () => {
expect(jdbcConnectionUsesDriverRowOffset({ db_type: "jdbc", connection_string: "jdbc:Cache://localhost:1972/USER" }, "iris")).toBe(true);
});
it("leaves SQL-paginated dialects and driver-capped JDBC drivers alone", () => {
expect(jdbcConnectionUsesDriverRowOffset({ db_type: "jdbc", connection_string: "jdbc:mysql://localhost:3306/app" }, "mysql")).toBe(false);
expect(jdbcConnectionUsesDriverRowOffset({ db_type: "jdbc", connection_string: "jdbc:oracle:thin:@localhost:1521:XE" }, "oracle")).toBe(false);
// YashanDB keeps the generic dialect, but its agent applies
// Statement.setMaxRows, which would cap the result set before the skipped rows.
expect(jdbcConnectionUsesDriverRowOffset({ db_type: "jdbc", connection_string: "jdbc:yasdb://localhost:1688/app" }, "jdbc")).toBe(false);
expect(jdbcConnectionUsesDriverRowOffset({ db_type: "postgres" }, "postgres")).toBe(false);
expect(jdbcConnectionUsesDriverRowOffset(undefined, "jdbc")).toBe(false);
});
});
describe("GaussDB connection mode", () => {
it("keeps native connections compatible and configures M mode for the vendor JDBC driver", () => {
const connection = { db_type: "gaussdb", driver_profile: "gaussdb", driver_label: "GaussDB" } as ConnectionConfig;
@@ -67,6 +67,29 @@ export function jdbcDriverProfileUsesSchemaQualification(driverProfile?: string)
return inferJdbcDialect({ db_type: "jdbc", driver_profile: driverProfile }) === "jdbc";
}
/**
* Whether a JDBC-backed table view must let the driver skip `rowOffset` rows
* instead of expecting SQL pagination.
*
* Generic JDBC (`DatabaseType::Jdbc` → `AgentMaxRows`) and Iris (`IrisTop`) are
* the two dialects that cannot express a page offset in the generated SELECT:
* generic JDBC emits no LIMIT/OFFSET at all and Iris only has `TOP`. Without the
* driver-side offset the agent re-runs the same unbounded statement for every
* page, so the grid keeps rendering page one (#9015).
*
* The Oracle, Dameng and Yashan driver families are excluded because the JDBC
* agent passes `maxRows + 1` to `Statement.setMaxRows` for them, which caps the
* result set *before* the skipped rows — those drivers paginate in SQL instead.
*/
const JDBC_STATEMENT_MAX_ROWS_URL_PREFIXES = ["jdbc:oracle:", "jdbc:dm:", "jdbc:yasdb:"];
export function jdbcConnectionUsesDriverRowOffset(connection: JdbcDialectConnection | undefined, effectiveDatabaseType: DatabaseType | undefined): boolean {
if (connection?.db_type !== "jdbc") return false;
if (effectiveDatabaseType !== "iris" && effectiveDatabaseType !== "jdbc") return false;
const url = connection.connection_string?.trim().toLowerCase() ?? "";
return !JDBC_STATEMENT_MAX_ROWS_URL_PREFIXES.some((prefix) => url.startsWith(prefix));
}
export function effectiveDatabaseTypeForConnection(connection?: JdbcDialectConnection): DatabaseType | undefined {
if (!connection) return undefined;
if (connection.db_type === "gbase" && isGbase8sProfile(connection.driver_profile)) return "informix";