drizzle-team / drizzle-team/drizzle-orm
[BUG]: SQLite push generates DEFAULT datetime('now') without parentheses, causing syntax error
- 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?
1.0.0-beta.21
### What version of `drizzle-kit` are you using?
1.0.0-beta.21
### Other packages
_No response_
### Describe the Bug
When drizzle-kit push recreates a SQLite table (e.g., to add a named UNIQUE constraint), it generates DEFAULT
datetime('now') instead of DEFAULT (datetime('now')) in the CREATE TABLE statement. SQLite requires parentheses around
expression defaults, so this produces a syntax error:
SQLITE_ERROR: near "(": syntax error
Expected behavior
The generated SQL should wrap expression defaults in parentheses:
`created_at` text DEFAULT (datetime('now'))
Actual behavior
The generated SQL omits the outer parentheses:
`created_at` text DEFAULT datetime('now')
The full generated statement:
```sql
CREATE TABLE `__new_fundraiser_updates` (
`id` integer PRIMARY KEY AUTOINCREMENT,
`fundraiser_id` integer NOT NULL,
`created_at` text DEFAULT datetime('now'),
`url` text,
CONSTRAINT `fundraiser_updates_fundraiser_url_unique` UNIQUE(`fundraiser_id`,`url`)
);
```
Steps to reproduce
Schema definition (schema.ts):
```ts
import { sqliteTable, integer, text, unique } from "drizzle-orm/sqlite-core";
import { sql } from "drizzle-orm";
export const fundraiserUpdates = sqliteTable(
"fundraiser_updates",
{
id: integer().primaryKey({ autoIncrement: true }),
fundraiserId: integer("fundraiser_id").notNull(),
createdAt: text("created_at").default(sql`datetime('now')`),
url: text(),
},
(t) => [
unique("fundraiser_updates_fundraiser_url_unique").on(
t.fundraiserId,
t.url
),
]
);
```
Seed the database with an unnamed UNIQUE constraint (reproduce.ts):
```ts
import { createClient } from "@libsql/client";
const client = createClient({ url: "file:./test.db" });
await client.execute(`
CREATE TABLE IF NOT EXISTS fundraiser_updates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
fundraiser_id INTEGER NOT NULL,
created_at TEXT DEFAULT (datetime('now')),
url TEXT,
UNIQUE (fundraiser_id, url)
);
`);
```
Trigger the bug:
npx tsx reproduce.ts
npx drizzle-kit push --force
The existing table has an unnamed UNIQUE (fundraiser_id, url) constraint. The schema defines a named one
(fundraiser_updates_fundraiser_url_unique), so drizzle-kit push recreates the table. During recreation, it reads the
existing DEFAULT (datetime('now')) from SQLite metadata, strips the outer parentheses, and doesn't re-add them in the
generated CREATE TABLE.
Environment
- Database: SQLite via @libsql/client
- OS: Windows 11
- drizzle-orm: 1.0.0-beta.21
- drizzle-kit: 1.0.0-beta.21
Contributor guide
Research direction
Start with schema.ts and reproduce.ts, then run npx tsx reproduce.ts and npx drizzle-kit push --force to observe the SQLite table recreation. Trace the drizzle-kit path that reads the existing DEFAULT (datetime('now')) and emits the CREATE TABLE statement. Done when the recreated table uses DEFAULT (datetime('now')) and push completes without SQLITE_ERROR.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- sqlite, typescript
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 65/100