Repository navigation
Find the framework surface we do not implement, and write it down - #18
Merged
Merged
Conversation
Issue #11 asks for the list of driver surface a framework calls unconditionally and we refuse, not for four passing tests. Four things came out of the search, and docs/unsupported.md now carries them. Nothing on DatabaseMetaData throws. DatabaseMetaDataSurfaceIT sweeps all 179 methods reflectively, which is what a JDBC GUI does at connect time and the reason issue #11 ranks DBeaver first: one refusal inside that sweep is reported as "could not connect", so the driver looks broken before the user has typed anything. 160 answer, 19 return an empty result set, none throws. The test asserts the zeros so the property cannot be lost by accident, and it checks every metadata result set against the column labels JDBC 4.3 specifies -- transcribed from the JDBC javadoc rather than from this driver -- because jOOQ and MyBatis address those columns by name and a zero-row set with the wrong labels is as broken as a throw and much harder to see. A bound parameter is typed String, and that is a usage constraint rather than a footnote. It works in a comparison, where ClickHouse converts the literal to the column's type, and fails where a numeric constant is required: LIMIT, OFFSET, arithmetic, numeric table-function arguments. jOOQ renders .limit() as a bind value by default, so this is the first thing a jOOQ user hits, and MyBatis's #{} in numbers() is the second. Both now have a test naming the engine's error code and the cast that fixes it. MyBatis and jOOQ both refuse a transaction at the same place: MyBatis's default JdbcTransactionFactory and jOOQ's DefaultTransactionProvider each call setAutoCommit(false) before running anything, which the driver will not do. MyBatis has a way out -- openSession(true), or ManagedTransactionFactory -- and jOOQ does not, so a jOOQ application against chDB works outside transaction(). ShardingSphere cannot be wired up at all, and it is upstream's. 5.5.3 already lists jdbc:chdb among its ClickHouse URL prefixes, but every DatabaseType then parses the URL with StandardJdbcUrlParser, which requires the //authority of a client/server URL and refuses the URL without it. No chDB URL of any form gets through, and the YAML driver and the programmatic factory fail identically, so there is no configuration route around it. ShardingSphereIT pins that rather than skipping, so it starts failing when ShardingSphere can parse an embedded URL. Versions are the last of each that runs on Java 11, the driver's floor: MyBatis 3.5.19, jOOQ 3.16.23 -- 3.17.0 is the first Open Source Edition compiled to class file 61, read out of the published jar -- and ShardingSphere 5.5.3. All test scope; chdb-jdbc still resolves to no non-test dependency at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three status lines still described the state before HikariPoolIT landed: the README called the whole row 🚧 and named Spring, HikariCP and ShardingSphere as the set; v1-progress listed HikariCP as not started, which it has not been since PR #6; and release-readiness grouped ShardingSphere with Spring as "lower yield, half a day". The last one is the misleading one. ShardingSphere is not lower yield, it is not reachable: every DatabaseType parses the URL with StandardJdbcUrlParser, which requires the //authority of a client/server URL, so jdbc:chdb:, jdbc:chdb::memory: and a filesystem path are all rejected before any config we could write is read. Half a day of effort would not have closed it. It is now its own row, marked upstream and pinned by ShardingSphereIT so it flips when that changes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Review asked whether the documented 179-method sweep happens on Java 11, the driver's floor, and said the interface has 170 methods there. It does not: DatabaseMetaData.class.getMethods() returns 179 on JDK 11, 21 and 26 alike, and the scan classified all 179 on each. The interface declares 177 of its own -- getSchemas and supportsConvert being overload pairs -- and inherits unwrap and isWrapperFor from Wrapper. So the coverage claim held, but it was resting on an assertion that could not have caught it if it had not. That assertion was `results.size() >= 165`, and the objection to it is right whatever the count turns out to be: a floor loose enough to pass with nine methods missing is not guarding the thing the test exists to guard. Replaced with an exact equality against DatabaseMetaData.class.getMethods().length -- every method the running JDK reports, invoked and classified, once each. That says what the test means, holds on any JDK, and does not have to be revisited when a JDBC revision moves the total. Checked by deleting one method from the swept list: the old assertion passed, the new one fails with 178 against 179. Two smaller holes in the same spirit. scannableMethods() filtered out Object's methods, which getMethods() on an interface never returns anyway (measured 0 on all three JDKs) and which would have made the new equality unreliable if it ever did; it is gone, so the count is exact rather than nearly exact. And everyResultSetCarriesItsJdbcColumns() silently skipped any ResultSet-returning method with no transcribed column list, so a future JDBC catalog query would have quietly gone unchecked; it now fails on the gap and asserts it checked every ResultSet-returning method on the interface. Docs say 179 where they say a number, but say it as a JDK property with the JDK versions named, and lead with the coverage property instead. The scan's printed report now names the JDK and the surface size, so a report pasted into an issue can be compared with another one. Verified with the full module suite on JDK 11 and JDK 26, and the sweep alone on 21: 160 values, 19 empty result sets, 0 refusals, 0 errors on each. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ut costs
Review said the "no setting for it" claim was wrong because jOOQ ships
NoTransactionProvider. Half right, and the half that is wrong is a trap
worth its own test.
Configuring org.jooq.impl.NoTransactionProvider changes nothing.
DefaultConfiguration.transactionProvider() treats that class as a
sentinel for "unset" and hands back a DefaultTransactionProvider
instead -- read out of jooq-3.16.23 and now asserted, along with
transaction() still being refused afterwards. Subclassing it does not
help either, because the check is an instanceof. Anyone following that
advice would have configured it, seen the same SQLFeatureNotSupportedException
and had no idea why.
What does work is the same SPI with any other implementation:
TransactionProvider has three methods, and a no-op class that is not
jOOQ's own is honoured, so begin never reaches setAutoCommit(false) and
the block runs. Verified.
The cost is the entire point, and it gets more space than the workaround.
A no-op provider means the statements in the block run one at a time as
they would outside it and a failure part-way through leaves the earlier
ones applied -- asserted by throwing out of a block after an INSERT and
finding the row still there. So it buys nothing but the ability to keep
transaction() in the source: not a weak transaction, no transaction, in
code that reads as though it had a unit of work. That is not a driver
gap. chDB has no transaction manager, so a framework's transaction
abstraction can only degrade to a no-op on it, and the real choice is
between a refusal at the call site and a block that silently is not
atomic. The driver refuses; installing the provider chooses the other
one.
Audited the section for the same sentence shape, since that is what got
picked up. Two more:
* "not fixable from here" and "no configuration route around it" for
ShardingSphere. The configuration claim stands -- no YAML key and no
factory argument avoids the URL parse, which the test covers for both
entry points -- but DatabaseType and ConnectionPropertiesParser are
ServiceLoader SPIs, so a chDB-specific pair registered ahead of
ShardingSphere's ClickHouse one is a code route. Documented, with why
it is not taken: it means versioning a plugin against SPIs that move
between minor releases, and it would test the plugin rather than this
driver.
The jOOQ column-type paragraph already carried its workaround, and
checking 3.19.24 confirmed no ClickHouse dialect exists in the Open
Source Edition's SQLDialect to over-claim about.
Full module suite on JDK 11 and JDK 26.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #11. Does not close it — Spring
JdbcTemplateis still open, and ShardingSphere turns outnot to be closable here at all.
The issue said the deliverable is less the passing test than the list of unconditionally-called
surface we do not implement. Here is that list, and the headline is that it is empty.
DatabaseMetaData, the DBeaver stand-inDatabaseMetaDataSurfaceITinvokes all 179 methods of JDBC 4.3'sDatabaseMetaDatareflectively, with the arguments a GUI would pass:
SQLFeatureNotSupportedExceptionSo the risk the issue names — "a
SQLFeatureNotSupportedExceptionthrown from somewhere DBeavercalls unconditionally would make the driver look broken on first contact" — does not exist.
The test does not stop at non-null. Every metadata result set is checked against the JDBC 4.3
column labels transcribed from the specification, not read back from the driver, and every
ResultSetMetaDataaccessor is called on every column of every one. All present, all answerable,rows or not. That is the empty-
ResultSet-with-correct-metadata path the issue flagged as adifferent code path, and it is correct.
The 19 empty ones:
getAttributes,getBestRowIdentifier,getCatalogs,getClientInfoProperties,getColumnPrivileges,getCrossReference,getExportedKeys,getFunctionColumns,getImportedKeys,getIndexInfo,getPrimaryKeys,getProcedureColumns,getProcedures,getPseudoColumns,getSuperTables,getSuperTypes,getTablePrivileges,getUDTs,getVersionColumns.Per framework
JdbcTransactionFactorywithopenSession()callssetAutoCommit(false), which the driver refuses; useopenSession(true)or
ManagedTransactionFactory. Auto-mapping picks the rightTypeHandlerper column andinsert()returns the real affected-row count..limit()fails by default because it isrendered as a bind value (fix:
StatementType.STATIC_STATEMENT), andtransaction()is refusedwith no setting to avoid it. Also recorded so it is not mistaken for a driver bug: jOOQ types
every chDB column as
ObjectbecauseSQLDialect.DEFAULThas noInt32/DateTime64. Thedriver reports
INTEGER/Int32/java.lang.Integercorrectly on populated and zero-row sets,which is asserted.
jdbc:chdbamong its ClickHouse URL prefixes, but everyDatabaseTypethen parses the URL withStandardJdbcUrlParser, which requires the//authorityof a client/server URL.jdbc:chdb:,jdbc:chdb::memory:and a filesystem storage path all fail withUnrecognizedDatabaseURLException; the YAML driver andShardingSphereDataSourceFactoryfailidentically, so no configuration reaches the driver.
ShardingSphereITpins this with 3 tests soit flips when upstream changes. Its connection management versus one-storage-path-per-JVM
therefore stays untested;
HikariPoolITis the nearest cover, since ShardingSphere's own poolsare HikariCP.
A cross-cutting finding
Bound parameters are typed
String, because the engine's binding is textual. Measured on 26.7.0:fine in
= ? < ? > ? IN (?)and string contexts; fails inLIMIT ?/OFFSET ?(Code 440),in arithmetic (Code 43), and in numeric table-function arguments like
numbers(?)(Code 43). Thisis the root cause of the jOOQ
.limit()failure. Workaround is to cast in SQL —toUInt64(?).Recorded in
docs/unsupported.md; it deserves its own issue.Nothing here is blocked on #12
The driver's
DatabaseMetaDatais implemented as plainSELECTs againstsystem.*tables, sonone of the metadata surface touches
SHOWorDESCRIBE.Also in this PR
Three status lines that described the state before
HikariPoolITlanded — the README row, thephase-9 row in
docs/v1-progress.md, and thedocs/release-readiness.mdgap table. The last wasthe misleading one: it grouped ShardingSphere with Spring as "lower yield, half a day", when
ShardingSphere is not lower yield but unreachable.
Verified
mvn -pl chdb-jdbc,chdb-integration-tests -am verifyon macos-aarch64: 148 unit + 127 integrationtests, 0 failures.
mvn -pl chdb-jdbc dependency:treeshows exactly one dependency,junit-jupiter:test— the driver's zero-third-party-runtime-dependency property is intact. Newdependencies are test scope only, with the version choices justified in the pom against the Java 11
floor (jOOQ 3.17.0 is class file 61, read out of the published jar).
🤖 Generated with Claude Code
Note
Add integration tests for
DatabaseMetaDatasurface, jOOQ, MyBatis, and ShardingSphereDatabaseMetaDatamethod from the running JDK, classifies outcomes, and verifies everyResultSet-returning method exposes the expected JDBC column labels#{...}parameter binding, type-handler selection, and transaction factoriesjdbc:chdbas a ClickHouse prefix but rejects embedded URL forms lacking an authorityMacroscope summarized a312ae9.