Skip to content

fix(jdbc): return java.sql-shaped DatabaseMetaData results (#156) - #162

Merged
magnusp merged 1 commit into
mainfrom
fix/i156-dbmetadata-gaps
Oct 23, 2026
Merged

magnusp merged 1 commit into
mainfrom
fix/i156-dbmetadata-gaps

Conversation

@magnusp

@magnusp magnusp commented Oct 23, 2026

Copy link
Copy Markdown
Owner

fix(jdbc): return java.sql-shaped DatabaseMetaData results (#156)

Fixes #156

Hrana 3 is the source of truth for transport, values, metadata, batching,
transactions, and error reporting. java.sql is the source of truth for the
JDBC surface. xerial/sqlite-jdbc 3.53.4.0 is the behavioral reference and
conformance foundation, never a copy target.

What changed

  • getProcedures, getProcedureColumns, getColumnPrivileges,
    getTablePrivileges, getBestRowIdentifier, getVersionColumns, and
    getUDTs return an empty result set with the java.sql column list through
    the existing synthesized-metadata path, instead of throwing
    SQLFeatureNotSupportedException.
  • getColumns synthesizes the sqlite_schema system table and orders rows the
    way getTables does: temporary, system, table, then view, by name.
  • getCrossReference returns no row when a non-empty catalog or schema is
    requested, because the server reports neither.
  • getPrimaryKeys sorts rows by COLUMN_NAME, matching xerial's order by cn,
    while KEY_SEQ keeps the declared key position.
  • NAMED_PRIMARY_KEY also matches a constraint name glued to the keywords,
    as in CONSTRAINT`NamedPk`PRIMARY KEY(...).

Red

New unit cases at base 3de2ad5 with only the test diff applied:

./mvnw -pl libsql-jdbc -Dtest=LibsqlDatabaseMetaDataTest test
Tests run: 53, Failures: 3, Errors: 14

Vendored DBMetaDataTest at the same base, with a temporary copy selected:

./mvnw -pl libsql-conformance -am -Dit.test=DBMetaDataTest verify
Tests run: 56, Failures: 3, Errors: 8, Skipped: 1
getColumns, getCrossReferenceCatalogSchemaWithQuote, columnOrderOfgetPrimaryKeys,
columnOrderOfgetProcedures, columnOrderOfgetProcedurColumns,
columnOrderOfgetColumnPrivileges, columnOrderOfgetTablePrivileges,
columnOrderOfgetBestRowIdentifier, columnOrderOfgetVersionColumns,
columnOrderOfgetUDTs, columnOrderOfgetTables

Green

At head, with the same temporary copy:

./mvnw -pl libsql-conformance -am -Dit.test=DBMetaDataTest verify
Tests run: 56, Failures: 0, Errors: 1, Skipped: 1

The single remaining error is columnOrderOfgetTables at line 1113:
sqld rejects CREATE TEMP TABLE with SQL_PARSE_ERROR. The xerial control run
passes all 56 on the same copy, so this is remote-model divergence, not a driver
gap. The driver does not fake TEMP support; the later selection PR records the
divergence or excludes the case. version is skipped by its compile-option
assumption.

Full lanes:

./mvnw -pl libsql-jdbc test                           Tests run: 336, Failures: 0, Errors: 0
./mvnw -pl libsql-conformance -am verify              Tests run: 123, Failures: 0, Errors: 0, Skipped: 1
./mvnw -pl libsql-conformance -am -Pxerial-control verify  Tests run: 100, Failures: 0, Errors: 0, Skipped: 1
./mvnw test                                           BUILD SUCCESS
./mvnw spotless:check                                 BUILD SUCCESS
./mvnw -pl libsql-jdbc -am package -DskipTests        BUILD SUCCESS
tools/export-upstream --verify                        verified

Perf, three interleaved runs of ./mvnw -pl libsql-jdbc test: base median
2.47 s, head median 2.50 s (+1.2%).

Logs are in /tmp/xerial-parity-i156/. The vendored tree is unchanged.

Files

libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlDatabaseMetaData.java,
libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlDatabaseMetaDataTest.java.

Fixes #156

Hrana 3 is the source of truth for transport, values, metadata, batching,
transactions, and error reporting. `java.sql` is the source of truth for the
JDBC surface. xerial/sqlite-jdbc 3.53.4.0 is the behavioral reference and
conformance foundation, never a copy target.

## What changed

- `getProcedures`, `getProcedureColumns`, `getColumnPrivileges`,
  `getTablePrivileges`, `getBestRowIdentifier`, `getVersionColumns`, and
  `getUDTs` return an empty result set with the `java.sql` column list through
  the existing synthesized-metadata path, instead of throwing
  `SQLFeatureNotSupportedException`.
- `getColumns` synthesizes the `sqlite_schema` system table and orders rows the
  way `getTables` does: temporary, system, table, then view, by name.
- `getCrossReference` returns no row when a non-empty catalog or schema is
  requested, because the server reports neither.
- `getPrimaryKeys` sorts rows by `COLUMN_NAME`, matching xerial's `order by cn`,
  while `KEY_SEQ` keeps the declared key position.
- `NAMED_PRIMARY_KEY` also matches a constraint name glued to the keywords,
  as in ``CONSTRAINT`NamedPk`PRIMARY KEY(...)``.

## Red

New unit cases at base `3de2ad5` with only the test diff applied:

```
./mvnw -pl libsql-jdbc -Dtest=LibsqlDatabaseMetaDataTest test
Tests run: 53, Failures: 3, Errors: 14
```

Vendored `DBMetaDataTest` at the same base, with a temporary copy selected:

```
./mvnw -pl libsql-conformance -am -Dit.test=DBMetaDataTest verify
Tests run: 56, Failures: 3, Errors: 8, Skipped: 1
getColumns, getCrossReferenceCatalogSchemaWithQuote, columnOrderOfgetPrimaryKeys,
columnOrderOfgetProcedures, columnOrderOfgetProcedurColumns,
columnOrderOfgetColumnPrivileges, columnOrderOfgetTablePrivileges,
columnOrderOfgetBestRowIdentifier, columnOrderOfgetVersionColumns,
columnOrderOfgetUDTs, columnOrderOfgetTables
```

## Green

At head, with the same temporary copy:

```
./mvnw -pl libsql-conformance -am -Dit.test=DBMetaDataTest verify
Tests run: 56, Failures: 0, Errors: 1, Skipped: 1
```

The single remaining error is `columnOrderOfgetTables` at line 1113:
sqld rejects `CREATE TEMP TABLE` with `SQL_PARSE_ERROR`. The xerial control run
passes all 56 on the same copy, so this is remote-model divergence, not a driver
gap. The driver does not fake TEMP support; the later selection PR records the
divergence or excludes the case. `version` is skipped by its compile-option
assumption.

Full lanes:

```
./mvnw -pl libsql-jdbc test                           Tests run: 336, Failures: 0, Errors: 0
./mvnw -pl libsql-conformance -am verify              Tests run: 123, Failures: 0, Errors: 0, Skipped: 1
./mvnw -pl libsql-conformance -am -Pxerial-control verify  Tests run: 100, Failures: 0, Errors: 0, Skipped: 1
./mvnw test                                           BUILD SUCCESS
./mvnw spotless:check                                 BUILD SUCCESS
./mvnw -pl libsql-jdbc -am package -DskipTests        BUILD SUCCESS
tools/export-upstream --verify                        verified
```

Perf, three interleaved runs of `./mvnw -pl libsql-jdbc test`: base median
2.47 s, head median 2.50 s (+1.2%).

Logs are in `/tmp/xerial-parity-i156/`. The vendored tree is unchanged.

## Files

`libsql-jdbc/src/main/java/com/github/magnusp/libsql/jdbc/LibsqlDatabaseMetaData.java`,
`libsql-jdbc/src/test/java/com/github/magnusp/libsql/jdbc/LibsqlDatabaseMetaDataTest.java`.
@magnusp
magnusp merged commit d02206c into main Oct 23, 2026
6 checks passed
@magnusp
magnusp deleted the fix/i156-dbmetadata-gaps branch October 23, 2026 03:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DBMetaDataTest exposes DatabaseMetaData gaps beyond the #41/#42/#50 fixes

1 participant