[#885] Ask the catalog for the table of a tree by name - #886
Merged
vharseko merged 1 commit intoAug 20, 2026
Merged
Conversation
… name isExistsTable() listed every table of the database and looked for a match in Java: no catalog filter, no schema filter, no table name. It is called from openTree(createOnDemand) through AbstractTree.open() for every tree of the backend - about 25 of them for a stock suffix - so opening a backend walked the whole catalog once per tree, on a database this backend may well be sharing with something else. The name is passed as the pattern now. It has to be passed in the form the catalog stores it, since an unquoted identifier is folded when it is stored - to upper case on oracle, to lower case on postgresql - and a metadata pattern is matched against the stored form rather than against the name as it was written. Which way a driver folds is asked of the driver itself, through the two methods the JDBC contract exposes for it, rather than by matching its class name as the dialect switches elsewhere in this class do. The comparison of the name is kept: "_" is a single-character wildcard in a metadata pattern, so "opendj_<hash>" also matches a table called "opendjX<hash>", and the result of the lookup is still verified rather than trusted. testTableOfATreeIsFoundByName covers both answers on every dialect: a second open has to find the table rather than create it again - getting the folding wrong would raise ORA-00955 on oracle - and a second delete has to find nothing rather than drop what is not there.
maximthomas
approved these changes
Aug 20, 2026
This was referenced Aug 20, 2026
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.
Problem
isExistsTable()asked the catalog for every table of the database and looked for a match in Java — no catalog filter, no schema filter, no table name:It is called from
openTree(createOnDemand)— throughAbstractTree.open(), which every tree of the backend goes through — and fromdeleteTree(). Opening a backend therefore walked the whole catalog once per tree: about 25 times for a stock suffix, on a database this backend may well be sharing with something else, and the cost is O(trees × tables) in something that ought to be a single indexed lookup.It was first written up as a missing timeout, in what was then the third section of #885. It is not: the call is unbounded and needlessly expensive, and making it cheap is the fix that matters, so it was split out as #887. (What remains unbounded there can only be reached by the read timeout #885 still asks for, since
DatabaseMetaDatatakes nosetQueryTimeoutat all.)Change
The table name is passed as the pattern, so the driver asks its catalog for one row instead of all of them.
The name has to be passed in the form the catalog stores it: an unquoted identifier is folded when it is stored — to upper case on Oracle, to lower case on PostgreSQL — and a metadata pattern is matched against the stored form, not against the name as it was written. Which way a driver folds is asked of the driver, through
storesUpperCaseIdentifiers()/storesLowerCaseIdentifiers(), rather than by matching its class name the way the dialect switches elsewhere in this class do: that pair of methods is exactly what the JDBC contract exposes for this, and it costs no round trip.The comparison of the returned name is kept rather than dropped as redundant.
_is a single-character wildcard in a metadata pattern, soopendj_<hash>also matches a table calledopendjX<hash>; escaping it throughgetSearchStringEscape()is the kind of thing drivers disagree about, and re-checking the answer is both cheaper and surer.isExistsIndex()is left alone: it already passes the table name togetIndexInfo(), so it is a targeted lookup already. Its caller still uppercases the name for Oracle by driver-name check, whichstoredIdentifier()could now replace — a tidy-up worth doing on its own rather than inside this one.Tests
testTableOfATreeIsFoundByNameexercises both answers of the lookup on all four dialects: a tree is opened, then opened again — the second open has to find the table rather than create it a second time, which is where a wrong identifier folding shows up asORA-00955on Oracle — the entry written before is read back to confirm the tree was not replaced, and the tree is then deleted twice, the second delete having to find nothing rather than drop what is no longer there.All four container suites pass with no skips: PgSql 38/38, MySql 38/38, MsSql 38/38, Oracle 38/38, plus the JDBC
EncryptedTestCase34/34. Every one of them runsopenTree()for every tree of the backend on each open, so the lookup is exercised far beyond the test written for it.Scope
#885 keeps what this does not touch — a read timeout for an established connection as a setting of its own, a lock timeout for the pooled connections, and the bound of the catalog reads and of
commit(). The first two live inCachedConnection, in code that #876 introduces, so no branch off master can reach them yet.Fixes #887