-
-
Notifications
You must be signed in to change notification settings - Fork 942
Description
Report hasn't been filed before.
- 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.43.1
What version of drizzle-kit
are you using?
0.31.1
Other packages
No response
Describe the Bug
What is the undesired behavior?
When using Drizzle operator functions (gt()
, gte()
, lt()
, lte()
, etc.) inside check()
constraints, the generated SQL migration contains parameterized placeholders ($1
, $2
, etc.) instead of literal values. This results in invalid CHECK constraints that cannot be executed by the database.
What are the steps to reproduce it?
- Create a table schema with CHECK constraints using operator functions:
import { gt, gte } from 'drizzle-orm'
import { check, integer, numeric, pgTable } from 'drizzle-orm/pg-core'
export const ExampleSchema = pgTable('example', {
id: integer('id').primaryKey(),
amount: numeric('amount').notNull(),
count: integer('count').notNull(),
}, t => [
check('amount_positive', gt(t.amount, '0')),
check('count_non_negative', gte(t.count, 0)),
])
- Run
drizzle-kit generate
to create migration files - Examine the generated SQL file
What is the desired result?
The generated SQL should contain literal values in CHECK constraints:
CONSTRAINT "amount_positive" CHECK ("example"."amount" > 0)
CONSTRAINT "count_non_negative" CHECK ("example"."count" >= 0)
Actual result:
The generated SQL contains parameterized values:
CONSTRAINT "amount_positive" CHECK ("example"."amount" > $1)
CONSTRAINT "count_non_negative" CHECK ("example"."count" >= $1)
Environment Details
What database engine are you using?
PostgreSQL (tested with PostgreSQL 14+)
Are you using a specific cloud provider?
No, this issue occurs with any PostgreSQL instance (local, cloud, etc.)
Do you think this bug pertains to a specific database driver?
Yes, this appears to be related to the pg
driver and how Drizzle handles parameterized queries in DDL statements.
Are you working in a monorepo?
Yes, using pnpm workspaces, but this issue is reproducible in any project structure.
Package Versions:
drizzle-orm
: 0.43.1drizzle-kit
: 0.31.1@types/pg
: 8.15.2pg
: 8.16.0
TypeScript version:
TypeScript 5.7.3
tsconfig.json (relevant parts):
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022"],
"module": "commonjs",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
}
}
Workaround
The issue can be avoided by using sql
template literals instead of operator functions:
import { sql } from 'drizzle-orm'
// Instead of: check('amount_positive', gt(t.amount, '0'))
check('amount_positive', sql`${t.amount} > 0`)
This generates the correct SQL:
CONSTRAINT "amount_positive" CHECK ("example"."amount" > 0)
Additional Context
This issue affects all comparison operators (gt
, gte
, lt
, lte
, eq
, ne
) when used in CHECK constraints. The problem seems to be that Drizzle treats the operator functions as parameterized queries even in DDL contexts where parameterization is not valid.
The issue doesn't occur with:
- WHERE clauses in SELECT statements
- Other SQL contexts that support parameterized queries
sql
template literals in CHECK constraints
This suggests the bug is specifically in how CHECK constraints process operator function expressions during migration generation.