okmodel 0.2.1 → 0.4.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 +882 -48
- package/dist/contracts/catalog/document.d.ts +6 -2
- package/dist/contracts/catalog/enum.d.ts +31 -4
- package/dist/contracts/catalog/extension.d.ts +61 -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 +164 -10
- package/dist/contracts/catalog/view.d.ts +73 -0
- package/dist/dialects/pg/column.d.ts +3 -1
- 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/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.js +104 -19
- package/dist/dialects/pg/introspect.d.ts +10 -1
- package/dist/dialects/pg/operators.d.ts +8 -1
- 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 +51 -0
- package/dist/dialects/pg/table.d.ts +24 -1
- package/dist/dialects/pg/tenancy.d.ts +9 -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 +22 -0
- package/dist/dialects/pg/where.d.ts +2 -2
- package/dist/runtime/catalog-cache.d.ts +17 -0
- package/dist/runtime/compat-words.d.ts +23 -0
- package/dist/runtime/drift-detail.d.ts +20 -4
- package/dist/runtime/drift.d.ts +4 -2
- package/dist/runtime/pg/bun.js +3 -3
- package/dist/runtime/pg/pg.js +3 -3
- package/dist/runtime/pg/pglite.js +3 -3
- package/dist/runtime/pg/postgresjs.js +3 -3
- package/dist/runtime/tenancy/index.js +6 -3
- package/dist/runtime/traits/index.d.ts +7 -2
- package/dist/runtime/traits/index.js +151 -13
- package/dist/runtime/types.d.ts +2 -0
- package/dist/runtime/validate/index.js +4 -4
- package/dist/shared/{xkz8g6by.js → 1g0drakv.js} +2 -2
- package/dist/shared/2321avmn.js +418 -0
- package/dist/shared/{7mht49yd.js → 3p4b1fg0.js} +57 -18
- package/dist/shared/41kv2xdm.js +318 -0
- package/dist/shared/{97g2jnrw.js → 4ef7mmqf.js} +3 -3
- package/dist/shared/{sacqha1y.js → 4m9fn52z.js} +2 -2
- package/dist/shared/5mtf6cj3.js +94 -0
- package/dist/shared/{1dp5knt7.js → 5vdm4sgp.js} +2 -2
- package/dist/shared/{a1gdp7j9.js → 6693j9rs.js} +1 -1
- package/dist/shared/{38crxbgn.js → 6p5k20sm.js} +3 -3
- package/dist/shared/7nk68fj8.js +751 -0
- package/dist/shared/84ptn35q.js +71 -0
- package/dist/shared/{d2whjz4k.js → 8jb4ymh2.js} +581 -28
- package/dist/shared/8ktwd3rh.js +97 -0
- package/dist/shared/94ez8kzh.js +19 -0
- package/dist/shared/{3a5ne750.js → 9m80mkac.js} +2 -2
- package/dist/shared/9x25fxhc.js +150 -0
- package/dist/shared/9yn6a2vd.js +11 -0
- package/dist/shared/ady1ms74.js +72 -0
- package/dist/shared/{4jzzghr6.js → awrsqrn7.js} +6 -6
- package/dist/shared/{4b9da9d7.js → axhk06q1.js} +19 -1
- package/dist/shared/{d04j53v8.js → c5g81ngb.js} +82 -14
- package/dist/shared/{n47rd821.js → c8aghh05.js} +1 -1
- package/dist/shared/{dd4f8mnx.js → c9z5g0fm.js} +4 -2
- package/dist/shared/{ps43134h.js → dyj86cmj.js} +4 -4
- package/dist/shared/{0qkxbm1f.js → fa9vt245.js} +1 -1
- package/dist/shared/{qa5dsc7z.js → fb00y8fp.js} +3 -3
- package/dist/shared/{qxa0yb9j.js → g7ez901n.js} +30 -1
- package/dist/shared/{py3nh7jy.js → gdh9mrtp.js} +2 -2
- package/dist/shared/{yw5c610b.js → gjthds9j.js} +2 -2
- package/dist/shared/hcmdtwgh.js +102 -0
- package/dist/shared/hqjsxnz7.js +13 -0
- package/dist/shared/htnaj77v.js +17 -0
- package/dist/shared/{v18jva5b.js → jgxzjzcz.js} +1 -1
- package/dist/shared/{x9v1qgeb.js → jsd07prz.js} +3 -3
- package/dist/shared/{g9f0zqce.js → kafaa5zv.js} +1 -1
- package/dist/shared/kj680nxv.js +19 -0
- package/dist/shared/{mxmcdsh5.js → kkzwp3d2.js} +9 -9
- package/dist/shared/{g1b5zzj9.js → n0dgs0pb.js} +1 -1
- package/dist/shared/n5y9zyj1.js +2431 -0
- package/dist/shared/{zt8y0wzb.js → n7mcc1gk.js} +1 -1
- package/dist/shared/{ge03bfca.js → nxb42q7h.js} +2 -2
- package/dist/shared/q6zsyh31.js +2192 -0
- package/dist/shared/{sfh4pk75.js → q795afwa.js} +26 -21
- package/dist/shared/{10tjenmd.js → qn0srwwq.js} +1 -1
- package/dist/shared/s4mb6a4b.js +545 -0
- package/dist/shared/{ytg3xf9p.js → sf8m6tfy.js} +3 -3
- package/dist/shared/{zd93g3rq.js → sr5ms7b3.js} +1 -1
- package/dist/shared/{xatfg0gn.js → tmbdywx0.js} +4 -19
- package/dist/shared/tny2t3sm.js +100 -0
- package/dist/shared/{e7a268fy.js → v7tpnhnz.js} +1 -1
- package/dist/shared/{ecdzej21.js → wqem4jed.js} +7 -7
- package/dist/shared/xghkt7a9.js +1144 -0
- package/dist/shared/y005b761.js +112 -0
- package/dist/shared/ycatkxmq.js +84 -0
- package/dist/shared/ygem90rn.js +900 -0
- package/dist/shared/{eaxwrgby.js → yjw02enp.js} +6 -3
- package/dist/shared/{mrq77sgw.js → zg24x0hm.js} +1 -1
- package/dist/shared/{cstgkzdx.js → zvbjc949.js} +1 -1
- package/dist/tooling/cli.js +66 -13
- package/dist/tooling/migrate/apply.d.ts +75 -5
- package/dist/tooling/migrate/backfill.d.ts +136 -0
- package/dist/tooling/migrate/check.d.ts +65 -0
- package/dist/tooling/migrate/classify.d.ts +108 -0
- package/dist/tooling/migrate/commands.d.ts +2 -1
- package/dist/tooling/migrate/config.d.ts +30 -0
- package/dist/tooling/migrate/doctor.d.ts +28 -0
- package/dist/tooling/migrate/drift.d.ts +35 -0
- package/dist/tooling/migrate/estimate.d.ts +50 -0
- package/dist/tooling/migrate/ext.d.ts +17 -0
- package/dist/tooling/migrate/extensions.d.ts +53 -0
- package/dist/tooling/migrate/files.d.ts +12 -0
- package/dist/tooling/migrate/index.d.ts +3 -2
- package/dist/tooling/migrate/index.js +67 -1
- package/dist/tooling/migrate/lint-rules.d.ts +51 -0
- package/dist/tooling/migrate/lint.d.ts +71 -0
- package/dist/tooling/migrate/managed.d.ts +17 -0
- package/dist/tooling/migrate/plan.d.ts +78 -10
- package/dist/tooling/migrate/project.d.ts +64 -5
- package/dist/tooling/migrate/provision.d.ts +18 -0
- package/dist/tooling/migrate/reference.d.ts +40 -0
- package/dist/tooling/migrate/runner.d.ts +108 -0
- package/dist/tooling/migrate/safe.d.ts +77 -0
- package/dist/tooling/migrate/seed.d.ts +20 -0
- package/dist/tooling/migrate/snapshot.d.ts +78 -0
- package/dist/tooling/migrate/status.d.ts +25 -6
- package/dist/tooling/migrate/type-name.d.ts +19 -0
- package/dist/tooling/testing/factories.d.ts +117 -0
- package/dist/tooling/testing/facts.d.ts +72 -0
- package/dist/tooling/testing/index.d.ts +89 -0
- package/dist/tooling/testing/index.js +8 -0
- package/dist/tooling/testing/isolation.d.ts +30 -0
- package/dist/tooling/testing/random.d.ts +40 -0
- package/dist/tooling/testing/record.d.ts +38 -0
- package/package.json +26 -2
- package/dist/shared/5z4q2zda.js +0 -2073
- package/dist/shared/eqmtn1bj.js +0 -399
- package/dist/shared/rtnaqre0.js +0 -37
- package/dist/shared/zwmqxb0g.js +0 -79
- package/dist/shared/{m9tv7xn7.js → radd3z4g.js} +3 -3
- /package/dist/shared/{9k6vetvf.js → rrstp3kb.js} +0 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Enum and domain columns.
|
|
3
3
|
*
|
|
4
4
|
* The catalog column type is the type name. Compile records a dependency on
|
|
5
|
-
* the
|
|
5
|
+
* the type, and the column's `emit` adds that type when the catalog is built.
|
|
6
6
|
*/
|
|
7
7
|
import { type ColumnBuilder, type ColumnFlags, type PlainFlags } from "./column.js";
|
|
8
8
|
/**
|
|
@@ -17,14 +17,16 @@ import { type ColumnBuilder, type ColumnFlags, type PlainFlags } from "./column.
|
|
|
17
17
|
*/
|
|
18
18
|
export declare function enumColumn<const TValues extends readonly string[]>(name: string, values: TValues): ColumnBuilder<TValues[number], PlainFlags>;
|
|
19
19
|
/**
|
|
20
|
-
* A named domain over a
|
|
20
|
+
* A named domain over a column type.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* The TypeScript row type and the codec are the base column's. The catalog
|
|
23
|
+
* column type is the domain name, and the domain is a `type` object (D141).
|
|
24
|
+
* An enum base is OKM1060. Changing the base type of an existing domain is
|
|
25
|
+
* OKM1020 when the plan is built.
|
|
24
26
|
*
|
|
25
27
|
* @param name - Domain name
|
|
26
|
-
* @param base -
|
|
27
|
-
* @param check - Domain check expression
|
|
28
|
-
* @returns A domain column
|
|
28
|
+
* @param base - Column the domain is based on
|
|
29
|
+
* @param check - Domain check expression, stored as written
|
|
30
|
+
* @returns A domain column
|
|
29
31
|
*/
|
|
30
|
-
export declare function domain<TValue, TFlags extends ColumnFlags>(
|
|
32
|
+
export declare function domain<TValue, TFlags extends ColumnFlags>(name: string, base: ColumnBuilder<TValue, TFlags>, check: string): ColumnBuilder<TValue, TFlags>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `citext` extension.
|
|
3
|
+
*
|
|
4
|
+
* Case-insensitive equality is the column's ordinary `eq` once the type is
|
|
5
|
+
* `citext`. This module declares the extension so that column can build.
|
|
6
|
+
*/
|
|
7
|
+
import { type Extension, type ExtensionOptions } from "./index.js";
|
|
8
|
+
/**
|
|
9
|
+
* Declares `citext`.
|
|
10
|
+
*
|
|
11
|
+
* @param options - Schema and version pin. The version differs by Postgres major, so the default is unpinned.
|
|
12
|
+
* @returns The extension object
|
|
13
|
+
*/
|
|
14
|
+
export declare function citext(options?: ExtensionOptions): Extension;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `okmodel/ext`.
|
|
3
|
+
*
|
|
4
|
+
* `extension()` returns an object that produces its own catalog record.
|
|
5
|
+
* Duplicate and undeclared-use checks run here. Core only asks each declared
|
|
6
|
+
* object for its records.
|
|
7
|
+
*/
|
|
8
|
+
import type { ExtensionObject } from "../../../contracts/catalog/types.js";
|
|
9
|
+
/** Options on {@link extension}. */
|
|
10
|
+
export type ExtensionOptions = {
|
|
11
|
+
/** Exact pin (`1.6`) or a floor (`>=0.7`). Omitted means unpinned. */
|
|
12
|
+
readonly version?: string;
|
|
13
|
+
/** Install schema. The default is `public`. */
|
|
14
|
+
readonly schema?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Whether the extension may move.
|
|
17
|
+
*
|
|
18
|
+
* The default is `true`. A move of a non-relocatable extension is OKM1814.
|
|
19
|
+
*/
|
|
20
|
+
readonly relocatable?: boolean;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* One declared extension.
|
|
24
|
+
*
|
|
25
|
+
* Methods on a built-in, such as `pgTrgm.similar`, are the typed API. They
|
|
26
|
+
* are not stored in the catalog record.
|
|
27
|
+
*/
|
|
28
|
+
export type Extension = {
|
|
29
|
+
readonly name: string;
|
|
30
|
+
readonly schema: string;
|
|
31
|
+
readonly relocatable: boolean;
|
|
32
|
+
readonly version?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Catalog records for this declaration.
|
|
35
|
+
*
|
|
36
|
+
* @param peers - The `schema({ extensions })` list
|
|
37
|
+
* @param built - Objects the schema has already staged
|
|
38
|
+
* @returns The extension record
|
|
39
|
+
*/
|
|
40
|
+
contribute(peers: unknown, built: unknown): readonly ExtensionObject[];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Declares an extension by name.
|
|
44
|
+
*
|
|
45
|
+
* A bare declaration has the full lifecycle and no typed operators. Built-ins
|
|
46
|
+
* wrap this and add their own methods.
|
|
47
|
+
*
|
|
48
|
+
* @param name - Extension name, such as `citext` or `vector`
|
|
49
|
+
* @param options - Schema, version pin, and whether it may move
|
|
50
|
+
* @returns The definition object `schema({ extensions })` stores
|
|
51
|
+
*/
|
|
52
|
+
export declare function extension(name: string, options?: ExtensionOptions): Extension;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `pg_trgm` extension.
|
|
3
|
+
*
|
|
4
|
+
* `similar` and `wordSimilar` are where-operators. Their SQL lives in the
|
|
5
|
+
* lazy operator module. Index methods set the catalog `expression` to a
|
|
6
|
+
* `using …` tail; the core index factory does not grow a `using` field.
|
|
7
|
+
*/
|
|
8
|
+
import { type Tagged } from "../operators.js";
|
|
9
|
+
import type { IndexCall } from "../table.js";
|
|
10
|
+
import { type Extension, type ExtensionOptions } from "./index.js";
|
|
11
|
+
/** Operand stored on a trigram operator. */
|
|
12
|
+
export type TrigramQuery = {
|
|
13
|
+
readonly query: string;
|
|
14
|
+
readonly schema: string;
|
|
15
|
+
};
|
|
16
|
+
/** `pg_trgm` plus its operators and index methods. */
|
|
17
|
+
export type PgTrgm = Extension & {
|
|
18
|
+
/**
|
|
19
|
+
* `column % query`.
|
|
20
|
+
*
|
|
21
|
+
* @param query - The text to compare
|
|
22
|
+
* @returns A tagged where-operator
|
|
23
|
+
*/
|
|
24
|
+
similar(query: string): Tagged<"similar", TrigramQuery>;
|
|
25
|
+
/**
|
|
26
|
+
* `column <% query`.
|
|
27
|
+
*
|
|
28
|
+
* @param query - The text to compare
|
|
29
|
+
* @returns A tagged where-operator
|
|
30
|
+
*/
|
|
31
|
+
wordSimilar(query: string): Tagged<"wordSimilar", TrigramQuery>;
|
|
32
|
+
/**
|
|
33
|
+
* A GIN index with `gin_trgm_ops`.
|
|
34
|
+
*
|
|
35
|
+
* @param column - SQL column name
|
|
36
|
+
* @returns An index call whose expression is the `using` tail
|
|
37
|
+
*/
|
|
38
|
+
gin(column: string): IndexCall;
|
|
39
|
+
/**
|
|
40
|
+
* A GiST index with `gist_trgm_ops`.
|
|
41
|
+
*
|
|
42
|
+
* @param column - SQL column name
|
|
43
|
+
* @returns An index call whose expression is the `using` tail
|
|
44
|
+
*/
|
|
45
|
+
gist(column: string): IndexCall;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Declares `pg_trgm`.
|
|
49
|
+
*
|
|
50
|
+
* @param options - Schema and version pin
|
|
51
|
+
* @returns The extension object and its operators
|
|
52
|
+
*/
|
|
53
|
+
export declare function pgTrgm(options?: ExtensionOptions): PgTrgm;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extension2
|
|
3
|
+
} from "../../../shared/ycatkxmq.js";
|
|
4
|
+
import {
|
|
5
|
+
tag
|
|
6
|
+
} from "../../../shared/cn0n68ft.js";
|
|
7
|
+
|
|
8
|
+
// src/dialects/pg/ext/pg-trgm.ts
|
|
9
|
+
function pgTrgm(options = {}) {
|
|
10
|
+
const declared = extension2("pg_trgm", options);
|
|
11
|
+
const schema = declared.schema;
|
|
12
|
+
return {
|
|
13
|
+
...declared,
|
|
14
|
+
similar(query) {
|
|
15
|
+
return tag("similar", { query, schema });
|
|
16
|
+
},
|
|
17
|
+
wordSimilar(query) {
|
|
18
|
+
return tag("wordSimilar", { query, schema });
|
|
19
|
+
},
|
|
20
|
+
gin(column) {
|
|
21
|
+
return usingIndex(column, "gin", "gin_trgm_ops");
|
|
22
|
+
},
|
|
23
|
+
gist(column) {
|
|
24
|
+
return usingIndex(column, "gist", "gist_trgm_ops");
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function usingIndex(column, method, opclass) {
|
|
29
|
+
const quoted = `"${column.replaceAll('"', '""')}"`;
|
|
30
|
+
const call = {
|
|
31
|
+
columns: [column],
|
|
32
|
+
isUnique: false,
|
|
33
|
+
expression: `using ${method} (${quoted} ${opclass})`,
|
|
34
|
+
unique() {
|
|
35
|
+
return call;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
return call;
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
pgTrgm
|
|
42
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `okmodel/fn`.
|
|
3
|
+
*
|
|
4
|
+
* `fn()` and `trigger()` return objects that produce their own catalog
|
|
5
|
+
* records. `schema()` only asks each declared object for those records.
|
|
6
|
+
*/
|
|
7
|
+
import type { CatalogObject, FunctionLanguage, FunctionSecurity, FunctionVolatility, TriggerEvent, TriggerLevel, TriggerTiming } from "../../../contracts/catalog/types.js";
|
|
8
|
+
import type { AnyTable, SqlText } from "../table.js";
|
|
9
|
+
/** One argument of {@link fn}. */
|
|
10
|
+
export type FunctionArgumentInput = {
|
|
11
|
+
readonly name: string;
|
|
12
|
+
readonly type: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A table, or one column of a table.
|
|
16
|
+
*
|
|
17
|
+
* A table is an object dependency. `{ table, column }` is a column dependency.
|
|
18
|
+
* `column` is the SQL name.
|
|
19
|
+
*/
|
|
20
|
+
export type DependsOn = AnyTable | {
|
|
21
|
+
readonly table: AnyTable;
|
|
22
|
+
readonly column: string;
|
|
23
|
+
};
|
|
24
|
+
/** Options for {@link fn}. */
|
|
25
|
+
export type FunctionOptions = {
|
|
26
|
+
readonly arguments?: readonly FunctionArgumentInput[];
|
|
27
|
+
readonly returns: string;
|
|
28
|
+
readonly language: FunctionLanguage;
|
|
29
|
+
readonly volatility?: FunctionVolatility;
|
|
30
|
+
readonly security?: FunctionSecurity;
|
|
31
|
+
/** Required when `security` is `"definer"` (OKM1823). */
|
|
32
|
+
readonly searchPath?: string;
|
|
33
|
+
readonly body: SqlText | string;
|
|
34
|
+
/**
|
|
35
|
+
* Tables and columns the body uses.
|
|
36
|
+
*
|
|
37
|
+
* Required for plpgsql (OKM1824). Omitted for `LANGUAGE sql` that begins
|
|
38
|
+
* with `BEGIN ATOMIC`; those edges are read from `pg_depend`.
|
|
39
|
+
*/
|
|
40
|
+
readonly dependsOn?: readonly DependsOn[];
|
|
41
|
+
/** Schema. The default is `public`. */
|
|
42
|
+
readonly schema?: string;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* One declared function.
|
|
46
|
+
*
|
|
47
|
+
* `contribute` builds the catalog record. Overloads differ by argument types.
|
|
48
|
+
*/
|
|
49
|
+
export type Routine = {
|
|
50
|
+
readonly name: string;
|
|
51
|
+
readonly schema: string;
|
|
52
|
+
readonly argTypes: readonly string[];
|
|
53
|
+
/**
|
|
54
|
+
* Catalog record for this declaration.
|
|
55
|
+
*
|
|
56
|
+
* @param peers - The `schema({ functions })` list
|
|
57
|
+
* @param built - Objects the schema has already staged
|
|
58
|
+
* @returns The function record
|
|
59
|
+
*/
|
|
60
|
+
contribute(peers: unknown, built: unknown): readonly CatalogObject[];
|
|
61
|
+
};
|
|
62
|
+
/** Options for {@link trigger}. */
|
|
63
|
+
export type TriggerOptions = {
|
|
64
|
+
readonly on: AnyTable;
|
|
65
|
+
readonly timing: TriggerTiming;
|
|
66
|
+
readonly events: readonly TriggerEvent[];
|
|
67
|
+
readonly level: TriggerLevel;
|
|
68
|
+
/** `UPDATE OF` columns. SQL names. Each one is a column dependency. */
|
|
69
|
+
readonly updateOf?: readonly string[];
|
|
70
|
+
readonly when?: SqlText | string;
|
|
71
|
+
readonly calls: Routine;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* One declared trigger.
|
|
75
|
+
*
|
|
76
|
+
* Identity is `(table, name)`.
|
|
77
|
+
*/
|
|
78
|
+
export type TriggerDeclaration = {
|
|
79
|
+
readonly name: string;
|
|
80
|
+
/**
|
|
81
|
+
* Catalog record for this declaration.
|
|
82
|
+
*
|
|
83
|
+
* @param peers - The `schema({ triggers })` list
|
|
84
|
+
* @param built - Objects the schema has already staged
|
|
85
|
+
* @returns The trigger record
|
|
86
|
+
*/
|
|
87
|
+
contribute(peers: unknown, built: unknown): readonly CatalogObject[];
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Declares a function.
|
|
91
|
+
*
|
|
92
|
+
* plpgsql without `dependsOn` is OKM1824. `security: "definer"` without
|
|
93
|
+
* `searchPath` is OKM1823.
|
|
94
|
+
*
|
|
95
|
+
* @param name - Function name
|
|
96
|
+
* @param options - Signature, language, body, and dependencies
|
|
97
|
+
* @returns The definition object `schema({ functions })` stores
|
|
98
|
+
*/
|
|
99
|
+
export declare function fn(name: string, options: FunctionOptions): Routine;
|
|
100
|
+
/**
|
|
101
|
+
* Declares a trigger.
|
|
102
|
+
*
|
|
103
|
+
* @param name - Trigger name, unique on its table
|
|
104
|
+
* @param options - Table, timing, events, and the function it calls
|
|
105
|
+
* @returns The definition object `schema({ triggers })` stores
|
|
106
|
+
*/
|
|
107
|
+
export declare function trigger(name: string, options: TriggerOptions): TriggerDeclaration;
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import {
|
|
2
|
+
functionObject,
|
|
3
|
+
triggerObject
|
|
4
|
+
} from "../../../shared/9x25fxhc.js";
|
|
5
|
+
import {
|
|
6
|
+
staticNamespace2
|
|
7
|
+
} from "../../../shared/t4tbsy9h.js";
|
|
8
|
+
import {
|
|
9
|
+
OkmError2
|
|
10
|
+
} from "../../../shared/52szzakm.js";
|
|
11
|
+
|
|
12
|
+
// src/dialects/pg/fn/index.ts
|
|
13
|
+
function fn(name, options) {
|
|
14
|
+
const language = options.language;
|
|
15
|
+
const body = bodyText(options.body);
|
|
16
|
+
const atomic = language === "sql" && /^\s*begin\s+atomic\b/i.test(body);
|
|
17
|
+
if (language === "plpgsql" && options.dependsOn === undefined) {
|
|
18
|
+
throw new OkmError2("OKM1824", `Function ${name} is plpgsql and has no dependsOn. Postgres does not record dependencies inside the body.`, {
|
|
19
|
+
fix: {
|
|
20
|
+
summary: "List dependsOn. LANGUAGE sql with BEGIN ATOMIC is inferred and does not need the list."
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (options.security === "definer" && (options.searchPath === undefined || options.searchPath.trim().length === 0)) {
|
|
25
|
+
throw new OkmError2("OKM1823", `Function ${name} is security definer and has no search_path.`, {
|
|
26
|
+
fix: { summary: "Set search_path on the function to the schemas it is allowed to see." }
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
const argTypes = (options.arguments ?? []).map((argument) => argument.type);
|
|
30
|
+
const schema = options.schema ?? "public";
|
|
31
|
+
return {
|
|
32
|
+
name,
|
|
33
|
+
schema,
|
|
34
|
+
argTypes,
|
|
35
|
+
contribute(peers, built) {
|
|
36
|
+
assertPeers(peers, "functions");
|
|
37
|
+
const namespace = staticNamespace2(schema);
|
|
38
|
+
const provenance = { origin: "file", name };
|
|
39
|
+
return [
|
|
40
|
+
functionObject({
|
|
41
|
+
namespace,
|
|
42
|
+
name,
|
|
43
|
+
...options.arguments !== undefined ? { arguments: options.arguments } : {},
|
|
44
|
+
returns: options.returns,
|
|
45
|
+
language,
|
|
46
|
+
...options.volatility !== undefined ? { volatility: options.volatility } : {},
|
|
47
|
+
...options.security !== undefined ? { security: options.security } : {},
|
|
48
|
+
...options.searchPath !== undefined ? { searchPath: options.searchPath } : {},
|
|
49
|
+
body,
|
|
50
|
+
...atomic ? { atomic: true } : {},
|
|
51
|
+
provenance,
|
|
52
|
+
dependencies: dependencyEdges(options.dependsOn, built)
|
|
53
|
+
})
|
|
54
|
+
];
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function trigger(name, options) {
|
|
59
|
+
return {
|
|
60
|
+
name,
|
|
61
|
+
contribute(peers, built) {
|
|
62
|
+
assertPeers(peers, "triggers");
|
|
63
|
+
const parent = tableRef(options.on, built);
|
|
64
|
+
const namespace = staticNamespace2(options.calls.schema);
|
|
65
|
+
const calls = {
|
|
66
|
+
namespace,
|
|
67
|
+
name: options.calls.name,
|
|
68
|
+
argTypes: options.calls.argTypes
|
|
69
|
+
};
|
|
70
|
+
if (!hasIdentity(built, { kind: "function", ...calls })) {
|
|
71
|
+
throw new OkmError2("OKM1020", `Trigger ${name} calls ${options.calls.name}, which is not in the catalog.`, { fix: { summary: "List the function in schema({ functions }) before the trigger." } });
|
|
72
|
+
}
|
|
73
|
+
for (const column of options.updateOf ?? []) {
|
|
74
|
+
if (!hasIdentity(built, { kind: "column", parent, name: column })) {
|
|
75
|
+
throw new OkmError2("OKM1020", `Trigger ${name} names column ${column}, which ${parent.name} does not have.`, { fix: { summary: "Name a column of the table the trigger is on." } });
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return [
|
|
79
|
+
triggerObject({
|
|
80
|
+
parent,
|
|
81
|
+
name,
|
|
82
|
+
timing: options.timing,
|
|
83
|
+
events: options.events,
|
|
84
|
+
level: options.level,
|
|
85
|
+
calls,
|
|
86
|
+
...options.updateOf !== undefined ? { updateOf: options.updateOf } : {},
|
|
87
|
+
...options.when !== undefined ? { when: bodyText(options.when) } : {},
|
|
88
|
+
provenance: { origin: "file", name }
|
|
89
|
+
})
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function bodyText(body) {
|
|
95
|
+
return typeof body === "string" ? body : body.text;
|
|
96
|
+
}
|
|
97
|
+
function assertPeers(peers, option) {
|
|
98
|
+
if (!Array.isArray(peers)) {
|
|
99
|
+
throw new OkmError2("OKM1020", `schema({ ${option} }) must be a list.`, {
|
|
100
|
+
fix: { summary: `Pass an array to schema({ ${option} }).` }
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function dependencyEdges(dependsOn, built) {
|
|
105
|
+
if (dependsOn === undefined)
|
|
106
|
+
return [];
|
|
107
|
+
return dependsOn.map((item) => {
|
|
108
|
+
if ("column" in item && "table" in item) {
|
|
109
|
+
const parent = tableRef(item.table, built);
|
|
110
|
+
const edge = { kind: "column", parent, name: item.column };
|
|
111
|
+
if (!hasIdentity(built, edge)) {
|
|
112
|
+
throw new OkmError2("OKM1020", `dependsOn names column ${item.column}, which ${parent.name} does not have.`, { fix: { summary: "Name a column of a table in this schema." } });
|
|
113
|
+
}
|
|
114
|
+
return edge;
|
|
115
|
+
}
|
|
116
|
+
const parent = tableRef(item, built);
|
|
117
|
+
return { kind: "table", namespace: parent.namespace, name: parent.name };
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
function tableRef(table, built) {
|
|
121
|
+
if (!Array.isArray(built)) {
|
|
122
|
+
throw new OkmError2("OKM1020", `Table ${table.name} is not in the catalog.`, {
|
|
123
|
+
fix: { summary: "List the table in schema({ tables })." }
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
for (const object of built) {
|
|
127
|
+
if (!isRecord(object) || object.kind !== "table")
|
|
128
|
+
continue;
|
|
129
|
+
const identity = object.identity;
|
|
130
|
+
const provenance = object.provenance;
|
|
131
|
+
if (!isRecord(identity) || !isRecord(provenance))
|
|
132
|
+
continue;
|
|
133
|
+
if (provenance.origin === "file" && provenance.name === table.name && typeof identity.name === "string") {
|
|
134
|
+
const namespace = identity.namespace;
|
|
135
|
+
if (isRecord(namespace) && namespace.form === "static" && typeof namespace.name === "string") {
|
|
136
|
+
return { namespace: staticNamespace2(namespace.name), name: identity.name };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
throw new OkmError2("OKM1020", `Table ${table.name} is not in the catalog.`, {
|
|
141
|
+
fix: { summary: "List the table in schema({ tables })." }
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function hasIdentity(built, identity) {
|
|
145
|
+
if (!Array.isArray(built))
|
|
146
|
+
return false;
|
|
147
|
+
for (const object of built) {
|
|
148
|
+
if (!isRecord(object) || !isRecord(object.identity))
|
|
149
|
+
continue;
|
|
150
|
+
if (same(object.identity, identity))
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
function same(left, right) {
|
|
156
|
+
if (left.kind !== right.kind)
|
|
157
|
+
return false;
|
|
158
|
+
if (right.kind === "function") {
|
|
159
|
+
return left.name === right.name && JSON.stringify(left.argTypes) === JSON.stringify(right.argTypes);
|
|
160
|
+
}
|
|
161
|
+
if (right.kind === "column") {
|
|
162
|
+
const parent = left.parent;
|
|
163
|
+
return left.name === right.name && isRecord(parent) && parent.name === right.parent.name;
|
|
164
|
+
}
|
|
165
|
+
if (right.kind === "table")
|
|
166
|
+
return left.name === right.name;
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
function isRecord(value) {
|
|
170
|
+
return typeof value === "object" && value !== null;
|
|
171
|
+
}
|
|
172
|
+
export {
|
|
173
|
+
fn,
|
|
174
|
+
trigger
|
|
175
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The trigger and function `timestamps({ enforce: "trigger" })` contributes.
|
|
3
|
+
*
|
|
4
|
+
* One function per updated-column SQL name. One trigger per table. Provenance
|
|
5
|
+
* is the timestamps trait. The body writes `new.<column> = now()`.
|
|
6
|
+
*/
|
|
7
|
+
import type { CatalogObject } from "../../../contracts/catalog/types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Catalog records for tables that carry the timestamps trait.
|
|
10
|
+
*
|
|
11
|
+
* @param built - Objects already staged, including columns
|
|
12
|
+
* @returns The function and one trigger per table, or nothing when no table opted in
|
|
13
|
+
*/
|
|
14
|
+
export declare function timestampRecords(built: unknown): readonly CatalogObject[];
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
jsonReplacer2,
|
|
3
3
|
json2,
|
|
4
4
|
jsonb2
|
|
5
|
-
} from "../../shared/
|
|
5
|
+
} from "../../shared/gjthds9j.js";
|
|
6
6
|
import {
|
|
7
7
|
encodeInstant,
|
|
8
8
|
decodeInstant,
|
|
@@ -14,17 +14,25 @@ import {
|
|
|
14
14
|
time2,
|
|
15
15
|
timetz2,
|
|
16
16
|
interval2
|
|
17
|
-
} from "../../shared/
|
|
18
|
-
import {
|
|
19
|
-
id2,
|
|
20
|
-
uuid2
|
|
21
|
-
} from "../../shared/ps43134h.js";
|
|
17
|
+
} from "../../shared/1g0drakv.js";
|
|
22
18
|
import {
|
|
23
19
|
one2,
|
|
24
20
|
many2,
|
|
25
21
|
manyThrough2,
|
|
26
22
|
schema2
|
|
27
|
-
} from "../../shared/
|
|
23
|
+
} from "../../shared/3p4b1fg0.js";
|
|
24
|
+
import {
|
|
25
|
+
domainType
|
|
26
|
+
} from "../../shared/g7ez901n.js";
|
|
27
|
+
import {
|
|
28
|
+
id2,
|
|
29
|
+
uuid2
|
|
30
|
+
} from "../../shared/dyj86cmj.js";
|
|
31
|
+
import {
|
|
32
|
+
table2,
|
|
33
|
+
index2,
|
|
34
|
+
sql2
|
|
35
|
+
} from "../../shared/jsd07prz.js";
|
|
28
36
|
import {
|
|
29
37
|
text2,
|
|
30
38
|
varchar2,
|
|
@@ -32,25 +40,27 @@ import {
|
|
|
32
40
|
citext2,
|
|
33
41
|
encodeText,
|
|
34
42
|
decodeText
|
|
35
|
-
} from "../../shared/
|
|
36
|
-
import {
|
|
37
|
-
table2,
|
|
38
|
-
index2,
|
|
39
|
-
sql2
|
|
40
|
-
} from "../../shared/x9v1qgeb.js";
|
|
43
|
+
} from "../../shared/4m9fn52z.js";
|
|
41
44
|
import {
|
|
42
45
|
ColumnBuilder2,
|
|
43
46
|
required,
|
|
44
|
-
openColumn
|
|
45
|
-
|
|
47
|
+
openColumn,
|
|
48
|
+
formatType
|
|
49
|
+
} from "../../shared/c9z5g0fm.js";
|
|
46
50
|
import {
|
|
47
51
|
definition,
|
|
48
|
-
unavailable,
|
|
49
52
|
rejected
|
|
50
|
-
} from "../../shared/
|
|
53
|
+
} from "../../shared/tmbdywx0.js";
|
|
54
|
+
import {
|
|
55
|
+
sameNamespace2,
|
|
56
|
+
compareText
|
|
57
|
+
} from "../../shared/t4tbsy9h.js";
|
|
51
58
|
import {
|
|
52
59
|
tag
|
|
53
60
|
} from "../../shared/cn0n68ft.js";
|
|
61
|
+
import {
|
|
62
|
+
catalogError2
|
|
63
|
+
} from "../../shared/52szzakm.js";
|
|
54
64
|
var __defProp = Object.defineProperty;
|
|
55
65
|
var __returnValue = (v) => v;
|
|
56
66
|
function __exportSetter(name, newValue) {
|
|
@@ -664,8 +674,83 @@ function enumColumn(name, values) {
|
|
|
664
674
|
sqlForm: "quote"
|
|
665
675
|
});
|
|
666
676
|
}
|
|
667
|
-
function domain(
|
|
668
|
-
|
|
677
|
+
function domain(name, base, check) {
|
|
678
|
+
if (name.length === 0)
|
|
679
|
+
definition("domain name must be a non-empty type name.");
|
|
680
|
+
if (check.length === 0)
|
|
681
|
+
definition("domain check must be a non-empty expression.");
|
|
682
|
+
if (base.state.enumLabels !== undefined) {
|
|
683
|
+
definition("A domain cannot use an enum as its base in this version. Use a scalar column type.");
|
|
684
|
+
}
|
|
685
|
+
const baseSql = canonicalBase(formatType(base.state.baseType, base.state.dims));
|
|
686
|
+
const extension = base.state.extension;
|
|
687
|
+
const inner = base.state.baseType;
|
|
688
|
+
const nested = base.state.domain !== undefined;
|
|
689
|
+
return new ColumnBuilder2({
|
|
690
|
+
...base.state,
|
|
691
|
+
baseType: name,
|
|
692
|
+
dims: 0,
|
|
693
|
+
typeDependency: name,
|
|
694
|
+
enumLabels: undefined,
|
|
695
|
+
domain: {
|
|
696
|
+
base: baseSql,
|
|
697
|
+
check,
|
|
698
|
+
emit(namespace, provenance, objects) {
|
|
699
|
+
base.state.domain?.emit?.(namespace, provenance, objects);
|
|
700
|
+
const dependencies = [];
|
|
701
|
+
if (extension !== undefined)
|
|
702
|
+
dependencies.push({ kind: "extension", name: extension });
|
|
703
|
+
if (nested)
|
|
704
|
+
dependencies.push({ kind: "type", namespace, name: inner });
|
|
705
|
+
const built = domainType({
|
|
706
|
+
namespace,
|
|
707
|
+
name,
|
|
708
|
+
base: baseSql,
|
|
709
|
+
check,
|
|
710
|
+
provenance,
|
|
711
|
+
...dependencies.length > 0 ? { dependencies } : {}
|
|
712
|
+
});
|
|
713
|
+
const index = objects.findIndex((object) => object.kind === "type" && object.identity.name === name && sameNamespace2(object.identity.namespace, namespace));
|
|
714
|
+
const previous = index >= 0 ? objects[index] : undefined;
|
|
715
|
+
if (previous !== undefined && previous.kind === "type") {
|
|
716
|
+
const definition = previous.definition;
|
|
717
|
+
if (!("base" in definition) || definition.base !== baseSql || definition.check !== check) {
|
|
718
|
+
catalogError2("OKM1020", `Domain ${name} is ${"base" in definition ? definition.base : "an enum"} on ${previous.provenance.name} and ${baseSql} on ${provenance.name}. One domain has one base and one check.`);
|
|
719
|
+
}
|
|
720
|
+
if (compareText(provenance.name, previous.provenance.name) < 0)
|
|
721
|
+
objects[index] = built;
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
objects.push(built);
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
function canonicalBase(typeName) {
|
|
730
|
+
const bracket = typeName.indexOf("[");
|
|
731
|
+
const scalar = bracket === -1 ? typeName : typeName.slice(0, bracket);
|
|
732
|
+
const suffix = bracket === -1 ? "" : typeName.slice(bracket);
|
|
733
|
+
return canonicalScalar(scalar) + suffix;
|
|
734
|
+
}
|
|
735
|
+
function canonicalScalar(typeName) {
|
|
736
|
+
const varchar = /^varchar\((\d+)\)$/.exec(typeName);
|
|
737
|
+
if (varchar !== null)
|
|
738
|
+
return `character varying(${varchar[1] ?? ""})`;
|
|
739
|
+
const fixed = /^char\((\d+)\)$/.exec(typeName);
|
|
740
|
+
if (fixed !== null)
|
|
741
|
+
return `character(${fixed[1] ?? ""})`;
|
|
742
|
+
const timed = /^(timestamptz|timestamp|timetz|time)(\(\d+\))?$/.exec(typeName);
|
|
743
|
+
if (timed === null)
|
|
744
|
+
return typeName;
|
|
745
|
+
const name = timed[1];
|
|
746
|
+
const precision = timed[2] ?? "";
|
|
747
|
+
if (name === "timestamptz")
|
|
748
|
+
return `timestamp${precision} with time zone`;
|
|
749
|
+
if (name === "timestamp")
|
|
750
|
+
return `timestamp${precision} without time zone`;
|
|
751
|
+
if (name === "timetz")
|
|
752
|
+
return `time${precision} with time zone`;
|
|
753
|
+
return `time${precision} without time zone`;
|
|
669
754
|
}
|
|
670
755
|
// src/dialects/pg/namespace.ts
|
|
671
756
|
var t = {
|