Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions node.js/app-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,20 +164,23 @@ When CAP's generic handlers run a CRUD operation, the result follows a consisten
| Operation | Return value |
|-----------------------|-----------------------------------------------------------------------------------------------|
| `READ` | Array of matching records, or a single record / `null` when read by key |
| `INSERT` / `CREATE` | Array with `.affected` (rows written); iterate to access the inserted rows' primary keys |
| `UPDATE` / `UPSERT` | Array with `.affected` (rows changed); populated with rows from a `RETURNING` clause |
| `DELETE` | Array with `.affected` (rows deleted); populated with rows from a `RETURNING` clause |
| `CREATE` | Array with `.affected` (rows created); iterate to access the created rows' generated keys |
| `UPDATE` | Array with `.affected` (rows changed); reserved for rows from a `RETURNING` clause |
| `UPSERT` | Array with `.affected` (rows written); reserved for rows from a `RETURNING` clause |
| `DELETE` | Array with `.affected` (rows deleted); reserved for rows from a `RETURNING` clause |

For `INSERT`s, the result is a lazy array: iterating it (`[...result]`, `for…of`, `JSON.stringify`) materializes the generated primary keys of the inserted rows. Direct index access works after the first iteration.
For `CREATE`, the array will be populated with rows from an SQL `RETURNING` clause once that is supported. Until then, the result is a lazy array that computes the created rows' generated primary keys on demand: iterating it (`[...result]`, `for…of`, `JSON.stringify`) populates those keys, avoiding the cost when you don't need them.

> [!warning] Iterate before indexing
> Direct index access (`result[0]`) returns `undefined` until the array has been iterated at least once. Spread or loop over the result first.

```js
const inserted = await srv.create(Books).entries({title:'Catweazle'})
inserted.affected // 1
const [row] = [...inserted] // materializes — row holds the generated key
inserted[0] // same row (materialized above)
const created = await srv.create(Books).entries({title:'Catweazle'})
created.affected // 1
const [row] = [...created] // iterate first — row holds the generated key
```

For `UPDATE`, `UPSERT`, and `DELETE`, the array is reserved for rows returned by a SQL `RETURNING` clause. But `RETURNING` is not yet supported, so the array currently is always empty:
For `UPDATE`, `UPSERT`, and `DELETE`, the array is reserved for rows returned by an SQL `RETURNING` clause. Unlike `CREATE`, there are no generated keys to synthesize client-side, so — with `RETURNING` not yet supported the array is currently always empty:

```js
const updated = await srv.update(Books).set({discount:'10%'}).where({stock:{'>':111}})
Expand Down
Loading