okmodel 0.7.0 → 0.9.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 +14 -0
- package/dist/adapters/capabilities.d.ts +32 -0
- package/dist/adapters/failure.d.ts +1 -1
- package/dist/adapters/pg/bun-sql.d.ts +53 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +1 -1
- package/dist/adapters/pg/bunsql.d.ts +1 -1
- 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 +1 -1
- package/dist/contracts/error.d.ts +1 -1
- package/dist/dialects/pg/ext/btree-gin.d.ts +26 -0
- package/dist/dialects/pg/ext/btree-gin.js +20 -0
- package/dist/dialects/pg/ext/btree-gist.d.ts +26 -0
- package/dist/dialects/pg/ext/btree-gist.js +20 -0
- package/dist/dialects/pg/ext/call.d.ts +53 -0
- package/dist/dialects/pg/ext/citext.js +1 -1
- package/dist/dialects/pg/ext/feature.d.ts +26 -0
- package/dist/dialects/pg/ext/fuzzystrmatch.d.ts +34 -0
- package/dist/dialects/pg/ext/fuzzystrmatch.js +33 -0
- package/dist/dialects/pg/ext/hstore.d.ts +41 -0
- package/dist/dialects/pg/ext/hstore.js +29 -0
- package/dist/dialects/pg/ext/index.d.ts +56 -0
- package/dist/dialects/pg/ext/index.js +1 -1
- package/dist/dialects/pg/ext/ltree.d.ts +41 -0
- package/dist/dialects/pg/ext/ltree.js +29 -0
- package/dist/dialects/pg/ext/pg-trgm.js +4 -13
- package/dist/dialects/pg/ext/pgcrypto.d.ts +33 -0
- package/dist/dialects/pg/ext/pgcrypto.js +33 -0
- package/dist/dialects/pg/ext/unaccent.d.ts +26 -0
- package/dist/dialects/pg/ext/unaccent.js +21 -0
- package/dist/dialects/pg/ext/using.d.ts +23 -0
- package/dist/dialects/pg/ext/versions.d.ts +36 -0
- package/dist/dialects/pg/external.d.ts +19 -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 +3 -0
- package/dist/dialects/pg/index.js +394 -14
- package/dist/dialects/pg/introspect.d.ts +11 -0
- package/dist/dialects/pg/operators.d.ts +1 -1
- package/dist/dialects/pg/ops/fragment.d.ts +119 -0
- package/dist/dialects/pg/ops/lane.d.ts +49 -0
- 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 +11 -5
- package/dist/runtime/artifact-file.d.ts +22 -0
- package/dist/runtime/client.d.ts +10 -0
- package/dist/runtime/drift-detail.d.ts +2 -1
- package/dist/runtime/drift.d.ts +3 -10
- package/dist/runtime/otel.d.ts +105 -0
- package/dist/runtime/otel.js +97 -0
- package/dist/runtime/pg/bun.js +4 -4
- package/dist/runtime/pg/neon.d.ts +38 -0
- package/dist/runtime/pg/neon.js +64 -0
- package/dist/runtime/pg/pg.js +4 -4
- package/dist/runtime/pg/pglite.js +4 -4
- package/dist/runtime/pg/postgresjs.js +4 -4
- package/dist/runtime/plan.d.ts +1 -1
- package/dist/runtime/server-check.d.ts +36 -6
- package/dist/runtime/sql-fragment.d.ts +43 -0
- package/dist/runtime/tenancy/index.js +10 -10
- package/dist/runtime/topology.d.ts +1 -1
- package/dist/runtime/traits/index.js +16 -17
- package/dist/runtime/types.d.ts +15 -1
- package/dist/runtime/validate/index.js +4 -4
- package/dist/shared/{81ebdx9p.js → 0j6qe91y.js} +4 -4
- package/dist/shared/{qq3899ht.js → 12z7aznj.js} +243 -14
- package/dist/shared/{gzaveazc.js → 1d9q9cv2.js} +29 -2
- package/dist/shared/{w79hsckn.js → 1mxm04fy.js} +5 -5
- package/dist/shared/{7k9grvf6.js → 2szgv6yj.js} +5 -5
- package/dist/shared/{gs74dbj5.js → 2zdxkt7b.js} +933 -111
- package/dist/shared/{m6p12kbr.js → 3456242y.js} +23 -23
- package/dist/shared/3bb7wsqt.js +99 -0
- package/dist/shared/{y6njgyda.js → 3t6kw83m.js} +2 -2
- package/dist/shared/{xhfsfkgk.js → 4vbf83xx.js} +9 -2
- package/dist/shared/{pt94kz7f.js → 5kyb3tqx.js} +1 -1
- package/dist/shared/61bmrmhr.js +35 -0
- package/dist/shared/{x933k9a3.js → 62b603gr.js} +10 -10
- package/dist/shared/{jgqj11w4.js → 6f0z3hzh.js} +4 -0
- package/dist/shared/{tsvww22q.js → 6nae0spm.js} +156 -95
- package/dist/shared/{mtaszv5a.js → 71n0jmhc.js} +102 -4
- package/dist/shared/{5e3tf63j.js → 760ppr76.js} +14 -6
- package/dist/shared/7ba5h6pb.js +17 -0
- package/dist/shared/{sfz1ksn6.js → 8jesqsrk.js} +2 -2
- package/dist/shared/{5v3xf80k.js → 8n688yjg.js} +1 -1
- package/dist/shared/{rs73fca9.js → 8qzkd9f3.js} +6 -6
- package/dist/shared/{ax7qv55k.js → 90sg0w5a.js} +202 -25
- package/dist/shared/{zm0ptry0.js → 99qp9vtg.js} +1 -1
- package/dist/shared/{xnxsed62.js → 9dr2qnx7.js} +14 -14
- package/dist/shared/{1w508jbr.js → 9dtgn1z2.js} +21 -17
- package/dist/shared/{h15jx9bc.js → 9dvh1dr6.js} +1 -1
- package/dist/shared/{q5c6ngn3.js → a62rb2da.js} +1 -1
- package/dist/shared/{te5as7z7.js → aksb89mn.js} +3 -3
- package/dist/shared/{bz84tkzm.js → bphrgwz9.js} +2 -2
- package/dist/shared/bsek72fg.js +225 -0
- package/dist/shared/{7mnme5tn.js → c3mvnq7a.js} +1 -1
- package/dist/shared/{p6qc5gcp.js → ccsmhv9r.js} +25 -7
- package/dist/shared/{pbp1ss85.js → cexb7z6b.js} +2 -2
- package/dist/shared/{ab9gmbwy.js → cf8zdz5p.js} +5 -5
- package/dist/shared/{jvd0mqag.js → ckz05z15.js} +5 -5
- package/dist/shared/{dk8v79p3.js → d5nmj7vv.js} +1 -1
- package/dist/shared/{14vx95q4.js → dd5pmnky.js} +7 -7
- package/dist/shared/{vb6qfyve.js → ds229x4r.js} +2 -2
- package/dist/shared/{1qa0qajz.js → e275q7sd.js} +1 -1
- package/dist/shared/{zp9fmend.js → ebhz8vh6.js} +4 -4
- package/dist/shared/{hyh73qk6.js → ecn8mfdq.js} +5 -5
- package/dist/shared/{je4axnm8.js → fdsz3w80.js} +2 -2
- package/dist/shared/{9s0ypp87.js → fk9vef30.js} +85 -74
- package/dist/shared/{g6evj1j3.js → g89fmz5s.js} +1 -1
- package/dist/shared/{aytqh5y2.js → ghqzdp94.js} +2 -2
- package/dist/shared/h9811jjm.js +17 -0
- package/dist/shared/{dkxgzaqd.js → hqpxf4a4.js} +1 -1
- package/dist/shared/{8skf0cam.js → jpybhf98.js} +1 -1
- package/dist/shared/{67txcrcw.js → kgwp4jdd.js} +4 -4
- package/dist/shared/kzgrnckd.js +29 -0
- package/dist/shared/mazpbcdj.js +233 -0
- package/dist/shared/{kb2sdhfb.js → mfvx6kjx.js} +17 -1
- package/dist/shared/{svncdeh5.js → mgaq2sd3.js} +11 -8
- package/dist/shared/{5mtf6cj3.js → mvmm3xpb.js} +5 -2
- package/dist/shared/{b5pftnn2.js → myk8fswx.js} +66 -21
- package/dist/shared/{2shdbn8q.js → n306gqkd.js} +9 -9
- package/dist/shared/{n816peh1.js → n454kcnw.js} +1 -1
- package/dist/shared/n5whk3mt.js +665 -0
- package/dist/shared/n7kg8mmx.js +61 -0
- package/dist/shared/{vqrjpcqn.js → nmnsgj7x.js} +1 -1
- package/dist/shared/{tbrvgw6z.js → npdftanb.js} +19 -26
- package/dist/shared/{ek2wt2dz.js → pg4ezgyf.js} +11 -30
- package/dist/shared/{5fe3kbsh.js → pgsak1yw.js} +1 -1
- package/dist/shared/{bm22fvzr.js → qfw14tna.js} +2 -2
- package/dist/shared/{wa07eas9.js → qvwwp1mp.js} +62 -41
- package/dist/shared/rbxt795q.js +1766 -0
- package/dist/shared/{xjk7hnn5.js → s7he5e5d.js} +2 -2
- package/dist/shared/{w72kgg4q.js → ss2kv2rs.js} +6 -6
- package/dist/shared/stfa9xcw.js +450 -0
- package/dist/shared/{3v7t1yrv.js → th3be82n.js} +2 -2
- package/dist/shared/{79dt02vc.js → tr64w5p0.js} +1 -1
- package/dist/shared/{cn957f8d.js → tw1nvvfj.js} +3 -3
- package/dist/shared/{ed0b8k4s.js → typ3vy7t.js} +1 -1
- package/dist/shared/{9628a9xt.js → vk7rag46.js} +1 -1
- package/dist/shared/{ze4hxsmy.js → w9ejzaqf.js} +1 -1
- package/dist/shared/{vczs8gd4.js → wvtjg5m3.js} +2 -2
- package/dist/shared/{9y3mmmh1.js → xfhe73sb.js} +1 -1
- package/dist/shared/xqacq37x.js +61 -0
- package/dist/shared/{1est4ezg.js → xtsydxjg.js} +3 -3
- package/dist/shared/xv8qj97g.js +96 -0
- package/dist/shared/{bg3rym3g.js → xwhdcrm4.js} +2 -2
- package/dist/shared/{kr0jzbw2.js → yvabyg9k.js} +7 -7
- package/dist/shared/yybhre6n.js +136 -0
- package/dist/shared/zdqf8k5d.js +8 -0
- package/dist/shared/{jznfax0y.js → zq1he88x.js} +4 -4
- package/dist/tooling/cli.js +108 -23
- package/dist/tooling/driver-run.js +4654 -0
- package/dist/tooling/driver-test.d.ts +36 -0
- package/dist/tooling/github/comment.d.ts +50 -0
- package/dist/tooling/github/post-comment.d.ts +17 -0
- package/dist/tooling/migrate/commands.d.ts +3 -2
- package/dist/tooling/migrate/config.d.ts +13 -0
- package/dist/tooling/migrate/export.d.ts +165 -0
- package/dist/tooling/migrate/ext-surface.d.ts +80 -0
- package/dist/tooling/migrate/ext.d.ts +31 -4
- package/dist/tooling/migrate/import-drizzle.d.ts +40 -0
- package/dist/tooling/migrate/index.d.ts +3 -0
- package/dist/tooling/migrate/index.js +55 -10
- package/dist/tooling/migrate/lint-rules.d.ts +18 -1
- package/dist/tooling/migrate/lint.d.ts +14 -1
- package/dist/tooling/migrate/place.d.ts +18 -0
- package/dist/tooling/migrate/plan-json.d.ts +65 -0
- package/dist/tooling/migrate/project.d.ts +13 -1
- package/dist/tooling/migrate/pull-emit.d.ts +98 -0
- package/dist/tooling/migrate/pull-routines.d.ts +126 -0
- package/dist/tooling/migrate/pull-verify.d.ts +26 -0
- package/dist/tooling/migrate/pull.d.ts +62 -0
- package/dist/tooling/migrate/reprint.d.ts +32 -0
- package/dist/tooling/migrate/sandbox.d.ts +8 -2
- package/dist/tooling/migrate/schema-api.d.ts +43 -0
- package/dist/tooling/migrate/sql-lex.d.ts +18 -0
- package/dist/tooling/shared/04svnxxj.js +344 -0
- package/dist/tooling/shared/0j0jtse1.js +13 -0
- package/dist/tooling/shared/0r05zhyq.js +618 -0
- package/dist/tooling/shared/1800eymw.js +49 -0
- package/dist/tooling/shared/35zemrmf.js +12 -0
- package/dist/tooling/shared/3rmaz3pq.js +140 -0
- package/dist/tooling/shared/3yn79q5m.js +12 -0
- package/dist/tooling/shared/54tqkxja.js +51 -0
- package/dist/tooling/shared/57btdkgm.js +209 -0
- package/dist/tooling/shared/5bmksndh.js +118 -0
- package/dist/tooling/shared/5p8km5jb.js +38 -0
- package/dist/tooling/shared/5x3pf400.js +185 -0
- package/dist/tooling/shared/5zrzffnk.js +6 -0
- package/dist/tooling/shared/62fxpc1p.js +332 -0
- package/dist/tooling/shared/68tf18v4.js +20 -0
- package/dist/tooling/shared/6vk28rjp.js +98 -0
- package/dist/tooling/shared/76pv6qff.js +9 -0
- package/dist/tooling/shared/7aews1zg.js +311 -0
- package/dist/tooling/shared/7b3xp9gc.js +195 -0
- package/dist/tooling/shared/7kms6fvj.js +20 -0
- package/dist/tooling/shared/7pxncnzs.js +40 -0
- package/dist/tooling/shared/829fjxyw.js +198 -0
- package/dist/tooling/shared/8m5znpdt.js +66 -0
- package/dist/tooling/shared/8yr7ges1.js +211 -0
- package/dist/tooling/shared/96ps4g1z.js +32 -0
- package/dist/tooling/shared/9qr9rkbh.js +143 -0
- package/dist/tooling/shared/9sfbtwsk.js +49 -0
- package/dist/tooling/shared/9wsnsvbf.js +10 -0
- package/dist/tooling/shared/a2xe04bm.js +18 -0
- package/dist/tooling/shared/a4pzghha.js +20 -0
- package/dist/tooling/shared/am04v8na.js +233 -0
- package/dist/tooling/shared/asgr07mp.js +194 -0
- package/dist/tooling/shared/c0xevn1h.js +312 -0
- package/dist/tooling/shared/dhatassp.js +134 -0
- package/dist/tooling/shared/ezqn88nj.js +1696 -0
- package/dist/tooling/shared/f77nnfqy.js +231 -0
- package/dist/tooling/shared/fh07z1dt.js +15 -0
- package/dist/tooling/shared/gqwevek4.js +81 -0
- package/dist/tooling/shared/hfq3n3bd.js +4116 -0
- package/dist/tooling/shared/htnaj77v.js +17 -0
- package/dist/tooling/shared/j664qjrt.js +64 -0
- package/dist/tooling/shared/jpgmjsx3.js +38 -0
- package/dist/tooling/shared/jr2nmr81.js +497 -0
- package/dist/tooling/shared/jsjjz875.js +139 -0
- package/dist/tooling/shared/kbqnrs1x.js +1425 -0
- package/dist/tooling/shared/kz715295.js +94 -0
- package/dist/tooling/shared/m3xt8b1h.js +22 -0
- package/dist/tooling/shared/m4hhb8aa.js +9 -0
- package/dist/tooling/shared/mw5npye0.js +16 -0
- package/dist/tooling/shared/n4jqhpqz.js +27 -0
- package/dist/tooling/shared/nxq95eb6.js +42 -0
- package/dist/tooling/shared/qartgazh.js +70 -0
- package/dist/tooling/shared/rcywj2w8.js +190 -0
- package/dist/tooling/shared/s6qha57m.js +16 -0
- package/dist/tooling/shared/shjs0379.js +150 -0
- package/dist/tooling/shared/sjwkt1pg.js +16 -0
- package/dist/tooling/shared/stebqyyd.js +401 -0
- package/dist/tooling/shared/t4xveemq.js +250 -0
- package/dist/tooling/shared/t6zjeake.js +261 -0
- package/dist/tooling/shared/tcwpjvxe.js +9 -0
- package/dist/tooling/shared/tpssp7ac.js +160 -0
- package/dist/tooling/shared/v6j1ep6w.js +42 -0
- package/dist/tooling/shared/vwr2y833.js +270 -0
- package/dist/tooling/shared/w17sj05d.js +7 -0
- package/dist/tooling/shared/w5d89rb4.js +131 -0
- package/dist/tooling/shared/wbwq1jsa.js +157 -0
- package/dist/tooling/shared/wezxf3h8.js +17 -0
- package/dist/tooling/shared/yb4kd19s.js +12 -0
- package/dist/tooling/shared/ybdew6j7.js +294 -0
- package/dist/tooling/shared/yfedr1zb.js +6 -0
- package/dist/tooling/shared/yhp829bx.js +177 -0
- package/dist/tooling/shared/ytk1tjs0.js +604 -0
- package/dist/tooling/shared/zs9aymcp.js +210 -0
- package/dist/tooling/shared/zx3v9phv.js +8 -0
- package/dist/tooling/testing/index.js +3 -3
- package/package.json +50 -9
- package/dist/shared/ktz42yez.js +0 -113
- package/dist/shared/ttsqgp4p.js +0 -71
- package/dist/shared/y34a8714.js +0 -150
- 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,3 +1,7 @@
|
|
|
1
|
+
import"../../shared/12z7aznj.js";
|
|
2
|
+
import {
|
|
3
|
+
quoteIdent2
|
|
4
|
+
} from "../../shared/fk9vef30.js";
|
|
1
5
|
import {
|
|
2
6
|
searchValue
|
|
3
7
|
} from "../../shared/dzj09cye.js";
|
|
@@ -11,7 +15,7 @@ import {
|
|
|
11
15
|
jsonReplacer2,
|
|
12
16
|
json2,
|
|
13
17
|
jsonb2
|
|
14
|
-
} from "../../shared/
|
|
18
|
+
} from "../../shared/vk7rag46.js";
|
|
15
19
|
import {
|
|
16
20
|
bucket2
|
|
17
21
|
} from "../../shared/nbw1z4yd.js";
|
|
@@ -36,13 +40,14 @@ import {
|
|
|
36
40
|
time2,
|
|
37
41
|
timetz2,
|
|
38
42
|
interval2
|
|
39
|
-
} from "../../shared/
|
|
43
|
+
} from "../../shared/nmnsgj7x.js";
|
|
40
44
|
import {
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
id2,
|
|
46
|
+
uuid2
|
|
47
|
+
} from "../../shared/ecn8mfdq.js";
|
|
43
48
|
import {
|
|
44
|
-
|
|
45
|
-
} from "../../shared/
|
|
49
|
+
schema2
|
|
50
|
+
} from "../../shared/9dr2qnx7.js";
|
|
46
51
|
import {
|
|
47
52
|
one2,
|
|
48
53
|
many2,
|
|
@@ -51,10 +56,6 @@ import {
|
|
|
51
56
|
morphMany2,
|
|
52
57
|
morphTo2
|
|
53
58
|
} from "../../shared/exn3sd90.js";
|
|
54
|
-
import {
|
|
55
|
-
id2,
|
|
56
|
-
uuid2
|
|
57
|
-
} from "../../shared/hyh73qk6.js";
|
|
58
59
|
import {
|
|
59
60
|
text2,
|
|
60
61
|
varchar2,
|
|
@@ -62,17 +63,25 @@ import {
|
|
|
62
63
|
citext2,
|
|
63
64
|
encodeText,
|
|
64
65
|
decodeText
|
|
65
|
-
} from "../../shared/
|
|
66
|
+
} from "../../shared/typ3vy7t.js";
|
|
66
67
|
import {
|
|
67
68
|
table2,
|
|
68
69
|
index2,
|
|
69
70
|
sql2
|
|
70
|
-
} from "../../shared/
|
|
71
|
+
} from "../../shared/gcefca6p.js";
|
|
71
72
|
import {
|
|
72
73
|
ColumnBuilder2,
|
|
73
74
|
required,
|
|
74
75
|
formatType
|
|
75
|
-
} from "../../shared/
|
|
76
|
+
} from "../../shared/606g0nbf.js";
|
|
77
|
+
import {
|
|
78
|
+
isFragmentParts,
|
|
79
|
+
fragment2,
|
|
80
|
+
ident2
|
|
81
|
+
} from "../../shared/bsek72fg.js";
|
|
82
|
+
import {
|
|
83
|
+
domainType
|
|
84
|
+
} from "../../shared/ywspezzx.js";
|
|
76
85
|
import {
|
|
77
86
|
definition,
|
|
78
87
|
rejected
|
|
@@ -82,11 +91,15 @@ import {
|
|
|
82
91
|
compareText
|
|
83
92
|
} from "../../shared/358zsv4r.js";
|
|
84
93
|
import {
|
|
94
|
+
isOperator,
|
|
95
|
+
operatorName,
|
|
96
|
+
operatorValue,
|
|
85
97
|
tag
|
|
86
98
|
} from "../../shared/cn0n68ft.js";
|
|
87
99
|
import {
|
|
88
100
|
OkmError2,
|
|
89
|
-
catalogError2
|
|
101
|
+
catalogError2,
|
|
102
|
+
throwNamed2
|
|
90
103
|
} from "../../shared/52szzakm.js";
|
|
91
104
|
var __defProp = Object.defineProperty;
|
|
92
105
|
var __returnValue = (v) => v;
|
|
@@ -102,6 +115,10 @@ var __export = (target, all) => {
|
|
|
102
115
|
set: __exportSetter.bind(all, name)
|
|
103
116
|
});
|
|
104
117
|
};
|
|
118
|
+
// src/dialects/pg/external.ts
|
|
119
|
+
function external(table) {
|
|
120
|
+
return withOwner2(table, "external");
|
|
121
|
+
}
|
|
105
122
|
// src/dialects/pg/custom.ts
|
|
106
123
|
function custom(spec) {
|
|
107
124
|
if (spec.sqlType.length === 0) {
|
|
@@ -815,6 +832,364 @@ function path(segments, op) {
|
|
|
815
832
|
function startsWith(value) {
|
|
816
833
|
return tag("startsWith", value);
|
|
817
834
|
}
|
|
835
|
+
// src/dialects/pg/ops/lane.ts
|
|
836
|
+
var LANE = Symbol.for("okm.lane");
|
|
837
|
+
var READ = "read";
|
|
838
|
+
var WRITE = "write";
|
|
839
|
+
var BLOCKED = new Set(["__proto__", "constructor", "toString", "hasOwnProperty"]);
|
|
840
|
+
async function raw(handle, cls, statement, source) {
|
|
841
|
+
const lane = readLane(handle);
|
|
842
|
+
const kind = readClass(statement);
|
|
843
|
+
const indexed = openTable(lane);
|
|
844
|
+
const parts = readParts(source);
|
|
845
|
+
const compiled = compile(indexed, parts);
|
|
846
|
+
const word = verb(compiled.text);
|
|
847
|
+
if (kind === READ && word !== "select") {
|
|
848
|
+
bad("A raw read starts with select.", 'Pass "read" and a single select. A leading with is a write.');
|
|
849
|
+
}
|
|
850
|
+
if (kind === WRITE && word !== "insert" && word !== "update" && word !== "delete") {
|
|
851
|
+
bad("A raw write starts with insert, update, or delete.", 'Pass "write" and one insert, update, or delete.');
|
|
852
|
+
}
|
|
853
|
+
const tenancy = predicateOf(lane.session, indexed);
|
|
854
|
+
if (kind === WRITE && tenancy !== undefined) {
|
|
855
|
+
unverifiable("A raw write on a tenant table cannot keep the tenant predicate.", 'Use update or delete. unscoped("reason") is the reviewed hatch.');
|
|
856
|
+
}
|
|
857
|
+
const guard = kind === READ ? guardOf(indexed, tenancy, compiled.params.length) : undefined;
|
|
858
|
+
if (guard !== undefined)
|
|
859
|
+
requireKey(indexed, lane.session.schema.tenancy?.key, parts);
|
|
860
|
+
const text = guard === undefined ? compiled.text : wrap(indexed, lane.session.schema.tenancy?.key, compiled.text, guard.text);
|
|
861
|
+
const params = guard === undefined ? compiled.params : [...compiled.params, ...guard.params];
|
|
862
|
+
await lane.session.connected;
|
|
863
|
+
try {
|
|
864
|
+
const result = await lane.session.pool.execute(text, params, kind === WRITE ? { route: "primary" } : undefined);
|
|
865
|
+
return decodeRows(cls, result.rows, indexed);
|
|
866
|
+
} catch (error) {
|
|
867
|
+
return raise(lane, error);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
async function explain(handle, query) {
|
|
871
|
+
const lane = readLane(handle);
|
|
872
|
+
const got = readPlanned(await readSql(query));
|
|
873
|
+
if (production())
|
|
874
|
+
return { text: got.text, params: [], plan: null };
|
|
875
|
+
await lane.session.connected;
|
|
876
|
+
let rows;
|
|
877
|
+
try {
|
|
878
|
+
const result = await lane.session.pool.execute(`explain ${got.text}`, got.params);
|
|
879
|
+
rows = result.rows;
|
|
880
|
+
} catch (error) {
|
|
881
|
+
return raise(lane, error);
|
|
882
|
+
}
|
|
883
|
+
const plan = [];
|
|
884
|
+
for (const row of rows) {
|
|
885
|
+
const line = row[0];
|
|
886
|
+
if (typeof line === "string")
|
|
887
|
+
plan.push(line);
|
|
888
|
+
}
|
|
889
|
+
return { text: got.text, params: got.params, plan };
|
|
890
|
+
}
|
|
891
|
+
async function raise(lane, error) {
|
|
892
|
+
const mapped = await lane.fail(lane.session, error);
|
|
893
|
+
lane.session.logger?.error?.({ code: mapped.code, summary: mapped.summary });
|
|
894
|
+
throw mapped;
|
|
895
|
+
}
|
|
896
|
+
function production() {
|
|
897
|
+
const proc = Reflect.get(globalThis, "process");
|
|
898
|
+
if (typeof proc !== "object" || proc === null)
|
|
899
|
+
return false;
|
|
900
|
+
const env = Reflect.get(proc, "env");
|
|
901
|
+
if (typeof env !== "object" || env === null)
|
|
902
|
+
return false;
|
|
903
|
+
return Reflect.get(env, "NODE_ENV") === "production";
|
|
904
|
+
}
|
|
905
|
+
function readLane(handle) {
|
|
906
|
+
const value = Reflect.get(handle, LANE);
|
|
907
|
+
if (!Array.isArray(value)) {
|
|
908
|
+
bad("Pass the table handle.", "raw and explain take the table, such as db.notes, including a table from for().");
|
|
909
|
+
}
|
|
910
|
+
const session = value[0];
|
|
911
|
+
const table = value[1];
|
|
912
|
+
const fail = value[2];
|
|
913
|
+
if (typeof table !== "string" || typeof fail !== "function" || !isSession(session)) {
|
|
914
|
+
bad("Pass the table handle.", "raw and explain take the table, such as db.notes, including a table from for().");
|
|
915
|
+
}
|
|
916
|
+
return { session, table, fail };
|
|
917
|
+
}
|
|
918
|
+
function isSession(value) {
|
|
919
|
+
if (typeof value !== "object" || value === null)
|
|
920
|
+
return false;
|
|
921
|
+
const schema = Reflect.get(value, "schema");
|
|
922
|
+
const connected = Reflect.get(value, "connected");
|
|
923
|
+
const pool = Reflect.get(value, "pool");
|
|
924
|
+
if (typeof schema !== "object" || schema === null)
|
|
925
|
+
return false;
|
|
926
|
+
if (typeof Reflect.get(schema, "model") !== "object")
|
|
927
|
+
return false;
|
|
928
|
+
if (typeof connected !== "object" || connected === null || typeof Reflect.get(connected, "then") !== "function") {
|
|
929
|
+
return false;
|
|
930
|
+
}
|
|
931
|
+
return typeof pool === "object" && pool !== null && typeof Reflect.get(pool, "execute") === "function";
|
|
932
|
+
}
|
|
933
|
+
function readSql(query) {
|
|
934
|
+
const sql = Reflect.get(query, "sql");
|
|
935
|
+
if (typeof sql !== "function") {
|
|
936
|
+
bad("Pass a query.", "explain takes the table and a query from that table, such as notes.find({ limit: 1 }).");
|
|
937
|
+
}
|
|
938
|
+
return sql.call(query);
|
|
939
|
+
}
|
|
940
|
+
function readPlanned(value) {
|
|
941
|
+
if (typeof value !== "object" || value === null) {
|
|
942
|
+
bad("The statement has no text.", "Call explain on a query.");
|
|
943
|
+
}
|
|
944
|
+
const text = Reflect.get(value, "text");
|
|
945
|
+
const params = Reflect.get(value, "params");
|
|
946
|
+
if (typeof text !== "string" || !Array.isArray(params)) {
|
|
947
|
+
bad("The statement has no text.", "Call explain on a query.");
|
|
948
|
+
}
|
|
949
|
+
const bound = [];
|
|
950
|
+
for (const param of params) {
|
|
951
|
+
if (typeof param !== "string" && param !== null) {
|
|
952
|
+
bad("A statement parameter was not text.", "Parameters are bound text.");
|
|
953
|
+
}
|
|
954
|
+
bound.push(param);
|
|
955
|
+
}
|
|
956
|
+
return { text, params: bound };
|
|
957
|
+
}
|
|
958
|
+
function openTable(lane) {
|
|
959
|
+
const model = lane.session.schema.model[lane.table];
|
|
960
|
+
if (model === undefined) {
|
|
961
|
+
bad(`Table ${lane.table} is not in the schema.`, "Call raw on a table this schema declares.");
|
|
962
|
+
}
|
|
963
|
+
const columns = new Map;
|
|
964
|
+
const names = [];
|
|
965
|
+
for (const column of model.columns) {
|
|
966
|
+
columns.set(column.field, column);
|
|
967
|
+
names.push(column.field);
|
|
968
|
+
}
|
|
969
|
+
names.sort();
|
|
970
|
+
return { model, columns, names };
|
|
971
|
+
}
|
|
972
|
+
function compile(table, parts) {
|
|
973
|
+
const params = [];
|
|
974
|
+
const chunks = [];
|
|
975
|
+
let count = 0;
|
|
976
|
+
const sink = {
|
|
977
|
+
text(value) {
|
|
978
|
+
chunks.push(value);
|
|
979
|
+
},
|
|
980
|
+
param(encoded) {
|
|
981
|
+
params.push(encoded);
|
|
982
|
+
count += 1;
|
|
983
|
+
chunks.push(`$${String(count)}`);
|
|
984
|
+
},
|
|
985
|
+
mark() {}
|
|
986
|
+
};
|
|
987
|
+
for (const part of parts)
|
|
988
|
+
writePart(part, sink, table);
|
|
989
|
+
return { text: chunks.join(""), params };
|
|
990
|
+
}
|
|
991
|
+
function writePart(part, sink, table) {
|
|
992
|
+
if (part.k === "t") {
|
|
993
|
+
sink.text(part.s);
|
|
994
|
+
return;
|
|
995
|
+
}
|
|
996
|
+
if (part.k === "p") {
|
|
997
|
+
sink.param(part.v);
|
|
998
|
+
return;
|
|
999
|
+
}
|
|
1000
|
+
if (part.k === "n") {
|
|
1001
|
+
sink.text("null");
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
if (part.k === "i") {
|
|
1005
|
+
writeIdent(part.n, sink, table);
|
|
1006
|
+
return;
|
|
1007
|
+
}
|
|
1008
|
+
if (part.k === "c") {
|
|
1009
|
+
throw new OkmError2("OKM1125", "fragment.column belongs on a where field.", {
|
|
1010
|
+
fix: { summary: "Use ident(name) in a raw statement." }
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
sink.text("(");
|
|
1014
|
+
for (const nested of part.parts)
|
|
1015
|
+
writePart(nested, sink, table);
|
|
1016
|
+
sink.text(")");
|
|
1017
|
+
}
|
|
1018
|
+
function writeIdent(name, sink, table) {
|
|
1019
|
+
const column = table.columns.get(name);
|
|
1020
|
+
if (column === undefined) {
|
|
1021
|
+
throwNamed2("OKM1120", name, table.names, `Field ${name} is not on ${table.model.name}. Accepted names: ${table.names.join(", ")}.`);
|
|
1022
|
+
}
|
|
1023
|
+
if (column.hidden) {
|
|
1024
|
+
throw new OkmError2("OKM1120", `Field ${column.field} is hidden.`, {
|
|
1025
|
+
fix: { summary: "A raw statement cannot name a hidden field." }
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
sink.text(quoteIdent2(column.sql));
|
|
1029
|
+
}
|
|
1030
|
+
function readClass(statement) {
|
|
1031
|
+
if (statement === READ || statement === WRITE)
|
|
1032
|
+
return statement;
|
|
1033
|
+
bad('The statement class is "read" or "write".', 'Pass "read" or "write".');
|
|
1034
|
+
}
|
|
1035
|
+
function readParts(source) {
|
|
1036
|
+
if (typeof source !== "object" || source === null) {
|
|
1037
|
+
bad("Pass fragment`...`.", "Identifiers are ident(name). A string, number, boolean, or null is a parameter.");
|
|
1038
|
+
}
|
|
1039
|
+
if (typeof Reflect.get(source, "as") === "string") {
|
|
1040
|
+
bad("Pass the fragment, not .as(name).", "The class names the row. Drop .as().");
|
|
1041
|
+
}
|
|
1042
|
+
if (!isOperator(source) || operatorName(source) !== "sql") {
|
|
1043
|
+
bad("Pass fragment`...`.", "Identifiers are ident(name). A string, number, boolean, or null is a parameter.");
|
|
1044
|
+
}
|
|
1045
|
+
const stored = operatorValue(source);
|
|
1046
|
+
if (!isFragmentParts(stored)) {
|
|
1047
|
+
bad("Pass fragment`...`.", "Call fragment`...`. Do not build the parts yourself.");
|
|
1048
|
+
}
|
|
1049
|
+
return stored;
|
|
1050
|
+
}
|
|
1051
|
+
function verb(text) {
|
|
1052
|
+
return /^[a-z]+/i.exec(text.trimStart())?.[0]?.toLowerCase() ?? "";
|
|
1053
|
+
}
|
|
1054
|
+
function predicateOf(session, table) {
|
|
1055
|
+
const tenancy = session.schema.tenancy;
|
|
1056
|
+
if (tenancy === undefined)
|
|
1057
|
+
return;
|
|
1058
|
+
const chunks = [];
|
|
1059
|
+
const params = [];
|
|
1060
|
+
let count = 0;
|
|
1061
|
+
const wrote = tenancy.predicate({
|
|
1062
|
+
table: table.model.name,
|
|
1063
|
+
fieldSql: (field) => table.columns.get(field)?.sql,
|
|
1064
|
+
encode: table.columns.get(tenancy.key)?.encode,
|
|
1065
|
+
alias: "okm_tenant",
|
|
1066
|
+
appended: false,
|
|
1067
|
+
scope: session.scope,
|
|
1068
|
+
sink: {
|
|
1069
|
+
text(value) {
|
|
1070
|
+
chunks.push(value);
|
|
1071
|
+
},
|
|
1072
|
+
param(encoded) {
|
|
1073
|
+
params.push(encoded);
|
|
1074
|
+
count += 1;
|
|
1075
|
+
chunks.push(`$${String(count)}`);
|
|
1076
|
+
},
|
|
1077
|
+
mark() {}
|
|
1078
|
+
}
|
|
1079
|
+
});
|
|
1080
|
+
if (!wrote)
|
|
1081
|
+
return;
|
|
1082
|
+
return { text: chunks.join("").replace(/^\s*where\s+/i, ""), params };
|
|
1083
|
+
}
|
|
1084
|
+
function guardOf(table, tenancy, userCount) {
|
|
1085
|
+
const archive = table.model.archive?.at;
|
|
1086
|
+
if (tenancy === undefined && archive === undefined)
|
|
1087
|
+
return;
|
|
1088
|
+
const parts = [];
|
|
1089
|
+
if (tenancy !== undefined)
|
|
1090
|
+
parts.push(shift(tenancy.text, userCount));
|
|
1091
|
+
if (archive !== undefined)
|
|
1092
|
+
parts.push(`okm_tenant.${quoteIdent2(archive)} is null`);
|
|
1093
|
+
return { text: parts.join(" and "), params: tenancy?.params ?? [] };
|
|
1094
|
+
}
|
|
1095
|
+
function requireKey(table, tenantKey, parts) {
|
|
1096
|
+
const key = rowKey(table, tenantKey);
|
|
1097
|
+
if (key === undefined) {
|
|
1098
|
+
unverifiable("A raw read needs one primary key column besides the tenant key.", "Declare one primary key. The tenant predicate binds that column.");
|
|
1099
|
+
}
|
|
1100
|
+
if (!namesIdent(parts, key)) {
|
|
1101
|
+
unverifiable(`A raw read must select ${key} with ident.`, `Put ident("${key}") in the select list. Do not alias it. The tenant predicate is added outside the statement.`);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
function rowKey(table, tenantKey) {
|
|
1105
|
+
const keys = table.model.primary.filter((field) => field !== tenantKey);
|
|
1106
|
+
return keys.length === 1 ? keys[0] : undefined;
|
|
1107
|
+
}
|
|
1108
|
+
function namesIdent(parts, name) {
|
|
1109
|
+
for (const part of parts) {
|
|
1110
|
+
if (part.k === "i" && part.n === name)
|
|
1111
|
+
return true;
|
|
1112
|
+
if (part.k === "f" && namesIdent(part.parts, name))
|
|
1113
|
+
return true;
|
|
1114
|
+
}
|
|
1115
|
+
return false;
|
|
1116
|
+
}
|
|
1117
|
+
function wrap(table, tenantKey, text, where) {
|
|
1118
|
+
const key = rowKey(table, tenantKey);
|
|
1119
|
+
const column = key === undefined ? undefined : table.columns.get(key);
|
|
1120
|
+
if (column === undefined) {
|
|
1121
|
+
unverifiable("A raw read needs one primary key column besides the tenant key.", "Declare one primary key. The tenant predicate binds that column.");
|
|
1122
|
+
}
|
|
1123
|
+
const quoted = quoteIdent2(column.sql);
|
|
1124
|
+
return `select okm_raw.* from (${text}) as okm_raw where okm_raw.${quoted} in (select ${quoted} from ${quoteIdent2(table.model.sql)} as okm_tenant where ${where})`;
|
|
1125
|
+
}
|
|
1126
|
+
function shift(text, by) {
|
|
1127
|
+
if (by === 0)
|
|
1128
|
+
return text;
|
|
1129
|
+
return text.replace(/\$(\d+)/g, (_match, digits) => `$${String(Number(digits) + by)}`);
|
|
1130
|
+
}
|
|
1131
|
+
function decodeRows(cls, rows, table) {
|
|
1132
|
+
const ctor = readClassCtor(cls);
|
|
1133
|
+
const sample = construct(ctor);
|
|
1134
|
+
const keys = Object.keys(sample);
|
|
1135
|
+
if (keys.length === 0) {
|
|
1136
|
+
bad("The class needs an initializer on every result column.", 'Write `id = ""` or `n = 0`. The initializer selects the decode, and the order is the select list.');
|
|
1137
|
+
}
|
|
1138
|
+
for (const key of keys) {
|
|
1139
|
+
if (BLOCKED.has(key))
|
|
1140
|
+
bad(`Field ${key} is reserved.`, "Rename the class field.");
|
|
1141
|
+
}
|
|
1142
|
+
return rows.map((wire) => {
|
|
1143
|
+
const row = construct(ctor);
|
|
1144
|
+
for (let index = 0;index < keys.length; index += 1) {
|
|
1145
|
+
const key = keys[index];
|
|
1146
|
+
if (key === undefined)
|
|
1147
|
+
continue;
|
|
1148
|
+
Reflect.set(row, key, decodeWire(wire[index], Reflect.get(sample, key), table.columns.get(key)));
|
|
1149
|
+
}
|
|
1150
|
+
return row;
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
function readClassCtor(cls) {
|
|
1154
|
+
if (typeof cls !== "function") {
|
|
1155
|
+
bad("Pass a class.", "The result of raw is one instance of that class per row.");
|
|
1156
|
+
}
|
|
1157
|
+
return cls;
|
|
1158
|
+
}
|
|
1159
|
+
function construct(ctor) {
|
|
1160
|
+
try {
|
|
1161
|
+
return new ctor;
|
|
1162
|
+
} catch {
|
|
1163
|
+
bad("The class must construct with no arguments.", "Give each field an initializer and no constructor arguments.");
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
function decodeWire(wire, sample, column) {
|
|
1167
|
+
if (wire === null || wire === undefined)
|
|
1168
|
+
return null;
|
|
1169
|
+
if (column !== undefined)
|
|
1170
|
+
return column.decode === undefined ? wire : column.decode(wire);
|
|
1171
|
+
if (typeof sample === "number") {
|
|
1172
|
+
const parsed = Number(wire);
|
|
1173
|
+
if (!Number.isFinite(parsed)) {
|
|
1174
|
+
bad("A class field initialized with a number received a non-numeric value.", "Use a numeric expression, or initialize the field with a string.");
|
|
1175
|
+
}
|
|
1176
|
+
return parsed;
|
|
1177
|
+
}
|
|
1178
|
+
if (typeof sample === "boolean") {
|
|
1179
|
+
if (wire === "t" || wire === "true" || wire === "1")
|
|
1180
|
+
return true;
|
|
1181
|
+
if (wire === "f" || wire === "false" || wire === "0")
|
|
1182
|
+
return false;
|
|
1183
|
+
bad("A class field initialized with a boolean received another value.", "Use a boolean expression, or initialize the field with a string.");
|
|
1184
|
+
}
|
|
1185
|
+
return wire;
|
|
1186
|
+
}
|
|
1187
|
+
function bad(message, fix) {
|
|
1188
|
+
throw new OkmError2("OKM1602", message, { fix: { summary: fix } });
|
|
1189
|
+
}
|
|
1190
|
+
function unverifiable(message, fix) {
|
|
1191
|
+
throw new OkmError2("OKM1702", message, { fix: { summary: fix } });
|
|
1192
|
+
}
|
|
818
1193
|
export {
|
|
819
1194
|
ColumnBuilder2 as ColumnBuilder,
|
|
820
1195
|
exports_arr_ns as arr,
|
|
@@ -838,12 +1213,16 @@ export {
|
|
|
838
1213
|
enumColumn as enum,
|
|
839
1214
|
eq,
|
|
840
1215
|
every,
|
|
1216
|
+
explain,
|
|
1217
|
+
external,
|
|
1218
|
+
fragment2 as fragment,
|
|
841
1219
|
gt,
|
|
842
1220
|
gte,
|
|
843
1221
|
has,
|
|
844
1222
|
hasAnyKey,
|
|
845
1223
|
hasKey,
|
|
846
1224
|
id2 as id,
|
|
1225
|
+
ident2 as ident,
|
|
847
1226
|
identity2 as identity,
|
|
848
1227
|
ilike,
|
|
849
1228
|
inList,
|
|
@@ -881,6 +1260,7 @@ export {
|
|
|
881
1260
|
path,
|
|
882
1261
|
point,
|
|
883
1262
|
rank2 as rank,
|
|
1263
|
+
raw,
|
|
884
1264
|
real,
|
|
885
1265
|
relevance,
|
|
886
1266
|
rowNumber2 as rowNumber,
|
|
@@ -52,6 +52,17 @@ export declare function introspectSchema(runner: CatalogQuery, concrete: string,
|
|
|
52
52
|
* Types only, comma-separated, no spaces. Argument names are left out.
|
|
53
53
|
*/
|
|
54
54
|
export declare const FUNCTION_ARG_TYPES = "replace(oidvectortypes(p.proargtypes), ' ', '')";
|
|
55
|
+
/**
|
|
56
|
+
* The `BEGIN ATOMIC` block inside `pg_get_functiondef`.
|
|
57
|
+
*
|
|
58
|
+
* A definition that does not contain that block is returned whole. The slice
|
|
59
|
+
* stops at the last `END`, which is the block closer. A `CASE` closer earlier
|
|
60
|
+
* in the reprint stays inside the block.
|
|
61
|
+
*
|
|
62
|
+
* @param definition - `pg_get_functiondef` text
|
|
63
|
+
* @returns The body introspection stores
|
|
64
|
+
*/
|
|
65
|
+
export declare function atomicBody(definition: string): string;
|
|
55
66
|
/**
|
|
56
67
|
* Applies one expression as a check and reads Postgres's reprint.
|
|
57
68
|
*
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
declare const brand: unique symbol;
|
|
8
8
|
declare const RUNTIME: unique symbol;
|
|
9
9
|
/** Operator names the read path compiles. */
|
|
10
|
-
export type OperatorName = "eq" | "lt" | "lte" | "gt" | "gte" | "between" | "startsWith" | "contains" | "endsWith" | "like" | "ilike" | "inList" | "notIn" | "not" | "or" | "and" | "has" | "none" | "every" | "inc" | "containedBy" | "overlaps" | "hasKey" | "hasAnyKey" | "path" | "matches" | "relevance" | "similar" | "wordSimilar" | "json.set" | "arr.append" | "arr.remove";
|
|
10
|
+
export type OperatorName = "eq" | "lt" | "lte" | "gt" | "gte" | "between" | "startsWith" | "contains" | "endsWith" | "like" | "ilike" | "inList" | "notIn" | "not" | "or" | "and" | "has" | "none" | "every" | "inc" | "containedBy" | "overlaps" | "hasKey" | "hasAnyKey" | "path" | "matches" | "relevance" | "similar" | "wordSimilar" | "sql" | "json.set" | "arr.append" | "arr.remove";
|
|
11
11
|
/** A tagged operator. `value` is the operand the helper stored. */
|
|
12
12
|
export type Tagged<Name extends OperatorName, V> = {
|
|
13
13
|
readonly [brand]: Name;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Composed SQL fragments (rule 15, D266).
|
|
3
|
+
*
|
|
4
|
+
* The check-constraint `sql` tag stays a string. A query fragment is a tagged
|
|
5
|
+
* operator named `sql`, so the planner compiles it on the existing lazy
|
|
6
|
+
* operator path. Values are parameters. `ident` stores a name the compiler
|
|
7
|
+
* quotes. `fragment.column` is the where field the fragment is attached to.
|
|
8
|
+
*/
|
|
9
|
+
import { type Eq } from "../operators.js";
|
|
10
|
+
import type { Window } from "./window.js";
|
|
11
|
+
declare const identBrand: unique symbol;
|
|
12
|
+
declare const columnBrand: unique symbol;
|
|
13
|
+
/** One piece of a fragment. The compiler walks this list. */
|
|
14
|
+
export type FragmentPart = {
|
|
15
|
+
readonly k: "t";
|
|
16
|
+
readonly s: string;
|
|
17
|
+
} | {
|
|
18
|
+
readonly k: "p";
|
|
19
|
+
readonly v: string;
|
|
20
|
+
} | {
|
|
21
|
+
readonly k: "n";
|
|
22
|
+
} | {
|
|
23
|
+
readonly k: "i";
|
|
24
|
+
readonly n: string;
|
|
25
|
+
} | {
|
|
26
|
+
readonly k: "c";
|
|
27
|
+
} | {
|
|
28
|
+
readonly k: "f";
|
|
29
|
+
readonly parts: readonly FragmentPart[];
|
|
30
|
+
};
|
|
31
|
+
/** A name `ident` stored. The compiler quotes it. */
|
|
32
|
+
export type FragmentIdent = {
|
|
33
|
+
readonly [identBrand]: string;
|
|
34
|
+
};
|
|
35
|
+
/** The where field a fragment is attached to. */
|
|
36
|
+
export type FragmentColumn = {
|
|
37
|
+
readonly [columnBrand]: true;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* A composed fragment.
|
|
41
|
+
*
|
|
42
|
+
* It is a where operand. `.as(name)` is the select form, and that result is a
|
|
43
|
+
* number.
|
|
44
|
+
*/
|
|
45
|
+
export type Fragment = Eq<never> & {
|
|
46
|
+
/**
|
|
47
|
+
* Names the select result.
|
|
48
|
+
*
|
|
49
|
+
* @typeParam A - Result key
|
|
50
|
+
* @param name - Result key. Not a column name
|
|
51
|
+
* @returns A select entry
|
|
52
|
+
*/
|
|
53
|
+
as<const A extends string>(name: A): Window<A, number>;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Reports whether `value` is the part list `fragment` stored.
|
|
57
|
+
*
|
|
58
|
+
* @param value - Operator operand
|
|
59
|
+
* @returns `true` when every part has a known kind
|
|
60
|
+
*/
|
|
61
|
+
export declare function isFragmentParts(value: unknown): value is readonly FragmentPart[];
|
|
62
|
+
/**
|
|
63
|
+
* Reads a select fragment.
|
|
64
|
+
*
|
|
65
|
+
* @param value - One `select` entry
|
|
66
|
+
* @returns The result name and the parts, or `undefined` when it is not a fragment
|
|
67
|
+
*/
|
|
68
|
+
export declare function readSelectFragment(value: unknown): {
|
|
69
|
+
readonly as: string;
|
|
70
|
+
readonly parts: readonly FragmentPart[];
|
|
71
|
+
readonly textual?: true;
|
|
72
|
+
} | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* A function call stored as a `sql` fragment.
|
|
75
|
+
*
|
|
76
|
+
* The planner compiles it on the same path as {@link fragment}. `textual`
|
|
77
|
+
* makes `.as(name)` keep the wire string. A numeric call parses a number.
|
|
78
|
+
*
|
|
79
|
+
* @param parts - Expression parts, including the function name
|
|
80
|
+
* @param textual - When true, a select result stays text
|
|
81
|
+
* @returns A where operand. Call `.as(name)` to use it in `select`
|
|
82
|
+
*/
|
|
83
|
+
export declare function sqlExpression(parts: readonly FragmentPart[], textual?: boolean): Fragment;
|
|
84
|
+
/**
|
|
85
|
+
* Reads the field name `ident` stored.
|
|
86
|
+
*
|
|
87
|
+
* @param value - A fragment interpolation
|
|
88
|
+
* @returns The field name, or `undefined` when `value` is not an ident
|
|
89
|
+
*/
|
|
90
|
+
export declare function identName(value: unknown): string | undefined;
|
|
91
|
+
/**
|
|
92
|
+
* A composed SQL fragment.
|
|
93
|
+
*
|
|
94
|
+
* `column` is the where field this fragment is attached to.
|
|
95
|
+
*/
|
|
96
|
+
export declare const fragment: {
|
|
97
|
+
/**
|
|
98
|
+
* Builds a composed SQL fragment.
|
|
99
|
+
*
|
|
100
|
+
* @param strings - Literal SQL
|
|
101
|
+
* @param values - Parameters, identifiers, the column, or nested fragments
|
|
102
|
+
* @returns A where operand
|
|
103
|
+
*/
|
|
104
|
+
(strings: TemplateStringsArray, ...values: readonly unknown[]): Fragment;
|
|
105
|
+
/** The where field this fragment is attached to, quoted by the compiler. */
|
|
106
|
+
readonly column: FragmentColumn;
|
|
107
|
+
};
|
|
108
|
+
/**
|
|
109
|
+
* Stores a field name for a fragment to resolve.
|
|
110
|
+
*
|
|
111
|
+
* The name is the TypeScript field, the same name `where` uses. Casing and
|
|
112
|
+
* `sqlName` are applied when the compiler quotes the column. A hidden field
|
|
113
|
+
* is OKM1120 at planning. Empty names and control characters are OKM1122.
|
|
114
|
+
*
|
|
115
|
+
* @param name - Field name
|
|
116
|
+
* @returns A value `fragment` resolves against the table
|
|
117
|
+
*/
|
|
118
|
+
export declare function ident(name: string): FragmentIdent;
|
|
119
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed raw SQL and `explain()` (P103, P104, D268).
|
|
3
|
+
*
|
|
4
|
+
* Exported from `okmodel/pg`. An app that does not import them drops this
|
|
5
|
+
* module. The table handle carries the session under `Symbol.for("okm.lane")`.
|
|
6
|
+
* The statement class is explicit. Parameters come from the fragment. The
|
|
7
|
+
* tenant predicate, when it applies, is written outside the fragment.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* What `explain()` returns.
|
|
11
|
+
*
|
|
12
|
+
* `plan` is null in production, and `params` is empty there.
|
|
13
|
+
*/
|
|
14
|
+
export type ExplainResult = {
|
|
15
|
+
/** The statement `explain` describes. */
|
|
16
|
+
readonly text: string;
|
|
17
|
+
/** Bound parameters. Empty in production. */
|
|
18
|
+
readonly params: readonly (string | null)[];
|
|
19
|
+
/** `EXPLAIN` lines, or null when the statement was not sent. */
|
|
20
|
+
readonly plan: readonly string[] | null;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Runs one typed raw statement on a table handle.
|
|
24
|
+
*
|
|
25
|
+
* `cls` is constructed once per row. Own enumerable keys of that instance, in
|
|
26
|
+
* order, are the result columns. A key that is a field of the table uses that
|
|
27
|
+
* field's decode. Any other key uses the initializer: a number, a boolean, or
|
|
28
|
+
* driver text. `null` stays `null`.
|
|
29
|
+
*
|
|
30
|
+
* @typeParam C - Result class. Each row is an instance
|
|
31
|
+
* @param handle - Table handle (`db.notes`, including one from `for()`)
|
|
32
|
+
* @param cls - Class with an initializer on every result column
|
|
33
|
+
* @param statement - `"read"` or `"write"`
|
|
34
|
+
* @param source - A `fragment` template. Identifiers are `ident(name)`
|
|
35
|
+
* @returns One instance per row
|
|
36
|
+
*/
|
|
37
|
+
export declare function raw<C extends new () => object>(handle: object, cls: C, statement: "read" | "write", source: unknown): Promise<InstanceType<C>[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Describes a query.
|
|
40
|
+
*
|
|
41
|
+
* Outside production this sends `EXPLAIN` and returns the lines. In production
|
|
42
|
+
* (`NODE_ENV` is `"production"`) it does not send the statement. `plan` is
|
|
43
|
+
* null and `params` is empty.
|
|
44
|
+
*
|
|
45
|
+
* @param handle - Table handle that owns the query's session
|
|
46
|
+
* @param query - A query from that table. `sql()` is the statement
|
|
47
|
+
* @returns The statement and, outside production, the plan lines
|
|
48
|
+
*/
|
|
49
|
+
export declare function explain(handle: object, query: object): Promise<ExplainResult>;
|