fix(nextly): the last two reads outside the pipeline resolve like a write - #1732
mobeenabdullah wants to merge 1 commit into
Conversation
|
Warning Review limit reachedNext included review available in 22 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
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. Comment |
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ee0c1fffd6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| * sequence-ownership check in `introspect-live.ts` already uses. | ||
| */ | ||
| export const PG_RELATION_THE_WRITES_HIT: SQL = sql`format('%I.%I', c.table_schema, c.table_name)::regclass = to_regclass(quote_ident(c.table_name))`; | ||
| export const PG_RELATION_THE_WRITES_HIT_SQL = `format('%I.%I', c.table_schema, c.table_name)::regclass = to_regclass(quote_ident(c.table_name))`; |
There was a problem hiding this comment.
Keep the relation predicate in Drizzle
This converts the existing Drizzle fragment into a raw SQL string and exposes that string for interpolation into two production driver queries. Even though this particular text is constant, it bypasses the repository's enforced Drizzle-only database-access boundary; keep the shared predicate as a Drizzle fragment and migrate these callers to execute composed Drizzle statements instead of introducing a raw-SQL API.
AGENTS.md reference: AGENTS.md:L274-L276
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Agreed, and I have closed the PR rather than working around it. Exporting the predicate as a raw string publishes a raw-SQL API, which is worse than the bug it fixes. Measured the migration you suggest: missing-columns.ts builds every statement as a string for executeQuery including its ALTER, system-table-service.ts holds 21 raw SQL strings across three dialect maps, and my test's fake adapter observes executeQuery — so it is a module-level migration, not a predicate change. Filed as its own task with those measurements. Inlining the predicate at both sites would have avoided the raw API and created two spellings of one rule, which is the defect this finding is about, so I did not take that route either.
|
Closing this — the finding is right and the fix belongs in a different change. What I got wrong. To reach two raw-SQL queries I exported the predicate as a Why I am not just doing the suggested migration here. I measured it:
So the honest scope is "migrate these two modules to Drizzle, then apply the The alternative I rejected: inlining the predicate at both sites instead of What happens now. Filed as
|
Finishes
finding:pg-schema-pinned-in-seven-places. #1721 took the three reads inthe schema pipeline; these are the last two that are free to touch.
schema/utils/missing-columns.tsservices/system/system-table-service.tsBoth now use the rule #1721 established: resolve the relation an unqualified
statement reaches, rather than naming a schema. Nothing changes for a database on
public, which is the default.One rule, two forms — not two rules
These two build raw SQL text for the driver; the pipeline reads compose
Drizzle
sqltemplates. Rather than write the predicate twice, the module nowholds it once as text and derives the Drizzle fragment from that:
sql.rawover a module constant interpolates nothing — the text is fixed atbuild time and names only catalog columns — so it carries no injection surface.
A rule copied between the two forms would drift the first time either was
corrected, which is the defect this whole finding is about.
Evidence
A test asserts the SQL the adapter is handed, not the source text of the
module that built it —
missing-columns.test.tsalready has a fake adapter thatrecords queries, so the assertion sits on the value the server would see.
Break-verified twice, each failing only that test:
'public'quote_ident, so a capitalised name folds awayNot here
Two of the seven sites stay on the finding:
cli/commands/migrate-fresh.ts— the destructive one: it listspublic'stables in order to DROP them, so on a tenant search path it drops unrelated
tables and leaves the real ones. PR refactor(nextly): one name per question #1729 is currently editing that file for an
unrelated refactor, so this would conflict. It deserves its own review anyway.
domains/collections/services/collection-relationship-service.ts— insidePR refactor(nextly): decide access with one mechanism, not two #1659's territory.
Gates
pnpm build0 · nextlycheck-types0lint0vitest0 (935 files, 11,874tests) ·
fallow auditpass, every*_introduced0 over 5 files ·changeset status0.Worth noting: the integration probe added in #1721/#1727 has now executed for the
first time and passed on all three dialects, so the search-path rule these
reads adopt is verified against a real PostgreSQL rather than only reasoned about.