drizzle-team / drizzle-team/drizzle-orm

[BUG]: drizzle-kit pull (Postgres, 0.31.10) introspection is not generate-clean: cast-form CHECKs, numeric defaults, partitioned parents, index opclasses

Open
#6,093 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
35.8k
Forks
1.6k
Avg merge
2d 7h
Merged PRs (30d)
4

Description

### Report hasn't been filed before.

- [x] I have verified that the bug I'm about to report hasn't been filed before.

### What version of `drizzle-orm` are you using?

0.45.2

### What version of `drizzle-kit` are you using?

0.31.10

### Describe the Bug

Running `drizzle-kit pull` against a Postgres 16 database and then `drizzle-kit generate` produces spurious DROP/ADD statements — the introspected schema is not symmetric with the generator. Four concrete defects, all verified against the same database:

**1. CHECK constraints re-imported with mid-expression casts, so the next generate emits spurious CHECK DROP/ADD.**

In the database (and in `pg_get_expr`), the constraint is:

```sql
CONSTRAINT shop_profiles_vertical_check CHECK (((vertical)::text = ANY (ARRAY['supplements'::text, ...])))
```

The introspection code strips casts only with a trailing-only regex (`res.replace(/(::[\w.\s]+...)+$/gi, '')`), so mid-expression casts like `(vertical)::text` survive in the pulled `schema.ts`. The generated `check()` then differs textually from the snapshot, and `generate` wants to drop and re-add the constraint.

**2. `numeric` column defaults re-imported as strings.**

A column with `DEFAULT 1` (`numeric`) is pulled as `.default('1')` (string literal), while the schema defines `default(1)`. `generate` emits a spurious default-value diff. (Same family as #5661, which was fixed for SQLite via a default-value normalizer — Postgres never got one.)

**3. Partitioned parent tables are dropped from introspection entirely.**

The introspection query filters `relkind IN ('r','v','m')` — partitioned parents (`relkind = 'p'`) are never selected, so a `PARTITION BY RANGE` parent table simply disappears from the pulled schema (its leaf partitions survive as plain tables). I see rc.4's query now includes `'p'` (`relkind IN ('r','p','v','m')`), but since the drizzle schema DSL has no partition concept, it's unclear whether rc can actually model it — worth verifying before 1.0 goes stable.

**4. Index opclasses are mis-assigned or lost.**

Four of our indexes declare opclasses (`uuid_ops` on a btree over uuid, `text_ops`/`timestamptz_ops` elsewhere). The pulled schema assigns wrong opclasses to some of them and drops others, producing spurious index diffs on the next `generate`.

### Expected behaviour

`pull` → `generate` on an unchanged database should report `No schema changes`. Today it emits DROP/ADD pairs for every defect above — and since these DROPs have no `IF EXISTS`, applying the generated migration against a rebuilt database fails loudly or destroys constraints.

### Additional context

- Looks like the same asymmetry family as #6020 (Postgres `up` → `generate` no-op rewrite) and #5661 (SQLite, fixed via a default normalizer). @AlexBlokh mentioned a snapshots rewrite is in progress — do these four 0.31 pull defects fall inside that rewrite's scope? Happy to provide a minimal repro repo if useful.
- Our workaround meanwhile: we hand-align the snapshot and treat `generate` reporting `No schema changes` as the acceptance check, and we've removed `db:pull` from our scripts entirely.

Contributor guide

Open the contributing guide

Research direction

Start at the PostgreSQL introspection path used by drizzle-kit pull, including the relkind query, then reproduce the report against PostgreSQL 16 and run drizzle-kit generate. Done means an unchanged pull→generate reports “No schema changes” while preserving CHECK expressions, numeric defaults, partitioned parents, and index opclasses.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, typescript
Domain
cli, database
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.