@intentius/chant-lexicon-sql 0.124.31 → 0.124.33
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/dist/change-set.js +250 -0
- package/dist/clickhouse/access.js +722 -0
- package/dist/clickhouse/apply/apply.js +243 -0
- package/dist/clickhouse/apply/mutations.js +66 -0
- package/dist/clickhouse/apply/statements.js +545 -0
- package/dist/clickhouse/catalog-types.js +7 -0
- package/dist/clickhouse/container.js +152 -0
- package/dist/clickhouse/engine-syntax.js +159 -0
- package/dist/clickhouse/entities.js +593 -0
- package/dist/clickhouse/expressions.js +107 -0
- package/dist/clickhouse/http.js +55 -0
- package/dist/clickhouse/import/generator.js +192 -0
- package/dist/clickhouse/import/inlined.js +207 -0
- package/dist/clickhouse/import/ir.js +160 -0
- package/dist/clickhouse/import/live-export.js +131 -0
- package/dist/clickhouse/import/parser.js +17 -0
- package/dist/clickhouse/live/bind.js +116 -0
- package/dist/clickhouse/live/catalog.js +223 -0
- package/dist/clickhouse/live/describe-resources.js +91 -0
- package/dist/clickhouse/live/undeclarable.js +59 -0
- package/dist/clickhouse/overlays/codecs.js +57 -0
- package/dist/clickhouse/overlays/engines.js +101 -0
- package/dist/clickhouse/overlays/kinds.js +1 -0
- package/dist/clickhouse/overlays/projections.js +26 -0
- package/dist/clickhouse/overlays/skip-indexes.js +40 -0
- package/dist/clickhouse/overlays/ttl.js +34 -0
- package/dist/clickhouse/overlays/types.js +59 -0
- package/dist/clickhouse/ownership.js +83 -0
- package/dist/clickhouse/parser.js +674 -0
- package/dist/clickhouse/plan/commands.js +159 -0
- package/dist/clickhouse/plan/deep.js +345 -0
- package/dist/clickhouse/plan/diff.js +312 -0
- package/dist/clickhouse/plan/disruption.js +73 -0
- package/dist/clickhouse/plan/normalize.js +545 -0
- package/dist/clickhouse/plan/rebuild-handoff.js +57 -0
- package/dist/clickhouse/plan/report.js +26 -0
- package/dist/clickhouse/plan/rules.js +72 -0
- package/dist/clickhouse/plan/schema.js +67 -0
- package/dist/clickhouse/plan/server-format.js +35 -0
- package/dist/clickhouse/rebuild/backfill.js +265 -0
- package/dist/clickhouse/rebuild/engines.js +146 -0
- package/dist/clickhouse/rebuild/observe.js +260 -0
- package/dist/clickhouse/rebuild/op.js +152 -0
- package/dist/clickhouse/rebuild/partitions.js +65 -0
- package/dist/clickhouse/rebuild/receipts.js +120 -0
- package/dist/clickhouse/rebuild/replicas.js +121 -0
- package/dist/clickhouse/rebuild/shards.js +76 -0
- package/dist/clickhouse/rebuild/steps.js +383 -0
- package/dist/clickhouse/rebuild/verify.js +279 -0
- package/dist/clickhouse/row-types.js +151 -0
- package/dist/clickhouse/testing/fake-server.js +47 -0
- package/dist/clickhouse/testing/roundtrip-schema.js +25 -0
- package/dist/clickhouse/testing/writable-server.js +123 -0
- package/dist/clickhouse/tokens.js +23 -0
- package/dist/clickhouse/topology.js +463 -0
- package/dist/clickhouse/type-syntax.js +73 -0
- package/dist/clickhouse.js +25 -0
- package/dist/codegen/classifier-page.js +93 -0
- package/dist/codegen/clickhouse-module.js +249 -0
- package/dist/codegen/coverage-page.js +70 -0
- package/dist/codegen/docs-cli.js +3 -0
- package/dist/codegen/docs.js +222 -0
- package/dist/codegen/generate-cli.js +13 -0
- package/dist/codegen/generate.js +97 -0
- package/dist/codegen/package.js +28 -0
- package/dist/codegen/postgres-classifier-page.js +95 -0
- package/dist/codegen/postgres-module.js +418 -0
- package/dist/codegen/registry.js +52 -0
- package/dist/composites/audit-log-table.js +35 -0
- package/dist/composites/catalog.js +524 -0
- package/dist/composites/cdc-mirror.js +32 -0
- package/dist/composites/clickhouse.js +6 -0
- package/dist/composites/events-table.js +26 -0
- package/dist/composites/index.js +8 -0
- package/dist/composites/join-table.js +25 -0
- package/dist/composites/postgres.js +6 -0
- package/dist/composites/refreshed-view.js +24 -0
- package/dist/composites/replacing-table.js +28 -0
- package/dist/composites/rollup-view.js +29 -0
- package/dist/composites/sharded-table.js +27 -0
- package/dist/composites/soft-delete-table.js +34 -0
- package/dist/composites/tenant-table.js +26 -0
- package/dist/composites/typed.js +8 -0
- package/dist/config.js +206 -0
- package/dist/core/apply.js +93 -0
- package/dist/core/classifier.js +115 -0
- package/dist/core/container.js +69 -0
- package/dist/core/cursor.js +261 -0
- package/dist/core/diff.js +48 -0
- package/dist/core/entity.js +58 -0
- package/dist/core/find-templates.js +118 -0
- package/dist/core/foreign-tables.js +27 -0
- package/dist/core/handoff.js +32 -0
- package/dist/core/index.js +64 -0
- package/dist/core/interpolation.js +191 -0
- package/dist/core/normalize.js +43 -0
- package/dist/core/ownership.js +119 -0
- package/dist/core/receipts.js +22 -0
- package/dist/core/references.js +61 -0
- package/dist/core/statements.js +42 -0
- package/dist/core/template.js +79 -0
- package/dist/core/testing/http-stub.js +21 -0
- package/dist/core/tokens.js +202 -0
- package/dist/core/typed.js +40 -0
- package/dist/core/undeclarable.js +46 -0
- package/dist/coverage.js +161 -0
- package/dist/detect.js +32 -0
- package/dist/dialects.js +18 -0
- package/dist/files/build-root.js +72 -0
- package/dist/files/clickhouse.js +138 -0
- package/dist/files/common.js +58 -0
- package/dist/files/postgres.js +389 -0
- package/dist/generated/clickhouse-types.js +5 -0
- package/dist/generated/clickhouse.js +4361 -0
- package/dist/generated/postgres-types.js +227 -0
- package/dist/generated/postgres.js +3667 -0
- package/dist/import-generator.js +14 -0
- package/dist/import-parser.js +71 -0
- package/dist/index.js +24 -0
- package/dist/init-templates.js +290 -0
- package/dist/integrity.json +2 -2
- package/dist/lint/audit-catalog.js +31 -0
- package/dist/lint/audit-lineage.js +22 -0
- package/dist/lint/post-synth/audit-entries.js +34 -0
- package/dist/lint/post-synth/clickhouse-helpers.js +79 -0
- package/dist/lint/post-synth/clickhouse-type-check.js +162 -0
- package/dist/lint/post-synth/index.js +112 -0
- package/dist/lint/post-synth/postgres-audit-entries.js +35 -0
- package/dist/lint/post-synth/postgres-helpers.js +65 -0
- package/dist/lint/post-synth/postgres-names.js +507 -0
- package/dist/lint/post-synth/sql-helpers.js +23 -0
- package/dist/lint/post-synth/sql101.js +59 -0
- package/dist/lint/post-synth/sql102.js +34 -0
- package/dist/lint/post-synth/sqlch101.js +34 -0
- package/dist/lint/post-synth/sqlch102.js +23 -0
- package/dist/lint/post-synth/sqlch103.js +45 -0
- package/dist/lint/post-synth/sqlch104.js +41 -0
- package/dist/lint/post-synth/sqlch105.js +36 -0
- package/dist/lint/post-synth/sqlch106.js +27 -0
- package/dist/lint/post-synth/sqlch107.js +39 -0
- package/dist/lint/post-synth/sqlch108.js +28 -0
- package/dist/lint/post-synth/sqlch109.js +21 -0
- package/dist/lint/post-synth/sqlch110.js +31 -0
- package/dist/lint/post-synth/sqlch111.js +41 -0
- package/dist/lint/post-synth/sqlch112.js +28 -0
- package/dist/lint/post-synth/sqlch113.js +19 -0
- package/dist/lint/post-synth/sqlch114.js +26 -0
- package/dist/lint/post-synth/sqlch115.js +30 -0
- package/dist/lint/post-synth/sqlch116.js +22 -0
- package/dist/lint/post-synth/sqlch117.js +26 -0
- package/dist/lint/post-synth/sqlch118.js +27 -0
- package/dist/lint/post-synth/sqlch119.js +32 -0
- package/dist/lint/post-synth/sqlch120.js +20 -0
- package/dist/lint/post-synth/sqlch121.js +11 -0
- package/dist/lint/post-synth/sqlch122.js +11 -0
- package/dist/lint/post-synth/sqlch123.js +10 -0
- package/dist/lint/post-synth/sqlch124.js +21 -0
- package/dist/lint/post-synth/sqlch125.js +55 -0
- package/dist/lint/post-synth/sqlch126.js +62 -0
- package/dist/lint/post-synth/sqlch127.js +132 -0
- package/dist/lint/post-synth/sqlpg101.js +25 -0
- package/dist/lint/post-synth/sqlpg102.js +35 -0
- package/dist/lint/post-synth/sqlpg103.js +23 -0
- package/dist/lint/post-synth/sqlpg104.js +23 -0
- package/dist/lint/post-synth/sqlpg105.js +22 -0
- package/dist/lint/post-synth/sqlpg106.js +22 -0
- package/dist/lint/post-synth/sqlpg107.js +22 -0
- package/dist/lint/post-synth/sqlpg108.js +28 -0
- package/dist/lint/post-synth/sqlpg109.js +39 -0
- package/dist/lint/post-synth/sqlpg110.js +38 -0
- package/dist/lint/post-synth/sqlpg111.js +23 -0
- package/dist/lint/post-synth/sqlpg112.js +25 -0
- package/dist/lint/post-synth/sqlpg113.js +29 -0
- package/dist/lint/post-synth/sqlpg114.js +39 -0
- package/dist/lint/post-synth/sqlpg115.js +48 -0
- package/dist/lint/post-synth/sqlpg116.js +26 -0
- package/dist/lint/post-synth/sqlpg117.js +24 -0
- package/dist/lint/post-synth/sqlpg118.js +22 -0
- package/dist/lint/post-synth/sqlpg119.js +41 -0
- package/dist/lint/post-synth/sqlpg120.js +83 -0
- package/dist/lint/post-synth/sqlpg121.js +33 -0
- package/dist/lint/post-synth/sqlpg122.js +27 -0
- package/dist/lint/post-synth/sqlpg123.js +69 -0
- package/dist/lint/post-synth/sqlpg124.js +50 -0
- package/dist/lint/post-synth/sqlpg125.js +41 -0
- package/dist/lint/post-synth/sqlpg126.js +38 -0
- package/dist/lint/rules/index.js +12 -0
- package/dist/lint/rules/postgres-templates.js +27 -0
- package/dist/lint/rules/sqlch001.js +79 -0
- package/dist/lint/rules/sqlch002.js +124 -0
- package/dist/lint/rules/sqlch003.js +69 -0
- package/dist/lint/rules/sqlch004.js +83 -0
- package/dist/lint/rules/sqlpg001.js +68 -0
- package/dist/lint/rules/sqlpg002.js +69 -0
- package/dist/lint/rules/sqlpg003.js +58 -0
- package/dist/lint/rules/sqlpg004.js +77 -0
- package/dist/lint/rules/sqlpg005.js +86 -0
- package/dist/lint/rules/templates.js +25 -0
- package/dist/lint/rules/typed-names.js +132 -0
- package/dist/live-dialect.js +32 -0
- package/dist/lsp/catalog.js +44 -0
- package/dist/lsp/completions.js +136 -0
- package/dist/lsp/hover.js +115 -0
- package/dist/lsp/postgres-catalog.js +176 -0
- package/dist/lsp/postgres-template.js +171 -0
- package/dist/lsp/postgres.js +266 -0
- package/dist/lsp/refs.js +60 -0
- package/dist/lsp/registry.d.ts.map +1 -1
- package/dist/lsp/registry.js +19 -0
- package/dist/lsp/template.js +143 -0
- package/dist/manifest.json +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +293 -0
- package/dist/mcp/postgres.js +117 -0
- package/dist/migration-statements.js +243 -0
- package/dist/op/activities/clickhouse-apply.js +83 -0
- package/dist/op/activities/clickhouse-emulator.js +53 -0
- package/dist/op/activities/clickhouse-rebuild.js +119 -0
- package/dist/op/activities/index.js +26 -0
- package/dist/op/activities/postgres-apply.js +126 -0
- package/dist/op/activities/postgres-emulator.js +70 -0
- package/dist/op/activities/postgres-migration.js +156 -0
- package/dist/op/activities/sql-exec.js +57 -0
- package/dist/op/activity-contracts.js +103 -0
- package/dist/package-cli.js +14 -0
- package/dist/plugin.js +259 -0
- package/dist/postgres/access/acl.js +344 -0
- package/dist/postgres/access/changes.js +30 -0
- package/dist/postgres/access/import.js +61 -0
- package/dist/postgres/access/live.js +96 -0
- package/dist/postgres/apply/apply.js +557 -0
- package/dist/postgres/apply/statements.js +882 -0
- package/dist/postgres/catalog-types.js +18 -0
- package/dist/postgres/container.js +58 -0
- package/dist/postgres/entities.js +1390 -0
- package/dist/postgres/entity-types.js +28 -0
- package/dist/postgres/import/generator.js +283 -0
- package/dist/postgres/import/ir.js +53 -0
- package/dist/postgres/import/live-export.js +83 -0
- package/dist/postgres/keywords.js +32 -0
- package/dist/postgres/live/bind.js +130 -0
- package/dist/postgres/live/catalog-kinds.js +301 -0
- package/dist/postgres/live/catalog.js +644 -0
- package/dist/postgres/live/client.js +151 -0
- package/dist/postgres/live/describe-resources.js +135 -0
- package/dist/postgres/live/undeclarable.js +111 -0
- package/dist/postgres/migrate/backfill.js +170 -0
- package/dist/postgres/migrate/batches.js +122 -0
- package/dist/postgres/migrate/carry.js +518 -0
- package/dist/postgres/migrate/handoff.js +59 -0
- package/dist/postgres/migrate/names.js +61 -0
- package/dist/postgres/migrate/observe.js +360 -0
- package/dist/postgres/migrate/op.js +178 -0
- package/dist/postgres/migrate/receipts.js +117 -0
- package/dist/postgres/migrate/replication.js +106 -0
- package/dist/postgres/migrate/steps.js +514 -0
- package/dist/postgres/overlays/columns.js +31 -0
- package/dist/postgres/overlays/constraints.js +52 -0
- package/dist/postgres/overlays/extension-objects.js +88 -0
- package/dist/postgres/overlays/indexes.js +25 -0
- package/dist/postgres/overlays/kinds.js +2 -0
- package/dist/postgres/overlays/partitioning.js +23 -0
- package/dist/postgres/overlays/relations.js +25 -0
- package/dist/postgres/overlays/storage.js +65 -0
- package/dist/postgres/overlays/type-ddl.js +36 -0
- package/dist/postgres/overlays/types.js +74 -0
- package/dist/postgres/parser.js +1824 -0
- package/dist/postgres/plan/commands.js +137 -0
- package/dist/postgres/plan/deep.js +324 -0
- package/dist/postgres/plan/diff.js +499 -0
- package/dist/postgres/plan/disruption.js +64 -0
- package/dist/postgres/plan/normalize.js +889 -0
- package/dist/postgres/plan/report.js +21 -0
- package/dist/postgres/plan/rules.js +115 -0
- package/dist/postgres/plan/schema.js +105 -0
- package/dist/postgres/plan/server-normalize.js +166 -0
- package/dist/postgres/providers/aurora.js +44 -0
- package/dist/postgres/providers/azure.js +53 -0
- package/dist/postgres/providers/cloud-sql.js +41 -0
- package/dist/postgres/providers/index.js +73 -0
- package/dist/postgres/providers/neon.js +44 -0
- package/dist/postgres/providers/rds.js +47 -0
- package/dist/postgres/providers/supabase.js +45 -0
- package/dist/postgres/providers/types.js +21 -0
- package/dist/postgres/row-types.js +107 -0
- package/dist/postgres/testing/fake-client.js +34 -0
- package/dist/postgres/testing/migration.js +48 -0
- package/dist/postgres/testing/roundtrip-schema.js +64 -0
- package/dist/postgres/testing/server.js +47 -0
- package/dist/postgres/testing/writable-server.js +160 -0
- package/dist/postgres/tokens.js +41 -0
- package/dist/postgres.js +15 -0
- package/dist/read/clickhouse.js +82 -0
- package/dist/read/objects.js +44 -0
- package/dist/read/postgres.js +104 -0
- package/dist/read.js +52 -0
- package/dist/receipts.js +207 -0
- package/dist/serializer.js +172 -0
- package/dist/skill-defs.js +93 -0
- package/dist/spec/catalog.js +191 -0
- package/dist/spec/fetch.d.ts.map +1 -1
- package/dist/spec/fetch.js +90 -0
- package/dist/spec/pin.js +42 -0
- package/dist/spec/postgres-catalog.js +171 -0
- package/dist/spec/postgres-fetch.js +91 -0
- package/dist/spec/postgres-pin.js +82 -0
- package/dist/sql-files.js +206 -0
- package/dist/sql-types-command.js +97 -0
- package/dist/sql-types.js +323 -0
- package/dist/token-source.js +156 -0
- package/dist/validate-cli.js +5 -0
- package/dist/validate.js +151 -0
- package/dist/workspace-outputs.js +191 -0
- package/package.json +7 -7
- package/src/codegen/package.ts +2 -2
- package/src/lint/rules/typescript-7.test.ts +2 -1
- package/src/lsp/catalog.ts +2 -2
- package/src/lsp/postgres-catalog.ts +2 -2
- package/src/lsp/registry.ts +2 -1
- package/src/mcp/index.ts +4 -2
- package/src/spec/fetch.ts +2 -2
- package/src/spec/postgres-fetch.ts +2 -2
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
export const compositeCatalog = [
|
|
2
|
+
{
|
|
3
|
+
"name": "AuditLogTable",
|
|
4
|
+
"lexicon": "sql",
|
|
5
|
+
"description": "An append-only audit log partitioned by month on its timestamp, with a default partition and an index by actor.",
|
|
6
|
+
"bundles": [
|
|
7
|
+
"PostgresIndex",
|
|
8
|
+
"PostgresTable"
|
|
9
|
+
],
|
|
10
|
+
"params": [
|
|
11
|
+
{
|
|
12
|
+
"name": "name",
|
|
13
|
+
"type": "string",
|
|
14
|
+
"required": true,
|
|
15
|
+
"description": "The table's name, unqualified."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"name": "schema",
|
|
19
|
+
"type": "PostgresSchema | string",
|
|
20
|
+
"required": false,
|
|
21
|
+
"description": "The schema the table and its partitions live in: the entity, or its name (default `public`)."
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"name": "timestamp",
|
|
25
|
+
"type": "string",
|
|
26
|
+
"required": false,
|
|
27
|
+
"description": "The event time column, the partition key (default `occurred_at`)."
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "actor",
|
|
31
|
+
"type": "string",
|
|
32
|
+
"required": false,
|
|
33
|
+
"description": "The column naming who acted (default `actor`)."
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
"name": "CdcMirror",
|
|
39
|
+
"lexicon": "sql",
|
|
40
|
+
"description": "A ReplacingMergeTree mirror of a CDC-fed source table, with a view of the rows not deleted.",
|
|
41
|
+
"bundles": [
|
|
42
|
+
"ClickHouseTable",
|
|
43
|
+
"ClickHouseView"
|
|
44
|
+
],
|
|
45
|
+
"params": [
|
|
46
|
+
{
|
|
47
|
+
"name": "name",
|
|
48
|
+
"type": "string",
|
|
49
|
+
"required": true,
|
|
50
|
+
"description": "The mirror table's name."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "columns",
|
|
54
|
+
"type": "string",
|
|
55
|
+
"required": true,
|
|
56
|
+
"description": "The source table's columns, as SQL, without the version and deleted columns."
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "primaryKey",
|
|
60
|
+
"type": "string",
|
|
61
|
+
"required": true,
|
|
62
|
+
"description": "The source table's primary key, the mirror's sort key: `id` or `(tenant_id, id)`."
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"name": "version",
|
|
66
|
+
"type": "string",
|
|
67
|
+
"required": false,
|
|
68
|
+
"description": "The version column the pipeline writes (default `_version`, UInt64)."
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"name": "deleted",
|
|
72
|
+
"type": "string",
|
|
73
|
+
"required": false,
|
|
74
|
+
"description": "The deleted flag the pipeline writes (default `_is_deleted`, UInt8, 1 for a delete)."
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"name": "partitionBy",
|
|
78
|
+
"type": "string",
|
|
79
|
+
"required": false,
|
|
80
|
+
"description": "A `PARTITION BY` expression."
|
|
81
|
+
}
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"name": "EventsTable",
|
|
86
|
+
"lexicon": "sql",
|
|
87
|
+
"description": "An append-only MergeTree events table, partitioned by its timestamp and expired by TTL.",
|
|
88
|
+
"bundles": [
|
|
89
|
+
"ClickHouseTable"
|
|
90
|
+
],
|
|
91
|
+
"params": [
|
|
92
|
+
{
|
|
93
|
+
"name": "name",
|
|
94
|
+
"type": "string",
|
|
95
|
+
"required": true,
|
|
96
|
+
"description": "The table's name, `name` or `database.name`."
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"name": "columns",
|
|
100
|
+
"type": "string",
|
|
101
|
+
"required": true,
|
|
102
|
+
"description": "Every column except the timestamp, as SQL: `user_id UUID, kind LowCardinality(String)`."
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"name": "orderBy",
|
|
106
|
+
"type": "string",
|
|
107
|
+
"required": true,
|
|
108
|
+
"description": "The sort key."
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "timestamp",
|
|
112
|
+
"type": "string",
|
|
113
|
+
"required": false,
|
|
114
|
+
"description": "The timestamp column (default `ts`)."
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"name": "timestampType",
|
|
118
|
+
"type": "string",
|
|
119
|
+
"required": false,
|
|
120
|
+
"description": "The timestamp's type (default `DateTime`): a Date, DateTime or DateTime64."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"name": "ttlDays",
|
|
124
|
+
"type": "number",
|
|
125
|
+
"required": false,
|
|
126
|
+
"description": "Days a row is kept (default 90)."
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"name": "partitionBy",
|
|
130
|
+
"type": "string",
|
|
131
|
+
"required": false,
|
|
132
|
+
"description": "The partition key (default `toYYYYMM(<timestamp>)`)."
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"name": "JoinTable",
|
|
138
|
+
"lexicon": "sql",
|
|
139
|
+
"description": "The table of a many-to-many relation: two foreign keys, a composite primary key and the reverse index.",
|
|
140
|
+
"bundles": [
|
|
141
|
+
"PostgresIndex",
|
|
142
|
+
"PostgresTable"
|
|
143
|
+
],
|
|
144
|
+
"params": [
|
|
145
|
+
{
|
|
146
|
+
"name": "name",
|
|
147
|
+
"type": "string",
|
|
148
|
+
"required": true,
|
|
149
|
+
"description": "The table's name, unqualified."
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "schema",
|
|
153
|
+
"type": "PostgresSchema | string",
|
|
154
|
+
"required": false,
|
|
155
|
+
"description": "The schema the table lives in: the entity, or its name (default `public`)."
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "left",
|
|
159
|
+
"type": "PostgresTable",
|
|
160
|
+
"required": true,
|
|
161
|
+
"description": "The table on the left of the relation, as the entity."
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "leftKey",
|
|
165
|
+
"type": "string",
|
|
166
|
+
"required": false,
|
|
167
|
+
"description": "The column on the left table the key references (default `id`)."
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"name": "leftColumn",
|
|
171
|
+
"type": "string",
|
|
172
|
+
"required": true,
|
|
173
|
+
"description": "The join table's column holding the left key: `user_id`."
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
"name": "leftType",
|
|
177
|
+
"type": "string",
|
|
178
|
+
"required": false,
|
|
179
|
+
"description": "The left column's type (default `bigint`)."
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"name": "right",
|
|
183
|
+
"type": "PostgresTable",
|
|
184
|
+
"required": true,
|
|
185
|
+
"description": "The table on the right of the relation, as the entity."
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"name": "rightKey",
|
|
189
|
+
"type": "string",
|
|
190
|
+
"required": false,
|
|
191
|
+
"description": "The column on the right table the key references (default `id`)."
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"name": "rightColumn",
|
|
195
|
+
"type": "string",
|
|
196
|
+
"required": true,
|
|
197
|
+
"description": "The join table's column holding the right key: `team_id`."
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"name": "rightType",
|
|
201
|
+
"type": "string",
|
|
202
|
+
"required": false,
|
|
203
|
+
"description": "The right column's type (default `bigint`)."
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"name": "onDelete",
|
|
207
|
+
"type": "string",
|
|
208
|
+
"required": false,
|
|
209
|
+
"description": "What happens to a link when the row it references is deleted (default `CASCADE`)."
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"name": "RefreshedView",
|
|
215
|
+
"lexicon": "sql",
|
|
216
|
+
"description": "A materialized view over a source, with the unique index that allows REFRESH ...",
|
|
217
|
+
"bundles": [
|
|
218
|
+
"PostgresIndex",
|
|
219
|
+
"PostgresView"
|
|
220
|
+
],
|
|
221
|
+
"params": [
|
|
222
|
+
{
|
|
223
|
+
"name": "name",
|
|
224
|
+
"type": "string",
|
|
225
|
+
"required": true,
|
|
226
|
+
"description": "The view's name, unqualified."
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"name": "schema",
|
|
230
|
+
"type": "PostgresSchema | string",
|
|
231
|
+
"required": false,
|
|
232
|
+
"description": "The schema the view lives in: the entity, or its name (default `public`)."
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"name": "source",
|
|
236
|
+
"type": "PostgresRelation",
|
|
237
|
+
"required": true,
|
|
238
|
+
"description": "The table or view the materialized view reads, as the entity."
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"name": "select",
|
|
242
|
+
"type": "string",
|
|
243
|
+
"required": true,
|
|
244
|
+
"description": "The select list, each computed item aliased: `region, count(*) AS orders, sum(total) AS revenue`."
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"name": "groupBy",
|
|
248
|
+
"type": "string",
|
|
249
|
+
"required": true,
|
|
250
|
+
"description": "The grouping key: `region`."
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
"name": "uniqueOn",
|
|
254
|
+
"type": "string",
|
|
255
|
+
"required": false,
|
|
256
|
+
"description": "The columns of the unique index, which must identify one row of the result (default `groupBy`)."
|
|
257
|
+
}
|
|
258
|
+
]
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
"name": "ReplacingTable",
|
|
262
|
+
"lexicon": "sql",
|
|
263
|
+
"description": "A ReplacingMergeTree table that keeps the highest version of each row, with its version column.",
|
|
264
|
+
"bundles": [
|
|
265
|
+
"ClickHouseTable"
|
|
266
|
+
],
|
|
267
|
+
"params": [
|
|
268
|
+
{
|
|
269
|
+
"name": "name",
|
|
270
|
+
"type": "string",
|
|
271
|
+
"required": true,
|
|
272
|
+
"description": "The table's name, `name` or `database.name`."
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"name": "columns",
|
|
276
|
+
"type": "string",
|
|
277
|
+
"required": true,
|
|
278
|
+
"description": "Every column except the version column, as SQL: `id UInt64, email String`."
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"name": "orderBy",
|
|
282
|
+
"type": "string",
|
|
283
|
+
"required": true,
|
|
284
|
+
"description": "The sort key, which is also the key rows are deduplicated by: `id` or `(tenant_id, id)`."
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"name": "version",
|
|
288
|
+
"type": "string",
|
|
289
|
+
"required": false,
|
|
290
|
+
"description": "The version column (default `version`)."
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"name": "versionType",
|
|
294
|
+
"type": "string",
|
|
295
|
+
"required": false,
|
|
296
|
+
"description": "The version column's type (default `UInt64`): a UInt, Date, DateTime or DateTime64."
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
"name": "partitionBy",
|
|
300
|
+
"type": "string",
|
|
301
|
+
"required": false,
|
|
302
|
+
"description": "A `PARTITION BY` expression."
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
"name": "RollupView",
|
|
308
|
+
"lexicon": "sql",
|
|
309
|
+
"description": "A materialized view that rolls a source table up into a target table it declares beside it.",
|
|
310
|
+
"bundles": [
|
|
311
|
+
"ClickHouseTable",
|
|
312
|
+
"ClickHouseView"
|
|
313
|
+
],
|
|
314
|
+
"params": [
|
|
315
|
+
{
|
|
316
|
+
"name": "name",
|
|
317
|
+
"type": "string",
|
|
318
|
+
"required": true,
|
|
319
|
+
"description": "The target table's name."
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"name": "source",
|
|
323
|
+
"type": "ClickHouseRelation",
|
|
324
|
+
"required": true,
|
|
325
|
+
"description": "The table or view the rollup reads, as the entity: `events`."
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
"name": "columns",
|
|
329
|
+
"type": "string",
|
|
330
|
+
"required": true,
|
|
331
|
+
"description": "The target's columns, as SQL: `day Date, kind LowCardinality(String), n UInt64`."
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
"name": "select",
|
|
335
|
+
"type": "string",
|
|
336
|
+
"required": true,
|
|
337
|
+
"description": "The select list, each item aliased to a target column: `toDate(ts) AS day, kind, count() AS n`."
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
"name": "groupBy",
|
|
341
|
+
"type": "string",
|
|
342
|
+
"required": true,
|
|
343
|
+
"description": "The grouping key: `day, kind`."
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
"name": "orderBy",
|
|
347
|
+
"type": "string",
|
|
348
|
+
"required": false,
|
|
349
|
+
"description": "The target's sort key (default `groupBy` in parentheses)."
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"name": "engine",
|
|
353
|
+
"type": "string",
|
|
354
|
+
"required": false,
|
|
355
|
+
"description": "The target's engine (default `SummingMergeTree`)."
|
|
356
|
+
},
|
|
357
|
+
{
|
|
358
|
+
"name": "partitionBy",
|
|
359
|
+
"type": "string",
|
|
360
|
+
"required": false,
|
|
361
|
+
"description": "The target's partition key."
|
|
362
|
+
}
|
|
363
|
+
]
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
"name": "ShardedTable",
|
|
367
|
+
"lexicon": "sql",
|
|
368
|
+
"description": "A ReplicatedMergeTree table on every node of a cluster and the Distributed table over it.",
|
|
369
|
+
"bundles": [
|
|
370
|
+
"ClickHouseTable"
|
|
371
|
+
],
|
|
372
|
+
"params": [
|
|
373
|
+
{
|
|
374
|
+
"name": "name",
|
|
375
|
+
"type": "string",
|
|
376
|
+
"required": true,
|
|
377
|
+
"description": "The Distributed table's name, unqualified."
|
|
378
|
+
},
|
|
379
|
+
{
|
|
380
|
+
"name": "cluster",
|
|
381
|
+
"type": "string",
|
|
382
|
+
"required": true,
|
|
383
|
+
"description": "The cluster both tables are created on, as the server's `remote_servers` names it."
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"name": "columns",
|
|
387
|
+
"type": "string",
|
|
388
|
+
"required": true,
|
|
389
|
+
"description": "The columns, as SQL."
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
"name": "orderBy",
|
|
393
|
+
"type": "string",
|
|
394
|
+
"required": true,
|
|
395
|
+
"description": "The local table's sort key."
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
"name": "shardingKey",
|
|
399
|
+
"type": "string",
|
|
400
|
+
"required": false,
|
|
401
|
+
"description": "The expression that picks a shard for an inserted row (default `rand()`)."
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
"name": "partitionBy",
|
|
405
|
+
"type": "string",
|
|
406
|
+
"required": false,
|
|
407
|
+
"description": "The local table's partition key."
|
|
408
|
+
}
|
|
409
|
+
]
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"name": "SoftDeleteTable",
|
|
413
|
+
"lexicon": "sql",
|
|
414
|
+
"description": "A table with created and updated timestamps and a soft-delete column, a view of its live rows and an index over them.",
|
|
415
|
+
"bundles": [
|
|
416
|
+
"PostgresIndex",
|
|
417
|
+
"PostgresTable",
|
|
418
|
+
"PostgresView"
|
|
419
|
+
],
|
|
420
|
+
"params": [
|
|
421
|
+
{
|
|
422
|
+
"name": "name",
|
|
423
|
+
"type": "string",
|
|
424
|
+
"required": true,
|
|
425
|
+
"description": "The table's name, unqualified."
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"name": "schema",
|
|
429
|
+
"type": "PostgresSchema | string",
|
|
430
|
+
"required": false,
|
|
431
|
+
"description": "The schema the table, its index and its view live in: the entity, or its name (default `public`)."
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
"name": "columns",
|
|
435
|
+
"type": "string",
|
|
436
|
+
"required": true,
|
|
437
|
+
"description": "Every column except the three the composite adds, as SQL, with the primary key: `id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, title text NOT NULL`."
|
|
438
|
+
},
|
|
439
|
+
{
|
|
440
|
+
"name": "liveKey",
|
|
441
|
+
"type": "string",
|
|
442
|
+
"required": false,
|
|
443
|
+
"description": "The column the live-rows index covers: the one the app looks rows up by, as SQL (default `id`)."
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
"name": "comment",
|
|
447
|
+
"type": "string",
|
|
448
|
+
"required": false,
|
|
449
|
+
"description": "The table's comment, which also covers its columns for SQLPG112 (default: says rows are soft-deleted)."
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"name": "createdAt",
|
|
453
|
+
"type": "string",
|
|
454
|
+
"required": false,
|
|
455
|
+
"description": "The creation timestamp column (default `created_at`)."
|
|
456
|
+
},
|
|
457
|
+
{
|
|
458
|
+
"name": "updatedAt",
|
|
459
|
+
"type": "string",
|
|
460
|
+
"required": false,
|
|
461
|
+
"description": "The update timestamp column (default `updated_at`)."
|
|
462
|
+
},
|
|
463
|
+
{
|
|
464
|
+
"name": "deletedAt",
|
|
465
|
+
"type": "string",
|
|
466
|
+
"required": false,
|
|
467
|
+
"description": "The deletion timestamp column (default `deleted_at`)."
|
|
468
|
+
}
|
|
469
|
+
]
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
"name": "TenantTable",
|
|
473
|
+
"lexicon": "sql",
|
|
474
|
+
"description": "A multi-tenant table with the tenant key first in its primary key and its index.",
|
|
475
|
+
"bundles": [
|
|
476
|
+
"PostgresIndex",
|
|
477
|
+
"PostgresTable"
|
|
478
|
+
],
|
|
479
|
+
"params": [
|
|
480
|
+
{
|
|
481
|
+
"name": "name",
|
|
482
|
+
"type": "string",
|
|
483
|
+
"required": true,
|
|
484
|
+
"description": "The table's name, unqualified."
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
"name": "schema",
|
|
488
|
+
"type": "PostgresSchema | string",
|
|
489
|
+
"required": false,
|
|
490
|
+
"description": "The schema the table lives in: the entity, or its name (default `public`)."
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
"name": "columns",
|
|
494
|
+
"type": "string",
|
|
495
|
+
"required": true,
|
|
496
|
+
"description": "Every column except the tenant's, as SQL: `id bigint GENERATED ALWAYS AS IDENTITY, title text NOT NULL`."
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
"name": "primaryKey",
|
|
500
|
+
"type": "string",
|
|
501
|
+
"required": true,
|
|
502
|
+
"description": "The columns that, after the tenant, make a row unique: `id`."
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
"name": "indexOn",
|
|
506
|
+
"type": "string",
|
|
507
|
+
"required": true,
|
|
508
|
+
"description": "The columns the secondary index covers after the tenant: `created_at DESC`."
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
"name": "tenant",
|
|
512
|
+
"type": "string",
|
|
513
|
+
"required": false,
|
|
514
|
+
"description": "The tenant column (default `tenant_id`)."
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
"name": "tenantType",
|
|
518
|
+
"type": "string",
|
|
519
|
+
"required": false,
|
|
520
|
+
"description": "The tenant column's type (default `uuid`)."
|
|
521
|
+
}
|
|
522
|
+
]
|
|
523
|
+
}
|
|
524
|
+
];
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `CdcMirror`: a ReplacingMergeTree mirror of a source database table fed by change data capture, with a view of its live rows.
|
|
3
|
+
*
|
|
4
|
+
* A CDC pipeline (ClickPipes, Debezium through Kafka, PeerDB) writes every
|
|
5
|
+
* change to a source row as a new row here, with an increasing version and a
|
|
6
|
+
* deleted flag. ReplacingMergeTree with both arguments keeps the latest
|
|
7
|
+
* version per primary key and, on merge, drops rows whose latest version is a
|
|
8
|
+
* delete. The `current` view reads the table with `FINAL` and without deleted
|
|
9
|
+
* rows, which is what a query of the source table would have returned.
|
|
10
|
+
*/
|
|
11
|
+
import { Composite } from "@intentius/chant/composite";
|
|
12
|
+
import { table, view } from "../clickhouse/entities.js";
|
|
13
|
+
/** A ReplacingMergeTree mirror of a CDC-fed source table, with a view of the rows not deleted. */
|
|
14
|
+
export const CdcMirror = Composite((props) => {
|
|
15
|
+
const version = props.version ?? "_version";
|
|
16
|
+
const deleted = props.deleted ?? "_is_deleted";
|
|
17
|
+
const mirror = table `
|
|
18
|
+
CREATE TABLE ${props.name} (
|
|
19
|
+
${props.columns},
|
|
20
|
+
${version} UInt64,
|
|
21
|
+
${deleted} UInt8
|
|
22
|
+
)
|
|
23
|
+
ENGINE = ReplacingMergeTree(${version}, ${deleted})
|
|
24
|
+
${props.partitionBy ? `PARTITION BY ${props.partitionBy}` : ""}
|
|
25
|
+
ORDER BY ${props.primaryKey}`;
|
|
26
|
+
const current = view `
|
|
27
|
+
CREATE VIEW ${`${props.name}_current`} AS
|
|
28
|
+
SELECT * EXCEPT (${version}, ${deleted})
|
|
29
|
+
FROM ${mirror} FINAL
|
|
30
|
+
WHERE ${deleted} = 0`;
|
|
31
|
+
return { table: mirror, current };
|
|
32
|
+
}, "CdcMirror");
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** The ClickHouse composites, exported at `@intentius/chant-lexicon-sql/clickhouse`. */
|
|
2
|
+
export { ReplacingTable } from "./replacing-table.js";
|
|
3
|
+
export { EventsTable } from "./events-table.js";
|
|
4
|
+
export { RollupView } from "./rollup-view.js";
|
|
5
|
+
export { CdcMirror } from "./cdc-mirror.js";
|
|
6
|
+
export { ShardedTable } from "./sharded-table.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `EventsTable`: an append-only MergeTree events table, partitioned by month and expired by TTL.
|
|
3
|
+
*
|
|
4
|
+
* The table is partitioned by its timestamp (by month unless `partitionBy`
|
|
5
|
+
* says otherwise) and drops rows older than `ttlDays`. It sets
|
|
6
|
+
* `ttl_only_drop_parts`, so expiry drops whole parts once every row in them
|
|
7
|
+
* has expired instead of rewriting parts to remove single rows, which is cheap
|
|
8
|
+
* when the partition and the TTL follow the same column.
|
|
9
|
+
*/
|
|
10
|
+
import { Composite } from "@intentius/chant/composite";
|
|
11
|
+
import { table } from "../clickhouse/entities.js";
|
|
12
|
+
/** An append-only MergeTree events table, partitioned by its timestamp and expired by TTL. */
|
|
13
|
+
export const EventsTable = Composite((props) => {
|
|
14
|
+
const ts = props.timestamp ?? "ts";
|
|
15
|
+
const events = table `
|
|
16
|
+
CREATE TABLE ${props.name} (
|
|
17
|
+
${props.columns},
|
|
18
|
+
${ts} ${props.timestampType ?? "DateTime"}
|
|
19
|
+
)
|
|
20
|
+
ENGINE = MergeTree
|
|
21
|
+
PARTITION BY ${props.partitionBy ?? `toYYYYMM(${ts})`}
|
|
22
|
+
ORDER BY ${props.orderBy}
|
|
23
|
+
TTL ${ts} + INTERVAL ${props.ttlDays ?? 90} DAY
|
|
24
|
+
SETTINGS ttl_only_drop_parts = 1`;
|
|
25
|
+
return { table: events };
|
|
26
|
+
}, "EventsTable");
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sql lexicon's composites: tables and views that are usually declared
|
|
3
|
+
* together, built from each dialect's `table`, `index` and `view` tags so every
|
|
4
|
+
* field keeps its provenance. `./clickhouse` and `./postgres` are what the two
|
|
5
|
+
* dialect subpaths export.
|
|
6
|
+
*/
|
|
7
|
+
export * from "./clickhouse.js";
|
|
8
|
+
export * from "./postgres.js";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `JoinTable`: the table of a many-to-many relation, with both foreign keys indexed.
|
|
3
|
+
*
|
|
4
|
+
* The primary key is `(<leftColumn>, <rightColumn>)`, which also serves
|
|
5
|
+
* lookups from the left side. The reverse index on `(<rightColumn>,
|
|
6
|
+
* <leftColumn>)` serves lookups from the right and keeps deletes of a
|
|
7
|
+
* referenced row off a table scan (SQLPG102). Each foreign key cascades by
|
|
8
|
+
* default, so deleting a row on either side removes its links.
|
|
9
|
+
*/
|
|
10
|
+
import { Composite } from "@intentius/chant/composite";
|
|
11
|
+
import { index, table } from "../postgres/entities.js";
|
|
12
|
+
/** The table of a many-to-many relation: two foreign keys, a composite primary key and the reverse index. */
|
|
13
|
+
export const JoinTable = Composite((props) => {
|
|
14
|
+
const schema = props.schema ?? "public";
|
|
15
|
+
const links = table `
|
|
16
|
+
CREATE TABLE ${schema}.${props.name} (
|
|
17
|
+
${props.leftColumn} ${props.leftType ?? "bigint"} NOT NULL REFERENCES ${props.left} (${props.leftKey ?? "id"}) ON DELETE ${props.onDelete ?? "CASCADE"},
|
|
18
|
+
${props.rightColumn} ${props.rightType ?? "bigint"} NOT NULL REFERENCES ${props.right} (${props.rightKey ?? "id"}) ON DELETE ${props.onDelete ?? "CASCADE"},
|
|
19
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20
|
+
PRIMARY KEY (${props.leftColumn}, ${props.rightColumn})
|
|
21
|
+
)`;
|
|
22
|
+
const reverse = index `
|
|
23
|
+
CREATE INDEX ${`${props.name}_reverse_idx`} ON ${links} (${props.rightColumn}, ${props.leftColumn})`;
|
|
24
|
+
return { table: links, reverseIndex: reverse };
|
|
25
|
+
}, "JoinTable");
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** The Postgres composites, exported at `@intentius/chant-lexicon-sql/postgres`. */
|
|
2
|
+
export { SoftDeleteTable } from "./soft-delete-table.js";
|
|
3
|
+
export { AuditLogTable } from "./audit-log-table.js";
|
|
4
|
+
export { JoinTable } from "./join-table.js";
|
|
5
|
+
export { TenantTable } from "./tenant-table.js";
|
|
6
|
+
export { RefreshedView } from "./refreshed-view.js";
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `RefreshedView`: a materialized view with the unique index that lets it refresh concurrently.
|
|
3
|
+
*
|
|
4
|
+
* `REFRESH MATERIALIZED VIEW CONCURRENTLY` needs at least one unique index
|
|
5
|
+
* over plain columns, and without it every refresh takes an ACCESS EXCLUSIVE
|
|
6
|
+
* lock that blocks readers (SQLPG111). The composite declares the view and
|
|
7
|
+
* that index together, so a view cannot be added without one. The view reads
|
|
8
|
+
* `source` by reference, so the build orders them and the view's lineage
|
|
9
|
+
* names the source's columns.
|
|
10
|
+
*/
|
|
11
|
+
import { Composite } from "@intentius/chant/composite";
|
|
12
|
+
import { index, view } from "../postgres/entities.js";
|
|
13
|
+
/** A materialized view over a source, with the unique index that allows REFRESH ... CONCURRENTLY. */
|
|
14
|
+
export const RefreshedView = Composite((props) => {
|
|
15
|
+
const schema = props.schema ?? "public";
|
|
16
|
+
const summary = view `
|
|
17
|
+
CREATE MATERIALIZED VIEW ${schema}.${props.name} AS
|
|
18
|
+
SELECT ${props.select}
|
|
19
|
+
FROM ${props.source}
|
|
20
|
+
GROUP BY ${props.groupBy}`;
|
|
21
|
+
const key = index `
|
|
22
|
+
CREATE UNIQUE INDEX ${`${props.name}_key`} ON ${summary} (${props.uniqueOn ?? props.groupBy})`;
|
|
23
|
+
return { view: summary, uniqueIndex: key };
|
|
24
|
+
}, "RefreshedView");
|