okmodel 0.5.1 → 0.7.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 -1116
- package/dist/adapters/capabilities.d.ts +3 -0
- package/dist/adapters/failure.d.ts +13 -2
- package/dist/adapters/lazy-errors.d.ts +22 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +54 -3
- package/dist/adapters/pg/bunsql.d.ts +14 -1
- package/dist/adapters/pg/cursor.d.ts +17 -0
- package/dist/adapters/pg/no-inflight-timeout.d.ts +20 -0
- 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 +41 -3
- package/dist/adapters/pg/reserved.d.ts +42 -0
- package/dist/adapters/pg/session.d.ts +0 -18
- package/dist/contracts/catalog/document.d.ts +19 -5
- package/dist/contracts/catalog/object.d.ts +2 -1
- package/dist/contracts/catalog/policy.d.ts +48 -0
- package/dist/contracts/catalog/types.d.ts +25 -1
- package/dist/contracts/catalog/view.d.ts +2 -0
- package/dist/contracts/connection.d.ts +7 -6
- package/dist/contracts/internal.js +1 -1
- package/dist/contracts/location.d.ts +10 -0
- package/dist/dialects/pg/column.d.ts +13 -2
- package/dist/dialects/pg/ddl.d.ts +37 -1
- package/dist/dialects/pg/emit.d.ts +19 -1
- package/dist/dialects/pg/errors.d.ts +32 -1
- package/dist/dialects/pg/ext/citext.js +1 -1
- package/dist/dialects/pg/ext/index.js +1 -1
- package/dist/dialects/pg/ext/pg-trgm.js +1 -1
- package/dist/dialects/pg/filter-parse.d.ts +5 -4
- package/dist/dialects/pg/floor.d.ts +68 -0
- package/dist/dialects/pg/fn/index.js +2 -2
- package/dist/dialects/pg/index.d.ts +8 -2
- package/dist/dialects/pg/index.js +67 -171
- package/dist/dialects/pg/introspect.d.ts +7 -0
- package/dist/dialects/pg/keys.d.ts +11 -8
- package/dist/dialects/pg/model.d.ts +47 -2
- 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/inc.d.ts +2 -2
- 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/owner.d.ts +42 -0
- package/dist/dialects/pg/path-endpoint.d.ts +20 -0
- package/dist/dialects/pg/preset.d.ts +1 -1
- package/dist/dialects/pg/relations.d.ts +100 -3
- package/dist/dialects/pg/role/check.d.ts +3 -0
- package/dist/dialects/pg/role/index.d.ts +71 -6
- package/dist/dialects/pg/role/sql.d.ts +11 -0
- package/dist/dialects/pg/schema.d.ts +33 -3
- package/dist/dialects/pg/table.d.ts +25 -3
- package/dist/dialects/pg/tenancy.d.ts +45 -3
- package/dist/dialects/pg/view/client.d.ts +19 -1
- package/dist/dialects/pg/view/index.d.ts +4 -0
- package/dist/dialects/pg/view/index.js +21 -178
- package/dist/dialects/pg/view/refresh.d.ts +24 -0
- package/dist/runtime/aggregate.d.ts +8 -2
- package/dist/runtime/batch.d.ts +1 -1
- package/dist/runtime/bucket-group.d.ts +70 -0
- package/dist/runtime/conflict.d.ts +24 -6
- package/dist/runtime/drift.d.ts +9 -0
- package/dist/runtime/include.d.ts +0 -8
- package/dist/runtime/inflight.d.ts +14 -0
- package/dist/runtime/page.d.ts +4 -1
- package/dist/runtime/pg/bun.js +12 -5
- package/dist/runtime/pg/pg.js +5 -5
- package/dist/runtime/pg/pglite.d.ts +1 -0
- package/dist/runtime/pg/pglite.js +9 -8
- package/dist/runtime/pg/postgresjs.js +5 -5
- package/dist/runtime/plan.d.ts +113 -15
- package/dist/runtime/predicate.d.ts +19 -0
- package/dist/runtime/read-stream.d.ts +13 -16
- package/dist/runtime/result-name.d.ts +17 -0
- package/dist/runtime/safety/index.js +1 -1
- 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/sync.d.ts +70 -0
- package/dist/runtime/tenancy/composite.d.ts +26 -0
- package/dist/runtime/tenancy/context.d.ts +16 -0
- package/dist/runtime/tenancy/index.d.ts +9 -5
- package/dist/runtime/tenancy/index.js +1511 -38
- package/dist/runtime/tenancy/path.d.ts +87 -0
- package/dist/runtime/tenancy/rls.d.ts +67 -0
- package/dist/runtime/tenancy/via.d.ts +22 -0
- package/dist/runtime/text-search.d.ts +20 -0
- package/dist/runtime/traits/index.d.ts +80 -0
- package/dist/runtime/traits/index.js +187 -17
- package/dist/runtime/tree.d.ts +38 -0
- package/dist/runtime/types.d.ts +231 -23
- 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 +55 -3
- package/dist/shared/{krxx77g0.js → 14vx95q4.js} +12 -18
- package/dist/shared/1est4ezg.js +313 -0
- package/dist/shared/{4az561fn.js → 1qa0qajz.js} +8 -23
- package/dist/shared/1w508jbr.js +1611 -0
- package/dist/shared/2c13q96h.js +18 -0
- package/dist/shared/2d3xq4ps.js +9 -0
- package/dist/shared/2shdbn8q.js +23 -0
- package/dist/shared/{t4tbsy9h.js → 358zsv4r.js} +1 -1
- package/dist/shared/3v7t1yrv.js +208 -0
- package/dist/shared/5e3tf63j.js +220 -0
- package/dist/shared/5fe3kbsh.js +10 -0
- package/dist/shared/5v3xf80k.js +37 -0
- package/dist/shared/{51mvgj8w.js → 63qtkrca.js} +130 -3
- package/dist/shared/{gbtcc2d7.js → 67txcrcw.js} +62 -66
- package/dist/shared/79dt02vc.js +12 -0
- package/dist/shared/{v36c5g6p.js → 7k9grvf6.js} +407 -14
- package/dist/shared/7kms6fvj.js +20 -0
- package/dist/shared/7mnme5tn.js +8 -0
- package/dist/shared/7n7ddwt4.js +6 -0
- package/dist/shared/{87jvvhnt.js → 81ebdx9p.js} +48 -68
- package/dist/shared/{szm0cksa.js → 8skf0cam.js} +34 -6
- package/dist/shared/{gjthds9j.js → 9628a9xt.js} +1 -1
- package/dist/shared/9a4ae4p8.js +31 -0
- package/dist/shared/{8xsbagad.js → 9s0ypp87.js} +88 -7
- package/dist/shared/9y3mmmh1.js +436 -0
- package/dist/shared/ab9gmbwy.js +213 -0
- package/dist/shared/{sycnx8gt.js → ax7qv55k.js} +18 -8
- package/dist/shared/{f5cw5q5r.js → aytqh5y2.js} +6 -4
- package/dist/shared/{fancm5pt.js → b5pftnn2.js} +138 -15
- package/dist/shared/{efmy2gcg.js → b76b8d95.js} +2 -2
- package/dist/shared/bdk4sty6.js +58 -0
- package/dist/shared/{32zqc1dw.js → bg3rym3g.js} +63 -32
- package/dist/shared/{0t22wwh1.js → bm22fvzr.js} +16 -14
- package/dist/shared/bz84tkzm.js +342 -0
- package/dist/shared/{31vm914h.js → cm3w0ywp.js} +15 -16
- package/dist/shared/cn957f8d.js +179 -0
- package/dist/shared/{pf0d8f77.js → cnkky55j.js} +25 -14
- package/dist/shared/{5fqx9yh4.js → dk8v79p3.js} +3 -1
- package/dist/shared/{nkaxvt9q.js → dkxgzaqd.js} +224 -19
- package/dist/shared/dzj09cye.js +10 -0
- package/dist/shared/{4m9fn52z.js → ed0b8k4s.js} +1 -1
- package/dist/shared/{z2rnngj4.js → ek2wt2dz.js} +8 -5
- package/dist/shared/exn3sd90.js +359 -0
- package/dist/shared/g6evj1j3.js +66 -0
- package/dist/shared/ga9j92qj.js +25 -0
- package/dist/shared/{qv2ydck9.js → gs74dbj5.js} +651 -76
- package/dist/shared/gzaveazc.js +285 -0
- package/dist/shared/{8rsy3hxz.js → h15jx9bc.js} +1 -1
- package/dist/shared/{dyj86cmj.js → hyh73qk6.js} +3 -3
- package/dist/shared/je4axnm8.js +22 -0
- package/dist/shared/{ycatkxmq.js → jgqj11w4.js} +1 -1
- package/dist/shared/{6qd27mx0.js → jvd0mqag.js} +5 -5
- package/dist/shared/jznfax0y.js +155 -0
- package/dist/shared/{cgbamx3e.js → kb2sdhfb.js} +7 -4
- package/dist/shared/{ps7a6h14.js → kr0jzbw2.js} +12 -8
- package/dist/shared/{janx09m5.js → ktz42yez.js} +20 -8
- package/dist/shared/{gde73es6.js → m6p12kbr.js} +56 -55
- package/dist/shared/{r6nwkxnt.js → m7n9h2a5.js} +4 -4
- package/dist/shared/{672t5vym.js → mss6ctgv.js} +2 -2
- package/dist/shared/{nxdp2ze3.js → mtaszv5a.js} +144 -12
- package/dist/shared/n816peh1.js +45 -0
- package/dist/shared/nbw1z4yd.js +18 -0
- package/dist/shared/{cctw17hj.js → p6qc5gcp.js} +38 -34
- package/dist/shared/{6rk2gen5.js → pbp1ss85.js} +20 -17
- package/dist/shared/pt94kz7f.js +6 -0
- package/dist/shared/{wq9n6pwr.js → pz6rj8ay.js} +82 -9
- package/dist/shared/q5c6ngn3.js +13 -0
- package/dist/shared/{8bwbwy8h.js → qq3899ht.js} +128 -18
- package/dist/shared/{8ktwd3rh.js → r3j8s5y0.js} +1 -1
- package/dist/shared/rhs3xe4k.js +7 -0
- package/dist/shared/{ntneex2a.js → rpycarcr.js} +6 -6
- package/dist/shared/{sdc7r2ww.js → rs73fca9.js} +8 -8
- package/dist/shared/{tm5ab8we.js → sfz1ksn6.js} +7 -4
- package/dist/shared/{6mnp99hx.js → svncdeh5.js} +16 -12
- package/dist/shared/{hf22e0wt.js → tbrvgw6z.js} +62 -42
- package/dist/shared/te5as7z7.js +622 -0
- package/dist/shared/{ga3sfy93.js → tsvww22q.js} +535 -200
- package/dist/shared/{47x8x9ze.js → ttsqgp4p.js} +20 -13
- package/dist/shared/{x72jb7ad.js → v8g1vgv8.js} +1 -1
- package/dist/shared/vb6qfyve.js +152 -0
- package/dist/shared/{r2sp8hrc.js → vczs8gd4.js} +22 -13
- package/dist/shared/{1g0drakv.js → vqrjpcqn.js} +145 -3
- package/dist/shared/{2pqx26h8.js → w72kgg4q.js} +31 -22
- package/dist/shared/{96qcj21c.js → w79hsckn.js} +16 -51
- package/dist/shared/wa07eas9.js +730 -0
- package/dist/shared/{k8v5v5wj.js → x933k9a3.js} +75 -34
- package/dist/shared/{cr74e96e.js → xhfsfkgk.js} +62 -28
- package/dist/shared/xjk7hnn5.js +272 -0
- package/dist/shared/{5enne4ma.js → xnxsed62.js} +66 -113
- package/dist/shared/xqve9598.js +53 -0
- package/dist/shared/{9x25fxhc.js → y34a8714.js} +1 -1
- package/dist/shared/{k7dwkhvq.js → y6jdds7g.js} +4 -1
- package/dist/shared/y6njgyda.js +249 -0
- package/dist/shared/{c9z5g0fm.js → ywr8hmey.js} +5 -2
- package/dist/shared/{g7ez901n.js → ywspezzx.js} +1 -1
- package/dist/shared/z7s6fpxv.js +62 -0
- package/dist/shared/{n7mcc1gk.js → zchaghkf.js} +4 -3
- package/dist/shared/{9m80mkac.js → ze4hxsmy.js} +1 -1
- package/dist/shared/zm0ptry0.js +40 -0
- package/dist/shared/{nsva2a6b.js → znm0bpp5.js} +3 -0
- package/dist/shared/zp9fmend.js +145 -0
- package/dist/shared/{y005b761.js → zy8r7qvz.js} +6 -2
- package/dist/tooling/cli.js +41 -15
- package/dist/tooling/migrate/apply.d.ts +14 -0
- package/dist/tooling/migrate/check.d.ts +3 -4
- package/dist/tooling/migrate/classify.d.ts +4 -0
- package/dist/tooling/migrate/config.d.ts +3 -2
- package/dist/tooling/migrate/engine.d.ts +3 -2
- package/dist/tooling/migrate/files.d.ts +11 -1
- package/dist/tooling/migrate/index.js +14 -14
- package/dist/tooling/migrate/lint.d.ts +1 -1
- package/dist/tooling/migrate/lost.d.ts +28 -0
- package/dist/tooling/migrate/paths.d.ts +14 -0
- package/dist/tooling/migrate/plan.d.ts +6 -3
- package/dist/tooling/migrate/runner.d.ts +25 -0
- package/dist/tooling/migrate/sandbox.d.ts +57 -0
- package/dist/tooling/migrate/sql-lex.d.ts +20 -3
- package/dist/tooling/migrate/text.d.ts +42 -0
- package/dist/tooling/node-version.d.ts +21 -0
- package/dist/tooling/testing/facts.d.ts +33 -5
- package/dist/tooling/testing/index.d.ts +1 -1
- package/dist/tooling/testing/index.js +3 -3
- package/dist/tooling/testing/isolation.d.ts +11 -5
- package/package.json +8 -3
- package/dist/shared/7m88x3e9.js +0 -45
- package/dist/shared/7zwwyh0v.js +0 -448
- package/dist/shared/aj2qxyhj.js +0 -90
- package/dist/shared/caw8b9d8.js +0 -204
- package/dist/shared/jwtxdj06.js +0 -76
- package/dist/shared/kfjp0gck.js +0 -212
- package/dist/shared/q58y17hy.js +0 -21
- package/dist/shared/qm7cdtvr.js +0 -912
- package/dist/shared/r8x5qhd7.js +0 -86
- package/dist/shared/zqrnhwsq.js +0 -31
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isConnectionSqlstate,
|
|
3
3
|
isConnectionFailure
|
|
4
|
-
} from "./
|
|
4
|
+
} from "./cnkky55j.js";
|
|
5
5
|
import {
|
|
6
6
|
OkmError2,
|
|
7
7
|
stripRowValues,
|
|
@@ -14,10 +14,13 @@ function mapPostgresError(error, options) {
|
|
|
14
14
|
return error;
|
|
15
15
|
if (!isDriverError(error))
|
|
16
16
|
return OkmError2.from(error);
|
|
17
|
+
const search = searchInputError(error);
|
|
18
|
+
if (search !== undefined)
|
|
19
|
+
return search;
|
|
17
20
|
const kind = kindOf(error);
|
|
18
21
|
const columns = columnsOf(error);
|
|
19
22
|
const hint = hintOf(error, kind);
|
|
20
|
-
const fieldReason = hint?.reason ?? (kind === "not_null" ? "not_null" : reasonOf(kind, error.table, error.constraint));
|
|
23
|
+
const fieldReason = hint?.reason ?? (kind === "not_null" ? "not_null" : reasonOf(kind, error.table, error.constraint, columns, options?.schema));
|
|
21
24
|
const values = options?.includeValues === true ? valuesOf(error.detail, columns) : undefined;
|
|
22
25
|
const code = kind === "outcome_unknown" ? "OKM1401" : kind;
|
|
23
26
|
return new OkmError2(code, summaryOf(kind, error, columns, fieldReason), {
|
|
@@ -45,6 +48,36 @@ function isDriverError(error) {
|
|
|
45
48
|
return false;
|
|
46
49
|
return "batchIndex" in error;
|
|
47
50
|
}
|
|
51
|
+
function searchQuery(error) {
|
|
52
|
+
const cause = error.cause;
|
|
53
|
+
if (typeof cause !== "object" || cause === null)
|
|
54
|
+
return false;
|
|
55
|
+
const query = Reflect.get(cause, "query");
|
|
56
|
+
return typeof query === "string" && query.includes("to_tsquery");
|
|
57
|
+
}
|
|
58
|
+
function searchInputError(error) {
|
|
59
|
+
const sqlstate = error.sqlstate;
|
|
60
|
+
const message = error.message;
|
|
61
|
+
if (sqlstate === "42601" && (message.includes("tsquery") || searchQuery(error))) {
|
|
62
|
+
return new OkmError2("OKM1120", `Search input is not valid. ${stripRowValues(message)}`, {
|
|
63
|
+
kind: "invalid",
|
|
64
|
+
sqlstate,
|
|
65
|
+
cause: error.cause ?? error,
|
|
66
|
+
fix: { summary: "Fix the advanced search text, or use natural, all-words, or phrase." }
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (sqlstate === "42704" && message.includes("text search configuration") && message.includes("does not exist")) {
|
|
70
|
+
return new OkmError2("OKM1122", stripRowValues(message), {
|
|
71
|
+
kind: "invalid",
|
|
72
|
+
sqlstate,
|
|
73
|
+
cause: error.cause ?? error,
|
|
74
|
+
fix: {
|
|
75
|
+
summary: "Use a text search configuration that exists, such as english, or omit language."
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
48
81
|
function kindOf(error) {
|
|
49
82
|
if (error.kind === "timeout" || error.kind === "cancelled" || error.kind === "outcome_unknown") {
|
|
50
83
|
return error.kind;
|
|
@@ -70,11 +103,39 @@ function hintOf(error, kind) {
|
|
|
70
103
|
return { reason: "undefined_table", fix: MIGRATE_FIX };
|
|
71
104
|
if (error.sqlstate === "42703")
|
|
72
105
|
return { reason: "undefined_column", fix: MIGRATE_FIX };
|
|
106
|
+
const refresh = refreshHint(error);
|
|
107
|
+
if (refresh !== undefined)
|
|
108
|
+
return refresh;
|
|
73
109
|
if (kind === "unavailable" && error.sqlstate === undefined && isTlsFailure(error)) {
|
|
74
110
|
return { reason: "tls", fix: TLS_FIX };
|
|
75
111
|
}
|
|
76
112
|
return;
|
|
77
113
|
}
|
|
114
|
+
function refreshHint(error) {
|
|
115
|
+
if (error.sqlstate === "0A000" && error.message.includes("materialized view is not populated")) {
|
|
116
|
+
return {
|
|
117
|
+
reason: "not_populated",
|
|
118
|
+
fix: { summary: "Refresh once without CONCURRENTLY so the view is populated." }
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
if (error.sqlstate === "55000" && error.message.includes("cannot refresh materialized view") && error.message.includes("concurrently")) {
|
|
122
|
+
return {
|
|
123
|
+
reason: "no_unique_index",
|
|
124
|
+
fix: {
|
|
125
|
+
summary: "Add a unique index with no WHERE clause, or refresh without CONCURRENTLY."
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (error.sqlstate === "42501" && error.message.includes("materialized view")) {
|
|
130
|
+
return {
|
|
131
|
+
reason: "not_owner",
|
|
132
|
+
fix: {
|
|
133
|
+
summary: "Refresh runs as the owner, the migration role. Connect as that role and call refresh(), or run REFRESH MATERIALIZED VIEW as that role. The application role is not the owner."
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
78
139
|
function kindFromSqlstate(sqlstate) {
|
|
79
140
|
switch (sqlstate) {
|
|
80
141
|
case "23505":
|
|
@@ -112,7 +173,15 @@ function kindFromSqlstate(sqlstate) {
|
|
|
112
173
|
return;
|
|
113
174
|
}
|
|
114
175
|
}
|
|
115
|
-
function reasonOf(kind, table, constraint) {
|
|
176
|
+
function reasonOf(kind, table, constraint, columns, schema) {
|
|
177
|
+
if (schema !== undefined && schema.catalog !== undefined && table !== undefined) {
|
|
178
|
+
const matched = matchObject(schema.catalog, table, constraint, columns);
|
|
179
|
+
if (matched !== undefined)
|
|
180
|
+
return reasonFromObject(schema, table, matched, columns);
|
|
181
|
+
}
|
|
182
|
+
return reasonFromName(kind, table, constraint);
|
|
183
|
+
}
|
|
184
|
+
function reasonFromName(kind, table, constraint) {
|
|
116
185
|
if (constraint === undefined || constraint.length === 0)
|
|
117
186
|
return kind;
|
|
118
187
|
if (table !== undefined) {
|
|
@@ -128,6 +197,61 @@ function reasonOf(kind, table, constraint) {
|
|
|
128
197
|
}
|
|
129
198
|
return constraint;
|
|
130
199
|
}
|
|
200
|
+
function matchObject(catalog, table, constraint, columns) {
|
|
201
|
+
const rows = [];
|
|
202
|
+
for (const object of catalog.objects) {
|
|
203
|
+
if (object.kind !== "constraint" && object.kind !== "index")
|
|
204
|
+
continue;
|
|
205
|
+
if (object.identity.parent.name !== table)
|
|
206
|
+
continue;
|
|
207
|
+
rows.push(object);
|
|
208
|
+
}
|
|
209
|
+
if (columns.length > 0) {
|
|
210
|
+
const key = columns.join(",");
|
|
211
|
+
const hits = rows.filter((object) => object.definition.columns.join(",") === key);
|
|
212
|
+
if (constraint !== undefined) {
|
|
213
|
+
const named = hits.find((object) => object.identity.name === constraint);
|
|
214
|
+
if (named !== undefined)
|
|
215
|
+
return named;
|
|
216
|
+
}
|
|
217
|
+
const only = hits.length === 1 ? hits[0] : undefined;
|
|
218
|
+
if (only !== undefined)
|
|
219
|
+
return only;
|
|
220
|
+
}
|
|
221
|
+
if (constraint === undefined)
|
|
222
|
+
return;
|
|
223
|
+
return rows.find((object) => object.identity.name === constraint);
|
|
224
|
+
}
|
|
225
|
+
function reasonFromObject(schema, table, object, columns) {
|
|
226
|
+
if (object.kind === "index")
|
|
227
|
+
return object.identity.name;
|
|
228
|
+
const nameKey = object.definition.nameKey;
|
|
229
|
+
if (columns.length === 0)
|
|
230
|
+
return nameKey;
|
|
231
|
+
const sqlKey = object.definition.columns.join("_");
|
|
232
|
+
if (nameKey !== sqlKey || object.definition.columns.length < 2)
|
|
233
|
+
return nameKey;
|
|
234
|
+
return fieldKey(schema, table, object.definition.columns) ?? nameKey;
|
|
235
|
+
}
|
|
236
|
+
function fieldKey(schema, table, columns) {
|
|
237
|
+
let model;
|
|
238
|
+
for (const item of Object.values(schema.model)) {
|
|
239
|
+
if (item.sql === table) {
|
|
240
|
+
model = item;
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
if (model === undefined)
|
|
245
|
+
return;
|
|
246
|
+
const fields = [];
|
|
247
|
+
for (const column of columns) {
|
|
248
|
+
const found = model.columns.find((item) => item.sql === column);
|
|
249
|
+
if (found === undefined)
|
|
250
|
+
return;
|
|
251
|
+
fields.push(found.field);
|
|
252
|
+
}
|
|
253
|
+
return fields.join("_");
|
|
254
|
+
}
|
|
131
255
|
function nameKeyOf(rest) {
|
|
132
256
|
const tags = ["_fkey", "_check", "_key"];
|
|
133
257
|
for (const tag of tags) {
|
|
@@ -212,6 +336,9 @@ function unquote(name) {
|
|
|
212
336
|
}
|
|
213
337
|
function summaryOf(kind, error, columns, fieldReason) {
|
|
214
338
|
const label = labelOf(kind);
|
|
339
|
+
if (kind === "driver" && fieldReason === "not_owner") {
|
|
340
|
+
return "The application role cannot refresh a materialized view. Refresh runs as the owner, the migration role.";
|
|
341
|
+
}
|
|
215
342
|
if (kind === "driver")
|
|
216
343
|
return stripRowValues(error.message);
|
|
217
344
|
const where = place(error.table, columns);
|
|
@@ -41,6 +41,7 @@ var FIND_OPTIONS = [
|
|
|
41
41
|
"include",
|
|
42
42
|
"limit",
|
|
43
43
|
"orderBy",
|
|
44
|
+
"search",
|
|
44
45
|
"select",
|
|
45
46
|
"route",
|
|
46
47
|
"signal",
|
|
@@ -56,12 +57,15 @@ var ONE_OPTIONS = [
|
|
|
56
57
|
"timeout",
|
|
57
58
|
"where"
|
|
58
59
|
];
|
|
60
|
+
var COUNT_OPTIONS = ["route", "search", "signal", "timeout", "where"];
|
|
59
61
|
var FILTER_OPTIONS = ["route", "signal", "timeout", "where"];
|
|
60
62
|
function readOptionNames(op) {
|
|
61
63
|
if (op === "find")
|
|
62
64
|
return FIND_OPTIONS;
|
|
63
65
|
if (op === "one")
|
|
64
66
|
return ONE_OPTIONS;
|
|
67
|
+
if (op === "count")
|
|
68
|
+
return COUNT_OPTIONS;
|
|
65
69
|
return FILTER_OPTIONS;
|
|
66
70
|
}
|
|
67
71
|
var BASE_RULES = [
|
|
@@ -78,7 +82,19 @@ function readNeedsOperatorSql(schema, call) {
|
|
|
78
82
|
if (operatorEmit !== undefined)
|
|
79
83
|
return false;
|
|
80
84
|
const table = indexes(schema).get(call.table);
|
|
81
|
-
|
|
85
|
+
if (table === undefined)
|
|
86
|
+
return false;
|
|
87
|
+
return needsOperatorSql(table, call.where) || orderHasRelevance(call.orderBy);
|
|
88
|
+
}
|
|
89
|
+
function orderHasRelevance(orderBy) {
|
|
90
|
+
if (!isRecord(orderBy))
|
|
91
|
+
return false;
|
|
92
|
+
for (const key of Object.keys(orderBy)) {
|
|
93
|
+
const value = orderBy[key];
|
|
94
|
+
if (isOperator(value) && operatorName(value) === "relevance")
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
82
98
|
}
|
|
83
99
|
function emitRelationFrom(schema, relation, child, sink, parent, alias, depth) {
|
|
84
100
|
if (relation.through !== undefined) {
|
|
@@ -122,12 +138,12 @@ function needsOperatorSql(table, value, key) {
|
|
|
122
138
|
function isTextColumn(dataType) {
|
|
123
139
|
return dataType === "text" || dataType === "citext" || dataType.startsWith("varchar(") || dataType.startsWith("char(") || dataType.startsWith("character");
|
|
124
140
|
}
|
|
125
|
-
function emitLazy(column, ref, name, value, sink) {
|
|
141
|
+
function emitLazy(column, ref, name, value, sink, order) {
|
|
126
142
|
const emit = operatorEmit;
|
|
127
143
|
if (emit === undefined) {
|
|
128
|
-
|
|
144
|
+
fail2("OKM1121", `Operator ${name} on ${column.field} is not loaded.`);
|
|
129
145
|
}
|
|
130
|
-
emit(column, ref, name, value, sink);
|
|
146
|
+
emit(column, ref, name, value, sink, order);
|
|
131
147
|
}
|
|
132
148
|
function verifyRead(schema, call) {
|
|
133
149
|
if (!safetyInstalled())
|
|
@@ -208,7 +224,7 @@ function logicalIntent(call) {
|
|
|
208
224
|
table: call.table,
|
|
209
225
|
where: plain(call.where),
|
|
210
226
|
select: call.select,
|
|
211
|
-
orderBy: call.orderBy,
|
|
227
|
+
orderBy: plain(call.orderBy),
|
|
212
228
|
limit: call.limit,
|
|
213
229
|
include: plain(call.include),
|
|
214
230
|
all: call.all
|
|
@@ -261,7 +277,7 @@ function emitRead(schema, call, sink, outputs, hooks) {
|
|
|
261
277
|
throwNamed2("OKM1120", call.table, [...indexes(schema).keys()], `Table ${call.table} is not in the schema. Accepted names: ${list([...indexes(schema).keys()])}.`);
|
|
262
278
|
}
|
|
263
279
|
if (call.build !== undefined) {
|
|
264
|
-
call.build(schema, table, sink, outputs, call);
|
|
280
|
+
call.build(schema, table, sink, outputs, call, hooks);
|
|
265
281
|
return;
|
|
266
282
|
}
|
|
267
283
|
rejectOptions(call);
|
|
@@ -296,7 +312,7 @@ function emitRead(schema, call, sink, outputs, hooks) {
|
|
|
296
312
|
column += 1;
|
|
297
313
|
}
|
|
298
314
|
if (call.include !== undefined && hooks === undefined) {
|
|
299
|
-
|
|
315
|
+
fail2("OKM1120", "An include needs the include planner.");
|
|
300
316
|
}
|
|
301
317
|
const includes = hooks === undefined || call.include === undefined ? [] : hooks.read(schema, table, call.include, call.all);
|
|
302
318
|
if (selected.length === 0 && includes.length === 0)
|
|
@@ -375,7 +391,7 @@ function emitWhere(schema, table, where, sink, alias, depth, appended = false, e
|
|
|
375
391
|
continue;
|
|
376
392
|
const joined = isOperator(part);
|
|
377
393
|
if (!joined && !isRecord(part))
|
|
378
|
-
|
|
394
|
+
fail2("OKM1121", WHERE_FIELDS);
|
|
379
395
|
if (!joined && Object.keys(part).length === 0)
|
|
380
396
|
continue;
|
|
381
397
|
sink.text(started ? " and " : " where ");
|
|
@@ -389,7 +405,7 @@ function emitWhere(schema, table, where, sink, alias, depth, appended = false, e
|
|
|
389
405
|
var WHERE_FIELDS = "where must be an object of fields. Wrap an object value with eq.";
|
|
390
406
|
function emitAnd(schema, table, where, sink, alias, depth) {
|
|
391
407
|
if (!isRecord(where)) {
|
|
392
|
-
|
|
408
|
+
fail2("OKM1121", WHERE_FIELDS);
|
|
393
409
|
}
|
|
394
410
|
const keys = Object.keys(where);
|
|
395
411
|
let wrote = false;
|
|
@@ -416,6 +432,7 @@ function emitPredicate(schema, table, key, value, sink, alias, depth) {
|
|
|
416
432
|
if (column === undefined) {
|
|
417
433
|
throwNamed2("OKM1120", key, table.names, `Field ${key} is not on ${table.model.name}. Accepted names: ${list(table.names)}.`);
|
|
418
434
|
}
|
|
435
|
+
refuseHidden(column);
|
|
419
436
|
sink.mark(`w:${key}`);
|
|
420
437
|
emitOperand(schema, table, column, value, sink, alias, depth);
|
|
421
438
|
}
|
|
@@ -445,7 +462,7 @@ function emitOperator(schema, table, column, ref, name, value, sink, alias, dept
|
|
|
445
462
|
return;
|
|
446
463
|
}
|
|
447
464
|
if (column === undefined) {
|
|
448
|
-
|
|
465
|
+
fail2("OKM1121", "That operator needs a field.");
|
|
449
466
|
}
|
|
450
467
|
if (name === "not") {
|
|
451
468
|
emitNot(schema, table, column, ref, value, sink, alias, depth);
|
|
@@ -463,7 +480,7 @@ function emitOperator(schema, table, column, ref, name, value, sink, alias, dept
|
|
|
463
480
|
}
|
|
464
481
|
if (name === "between") {
|
|
465
482
|
if (!Array.isArray(value) || value.length !== 2) {
|
|
466
|
-
|
|
483
|
+
fail2("OKM1121", `between on ${column.field} needs two values.`);
|
|
467
484
|
}
|
|
468
485
|
sink.text(ref);
|
|
469
486
|
sink.text(" between ");
|
|
@@ -478,7 +495,7 @@ function emitOperator(schema, table, column, ref, name, value, sink, alias, dept
|
|
|
478
495
|
}
|
|
479
496
|
if (TEXT_OPERATORS.includes(`,${name},`) && isTextColumn(column.dataType)) {
|
|
480
497
|
if (typeof value !== "string") {
|
|
481
|
-
|
|
498
|
+
fail2("OKM1121", `${name} on ${column.field} needs a string.`);
|
|
482
499
|
}
|
|
483
500
|
sink.text(ref);
|
|
484
501
|
if (name === "like" || name === "ilike") {
|
|
@@ -488,7 +505,7 @@ function emitOperator(schema, table, column, ref, name, value, sink, alias, dept
|
|
|
488
505
|
}
|
|
489
506
|
sink.text(" like ");
|
|
490
507
|
if (name !== "startsWith" && name !== "endsWith" && name !== "contains") {
|
|
491
|
-
|
|
508
|
+
fail2("OKM1121", `${name} on ${column.field} needs a string.`);
|
|
492
509
|
}
|
|
493
510
|
sink.param(literalPattern(value, name));
|
|
494
511
|
sink.text(" escape E'\\\\'");
|
|
@@ -516,7 +533,7 @@ function emitNot(schema, table, column, ref, value, sink, alias, depth) {
|
|
|
516
533
|
}
|
|
517
534
|
function emitIn(column, ref, name, value, sink) {
|
|
518
535
|
if (!Array.isArray(value)) {
|
|
519
|
-
|
|
536
|
+
fail2("OKM1121", `${name} on ${column.field} needs a list.`);
|
|
520
537
|
}
|
|
521
538
|
sink.mark(`:${String(value.length)}`);
|
|
522
539
|
if (value.length === 0) {
|
|
@@ -548,7 +565,7 @@ function emitOr(schema, table, value, sink, alias, depth) {
|
|
|
548
565
|
sink.text(" or ");
|
|
549
566
|
sink.text("(");
|
|
550
567
|
if (!isRecord(branch)) {
|
|
551
|
-
|
|
568
|
+
fail2("OKM1121", "or() branches must be where objects.");
|
|
552
569
|
}
|
|
553
570
|
let wrote = false;
|
|
554
571
|
for (const key of Object.keys(branch)) {
|
|
@@ -568,15 +585,15 @@ function emitOr(schema, table, value, sink, alias, depth) {
|
|
|
568
585
|
}
|
|
569
586
|
function emitRelationFilter(schema, relation, value, sink, alias, depth) {
|
|
570
587
|
if (!isOperator(value)) {
|
|
571
|
-
|
|
588
|
+
fail2("OKM1121", `Relation ${relation.name} needs has, none, or every.`);
|
|
572
589
|
}
|
|
573
590
|
const name = operatorName(value);
|
|
574
591
|
if (name !== "has" && name !== "none" && name !== "every") {
|
|
575
|
-
|
|
592
|
+
fail2("OKM1121", `Relation ${relation.name} needs has, none, or every.`);
|
|
576
593
|
}
|
|
577
594
|
const child = indexes(schema).get(relation.table);
|
|
578
595
|
if (child === undefined) {
|
|
579
|
-
|
|
596
|
+
fail2("OKM1120", `Relation ${relation.name} names ${relation.table}, which is not in the schema.`);
|
|
580
597
|
}
|
|
581
598
|
const childAlias = `r${String(depth)}_${relation.name}`;
|
|
582
599
|
sink.mark(`rel:${relation.name}:${name}`);
|
|
@@ -600,7 +617,7 @@ function emitOrder(table, orderBy, sink, alias) {
|
|
|
600
617
|
if (orderBy === undefined)
|
|
601
618
|
return;
|
|
602
619
|
if (!isRecord(orderBy)) {
|
|
603
|
-
|
|
620
|
+
fail2("OKM1120", "orderBy must be an object of fields.");
|
|
604
621
|
}
|
|
605
622
|
const keys = Object.keys(orderBy);
|
|
606
623
|
if (keys.length === 0)
|
|
@@ -614,9 +631,15 @@ function emitOrder(table, orderBy, sink, alias) {
|
|
|
614
631
|
if (column === undefined) {
|
|
615
632
|
throwNamed2("OKM1120", key, table.names, `Field ${key} is not on ${table.model.name}. Accepted names: ${list(table.names)}.`);
|
|
616
633
|
}
|
|
617
|
-
|
|
634
|
+
refuseHidden(column);
|
|
635
|
+
const value = orderBy[key];
|
|
618
636
|
if (index > 0)
|
|
619
637
|
sink.text(", ");
|
|
638
|
+
if (isOperator(value) && operatorName(value) === "relevance") {
|
|
639
|
+
emitLazy(column, `${alias}.${quote(column.sql)}`, "relevance", operatorValue(value), sink, true);
|
|
640
|
+
continue;
|
|
641
|
+
}
|
|
642
|
+
const parsed = parseOrder(key, value);
|
|
620
643
|
sink.text(alias);
|
|
621
644
|
sink.text(".");
|
|
622
645
|
sink.text(quote(column.sql));
|
|
@@ -642,6 +665,11 @@ function emitPrimaryOrder(table, sink, alias) {
|
|
|
642
665
|
sink.text(" asc");
|
|
643
666
|
}
|
|
644
667
|
}
|
|
668
|
+
function refuseHidden(column) {
|
|
669
|
+
if (column.hidden !== true)
|
|
670
|
+
return;
|
|
671
|
+
fail2("OKM1120", `Field ${column.field} is hidden.`, "Call hidden({ filterable: true }).");
|
|
672
|
+
}
|
|
645
673
|
function emitLimit(call, sink) {
|
|
646
674
|
if (call.op === "one") {
|
|
647
675
|
const ordered = call.orderBy !== undefined && isRecord(call.orderBy) && Object.keys(call.orderBy).length > 0;
|
|
@@ -653,7 +681,7 @@ function emitLimit(call, sink) {
|
|
|
653
681
|
return;
|
|
654
682
|
if (call.all !== undefined) {
|
|
655
683
|
if (call.all.length === 0) {
|
|
656
|
-
|
|
684
|
+
fail2("OKM1101", "find() .all needs a reason.");
|
|
657
685
|
}
|
|
658
686
|
sink.mark(`all:${call.all}`);
|
|
659
687
|
if (call.limit !== undefined) {
|
|
@@ -665,7 +693,7 @@ function emitLimit(call, sink) {
|
|
|
665
693
|
return;
|
|
666
694
|
}
|
|
667
695
|
if (call.limit === undefined) {
|
|
668
|
-
|
|
696
|
+
fail2("OKM1101", "find() needs a limit, or .all(reason) when the full set is intentional.");
|
|
669
697
|
}
|
|
670
698
|
const limit = readLimit(call.limit);
|
|
671
699
|
sink.text(" limit ");
|
|
@@ -682,12 +710,12 @@ function selectedColumns(table, select) {
|
|
|
682
710
|
return columns;
|
|
683
711
|
}
|
|
684
712
|
if (!Array.isArray(select)) {
|
|
685
|
-
|
|
713
|
+
fail2("OKM1120", "select must be a list of field names.");
|
|
686
714
|
}
|
|
687
715
|
const columns = [];
|
|
688
716
|
for (const name of select) {
|
|
689
717
|
if (typeof name !== "string") {
|
|
690
|
-
|
|
718
|
+
fail2("OKM1120", "select must be a list of field names.");
|
|
691
719
|
}
|
|
692
720
|
const column = table.columns.get(name);
|
|
693
721
|
if (column === undefined) {
|
|
@@ -705,17 +733,17 @@ function parseOrder(field, value) {
|
|
|
705
733
|
if (isRecord(value)) {
|
|
706
734
|
const dir = value.dir ?? value.direction;
|
|
707
735
|
if (dir !== "asc" && dir !== "desc") {
|
|
708
|
-
|
|
736
|
+
fail2("OKM1120", `orderBy ${field} must be asc or desc.`);
|
|
709
737
|
}
|
|
710
738
|
const nulls = value.nulls;
|
|
711
739
|
if (nulls === undefined)
|
|
712
740
|
return { dir, nulls: dir === "asc" ? "last" : "first" };
|
|
713
741
|
if (nulls !== "first" && nulls !== "last") {
|
|
714
|
-
|
|
742
|
+
fail2("OKM1120", `orderBy ${field} nulls must be first or last.`);
|
|
715
743
|
}
|
|
716
744
|
return { dir, nulls };
|
|
717
745
|
}
|
|
718
|
-
|
|
746
|
+
fail2("OKM1120", `orderBy ${field} must be asc or desc.`);
|
|
719
747
|
}
|
|
720
748
|
function rejectOptions(call) {
|
|
721
749
|
const accepted = readOptionNames(call.op);
|
|
@@ -732,11 +760,11 @@ function rejectOptions(call) {
|
|
|
732
760
|
present.include = call.include;
|
|
733
761
|
rejectKeys(present, accepted, call.op);
|
|
734
762
|
}
|
|
735
|
-
function rejectKeys(value, accepted, where) {
|
|
763
|
+
function rejectKeys(value, accepted, where, search) {
|
|
736
764
|
for (const key of Object.keys(value)) {
|
|
737
765
|
if (accepted.includes(key))
|
|
738
766
|
continue;
|
|
739
|
-
throwNamed2("OKM1120", key, accepted, `Option ${key} is not accepted by ${where}. Accepted options: ${list(accepted)}.`);
|
|
767
|
+
throwNamed2("OKM1120", key, accepted, key === "search" && search === true ? `${where}() does not take search. Pass search to find or count.` : `Option ${key} is not accepted by ${where}. Accepted options: ${list(accepted)}.`);
|
|
740
768
|
}
|
|
741
769
|
}
|
|
742
770
|
function readLimit(value) {
|
|
@@ -747,7 +775,7 @@ function readLimit(value) {
|
|
|
747
775
|
}
|
|
748
776
|
function requireValue(column, value) {
|
|
749
777
|
if (value === undefined || value === null) {
|
|
750
|
-
|
|
778
|
+
fail2("OKM1121", `Field ${column.field} needs a value.`);
|
|
751
779
|
}
|
|
752
780
|
if (typeof value === "object")
|
|
753
781
|
takeObject(column, value);
|
|
@@ -755,7 +783,7 @@ function requireValue(column, value) {
|
|
|
755
783
|
}
|
|
756
784
|
function takeObject(column, value, bare = false) {
|
|
757
785
|
if (bare || !column.accepts?.includes({}.toString.call(value).slice(8, -1))) {
|
|
758
|
-
|
|
786
|
+
fail2("OKM1121", `Field ${column.field} rejects that object.`);
|
|
759
787
|
}
|
|
760
788
|
}
|
|
761
789
|
function projectExpr(sql, dataType) {
|
|
@@ -846,38 +874,6 @@ function list(names) {
|
|
|
846
874
|
function isRecord(value) {
|
|
847
875
|
return typeof value === "object" && value !== null && !Array.isArray(value) && !isOperator(value);
|
|
848
876
|
}
|
|
849
|
-
function effectivePredicate(where) {
|
|
850
|
-
if (where === undefined)
|
|
851
|
-
return false;
|
|
852
|
-
if (isOperator(where)) {
|
|
853
|
-
const name = operatorName(where);
|
|
854
|
-
const value = operatorValue(where);
|
|
855
|
-
if (name === "or") {
|
|
856
|
-
if (!Array.isArray(value))
|
|
857
|
-
orFail(false);
|
|
858
|
-
if (value.length === 0)
|
|
859
|
-
return true;
|
|
860
|
-
for (const branch of value) {
|
|
861
|
-
if (!effectivePredicate(branch))
|
|
862
|
-
orFail(true);
|
|
863
|
-
}
|
|
864
|
-
return true;
|
|
865
|
-
}
|
|
866
|
-
if (name === "and") {
|
|
867
|
-
return Array.isArray(value) && value.some((part) => effectivePredicate(part));
|
|
868
|
-
}
|
|
869
|
-
if (name === "not")
|
|
870
|
-
return effectivePredicate(value);
|
|
871
|
-
return true;
|
|
872
|
-
}
|
|
873
|
-
if (!isRecord(where))
|
|
874
|
-
return true;
|
|
875
|
-
for (const key of Object.keys(where)) {
|
|
876
|
-
if (where[key] !== undefined)
|
|
877
|
-
return true;
|
|
878
|
-
}
|
|
879
|
-
return false;
|
|
880
|
-
}
|
|
881
877
|
function orFail(empty) {
|
|
882
878
|
throw new OkmError2("OKM1121", empty ? "or() branch is empty." : "Pass an array: or([a, b]).", {
|
|
883
879
|
fix: {
|
|
@@ -892,8 +888,8 @@ var FAIL_FIX = {
|
|
|
892
888
|
function registerFailFix(code, summary) {
|
|
893
889
|
FAIL_FIX[code] = summary;
|
|
894
890
|
}
|
|
895
|
-
function
|
|
896
|
-
const summary = FAIL_FIX[code];
|
|
891
|
+
function fail2(code, message, fix) {
|
|
892
|
+
const summary = fix ?? FAIL_FIX[code];
|
|
897
893
|
throw new OkmError2(code, message, summary === undefined ? undefined : { fix: { summary } });
|
|
898
894
|
}
|
|
899
895
|
function plain(value) {
|
|
@@ -916,4 +912,4 @@ function hasMany(include) {
|
|
|
916
912
|
return Object.keys(include).length > 0;
|
|
917
913
|
}
|
|
918
914
|
|
|
919
|
-
export { withRowFilters, installArchiveInspect, archiveRules, readOptionNames, installOperatorSql, readNeedsOperatorSql, emitRelationFrom, bindCall, compileCall, decodeResult, logicalIntent, appliedRules, emitJoin, emitWhere, emitOrder, emitPrimaryOrder, selectedColumns, parseOrder, rejectKeys, readLimit, takeObject, projectExpr, jsonExpr, decodeRow, cell, indexes, quote, list, isRecord,
|
|
915
|
+
export { withRowFilters, installArchiveInspect, archiveRules, readOptionNames, installOperatorSql, readNeedsOperatorSql, orderHasRelevance, emitRelationFrom, needsOperatorSql, bindCall, compileCall, decodeResult, logicalIntent, appliedRules, emitJoin, emitWhere, emitOrder, emitPrimaryOrder, refuseHidden, emitLimit, selectedColumns, parseOrder, rejectKeys, readLimit, takeObject, projectExpr, jsonExpr, decodeRow, cell, indexes, quote, list, isRecord, orFail, registerFailFix, fail2 };
|