Skip to content

Commit f45b096

Browse files
committed
fix(spec): the driver-sql-unresolvable-where-column-refused entry names the remote aggregate refusals
The protocol-18 D3 entry named only a `where` column on find / findOne / count and INVALID_FILTER / 400. On the remote face of TursoDriver the aggregate() door answered [] for a missing column or a missing table; it now refuses as the local face does (SqlDriver.aggregateBackendFault): INVALID_FILTER / 400 for a where column, INVALID_FIELD / 400 for a groupBy or aggregation column, DATABASE_ERROR / 500 for an absent table, as pinned by turso-local-remote-missing-table-column-parity.test.ts. The entry's surface names that door and those codes, its remedy adds grouping / aggregating and running schema sync so the object's table exists, and its acceptance criterion covers a report or dashboard that groups by or aggregates over a missing column. The reason paragraph is unchanged. registry.ts was regenerated with gen:migration-registry; spec-changes.json and the upgrade guide project protocol 17 only, so they do not carry this step-18 entry and are unchanged. The shared changeset now describes both entries. Claude-Session: https://claude.ai/code/session_018fxqvRJW12TaHC7DUQ89Y6 Co-authored-by: Claude <noreply@anthropic.com>
1 parent 2707067 commit f45b096

3 files changed

Lines changed: 41 additions & 15 deletions

File tree

‎.changeset/20773-etl-entry-syncconfig-schedule-deleted-in-17.md‎

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,27 @@
22
'@objectstack/spec': patch
33
---
44

5-
fix(spec): the `etl-pipeline-layer-retired` migration entry dates the `syncConfig.schedule` deletion to `@objectstack/spec` 17, not 18
5+
fix(spec): two ADR-0087 migration entries state what the tree does — `etl-pipeline-layer-retired` dates the `syncConfig.schedule` deletion to `@objectstack/spec` 17, and `driver-sql-unresolvable-where-column-refused` names the remote `aggregate()` refusals
66

77
Clause-②: no
88

9-
The protocol-17 semantic entry `etl-pipeline-layer-retired` explains that connector-attached
9+
**`etl-pipeline-layer-retired` (protocol 17).** The entry explains that connector-attached
1010
`syncConfig` has no reader outside `packages/spec`, and cites the same measurement that removed
1111
`syncConfig.schedule`. Its `replacement` text said that key was retired "in 18". It was deleted
1212
in `@objectstack/spec` 17 under ADR-0049 (first released in 17.5.0), as the note at the deleted
13-
position in `integration/connector.zod.ts` already says. The sentence now reads "the same measurement that deleted `syncConfig.schedule` in
14-
@objectstack/spec 17 under ADR-0049".
13+
position in `integration/connector.zod.ts` already says. The sentence now reads "the same
14+
measurement that deleted `syncConfig.schedule` in @objectstack/spec 17 under ADR-0049".
1515

16-
Text only: no entry id, `surface`, conversion or matching logic changes, and `os migrate meta`
17-
rewrites exactly what it rewrote before. The generated migration registry, `spec-changes.json`
18-
and the protocol upgrade guide carry the corrected sentence.
16+
**`driver-sql-unresolvable-where-column-refused` (protocol 18).** The entry named only a `where`
17+
column on `find()` / `findOne()` / `count()` and `INVALID_FILTER` / 400. On the remote face of
18+
`TursoDriver`, the `aggregate()` door answered `[]` for a missing column or a missing table. It
19+
now refuses as the local face does: `INVALID_FILTER` / 400 for a `where` column the table lacks, `INVALID_FIELD` / 400 for a
20+
`groupBy` or aggregation column the table lacks, and `DATABASE_ERROR` / 500 for an object whose
21+
table is absent. The entry's `surface` now names that door and those codes. Its remedy adds
22+
grouping and aggregating, and running schema sync so the object's table exists. Its acceptance
23+
criterion now also covers a report or dashboard that groups by, or aggregates over, a name the
24+
object has no column for.
25+
26+
Text only: no entry id, conversion or matching logic changes, and `os migrate meta` rewrites
27+
exactly what it rewrote before. The generated migration registry, `spec-changes.json` and the
28+
protocol upgrade guide carry the corrected text.

‎packages/spec/src/migrations/entries/semantic/18.driver-sql-unresolvable-where-column-refused.ts‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ export const entry: SemanticMigration = {
88
'a `where` naming a column the table does not have, on `driver-sql` (and its '
99
+ '`TursoDriver` / `SqliteWasmDriver` subclasses) — `find()` / `findOne()` answered '
1010
+ '`[]` and `count()` threw the dialect\'s own error; both now refuse with '
11-
+ '`INVALID_FILTER` / 400',
11+
+ '`INVALID_FILTER` / 400. The `aggregate()` door of `TursoDriver`\'s remote face '
12+
+ 'answered `[]` for a missing column or a missing table, and now refuses as the local '
13+
+ 'face does: `INVALID_FILTER` / 400 for a `where` column the table lacks, '
14+
+ '`INVALID_FIELD` / 400 for a `groupBy` or aggregation column the table lacks, and '
15+
+ '`DATABASE_ERROR` / 500 for an object whose table is absent',
1216
replacement:
1317
'name a column the object actually has, or run schema sync so a recently declared '
14-
+ 'field exists as a column before filtering on it. A caller that legitimately wants '
18+
+ 'field exists as a column before filtering, grouping or aggregating on it, and so '
19+
+ 'the object\'s table exists. A caller that legitimately wants '
1520
+ '"no rows unless this matches" gets that from a predicate over a real column; there '
1621
+ 'is no spelling of an unresolvable column that means "match nothing", which is '
1722
+ 'exactly what the old empty list was mistaken for',
@@ -88,9 +93,12 @@ export const entry: SemanticMigration = {
8893
+ 'caller never asked for. ADR-0112.',
8994
acceptanceCriteria:
9095
'No saved report `query.filter`, flow condition, sharing/permission rule or hook '
91-
+ 'filters on a name the queried object has no column for. Reads and counts complete '
96+
+ 'filters on a name the queried object has no column for, and no report or dashboard '
97+
+ 'groups by, or aggregates over, such a name. Reads, counts and aggregates complete '
9298
+ 'with no `INVALID_FILTER` whose message says "names a column that object" or "names a '
93-
+ 'column the database could not resolve". Where a filter key was a relationship '
99+
+ 'column the database could not resolve", no `INVALID_FIELD` whose message says "has '
100+
+ 'no column for, so the aggregate never ran", and no aggregate refused with '
101+
+ '`DATABASE_ERROR` / 500 because the object\'s table is absent. Where a filter key was a relationship '
94102
+ 'traversal spelled as a dotted path, rewrite it against a column on the queried '
95103
+ 'object — the driver never resolved such a path and answered `[]`, so any list that '
96104
+ 'looked correct under one was already showing nothing.',

‎packages/spec/src/migrations/registry.ts‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9153,10 +9153,15 @@ const step18: MigrationStep = {
91539153
'a `where` naming a column the table does not have, on `driver-sql` (and its '
91549154
+ '`TursoDriver` / `SqliteWasmDriver` subclasses) — `find()` / `findOne()` answered '
91559155
+ '`[]` and `count()` threw the dialect\'s own error; both now refuse with '
9156-
+ '`INVALID_FILTER` / 400',
9156+
+ '`INVALID_FILTER` / 400. The `aggregate()` door of `TursoDriver`\'s remote face '
9157+
+ 'answered `[]` for a missing column or a missing table, and now refuses as the local '
9158+
+ 'face does: `INVALID_FILTER` / 400 for a `where` column the table lacks, '
9159+
+ '`INVALID_FIELD` / 400 for a `groupBy` or aggregation column the table lacks, and '
9160+
+ '`DATABASE_ERROR` / 500 for an object whose table is absent',
91579161
replacement:
91589162
'name a column the object actually has, or run schema sync so a recently declared '
9159-
+ 'field exists as a column before filtering on it. A caller that legitimately wants '
9163+
+ 'field exists as a column before filtering, grouping or aggregating on it, and so '
9164+
+ 'the object\'s table exists. A caller that legitimately wants '
91609165
+ '"no rows unless this matches" gets that from a predicate over a real column; there '
91619166
+ 'is no spelling of an unresolvable column that means "match nothing", which is '
91629167
+ 'exactly what the old empty list was mistaken for',
@@ -9233,9 +9238,12 @@ const step18: MigrationStep = {
92339238
+ 'caller never asked for. ADR-0112.',
92349239
acceptanceCriteria:
92359240
'No saved report `query.filter`, flow condition, sharing/permission rule or hook '
9236-
+ 'filters on a name the queried object has no column for. Reads and counts complete '
9241+
+ 'filters on a name the queried object has no column for, and no report or dashboard '
9242+
+ 'groups by, or aggregates over, such a name. Reads, counts and aggregates complete '
92379243
+ 'with no `INVALID_FILTER` whose message says "names a column that object" or "names a '
9238-
+ 'column the database could not resolve". Where a filter key was a relationship '
9244+
+ 'column the database could not resolve", no `INVALID_FIELD` whose message says "has '
9245+
+ 'no column for, so the aggregate never ran", and no aggregate refused with '
9246+
+ '`DATABASE_ERROR` / 500 because the object\'s table is absent. Where a filter key was a relationship '
92399247
+ 'traversal spelled as a dotted path, rewrite it against a column on the queried '
92409248
+ 'object — the driver never resolved such a path and answered `[]`, so any list that '
92419249
+ 'looked correct under one was already showing nothing.',

0 commit comments

Comments
 (0)