Repository navigation
feat(database): relational reads with defineRelations and findMany - #110
Conversation
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 49 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…imit A level with more keys than D1's 100 bindings failed to compile. Each level now sends one IN statement per batch that fits maxParameters next to its other bindings. Adds SQLite and D1 coverage and updates the docs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings in origin/main and MapleTechLabs#110's IN-list batching. The count level and the loaded level now share runBatched, so _count is split to the dialect's bound-value limit too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Brought up to date for merge (head
Verified locally: CI run 41472770236 failed, but not because of this PR. On 26.8, Left for the maintainer: the types do not require |
…te migrate tests 30s ClickHouse 26.2 returns 3 for `-5 % -4` under UNION ALL (26.8: -1). Record it as a known issue scoped to a negative constant divisor. pg-enums-uniques starts a PGlite per test, which timed out at 5s on CI runners busy with the fuzz suite (#110, #113, #114, #131). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
effect-orm has no relational read API. Each nested read becomes manual joins and grouping in app code.
Closes #79.
Part of #52.
Changes
Db.defineRelations(tables, (r) => ...)in/database:r.oneandr.manyrelations, declared over all tables in one callback, as Drizzle v2defineRelations. A relation names its target by key, so tables can point at each other. The types check the target, thefromandtocolumns, that both arestring | number | bigintkeys, and that a relation name is not a column name.Db.findMany(schema.table, { where, orderBy, limit, offset, with, crossTenant }): every column of the table plus each relation inwith, nested to any depth. Nested levels takewhere,orderByandwith. The row type follows thewithtree:manyis an array,oneis a row ornull.WHERE <to> IN (<keys from the level above>), then grouping in memory. A level with no keys sends nothing. Each level is an ordinary builder query, so each level decodes through its own row codec (a nestedtimestamptzis aDateTime.Utc) and has its owntenantScope.tenantColumnand the parent rows carry one tenant, the nested query gets<tenant column> = <that tenant>. Otherwise the level is cross-tenant, andrequireTenantScoperefuses it.crossTenant: truedeclares every level.design/relations.md: why one statement per level and not JSON aggregation, and the tenant rule.docs/relations.md, a typechecked example, and reference / README rows. Aminorchangeset.Left out
jsonb_agg, one statement). Each column type would need a JSON codec per dialect:int8loses precision as a JSON number,timestamptzandbyteachange format. It can come later as a second strategy behind the same API. Seedesign/relations.mdsection 3.columnsper level, alimitper parent on a nested level, composite keys, andfindFirst. Smallest slice first._countandsome/every/none(Relation counts and filters:_count,some,every,none#80).param.*in a nestedwhere:findManytakes no params.INlists (Postgres has a 65,535 bound-value limit). This belongs with Bound-parameter limits: chunkINlists and multi-row inserts #57.IN, so no dialect work is expected.Validation
bun run build: pass.bun run typecheck: pass (includessrc/database/relations.test-d.ts).bunx vitest run --testTimeout=60000 --hookTimeout=60000with live ClickHouse 26.8.2.7 (EFFECT_ORM_CLICKHOUSE_*set): 62 files, 1043 tests passed, 0 skipped.node scripts/check-doc-citations.mjs,node scripts/check-exports-documented.mjs,node scripts/check-doc-examples.mjs: pass.bun scripts/check-package.ts: pass.Need help on this PR? Tag
@codesmith-botwith what you need.