Skip to content

Commit 9dc3aba

Browse files
committed
docs(data-modeling): say what expression means on a stored field, beside its formula meaning
field-types.mdx gains a short subsection under `formula`, and validation-rules.mdx a short paragraph under its `formula` section: on a field of any other type the engine computes the declared expression on every insert and every update by id and stores it, a predicate update computes it only when the patch moves an input and is refused when the matched rows would compute different values, and a client-sent value is overwritten, not refused or reported. Both link to the generated FieldSchema reference. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
1 parent ec2694d commit 9dc3aba

2 files changed

Lines changed: 11 additions & 0 deletions

File tree

‎content/docs/data-modeling/field-types.mdx‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,15 @@ Calculated field using a CEL expression (see [Expressions](/docs/data-modeling/f
415415
{ name: 'total', label: 'Total', type: 'formula', expression: 'record.quantity * record.unit_price', returnType: 'number' }
416416
```
417417

418+
#### `expression` on a stored field
419+
420+
`expression` is not only a `formula` key. On a field of any other type, the engine computes it from the row each write stores and **stores** the result in the field's column, so a `summary` can roll the column up. It is computed on every insert and every update by id (the stored row merged with the patch). On a predicate update it is computed only when the patch moves an input: one value is stored for every matched row, and the update is refused (`VALIDATION_FAILED`, an `invalid_value` error on the field) when the rows would compute different values. Update those rows by id instead. A value a client sends for the field never stands: it is overwritten by the computed one, with no refusal and no dropped-field report. The full contract is the `expression` row of [`FieldSchema`](/docs/references/data/field).
421+
422+
```typescript
423+
// Stored, so a parent `summary` can sum it. A client-sent amount is overwritten.
424+
Field.currency({ label: 'Amount', expression: 'record.quantity * record.unit_price' })
425+
```
426+
418427
### `summary`
419428
Roll-up summary from child records.
420429

‎content/docs/data-modeling/validation-rules.mdx‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,8 @@ application-level emptiness check is needed.
365365
}
366366
```
367367

368+
**`expression` on a stored field.** A field of any other type may declare `expression` too, and it validates differently from a `formula`. The engine computes the value on every insert and every update by id, and stores it. A value a client sends for the field is not refused and not reported as dropped: it is overwritten by the computed one. The one refusal is a predicate update that moves an input: when the matched rows would compute different values, the update is refused with `VALIDATION_FAILED` and an `invalid_value` error naming the field, and nothing is written. See [`expression` on a stored field](/docs/data-modeling/field-types#expression-on-a-stored-field) and the `expression` row of [`FieldSchema`](/docs/references/data/field).
369+
368370
### `summary`
369371

370372
| Property | Type | Default | Validation Behavior |

0 commit comments

Comments
 (0)