okmodel 0.1.1 → 0.3.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 +727 -37
- package/dist/adapters/capabilities.d.ts +34 -0
- package/dist/adapters/pg/bunsql-extra.d.ts +17 -0
- package/dist/adapters/pg/bunsql.d.ts +60 -0
- package/dist/adapters/pg/call.d.ts +2 -12
- package/dist/adapters/pg/nodepostgres-extra.d.ts +18 -0
- package/dist/adapters/pg/nodepostgres.d.ts +57 -0
- package/dist/adapters/pg/postgres-extra.d.ts +50 -1
- package/dist/adapters/pg/postgresjs.d.ts +0 -4
- package/dist/adapters/pg/session.d.ts +94 -0
- package/dist/adapters/pg/watch.d.ts +18 -0
- package/dist/contracts/catalog/enum.d.ts +31 -4
- package/dist/contracts/catalog/extension.d.ts +61 -0
- package/dist/contracts/catalog/object.d.ts +1 -0
- package/dist/contracts/catalog/privilege.d.ts +64 -0
- package/dist/contracts/catalog/routine.d.ts +56 -0
- package/dist/contracts/catalog/types.d.ts +179 -18
- package/dist/contracts/catalog/view.d.ts +73 -0
- package/dist/contracts/connection.d.ts +13 -0
- package/dist/contracts/driver.d.ts +18 -5
- package/dist/contracts/error.d.ts +17 -1
- package/dist/contracts/generator.d.ts +63 -0
- package/dist/contracts/index.d.ts +2 -2
- package/dist/contracts/index.js +1 -1
- package/dist/contracts/internal.js +11 -9
- package/dist/contracts/location.d.ts +24 -0
- package/dist/contracts/rows.d.ts +15 -0
- package/dist/dialects/pg/archive-bind.d.ts +22 -0
- package/dist/dialects/pg/column.d.ts +129 -10
- package/dist/dialects/pg/compile.d.ts +1 -0
- package/dist/dialects/pg/custom.d.ts +6 -0
- package/dist/dialects/pg/ddl.d.ts +65 -1
- package/dist/dialects/pg/enum.d.ts +10 -8
- package/dist/dialects/pg/ext/citext.d.ts +14 -0
- package/dist/dialects/pg/ext/citext.js +11 -0
- package/dist/dialects/pg/ext/index.d.ts +52 -0
- package/dist/dialects/pg/ext/index.js +6 -0
- package/dist/dialects/pg/ext/pg-trgm.d.ts +53 -0
- package/dist/dialects/pg/ext/pg-trgm.js +42 -0
- package/dist/dialects/pg/filter-parse.d.ts +19 -0
- package/dist/dialects/pg/filters.d.ts +19 -0
- package/dist/dialects/pg/fn/index.d.ts +107 -0
- package/dist/dialects/pg/fn/index.js +175 -0
- package/dist/dialects/pg/fn/touch.d.ts +14 -0
- package/dist/dialects/pg/index.d.ts +11 -2
- package/dist/dialects/pg/index.js +243 -1062
- package/dist/dialects/pg/introspect.d.ts +10 -1
- package/dist/dialects/pg/keys.d.ts +19 -3
- package/dist/dialects/pg/model.d.ts +223 -2
- package/dist/dialects/pg/operator-fit.d.ts +86 -0
- package/dist/dialects/pg/operators.d.ts +46 -1
- package/dist/dialects/pg/ops/arr-append.d.ts +9 -0
- package/dist/dialects/pg/ops/arr-ns.d.ts +7 -0
- package/dist/dialects/pg/ops/arr-remove.d.ts +9 -0
- package/dist/dialects/pg/ops/containedBy.d.ts +9 -0
- package/dist/dialects/pg/ops/contains.d.ts +8 -4
- package/dist/dialects/pg/ops/hasAnyKey.d.ts +8 -0
- package/dist/dialects/pg/ops/hasKey.d.ts +8 -0
- package/dist/dialects/pg/ops/json-ns.d.ts +6 -0
- package/dist/dialects/pg/ops/json-set.d.ts +12 -0
- package/dist/dialects/pg/ops/matches.d.ts +16 -0
- package/dist/dialects/pg/ops/overlaps.d.ts +9 -0
- package/dist/dialects/pg/ops/path.d.ts +13 -0
- package/dist/dialects/pg/preset.d.ts +76 -0
- package/dist/dialects/pg/relations.d.ts +59 -2
- package/dist/dialects/pg/role/check.d.ts +45 -0
- package/dist/dialects/pg/role/index.d.ts +50 -0
- package/dist/dialects/pg/role/sql.d.ts +44 -0
- package/dist/dialects/pg/schema.d.ts +109 -5
- package/dist/dialects/pg/table.d.ts +137 -11
- package/dist/dialects/pg/temporal.d.ts +9 -7
- package/dist/dialects/pg/tenancy.d.ts +103 -0
- package/dist/dialects/pg/through.d.ts +21 -0
- package/dist/dialects/pg/trait.d.ts +141 -0
- package/dist/dialects/pg/view/client.d.ts +30 -0
- package/dist/dialects/pg/view/depend.d.ts +35 -0
- package/dist/dialects/pg/view/index.d.ts +114 -0
- package/dist/dialects/pg/view/index.js +289 -0
- package/dist/dialects/pg/view/scratch.d.ts +21 -0
- package/dist/dialects/pg/where.d.ts +37 -0
- package/dist/runtime/aggregate.d.ts +25 -0
- package/dist/runtime/archive-handle.d.ts +18 -0
- package/dist/runtime/archive-rules.d.ts +12 -0
- package/dist/runtime/archive.d.ts +73 -0
- package/dist/runtime/batch.d.ts +20 -0
- package/dist/runtime/client.d.ts +114 -5
- package/dist/runtime/conflict.d.ts +2 -1
- package/dist/runtime/exposure.d.ts +27 -0
- package/dist/runtime/hookm.d.ts +39 -0
- package/dist/runtime/ids/index.d.ts +11 -0
- package/dist/runtime/ids/index.js +193 -0
- package/dist/runtime/ids/okid-extended.d.ts +19 -0
- package/dist/runtime/ids/okid-generator.d.ts +21 -0
- package/dist/runtime/ids/okid-shared.d.ts +89 -0
- package/dist/runtime/ids/okid.d.ts +24 -0
- package/dist/runtime/ids/uuid.d.ts +21 -0
- package/dist/runtime/lock.d.ts +22 -0
- package/dist/runtime/operator-sql.d.ts +8 -0
- package/dist/runtime/page.d.ts +25 -0
- package/dist/runtime/pg/bun.d.ts +30 -0
- package/dist/runtime/pg/bun.js +52 -0
- package/dist/runtime/pg/pg.d.ts +29 -0
- package/dist/runtime/pg/pg.js +52 -0
- package/dist/runtime/pg/pglite.js +16 -17
- package/dist/runtime/pg/postgresjs.js +14 -24
- package/dist/runtime/plan.d.ts +146 -7
- package/dist/runtime/preset-stack.d.ts +17 -0
- package/dist/runtime/presets.d.ts +48 -0
- package/dist/runtime/read-stream.d.ts +26 -0
- package/dist/runtime/safety/index.d.ts +159 -0
- package/dist/runtime/safety/index.js +294 -0
- package/dist/runtime/safety-hook.d.ts +42 -0
- package/dist/runtime/server-check.d.ts +34 -0
- package/dist/runtime/tenancy/index.d.ts +37 -0
- package/dist/runtime/tenancy/index.js +368 -0
- package/dist/runtime/trait-read.d.ts +30 -0
- package/dist/runtime/traits/index.d.ts +133 -0
- package/dist/runtime/traits/index.js +646 -0
- package/dist/runtime/transaction.d.ts +19 -0
- package/dist/runtime/tx.d.ts +22 -7
- package/dist/runtime/types.d.ts +376 -27
- package/dist/runtime/validate/bind.d.ts +11 -0
- package/dist/runtime/validate/closed.d.ts +16 -0
- package/dist/runtime/validate/engine.d.ts +41 -0
- package/dist/runtime/validate/hook.d.ts +17 -0
- package/dist/runtime/validate/index.d.ts +21 -0
- package/dist/runtime/validate/index.js +175 -0
- package/dist/runtime/validate/load.d.ts +13 -0
- package/dist/runtime/validate/places.d.ts +41 -0
- package/dist/runtime/validate/rules.d.ts +108 -0
- package/dist/runtime/validate/surface.d.ts +102 -0
- package/dist/runtime/write.d.ts +30 -5
- package/dist/shared/01yr20s5.js +149 -0
- package/dist/shared/0jc3ffzf.js +154 -0
- package/dist/shared/0v1g424p.js +26 -0
- package/dist/shared/1g0drakv.js +225 -0
- package/dist/shared/{kprcwaha.js → 1tfdfvhh.js} +5 -3
- package/dist/shared/{05w44d8g.js → 2ssqrv66.js} +767 -715
- package/dist/shared/3ekj9x92.js +210 -0
- package/dist/shared/49ypnfwt.js +1122 -0
- package/dist/shared/4e4c6vq2.js +62 -0
- package/dist/shared/4m9fn52z.js +70 -0
- package/dist/shared/{ycwz42az.js → 52szzakm.js} +6 -26
- package/dist/shared/5nmdenb6.js +1229 -0
- package/dist/shared/672t5vym.js +12 -0
- package/dist/shared/6bazvqwm.js +86 -0
- package/dist/shared/6w5j844a.js +201 -0
- package/dist/shared/{fgqgsb5z.js → 75xkjv0t.js} +2 -2
- package/dist/shared/7fvtrkwr.js +84 -0
- package/dist/shared/7m88x3e9.js +45 -0
- package/dist/shared/{mtkwv8wx.js → 7p2wbz7f.js} +1 -1
- package/dist/shared/83eaefwr.js +10 -0
- package/dist/shared/94ez8kzh.js +19 -0
- package/dist/shared/96ps4g1z.js +32 -0
- package/dist/shared/{xqbhg6cn.js → 999ade2q.js} +95 -10
- package/dist/shared/9m80mkac.js +158 -0
- package/dist/shared/9x25fxhc.js +150 -0
- package/dist/shared/a5sxz52y.js +13 -0
- package/dist/shared/axhk06q1.js +156 -0
- package/dist/shared/{dynq16vb.js → b066g80h.js} +8 -6
- package/dist/shared/bqha5cg6.js +229 -0
- package/dist/shared/bryqk9k9.js +31 -0
- package/dist/shared/c8aghh05.js +442 -0
- package/dist/shared/c9z5g0fm.js +309 -0
- package/dist/shared/{m3ypagh5.js → dbjej1tw.js} +124 -15
- package/dist/shared/dyj86cmj.js +69 -0
- package/dist/shared/e6wg00wd.js +164 -0
- package/dist/shared/{hadrfb9h.js → edwqqryd.js} +17 -14
- package/dist/shared/{qk3hxfja.js → fptpmvxp.js} +5 -5
- package/dist/shared/fs0ex00p.js +76 -0
- package/dist/shared/{jjb7yht9.js → g4f5kcx9.js} +3 -3
- package/dist/shared/gjthds9j.js +48 -0
- package/dist/shared/hcmdtwgh.js +102 -0
- package/dist/shared/{g5fhqmwe.js → jkc6ws1p.js} +6 -56
- package/dist/shared/{yd1kzwn2.js → jns2wx4t.js} +55 -12
- package/dist/shared/k34e0xf2.js +450 -0
- package/dist/shared/k3ted12y.js +33 -0
- package/dist/shared/k7dwkhvq.js +31 -0
- package/dist/shared/{8b04d28c.js → kgnc8grt.js} +2 -2
- package/dist/shared/{hd293j9g.js → kyxb62mc.js} +14 -2
- package/dist/shared/m78s7898.js +376 -0
- package/dist/shared/m9tv7xn7.js +404 -0
- package/dist/shared/meck53jv.js +99 -0
- package/dist/shared/mt5wswjz.js +90 -0
- package/dist/shared/n0dgs0pb.js +75 -0
- package/dist/shared/n442h54c.js +14 -0
- package/dist/shared/n4jqhpqz.js +27 -0
- package/dist/shared/n7mcc1gk.js +132 -0
- package/dist/shared/ne02ng5c.js +68 -0
- package/dist/shared/{mkjmqjv4.js → nfzc5z0w.js} +2 -104
- package/dist/shared/nsva2a6b.js +42 -0
- package/dist/shared/p24x2334.js +195 -0
- package/dist/shared/qbxzvwwc.js +88 -0
- package/dist/shared/{w8samvk1.js → qybh48nd.js} +1 -1
- package/dist/shared/r6nwkxnt.js +86 -0
- package/dist/shared/{xy79j5hq.js → rrstp3kb.js} +25 -36
- package/dist/shared/rwmrejjz.js +26 -0
- package/dist/shared/{zhc5vmgf.js → s6gqfn5j.js} +2 -2
- package/dist/shared/{523ft3e8.js → scwxrpx2.js} +7 -5
- package/dist/shared/{j5cn2963.js → t4tbsy9h.js} +13 -64
- package/dist/shared/{y9m15dfv.js → t616ynfn.js} +544 -32
- package/dist/shared/{ngk8gj61.js → tbszx8mz.js} +15 -1
- package/dist/shared/th14ygv2.js +69 -0
- package/dist/shared/tmbdywx0.js +178 -0
- package/dist/shared/ty3v3hfk.js +64 -0
- package/dist/shared/wekze34d.js +246 -0
- package/dist/shared/x6wysh83.js +1132 -0
- package/dist/shared/{rgs0st28.js → xrfnq5k8.js} +237 -434
- package/dist/shared/{x5x59srr.js → xva8v7qk.js} +416 -83
- package/dist/shared/{dkn3y60a.js → xw1d69vd.js} +76 -112
- package/dist/shared/y005b761.js +112 -0
- package/dist/shared/ydaz1sv3.js +55 -0
- package/dist/shared/{p0cbr3g2.js → zwmqxb0g.js} +1 -1
- package/dist/tooling/cli.js +40 -12
- package/dist/tooling/migrate/apply.d.ts +16 -0
- package/dist/tooling/migrate/commands.d.ts +12 -1
- package/dist/tooling/migrate/config.d.ts +8 -0
- package/dist/tooling/migrate/doctor.d.ts +25 -0
- package/dist/tooling/migrate/drift.d.ts +19 -0
- package/dist/tooling/migrate/engine.d.ts +36 -0
- package/dist/tooling/migrate/ext.d.ts +17 -0
- package/dist/tooling/migrate/extensions.d.ts +51 -0
- package/dist/tooling/migrate/managed.d.ts +17 -0
- package/dist/tooling/migrate/plan.d.ts +14 -1
- package/dist/tooling/migrate/project.d.ts +25 -1
- package/dist/tooling/migrate/type-name.d.ts +19 -0
- package/package.json +61 -4
- package/dist/shared/gk7cs7sp.js +0 -566
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ColumnBuilder2
|
|
3
|
+
} from "./c9z5g0fm.js";
|
|
4
|
+
import {
|
|
5
|
+
definition
|
|
6
|
+
} from "./tmbdywx0.js";
|
|
7
|
+
import {
|
|
8
|
+
OkmError2
|
|
9
|
+
} from "./52szzakm.js";
|
|
10
|
+
|
|
11
|
+
// src/runtime/validate/places.ts
|
|
12
|
+
function assertValidation(schema) {
|
|
13
|
+
const record = schema;
|
|
14
|
+
const tables = record.tables;
|
|
15
|
+
if (tables === undefined)
|
|
16
|
+
return;
|
|
17
|
+
for (const item of tables)
|
|
18
|
+
validationGate(record.validation, item);
|
|
19
|
+
}
|
|
20
|
+
function validationGate(schemaFlag, table) {
|
|
21
|
+
return buildGate(schemaFlag, table);
|
|
22
|
+
}
|
|
23
|
+
function writeWouldValidate(schemaFlag, table, options) {
|
|
24
|
+
if (options.validate === false)
|
|
25
|
+
return false;
|
|
26
|
+
const setting = tableSetting(readSetting(schemaFlag, "schema()"), table.options);
|
|
27
|
+
if (setting.enabled)
|
|
28
|
+
return true;
|
|
29
|
+
const section = table.options;
|
|
30
|
+
if (section?.validate !== undefined)
|
|
31
|
+
return true;
|
|
32
|
+
for (const builder of Object.values(table.columns)) {
|
|
33
|
+
if (builder instanceof ColumnBuilder2 && builder.state.validate !== undefined)
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
function buildGate(schemaFlag, table) {
|
|
39
|
+
const setting = tableSetting(readSetting(schemaFlag, "schema()"), table.options);
|
|
40
|
+
const section = readSection(table.name, table.options);
|
|
41
|
+
if (setting.style === "inline" && section.rowPresent)
|
|
42
|
+
conflict(table.name, "$row");
|
|
43
|
+
const fields = {};
|
|
44
|
+
const required = [];
|
|
45
|
+
const notNull = [];
|
|
46
|
+
const pick = {};
|
|
47
|
+
const names = new Set;
|
|
48
|
+
for (const [field, builder] of Object.entries(table.columns)) {
|
|
49
|
+
if (!(builder instanceof ColumnBuilder2))
|
|
50
|
+
continue;
|
|
51
|
+
names.add(field);
|
|
52
|
+
const inline = builder.state.validate?.rules;
|
|
53
|
+
const named = Object.hasOwn(section.fields, field) ? section.fields[field] : undefined;
|
|
54
|
+
const rules = takeRules(table.name, field, inline, named, setting.style);
|
|
55
|
+
if (rules !== undefined)
|
|
56
|
+
fields[field] = rules;
|
|
57
|
+
const state = builder.state;
|
|
58
|
+
const writable = state.guarded !== true && state.omitWrite !== true && state.generated === undefined;
|
|
59
|
+
if (setting.enabled && writable) {
|
|
60
|
+
if (!state.nullable && state.hasDefault !== true)
|
|
61
|
+
required.push(field);
|
|
62
|
+
if (!state.nullable)
|
|
63
|
+
notNull.push(field);
|
|
64
|
+
if (state.picklist !== undefined)
|
|
65
|
+
pick[field] = state.picklist.values;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (const field of Object.keys(section.fields)) {
|
|
69
|
+
if (!names.has(field))
|
|
70
|
+
definition(`Table ${table.name} validate.${field} is not a column.`);
|
|
71
|
+
}
|
|
72
|
+
if (!setting.enabled)
|
|
73
|
+
return;
|
|
74
|
+
return { onRead: setting.onRead, row: section.row, fields, required, notNull, pick };
|
|
75
|
+
}
|
|
76
|
+
function readSetting(value, where) {
|
|
77
|
+
if (value === undefined || value === false)
|
|
78
|
+
return { enabled: false, onRead: false, style: undefined };
|
|
79
|
+
if (value === true)
|
|
80
|
+
return { enabled: true, onRead: false, style: undefined };
|
|
81
|
+
if (isPlain(value)) {
|
|
82
|
+
return {
|
|
83
|
+
enabled: value.enabled === undefined ? true : value.enabled === true,
|
|
84
|
+
onRead: value.onRead === true,
|
|
85
|
+
style: readStyle(value.style)
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
definition(`${where} validation must be a boolean or { enabled, onRead, style }.`);
|
|
89
|
+
}
|
|
90
|
+
function tableSetting(schemaSetting, options) {
|
|
91
|
+
const value = options === undefined ? undefined : options.validation;
|
|
92
|
+
if (value === undefined)
|
|
93
|
+
return schemaSetting;
|
|
94
|
+
if (value === true)
|
|
95
|
+
return { enabled: true, onRead: schemaSetting.onRead, style: schemaSetting.style };
|
|
96
|
+
if (value === false)
|
|
97
|
+
return { enabled: false, onRead: schemaSetting.onRead, style: schemaSetting.style };
|
|
98
|
+
if (isPlain(value)) {
|
|
99
|
+
return {
|
|
100
|
+
enabled: value.enabled === undefined ? true : value.enabled === true,
|
|
101
|
+
onRead: value.onRead === undefined ? schemaSetting.onRead : value.onRead === true,
|
|
102
|
+
style: value.style === undefined ? schemaSetting.style : readStyle(value.style)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
definition("table() validation must be a boolean or { enabled, onRead, style }.");
|
|
106
|
+
}
|
|
107
|
+
function readStyle(value) {
|
|
108
|
+
if (value === undefined)
|
|
109
|
+
return;
|
|
110
|
+
if (value === "inline" || value === "section")
|
|
111
|
+
return value;
|
|
112
|
+
definition("validation.style must be inline or section.");
|
|
113
|
+
}
|
|
114
|
+
function readSection(table, options) {
|
|
115
|
+
const validate = options === undefined ? undefined : options.validate;
|
|
116
|
+
if (validate === undefined)
|
|
117
|
+
return { fields: {}, row: [], rowPresent: false };
|
|
118
|
+
if (!isPlain(validate)) {
|
|
119
|
+
definition(`Table ${table} option validate must be { field: rules, $row: rules }.`);
|
|
120
|
+
}
|
|
121
|
+
const fields = {};
|
|
122
|
+
let row = [];
|
|
123
|
+
let rowPresent = false;
|
|
124
|
+
for (const key of Object.keys(validate)) {
|
|
125
|
+
const item = validate[key];
|
|
126
|
+
if (!Array.isArray(item))
|
|
127
|
+
definition(`Table ${table} validate.${key} must be a list of rules.`);
|
|
128
|
+
if (key === "$row") {
|
|
129
|
+
row = item;
|
|
130
|
+
rowPresent = true;
|
|
131
|
+
} else
|
|
132
|
+
fields[key] = item;
|
|
133
|
+
}
|
|
134
|
+
return { fields, row, rowPresent };
|
|
135
|
+
}
|
|
136
|
+
function takeRules(table, field, inline, section, style) {
|
|
137
|
+
const hasInline = inline !== undefined;
|
|
138
|
+
const hasSection = section !== undefined;
|
|
139
|
+
if (hasInline && hasSection || style === "inline" && hasSection || style === "section" && hasInline) {
|
|
140
|
+
conflict(table, field);
|
|
141
|
+
}
|
|
142
|
+
if (hasInline && inline.length > 0)
|
|
143
|
+
return inline;
|
|
144
|
+
if (hasSection && section.length > 0)
|
|
145
|
+
return section;
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
function conflict(table, field) {
|
|
149
|
+
throw new OkmError2("OKM1030", `Field ${table}.${field} is validated in two places. Keep the column rules or the validate section.`, {
|
|
150
|
+
...field === "$row" ? {} : { columns: [field] },
|
|
151
|
+
fix: { summary: "Keep one validation for the field." }
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function isPlain(value) {
|
|
155
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export { assertValidation, validationGate, writeWouldValidate };
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import {
|
|
2
|
+
staticNamespace2,
|
|
3
|
+
assertNamespace2,
|
|
4
|
+
normaliseEdges,
|
|
5
|
+
assertProvenance
|
|
6
|
+
} from "./t4tbsy9h.js";
|
|
7
|
+
import {
|
|
8
|
+
assertIdentifier2
|
|
9
|
+
} from "./nfzc5z0w.js";
|
|
10
|
+
import {
|
|
11
|
+
catalogError2
|
|
12
|
+
} from "./52szzakm.js";
|
|
13
|
+
|
|
14
|
+
// src/contracts/catalog/routine.ts
|
|
15
|
+
var VOLATILITY = new Set(["volatile", "stable", "immutable"]);
|
|
16
|
+
var SECURITY = new Set(["invoker", "definer"]);
|
|
17
|
+
var TIMING = new Set(["before", "after", "instead"]);
|
|
18
|
+
var LEVEL = new Set(["row", "statement"]);
|
|
19
|
+
var EVENT_ORDER = ["insert", "update", "delete", "truncate"];
|
|
20
|
+
var TYPE_TEXT = /^[A-Za-z][A-Za-z0-9_ ]*(\(\d+(,\s*\d+)?\))?(\[\])*$/;
|
|
21
|
+
function functionObject(input) {
|
|
22
|
+
assertIdentifier2(input.name, "function");
|
|
23
|
+
const namespace = input.namespace ?? staticNamespace2("public");
|
|
24
|
+
assertNamespace2(namespace);
|
|
25
|
+
assertProvenance(input.provenance);
|
|
26
|
+
if (input.language !== "sql" && input.language !== "plpgsql") {
|
|
27
|
+
catalogError2("OKM1020", `Function ${input.name} language must be sql or plpgsql.`);
|
|
28
|
+
}
|
|
29
|
+
const volatility = input.volatility ?? "volatile";
|
|
30
|
+
if (!VOLATILITY.has(volatility)) {
|
|
31
|
+
catalogError2("OKM1020", `Function ${input.name} volatility ${volatility} is not supported.`);
|
|
32
|
+
}
|
|
33
|
+
const security = input.security ?? "invoker";
|
|
34
|
+
if (!SECURITY.has(security)) {
|
|
35
|
+
catalogError2("OKM1020", `Function ${input.name} security ${security} is not supported.`);
|
|
36
|
+
}
|
|
37
|
+
assertTypeName(input.returns, `function ${input.name} return type`);
|
|
38
|
+
const args = (input.arguments ?? []).map((argument) => readArgument(input.name, argument));
|
|
39
|
+
if (input.body.length === 0) {
|
|
40
|
+
catalogError2("OKM1020", `Function ${input.name} needs a body.`);
|
|
41
|
+
}
|
|
42
|
+
const atomic = input.atomic === true;
|
|
43
|
+
if (atomic && input.language !== "sql") {
|
|
44
|
+
catalogError2("OKM1020", `Function ${input.name} BEGIN ATOMIC needs language sql.`);
|
|
45
|
+
}
|
|
46
|
+
if (input.searchPath !== undefined && input.searchPath.trim().length === 0) {
|
|
47
|
+
catalogError2("OKM1020", `Function ${input.name} search_path is empty.`);
|
|
48
|
+
}
|
|
49
|
+
const definition = {
|
|
50
|
+
arguments: args,
|
|
51
|
+
returns: input.returns,
|
|
52
|
+
language: input.language,
|
|
53
|
+
volatility,
|
|
54
|
+
security,
|
|
55
|
+
body: input.body,
|
|
56
|
+
...input.searchPath !== undefined ? { searchPath: input.searchPath } : {},
|
|
57
|
+
...atomic ? { atomic: true } : {}
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
kind: "function",
|
|
61
|
+
identity: {
|
|
62
|
+
kind: "function",
|
|
63
|
+
namespace,
|
|
64
|
+
name: input.name,
|
|
65
|
+
argTypes: args.map((arg) => arg.type)
|
|
66
|
+
},
|
|
67
|
+
owner: input.owner ?? "managed",
|
|
68
|
+
definition,
|
|
69
|
+
dependencies: normaliseEdges(input.dependencies ?? []),
|
|
70
|
+
provenance: input.provenance
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function triggerObject(input) {
|
|
74
|
+
assertIdentifier2(input.name, "trigger");
|
|
75
|
+
assertNamespace2(input.parent.namespace);
|
|
76
|
+
assertIdentifier2(input.parent.name, "trigger table");
|
|
77
|
+
assertProvenance(input.provenance);
|
|
78
|
+
if (!TIMING.has(input.timing)) {
|
|
79
|
+
catalogError2("OKM1020", `Trigger ${input.name} timing ${input.timing} is not supported.`);
|
|
80
|
+
}
|
|
81
|
+
if (!LEVEL.has(input.level)) {
|
|
82
|
+
catalogError2("OKM1020", `Trigger ${input.name} level ${input.level} is not supported.`);
|
|
83
|
+
}
|
|
84
|
+
const events = EVENT_ORDER.filter((event) => input.events.includes(event));
|
|
85
|
+
if (events.length === 0) {
|
|
86
|
+
catalogError2("OKM1020", `Trigger ${input.name} needs an event.`);
|
|
87
|
+
}
|
|
88
|
+
const updateOf = input.updateOf === undefined ? undefined : [...input.updateOf];
|
|
89
|
+
if (updateOf !== undefined) {
|
|
90
|
+
if (!events.includes("update")) {
|
|
91
|
+
catalogError2("OKM1020", `Trigger ${input.name} lists UPDATE OF columns without an update event.`);
|
|
92
|
+
}
|
|
93
|
+
if (input.level !== "row") {
|
|
94
|
+
catalogError2("OKM1020", `Trigger ${input.name} UPDATE OF columns need level row.`);
|
|
95
|
+
}
|
|
96
|
+
for (const column of updateOf)
|
|
97
|
+
assertIdentifier2(column, "trigger column");
|
|
98
|
+
}
|
|
99
|
+
assertIdentifier2(input.calls.name, "trigger function");
|
|
100
|
+
assertNamespace2(input.calls.namespace);
|
|
101
|
+
for (const typeName of input.calls.argTypes)
|
|
102
|
+
assertTypeName(typeName, `trigger ${input.name}`);
|
|
103
|
+
const edges = [
|
|
104
|
+
{ kind: "table", namespace: input.parent.namespace, name: input.parent.name },
|
|
105
|
+
{
|
|
106
|
+
kind: "function",
|
|
107
|
+
namespace: input.calls.namespace,
|
|
108
|
+
name: input.calls.name,
|
|
109
|
+
argTypes: input.calls.argTypes
|
|
110
|
+
},
|
|
111
|
+
...(updateOf ?? []).map((column) => ({
|
|
112
|
+
kind: "column",
|
|
113
|
+
parent: input.parent,
|
|
114
|
+
name: column
|
|
115
|
+
})),
|
|
116
|
+
...input.dependencies ?? []
|
|
117
|
+
];
|
|
118
|
+
const definition = {
|
|
119
|
+
timing: input.timing,
|
|
120
|
+
events,
|
|
121
|
+
level: input.level,
|
|
122
|
+
calls: {
|
|
123
|
+
namespace: input.calls.namespace,
|
|
124
|
+
name: input.calls.name,
|
|
125
|
+
argTypes: [...input.calls.argTypes]
|
|
126
|
+
},
|
|
127
|
+
...updateOf !== undefined && updateOf.length > 0 ? { updateOf } : {},
|
|
128
|
+
...input.when !== undefined && input.when.length > 0 ? { when: input.when } : {}
|
|
129
|
+
};
|
|
130
|
+
return {
|
|
131
|
+
kind: "trigger",
|
|
132
|
+
identity: { kind: "trigger", parent: input.parent, name: input.name },
|
|
133
|
+
owner: input.owner ?? "managed",
|
|
134
|
+
definition,
|
|
135
|
+
dependencies: normaliseEdges(edges),
|
|
136
|
+
provenance: input.provenance
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function readArgument(fn, argument) {
|
|
140
|
+
assertIdentifier2(argument.name, `function ${fn} argument`);
|
|
141
|
+
assertTypeName(argument.type, `function ${fn} argument ${argument.name}`);
|
|
142
|
+
return { name: argument.name, type: argument.type };
|
|
143
|
+
}
|
|
144
|
+
function assertTypeName(typeName, role) {
|
|
145
|
+
if (!TYPE_TEXT.test(typeName)) {
|
|
146
|
+
catalogError2("OKM1020", `${role} ${typeName} is not a type name.`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export { functionObject, triggerObject };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/runtime/safety-hook.ts
|
|
2
|
+
var hook;
|
|
3
|
+
function safetyInstalled() {
|
|
4
|
+
return hook !== undefined;
|
|
5
|
+
}
|
|
6
|
+
function installSafetyHook(next) {
|
|
7
|
+
hook = next;
|
|
8
|
+
}
|
|
9
|
+
function runSafety(contributions, hatches) {
|
|
10
|
+
hook?.(contributions, hatches);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { safetyInstalled, installSafetyHook, runSafety };
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertOperatorFits,
|
|
3
|
+
sqlType,
|
|
4
|
+
assertNoControl,
|
|
5
|
+
assertBoundText,
|
|
6
|
+
assertRegconfig,
|
|
7
|
+
textArray
|
|
8
|
+
} from "./n7mcc1gk.js";
|
|
9
|
+
import {
|
|
10
|
+
installOperatorSql,
|
|
11
|
+
quote,
|
|
12
|
+
isRecord,
|
|
13
|
+
fail
|
|
14
|
+
} from "./xrfnq5k8.js";
|
|
15
|
+
import {
|
|
16
|
+
isOperator,
|
|
17
|
+
operatorName,
|
|
18
|
+
operatorValue
|
|
19
|
+
} from "./cn0n68ft.js";
|
|
20
|
+
|
|
21
|
+
// src/runtime/operator-sql.ts
|
|
22
|
+
function emitStructured(column, ref, name, value, sink) {
|
|
23
|
+
if (name === "contains" || name === "containedBy" || name === "overlaps") {
|
|
24
|
+
emitContainment(column, ref, name, value, sink);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (name === "hasKey" || name === "hasAnyKey") {
|
|
28
|
+
emitJsonKey(column, ref, name, value, sink);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if (name === "path") {
|
|
32
|
+
emitPath(column, ref, value, sink);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (name === "matches") {
|
|
36
|
+
emitMatches(column, ref, value, sink);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
if (name === "similar" || name === "wordSimilar") {
|
|
40
|
+
emitTrigram(column, ref, name, value, sink);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
assertOperatorFits(column, name);
|
|
44
|
+
fail("OKM1121", `${name} is not a value operator on ${column.field}. Use has, none, or every on a relation.`);
|
|
45
|
+
}
|
|
46
|
+
function emitContainment(column, ref, name, value, sink) {
|
|
47
|
+
assertOperatorFits(column, name);
|
|
48
|
+
const op = name === "contains" ? " @> " : name === "containedBy" ? " <@ " : " && ";
|
|
49
|
+
sink.text(ref);
|
|
50
|
+
sink.text(op);
|
|
51
|
+
sink.param(column.encode(value));
|
|
52
|
+
sink.text("::");
|
|
53
|
+
sink.text(sqlType(column.dataType, column));
|
|
54
|
+
}
|
|
55
|
+
function emitJsonKey(column, ref, name, value, sink) {
|
|
56
|
+
assertOperatorFits(column, name);
|
|
57
|
+
if (name === "hasKey") {
|
|
58
|
+
if (typeof value !== "string")
|
|
59
|
+
fail("OKM1121", `hasKey on ${column.field} needs a key.`);
|
|
60
|
+
assertBoundText(value, `key on ${column.field}`);
|
|
61
|
+
sink.text("jsonb_exists(");
|
|
62
|
+
sink.text(ref);
|
|
63
|
+
sink.text(", ");
|
|
64
|
+
sink.param(value);
|
|
65
|
+
sink.text(")");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
69
|
+
fail("OKM1121", `hasAnyKey on ${column.field} needs a list of keys.`);
|
|
70
|
+
}
|
|
71
|
+
sink.text("jsonb_exists_any(");
|
|
72
|
+
sink.text(ref);
|
|
73
|
+
sink.text(", ");
|
|
74
|
+
sink.param(textArray(value, `key on ${column.field}`));
|
|
75
|
+
sink.text("::text[])");
|
|
76
|
+
}
|
|
77
|
+
function emitPath(column, ref, value, sink) {
|
|
78
|
+
assertOperatorFits(column, "path");
|
|
79
|
+
if (!isRecord(value) || !Array.isArray(value.segments) || !isOperator(value.op)) {
|
|
80
|
+
fail("OKM1121", `path on ${column.field} needs segments and a comparison.`);
|
|
81
|
+
}
|
|
82
|
+
const segments = value.segments;
|
|
83
|
+
if (segments.length === 0 || segments.some((item) => typeof item !== "string")) {
|
|
84
|
+
fail("OKM1121", `path on ${column.field} needs a list of segments.`);
|
|
85
|
+
}
|
|
86
|
+
const opName = operatorName(value.op);
|
|
87
|
+
if (opName !== "eq" && opName !== "lt" && opName !== "lte" && opName !== "gt" && opName !== "gte") {
|
|
88
|
+
fail("OKM1121", `path on ${column.field} compares with eq, lt, lte, gt, or gte.`);
|
|
89
|
+
}
|
|
90
|
+
const operand = operatorValue(value.op);
|
|
91
|
+
const cast = pathCast(column, operand);
|
|
92
|
+
const sql = opName === "eq" ? " = " : opName === "lt" ? " < " : opName === "lte" ? " <= " : opName === "gt" ? " > " : " >= ";
|
|
93
|
+
sink.text("(");
|
|
94
|
+
sink.text(ref);
|
|
95
|
+
sink.text(" #>> ");
|
|
96
|
+
sink.param(textArray(segments, `path on ${column.field}`));
|
|
97
|
+
sink.text("::text[])::");
|
|
98
|
+
sink.text(cast);
|
|
99
|
+
sink.text(sql);
|
|
100
|
+
sink.param(pathParam(operand));
|
|
101
|
+
}
|
|
102
|
+
function pathCast(column, operand) {
|
|
103
|
+
if (typeof operand === "number")
|
|
104
|
+
return "numeric";
|
|
105
|
+
if (typeof operand === "boolean")
|
|
106
|
+
return "boolean";
|
|
107
|
+
if (typeof operand === "string")
|
|
108
|
+
return "text";
|
|
109
|
+
fail("OKM1121", `path on ${column.field} compares a string, number, or boolean.`);
|
|
110
|
+
}
|
|
111
|
+
function pathParam(operand) {
|
|
112
|
+
if (typeof operand === "number")
|
|
113
|
+
return String(operand);
|
|
114
|
+
if (typeof operand === "boolean")
|
|
115
|
+
return operand ? "true" : "false";
|
|
116
|
+
if (typeof operand === "string")
|
|
117
|
+
return operand;
|
|
118
|
+
return "";
|
|
119
|
+
}
|
|
120
|
+
function emitMatches(column, ref, value, sink) {
|
|
121
|
+
assertOperatorFits(column, "matches");
|
|
122
|
+
if (!isRecord(value) || typeof value.query !== "string") {
|
|
123
|
+
fail("OKM1121", `matches on ${column.field} needs search text.`);
|
|
124
|
+
}
|
|
125
|
+
assertNoControl(value.query, `matches on ${column.field}`);
|
|
126
|
+
const mode = value.mode ?? "websearch";
|
|
127
|
+
const fn = mode === "websearch" ? "websearch_to_tsquery" : mode === "plain" ? "plainto_tsquery" : mode === "phrase" ? "phraseto_tsquery" : undefined;
|
|
128
|
+
if (fn === undefined) {
|
|
129
|
+
fail("OKM1121", `matches on ${column.field} mode must be websearch, plain, or phrase.`);
|
|
130
|
+
}
|
|
131
|
+
sink.text(ref);
|
|
132
|
+
sink.text(" @@ ");
|
|
133
|
+
sink.text(fn);
|
|
134
|
+
sink.text("(");
|
|
135
|
+
if (typeof value.config === "string") {
|
|
136
|
+
assertRegconfig(value.config);
|
|
137
|
+
sink.param(value.config);
|
|
138
|
+
sink.text("::regconfig, ");
|
|
139
|
+
}
|
|
140
|
+
sink.param(value.query);
|
|
141
|
+
sink.text(")");
|
|
142
|
+
}
|
|
143
|
+
function emitTrigram(column, ref, name, value, sink) {
|
|
144
|
+
if (!isRecord(value) || typeof value.query !== "string" || typeof value.schema !== "string") {
|
|
145
|
+
fail("OKM1121", `${name} on ${column.field} needs query text.`);
|
|
146
|
+
}
|
|
147
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value.schema)) {
|
|
148
|
+
fail("OKM1121", `${name} on ${column.field} needs an extension schema name.`);
|
|
149
|
+
}
|
|
150
|
+
sink.text(ref);
|
|
151
|
+
sink.text(" operator(");
|
|
152
|
+
sink.text(quote(value.schema));
|
|
153
|
+
sink.text(name === "similar" ? ".%) " : ".<%) ");
|
|
154
|
+
sink.param(value.query);
|
|
155
|
+
}
|
|
156
|
+
installOperatorSql(emitStructured);
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
DriverError2,
|
|
3
3
|
outcomeUnknown2,
|
|
4
4
|
mapDriverError2
|
|
5
|
-
} from "./
|
|
5
|
+
} from "./kyxb62mc.js";
|
|
6
6
|
import {
|
|
7
|
-
|
|
8
|
-
} from "./
|
|
7
|
+
isConnectionLost
|
|
8
|
+
} from "./tbszx8mz.js";
|
|
9
9
|
|
|
10
10
|
// src/adapters/pg/batch.ts
|
|
11
11
|
var savepointIds = 0;
|
|
@@ -21,13 +21,14 @@ async function transaction(session, statements, watch) {
|
|
|
21
21
|
try {
|
|
22
22
|
await control(session, "COMMIT", watch);
|
|
23
23
|
} catch (error) {
|
|
24
|
-
if (
|
|
24
|
+
if (isConnectionLost(error))
|
|
25
25
|
throw outcomeUnknown2(error);
|
|
26
26
|
throw stamp(error, null);
|
|
27
27
|
}
|
|
28
28
|
return results;
|
|
29
29
|
} catch (error) {
|
|
30
|
-
|
|
30
|
+
if (!isConnectionLost(error))
|
|
31
|
+
await rollback(session);
|
|
31
32
|
throw error;
|
|
32
33
|
}
|
|
33
34
|
}
|
|
@@ -40,7 +41,8 @@ async function savepoint(session, statements, watch) {
|
|
|
40
41
|
await control(session, `RELEASE SAVEPOINT ${name}`, watch);
|
|
41
42
|
return results;
|
|
42
43
|
} catch (error) {
|
|
43
|
-
|
|
44
|
+
if (!isConnectionLost(error))
|
|
45
|
+
await rollback(session, `ROLLBACK TO SAVEPOINT ${name}`);
|
|
44
46
|
throw error;
|
|
45
47
|
}
|
|
46
48
|
}
|