Skip to content

refactor(platform): Extract a per-engine CatalogDialect#9

Merged
jeffjensen merged 6 commits into
mainfrom
refactor/extract-catalog-dialect
Jul 4, 2026
Merged

refactor(platform): Extract a per-engine CatalogDialect#9
jeffjensen merged 6 commits into
mainfrom
refactor/extract-catalog-dialect

Conversation

@jeffjensen

@jeffjensen jeffjensen commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Extracts the catalog audits' per-engine SQL into a CatalogDialect held by each DatabasePlatform constant, so adding a database engine no longer means editing an exhaustive switch in five classes. Scaling-plan WS1; behavior-preserving.

  • CatalogDialect: abstract methods for the SQL that genuinely diverges between engines (indexCatalogSql, foreignKeysSql, foreignKeyColumnTypesSql) — a new dialect won't compile until it supplies all three, keeping the exhaustive-switch completeness guarantee — and default methods for the standard information_schema SQL every engine shares (tablesWithoutPrimaryKeySql, nullableForeignKeyColumnSql).
  • PostgresqlCatalogDialect, MysqlCatalogDialect, H2CatalogDialect; MARIADB reuses MysqlCatalogDialect. DatabasePlatform holds one dialect per constant and exposes catalogDialect().
  • IndexCatalog and the four catalog audits drop their *_SQL constants + sql() switches for platform.catalogDialect().…() calls. The audits still take a DatabasePlatform, so callers (including the spring-boot DatabaseAuditSuite) are unchanged; QueryPlanExplainer's PostgreSQL-only guard is untouched.
  • Added CatalogDialectTest; extended DatabasePlatformTest to assert each constant's dialect type.

The SQL text moved verbatim: every existing catalog audit / IndexCatalog test passes unchanged, and CatalogAuditsIT is green on all four engines (mvnw clean install).

🤖 Generated with Claude Code

https://claude.ai/code/session_0141skitWw3Cdgkf2kP3vve6

Summary by CodeRabbit

  • New Features

    • Added a shared catalog SQL abstraction that enables consistent primary key, foreign key, and index audits across PostgreSQL, MySQL, MariaDB, and H2.
  • Refactor

    • Updated catalog-based audits to generate their SQL via the selected database’s dialect, centralizing engine-specific behavior.
  • Bug Fixes

    • Improved detection of DECIMAL precision/scale mismatches for foreign key type checks on H2.
  • Tests

    • Added unit tests for dialect SQL generation and integration tests for H2 DECIMAL behavior.
  • Documentation

    • Added “Adding a Database” and “Adding an Audit” guides and updated the architecture overview/navigation.

@coderabbitai

coderabbitai Bot commented Jul 3, 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: 58 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2a58d970-7b38-4481-aa58-ce41e7392840

📥 Commits

Reviewing files that changed from the base of the PR and between b908f1b and e374cd4.

📒 Files selected for processing (7)
  • pom.xml
  • src/main/java/io/github/databaseaudits/audit/runtime/plan/CapturedSqlPlanAuditTemplate.java
  • src/main/java/io/github/databaseaudits/audit/runtime/plan/JoinIndexAudit.java
  • src/main/java/io/github/databaseaudits/audit/runtime/plan/OrderByIndexAudit.java
  • src/main/java/io/github/databaseaudits/audit/runtime/plan/PlanJson.java
  • src/main/java/io/github/databaseaudits/audit/runtime/plan/WhereClauseIndexAudit.java
  • src/site/asciidoc/audits.adoc
📝 Walkthrough

Walkthrough

Introduces a CatalogDialect interface with PostgreSQL, MySQL, and H2 implementations, wires each into DatabasePlatform, and updates catalog audits and IndexCatalog to delegate SQL generation through the platform dialect. Documentation and tests were expanded for the new dialect model.

Changes

CatalogDialect refactor

Layer / File(s) Summary
CatalogDialect contract
src/main/java/io/github/databaseaudits/platform/CatalogDialect.java
New interface with abstract per-engine SQL methods and default shared information_schema methods.
Dialect implementations
src/main/java/io/github/databaseaudits/platform/PostgresqlCatalogDialect.java, .../MysqlCatalogDialect.java, .../H2CatalogDialect.java
Implements engine-specific catalog SQL for PostgreSQL, MySQL, and H2.
DatabasePlatform wiring
src/main/java/io/github/databaseaudits/platform/DatabasePlatform.java, src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java
Enum constants now carry a CatalogDialect, exposed via catalogDialect(), with a test covering the mapped dialect types.
Audit and catalog delegation
src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyIndexAudit.java, .../ForeignKeyNotNullAudit.java, .../ForeignKeyTypeMatchAudit.java, .../PrimaryKeyPresenceAudit.java, src/main/java/io/github/databaseaudits/catalog/IndexCatalog.java
Removes local SQL constants and platform switches; SQL methods now delegate to platform.catalogDialect().
Docs and SQL verification
src/site/asciidoc/architecture.adoc, src/site/asciidoc/adding-a-database.adoc, src/site/asciidoc/adding-an-audit.adoc, src/site/site.xml, src/test/java/io/github/databaseaudits/platform/CatalogDialectTest.java, src/test/java/io/github/databaseaudits/platform/H2CatalogDialectIT.java
Updates architecture and onboarding docs, adds navigation links, and adds tests for dialect SQL generation and H2 decimal precision handling.

Estimated code review effort: 3 (Moderate) | ~30 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main refactor: extracting a per-engine CatalogDialect for platform-specific SQL generation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/extract-catalog-dialect

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.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Refactor: extract per-engine CatalogDialect for catalog audit SQL

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

• Introduce a CatalogDialect strategy to own per-engine catalog SQL.
• Wire a dialect into each DatabasePlatform constant and remove audit SQL switches.
• Add unit tests and docs to enforce dialect coverage and reuse.
Diagram

graph TD
  A["Catalog audits"] --> DP["DatabasePlatform"] --> CD["CatalogDialect"] --> PG["PostgreSQL dialect"] & MY["MySQL/MariaDB dialect"] & H2["H2 dialect"]
  IC["IndexCatalog"] --> DP
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Move SQL methods onto DatabasePlatform constants
  • ➕ Avoids extra classes (dialects) by overriding methods per enum constant
  • ➕ Keeps dispatch local to the enum without an additional interface type
  • ➖ Large SQL blocks bloat the enum and reduce readability
  • ➖ Harder to share behavior across platforms (e.g., MariaDB reusing MySQL) without additional indirection
2. Central SQL registry (Map) per query
  • ➕ Simple data-driven lookup; easy to see coverage in one place
  • ➕ Can keep SQL as constants without creating new types
  • ➖ Weaker compile-time guarantees unless carefully structured
  • ➖ Less discoverable API than platform.catalogDialect().() and easier to drift across multiple registries
3. Externalize SQL into resource files per engine
  • ➕ Keeps Java classes smaller; SQL can be edited without touching code structure
  • ➕ Potentially friendlier for DBAs reviewing SQL changes
  • ➖ Runtime resource loading adds failure modes and complicates tests
  • ➖ Still needs a dispatch mechanism and does not inherently improve compile-time coverage

Recommendation: The PR’s CatalogDialect strategy is a strong fit: it preserves the compile-time “new engine must provide SQL” guarantee (via abstract methods) while removing duplicated switch logic and enabling reuse (MariaDB→MySQL). Keeping shared information_schema SQL as defaults is a pragmatic way to reduce duplication without obscuring per-engine divergences.

Files changed (13) +474 / -296

Enhancement (4) +354 / -0
CatalogDialect.javaAdd CatalogDialect interface with abstract + default SQL methods +99/-0

Add CatalogDialect interface with abstract + default SQL methods

• Introduces a new strategy interface for catalog-audit SQL. Defines three abstract methods for engine-divergent queries and two default methods for shared information_schema queries, preserving compile-time coverage for new engines.

src/main/java/io/github/databaseaudits/platform/CatalogDialect.java

H2CatalogDialect.javaIntroduce H2CatalogDialect with H2 information_schema SQL +99/-0

Introduce H2CatalogDialect with H2 information_schema SQL

• Adds an H2-specific CatalogDialect implementation providing index, foreign key, and FK-column-type queries using H2’s information_schema layout.

src/main/java/io/github/databaseaudits/platform/H2CatalogDialect.java

MysqlCatalogDialect.javaIntroduce MysqlCatalogDialect reused by MySQL and MariaDB +76/-0

Introduce MysqlCatalogDialect reused by MySQL and MariaDB

• Adds a MySQL/MariaDB CatalogDialect implementation using information_schema.statistics and key_column_usage. Designed for reuse by MariaDB and future divergence via subclassing if needed.

src/main/java/io/github/databaseaudits/platform/MysqlCatalogDialect.java

PostgresqlCatalogDialect.javaIntroduce PostgresqlCatalogDialect backed by pg_catalog +80/-0

Introduce PostgresqlCatalogDialect backed by pg_catalog

• Adds a PostgreSQL CatalogDialect implementation using pg_catalog for indexes and foreign keys, including format_type rendering for declared column types.

src/main/java/io/github/databaseaudits/platform/PostgresqlCatalogDialect.java

Refactor (6) +32 / -286
ForeignKeyIndexAudit.javaDelegate foreign-key catalog SQL to CatalogDialect +1/-60

Delegate foreign-key catalog SQL to CatalogDialect

• Removes embedded per-platform foreign key SQL constants and the exhaustive switch. The audit now calls platform.catalogDialect().foreignKeysSql().

src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyIndexAudit.java

ForeignKeyNotNullAudit.javaUse shared dialect SQL for nullable FK columns query +1/-28

Use shared dialect SQL for nullable FK columns query

• Removes the duplicated information_schema SQL constant and the platform switch. The query is now provided by platform.catalogDialect().nullableForeignKeyColumnSql() (defaulted by the interface).

src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyNotNullAudit.java

ForeignKeyTypeMatchAudit.javaDelegate FK column type matching SQL to CatalogDialect +1/-100

Delegate FK column type matching SQL to CatalogDialect

• Deletes per-engine SQL constants and switch selection for FK column type pairing. Uses platform.catalogDialect().foreignKeyColumnTypesSql() for engine-specific implementations.

src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyTypeMatchAudit.java

PrimaryKeyPresenceAudit.javaUse shared dialect SQL for tables-without-PK query +1/-23

Use shared dialect SQL for tables-without-PK query

• Removes the duplicated information_schema SQL constant and platform switch. Uses platform.catalogDialect().tablesWithoutPrimaryKeySql() (default method) to keep shared SQL in one place.

src/main/java/io/github/databaseaudits/audit/catalog/PrimaryKeyPresenceAudit.java

IndexCatalog.javaReplace index catalog SQL switch with dialect call +1/-68

Replace index catalog SQL switch with dialect call

• Eliminates per-platform index SQL constants and the exhaustive switch. IndexCatalog.sql() now returns platform.catalogDialect().indexCatalogSql().

src/main/java/io/github/databaseaudits/catalog/IndexCatalog.java

DatabasePlatform.javaAttach a CatalogDialect instance to each DatabasePlatform constant +27/-7

Attach a CatalogDialect instance to each DatabasePlatform constant

• Updates enum constants to supply a CatalogDialect via a constructor and exposes catalogDialect(). This replaces the previous model where each audit carried exhaustive per-platform switches.

src/main/java/io/github/databaseaudits/platform/DatabasePlatform.java

Tests (2) +74 / -0
CatalogDialectTest.javaAdd unit tests asserting divergent and shared SQL behavior +61/-0

Add unit tests asserting divergent and shared SQL behavior

• Adds tests verifying each dialect’s divergent SQL references the expected catalog sources and that shared default SQL is identical across dialects.

src/test/java/io/github/databaseaudits/platform/CatalogDialectTest.java

DatabasePlatformTest.javaAssert each DatabasePlatform constant exposes the expected dialect type +13/-0

Assert each DatabasePlatform constant exposes the expected dialect type

• Extends existing platform tests to validate the dialect instance type for POSTGRESQL, MYSQL, MARIADB (reusing MySQL), and H2.

src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java

Documentation (1) +14 / -10
architecture.adocDocument DatabasePlatform owning CatalogDialect instead of SQL switches +14/-10

Document DatabasePlatform owning CatalogDialect instead of SQL switches

• Updates the architecture documentation to describe the new CatalogDialect abstraction, the abstract/default split, and how adding an engine works under the new design.

src/site/asciidoc/architecture.adoc

@qodo-code-review

qodo-code-review Bot commented Jul 3, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Context used
✅ Compliance rules (platform): 22 rules

Grey Divider


Action required

1. Missing .as() in DatabasePlatformTest ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new AssertJ assertions in testCatalogDialect_EachPlatform_HoldsItsDialectType() omit
.as("...") descriptions, violating the test assertion description requirement. This reduces
diagnostic clarity when a test fails.
Code

src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java[R70-78]

+        assertThat(DatabasePlatform.POSTGRESQL.catalogDialect())
+                .isInstanceOf(PostgresqlCatalogDialect.class);
+        assertThat(DatabasePlatform.MYSQL.catalogDialect())
+                .isInstanceOf(MysqlCatalogDialect.class);
+        assertThat(DatabasePlatform.MARIADB.catalogDialect())
+                .as("MariaDB reuses the MySQL catalog dialect.")
+                .isInstanceOf(MysqlCatalogDialect.class);
+        assertThat(DatabasePlatform.H2.catalogDialect())
+                .isInstanceOf(H2CatalogDialect.class);
Evidence
PR Compliance ID 1493065 requires each AssertJ assertion chain to include an .as("...")
description ending with a period. In the newly added test method, several assertThat(...) chains
call .isInstanceOf(...) without any .as(...) description.

Rule 1493065: AssertJ assertions must include a .as() description ending with a period
src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java[70-78]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New AssertJ assertion chains were added without an `.as("...")` description (and the policy requires the description to be a non-empty string literal ending with a period).

## Issue Context
Rule requires every AssertJ `assertThat(...)` chain to include `.as("...")`/`.describedAs("...")` before the terminal assertion method, and the description literal must end with `.`.

## Fix Focus Areas
- src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java[70-78]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@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: 2

🧹 Nitpick comments (1)
src/main/java/io/github/databaseaudits/platform/DatabasePlatform.java (1)

45-45: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Two MysqlCatalogDialect instances for MariaDB/MySQL.

Since the dialect is stateless, consider sharing one instance between MARIADB and MYSQL instead of instantiating twice.

♻️ Suggested tweak
+    private static final MysqlCatalogDialect MYSQL_DIALECT = new MysqlCatalogDialect();
+
     ...
-    MARIADB(new MysqlCatalogDialect()),
+    MARIADB(MYSQL_DIALECT),
     ...
-    MYSQL(new MysqlCatalogDialect()),
+    MYSQL(MYSQL_DIALECT),

Also applies to: 48-48

🤖 Prompt for 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.

In `@src/main/java/io/github/databaseaudits/platform/DatabasePlatform.java` at
line 45, The DatabasePlatform enum currently creates two separate
MysqlCatalogDialect instances for MARIADB and MYSQL even though the dialect is
stateless. Update DatabasePlatform so both enum constants reuse a shared
MysqlCatalogDialect instance, and verify any constructor or field setup in
DatabasePlatform still exposes the same behavior for both MARIADB and MYSQL.
🤖 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/io/github/databaseaudits/platform/H2CatalogDialect.java`:
- Around line 64-98: The H2 type rendering in foreignKeyColumnTypesSql() only
uses data_type and character_maximum_length, so precision-sensitive numeric
types are flattened and mismatches can be missed. Update the SQL in
H2CatalogDialect.foreignKeyColumnTypesSql() to render numeric types with
numeric_precision and numeric_scale (while preserving existing length handling
for text types) for both column_type and referenced_type so
ForeignKeyTypeMatchAudit compares the full type signature.

In `@src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java`:
- Around line 68-79: The assertions in
DatabasePlatformTest.testCatalogDialect_EachPlatform_HoldsItsDialectType should
all include AssertJ .as() fail messages ending with a period, not just the
MariaDB check. Update the PostgreSQL, MYSQL, and H2 catalogDialect() assertions
to add clear descriptive .as() messages so each assertion has consistent failure
context.

---

Nitpick comments:
In `@src/main/java/io/github/databaseaudits/platform/DatabasePlatform.java`:
- Line 45: The DatabasePlatform enum currently creates two separate
MysqlCatalogDialect instances for MARIADB and MYSQL even though the dialect is
stateless. Update DatabasePlatform so both enum constants reuse a shared
MysqlCatalogDialect instance, and verify any constructor or field setup in
DatabasePlatform still exposes the same behavior for both MARIADB and MYSQL.
🪄 Autofix (Beta)

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b70c04d0-cb40-4d97-9f93-5aafc106aaf6

📥 Commits

Reviewing files that changed from the base of the PR and between 8b85bee and bcd5a54.

📒 Files selected for processing (13)
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyIndexAudit.java
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyNotNullAudit.java
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyTypeMatchAudit.java
  • src/main/java/io/github/databaseaudits/audit/catalog/PrimaryKeyPresenceAudit.java
  • src/main/java/io/github/databaseaudits/catalog/IndexCatalog.java
  • src/main/java/io/github/databaseaudits/platform/CatalogDialect.java
  • src/main/java/io/github/databaseaudits/platform/DatabasePlatform.java
  • src/main/java/io/github/databaseaudits/platform/H2CatalogDialect.java
  • src/main/java/io/github/databaseaudits/platform/MysqlCatalogDialect.java
  • src/main/java/io/github/databaseaudits/platform/PostgresqlCatalogDialect.java
  • src/site/asciidoc/architecture.adoc
  • src/test/java/io/github/databaseaudits/platform/CatalogDialectTest.java
  • src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java

Move the catalog audits' per-platform SQL out of exhaustive switches and *_SQL
constants scattered across IndexCatalog and the four catalog audits into a
CatalogDialect held by each DatabasePlatform constant. IndexCatalog and the audits
now ask platform.catalogDialect() for their SQL instead of switching on the platform.

* Add CatalogDialect: abstract methods for the SQL that genuinely diverges between
  engines (indexCatalogSql, foreignKeysSql, foreignKeyColumnTypesSql) — a new dialect
  will not compile until it supplies all three, preserving the exhaustive-switch
  completeness guarantee — and default methods for the standard information_schema SQL
  every engine shares (tablesWithoutPrimaryKeySql, nullableForeignKeyColumnSql).
* Add PostgresqlCatalogDialect, MysqlCatalogDialect, H2CatalogDialect; MARIADB reuses
  MysqlCatalogDialect. DatabasePlatform holds one dialect per constant and exposes
  catalogDialect().
* Replace the *_SQL constants + sql() switches in IndexCatalog, ForeignKeyIndexAudit,
  ForeignKeyTypeMatchAudit, ForeignKeyNotNullAudit, and PrimaryKeyPresenceAudit with
  platform.catalogDialect() calls. The audits still take a DatabasePlatform, so callers
  (including the spring-boot DatabaseAuditSuite) are unchanged; QueryPlanExplainer's
  PostgreSQL-only guard is untouched.
* Add CatalogDialectTest; extend DatabasePlatformTest to assert each constant's dialect
  type. The existing catalog audit and IndexCatalog tests pass unchanged (the SQL text
  is identical), and CatalogAuditsIT stays green on all four engines.
* Update the "add a platform" narrative in DatabasePlatform javadoc and architecture.adoc.

Completes WS1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0141skitWw3Cdgkf2kP3vve6
@jeffjensen jeffjensen force-pushed the refactor/extract-catalog-dialect branch from bcd5a54 to 49e1c2e Compare July 3, 2026 23:21

@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.

🧹 Nitpick comments (1)
src/test/java/io/github/databaseaudits/platform/H2CatalogDialectIT.java (1)

26-54: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

No exclusion-pass case in this IT.

Per path instructions, each audit IT should report the planted violation then pass once excluded, to guard against a vacuously green audit. This class only covers report/no-mismatch, not exclusion of the planted decimal mismatch. If exclusion behavior for ForeignKeyTypeMatchAudit is already fully exercised in CatalogAuditsIT, this narrower dialect-focused test may be an acceptable exception — please confirm.

As per path instructions, "Each audit must be verified against planted violations: REPORT the planted violation, then PASS once it is excluded — a vacuously green audit is a bug."

🤖 Prompt for 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.

In `@src/test/java/io/github/databaseaudits/platform/H2CatalogDialectIT.java`
around lines 26 - 54, Add an exclusion-pass assertion to H2CatalogDialectIT for
ForeignKeyTypeMatchAudit so the planted decimal mismatch is first reported and
then excluded; use the existing
testForeignKeyTypeMatchAudit_DecimalPrecisionMismatchOnH2_ReportsBothTypesWithPrecisionAndScale
setup with audit.audit("PUBLIC", Set.of(...)) to verify it becomes empty after
excluding the planted violation, while keeping the equal-type test intact.

Source: Path instructions

🤖 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.

Nitpick comments:
In `@src/test/java/io/github/databaseaudits/platform/H2CatalogDialectIT.java`:
- Around line 26-54: Add an exclusion-pass assertion to H2CatalogDialectIT for
ForeignKeyTypeMatchAudit so the planted decimal mismatch is first reported and
then excluded; use the existing
testForeignKeyTypeMatchAudit_DecimalPrecisionMismatchOnH2_ReportsBothTypesWithPrecisionAndScale
setup with audit.audit("PUBLIC", Set.of(...)) to verify it becomes empty after
excluding the planted violation, while keeping the equal-type test intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: f7697c85-6d6e-4de3-b949-a07c821cb3ac

📥 Commits

Reviewing files that changed from the base of the PR and between bcd5a54 and b908f1b.

📒 Files selected for processing (17)
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyIndexAudit.java
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyNotNullAudit.java
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyTypeMatchAudit.java
  • src/main/java/io/github/databaseaudits/audit/catalog/PrimaryKeyPresenceAudit.java
  • src/main/java/io/github/databaseaudits/catalog/IndexCatalog.java
  • src/main/java/io/github/databaseaudits/platform/CatalogDialect.java
  • src/main/java/io/github/databaseaudits/platform/DatabasePlatform.java
  • src/main/java/io/github/databaseaudits/platform/H2CatalogDialect.java
  • src/main/java/io/github/databaseaudits/platform/MysqlCatalogDialect.java
  • src/main/java/io/github/databaseaudits/platform/PostgresqlCatalogDialect.java
  • src/site/asciidoc/adding-a-database.adoc
  • src/site/asciidoc/adding-an-audit.adoc
  • src/site/asciidoc/architecture.adoc
  • src/site/site.xml
  • src/test/java/io/github/databaseaudits/platform/CatalogDialectTest.java
  • src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java
  • src/test/java/io/github/databaseaudits/platform/H2CatalogDialectIT.java
✅ Files skipped from review due to trivial changes (2)
  • src/site/asciidoc/architecture.adoc
  • src/site/asciidoc/adding-an-audit.adoc
🚧 Files skipped from review as they are similar to previous changes (12)
  • src/test/java/io/github/databaseaudits/platform/CatalogDialectTest.java
  • src/main/java/io/github/databaseaudits/platform/CatalogDialect.java
  • src/main/java/io/github/databaseaudits/platform/PostgresqlCatalogDialect.java
  • src/main/java/io/github/databaseaudits/platform/H2CatalogDialect.java
  • src/test/java/io/github/databaseaudits/platform/DatabasePlatformTest.java
  • src/main/java/io/github/databaseaudits/platform/MysqlCatalogDialect.java
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyNotNullAudit.java
  • src/main/java/io/github/databaseaudits/catalog/IndexCatalog.java
  • src/main/java/io/github/databaseaudits/audit/catalog/PrimaryKeyPresenceAudit.java
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyIndexAudit.java
  • src/main/java/io/github/databaseaudits/platform/DatabasePlatform.java
  • src/main/java/io/github/databaseaudits/audit/catalog/ForeignKeyTypeMatchAudit.java

jeffjensen and others added 4 commits July 4, 2026 09:08
The asciidoctor-parser doxia module drops inline NOTE/TIP/WARNING bodies (it
logs "Fallback behaviour for node: admonition"), so the text never reached the
rendered site. Convert the ForeignKeyIndex note to a bold "*Note:*" lead-in
paragraph — matching the extending guides — so the content shows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UEuiBscyCyDrtzszMwiAo8
The plan-based audits matched PostgreSQL EXPLAIN field names ("Node Type",
"Relation Name", "Plans", …) and node-type values ("Seq Scan", "Sort",
"Nested Loop", …) as repeated string literals across the three audits and their
shared template. Extract them into a package-private PlanJson holder so the
production detection logic carries no duplicated magic strings.

The audit unit tests build their fixture plans as literal JSON text, where a
Java constant cannot sit inside a JSON string literal, so they are intentionally
left unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UEuiBscyCyDrtzszMwiAo8
@jeffjensen jeffjensen merged commit 61594e0 into main Jul 4, 2026
5 checks passed
@jeffjensen jeffjensen deleted the refactor/extract-catalog-dialect branch July 4, 2026 19:20
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.

1 participant