Skip to content

923 h2 information schema leak - #924

Merged
jeffjensen merged 3 commits into
mainfrom
923-h2-information-schema-leak
Aug 9, 2026
Merged

923 h2 information schema leak#924
jeffjensen merged 3 commits into
mainfrom
923-h2-information-schema-leak

Conversation

@jeffjensen

@jeffjensen jeffjensen commented Aug 9, 2026

Copy link
Copy Markdown
Member

Summary by Sourcery

Add H2-specific metadata handling and shared in-memory ResultSet utilities to prevent H2 INFORMATION_SCHEMA tables from appearing as user tables, and update tests, documentation, and build configuration accordingly.

New Features:

  • Introduce H2MetadataHandler and wire it into H2Connection to filter out INFORMATION_SCHEMA tables from H2 metadata queries.
  • Add a reusable InMemoryMetadataResultSet utility with merge and filter factories for composing and filtering JDBC metadata result sets.

Enhancements:

  • Refactor MultiSchemaMySqlMetadataHandler to use the shared InMemoryMetadataResultSet implementation instead of its private nested version.
  • Adjust DatabaseDataSet multi-schema tests to use a delegating TestMetadataHandler and the real H2MetadataHandler, decoupling tests from concrete vendor handler inheritance.
  • Update DatabaseSequenceFilter integration tests to use H2Connection for multi-schema foreign key ordering scenarios.

Build:

  • Bump the H2 JDBC driver version from 1.4.200 to 2.4.240 in the Maven build configuration.

Documentation:

  • Add an IMetadataHandler core components page documenting the interface, built-in implementations, and InMemoryMetadataResultSet utilities, and cross-reference it from existing component and database documentation.
  • Document H2MetadataHandler usage and list MultiSchemaMySqlMetadataHandler under the metadataHandler property, and add testing conventions guidance favoring delegating wrappers over subclassing vendor handlers.

Summary by CodeRabbit

  • Bug Fixes

    • Added support for H2 2.x databases.
    • Excluded H2 INFORMATION_SCHEMA system tables from metadata results, preserving visibility of user tables.
    • Improved multi-schema metadata handling and result filtering.
  • Documentation

    • Added guidance for metadata handlers, custom configurations, and reusable metadata result sets.
    • Updated H2, database, properties, and component documentation with the new behavior and configuration details.

…maMySqlMetadataHandler

* Move the private nested InMemoryMetadataResultSet proxy out to its own
  public class in org.dbunit.database so other IMetadataHandler
  implementations can reuse it, not just MySQL's.
* No behavior change; MultiSchemaMySqlMetadataHandler's merge() usage is
  unaffected.

Refs: 923
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@sourcery-ai

sourcery-ai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduce a reusable in-memory metadata ResultSet helper and an H2-specific metadata handler to filter out INFORMATION_SCHEMA tables when using H2 2.x, wire it into H2 connections and tests, and update documentation and build configuration accordingly.

Sequence diagram for H2MetadataHandler getTables filtering INFORMATION_SCHEMA

sequenceDiagram
    participant Client
    participant H2Connection
    participant DatabaseConfig
    participant H2MetadataHandler
    participant DefaultMetadataHandler
    participant InMemoryMetadataResultSet

    Client->>H2Connection: new H2Connection(connection, schema)
    H2Connection->>DatabaseConfig: setProperty(PROPERTY_METADATA_HANDLER, new H2MetadataHandler())

    Client->>H2MetadataHandler: getTables(metaData, null, {"TABLE"})
    H2MetadataHandler->>DefaultMetadataHandler: getTables(metaData, null, {"TABLE"})
    DefaultMetadataHandler-->>H2MetadataHandler: ResultSet rawTables
    H2MetadataHandler->>InMemoryMetadataResultSet: filter(rawTables, row -> !"INFORMATION_SCHEMA".equalsIgnoreCase(getSchema(row)))
    InMemoryMetadataResultSet-->>H2MetadataHandler: ResultSet filteredTables
    H2MetadataHandler-->>Client: ResultSet filteredTables
Loading

File-Level Changes

Change Details Files
Extract and generalize the in-memory metadata ResultSet implementation into a reusable utility class with merge and filter capabilities.
  • Remove the private nested InMemoryMetadataResultSet from the MySQL multi-schema metadata handler and replace it with an import of the shared implementation.
  • Create org.dbunit.database.InMemoryMetadataResultSet as a standalone InvocationHandler-based proxy over ResultSet/ResultSetMetaData.
  • Implement merge(List) to copy and combine rows from multiple source ResultSets, preserving column labels and closing all sources.
  • Implement filter(ResultSet, RowFilter) to copy only rows matching a caller-provided predicate from a single source ResultSet.
  • Factor common copy-and-close logic into a private method that builds the in-memory representation and proxy.
  • Provide minimal implementations for next, getString, getInt, getMetaData, getColumnCount, close, equals, hashCode, and toString, throwing UnsupportedOperationException for any other method.
src/main/java/org/dbunit/ext/mysql/MultiSchemaMySqlMetadataHandler.java
src/main/java/org/dbunit/database/InMemoryMetadataResultSet.java
Add an H2-specific metadata handler that filters out INFORMATION_SCHEMA tables now reported as BASE TABLE in H2 2.x, and wire it into H2Connection and tests.
  • Introduce H2MetadataHandler extending DefaultMetadataHandler and overriding getTables to wrap the superclass result in an InMemoryMetadataResultSet.filter call.
  • Implement a RowFilter that rejects rows whose schema matches INFORMATION_SCHEMA, using getSchema to read the schema name and a case-insensitive comparison.
  • Configure H2Connection to use H2MetadataHandler via DatabaseConfig.PROPERTY_METADATA_HANDLER in its constructor.
  • Add H2MetadataHandlerTests using Mockito to mock DatabaseMetaData and ResultSet/ResultSetMetaData, asserting that INFORMATION_SCHEMA rows are removed and user tables preserved, that lower-case information_schema is also excluded, and that the underlying ResultSet is closed.
src/main/java/org/dbunit/ext/h2/H2Connection.java
src/main/java/org/dbunit/ext/h2/H2MetadataHandler.java
src/test/java/org/dbunit/ext/h2/H2MetadataHandlerTest.java
Adjust multi-schema H2 tests to use a delegating metadata handler spy instead of subclassing DefaultMetadataHandler, and ensure the H2 connection under test uses the new H2MetadataHandler.
  • Change DatabaseDataSet_MultiSchemaTest to construct TestMetadataHandler with a real H2MetadataHandler delegate rather than extending DefaultMetadataHandler.
  • Implement TestMetadataHandler as an IMetadataHandler wrapper that records schema names in getTables and delegates all IMetadataHandler methods to the provided delegate.
  • Update makeDatabaseConnection to pass the new TestMetadataHandler instance into the DatabaseConnection configuration.
  • Ensure the multi-schema H2 tests exercise the H2MetadataHandler rather than any vendor-agnostic default handler.
src/test/java/org/dbunit/database/DatabaseDataSet_MultiSchemaTest.java
Update integration tests and build configuration for H2 2.x and the new H2Connection behavior.
  • Modify DatabaseSequenceFilterIT to construct an H2Connection instead of a generic DatabaseConnection for H2 multi-schema foreign-key ordering tests, so the new metadata handler and datatype factory are used.
  • Bump the h2DriverVersion property in pom.xml from 1.4.200 to 2.4.240 to run tests and consumers against H2 2.x.
src/test/java/org/dbunit/database/DatabaseSequenceFilterIT.java
pom.xml
Document the new metadata handler, the in-memory metadata result set helper, and testing conventions for metadata handlers.
  • Add changes.xml entries describing the H2 2.x INFORMATION_SCHEMA behavior change, the introduction of H2MetadataHandler, and the extraction/generalization of InMemoryMetadataResultSet with merge and filter factories.
  • Create the IMetadataHandler core components page describing the interface, its built-in implementations (including H2MetadataHandler and MultiSchemaMySqlMetadataHandler), and guidance on custom handlers using InMemoryMetadataResultSet.
  • Add or update documentation pages (components.adoc, databases.adoc, databases/h2.adoc, properties.adoc) to mention H2MetadataHandler, cross-reference the new IMetadataHandler page, and document the metadataHandler property including MultiSchemaMySqlMetadataHandler.
  • Introduce a Test Conventions section (codingstandards/testconventions.adoc) that recommends delegating wrappers over subclassing concrete vendor handlers for test doubles, using TestMetadataHandler as the example.
  • Expose the IMetadataHandler page in the site navigation via site.xml.
src/changes/changes.xml
src/site/site.xml
src/site/asciidoc/components/imetadatahandler.adoc
src/site/asciidoc/components.adoc
src/site/asciidoc/databases.adoc
src/site/asciidoc/databases/h2.adoc
src/site/asciidoc/properties.adoc
src/site/asciidoc/codingstandards/testconventions.adoc

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@jeffjensen jeffjensen linked an issue Aug 9, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jeffjensen, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 8 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 76db79d6-7313-4413-9cec-39ea8265c27a

📥 Commits

Reviewing files that changed from the base of the PR and between 14af640 and 977e44f.

📒 Files selected for processing (4)
  • src/main/java/org/dbunit/database/InMemoryMetadataResultSet.java
  • src/main/java/org/dbunit/ext/h2/H2Connection.java
  • src/test/java/org/dbunit/database/InMemoryMetadataResultSetTest.java
  • src/test/java/org/dbunit/ext/h2/H2MetadataHandlerTest.java
📝 Walkthrough

Walkthrough

The PR upgrades H2, adds H2-specific metadata filtering for INFORMATION_SCHEMA, extracts a shared InMemoryMetadataResultSet, updates H2 and multi-schema integration, and documents the metadata-handler APIs and configuration.

Changes

H2 metadata compatibility

Layer / File(s) Summary
Shared metadata support
src/main/java/org/dbunit/database/InMemoryMetadataResultSet.java, src/main/java/org/dbunit/ext/mysql/MultiSchemaMySqlMetadataHandler.java, src/site/asciidoc/components/*, src/site/asciidoc/codingstandards/testconventions.adoc, src/site/asciidoc/properties.adoc, src/site/site.xml
Adds the shared in-memory result-set proxy for merging and filtering rows. The MySQL metadata handler reuses it. Documentation covers metadata handlers, result-set operations, registration, and delegating test doubles.
H2 handler and connection wiring
pom.xml, src/main/java/org/dbunit/ext/h2/H2MetadataHandler.java, src/main/java/org/dbunit/ext/h2/H2Connection.java, src/site/asciidoc/databases.adoc, src/site/asciidoc/databases/h2.adoc, src/changes/changes.xml
Upgrades H2 to 2.4.240. Adds H2MetadataHandler to exclude INFORMATION_SCHEMA rows and registers it in H2Connection. Updates H2 documentation and the changelog.
Metadata integration validation
src/test/java/org/dbunit/database/DatabaseDataSet_MultiSchemaTest.java, src/test/java/org/dbunit/database/DatabaseSequenceFilterIT.java, src/test/java/org/dbunit/ext/h2/H2MetadataHandlerTest.java
Updates multi-schema tests to delegate through IMetadataHandler and use H2Connection. Adds tests for case-insensitive filtering, user-table retention, empty results, and source-result-set closure.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: preventing the H2 INFORMATION_SCHEMA metadata leak.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 923-h2-information-schema-leak

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • Consider marking InMemoryMetadataResultSet.RowFilter as a @FunctionalInterface to make its intended use with lambdas clearer and catch accidental signature changes at compile time.
  • In H2MetadataHandler.getTables, the INFORMATION_SCHEMA filtering currently relies on DefaultMetadataHandler#getSchema; if H2’s metadata shape ever diverges, a more direct check against TABLE_SCHEM via column index/label in the RowFilter would be more robust.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider marking InMemoryMetadataResultSet.RowFilter as a @FunctionalInterface to make its intended use with lambdas clearer and catch accidental signature changes at compile time.
- In H2MetadataHandler.getTables, the INFORMATION_SCHEMA filtering currently relies on DefaultMetadataHandler#getSchema; if H2’s metadata shape ever diverges, a more direct check against TABLE_SCHEM via column index/label in the RowFilter would be more robust.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/main/java/org/dbunit/database/InMemoryMetadataResultSet.java`:
- Around line 163-175: Update closeAll to attempt SQLHelper.close for every
ResultSet even when a close fails, recording the first SQLException and
continuing through the remaining sources, then rethrowing that first failure
after the loop completes. Preserve the existing null/already-closed-safe
behavior and ensure the copy finally block does not lose the original exception
when cleanup also fails.

In `@src/main/java/org/dbunit/ext/h2/H2Connection.java`:
- Around line 52-53: Update the constructor JavaDoc associated with H2Connection
to document that its initialization configures both H2DataTypeFactory and
H2MetadataHandler, while preserving the existing description of the data type
factory.

In `@src/test/java/org/dbunit/ext/h2/H2MetadataHandlerTest.java`:
- Line 103: Rename the test method testGetTables_closesTheUnderlyingResultSet to
include the relevant starting state, while preserving its existing assertion
that getTables closes the underlying result set.
- Line 84: Update the assertion in H2MetadataHandlerTest by adding an AssertJ
.as() failure description before the existing isEqualTo("foo") call; ensure the
message clearly identifies the assertion and ends with a period.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f460a926-2333-4382-9d75-309717173511

📥 Commits

Reviewing files that changed from the base of the PR and between c1236eb and 14af640.

📒 Files selected for processing (16)
  • pom.xml
  • src/changes/changes.xml
  • src/main/java/org/dbunit/database/InMemoryMetadataResultSet.java
  • src/main/java/org/dbunit/ext/h2/H2Connection.java
  • src/main/java/org/dbunit/ext/h2/H2MetadataHandler.java
  • src/main/java/org/dbunit/ext/mysql/MultiSchemaMySqlMetadataHandler.java
  • src/site/asciidoc/codingstandards/testconventions.adoc
  • src/site/asciidoc/components.adoc
  • src/site/asciidoc/components/imetadatahandler.adoc
  • src/site/asciidoc/databases.adoc
  • src/site/asciidoc/databases/h2.adoc
  • src/site/asciidoc/properties.adoc
  • src/site/site.xml
  • src/test/java/org/dbunit/database/DatabaseDataSet_MultiSchemaTest.java
  • src/test/java/org/dbunit/database/DatabaseSequenceFilterIT.java
  • src/test/java/org/dbunit/ext/h2/H2MetadataHandlerTest.java

Comment thread src/main/java/org/dbunit/database/InMemoryMetadataResultSet.java
Comment thread src/main/java/org/dbunit/ext/h2/H2Connection.java
Comment thread src/test/java/org/dbunit/ext/h2/H2MetadataHandlerTest.java Outdated
Comment thread src/test/java/org/dbunit/ext/h2/H2MetadataHandlerTest.java Outdated
jeffjensen added a commit that referenced this pull request Aug 9, 2026
* InMemoryMetadataResultSet#closeAll() aborted on the first ResultSet
  that failed to close, leaking every source after it. Track the first
  failure, attempt every source's close, then rethrow it. Add
  InMemoryMetadataResultSetTest covering it directly.
* Mark RowFilter @FunctionalInterface.
* Add Javadoc to invoke(), and to H2Connection's constructor, which now
  also configures H2MetadataHandler, not just H2DataTypeFactory.
* H2MetadataHandlerTest: add a missing assertion .as() message, and the
  missing starting-state segment to a test method name.

Addresses CodeRabbit/Sourcery feedback on PR #924.

Refs: 923
@jeffjensen

Copy link
Copy Markdown
Member Author

Addressing Sourcery's review feedback:

  • RowFilter is now @FunctionalInterface (53601d7).
  • Declining the suggestion to check TABLE_SCHEM directly instead of going through getSchema(ResultSet) in H2MetadataHandler's filter: getSchema() already is that direct check — DefaultMetadataHandler#getSchema does resultSet.getString(2), and column 2 is TABLE_SCHEM per DatabaseMetaData#getTables()'s documented contract. It's just named instead of inlined as a bare column index. Going through the (overridable) method rather than hardcoding the index in the lambda is also what lets a future override of getSchema() — the way MySqlMetadataHandler already overrides it for its catalog/schema swap — correctly affect this filter too. Inlining the index would be a step backward, not forward.

Bump h2DriverVersion from 1.4.200 to 2.4.240 and adjust issues caused
by it.

* H2 2.x rewrote INFORMATION_SCHEMA to be SQL-standard-compliant, and
  15 of its tables now report JDBC TABLE_TYPE = "BASE TABLE" instead
  of the "SYSTEM TABLE" type H2 1.x used.
  DatabaseConfig#PROPERTY_TABLE_TYPE defaults to {"TABLE"}, so those
  tables now pass dbunit's default system-table filter and leak into
  DatabaseDataSet's table listing whenever a query is not scoped to a
  single schema (schema is null, e.g. an admin/multi-schema
  connection).
* Add H2MetadataHandler, wired into H2Connection, whose getTables()
  excludes the INFORMATION_SCHEMA schema. It builds the filtered
  result via InMemoryMetadataResultSet#filter(ResultSet, RowFilter),
  a new factory alongside the existing merge() one.
* Update DatabaseDataSet_MultiSchemaTest and DatabaseSequenceFilterIT,
  both of which hit the same leak, to exercise/use H2MetadataHandler.
* Fix InMemoryMetadataResultSet#closeAll(), it aborted on the first
  ResultSet that failed to close, leaking every source after it.
  Track the first failure, attempt every source's close, then
  rethrow it. Add InMemoryMetadataResultSetTest covering it directly.

Refs: 923
* Add components/imetadatahandler.adoc: the interface's method groups, a
  built-in-implementations table (DefaultMetadataHandler,
  Db2/MySql/MultiSchemaMySql/Netezza/H2MetadataHandler), and
  InMemoryMetadataResultSet's two factories (merge() for combining several
  real result sets, filter() for dropping rows out of one), with guidance
  on writing a custom handler. Cross-referenced from components.adoc,
  properties.adoc's metadataHandler entry, databases/h2.adoc, and
  site.xml's Core Components nav.
* Update databases.adoc and databases/h2.adoc's IMetadataHandler/Connection
  Preconfiguration Class/Known Quirks sections for H2MetadataHandler.
* Add the previously-undocumented MultiSchemaMySqlMetadataHandler to
  properties.adoc's metadataHandler entry alongside H2MetadataHandler.
* Add a Test Conventions section (codingstandards/testconventions.adoc) on
  wrapping a delegate instead of subclassing a concrete vendor handler for
  test doubles, using DatabaseDataSet_MultiSchemaTest's TestMetadataHandler
  as the worked example.
* Re-type changes.xml's existing 923 entry from fix to add, matching the
  GitHub issue's Bug-to-Feature retype, and add a second 923 entry for
  this documentation.

Refs: 923
@jeffjensen
jeffjensen force-pushed the 923-h2-information-schema-leak branch from 53601d7 to 977e44f Compare August 9, 2026 15:52
@jeffjensen
jeffjensen merged commit fedec4e into main Aug 9, 2026
29 checks passed
@jeffjensen
jeffjensen deleted the 923-h2-information-schema-leak branch August 9, 2026 16:10
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.

H2 2.x INFORMATION_SCHEMA tables leak into unscoped table listings

1 participant