Replies: 1 comment
|
Half of this already works RLS policies live in the schema today import { sql } from 'drizzle-orm';
import { pgPolicy, pgTable, uuid } from 'drizzle-orm/pg-core';
export const posts = pgTable('posts', {
id: uuid().primaryKey(),
ownerId: uuid().notNull(),
}, (t) => [
pgPolicy('owner reads own posts', {
for: 'select',
to: 'authenticated',
using: sql`${t.ownerId} = current_setting('app.user_id')::uuid`,
}),
]).enableRLS();
Functions and triggers have no schema level API so the supported path stays custom migrations drizzle-kit generate --custom --name=touch_updated_atThe file lands in the same journal and runs in order with everything else What kills most of the churn at your scale |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Postgres is great. Drizzle is great. You know what would make both better?
Defining Postgres primitives in the Drizzle schema.
We run a production app on Drizzle + Postgres: 157 functions (most of them
SECURITY DEFINER), a wall of RLS policies, triggers wiring it together. All of it lives in 60 hand-written migration files, because Drizzle can't see any of it. Half those files are justCREATE OR REPLACE FUNCTIONwith an edited body. Every change is a manual migration.It would be rad if we could write the function in the schema, change the body, run
generate, and be done. Same loop we already get for tables.I was curious, pointed Opus at it, and we did a first pass, unsolicited, to see if the shape feels right.
pgFunctionandpgTriggeras first-class entities, on the v1 engine, through the whole pipeline: generate, push, and pull. A test suite the size of the policy suite, round-tripped against a real database.https://github.com/tyrauber/drizzle-orm/tree/pg-functions-triggers-v1
What it looks like
Triggers stand alone or colocate in the table's extras callback, the way policies do:
Args are columns
Function args and returns reuse the column builders.
pgEnum,.array(),customType,.$type<T>(), defaults: all of it works as-is, no new type vocabulary.InferFunctionArgsandInferFunctionReturnscome for free, so you can type RPC off the schema.The limit: a column builder has no way to say
OUT,INOUT, orVARIADIC, so every arg isINfor now. Covers most functions, not all. This is the call I'd most want your read on. Right approach, or do you want an arg type that carries a mode?How the diffing behaves
Identity is the full signature,
schema.name(argtypes). Overloads coexist. Change the signature and it's a drop + create.A body or flag edit is one
CREATE OR REPLACE. The OID holds, so dependent triggers stay put. A return-type change is the one case Postgres forces to drop + create; dependent triggers drop before and recreate after, in order.Functions create before tables, with
SET check_function_bodies = offup front (pg_dump does the same), so a sql-language body that references a not-yet-created table still applies.A trigger's
WHENcan't be compared as text on pull, because Postgres rewritestgqual. We hash the source text into aCOMMENT ON TRIGGER 'drizzle:when:<sha256>'and compare hashes: changed hash is a real edit, matching hash is just Postgres normalizing. This is the piece I'm least sure about. It writes Drizzle metadata into the database. If there's a cleaner way, I want to hear it.Scope
First pass: functions and triggers. Out for now, easy to follow up: constraint and deferrable triggers, transition tables,
OUT/VARIADICargs, cross-schema moves, grants, extensions.One limit I'd rather name than hide: push can't track an arg-default edit, because Postgres won't hand back per-arg defaults through introspection. So push warns and sends you to generate, which catches them. Trigger
WHENedits work the same way, detected through the hash above.What I'm asking
A review, thoughts, guidance.
Purposely a discussion, not a PR.
No pressure. Mostly I just think Postgres-in-the-schema would be rad and wanted to put a real shape in front of you.
Thanks for the awesome library. This was fun.
All reactions