Skip to content

Commit e0c193f

Browse files
committed
chore(changeset): objectql patch for the blank-typed-value write door
Claude-Session: https://claude.ai/code/session_01Bvd69VPa6puiNzzPUroDBx Co-authored-by: Claude <noreply@anthropic.com>
1 parent e7ef2db commit e0c193f

1 file changed

Lines changed: 69 additions & 0 deletions

File tree

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
"@objectstack/objectql": patch
3+
---
4+
5+
fix(objectql): a cleared number, boolean, date, datetime or time field stores `null`, on every backend (#20308)
6+
7+
`patch` — a bug fix in a released package. No exported symbol, no spec key and
8+
no API signature changes.
9+
10+
## What was wrong
11+
12+
The record validator reads a blank string — `''`, or whitespace only — as
13+
"missing", and returns before any type check. Nothing rewrote the value, so the
14+
driver received the blank exactly as sent. The same clear of one field therefore
15+
had three outcomes:
16+
17+
- **memory and SQLite** stored `''` in a number, currency, percent, rating,
18+
slider, progress, summary, boolean, toggle, date, datetime or time column, on
19+
every write door (create, update, batch, `createMany`, `updateMany`). On SQLite
20+
a stored `''` on a boolean then read back as `false`.
21+
- **PostgreSQL** refused the statement (`invalid input syntax for type
22+
numeric` / `boolean` / `date`), which REST answered as `500 DATABASE_ERROR` —
23+
or as a failed row with `INTERNAL_ERROR` on the batch doors.
24+
25+
objectui's edit form sends a cleared date, datetime or time box as `''`, so this
26+
is the ordinary "clear the field and save" gesture.
27+
28+
Separately, `progress` and `summary` had no type check at all: a non-numeric
29+
string such as `'abc'` was stored verbatim on memory and SQLite.
30+
31+
## What changes
32+
33+
- **The write door reads a blank on a non-string-typed column as `null`.** Every
34+
field whose declared type is in the spec's `NON_TEXT_STORED_VALUE_TYPES` (the
35+
numeric types including `progress` and `summary`, `boolean`, `toggle`,
36+
`date`, `datetime`, `time`) has a blank string replaced by `null`. It happens
37+
at the start of `ObjectQL.insert()` and `ObjectQL.update()`, before the
38+
middleware, the hooks, the defaults and validation read the payload, and at
39+
the same point in `ObjectQL.validate()` (the dry run). Every REST, batch and
40+
import door writes through those methods. The caller's own objects are never
41+
mutated.
42+
- **What that means for a write:** the column stores `null` on every backend,
43+
and PostgreSQL no longer refuses the request. A blank on a `required` field is
44+
refused with `required`, exactly as `null` is. On create, a blank takes the
45+
field's `defaultValue` exactly as `null` does.
46+
- **String-stored columns are untouched.** A text, lookup or select `''` is still
47+
stored as `''`.
48+
- **`progress` and `summary` join the numeric type check.** A non-numeric
49+
string on either is refused with `invalid_number`, as on `number`. No `min`,
50+
`max` or `scale` is newly enforced on them.
51+
- **One consequence for roll-ups.** A `summary` whose `summaryOperations` takes
52+
`min` or `max` over a `date`, `datetime` or `time` field writes a date string
53+
into the numeric summary. PostgreSQL already refused that recompute
54+
(`ERR_SUMMARY_RECOMPUTE`). Memory and SQLite now refuse it the same way,
55+
instead of storing the string.
56+
57+
## Rows already stored
58+
59+
This fixes new writes only. Rows written earlier on SQLite (and on memory,
60+
MongoDB or libSQL) may still hold `''` in such a column; on SQLite a boolean
61+
holding `''` reads back as `false`, and one holding whitespace as `true`.
62+
PostgreSQL never stored one. To repair a
63+
SQLite table, run this once per non-string-typed column (a field of one of the
64+
types listed above):
65+
66+
```sql
67+
UPDATE "<object>" SET "<field>" = NULL
68+
WHERE typeof("<field>") = 'text' AND trim("<field>", ' ' || char(9) || char(10) || char(13)) = '';
69+
```

0 commit comments

Comments
 (0)