Commit 3e8b492
fix(driver-turso): the remote face refuses a missing table or column with the local face's code instead of answering [] (#20461)
Fixes #20424
Clause-②: no (narrowing)
Seat ruling: the amended claim 5872640432 on #20424 rules this change an
accept-set narrowing: `Clause-②: no (narrowing)`,
`@objectstack/driver-turso` `minor` with the BREAKING banner, and the
ADR-0087 disposition `not-required (already-registered
driver-sql-unresolvable-where-column-refused)`.
## Summary
On the Turso **remote** face, `aggregate`, `find`, `findOne` and `count`
now answer a missing table or a missing column the way the local face of
the same driver answers it over the same file: `DATABASE_ERROR` / 500,
`INVALID_FIELD` / 400 or `INVALID_FILTER` / 400, and never "no rows".
Two catches in `RemoteTransport` read the backend's `no such table` /
`no such column` as `[]`. They now let the error out, and
`TursoDriver`'s remote read exits classify it with the local face's
inherited seam, `SqlDriver.aggregateBackendFault`. No code is minted,
nothing in `driver-sql` or `spec` is edited, and no classification is
copied.
Measured head: `daad09aa1` (this branch after merging `origin/main` at
`3cf644938`). Patch round 1 changed only the changeset and this body,
then merged `origin/main` at `2304b1608`: head `3b56eb769`, with
`packages/drivers` byte-identical to `daad09aa1` (see "Patch round 1"
below).
## H1: reproduced on `main` before any change
Base `6e3e5462c`. The remote face is a `TursoDriver` over a real
`@libsql/client` on a `file:` database, and the local control is a
`TursoDriver` over the same file (a throwaway probe, not committed).
"Declared field, column absent" is a field the object declares and the
table lacks.
| read | local | remote |
|:--|:--|:--|
| row 1: `aggregate`, mapped table really absent | `DATABASE_ERROR` /
500 | `[]` |
| row 2: `aggregate` grouped by a declared field, column absent |
`INVALID_FIELD` / 400 | `[]` |
| row 3: `find` whose `where` names that field | `INVALID_FILTER` / 400
| `[]` |
| `findOne`, the same `where` | `INVALID_FILTER` / 400 | `null` |
| `find` with a projection and that `where` | `INVALID_FILTER` / 400 |
`[]` |
| `count`, the same `where` | `INVALID_FILTER` / 400 | `DATABASE_ERROR`
/ 500 |
| `aggregate` summing that field | `INVALID_FIELD` / 400 | `[]` |
| `aggregate` whose `where` names that field | `INVALID_FILTER` / 400 |
`[]` |
| `find` ordered by that field | the rows, unordered | `[]` |
| `find` projecting that field | the rows | the rows |
| `find`, mapped table absent | `DATABASE_ERROR` / 500 |
`DATABASE_ERROR` / 500 |
| controls: a real table and column | the rows | the rows |
H1 holds for all three card rows. **H4 holds too**: rows 1 to 3 answered
the same way for a managed object whose synced table or column was
dropped under it (`aggregate` `[]`, `aggregate` grouped `[]`, `find`
`[]`, where the local face refused with 500 / 400 / 400).
## H2: where the `[]` came from, and why each catch existed
- **`RemoteTransport.aggregate`'s catch.** `git log -S` finds it in the
method's first version, `101d5c345` ("Add i18n, analytics, turso
aggregate, auth date normalization", 2026-05-16). It had no comment, no
test and no card, and nothing in that commit names a first-boot or
not-yet-created table. The local face refuses both conditions (a missing
table since #11455, a missing column since #11541), so under the order's
rule there is no case to keep. The catch is removed.
- **`RemoteTransport.find`'s `$select` backstop.** It arrived with the
migration from the cloud repository (`06ba03627`). Its comment names one
case, a list view that projects fields the object lacks, and that case
is kept: the projection is still dropped and the rows answer. Its
terminal `return []` (no projection to drop, or the retry failed too)
was the pre-#8790 behaviour it mirrored. The local face's terminal
became a refusal in `716ac9bf8`, and this copy never followed. The unit
pin `still returns empty when even SELECT * fails (e.g. unknown table)`
asserted that `[]`, and its stub threw `no such column`, not a table
error: a real `no such table` was already rethrown by this catch. It is
replaced, with the same input and the opposite assertion.
## H3: the seam. The mechanism is falsified; the seam is reachable
The hypothesis was a field check that decides before the statement runs.
The local face has none for this condition: the ingress field checks
pass because the field *is* declared. The local face decides **after**
the statement runs, from the backend's error. `count` and `findRows`
send an unresolvable column to `unresolvableFilterColumnRefusal` and
everything else to `backendStatementFault`. `aggregate` goes through
`aggregateBackendFault`, which attributes the column to the groupBy, the
aggregation or the `where` from the caller's own query.
All of those compositions are `protected` on `SqlDriver`, and
`TursoDriver` inherits them. The class predicate they share,
`isUnresolvableColumnError`, is a module function that
`@objectstack/driver-sql` does not export. So:
- The remote `aggregate` exit calls `aggregateBackendFault(object,
query, error)` with the caller's own query. That is the local exit
verbatim.
- The remote `find` / `findOne` / `count` exits call the same method
with the `where` alone. With no groupBy and no aggregation, arm 1 cannot
fire. Arm 2 is `unresolvableFilterColumnRefusal(object, error, where)`,
and the terminal is `backendStatementFault`, which is the local exit.
The two can differ only on a recognised wording whose column name does
not parse, and that cannot arise on libSQL, whose only wording is `no
such column: NAME`.
- A remote door compiles and executes inside one transport call, while
the local face guards only the execution. So the new `remoteReadFault`
first returns anything that already declares a numeric `status`
unchanged. That is the same "is it already ours" gate
`backendStatementFault` applies, so the classifier sees what the local
one sees. The transport's own compile refusals and the timeout envelope
keep their answers.
The `where` handed over is the caller's own, from before
`toRemoteFilter` rewrote it, so the read-scope provenance marks decide
whether the column is named, exactly as they do locally.
## What changes
- `packages/drivers/driver-turso/src/remote-transport.ts`:
- `aggregate`: the catch is removed, and the backend's error leaves the
method.
- `find`: the ladder has the local face's two rungs, the projection and
then the ORDER BY (the new one), each rebuilt with the caller's `where`,
which neither drops. The terminal throws the last rung's error instead
of answering `[]`.
- `packages/drivers/driver-turso/src/turso-driver.ts`:
- `remoteReadExit(object, query, read)` ends in a new private
`remoteReadFault`: the status gate, then `aggregateBackendFault`.
- The remote `aggregate` arm now goes through that exit. `find`,
`findOne` and `count` pass the caller's `where`.
- One sentence in `refuseRemoteColumnMap`'s docblock moves to the past
tense: the `[]` it described is now a refusal, and the 501 refusal
stays. A parenthetical sentence is also added after it, saying so: that
read is now refused `INVALID_FILTER` / 400, and the 501 refusal stays
the answer.
- No change to `RemoteTransport`'s or `TursoDriver`'s published
signatures. The constructor (PR #20447) and the write doors are
untouched.
## Bounded in-place fixes, declared
1. **`count`'s remote exit.** For the same `where`, local answers
`INVALID_FILTER` / 400 and remote answers `DATABASE_ERROR` / 500. This
is not one of the card's three rows. It shares `remoteReadExit` with
`find`, and leaving it would reopen the split #8790 ruled out: a list
view calls both halves. ① Same class: a remote read exit answers an
unresolvable `where` column differently from the local face. ②
Mechanical, with a pinned shape: the local seam, called. ③ Inside the
claimed surface (the remote read arms of `turso-driver.ts`), and no
other claim holds those lines. ④ Same package tests.
2. **The ORDER BY rung.** Without it, removing the terminal `[]` turns
"ordered by a column the table lacks" from `[]` into an `INVALID_FILTER`
refusal that tells the caller their filter was wrong (measured, ablation
leg D below). The local face answers the rows, unordered (#3821). The
registered migration entry
`driver-sql-unresolvable-where-column-refused` already says the ladder
drops an ORDER BY and keeps the rows. ① The same `return []` line. ②
Mechanical: the local ladder's second rung. ③ The claimed catch, in the
claimed file. ④ Same package tests.
## Tests
- New `turso-local-remote-missing-table-column-parity.test.ts`: 22 cases
over a real `@libsql/client` `file:` database, with a local driver over
the same file.
- The card's three rows as local-and-remote pairs, for a federated and a
managed object (6 cases). Each asserts `code` + `status` on both faces.
- The neighbours: `findOne`, find with projection and `where`, `count`
(federated and managed), `sum` over the field, `aggregate` with that
`where`, and ORDER BY and projection recoveries answering the literal
rows on both faces (8 cases).
- Controls: literal answers for real tables and columns on both faces (6
cases). An undeclared aggregate function is refused with the same
envelope on both faces, with no statement sent. A synthetic
already-enveloped refusal passes the remote exit unchanged.
- `remote-transport-unknown-select.test.ts`: the `[]` pin is replaced as
described under H2.
- At the measured head `daad09aa1`: `pnpm --filter
@objectstack/driver-turso exec vitest run --maxWorkers=2` gave `Test
Files 75 passed (75)` and `Tests 2003 passed | 16 skipped (2019)`. `pnpm
--filter @objectstack/driver-turso typecheck` exited 0, and `tsc
--listFiles` includes both test files. Run after rebuilding the
dependency closure on the merged tree.
### Reverse verification
The fix was committed first (`a10647239`). Every leg went through `node
scripts/ablation-replace.mjs`: the anchor hit 1 → 0, the blob changed,
and the restore was proven by blob == HEAD and an empty `git diff HEAD`.
An outer trap re-verified the restore against the HEAD blob. The subject
resolves from `src/` through a relative import (vitest, no alias), so no
`dist/` is in the path. Suites: the new parity file, the unit file and
the #20107 external-object parity file (79 cases). Directions were
predicted in the test header before running:
- **A**, `aggregate`'s `[]` catch restored: **6 failed / 73 passed**,
exactly the six aggregate pairs.
- **B**, the find terminal back to `return []`: **5 failed / 74
passed**. That is the find, findOne and find-with-projection pairs, plus
the replaced unit pin. `count`, `aggregate` and ORDER BY stayed green.
- **C**, `remoteReadFault` reduced to `backendStatementFault`: **10
failed / 69 passed**, every 400 pair. Both missing-table pairs stayed
green, since they answer 500 on both faces anyway.
- **D**, the ORDER BY rung deleted: **1 failed / 78 passed**, the ORDER
BY case. The remote face refused with the unnamed `INVALID_FILTER`
wording ("A filter on object 'ext_t' names a column the database could
not resolve …") where the local face answered the rows.
- **E**, the status gate deleted: **1 failed / 78 passed**, the
synthetic case, re-worded as `INVALID_FIELD` / 400. The real
compile-refusal control stayed green, as predicted: no real refusal text
parses as a backend column fault today.
A first harness dry run was refused by the tool itself (its replacement
contained the anchor, so the anchor count did not drop), and it
restored. Nothing was measured there.
### Gates at `daad09aa1`
`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 63 commands (5 paths vs merge base
`3cf644938`). All 63 were run, and each exit code was written to a file
before any pipe.
Three gates first answered PREREQUISITE NOT MET (exit 3):
`check:dual-build-cjs-loads`, `check:lean-entry-closure` and
`check:type-check-debt`. I built every package with `pnpm turbo run
build --filter='./packages/*' --filter='./packages/*/*'
--concurrency=2`: 71 of 71 tasks succeeded. All three then exited 0. The
dist-sweeping `check:dts-closure` (71 packages),
`check:sourcemap-no-sources-content` (68) and `check:published-files`
were re-run on the full build and exited 0.
`--ran` answered: `63 derived famil(ies) accounted for — 63 run, 0
NOT-MEASURED (a DERIVED zero — all 63 recorded an exit code and none of
them is 3)`.
**Driver conformance ledger:**
- Before, at `6e3e5462c`: `OK — 50 covered cell(s), 0 in the DEBT
ledger, 0 exempt.`
- After, at `daad09aa1`: `OK — 50 covered cell(s), 0 in the DEBT ledger,
0 exempt.`
- The `driver-turso` row is `ok` in every column at both readings.
**Lint, narrowed:** `eslint --no-inline-config --format json` over the 4
changed `.ts` files gave 4 files, 0 errors and 0 warnings.
- The population comes from `eslint.config.mjs`:
`**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` minus its ignores.
- The file count is from the JSON.
- The effective `parserOptions` are `{ecmaVersion: latest, sourceType:
module}`, with no `project`. All 6 active rules are per-file AST rules,
so type-aware linting is off and this diff cannot move a verdict on any
untouched file. The full `pnpm lint` is CI's.
## Clause-② and the changeset
`.changeset/20424-turso-remote-missing-table-column-refused.md` ships
`@objectstack/driver-turso` `minor`, with `Clause-②: no (narrowing)`,
the **BREAKING** banner in the launch-window form
(`check-changeset-no-major` refuses `major`), a FROM → TO line with the
fix, and the ADR-0087 disposition `not-required (already-registered
driver-sql-unresolvable-where-column-refused)`. This follows the seat's
ruling in the amended claim 5872640432. The precedent the ruling reads:
- #8790 (`716ac9bf8`, `find` `[]` → `INVALID_FILTER` / 400, the same
shape as row 3) declared **BREAKING accept-set narrowing**: `minor`,
with an ADR-0087 `registered` disposition and the migration entry
`driver-sql-unresolvable-where-column-refused`.
- That registered entry's `surface` already names "`driver-sql` (and its
`TursoDriver` / `SqliteWasmDriver` subclasses)" and prescribes this
change's remedy (name a real column, or run schema sync). So no new
entry is owed; the `aggregate` legs are the same drifted-schema family
with the same remedy. Remote-face users meet the refusal for the first
time here, so the banner is owed.
- #11541 (`ef52884a8`, `aggregate` 500 → `INVALID_FIELD` / 400) shipped
as `patch` with no narrowing: a refusal that changed its code, not an
accept set.
- `RemoteTransport.find` and `RemoteTransport.aggregate`, exported from
the package root, now raise the backend's error where they answered
`[]`. The changeset says so.
## Files
- `.changeset/20424-turso-remote-missing-table-column-refused.md` (+33 /
-0)
- `packages/drivers/driver-turso/src/remote-transport.ts` (+45 / -22)
- `packages/drivers/driver-turso/src/turso-driver.ts` (+90 / -15)
-
`packages/drivers/driver-turso/src/remote-transport-unknown-select.test.ts`
(+15 / -4)
-
`packages/drivers/driver-turso/src/turso-local-remote-missing-table-column-parity.test.ts`
(+345 / -0)
-
`packages/drivers/driver-turso/src/turso-local-remote-external-object-parity.test.ts`
(+3 / -2, a header prediction line only)
In total, +531 / -43 over 6 files, under the 5,000-line threshold. No
governed surface.
## Patch round 1
The seat's amended claim 5872640432 answered the round-0 open question
with B, and accepted the two bounded in-place fixes and the H3 route.
This round changes only the changeset and this body, with no code or
test change:
- The changeset: `patch` → `minor`; `Clause-②: no` → `Clause-②: no
(narrowing)`; the **BREAKING** banner; the ADR-0087 marker `not-required
(already-registered driver-sql-unresolvable-where-column-refused)` with
its reason; a FROM → TO line naming the refusals, the fix, and
`RemoteTransport.find` / `aggregate` now raising where they answered
`[]`.
- This body: the `Clause-②` line, the seat-ruling line under it, the
"Clause-② and the changeset" section, the Files line and one Acceptance
note.
- `origin/main` merged at `2304b1608` (a true merge commit, five
incoming commits, none on a `driver-*` path). Head `3b56eb769`. `git
diff daad09a 3b56eb7 -- packages/drivers` is empty. After rebuilding
the dependency closure on the merged tree: `pnpm --filter
@objectstack/driver-turso exec vitest run --maxWorkers=2` gave `Test
Files 75 passed (75)` and `Tests 2003 passed | 16 skipped (2019)`, and
`typecheck` exited 0.
- Changeset gates at `3b56eb769`, each exit code recorded before any
pipe: `pnpm check:adr-0087-registration` exit 0; `node
scripts/check-changeset-no-major.mjs --base origin/main --event` (this
body) exit 0; `node scripts/check-empty-changeset.mjs --base
origin/main` exit 0.
## Patch round 2
After the at-tier review 5873239611 (PASS at `3b56eb769`) and the seat's
amended claim 5873267997, this round is text only plus a merge, with no
logic or test-assertion change:
- `remote-transport.ts`, the `$`-prefixed-key comment: its sentence
saying `find()`'s `no such column` backstop "swallows the error into
`[]` anyway" under `SQLITE_DQS=0` was made false by this PR. It now says
the backstop refuses, as the local face does (`INVALID_FILTER` / 400),
and that it used to answer `[]`.
- `turso-local-remote-external-object-parity.test.ts`, the #20107
suite's header prediction for its first ablation leg: `aggregate` now
refuses the missing table as `DATABASE_ERROR` / 500, instead of
answering `[]` in place of the sum.
- `origin/main` merged at `acd009521` (a true merge commit), carrying PR
#20447 (`bea6d2ea3`, the constructor region of `turso-driver.ts`). The
merge was clean. Head `0c47b7bbe`.
- On the combined tree, after rebuilding the dependency closure: `pnpm
--filter @objectstack/driver-turso test` gave `Test Files 76 passed
(76)` and `Tests 2036 passed | 18 skipped (2054)` (the added file and
cases are #20447's), and `typecheck` exited 0.
- `dispatch-gates --commands` at `0c47b7bbe` derived the same 63
commands. After a full package build (71 of 71), all 63 exited 0 on the
first pass. `--ran`: `63 derived famil(ies) accounted for — 63 run, 0
NOT-MEASURED (a DERIVED zero — all 63 recorded an exit code and none of
them is 3)`. Driver conformance: `OK — 50 covered cell(s), 0 in the DEBT
ledger, 0 exempt.` Narrowed eslint over the 5 changed `.ts` files: 0
errors, 0 warnings.
- Not changed, outside the claimed surface: the same #20107 header's
third prediction ("A filter on the renamed field answers `[]`") is also
out of date after this PR. With the column-map refusal deleted, that
filter would now be refused `INVALID_FILTER` / 400. It is prediction
prose, and no assertion depends on it.
## Acceptance notes
- **The shared predicate is not exported.** `isUnresolvableColumnError`
is not exported from `@objectstack/driver-sql`, so the remote find/count
exit reaches it through `aggregateBackendFault` with a `where`-only
query. An exported predicate, or a protected `where`-exit on `SqlDriver`
shared by `count` and `findRows`, would be the plainer seam. This card
may not edit `driver-sql`. Carrier: none.
- **The transport keeps an inline recognizer.** `RemoteTransport.find`
still recognises the unresolvable-column class inline (`no such column`,
or `column` + `does not exist`) to gate its ladder. That pre-existing
copy of the predicate lacks the MySQL arm, which libSQL never speaks.
- **An unmeasured edge.** If a ladder rung fails with an error that is
not a column error, the local face refuses `INVALID_FILTER` (unnamed
wording) and this face answers `DATABASE_ERROR` / 500. No producer is
known.
- **Standalone transport use.** `RemoteTransport.find` and
`RemoteTransport.aggregate`, used on their own without `TursoDriver`,
now raise the backend's error where they answered `[]`. The changeset
says so.
- **`main` moved after the measured merge.** Round 0 did not re-merge
`b28550818` (additive in `packages/spec` only). Patch round 1 merged
`origin/main` at `2304b1608` (five commits, none on a `driver-*` path).
It then moved once more, to `fbeb56e4b` (one `packages/spec` test pin,
`turbo.json` and `scripts/cross-package-test-inputs.mjs`, no `driver-*`
path). Patch round 2 merged `origin/main` at `acd009521`, which carries
both. PR #20447 (#20200) landed as `bea6d2ea3`, is merged here, and
driver-turso was re-tested on the combined tree (see "Patch round 2").
---
_Generated by [Claude
Code](https://claude.ai/code/session_01N8TPEsoJxPsdSdNKGnNGEN)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 75b2169 commit 3e8b492
6 files changed
Lines changed: 531 additions & 43 deletions
Lines changed: 33 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
Lines changed: 15 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
54 | | - | |
55 | | - | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
56 | 63 | | |
57 | 64 | | |
58 | | - | |
59 | | - | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
60 | 71 | | |
61 | 72 | | |
62 | 73 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1412 | 1412 | | |
1413 | 1413 | | |
1414 | 1414 | | |
| 1415 | + | |
| 1416 | + | |
| 1417 | + | |
| 1418 | + | |
| 1419 | + | |
| 1420 | + | |
| 1421 | + | |
| 1422 | + | |
| 1423 | + | |
| 1424 | + | |
| 1425 | + | |
| 1426 | + | |
| 1427 | + | |
| 1428 | + | |
1415 | 1429 | | |
| 1430 | + | |
| 1431 | + | |
| 1432 | + | |
| 1433 | + | |
| 1434 | + | |
| 1435 | + | |
| 1436 | + | |
1416 | 1437 | | |
1417 | | - | |
| 1438 | + | |
1418 | 1439 | | |
1419 | 1440 | | |
1420 | | - | |
1421 | | - | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
1422 | 1445 | | |
1423 | 1446 | | |
1424 | | - | |
| 1447 | + | |
1425 | 1448 | | |
1426 | 1449 | | |
1427 | 1450 | | |
| |||
1626 | 1649 | | |
1627 | 1650 | | |
1628 | 1651 | | |
1629 | | - | |
1630 | | - | |
1631 | | - | |
1632 | | - | |
1633 | | - | |
1634 | | - | |
1635 | | - | |
1636 | | - | |
1637 | | - | |
1638 | | - | |
1639 | | - | |
1640 | | - | |
1641 | | - | |
| 1652 | + | |
| 1653 | + | |
| 1654 | + | |
| 1655 | + | |
| 1656 | + | |
| 1657 | + | |
| 1658 | + | |
| 1659 | + | |
| 1660 | + | |
| 1661 | + | |
| 1662 | + | |
| 1663 | + | |
1642 | 1664 | | |
1643 | 1665 | | |
1644 | 1666 | | |
| |||
2883 | 2905 | | |
2884 | 2906 | | |
2885 | 2907 | | |
2886 | | - | |
2887 | | - | |
2888 | | - | |
2889 | | - | |
2890 | | - | |
| 2908 | + | |
| 2909 | + | |
| 2910 | + | |
| 2911 | + | |
| 2912 | + | |
| 2913 | + | |
2891 | 2914 | | |
2892 | 2915 | | |
2893 | 2916 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
673 | 673 | | |
674 | 674 | | |
675 | 675 | | |
676 | | - | |
677 | | - | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
678 | 680 | | |
679 | 681 | | |
680 | 682 | | |
| |||
1918 | 1920 | | |
1919 | 1921 | | |
1920 | 1922 | | |
1921 | | - | |
| 1923 | + | |
| 1924 | + | |
| 1925 | + | |
| 1926 | + | |
1922 | 1927 | | |
1923 | 1928 | | |
1924 | 1929 | | |
| |||
1934 | 1939 | | |
1935 | 1940 | | |
1936 | 1941 | | |
1937 | | - | |
| 1942 | + | |
| 1943 | + | |
| 1944 | + | |
| 1945 | + | |
1938 | 1946 | | |
1939 | 1947 | | |
1940 | 1948 | | |
| |||
2061 | 2069 | | |
2062 | 2070 | | |
2063 | 2071 | | |
2064 | | - | |
2065 | | - | |
2066 | | - | |
2067 | | - | |
2068 | | - | |
2069 | | - | |
2070 | | - | |
| 2072 | + | |
| 2073 | + | |
| 2074 | + | |
| 2075 | + | |
| 2076 | + | |
| 2077 | + | |
| 2078 | + | |
2071 | 2079 | | |
2072 | | - | |
| 2080 | + | |
2073 | 2081 | | |
2074 | 2082 | | |
2075 | 2083 | | |
2076 | | - | |
| 2084 | + | |
2077 | 2085 | | |
2078 | 2086 | | |
2079 | 2087 | | |
| 2088 | + | |
| 2089 | + | |
| 2090 | + | |
| 2091 | + | |
| 2092 | + | |
| 2093 | + | |
| 2094 | + | |
| 2095 | + | |
| 2096 | + | |
| 2097 | + | |
| 2098 | + | |
| 2099 | + | |
| 2100 | + | |
| 2101 | + | |
| 2102 | + | |
| 2103 | + | |
| 2104 | + | |
| 2105 | + | |
| 2106 | + | |
| 2107 | + | |
| 2108 | + | |
| 2109 | + | |
| 2110 | + | |
| 2111 | + | |
| 2112 | + | |
| 2113 | + | |
| 2114 | + | |
| 2115 | + | |
| 2116 | + | |
| 2117 | + | |
| 2118 | + | |
| 2119 | + | |
| 2120 | + | |
| 2121 | + | |
| 2122 | + | |
| 2123 | + | |
| 2124 | + | |
| 2125 | + | |
| 2126 | + | |
| 2127 | + | |
| 2128 | + | |
| 2129 | + | |
| 2130 | + | |
| 2131 | + | |
| 2132 | + | |
| 2133 | + | |
| 2134 | + | |
| 2135 | + | |
| 2136 | + | |
| 2137 | + | |
| 2138 | + | |
| 2139 | + | |
| 2140 | + | |
| 2141 | + | |
| 2142 | + | |
| 2143 | + | |
| 2144 | + | |
| 2145 | + | |
| 2146 | + | |
| 2147 | + | |
| 2148 | + | |
| 2149 | + | |
2080 | 2150 | | |
2081 | 2151 | | |
2082 | 2152 | | |
| |||
2274 | 2344 | | |
2275 | 2345 | | |
2276 | 2346 | | |
2277 | | - | |
| 2347 | + | |
2278 | 2348 | | |
2279 | 2349 | | |
2280 | 2350 | | |
| |||
2305 | 2375 | | |
2306 | 2376 | | |
2307 | 2377 | | |
2308 | | - | |
| 2378 | + | |
| 2379 | + | |
| 2380 | + | |
| 2381 | + | |
| 2382 | + | |
| 2383 | + | |
2309 | 2384 | | |
2310 | 2385 | | |
2311 | 2386 | | |
| |||
0 commit comments