Skip to content

[#1075] Test the JDBC guards against a neighbouring MySQL database and Oracle schema - #1108

Open
vharseko wants to merge 1 commit into
OpenIdentityPlatform:masterfrom
vharseko:issues/1075-jdbc-neighbour-catalog-guard
Open

vharseko wants to merge 1 commit into
OpenIdentityPlatform:masterfrom
vharseko:issues/1075-jdbc-neighbour-catalog-guard

Conversation

@vharseko

Copy link
Copy Markdown
Member

Fixes #1075

Test-only change: the MySQL/Oracle twin of #902's postgres case (PgSqlTestCase.testAnOpenIsAnsweredForByNoTableOfASchemaOffTheSearchPath), shaped by what the drivers actually return rather than by the case the issue sketched.

What the drivers do (measured)

Probes against the drivers this backend ships (Connector/J 9.2.0 on mysql:9.2, ojdbc8 23.7 on oracle-free 23.26.2), with a neighbour holding the same table and index name:

Setting getCatalog / getSchema What the lookup returns for the neighbour What guards against it
MySQL, default databaseTerm=CATALOG database / null nothing with the catalog passed; TABLE_CAT=<neighbour> rows with null two layers: the catalog passed to getTables/getIndexInfo, and isSameCatalog in TableScope.covers()
MySQL, databaseTerm=SCHEMA null / database TABLE_CAT=def, TABLE_SCHEM=<neighbour> only the mysql branch of schemaPathOf() + the schema half of covers()
Oracle null / OPENDJ nothing without a grant; SCHEM=<neighbour> once grant select is given only the oracle branch of schemaPathOf() + the schema half of covers()

So the case #1075 sketched — two databases on the default MySQL connection — goes red only when both layers give way at once; a loosening of either one alone, which is what the issue worries about, stays green there. Each layer needs a case of its own.

Changes

  • JDBCStorageRetryTest — three mock cases on the mysql branch:
    • testTheMySqlGuardsAskInTheDatabaseOfTheConnection — getTables/getIndexInfo are asked with con.getCatalog(), not any();
    • testAnIndexOfAnotherDatabaseAnswersForNoneOfThisOne — an index row of another TABLE_CAT is not this backend's, and create index is issued;
    • testUnderDatabaseTermSchemaAnIndexOfAnotherDatabaseAnswersForNoneOfThisOne — the same with the row shape measured under databaseTerm=SCHEMA.
  • MySqlTestCase.testAnOpenIsAnsweredForByNoTableOfAnotherDatabase — live, data-provided over catalog (default) and schema (?databaseTerm=SCHEMA); neighbour database made as root, asserted through information_schema.
  • OracleTestCase.testAnOpenIsAnsweredForByNoTableOfAnotherSchema — live; the neighbour user is made by SYSTEM (the container's ORACLE_PASSWORD is the withPassword value — checked in testcontainers 1.20.6) and granted to opendj, without which the dictionary views show nothing and the case would pin nothing. The manual docker run hint now passes -e ORACLE_PASSWORD=password.
  • TestCase.dropStaleNeighbours() — a best-effort hook run in setUp() before dropStaleTrees(). That listing spans every database/schema the connection sees, so a neighbour left by a killed run on a long-lived manual container would make its unqualified (mysql) or unprivileged (oracle) drop table fail and skip the whole class on every later run.

No production code changes.

Verification

Mutants of JDBCStorage, each run against the mock class and the live case:

Mutant Mock cases Live MySQL Live Oracle
m1: no catalog passed to getTables/getIndexInfo red: …AskInTheDatabase… green —
m2: covers() ignores the row's database red: …AnIndexOfAnotherDatabase… green —
m3: m1 + m2 both red red (catalog) —
m4: mysql branch of schemaPathOf() returns null red: …UnderDatabaseTermSchema… red (schema) —
m5: oracle branch of schemaPathOf() returns null green — red (ORA-00942)

Head, one JVM per class: JDBCStorageRetryTest 116/116, MySqlTestCase 97/97, PgSqlTestCase 94/94, jdbc EncryptedTestCase 38/38, OracleTestCase 92 passed + 1 skip (the existing SkipException of testAConnectionGetsItsLockBoundBackAfterADdl on Oracle — "no session lock bound"). MsSqlTestCase is not runnable locally and is left to CI.

…ng MySQL database and Oracle schema

Pin each layer that keeps a table or index of another database of the server
from answering for one of this backend's in openTree():

- JDBCStorageRetryTest: the MySQL guards pass the database of the connection
  as the catalog; covers() drops a row of another database; under
  databaseTerm=SCHEMA the schema path alone tells the neighbour apart.
- MySqlTestCase: a live case over a second database of the same server, under
  the default databaseTerm and under databaseTerm=SCHEMA.
- OracleTestCase: a live case over another user's schema, visible to the
  suite through a grant.
- TestCase: drop such a neighbour left by a killed run before dropStaleTrees(),
  which would otherwise skip the whole class on every later run.

Fixes OpenIdentityPlatform#1075
@vharseko vharseko added jdbc tests Test suites: fixing, enabling, un-disabling java Changes to Java sources labels Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

java Changes to Java sources jdbc tests Test suites: fixing, enabling, un-disabling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[#902] No MySQL/Oracle twin of the JDBC schema-collision guard case

1 participant