drizzle-team / drizzle-team/drizzle-orm
[Pg-kit]: aws-data-api adapter forwards $N placeholders untranslated (no known Studio trigger on 1.0.0-rc.4)
- Dominant language
- TypeScript
- Stars
- 35.8k
- Forks
- 1.6k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 4
Description
**Correction (2026-09-12).** The Studio claim below is wrong. Studio's client uses `AwsPgDialect` for this driver and emits `:N`; I could not find a normal Studio action that sends `$N` with bound values. What stands is narrower: drizzle-kit's `aws-data-api` `query` and `proxy` forward SQL to `prepareQuery` without translating placeholders, and the Data API only binds `:N`. Details in [this comment](https://github.com/drizzle-team/drizzle-orm/issues/6147#issuecomment-5650035780). On `main` (`0.31.10`) the same untranslated path is reached by kit's own composite primary key introspection, which is #2372.
---
### What version of `drizzle-orm` are you using?
1.0.0-rc.4 (also reproduced on 0.45.2)
### What version of `drizzle-kit` are you using?
1.0.0-rc.4 (also reproduced on 0.31.10)
### Other packages
@aws-sdk/client-rds-data@3.1114.0 (also reproduced on 3.928.0)
### Describe the Bug
**Reproduction:** https://github.com/simiancraft/drizzle-kit-rds-data-api-repro
**Undesired behavior.** Over the RDS Data API, any query drizzle-kit sends with positional `$N` placeholders fails, because the Data API binds named parameters only and drizzle-kit forwards the placeholders unchanged. On `1.0.0-rc.4` this is reachable through `drizzle-kit studio`, whose client sends raw SQL:
```
ERROR: bind message supplies 0 parameters, but prepared statement "sqlx_s_35" requires 1; SQLState: 08P01
```
**Desired result.** Parameterized queries execute, so studio works against a Data API connection.
**Environment.** Aurora Serverless v2, PostgreSQL 15.12, Data API enabled. Not a monorepo. The reproduction creates its catalog with plain DDL over the Data API rather than with drizzle-kit, so the tool under test is isolated from the fixture that produces its input.
### Steps to reproduce
```bash
git clone https://github.com/simiancraft/drizzle-kit-rds-data-api-repro
cd drizzle-kit-rds-data-api-repro
git checkout rc # drizzle-kit + drizzle-orm 1.0.0-rc.4
cp .env.example .env # your own cluster ARN, secret ARN, database
bun install
bun run seed # creates the catalog with plain DDL
bun x drizzle-kit studio --port 5599 # in one shell
bun run probe:studio 5599 # in another
```
Use an empty, dedicated database.
### Isolating it to parameter binding
The probe sends the same query twice over the same connection, once without parameters and once with one:
```
### CONTROL: no parameters
sql: select count(*)::text as n from regions
result: [{"n":"0"}]
### TEST: one bound parameter
sql: select count(*)::text as n from regions where country_code = $1
params: ["US"]
result: {"status":"error","error":"ERROR: bind message supplies 0 parameters,
but prepared statement \"sqlx_s_35\" requires 1; SQLState: 08P01"}
```
The control succeeds, so the failure is the parameter binding rather than the query, the credentials, or the connection. Sent straight to the Data API with no drizzle involved, `SELECT $1::text` returns the identical `08P01`, which is the defect in one line.
### Cause
`AwsPgDialect.escapeParam(num)` returns `` `:${num + 1}` ``, so SQL the ORM *generates* already carries Data API named placeholders. SQL that arrives at drizzle-kit's proxy does not come from the dialect, and nothing translates it.
Two sites, with different mechanisms that produce the same error:
1. **Placeholders are not translated.** [`cli/connections.ts` L96 and L116 on `beta`](https://github.com/drizzle-team/drizzle-orm/blob/748058e837d9c4247330e3d45580cbdae52bffda/drizzle-kit/src/cli/connections.ts#L96) (L79 and L89 [on `main`](https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-kit/src/cli/connections.ts#L79)) pass `sql` to `session.prepareQuery` verbatim.
2. **Parameters are dropped.** [`ext/api-postgres.ts` L134 on `beta`](https://github.com/drizzle-team/drizzle-orm/blob/748058e837d9c4247330e3d45580cbdae52bffda/drizzle-kit/src/ext/api-postgres.ts#L134) ([`api.ts` L139 on `main`](https://github.com/drizzle-team/drizzle-orm/blob/b7862528fd8fc39bc2653a6c18dad7c1f4e68d10/drizzle-kit/src/api.ts#L139)) accepts `params` and executes `sql.raw(query)` without them. On `beta` it is named `_params`, so the discard may well be deliberate; if it is, then callers passing parameters into it are the problem instead. That one is your call, not ours.
### Why `pull` is not affected on 1.0.0-rc.4
Not because binding was fixed, but because that path stopped using parameters. [`dialects/postgres/aws-introspect.ts`](https://github.com/drizzle-team/drizzle-orm/blob/748058e837d9c4247330e3d45580cbdae52bffda/drizzle-kit/src/dialects/postgres/aws-introspect.ts) contains zero positional placeholders, and it carries the `::text` casts the Data API needs (`contype::text`, `attidentity::text`, `attgenerated::text`, `pg_get_serial_sequence(...)::regclass::oid`), since the Data API rejects `char` and `regclass` result columns. That is a genuine improvement over the 0.31.x line; `pull` on `1.0.0-rc.4` is clean for us, including against a 43 table, 384 column, 100 index, 62 foreign key schema. It leaves the proxy path uncovered.
| Surface | 0.31.10 | 1.0.0-rc.4 |
|---|---|---|
| `pull` / `push` introspection | fails | works |
| `studio` proxy | not tested by us (`pull` fails first) | **fails** |
| programmatic `pushSchema` | params discarded in source | params discarded in source |
### Possibly related
- #2372 (open) reports `bind message supplies 0 parameters` from `push` on a composite primary key, which is the same underlying incompatibility reached through a different command. Its reported symptom appears fixed on `1.0.0-rc.4` by the parameter-free introspection above, which is why we filed this separately rather than commenting there; the defect underneath it is still live and still reachable. @petejodo diagnosed site 2 there in January 2025.
- #3273 (closed) reports `Unsupported data type "CHAR"` in studio, which is a different defect on the same driver, addressed by the casts in `aws-introspect.ts`.
- #2982 (open) is the umbrella report for drizzle-kit over the Data API.
Contributor guide
Assessment
This issue has not been assessed yet.