okmodel 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -1131
- package/dist/adapters/capabilities.d.ts +35 -0
- package/dist/adapters/failure.d.ts +13 -2
- package/dist/adapters/lazy-errors.d.ts +22 -0
- package/dist/adapters/pg/bun-sql.d.ts +53 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +54 -3
- package/dist/adapters/pg/bunsql.d.ts +15 -2
- package/dist/adapters/pg/cursor.d.ts +17 -0
- package/dist/adapters/pg/neon-extra.d.ts +18 -0
- package/dist/adapters/pg/neon.d.ts +104 -0
- package/dist/adapters/pg/no-inflight-timeout.d.ts +11 -8
- package/dist/adapters/pg/nodepostgres-extra.d.ts +22 -1
- package/dist/adapters/pg/nodepostgres.d.ts +12 -0
- package/dist/adapters/pg/pglite-wire.d.ts +24 -0
- package/dist/adapters/pg/pglite.d.ts +10 -0
- package/dist/adapters/pg/postgres-extra.d.ts +27 -11
- package/dist/adapters/pg/reserved.d.ts +42 -0
- package/dist/adapters/pg/session.d.ts +0 -18
- package/dist/contracts/connection.d.ts +7 -6
- package/dist/contracts/error.d.ts +1 -1
- package/dist/dialects/pg/floor.d.ts +68 -0
- package/dist/dialects/pg/fn/index.d.ts +39 -1
- package/dist/dialects/pg/fn/index.js +118 -26
- package/dist/dialects/pg/index.d.ts +8 -1
- package/dist/dialects/pg/index.js +435 -170
- package/dist/dialects/pg/introspect.d.ts +11 -0
- package/dist/dialects/pg/keys.d.ts +11 -8
- package/dist/dialects/pg/model.d.ts +40 -0
- package/dist/dialects/pg/morph.d.ts +43 -0
- package/dist/dialects/pg/operator-fit.d.ts +2 -2
- package/dist/dialects/pg/operators.d.ts +14 -7
- package/dist/dialects/pg/ops/bucket.d.ts +65 -0
- package/dist/dialects/pg/ops/fragment.d.ts +119 -0
- package/dist/dialects/pg/ops/inc.d.ts +2 -2
- package/dist/dialects/pg/ops/lane.d.ts +49 -0
- package/dist/dialects/pg/ops/matches.d.ts +9 -12
- package/dist/dialects/pg/ops/relevance.d.ts +13 -0
- package/dist/dialects/pg/ops/search-query.d.ts +22 -0
- package/dist/dialects/pg/ops/window.d.ts +103 -0
- package/dist/dialects/pg/preset.d.ts +1 -1
- package/dist/dialects/pg/relations.d.ts +100 -3
- package/dist/dialects/pg/schema.d.ts +31 -3
- package/dist/dialects/pg/view/client.d.ts +14 -6
- package/dist/dialects/pg/view/index.d.ts +73 -1
- package/dist/dialects/pg/view/index.js +156 -5
- package/dist/dialects/pg/view/scratch.d.ts +8 -5
- package/dist/runtime/aggregate.d.ts +8 -2
- package/dist/runtime/bucket-group.d.ts +70 -0
- package/dist/runtime/conflict.d.ts +22 -4
- package/dist/runtime/include.d.ts +0 -8
- package/dist/runtime/inflight.d.ts +1 -1
- package/dist/runtime/otel.d.ts +105 -0
- package/dist/runtime/otel.js +97 -0
- package/dist/runtime/page.d.ts +4 -1
- package/dist/runtime/pg/bun.js +12 -6
- package/dist/runtime/pg/neon.d.ts +38 -0
- package/dist/runtime/pg/neon.js +64 -0
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.d.ts +1 -0
- package/dist/runtime/pg/pglite.js +9 -9
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +95 -5
- package/dist/runtime/read-stream.d.ts +13 -16
- package/dist/runtime/result-name.d.ts +17 -0
- package/dist/runtime/server-check.d.ts +3 -3
- package/dist/runtime/sort-bind.d.ts +21 -0
- package/dist/runtime/sort.d.ts +56 -0
- package/dist/runtime/sql-fragment.d.ts +43 -0
- package/dist/runtime/sync.d.ts +70 -0
- package/dist/runtime/tenancy/index.js +15 -13
- package/dist/runtime/text-search.d.ts +20 -0
- package/dist/runtime/topology.d.ts +1 -1
- package/dist/runtime/traits/index.d.ts +80 -0
- package/dist/runtime/traits/index.js +184 -21
- package/dist/runtime/tree.d.ts +38 -0
- package/dist/runtime/types.d.ts +232 -22
- package/dist/runtime/validate/index.js +4 -4
- package/dist/runtime/version.d.ts +39 -0
- package/dist/runtime/window.d.ts +21 -0
- package/dist/runtime/write.d.ts +54 -2
- package/dist/shared/{929h19xp.js → 0wrea3jq.js} +141 -13
- package/dist/shared/{qq3899ht.js → 12z7aznj.js} +243 -14
- package/dist/shared/{1z04fa85.js → 14x60fbf.js} +12 -57
- package/dist/shared/{ek2wt2dz.js → 16kvjebh.js} +4 -4
- package/dist/shared/{wynzeggs.js → 195pzzzz.js} +8 -8
- package/dist/shared/1d9q9cv2.js +312 -0
- package/dist/shared/2c13q96h.js +18 -0
- package/dist/shared/{b4v57v3x.js → 2d3xq4ps.js} +2 -2
- package/dist/shared/{1f0xa3cb.js → 3449rcae.js} +5 -5
- package/dist/shared/{wkme6tep.js → 35q0n9tz.js} +8 -16
- package/dist/shared/3bb7wsqt.js +99 -0
- package/dist/shared/3t6kw83m.js +249 -0
- package/dist/shared/{5j36z8dn.js → 4m6hskg8.js} +39 -70
- package/dist/shared/{n076ydsc.js → 4vbf83xx.js} +69 -28
- package/dist/shared/{vmfkhszw.js → 63f4ksbz.js} +33 -26
- package/dist/shared/{c58secgj.js → 63qtkrca.js} +38 -4
- package/dist/shared/6m78c8ss.js +6 -0
- package/dist/shared/{x3jc53kg.js → 760ppr76.js} +15 -7
- package/dist/shared/7ghwamrf.js +40 -0
- package/dist/shared/7kms6fvj.js +20 -0
- package/dist/shared/7n7ddwt4.js +6 -0
- package/dist/shared/9a4ae4p8.js +31 -0
- package/dist/shared/{hazqqecq.js → 9dr2qnx7.js} +63 -34
- package/dist/shared/{h15jx9bc.js → 9dvh1dr6.js} +1 -1
- package/dist/shared/a62rb2da.js +13 -0
- package/dist/shared/{cgbamx3e.js → ae4j5f42.js} +23 -4
- package/dist/shared/agsfb86s.js +233 -0
- package/dist/shared/{8x72s86k.js → b6d6p0zc.js} +13 -7
- package/dist/shared/{ag4c7516.js → b76b8d95.js} +2 -2
- package/dist/shared/{j60w0dvr.js → bah9nbg3.js} +58 -38
- package/dist/shared/bnby0esn.js +10 -0
- package/dist/shared/bsek72fg.js +225 -0
- package/dist/shared/{2cg3wnxc.js → bxas03mq.js} +608 -141
- package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
- package/dist/shared/{gwn6v667.js → cnkky55j.js} +25 -14
- package/dist/shared/{dk8v79p3.js → d5nmj7vv.js} +1 -1
- package/dist/shared/{ttmg09vd.js → dpc2r7rb.js} +8 -8
- package/dist/shared/dzj09cye.js +10 -0
- package/dist/shared/{sbdme3vy.js → e8zyaqvj.js} +60 -10
- package/dist/shared/{2jd1sn0e.js → ecn8mfdq.js} +6 -6
- package/dist/shared/exn3sd90.js +359 -0
- package/dist/shared/{t3g0k88x.js → f4jy1j7x.js} +39 -22
- package/dist/shared/{y2t3jktd.js → fjpnhqan.js} +20 -13
- package/dist/shared/g5yc06ka.js +272 -0
- package/dist/shared/ga9j92qj.js +25 -0
- package/dist/shared/{3fqwmr09.js → hfqmpasr.js} +6 -6
- package/dist/shared/{wt5rzv1h.js → hm5f8jby.js} +7 -7
- package/dist/shared/{ys0xzyaj.js → hqpxf4a4.js} +224 -19
- package/dist/shared/jebgrkeq.js +179 -0
- package/dist/shared/{09p049xa.js → jp36k7dp.js} +44 -16
- package/dist/shared/jx2m62cs.js +96 -0
- package/dist/shared/{r11n8grd.js → k86n8vq3.js} +7 -4
- package/dist/shared/{2z7wv5tj.js → kgwp4jdd.js} +56 -35
- package/dist/shared/{knmes2kh.js → kj9d8maq.js} +1 -1
- package/dist/shared/{g90m9b0g.js → m4xff2a6.js} +6 -5
- package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
- package/dist/shared/mfedzr74.js +145 -0
- package/dist/shared/{f0f1n281.js → mkrn359n.js} +60 -11
- package/dist/shared/{p248q79y.js → mnvjvqyp.js} +10 -10
- package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
- package/dist/shared/{4az561fn.js → mtw6jz76.js} +8 -23
- package/dist/shared/n05z9nwz.js +313 -0
- package/dist/shared/{pjr6xrm5.js → n0jmpgj1.js} +20 -17
- package/dist/shared/{p6bjzq9q.js → n41w4fbz.js} +14 -6
- package/dist/shared/{b3awxn7h.js → n454kcnw.js} +1 -1
- package/dist/shared/n7kg8mmx.js +61 -0
- package/dist/shared/nbw1z4yd.js +18 -0
- package/dist/shared/needfe47.js +66 -0
- package/dist/shared/{1nw1f3vs.js → njga14v4.js} +9 -9
- package/dist/shared/{5yv4k6a6.js → nmnsgj7x.js} +145 -3
- package/dist/shared/{vjpnzwjz.js → p3xbdcvt.js} +14 -18
- package/dist/shared/p5nh3r8q.js +622 -0
- package/dist/shared/{nx9hh281.js → pan0370z.js} +13 -12
- package/dist/shared/q0cqt2sp.js +12 -0
- package/dist/shared/qd9hhd8f.js +37 -0
- package/dist/shared/{mb2ycs1p.js → qfw14tna.js} +15 -15
- package/dist/shared/{9s0ypp87.js → sjk86yrx.js} +1 -1
- package/dist/shared/th3be82n.js +208 -0
- package/dist/shared/{ed0b8k4s.js → typ3vy7t.js} +1 -1
- package/dist/shared/{5d8t84hg.js → v1wad97q.js} +14 -14
- package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
- package/dist/shared/{9628a9xt.js → vk7rag46.js} +1 -1
- package/dist/shared/{ze4hxsmy.js → w9ejzaqf.js} +1 -1
- package/dist/shared/{q3j1tq7a.js → wcrheftc.js} +148 -23
- package/dist/shared/wvdjznah.js +213 -0
- package/dist/shared/wz2a78mp.js +8 -0
- package/dist/shared/xfhe73sb.js +436 -0
- package/dist/shared/{r1fdd0f6.js → z581d7ny.js} +5 -2
- package/dist/shared/{8etn7d8w.js → z7s6fpxv.js} +1 -1
- package/dist/shared/{32cnm7kn.js → zbqbmmrp.js} +76 -40
- package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
- package/dist/shared/{xq0mvhts.js → zgex00fd.js} +6 -6
- package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
- package/dist/shared/zq1he88x.js +155 -0
- package/dist/tooling/cli.js +26 -13
- package/dist/tooling/driver-run.js +4971 -0
- package/dist/tooling/driver-test.d.ts +36 -0
- package/dist/tooling/migrate/commands.d.ts +2 -2
- package/dist/tooling/migrate/engine.d.ts +3 -2
- package/dist/tooling/migrate/index.js +9 -9
- package/dist/tooling/migrate/project.d.ts +3 -0
- package/dist/tooling/shared/03k6res6.js +210 -0
- package/dist/tooling/shared/08kemxjd.js +10 -0
- package/dist/tooling/shared/2revefqt.js +209 -0
- package/dist/tooling/shared/2wtvc7rw.js +1425 -0
- package/dist/tooling/shared/345tbc2k.js +16 -0
- package/dist/tooling/shared/3m1hkg7z.js +344 -0
- package/dist/tooling/shared/3rrw5w8f.js +81 -0
- package/dist/tooling/shared/3tq8pnb8.js +131 -0
- package/dist/tooling/shared/417zdsk7.js +194 -0
- package/dist/tooling/shared/4d2w25vw.js +40 -0
- package/dist/tooling/shared/54tqkxja.js +51 -0
- package/dist/tooling/shared/5bvw2nev.js +12 -0
- package/dist/tooling/shared/6nyfyw70.js +231 -0
- package/dist/tooling/shared/72fyg4zv.js +160 -0
- package/dist/tooling/shared/733a1tq3.js +38 -0
- package/dist/tooling/shared/7ae7rjmn.js +20 -0
- package/dist/tooling/shared/7kms6fvj.js +20 -0
- package/dist/tooling/shared/8sqrsw3s.js +49 -0
- package/dist/tooling/shared/96ps4g1z.js +32 -0
- package/dist/tooling/shared/9kazs5p6.js +195 -0
- package/dist/tooling/shared/9xzm7hjg.js +38 -0
- package/dist/tooling/shared/a6pp9d12.js +49 -0
- package/dist/tooling/shared/a7q7t4n3.js +22 -0
- package/dist/tooling/shared/aftb2mwr.js +18 -0
- package/dist/tooling/shared/bz2dqhab.js +311 -0
- package/dist/tooling/shared/cmptmb4f.js +12 -0
- package/dist/tooling/shared/ddjtfgnx.js +177 -0
- package/dist/tooling/shared/djydjpqt.js +261 -0
- package/dist/tooling/shared/dw08f3m8.js +9 -0
- package/dist/tooling/shared/dy672fz6.js +16 -0
- package/dist/tooling/shared/dzx85q70.js +66 -0
- package/dist/tooling/shared/ec71zqgt.js +270 -0
- package/dist/{shared/d5azex6s.js → tooling/shared/ep8zh3bk.js} +1 -1
- package/dist/tooling/shared/f9mphxej.js +3789 -0
- package/dist/tooling/shared/fb9k2qwd.js +89 -0
- package/dist/tooling/shared/g9ad4n80.js +211 -0
- package/dist/tooling/shared/gfvtj6d0.js +94 -0
- package/dist/tooling/shared/gmcf9cxf.js +294 -0
- package/dist/tooling/shared/htnaj77v.js +17 -0
- package/dist/tooling/shared/j9t5s12a.js +7 -0
- package/dist/tooling/shared/jne7b93p.js +42 -0
- package/dist/tooling/shared/ma2340rx.js +118 -0
- package/dist/tooling/shared/mtrqn2hn.js +505 -0
- package/dist/tooling/shared/n4jqhpqz.js +27 -0
- package/dist/tooling/shared/nf7jmhfa.js +20 -0
- package/dist/tooling/shared/p7f08ktn.js +332 -0
- package/dist/tooling/shared/ppnnnvj8.js +13 -0
- package/dist/tooling/shared/pqy21k24.js +312 -0
- package/dist/tooling/shared/pw8fgahx.js +69 -0
- package/dist/tooling/shared/pwsytxm5.js +17 -0
- package/dist/tooling/shared/rf83gr2d.js +94 -0
- package/dist/tooling/shared/rq5kk8j6.js +401 -0
- package/dist/tooling/shared/rs1jb051.js +12 -0
- package/dist/tooling/shared/smn6kz1p.js +157 -0
- package/dist/tooling/shared/spk1jg3r.js +1696 -0
- package/dist/tooling/shared/tn8gay14.js +143 -0
- package/dist/tooling/shared/vraj6d74.js +42 -0
- package/dist/tooling/shared/vs0t6qt8.js +64 -0
- package/dist/tooling/shared/vx86qjv8.js +150 -0
- package/dist/tooling/shared/w7qe8sj1.js +140 -0
- package/dist/tooling/shared/wt7j7nf6.js +15 -0
- package/dist/tooling/shared/wwnekq5n.js +6 -0
- package/dist/tooling/shared/xhrnjch9.js +185 -0
- package/dist/tooling/shared/xjs6zqtc.js +190 -0
- package/dist/tooling/shared/y031jct9.js +16 -0
- package/dist/tooling/shared/y5656f0e.js +233 -0
- package/dist/tooling/shared/yfr8hzhm.js +604 -0
- package/dist/tooling/shared/yk9mp7vb.js +250 -0
- package/dist/tooling/shared/yw30vnq2.js +139 -0
- package/dist/tooling/shared/z8d7ptht.js +618 -0
- package/dist/tooling/shared/zhwnfyb2.js +9 -0
- package/dist/tooling/shared/zvnhh1n0.js +198 -0
- package/dist/tooling/testing/index.js +3 -3
- package/package.json +17 -3
- package/dist/shared/3qnhc7w5.js +0 -38
- package/dist/shared/7m88x3e9.js +0 -45
- package/dist/shared/8dqhth8c.js +0 -12
- package/dist/shared/j3rkk835.js +0 -99
- package/dist/shared/k68eedmy.js +0 -85
- package/dist/shared/venqrjna.js +0 -216
- package/dist/shared/wxr8cwns.js +0 -6
- package/dist/shared/y34a8714.js +0 -150
- package/dist/shared/zm0mafk4.js +0 -92
- package/dist/shared/zy8r7qvz.js +0 -116
- package/dist/shared/{ywr8hmey.js → 606g0nbf.js} +3 -3
- package/dist/shared/{rpycarcr.js → gcefca6p.js} +4 -4
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `one`, `many`, and `
|
|
2
|
+
* `one`, `many`, `manyThrough`, and `morph` relations.
|
|
3
3
|
*
|
|
4
4
|
* They name a table. `schema()` resolves the foreign key. An ambiguous key
|
|
5
|
-
* is OKM1021. `manyThrough`
|
|
6
|
-
*
|
|
5
|
+
* is OKM1021. `manyThrough` and `morph` carry their own resolvers, so a schema
|
|
6
|
+
* that never calls one does not pay for it.
|
|
7
7
|
*/
|
|
8
8
|
import type { RelationModel } from "./model.js";
|
|
9
9
|
/** A to-one relation. `field` is the local foreign key when the table has several. */
|
|
@@ -28,6 +28,26 @@ export type RelationEdge = {
|
|
|
28
28
|
/** Referenced SQL names, in the same order. */
|
|
29
29
|
readonly remote: readonly string[];
|
|
30
30
|
};
|
|
31
|
+
/** A table as a morph resolver reads it. Foreign-key resolvers ignore this. */
|
|
32
|
+
export type RelationDescribed = {
|
|
33
|
+
readonly tsName: string;
|
|
34
|
+
readonly sqlName: string;
|
|
35
|
+
/** Primary-key SQL names, in catalog order. */
|
|
36
|
+
readonly primary: readonly string[];
|
|
37
|
+
readonly byField: ReadonlyMap<string, {
|
|
38
|
+
readonly field: string;
|
|
39
|
+
readonly sqlName: string;
|
|
40
|
+
readonly dataType: string;
|
|
41
|
+
readonly nullable: boolean;
|
|
42
|
+
}>;
|
|
43
|
+
readonly bySql: ReadonlyMap<string, {
|
|
44
|
+
readonly field: string;
|
|
45
|
+
readonly sqlName: string;
|
|
46
|
+
readonly dataType: string;
|
|
47
|
+
}>;
|
|
48
|
+
/** Relation calls stored on the table, before they are resolved. */
|
|
49
|
+
readonly relationOptions: unknown;
|
|
50
|
+
};
|
|
31
51
|
/** What a relation's own resolver reads from `schema()`. */
|
|
32
52
|
export type RelationScope = {
|
|
33
53
|
/** The table that declares the relation. */
|
|
@@ -37,6 +57,19 @@ export type RelationScope = {
|
|
|
37
57
|
readonly edges: readonly RelationEdge[];
|
|
38
58
|
/** Every table name in the schema, sorted. */
|
|
39
59
|
readonly tables: readonly string[];
|
|
60
|
+
/**
|
|
61
|
+
* Looks up a table's columns.
|
|
62
|
+
*
|
|
63
|
+
* Present when `schema()` resolves relations. A resolver that only needs
|
|
64
|
+
* foreign keys ignores it. The value is the prepared table; morph narrows it.
|
|
65
|
+
*/
|
|
66
|
+
readonly describe?: (table: string) => unknown;
|
|
67
|
+
/**
|
|
68
|
+
* Tenant fields tenancy added to a primary key.
|
|
69
|
+
*
|
|
70
|
+
* A morph id matches the key that remains. Absent when the schema has no tenancy.
|
|
71
|
+
*/
|
|
72
|
+
readonly scopeFields?: readonly string[];
|
|
40
73
|
};
|
|
41
74
|
/**
|
|
42
75
|
* A to-many relation through a join table.
|
|
@@ -100,3 +133,67 @@ export declare function isRelationCall(value: unknown): value is RelationCall;
|
|
|
100
133
|
export declare function manyThrough<const TTable extends string>(table: TTable, options: {
|
|
101
134
|
readonly through: string;
|
|
102
135
|
} & ThroughKeys): ManyThroughRelation<TTable>;
|
|
136
|
+
/**
|
|
137
|
+
* A polymorphic to-one relation.
|
|
138
|
+
*
|
|
139
|
+
* `name` is the column stem: the table declares `${name}Type` and `${name}Id`.
|
|
140
|
+
* The type column stores a target table name. The id column stores that
|
|
141
|
+
* table's primary key. Include returns one row of the matching target, or
|
|
142
|
+
* null, as a flat union discriminated by the type field.
|
|
143
|
+
*
|
|
144
|
+
* @typeParam TName - Column stem
|
|
145
|
+
* @typeParam TTargets - Closed list of target tables
|
|
146
|
+
* @param name - Column stem
|
|
147
|
+
* @param targets - Target table names, each with one primary-key column
|
|
148
|
+
* @returns The relation `schema()` resolves
|
|
149
|
+
*/
|
|
150
|
+
export declare function morph<const TName extends string, const TTargets extends readonly [string, ...string[]]>(name: TName, targets: TTargets): MorphRelation<TName, TTargets>;
|
|
151
|
+
/**
|
|
152
|
+
* The reverse of {@link morph}: many owner rows that point at this table.
|
|
153
|
+
*
|
|
154
|
+
* Declare it on each target. `table` is the table that holds the type and id
|
|
155
|
+
* columns, and `name` is the stem passed to `morph`.
|
|
156
|
+
*
|
|
157
|
+
* @typeParam TTable - Table that holds the type and id columns
|
|
158
|
+
* @param table - That table
|
|
159
|
+
* @param name - Column stem
|
|
160
|
+
* @returns The relation `schema()` resolves
|
|
161
|
+
*/
|
|
162
|
+
export declare function morphMany<const TTable extends string>(table: TTable, name: string): MorphManyRelation<TTable>;
|
|
163
|
+
/**
|
|
164
|
+
* A polymorphic relation declared with {@link morph}.
|
|
165
|
+
*
|
|
166
|
+
* It is a {@link OneRelation} so the relation map stays assignable. `morph`
|
|
167
|
+
* is what include reads to build the union.
|
|
168
|
+
*/
|
|
169
|
+
export type MorphRelation<TName extends string = string, TTargets extends readonly string[] = readonly string[]> = OneRelation<TTargets[number]> & {
|
|
170
|
+
readonly morph: {
|
|
171
|
+
readonly name: TName;
|
|
172
|
+
readonly targets: TTargets;
|
|
173
|
+
readonly typeField: `${TName}Type`;
|
|
174
|
+
};
|
|
175
|
+
readonly resolve: (scope: RelationScope) => RelationModel;
|
|
176
|
+
};
|
|
177
|
+
/**
|
|
178
|
+
* The reverse many declared with {@link morphMany}.
|
|
179
|
+
*
|
|
180
|
+
* It is a {@link ManyRelation}, so include, `has`, `none`, and `every` read it as one.
|
|
181
|
+
*/
|
|
182
|
+
export type MorphManyRelation<TTable extends string = string> = ManyRelation<TTable> & {
|
|
183
|
+
readonly resolve: (scope: RelationScope) => RelationModel;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* Sets a morph's type and id columns together.
|
|
187
|
+
*
|
|
188
|
+
* @typeParam TName - Column stem
|
|
189
|
+
* @typeParam TType - Target table name
|
|
190
|
+
* @param name - Column stem passed to `morph`
|
|
191
|
+
* @param type - Target table name
|
|
192
|
+
* @param id - That table's primary key
|
|
193
|
+
* @returns The two fields an insert or update spreads in
|
|
194
|
+
*/
|
|
195
|
+
export declare function morphTo<const TName extends string, const TType extends string>(name: TName, type: TType, id: string): {
|
|
196
|
+
readonly [K in `${TName}Type`]: TType;
|
|
197
|
+
} & {
|
|
198
|
+
readonly [K in `${TName}Id`]: string;
|
|
199
|
+
};
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { Catalog } from "../../contracts/catalog/types.js";
|
|
7
7
|
import { type ClientGenerator } from "../../contracts/generator.js";
|
|
8
|
+
import { type PostgresMajor } from "./floor.js";
|
|
8
9
|
import { type SchemaHook, type TableModel } from "./model.js";
|
|
9
10
|
import type { FieldsOfList, HasArchive, PresetsOfList, Trait } from "./trait.js";
|
|
10
11
|
import { type ColumnTenancy, type TenantFields } from "./tenancy.js";
|
|
@@ -15,8 +16,16 @@ export type SchemaCodecs = {
|
|
|
15
16
|
readonly numeric: "string" | "number";
|
|
16
17
|
readonly timestamps: "temporal";
|
|
17
18
|
};
|
|
18
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Engine requirement recorded for connect.
|
|
21
|
+
*
|
|
22
|
+
* The stored value is `>=` and a major. `minPostgres` and the deprecated
|
|
23
|
+
* string form normalise to the same object.
|
|
24
|
+
*/
|
|
19
25
|
export type SchemaRequires = {
|
|
26
|
+
/**
|
|
27
|
+
* @deprecated Use `minPostgres`. `">=17"` is the same floor as `minPostgres: 17`.
|
|
28
|
+
*/
|
|
20
29
|
readonly postgres?: string;
|
|
21
30
|
};
|
|
22
31
|
/**
|
|
@@ -28,6 +37,15 @@ export type SchemaRequires = {
|
|
|
28
37
|
*/
|
|
29
38
|
export type SchemaInput<TTables extends readonly AnyTable[]> = {
|
|
30
39
|
readonly tables: TTables;
|
|
40
|
+
/**
|
|
41
|
+
* Oldest Postgres major this schema runs on.
|
|
42
|
+
*
|
|
43
|
+
* Omitted means 15. A feature that needs a newer major is refused here.
|
|
44
|
+
*/
|
|
45
|
+
readonly minPostgres?: PostgresMajor;
|
|
46
|
+
/**
|
|
47
|
+
* @deprecated Use {@link SchemaInput.minPostgres}. `">=17"` is the same floor as `minPostgres: 17`.
|
|
48
|
+
*/
|
|
31
49
|
readonly requires?: SchemaRequires;
|
|
32
50
|
readonly casing?: "snake";
|
|
33
51
|
readonly codecs?: {
|
|
@@ -39,8 +57,13 @@ export type SchemaInput<TTables extends readonly AnyTable[]> = {
|
|
|
39
57
|
/**
|
|
40
58
|
* What a bare `t.id()` means.
|
|
41
59
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
60
|
+
* Omitted, the database default is `gen_random_uuid()`. `"uuidv4"` stores
|
|
61
|
+
* the same function. `"uuidv7"` stores `uuidv7()` and needs Postgres 18
|
|
62
|
+
* (`minPostgres: 18`).
|
|
63
|
+
* Pick `uuidv7` for a large write-heavy table: the ids are time-ordered
|
|
64
|
+
* and the index stays local. Random ids are fine elsewhere. A client
|
|
65
|
+
* generator is filled on insert and stays out of the catalog. A column
|
|
66
|
+
* option wins.
|
|
44
67
|
*/
|
|
45
68
|
readonly defaults?: {
|
|
46
69
|
readonly id?: "uuidv7" | "uuidv4" | ClientGenerator<string>;
|
|
@@ -80,6 +103,11 @@ export type BuiltSchema<TTables extends readonly AnyTable[]> = {
|
|
|
80
103
|
readonly types: "emitted" | "inferred";
|
|
81
104
|
readonly casing: "snake" | undefined;
|
|
82
105
|
readonly codecs: SchemaCodecs;
|
|
106
|
+
/**
|
|
107
|
+
* Declared floor, normalised to `>=` and a major.
|
|
108
|
+
*
|
|
109
|
+
* Absent when the schema names no floor. Connect then uses 15.
|
|
110
|
+
*/
|
|
83
111
|
readonly requires: SchemaRequires | undefined;
|
|
84
112
|
readonly tables: TTables;
|
|
85
113
|
/**
|
|
@@ -28,21 +28,29 @@ export declare function viewMentions(query: string, name: string): boolean;
|
|
|
28
28
|
export type ViewInstall = (model: {
|
|
29
29
|
[name: string]: TableModel;
|
|
30
30
|
}, tenancy: ColumnTenancy | undefined, tables: readonly AnyTable[], casing: "snake" | undefined, scoped: Set<string>) => void;
|
|
31
|
+
/** A value, or a function `install` calls once casing is known. */
|
|
32
|
+
type ColumnSource = readonly {
|
|
33
|
+
readonly name: string;
|
|
34
|
+
readonly type: string;
|
|
35
|
+
}[] | (() => readonly {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly type: string;
|
|
38
|
+
}[]);
|
|
39
|
+
/** A query string, or a function `install` calls once casing is known. */
|
|
40
|
+
type QuerySource = string | (() => string);
|
|
31
41
|
/**
|
|
32
42
|
* Client name, read model, and the hook that moves the handle under `views`.
|
|
33
43
|
*
|
|
34
44
|
* @param name - SQL name of the view
|
|
35
|
-
* @param columns - Declared output columns
|
|
36
|
-
* @param query - Author SQL
|
|
45
|
+
* @param columns - Declared output columns, or a getter `install` calls
|
|
46
|
+
* @param query - Author SQL, or a getter `install` calls
|
|
37
47
|
* @param tenancy - `global("reason")`, when the view opts out
|
|
38
48
|
* @param refresh - `plain` stores no `refresh`. A materialized view is `blocking` or `concurrently`
|
|
39
49
|
* @returns Methods stored on the declaration
|
|
40
50
|
*/
|
|
41
|
-
export declare function viewClient(name: string, columns:
|
|
42
|
-
readonly name: string;
|
|
43
|
-
readonly type: string;
|
|
44
|
-
}[], query: string, tenancy: unknown, refresh?: "plain" | "blocking" | "concurrently"): {
|
|
51
|
+
export declare function viewClient(name: string, columns: ColumnSource, query: QuerySource, tenancy: unknown, refresh?: "plain" | "blocking" | "concurrently"): {
|
|
45
52
|
readonly field: string;
|
|
46
53
|
readonly install: ViewInstall;
|
|
47
54
|
readonly hook: SchemaHook;
|
|
48
55
|
};
|
|
56
|
+
export {};
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import type { CatalogObject } from "../../../contracts/catalog/types.js";
|
|
10
10
|
import type { SchemaHook } from "../model.js";
|
|
11
|
-
import type
|
|
11
|
+
import { type AnyTable, type SqlText } from "../table.js";
|
|
12
12
|
import { type ViewInstall } from "./client.js";
|
|
13
13
|
/** One declared output column. `type` is the Postgres type name. */
|
|
14
14
|
export type ViewColumnInput = {
|
|
@@ -29,6 +29,66 @@ export type ViewOptions = {
|
|
|
29
29
|
*/
|
|
30
30
|
readonly tenancy?: unknown;
|
|
31
31
|
};
|
|
32
|
+
/** Output columns of {@link ViewFrom.from}. A tuple keeps each name. */
|
|
33
|
+
type TupleColumns<K extends readonly string[]> = K extends readonly [] ? readonly [] : K extends readonly [infer H extends string, ...infer R extends readonly string[]] ? readonly [{
|
|
34
|
+
readonly name: H;
|
|
35
|
+
readonly type: string;
|
|
36
|
+
}, ...TupleColumns<R>] : readonly {
|
|
37
|
+
readonly name: K[number];
|
|
38
|
+
readonly type: string;
|
|
39
|
+
}[];
|
|
40
|
+
/** Every column of a table, when `from` is not given a list. */
|
|
41
|
+
type AllColumns<T extends AnyTable> = readonly {
|
|
42
|
+
readonly name: keyof T["columns"] & string;
|
|
43
|
+
readonly type: string;
|
|
44
|
+
}[];
|
|
45
|
+
/**
|
|
46
|
+
* The value `(q) => q.from(...)` returns.
|
|
47
|
+
*
|
|
48
|
+
* @typeParam C - Output columns, for `db.views`
|
|
49
|
+
*/
|
|
50
|
+
export type ViewBuilt<C extends readonly ViewColumnInput[] = readonly ViewColumnInput[]> = {
|
|
51
|
+
/** Declared columns. Present for the type. The catalog uses the SQL names. */
|
|
52
|
+
readonly "~columns"?: C;
|
|
53
|
+
/**
|
|
54
|
+
* Adds a WHERE clause.
|
|
55
|
+
*
|
|
56
|
+
* The text is stored as written, the same way `query` is.
|
|
57
|
+
*
|
|
58
|
+
* @param predicate - SQL after `where`
|
|
59
|
+
* @returns The same view, with the clause
|
|
60
|
+
*/
|
|
61
|
+
where(predicate: SqlText | string): ViewBuilt<C>;
|
|
62
|
+
/**
|
|
63
|
+
* Opts the view out of tenancy.
|
|
64
|
+
*
|
|
65
|
+
* Pass `global("reason")` from `okmodel/tenancy`.
|
|
66
|
+
*
|
|
67
|
+
* @param mark - `global("reason")`
|
|
68
|
+
* @returns The same view, opted out
|
|
69
|
+
*/
|
|
70
|
+
tenancy(mark: unknown): ViewBuilt<C>;
|
|
71
|
+
};
|
|
72
|
+
/**
|
|
73
|
+
* The argument of `view(name, (q) => q.from(...))`.
|
|
74
|
+
*/
|
|
75
|
+
export type ViewFrom = {
|
|
76
|
+
/**
|
|
77
|
+
* Selects every column of `table`.
|
|
78
|
+
*
|
|
79
|
+
* @param table - Source table
|
|
80
|
+
* @returns The view query
|
|
81
|
+
*/
|
|
82
|
+
from<const T extends AnyTable>(table: T): ViewBuilt<AllColumns<T>>;
|
|
83
|
+
/**
|
|
84
|
+
* Selects `columns` from `table`, in that order.
|
|
85
|
+
*
|
|
86
|
+
* @param table - Source table
|
|
87
|
+
* @param columns - Output columns. Names are the table's fields
|
|
88
|
+
* @returns The view query
|
|
89
|
+
*/
|
|
90
|
+
from<const T extends AnyTable, const K extends readonly (keyof T["columns"] & string)[]>(table: T, columns: K): ViewBuilt<TupleColumns<K>>;
|
|
91
|
+
};
|
|
32
92
|
/**
|
|
33
93
|
* One declared view.
|
|
34
94
|
*
|
|
@@ -117,6 +177,17 @@ export type MaterializedViewDeclaration<N extends string = string, C extends rea
|
|
|
117
177
|
export declare function view<const N extends string, const C extends readonly ViewColumnInput[]>(name: N, options: ViewOptions & {
|
|
118
178
|
readonly columns: C;
|
|
119
179
|
}): ViewDeclaration<N, C>;
|
|
180
|
+
/**
|
|
181
|
+
* Declares a view from a table.
|
|
182
|
+
*
|
|
183
|
+
* `view(name, (q) => q.from(table))` selects that table's columns. Pass a
|
|
184
|
+
* column list to project. `.where` adds a predicate. `.tenancy` opts out.
|
|
185
|
+
*
|
|
186
|
+
* @param name - View name
|
|
187
|
+
* @param build - `q.from(...)`
|
|
188
|
+
* @returns The definition object `schema({ views })` stores
|
|
189
|
+
*/
|
|
190
|
+
export declare function view<const N extends string, const C extends readonly ViewColumnInput[]>(name: N, build: (q: ViewFrom) => ViewBuilt<C>): ViewDeclaration<N, C>;
|
|
120
191
|
/**
|
|
121
192
|
* Declares a materialized view.
|
|
122
193
|
*
|
|
@@ -130,3 +201,4 @@ export declare function view<const N extends string, const C extends readonly Vi
|
|
|
130
201
|
export declare function materializedView<const N extends string, const C extends readonly ViewColumnInput[]>(name: N, options: MaterializedViewOptions & {
|
|
131
202
|
readonly columns: C;
|
|
132
203
|
}): MaterializedViewDeclaration<N, C>;
|
|
204
|
+
export {};
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
viewClient
|
|
3
|
-
} from "../../../shared/x3jc53kg.js";
|
|
4
1
|
import {
|
|
5
2
|
viewObject,
|
|
6
3
|
materializedViewObject,
|
|
7
4
|
materializedViewIndex
|
|
8
|
-
} from "../../../shared/
|
|
5
|
+
} from "../../../shared/12z7aznj.js";
|
|
6
|
+
import {
|
|
7
|
+
viewClient
|
|
8
|
+
} from "../../../shared/760ppr76.js";
|
|
9
|
+
import {
|
|
10
|
+
snakeCase
|
|
11
|
+
} from "../../../shared/gcefca6p.js";
|
|
12
|
+
import {
|
|
13
|
+
formatType
|
|
14
|
+
} from "../../../shared/606g0nbf.js";
|
|
15
|
+
import {
|
|
16
|
+
quoteIdent
|
|
17
|
+
} from "../../../shared/sjk86yrx.js";
|
|
9
18
|
import {
|
|
10
19
|
staticNamespace2
|
|
11
20
|
} from "../../../shared/358zsv4r.js";
|
|
@@ -14,7 +23,11 @@ import {
|
|
|
14
23
|
} from "../../../shared/52szzakm.js";
|
|
15
24
|
|
|
16
25
|
// src/dialects/pg/view/index.ts
|
|
17
|
-
|
|
26
|
+
var BUILT = Symbol("okmodel.view.from");
|
|
27
|
+
function view(name, source) {
|
|
28
|
+
if (typeof source === "function")
|
|
29
|
+
return viewFrom(name, source);
|
|
30
|
+
const options = source;
|
|
18
31
|
const schema = options.schema ?? "public";
|
|
19
32
|
const columns = options.columns.map((column) => ({ name: column.name, dataType: column.type }));
|
|
20
33
|
const query = bodyText(options.query);
|
|
@@ -100,6 +113,144 @@ function materializedView(name, options) {
|
|
|
100
113
|
}
|
|
101
114
|
};
|
|
102
115
|
}
|
|
116
|
+
var viewFromApi = {
|
|
117
|
+
from(table, columns) {
|
|
118
|
+
return finish({
|
|
119
|
+
[BUILT]: true,
|
|
120
|
+
table,
|
|
121
|
+
picked: columns,
|
|
122
|
+
predicate: undefined,
|
|
123
|
+
mark: undefined
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
function viewFrom(name, build) {
|
|
128
|
+
const built = build(viewFromApi);
|
|
129
|
+
if (!isRecipe(built)) {
|
|
130
|
+
throw new OkmError2("OKM1121", `View ${name} must return q.from(...).`, {
|
|
131
|
+
fix: { summary: "Return q.from(table), and chain where() or tenancy() on that value." }
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const recipe = built;
|
|
135
|
+
let casingMode;
|
|
136
|
+
let rendered;
|
|
137
|
+
const render = () => {
|
|
138
|
+
rendered ??= renderQuery(name, recipe, casingMode);
|
|
139
|
+
return rendered;
|
|
140
|
+
};
|
|
141
|
+
const bound = viewClient(name, () => render().columns, () => render().query, recipe.mark, "plain");
|
|
142
|
+
let securityInvoker = false;
|
|
143
|
+
return {
|
|
144
|
+
name,
|
|
145
|
+
schema: "public",
|
|
146
|
+
"~kind": "view",
|
|
147
|
+
install(model, tenancy, tables, casing, scoped) {
|
|
148
|
+
casingMode = casing;
|
|
149
|
+
rendered = undefined;
|
|
150
|
+
bound.install(model, tenancy, tables, casing, scoped);
|
|
151
|
+
securityInvoker = tenancy?.strategy === "rls" && scoped.has(name);
|
|
152
|
+
},
|
|
153
|
+
hook: bound.hook,
|
|
154
|
+
contribute(peers, builtObjects) {
|
|
155
|
+
assertPeers(peers);
|
|
156
|
+
assertNoTable(builtObjects, name);
|
|
157
|
+
const query = render().query;
|
|
158
|
+
const columns = render().columns.map((column) => ({
|
|
159
|
+
name: column.name,
|
|
160
|
+
dataType: column.type
|
|
161
|
+
}));
|
|
162
|
+
const provenance = { origin: "file", name };
|
|
163
|
+
return [
|
|
164
|
+
viewObject({
|
|
165
|
+
namespace: staticNamespace2("public"),
|
|
166
|
+
name,
|
|
167
|
+
columns,
|
|
168
|
+
query,
|
|
169
|
+
provenance,
|
|
170
|
+
...securityInvoker ? { securityInvoker: true } : {}
|
|
171
|
+
})
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
function isRecipe(value) {
|
|
177
|
+
return typeof value === "object" && value !== null && BUILT in value;
|
|
178
|
+
}
|
|
179
|
+
function finish(recipe) {
|
|
180
|
+
const built = {
|
|
181
|
+
...recipe,
|
|
182
|
+
where(predicate) {
|
|
183
|
+
return finish({ ...recipe, predicate: bodyText(predicate) });
|
|
184
|
+
},
|
|
185
|
+
tenancy(mark) {
|
|
186
|
+
return finish({ ...recipe, mark });
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
return built;
|
|
190
|
+
}
|
|
191
|
+
function renderQuery(name, recipe, casing) {
|
|
192
|
+
const fields = recipe.picked ?? Object.keys(recipe.table.columns);
|
|
193
|
+
if (fields.length === 0) {
|
|
194
|
+
throw new OkmError2("OKM1120", `View ${name} selects no columns.`, {
|
|
195
|
+
fix: { summary: "Pick at least one column of the table." }
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
const columns = [];
|
|
199
|
+
const selected = [];
|
|
200
|
+
for (const field of fields) {
|
|
201
|
+
const column = recipe.table.columns[field];
|
|
202
|
+
if (column === undefined || typeof column !== "object" || column === null) {
|
|
203
|
+
throw new OkmError2("OKM1020", `View ${name} names ${field}, which ${recipe.table.name} does not have.`, { fix: { summary: "Pass a column of that table." } });
|
|
204
|
+
}
|
|
205
|
+
const sqlName = columnSql(column, field, casing);
|
|
206
|
+
columns.push({ name: sqlName, type: columnType(column, field) });
|
|
207
|
+
selected.push(quoteIdent(sqlName));
|
|
208
|
+
}
|
|
209
|
+
const tableName = tableSql(recipe.table, casing);
|
|
210
|
+
let query = `select ${selected.join(", ")} from ${quoteIdent(tableName)}`;
|
|
211
|
+
if (recipe.predicate !== undefined && recipe.predicate.trim().length > 0) {
|
|
212
|
+
query += ` where ${recipe.predicate}`;
|
|
213
|
+
}
|
|
214
|
+
return { query, columns };
|
|
215
|
+
}
|
|
216
|
+
function tableSql(table, casing) {
|
|
217
|
+
const options = table.options;
|
|
218
|
+
if (typeof options?.sqlName === "string" && options.sqlName.length > 0)
|
|
219
|
+
return options.sqlName;
|
|
220
|
+
return casing === "snake" ? snakeCase(table.name) : table.name;
|
|
221
|
+
}
|
|
222
|
+
function columnSql(column, field, casing) {
|
|
223
|
+
const state = readState(column, field);
|
|
224
|
+
if (state.sqlName !== undefined && state.sqlName.length > 0)
|
|
225
|
+
return state.sqlName;
|
|
226
|
+
return casing === "snake" ? snakeCase(field) : field;
|
|
227
|
+
}
|
|
228
|
+
function columnType(column, field) {
|
|
229
|
+
const state = readState(column, field);
|
|
230
|
+
return formatType(state.baseType, state.dims);
|
|
231
|
+
}
|
|
232
|
+
function readState(column, field) {
|
|
233
|
+
if (!("state" in column)) {
|
|
234
|
+
throw new OkmError2("OKM1020", `Column ${field} has no type.`, {
|
|
235
|
+
fix: { summary: "Pass a column built with t." }
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
const state = column.state;
|
|
239
|
+
if (typeof state !== "object" || state === null || !("baseType" in state)) {
|
|
240
|
+
throw new OkmError2("OKM1020", `Column ${field} has no type.`, {
|
|
241
|
+
fix: { summary: "Pass a column built with t." }
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
const baseType = state.baseType;
|
|
245
|
+
const dims = "dims" in state && typeof state.dims === "number" ? state.dims : 0;
|
|
246
|
+
const sqlName = "sqlName" in state && typeof state.sqlName === "string" ? state.sqlName : undefined;
|
|
247
|
+
if (typeof baseType !== "string" || baseType.length === 0) {
|
|
248
|
+
throw new OkmError2("OKM1020", `Column ${field} has no type.`, {
|
|
249
|
+
fix: { summary: "Pass a column built with t." }
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
return { baseType, dims, sqlName };
|
|
253
|
+
}
|
|
103
254
|
function bodyText(body) {
|
|
104
255
|
return typeof body === "string" ? body : body.text;
|
|
105
256
|
}
|
|
@@ -4,19 +4,22 @@
|
|
|
4
4
|
* Domain and enum types from the catalog are created there, then the tables,
|
|
5
5
|
* then the functions a view may call, then each view. `pg_get_viewdef`
|
|
6
6
|
* replaces the author query and `pg_depend` supplies column edges (D117).
|
|
7
|
-
*
|
|
7
|
+
* A `BEGIN ATOMIC` body is replaced with the `pg_get_functiondef` block, so a
|
|
8
|
+
* plan from the live catalog does not treat Postgres's reprint as a change
|
|
9
|
+
* (D273). The scratch schema is dropped before this returns. Plans never use it.
|
|
8
10
|
*/
|
|
9
11
|
import type { Catalog } from "../../../contracts/catalog/types.js";
|
|
10
|
-
import type
|
|
12
|
+
import { type CatalogQuery } from "../introspect.js";
|
|
11
13
|
/**
|
|
12
14
|
* Reads dependencies and reprints for every view in `source`.
|
|
13
15
|
*
|
|
14
16
|
* The returned catalog matches what introspection prints for those views
|
|
15
17
|
* when the same query is applied. A declared column list that disagrees
|
|
16
|
-
* with the database is OKM1020.
|
|
18
|
+
* with the database is OKM1020. A `BEGIN ATOMIC` function body is the
|
|
19
|
+
* server reprint, including an argument qualifier such as `by_id.n`.
|
|
17
20
|
*
|
|
18
21
|
* @param runner - Database connection. Statements share its session
|
|
19
|
-
* @param source - Catalog whose views are still author SQL
|
|
20
|
-
* @returns A catalog whose views carry the reprint
|
|
22
|
+
* @param source - Catalog whose views and atomic bodies are still author SQL
|
|
23
|
+
* @returns A catalog whose views and atomic bodies carry the reprint
|
|
21
24
|
*/
|
|
22
25
|
export declare function sealViews(runner: CatalogQuery, source: Catalog): Promise<Catalog>;
|
|
@@ -7,8 +7,14 @@
|
|
|
7
7
|
* every aggregate exactly as they apply to a `find`. This module loads on the
|
|
8
8
|
* first `aggregate()`.
|
|
9
9
|
*
|
|
10
|
-
* Not here: `having`,
|
|
11
|
-
* cannot be grouped or aggregated, so an aggregate
|
|
10
|
+
* Not here: `having`, ordering by an aggregate, and the time-zone date helpers
|
|
11
|
+
* (tool 5). A hidden column cannot be grouped or aggregated, so an aggregate
|
|
12
|
+
* never shows what a read hides.
|
|
13
|
+
*
|
|
14
|
+
* `bucket()` is a tagged helper. Its validation and SQL load in their own
|
|
15
|
+
* chunk, and only when `groupBy` contains one. A request object cannot create
|
|
16
|
+
* one. A NULL timestamp is one group: the result key is present and the value
|
|
17
|
+
* is null.
|
|
12
18
|
*/
|
|
13
19
|
import { type Mods, type Session } from "./client.js";
|
|
14
20
|
import { type ArchiveView } from "./plan.js";
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time buckets inside `aggregate` `groupBy` (spec §10, §13 tool 4).
|
|
3
|
+
*
|
|
4
|
+
* This module loads on the first `aggregate()` whose `groupBy` contains a
|
|
5
|
+
* `bucket()`. A plain aggregate does not import it. A NULL timestamp is one
|
|
6
|
+
* group: the `as` key is present and the value is null.
|
|
7
|
+
*/
|
|
8
|
+
import type { ColumnModel } from "../dialects/pg/model.js";
|
|
9
|
+
import { type BucketUnit } from "../dialects/pg/ops/bucket.js";
|
|
10
|
+
import { type Built, type Indexed, type Sink } from "./plan.js";
|
|
11
|
+
/** One bucket in a group list. */
|
|
12
|
+
export type BucketGroup = {
|
|
13
|
+
readonly kind: "bucket";
|
|
14
|
+
readonly column: ColumnModel;
|
|
15
|
+
readonly unit: BucketUnit;
|
|
16
|
+
readonly tz: string | undefined;
|
|
17
|
+
readonly as: string;
|
|
18
|
+
readonly shift: 0 | 1 | 2;
|
|
19
|
+
readonly clock: boolean;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* What the aggregate chunk calls after this module loads.
|
|
23
|
+
*
|
|
24
|
+
* The aggregate chunk does not import this file. It receives the functions
|
|
25
|
+
* from `import()`.
|
|
26
|
+
*/
|
|
27
|
+
export type BucketChunk = {
|
|
28
|
+
readBucket(table: Indexed, value: unknown, fields: ReadonlySet<string>, aliases: Set<string>): BucketGroup;
|
|
29
|
+
writeBucket(sink: Sink, outputs: Built | undefined, wrote: {
|
|
30
|
+
at: number;
|
|
31
|
+
}, group: BucketGroup): void;
|
|
32
|
+
writeGrouped(sink: Sink, names: readonly string[], orderBy: unknown): void;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Reads one `bucket()` group.
|
|
36
|
+
*
|
|
37
|
+
* Refuses a bad unit, zone, week start, or result name before any SQL.
|
|
38
|
+
* `__proto__`, `constructor`, `toString`, and `hasOwnProperty` are refused.
|
|
39
|
+
* `timestamptz` needs an IANA `tz`. `date` refuses `tz`. `timestamp` without
|
|
40
|
+
* a zone is refused.
|
|
41
|
+
*
|
|
42
|
+
* @param table - The grouped table
|
|
43
|
+
* @param value - One `groupBy` entry
|
|
44
|
+
* @param fields - Plain group fields already seen
|
|
45
|
+
* @param aliases - Bucket result names already seen
|
|
46
|
+
* @returns The group the statement writes
|
|
47
|
+
*/
|
|
48
|
+
export declare function readBucket(table: Indexed, value: unknown, fields: ReadonlySet<string>, aliases: Set<string>): BucketGroup;
|
|
49
|
+
/**
|
|
50
|
+
* Writes one bucket expression into the select list.
|
|
51
|
+
*
|
|
52
|
+
* @param sink - Statement buffer
|
|
53
|
+
* @param outputs - Decode plan, absent while only marking
|
|
54
|
+
* @param wrote - How many select items are already written
|
|
55
|
+
* @param group - The bucket
|
|
56
|
+
*/
|
|
57
|
+
export declare function writeBucket(sink: Sink, outputs: Built | undefined, wrote: {
|
|
58
|
+
at: number;
|
|
59
|
+
}, group: BucketGroup): void;
|
|
60
|
+
/**
|
|
61
|
+
* Groups and orders by select-list ordinals.
|
|
62
|
+
*
|
|
63
|
+
* The bucket expression is written once, in the select list. A second copy
|
|
64
|
+
* would bind a new `$n`, and Postgres treats that as a different expression.
|
|
65
|
+
*
|
|
66
|
+
* @param sink - Statement buffer
|
|
67
|
+
* @param names - Group names, in select order
|
|
68
|
+
* @param orderBy - Caller order, or the default group order
|
|
69
|
+
*/
|
|
70
|
+
export declare function writeGrouped(sink: Sink, names: readonly string[], orderBy: unknown): void;
|
|
@@ -23,18 +23,36 @@ export type ConflictPlan = {
|
|
|
23
23
|
*/
|
|
24
24
|
export declare function readConflict(table: Indexed, value: unknown, allow?: ReadonlySet<string>, tenantKey?: string | readonly string[]): ConflictPlan | undefined;
|
|
25
25
|
/**
|
|
26
|
-
* Appends the conflict clause
|
|
26
|
+
* Appends the conflict clause.
|
|
27
|
+
*
|
|
28
|
+
* First-or-create is `on conflict do nothing`. It does not read the existing
|
|
29
|
+
* row here: that lookup is a later statement, so it sees a row another
|
|
30
|
+
* transaction committed while this insert waited (D246).
|
|
27
31
|
*
|
|
28
32
|
* @param head - `insert into … values …` without `returning`
|
|
29
33
|
* @param returning - ` returning …`, including the leading space
|
|
30
34
|
* @param params - Insert parameters
|
|
31
35
|
* @param plan - Conflict plan
|
|
32
36
|
* @param table - Target table
|
|
33
|
-
* @param returningColumns - Columns in `returning`
|
|
34
|
-
* @param keys - Encoded conflict-key tuples, one per inserted row. Used by `return`
|
|
35
37
|
* @returns Statement text and parameters
|
|
36
38
|
*/
|
|
37
|
-
export declare function finishInsert(head: string, returning: string, params: readonly (string | null)[], plan: ConflictPlan, table: Indexed
|
|
39
|
+
export declare function finishInsert(head: string, returning: string, params: readonly (string | null)[], plan: ConflictPlan, table: Indexed): {
|
|
40
|
+
readonly text: string;
|
|
41
|
+
readonly params: (string | null)[];
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Reads rows a first-or-create insert did not return.
|
|
45
|
+
*
|
|
46
|
+
* The conflict target is the same unique, including the tenant key. A partial
|
|
47
|
+
* unique on an archivable table only matches the active row.
|
|
48
|
+
*
|
|
49
|
+
* @param table - Target table
|
|
50
|
+
* @param keys - Conflict columns, in constraint order
|
|
51
|
+
* @param returningColumns - Columns the insert returns, in that order
|
|
52
|
+
* @param keyRows - Encoded conflict-key tuples that the insert did not return
|
|
53
|
+
* @returns One select
|
|
54
|
+
*/
|
|
55
|
+
export declare function lookupExisting(table: Indexed, keys: readonly ColumnModel[], returningColumns: readonly ColumnModel[], keyRows: readonly (readonly (string | null)[])[]): {
|
|
38
56
|
readonly text: string;
|
|
39
57
|
readonly params: (string | null)[];
|
|
40
58
|
};
|