Skip to content

Fix second batch of code-review findings: build, loader, deploy, pull, ddl#54

Merged
gmr merged 12 commits into
mainfrom
fix/review-findings-batch2
Jul 7, 2026
Merged

Fix second batch of code-review findings: build, loader, deploy, pull, ddl#54
gmr merged 12 commits into
mainfrom
fix/review-findings-batch2

Conversation

@gmr

@gmr gmr commented Jul 7, 2026

Copy link
Copy Markdown
Owner

Summary

Second batch of fixes from the 2026-07-06 code review, following #53.
Covers the correctness follow-ups deferred from the first PR: build-side
rendering of newly-captured table structure, loader safety, deploy drop
ordering, role comments on pull, and DDL COMMENT/identifier handling.
Work was split across isolated worktrees by disjoint file ownership,
integrated, and validated (just check + just gates).

Problem

  • N-L2: build declared but never rendered from_type (typed
    tables), partitions (child partitions), or index_tablespace, so
    hand-authored or freshly-pulled values silently vanished from the
    archive and then produced unreconcilable deploy diffs.
  • M6/L7/L10/L8: the loader accepted duplicate objects silently
    (emitting them twice), dropped cast dependencies: edges, aborted the
    whole load on a single missing name, and rejected several object
    types as dependency targets.
  • L5: removed functions with named parameters missed the
    topologically-ordered drop pass (archive TOC tag omits parameter
    names) and fell to an unordered append.
  • N-M2: COMMENT ON ROLE from pg_dumpall was dropped on pull with
    a spurious "unexpected statement" warning.
  • L2/L3: COMMENT ON TRIGGER trg ON tbl lost the trigger name;
    unhandled COMMENT targets were silently empty; unquoted identifiers
    were not case-folded to lowercase as PostgreSQL does.

Solution

  • build (src/build/mod.rs): render typed tables
    (CREATE TABLE ... OF type, columns via WITH OPTIONS), child
    partitions (PARTITION OF ... FOR VALUES ... / DEFAULT), and
    USING INDEX TABLESPACE on PK/unique constraints.
  • loader (src/project/load.rs, src/constants.rs): error on
    duplicate (desc, schema, name) naming both files; compute cast
    dependency tags as (src AS tgt); skip a nameless entry instead of
    aborting; map the previously-missing plural dependency keys.
  • deploy (src/deploy/mod.rs, diff.rs): match removed functions
    in the ordered drop pass via a type-only tag key; function_key_name
    and its callers are untouched.
  • pull (src/pull/mod.rs, writer.rs): capture COMMENT ON ROLE
    into role/user YAML.
  • ddl (src/ddl/object.rs, mod.rs): preserve both names in
    two-name COMMENT forms, warn on unhandled targets, and case-fold
    unquoted identifiers (quoted kept verbatim; PUBLIC preserved).

Each fix ships with unit tests.

Verification

  • just check — fmt, clippy -D warnings, full test suite: green.
  • just gates — round-trip diff empty; deploy equivalence + convergence
    empty; safety gate excludes drops without --allow-drop.

Notes / remaining follow-ups

  • L8 is dormant: schemata/dependencies.yml has
    additionalProperties: false and whitelists only 9 dependency keys,
    so the newly-mapped types can't be exercised through real YAML until
    that schema is widened (a separate change).
  • Still open from the review: L1 ($$-quoting collision-safety), L6
    (--log-file disables progress bars), L9 (overload filename
    counter), efficiency E1–E4, and duplication D1–D3.

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Summary by CodeRabbit

  • New Features

    • Enhanced SQL table export with better support for typed tables, table constraints, and partition rendering (including MINVALUE/MAXVALUE).
    • Role and user exports now preserve COMMENT ON ROLE content from dumps.
  • Bug Fixes

    • Improved parsing of COMMENT ON ... for triggers, rules, policies, and constraints, including edge cases.
    • Corrected identifier and PUBLIC role normalization, and improved deploy matching/order for removed functions.
  • Chores

    • Expanded project loading support (more recognized keys, duplicate detection, cast dependency caching, and improved path tracking).

gmr and others added 11 commits July 7, 2026 11:45
apply_role_statement had no arm for Statement::Comment, so
COMMENT ON ROLE emitted by pg_dumpall fell through to the
unexpected-statement branch, logged a spurious warning, and was
lost. Add a comment field to RoleState, populate it from the
matched COMMENT ON ROLE statement, and wire it through to both
the Role and User models on write (they already had a comment
field, always written None).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The removed-object drop pass in deploy keyed archive TOC entries by
their literal tag (entry_key), which pg_dump renders as parameter
types only. ObjectKey's function identity (function_key_name)
includes parameter names when present, so a removed function with a
named parameter never matched an archive entry and fell into the
unordered fallback loop instead of the dependency-ordered drop pass.

Add diff::function_tag_name, a type-only signature in the same shape
as the archive tag, and use it (via drop_match_key) only when matching
removed objects against snapshot entries for ordering. function_key_name
itself is untouched, so its other callers (identity/ACL matching) are
unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
missing-name aborts, and unsupported dependency types

- add_definition now rejects a second object with the same
  (desc, schema, name) as an error naming both file paths, instead of
  silently keeping the duplicate and letting build emit it twice
- cache_and_remove_dependencies computes a cast's identity tag the
  same way Definition::name() does, so a cast's dependencies: block
  resolves instead of being dropped with a "missing" warning
- a definition missing name now increments the error count and skips
  just that entry instead of aborting the rest of the load via `?`
- from_plural_key gains the plural keys for aggregates, collations,
  event_triggers, materialized_views, publications, servers,
  subscriptions, users, and user_mappings, so dependencies: blocks
  naming those types are recognized rather than failing the load

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
These three Table fields were declared but never rendered, so a
hand-authored or pulled value for a typed table (CREATE TABLE OF
type), a partitioned table's child partitions, or a PK/UNIQUE index
tablespace silently vanished from the build archive, producing an
unreconcilable deploy diff (deploy::alter::table already treats all
three as rebuild-triggering, but the rebuilt DDL dropped them).

- from_type renders CREATE TABLE ... OF type, with column entries
  reduced to their WITH OPTIONS constraints per the typed-table
  grammar (no explicit data type).
- partitions renders each child as its own archive entry:
  CREATE TABLE child PARTITION OF parent FOR VALUES ... / DEFAULT,
  depending on the parent's dump id.
- index_tablespace renders USING INDEX TABLESPACE on the PRIMARY KEY
  constraint (or every UNIQUE constraint when there is no primary
  key, since the model holds one table-wide value).

Added inline unit tests for each of the three renders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- COMMENT ON forms with two names (TRIGGER/RULE/POLICY ... ON ...,
  CONSTRAINT ... ON [DOMAIN] ...) previously had the first name
  overwritten by the second; both are now preserved, using the same
  schema/name convention as COLUMN comments (schema holds the
  relation, name holds the trigger/rule/policy/constraint name).
- Unmatched COMMENT targets (e.g. LARGE OBJECT) now log a warning
  instead of silently producing an empty target.
- unquote() now folds unquoted identifiers to lowercase, matching
  PostgreSQL's identifier folding rules; quoted identifiers are
  unaffected. PUBLIC is special-cased to stay uppercase since it's a
  keyword denoting the pseudo-role rather than a folded identifier
  (mirrors utils::user_mapping_subject's existing handling).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 67044223-89a0-4f64-b4f2-f7d5c9c56381

📥 Commits

Reviewing files that changed from the base of the PR and between d8d2f1d and c0a51e2.

📒 Files selected for processing (5)
  • src/build/mod.rs
  • src/constants.rs
  • src/ddl/acl.rs
  • src/ddl/foreign.rs
  • src/ddl/mod.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/constants.rs
  • src/build/mod.rs

📝 Walkthrough

Walkthrough

The PR updates TABLE SQL rendering for typed tables and partitions, adjusts identifier unquoting and COMMENT ON parsing, changes deploy drop matching for functions, expands loader path/duplicate tracking, and persists role comments through pull and write paths.

Changes

Table, DDL, deploy, load, and pull updates

Layer / File(s) Summary
Typed and non-typed table rendering
src/build/mod.rs
dump_table now renders typed tables with OF type, shared constraint helpers, and updated non-typed column/constraint assembly.
Partition rendering
src/build/mod.rs
dump_partition emits PARTITION OF statements with partition clauses, bounds, and parent dependencies.
Table test helpers and coverage
src/build/mod.rs
Table test helpers were rewritten and coverage was expanded for constraints, comments, typed tables, tablespaces, and partitions.
Identifier case-folding
src/ddl/mod.rs
unquote lowercases unquoted identifiers, and unquote_role preserves PUBLIC as uppercase.
COMMENT ON target parsing
src/ddl/object.rs
COMMENT ON parsing now handles two-name targets for trigger, rule, policy, and constraint forms.
Function tag remapping
src/deploy/diff.rs, src/deploy/mod.rs
Function drop matching now uses a type-only tag key and remaps removed-object lookup keys during planning.
Plural key mapping
src/constants.rs
from_plural_key recognizes additional plural object keys and the underscore form for foreign data wrappers.
Loader path plumbing
src/project/load.rs
Loaded items now keep source paths, and file paths are threaded through project and container loading into add_definition.
Duplicate checks and cast tags
src/project/load.rs
Duplicate definitions are rejected with path-aware diagnostics, and cast dependency tags are derived from source and target types.
Role comment handling
src/pull/mod.rs, src/pull/writer.rs
Role comments are captured from COMMENT ON ROLE and written back into generated YAML for users and roles.

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

Possibly related PRs

🚥 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 PR as a follow-up fix across build, loader, deploy, pull, and DDL areas.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/review-findings-batch2

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

@gmr

gmr commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🧹 Nitpick comments (4)
src/pull/mod.rs (1)

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

Missing doc comment on new comment field.

Sibling fields like created and options carry doc comments explaining their semantics; comment has none. Minor consistency nit only.

🤖 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/pull/mod.rs` at line 282, The new comment field in the pull request model
is missing the same style of documentation as sibling fields like created and
options. Add a doc comment directly on the comment field in the Pull struct so
its meaning is clear and the field matches the surrounding API documentation
style.
src/ddl/object.rs (1)

318-329: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover the remaining two-name COMMENT forms.

The new state handles RULE and CONSTRAINT too, including CONSTRAINT ... ON DOMAIN ..., but tests only exercise TRIGGER and POLICY. Add targeted cases so the pending_first_name/in_target behavior stays locked down.

Suggested test coverage
     fn parses_policy_comment_preserves_both_names() {
         let Statement::Comment { on, target, .. } =
             parse_one("COMMENT ON POLICY pol ON tbl IS 'x';")
         else {
             panic!("expected Comment")
@@
         assert_eq!(target.schema.as_deref(), Some("tbl"));
         assert_eq!(target.name, "pol");
     }
+
+    #[test]
+    fn parses_rule_comment_preserves_both_names() {
+        let Statement::Comment { on, target, .. } =
+            parse_one("COMMENT ON RULE rul ON tbl IS 'x';")
+        else {
+            panic!("expected Comment")
+        };
+        assert_eq!(on, "RULE");
+        assert_eq!(target.schema.as_deref(), Some("tbl"));
+        assert_eq!(target.name, "rul");
+    }
+
+    #[test]
+    fn parses_constraint_comment_preserves_both_names() {
+        let Statement::Comment { on, target, .. } =
+            parse_one("COMMENT ON CONSTRAINT chk ON tbl IS 'x';")
+        else {
+            panic!("expected Comment")
+        };
+        assert_eq!(on, "CONSTRAINT");
+        assert_eq!(target.schema.as_deref(), Some("tbl"));
+        assert_eq!(target.name, "chk");
+    }
+
+    #[test]
+    fn parses_domain_constraint_comment() {
+        let Statement::Comment { on, target, .. } =
+            parse_one("COMMENT ON CONSTRAINT chk ON DOMAIN dom IS 'x';")
+        else {
+            panic!("expected Comment")
+        };
+        assert_eq!(on, "CONSTRAINT");
+        assert_eq!(target.schema.as_deref(), Some("dom"));
+        assert_eq!(target.name, "chk");
+    }

Also applies to: 545-571

🤖 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/ddl/object.rs` around lines 318 - 329, Add targeted test coverage for the
remaining two-name COMMENT ON forms in the object parsing logic so the new
pending_first_name/in_target behavior stays fixed for RULE and CONSTRAINT,
including the CONSTRAINT ... ON DOMAIN ... case. Extend the existing tests
around the object-name parsing path in src/ddl/object.rs to assert that the
leading name is preserved and the following node correctly qualifies it for
these forms, not just TRIGGER and POLICY.
src/project/load.rs (2)

27-29: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚖️ Poor tradeoff

Parallel paths vector can silently desync from project.inventory.

paths is only kept aligned with inventory inside add_definition (Lines 392-398). Anything that grows project.inventory outside that path breaks the 1:1 index correspondence with no runtime check to catch it. The new test cast_dependency_edge_resolves (Lines 564-575) does exactly this - it pushes an Item straight into loader.project.inventory, then add_definition (Line 587) appends to both vectors, leaving paths one index behind inventory for the rest of the test. It happens to be harmless here because the lookup at Lines 375-380 falls back to "<unknown>" for both None and out-of-range indices, but the underlying invariant is fragile and could misattribute a duplicate-diagnostic to the wrong file if this pattern is reused elsewhere.

Consider storing the path directly on Item (or on Definition) instead of a side-channel vector, or at minimum add a debug_assert_eq!(self.paths.len(), self.project.inventory.len()) after every mutation site to fail fast on desync.

🤖 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/project/load.rs` around lines 27 - 29, The `Loader`’s parallel `paths`
vector can drift out of sync with `project.inventory`, especially when items are
pushed directly in tests or other code paths outside `add_definition`. Fix this
by removing the side-channel state and storing the source path on `Item` or
`Definition`, or at minimum enforce the invariant in `Loader::add_definition`
and any other inventory mutation sites with a `debug_assert_eq!` against
`paths.len()` and `project.inventory.len()`. Use the existing `Loader`,
`project.inventory`, and `paths` symbols to locate all mutation points and keep
duplicate-diagnostic lookups reliable.

346-368: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Include path in the other two error branches of add_definition for consistent diagnostics.

path is now available and used for the duplicate-object diagnostic, but the to_definition failure and round-trip-mismatch failure logs still omit it, making it harder to locate the offending file for those errors.

♻️ Suggested fix
         let definition = match to_definition(ot, value.clone()) {
             Ok(definition) => definition,
             Err(error) => {
                 log::error!(
-                    "Failed to load {} definition: {error}",
-                    ot.as_str()
+                    "Failed to load {} definition from {}: {error}",
+                    ot.as_str(),
+                    path.map(|p| p.display().to_string())
+                        .unwrap_or_else(|| String::from("<unknown>")),
                 );
                 self.errors += 1;
                 return;
             }
         };
         let round_trip = serde_json::to_value(&definition)
             .expect("model serialization cannot fail");
         let normalized = strip_nulls(value);
         if round_trip != normalized {
             log::error!(
-                "{} {} did not round-trip: {normalized} != {round_trip}",
+                "{} {} ({}) did not round-trip: {normalized} != {round_trip}",
                 ot.as_str(),
                 definition.name(),
+                path.map(|p| p.display().to_string())
+                    .unwrap_or_else(|| String::from("<unknown>")),
             );
             self.errors += 1;
             return;
         }
🤖 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/project/load.rs` around lines 346 - 368, The error diagnostics in
add_definition are inconsistent because the to_definition failure and round-trip
mismatch logs do not include path, even though it is available in this scope.
Update both log::error! branches in add_definition to include path alongside the
existing object type and definition details, matching the duplicate-object
diagnostic style so the offending file can be identified easily.
🤖 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/build/mod.rs`:
- Around line 2260-2285: render_partition_for_values currently allows empty or
ambiguous bounds, which can emit invalid DDL. Update this function to validate
the TablePartition bound fields explicitly: return an error/panic or otherwise
fail fast when none of for_values_in, for_values_from/to, or for_values_with is
set, and also when more than one bound style is provided. Keep the existing
formatting logic for the valid cases, but make the ambiguity checks happen
before constructing the clause so callers cannot get a silently wrong result.
- Around line 2239-2242: The typed-table column CHECK rendering in the column
constraint assembly path should wrap the expression in parentheses so PostgreSQL
gets a valid CHECK clause. Update the logic in the constraint-building code that
handles column.check_constraint so the rendered output becomes CHECK (expr)
instead of CHECK expr, matching the table-level constraint formatting used
elsewhere in the build module.
- Around line 1251-1252: The partition emission loop in dump_table is allowing
child partitions to be generated even when the parent table is not partitioned.
Update the logic around the dump_partition call so it only runs for generated
parents that have an actual partitioning definition, checking the same parent
partition state used when emitting PARTITION BY, and skip or guard d.partitions
unless the parent is partitioned.

In `@src/constants.rs`:
- Around line 139-163: The dependency key used for foreign data wrappers is
inconsistent with the rest of the codebase, so `src/project/load.rs` will not
recognize it when reading `project.yaml`. Update the `Category` mapping in
`src/constants.rs` to use `foreign_data_wrappers` for
`Self::ForeignDataWrapper`, matching the underscore-separated naming used
elsewhere so FDW dependencies are parsed instead of skipped.

In `@src/ddl/mod.rs`:
- Around line 384-388: `unquote` in `src/ddl/mod.rs` is incorrectly
canonicalizing the identifier `public` to the pseudo-role literal `PUBLIC`,
which breaks callers that use it for object names like schema/table parsing.
Remove the `PUBLIC` special-case from `unquote` so it remains context-free and
preserves PostgreSQL-style folded identifiers, and move the pseudo-role
normalization into the role/ACL-specific caller(s) that need it, such as the
code paths around `utils::user_mapping_subject` and the other `PUBLIC` handling
referenced in the same module.

---

Nitpick comments:
In `@src/ddl/object.rs`:
- Around line 318-329: Add targeted test coverage for the remaining two-name
COMMENT ON forms in the object parsing logic so the new
pending_first_name/in_target behavior stays fixed for RULE and CONSTRAINT,
including the CONSTRAINT ... ON DOMAIN ... case. Extend the existing tests
around the object-name parsing path in src/ddl/object.rs to assert that the
leading name is preserved and the following node correctly qualifies it for
these forms, not just TRIGGER and POLICY.

In `@src/project/load.rs`:
- Around line 27-29: The `Loader`’s parallel `paths` vector can drift out of
sync with `project.inventory`, especially when items are pushed directly in
tests or other code paths outside `add_definition`. Fix this by removing the
side-channel state and storing the source path on `Item` or `Definition`, or at
minimum enforce the invariant in `Loader::add_definition` and any other
inventory mutation sites with a `debug_assert_eq!` against `paths.len()` and
`project.inventory.len()`. Use the existing `Loader`, `project.inventory`, and
`paths` symbols to locate all mutation points and keep duplicate-diagnostic
lookups reliable.
- Around line 346-368: The error diagnostics in add_definition are inconsistent
because the to_definition failure and round-trip mismatch logs do not include
path, even though it is available in this scope. Update both log::error!
branches in add_definition to include path alongside the existing object type
and definition details, matching the duplicate-object diagnostic style so the
offending file can be identified easily.

In `@src/pull/mod.rs`:
- Line 282: The new comment field in the pull request model is missing the same
style of documentation as sibling fields like created and options. Add a doc
comment directly on the comment field in the Pull struct so its meaning is clear
and the field matches the surrounding API documentation style.
🪄 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: 654d5294-8d43-49c2-93c6-aecfa6de3599

📥 Commits

Reviewing files that changed from the base of the PR and between 060b2b9 and d8d2f1d.

📒 Files selected for processing (9)
  • src/build/mod.rs
  • src/constants.rs
  • src/ddl/mod.rs
  • src/ddl/object.rs
  • src/deploy/diff.rs
  • src/deploy/mod.rs
  • src/project/load.rs
  • src/pull/mod.rs
  • src/pull/writer.rs

Comment thread src/build/mod.rs
Comment thread src/build/mod.rs
Comment thread src/build/mod.rs
Comment thread src/constants.rs
Comment thread src/ddl/mod.rs Outdated
…HECK

Three verified fixes from CodeRabbit's review of PR #54:

- unquote() no longer special-cases PUBLIC, which was corrupting every
  unquoted "public" identifier (e.g. the public schema in
  "public.foo") to the pseudo-role literal "PUBLIC". Pseudo-role
  canonicalization now lives in a role-scoped unquote_role() applied
  only at grantee (ACL) and USER MAPPING subject parse sites, where
  PUBLIC is a keyword rather than a folded identifier.
- constants::from_plural_key now maps "foreign_data_wrappers" (the
  underscore form used everywhere else, including schemata and the
  writer) instead of "foreign data wrappers", so FDW dependencies in
  project.yaml are recognized rather than logged as unknown and skipped.
- Typed-table column CHECK constraints render as CHECK (expr) to match
  table-level constraint rendering and produce valid SQL, instead of
  the bare CHECK expr that PostgreSQL rejects.

Skipped two CodeRabbit findings as invalid/redundant:
- Partition-bound validation in render_partition_for_values is already
  enforced by schemata/table.yml's oneOf on the partition bound styles,
  which the loader validates before build.
- A guard requiring a parent partition key before emitting child
  partitions would add renderer-side validation of malformed input
  (the renderer trusts schema-validated input) and would break the
  existing renders_list_partition / renders_range_partition /
  renders_default_partition unit tests, which intentionally render
  child partitions without a parent partition key.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@gmr

gmr commented Jul 7, 2026

Copy link
Copy Markdown
Owner Author

🤖 This comment was posted by Claude on behalf of @gmr

Addressed CodeRabbit's review (pushed as c0a51e2).

Fixed (3):

  • unquote PUBLIC scope (src/ddl/mod.rs) — removed the PUBLIC special-case that was corrupting every unquoted public identifier (e.g. the public schema) to the pseudo-role literal. Pseudo-role canonicalization moved to a role-scoped unquote_role, applied only at grantee (ACL) and USER MAPPING subject parse sites.
  • FDW dependency key (src/constants.rs) — from_plural_key now maps foreign_data_wrappers (the underscore form used everywhere else) instead of foreign data wrappers, so FDW dependencies resolve instead of being skipped.
  • Typed-table column CHECK (src/build/mod.rs) — now renders CHECK (expr) to match table-level constraints and produce valid SQL; added a unit test.

Skipped (2), with reasoning on the threads:

  • Partition-bound validation in render_partition_for_values — already enforced by schemata/table.yml's oneOf on bound styles, validated at load time.
  • Guard requiring a parent partition key before emitting child partitions — would add renderer-side validation of malformed input (the renderer trusts schema-validated input) and break the existing renders_list_partition / renders_range_partition / renders_default_partition unit tests.

just check (fmt + clippy + tests) passes locally. All five review threads resolved.

@gmr gmr merged commit d14ab5c into main Jul 7, 2026
2 checks passed
@gmr gmr deleted the fix/review-findings-batch2 branch July 7, 2026 18:21
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