also looking at this
fix(client): unsafe() refuses ?-style bindings on Postgres
#1172
3 files
+247
-13
Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.
| @@ -258,24 +258,31 @@ stats.forEach((s) => { | ||
| 258 | 258 | |
| 259 | 259 | ``` |
| 260 | 260 | |
| 261 | ## Prepared Statements | |
| 261 | ## Repeated Queries | |
| 262 | 262 | |
| 263 | Use prepared statements for repeated queries: | |
| 263 | `unsafe` is not a prepared-statement handle. It returns a query that runs when you | |
| 264 | await it and resolves to an array of rows, so there is no `.get()` to call per | |
| 265 | execution and nothing to finalize: | |
| 264 | 266 | |
| 265 | 267 | ```typescript |
| 268 | // Run it once per set of values, awaiting each. Postgres placeholders shown — | |
| 269 | // see "Placeholder style is the connection's, not the builder's" above. | |
| 270 | const user1 = await db.unsafe('SELECT * FROM users WHERE id = $1', [1]) | |
| 271 | const user2 = await db.unsafe('SELECT * FROM users WHERE id = $1', [2]) | |
| 266 | 272 | |
| 267 | // Prepare a statement | |
| 268 | const stmt = db.unsafe('SELECT * FROM users WHERE id = ?') | |
| 269 | ||
| 270 | // Execute multiple times efficiently | |
| 271 | const user1 = await stmt.get([1]) | |
| 272 | const user2 = await stmt.get([2]) | |
| 273 | const user3 = await stmt.get([3]) | |
| 273 | // Each resolves to an array of rows — index in, or use the builder's first(). | |
| 274 | console.log(user1[0]?.name) | |
| 275 | ``` | |
| 274 | 276 | |
| 275 | // Finalize when done | |
| 276 | stmt.finalize() | |
| 277 | Keep the SQL text identical across those calls and vary only the bindings. That is | |
| 278 | what lets the driver reuse its plan, and it is also what keeps the values | |
| 279 | parameterized rather than concatenated in. | |
| 277 | 280 | |
| 278 | ``` | |
| 281 | ::: tip | |
| 282 | The object `unsafe` returns before you await it is the driver's own, and its shape | |
| 283 | differs between `bun:sqlite` and `Bun.sql`. Await it and work with the rows; don't | |
| 284 | reach for methods on the unawaited value. | |
| 285 | ::: | |
| 279 | 286 | |
| 280 | 287 | ## Transaction with Raw Queries |
| 281 | 288 | |