| 38 | }; |
| 39 | |
| 40 | constructor() { |
| 41 | this.db = new DatabaseSync(":memory:"); |
| 42 | this.sql = { |
| 43 | exec: <Row extends object>(query: string, ...bindings: unknown[]): SQLCursorLike<Row> => { |
| 44 | // node:sqlite refuses statements with trailing whitespace through |
| 45 | // prepare(); also we cache prepared statements per unique query |
| 46 | // string to keep the fixture fast. |
| 47 | const key = query; |
| 48 | let stmt = this.cache.get(key); |
| 49 | if (stmt === undefined) { |
| 50 | stmt = this.db.prepare(query); |
| 51 | this.cache.set(key, stmt); |
| 52 | } |
| 53 | const normalizedBindings = bindings.map(toSQLiteValue); |
| 54 | const rows = (stmt.all(...(normalizedBindings as never[])) as Row[]) ?? []; |
| 55 | return new TestCursor<Row>(rows); |
| 56 | }, |
| 57 | }; |
| 58 | } |
| 59 | |
| 60 | transactionSync<T>(closure: () => T): T { |
| 61 | this.db.exec("BEGIN"); |