drizzle-team / drizzle-team/drizzle-orm
[BUG]: postgres.js adapter ignores client-level prepare: true for regular queries
- 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
### Other packages
postgres@3.4.9, Cloudflare Workers with Hyperdrive
### Describe the Bug
When the Postgres.js client is configured with `{ prepare: true }`, ordinary Drizzle queries still run without prepared statements.
Unlike #5502, this affects ordinary queries rather than queries explicitly created with `.prepare(name)`.
Given this client:
```ts
const client = postgres(connectionString, { prepare: true })
const db = drizzle(client)
```
Drizzle executes ordinary queries through:
```ts
client.unsafe(query, params)
```
Postgres.js treats an `unsafe()` call without query options as `prepare: false`, which overrides the client setting.
This matters for Cloudflare Hyperdrive because Postgres.js queries using `prepare: false` may not be cacheable:
https://developers.cloudflare.com/hyperdrive/observability/troubleshooting/#uncached-queries
#### Minimal reproduction
No database is required. This script records the options Drizzle passes to `client.unsafe()`:
```js
import { drizzle } from 'drizzle-orm/postgres-js'
import { integer, pgTable } from 'drizzle-orm/pg-core'
import postgres from 'postgres'
const users = pgTable('users', {
id: integer('id').primaryKey(),
})
const client = postgres('postgres://unused:unused@127.0.0.1:1/unused', {
prepare: true,
})
const observedQueryOptions = []
client.unsafe = (query, params, options) => {
observedQueryOptions.push(options)
return { values: async () => [] }
}
const db = drizzle(client)
await db.select().from(users)
console.log(client.options.prepare) // true
console.log(observedQueryOptions[0]) // undefined
```
To address #5502, `drizzle-orm@1.0.0-rc.4` calls:
```ts
client.unsafe(query.sql, params, { prepare: name !== false })
```
However, `name` is `false` for ordinary queries, so they still pass `{ prepare: false }` even when the client was created with `{ prepare: true }`.
#### Expected behavior
Ordinary queries should honor the Postgres.js client's `prepare: true` setting, or the adapter should expose an option for forwarding `unsafe()` query options. The same behavior should apply inside transactions and nested savepoints.
#### Actual behavior
`drizzle-orm@0.45.2` omits the third `unsafe()` argument. `drizzle-orm@1.0.0-rc.4` explicitly passes `{ prepare: false }` for ordinary queries. In both cases, the client-level setting cannot enable prepared statements for those queries.
#### Environment
- Database: PostgreSQL (Neon)
- Runtime: Cloudflare Workers
- Connection proxy/pooler: Cloudflare Hyperdrive
- Driver: Postgres.js
Contributor guide
Research direction
Start in the Postgres.js adapter entry point that calls client.unsafe(query, params), then trace the transaction and nested-savepoint paths. Use the supplied no-database reproduction to inspect the options passed for ordinary queries; done when client-level prepare: true is honored consistently for ordinary, transactional, and nested-savepoint queries.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- postgres, typescript
- Domain
- database
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 62/100