@intentius/chant-lexicon-sql 0.0.0-stage → 0.112.1
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 +39 -2
- package/dist/clickhouse/apply/apply.d.ts +82 -0
- package/dist/clickhouse/apply/apply.d.ts.map +1 -0
- package/dist/clickhouse/apply/mutations.d.ts +46 -0
- package/dist/clickhouse/apply/mutations.d.ts.map +1 -0
- package/dist/clickhouse/apply/statements.d.ts +99 -0
- package/dist/clickhouse/apply/statements.d.ts.map +1 -0
- package/dist/clickhouse/catalog-types.d.ts +76 -0
- package/dist/clickhouse/catalog-types.d.ts.map +1 -0
- package/dist/clickhouse/container.d.ts +63 -0
- package/dist/clickhouse/container.d.ts.map +1 -0
- package/dist/clickhouse/engine-syntax.d.ts +43 -0
- package/dist/clickhouse/engine-syntax.d.ts.map +1 -0
- package/dist/clickhouse/entities.d.ts +183 -0
- package/dist/clickhouse/entities.d.ts.map +1 -0
- package/dist/clickhouse/http.d.ts +40 -0
- package/dist/clickhouse/http.d.ts.map +1 -0
- package/dist/clickhouse/import/generator.d.ts +16 -0
- package/dist/clickhouse/import/generator.d.ts.map +1 -0
- package/dist/clickhouse/import/ir.d.ts +52 -0
- package/dist/clickhouse/import/ir.d.ts.map +1 -0
- package/dist/clickhouse/import/live-export.d.ts +28 -0
- package/dist/clickhouse/import/live-export.d.ts.map +1 -0
- package/dist/clickhouse/import/parser.d.ts +10 -0
- package/dist/clickhouse/import/parser.d.ts.map +1 -0
- package/dist/clickhouse/live/bind.d.ts +56 -0
- package/dist/clickhouse/live/bind.d.ts.map +1 -0
- package/dist/clickhouse/live/catalog.d.ts +39 -0
- package/dist/clickhouse/live/catalog.d.ts.map +1 -0
- package/dist/clickhouse/live/describe-resources.d.ts +34 -0
- package/dist/clickhouse/live/describe-resources.d.ts.map +1 -0
- package/dist/clickhouse/overlays/codecs.d.ts +28 -0
- package/dist/clickhouse/overlays/codecs.d.ts.map +1 -0
- package/dist/clickhouse/overlays/engines.d.ts +20 -0
- package/dist/clickhouse/overlays/engines.d.ts.map +1 -0
- package/dist/clickhouse/overlays/kinds.d.ts +38 -0
- package/dist/clickhouse/overlays/kinds.d.ts.map +1 -0
- package/dist/clickhouse/overlays/projections.d.ts +27 -0
- package/dist/clickhouse/overlays/projections.d.ts.map +1 -0
- package/dist/clickhouse/overlays/skip-indexes.d.ts +10 -0
- package/dist/clickhouse/overlays/skip-indexes.d.ts.map +1 -0
- package/dist/clickhouse/overlays/ttl.d.ts +35 -0
- package/dist/clickhouse/overlays/ttl.d.ts.map +1 -0
- package/dist/clickhouse/overlays/types.d.ts +21 -0
- package/dist/clickhouse/overlays/types.d.ts.map +1 -0
- package/dist/clickhouse/ownership.d.ts +71 -0
- package/dist/clickhouse/ownership.d.ts.map +1 -0
- package/dist/clickhouse/parser.d.ts +130 -0
- package/dist/clickhouse/parser.d.ts.map +1 -0
- package/dist/clickhouse/plan/commands.d.ts +26 -0
- package/dist/clickhouse/plan/commands.d.ts.map +1 -0
- package/dist/clickhouse/plan/deep.d.ts +32 -0
- package/dist/clickhouse/plan/deep.d.ts.map +1 -0
- package/dist/clickhouse/plan/diff.d.ts +37 -0
- package/dist/clickhouse/plan/diff.d.ts.map +1 -0
- package/dist/clickhouse/plan/disruption.d.ts +17 -0
- package/dist/clickhouse/plan/disruption.d.ts.map +1 -0
- package/dist/clickhouse/plan/normalize.d.ts +97 -0
- package/dist/clickhouse/plan/normalize.d.ts.map +1 -0
- package/dist/clickhouse/plan/rebuild-handoff.d.ts +38 -0
- package/dist/clickhouse/plan/rebuild-handoff.d.ts.map +1 -0
- package/dist/clickhouse/plan/report.d.ts +6 -0
- package/dist/clickhouse/plan/report.d.ts.map +1 -0
- package/dist/clickhouse/plan/rules.d.ts +60 -0
- package/dist/clickhouse/plan/rules.d.ts.map +1 -0
- package/dist/clickhouse/plan/schema.d.ts +23 -0
- package/dist/clickhouse/plan/schema.d.ts.map +1 -0
- package/dist/clickhouse/plan/server-format.d.ts +12 -0
- package/dist/clickhouse/plan/server-format.d.ts.map +1 -0
- package/dist/clickhouse/rebuild/backfill.d.ts +70 -0
- package/dist/clickhouse/rebuild/backfill.d.ts.map +1 -0
- package/dist/clickhouse/rebuild/observe.d.ts +157 -0
- package/dist/clickhouse/rebuild/observe.d.ts.map +1 -0
- package/dist/clickhouse/rebuild/op.d.ts +108 -0
- package/dist/clickhouse/rebuild/op.d.ts.map +1 -0
- package/dist/clickhouse/rebuild/partitions.d.ts +24 -0
- package/dist/clickhouse/rebuild/partitions.d.ts.map +1 -0
- package/dist/clickhouse/rebuild/receipts.d.ts +76 -0
- package/dist/clickhouse/rebuild/receipts.d.ts.map +1 -0
- package/dist/clickhouse/rebuild/replicas.d.ts +78 -0
- package/dist/clickhouse/rebuild/replicas.d.ts.map +1 -0
- package/dist/clickhouse/rebuild/steps.d.ts +151 -0
- package/dist/clickhouse/rebuild/steps.d.ts.map +1 -0
- package/dist/clickhouse/rebuild/verify.d.ts +51 -0
- package/dist/clickhouse/rebuild/verify.d.ts.map +1 -0
- package/dist/clickhouse/testing/fake-server.d.ts +27 -0
- package/dist/clickhouse/testing/fake-server.d.ts.map +1 -0
- package/dist/clickhouse/testing/roundtrip-schema.d.ts +3 -0
- package/dist/clickhouse/testing/roundtrip-schema.d.ts.map +1 -0
- package/dist/clickhouse/testing/writable-server.d.ts +35 -0
- package/dist/clickhouse/testing/writable-server.d.ts.map +1 -0
- package/dist/clickhouse/tokens.d.ts +15 -0
- package/dist/clickhouse/tokens.d.ts.map +1 -0
- package/dist/clickhouse.d.ts +24 -0
- package/dist/clickhouse.d.ts.map +1 -0
- package/dist/codegen/classifier-page.d.ts +6 -0
- package/dist/codegen/classifier-page.d.ts.map +1 -0
- package/dist/codegen/clickhouse-module.d.ts +23 -0
- package/dist/codegen/clickhouse-module.d.ts.map +1 -0
- package/dist/codegen/docs-cli.d.ts +3 -0
- package/dist/codegen/docs-cli.d.ts.map +1 -0
- package/dist/codegen/docs.d.ts +8 -0
- package/dist/codegen/docs.d.ts.map +1 -0
- package/dist/codegen/generate-cli.d.ts +3 -0
- package/dist/codegen/generate-cli.d.ts.map +1 -0
- package/dist/codegen/generate.d.ts +40 -0
- package/dist/codegen/generate.d.ts.map +1 -0
- package/dist/codegen/package.d.ts +7 -0
- package/dist/codegen/package.d.ts.map +1 -0
- package/dist/codegen/postgres-classifier-page.d.ts +7 -0
- package/dist/codegen/postgres-classifier-page.d.ts.map +1 -0
- package/dist/codegen/postgres-module.d.ts +30 -0
- package/dist/codegen/postgres-module.d.ts.map +1 -0
- package/dist/codegen/registry.d.ts +12 -0
- package/dist/codegen/registry.d.ts.map +1 -0
- package/dist/composites/audit-log-table.d.ts +31 -0
- package/dist/composites/audit-log-table.d.ts.map +1 -0
- package/dist/composites/catalog.d.ts +3 -0
- package/dist/composites/catalog.d.ts.map +1 -0
- package/dist/composites/cdc-mirror.d.ts +32 -0
- package/dist/composites/cdc-mirror.d.ts.map +1 -0
- package/dist/composites/clickhouse.d.ts +7 -0
- package/dist/composites/clickhouse.d.ts.map +1 -0
- package/dist/composites/events-table.d.ts +32 -0
- package/dist/composites/events-table.d.ts.map +1 -0
- package/dist/composites/index.d.ts +9 -0
- package/dist/composites/index.d.ts.map +1 -0
- package/dist/composites/join-table.d.ts +41 -0
- package/dist/composites/join-table.d.ts.map +1 -0
- package/dist/composites/postgres.d.ts +7 -0
- package/dist/composites/postgres.d.ts.map +1 -0
- package/dist/composites/refreshed-view.d.ts +32 -0
- package/dist/composites/refreshed-view.d.ts.map +1 -0
- package/dist/composites/replacing-table.d.ts +34 -0
- package/dist/composites/replacing-table.d.ts.map +1 -0
- package/dist/composites/rollup-view.d.ts +39 -0
- package/dist/composites/rollup-view.d.ts.map +1 -0
- package/dist/composites/sharded-table.d.ts +35 -0
- package/dist/composites/sharded-table.d.ts.map +1 -0
- package/dist/composites/soft-delete-table.d.ts +40 -0
- package/dist/composites/soft-delete-table.d.ts.map +1 -0
- package/dist/composites/tenant-table.d.ts +34 -0
- package/dist/composites/tenant-table.d.ts.map +1 -0
- package/dist/config.d.ts +213 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/core/apply.d.ts +89 -0
- package/dist/core/apply.d.ts.map +1 -0
- package/dist/core/classifier.d.ts +88 -0
- package/dist/core/classifier.d.ts.map +1 -0
- package/dist/core/container.d.ts +45 -0
- package/dist/core/container.d.ts.map +1 -0
- package/dist/core/cursor.d.ts +67 -0
- package/dist/core/cursor.d.ts.map +1 -0
- package/dist/core/diff.d.ts +49 -0
- package/dist/core/diff.d.ts.map +1 -0
- package/dist/core/entity.d.ts +41 -0
- package/dist/core/entity.d.ts.map +1 -0
- package/dist/core/find-templates.d.ts +69 -0
- package/dist/core/find-templates.d.ts.map +1 -0
- package/dist/core/handoff.d.ts +36 -0
- package/dist/core/handoff.d.ts.map +1 -0
- package/dist/core/index.d.ts +61 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/interpolation.d.ts +88 -0
- package/dist/core/interpolation.d.ts.map +1 -0
- package/dist/core/normalize.d.ts +18 -0
- package/dist/core/normalize.d.ts.map +1 -0
- package/dist/core/ownership.d.ts +60 -0
- package/dist/core/ownership.d.ts.map +1 -0
- package/dist/core/receipts.d.ts +28 -0
- package/dist/core/receipts.d.ts.map +1 -0
- package/dist/core/references.d.ts +37 -0
- package/dist/core/references.d.ts.map +1 -0
- package/dist/core/template.d.ts +41 -0
- package/dist/core/template.d.ts.map +1 -0
- package/dist/core/testing/http-stub.d.ts +17 -0
- package/dist/core/testing/http-stub.d.ts.map +1 -0
- package/dist/core/tokens.d.ts +102 -0
- package/dist/core/tokens.d.ts.map +1 -0
- package/dist/coverage.d.ts +25 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/detect.d.ts +15 -0
- package/dist/detect.d.ts.map +1 -0
- package/dist/dialects.d.ts +20 -0
- package/dist/dialects.d.ts.map +1 -0
- package/dist/generated/clickhouse-types.d.ts +4380 -0
- package/dist/generated/clickhouse-types.d.ts.map +1 -0
- package/dist/generated/clickhouse.d.ts +11 -0
- package/dist/generated/clickhouse.d.ts.map +1 -0
- package/dist/generated/postgres-types.d.ts +1579 -0
- package/dist/generated/postgres-types.d.ts.map +1 -0
- package/dist/generated/postgres.d.ts +9 -0
- package/dist/generated/postgres.d.ts.map +1 -0
- package/dist/import-generator.d.ts +8 -0
- package/dist/import-generator.d.ts.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/init-templates.d.ts +20 -0
- package/dist/init-templates.d.ts.map +1 -0
- package/dist/integrity.json +61 -0
- package/dist/lint/audit-catalog.d.ts +10 -0
- package/dist/lint/audit-catalog.d.ts.map +1 -0
- package/dist/lint/audit-lineage.d.ts +25 -0
- package/dist/lint/audit-lineage.d.ts.map +1 -0
- package/dist/lint/post-synth/audit-entries.d.ts +8 -0
- package/dist/lint/post-synth/audit-entries.d.ts.map +1 -0
- package/dist/lint/post-synth/clickhouse-helpers.d.ts +85 -0
- package/dist/lint/post-synth/clickhouse-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/index.d.ts +3 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -0
- package/dist/lint/post-synth/postgres-audit-entries.d.ts +9 -0
- package/dist/lint/post-synth/postgres-audit-entries.d.ts.map +1 -0
- package/dist/lint/post-synth/postgres-helpers.d.ts +89 -0
- package/dist/lint/post-synth/postgres-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/sql-helpers.d.ts +27 -0
- package/dist/lint/post-synth/sql-helpers.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch101.d.ts +12 -0
- package/dist/lint/post-synth/sqlch101.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch102.d.ts +9 -0
- package/dist/lint/post-synth/sqlch102.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch103.d.ts +10 -0
- package/dist/lint/post-synth/sqlch103.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch104.d.ts +9 -0
- package/dist/lint/post-synth/sqlch104.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch105.d.ts +10 -0
- package/dist/lint/post-synth/sqlch105.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch106.d.ts +11 -0
- package/dist/lint/post-synth/sqlch106.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch107.d.ts +10 -0
- package/dist/lint/post-synth/sqlch107.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch108.d.ts +11 -0
- package/dist/lint/post-synth/sqlch108.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch109.d.ts +10 -0
- package/dist/lint/post-synth/sqlch109.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch110.d.ts +12 -0
- package/dist/lint/post-synth/sqlch110.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch111.d.ts +11 -0
- package/dist/lint/post-synth/sqlch111.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch112.d.ts +12 -0
- package/dist/lint/post-synth/sqlch112.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch113.d.ts +9 -0
- package/dist/lint/post-synth/sqlch113.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch114.d.ts +8 -0
- package/dist/lint/post-synth/sqlch114.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch115.d.ts +13 -0
- package/dist/lint/post-synth/sqlch115.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch116.d.ts +10 -0
- package/dist/lint/post-synth/sqlch116.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch117.d.ts +9 -0
- package/dist/lint/post-synth/sqlch117.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch118.d.ts +10 -0
- package/dist/lint/post-synth/sqlch118.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch119.d.ts +11 -0
- package/dist/lint/post-synth/sqlch119.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch120.d.ts +10 -0
- package/dist/lint/post-synth/sqlch120.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg101.d.ts +12 -0
- package/dist/lint/post-synth/sqlpg101.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg102.d.ts +11 -0
- package/dist/lint/post-synth/sqlpg102.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg103.d.ts +11 -0
- package/dist/lint/post-synth/sqlpg103.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg104.d.ts +10 -0
- package/dist/lint/post-synth/sqlpg104.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg105.d.ts +10 -0
- package/dist/lint/post-synth/sqlpg105.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg106.d.ts +9 -0
- package/dist/lint/post-synth/sqlpg106.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg107.d.ts +10 -0
- package/dist/lint/post-synth/sqlpg107.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg108.d.ts +11 -0
- package/dist/lint/post-synth/sqlpg108.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg109.d.ts +11 -0
- package/dist/lint/post-synth/sqlpg109.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg110.d.ts +12 -0
- package/dist/lint/post-synth/sqlpg110.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg111.d.ts +10 -0
- package/dist/lint/post-synth/sqlpg111.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg112.d.ts +10 -0
- package/dist/lint/post-synth/sqlpg112.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg113.d.ts +11 -0
- package/dist/lint/post-synth/sqlpg113.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg114.d.ts +13 -0
- package/dist/lint/post-synth/sqlpg114.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg115.d.ts +13 -0
- package/dist/lint/post-synth/sqlpg115.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg116.d.ts +11 -0
- package/dist/lint/post-synth/sqlpg116.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg117.d.ts +12 -0
- package/dist/lint/post-synth/sqlpg117.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlpg118.d.ts +12 -0
- package/dist/lint/post-synth/sqlpg118.d.ts.map +1 -0
- package/dist/lint/rules/index.d.ts +12 -0
- package/dist/lint/rules/index.d.ts.map +1 -0
- package/dist/lint/rules/postgres-templates.d.ts +18 -0
- package/dist/lint/rules/postgres-templates.d.ts.map +1 -0
- package/dist/lint/rules/sqlch001.d.ts +12 -0
- package/dist/lint/rules/sqlch001.d.ts.map +1 -0
- package/dist/lint/rules/sqlch002.d.ts +11 -0
- package/dist/lint/rules/sqlch002.d.ts.map +1 -0
- package/dist/lint/rules/sqlch003.d.ts +12 -0
- package/dist/lint/rules/sqlch003.d.ts.map +1 -0
- package/dist/lint/rules/sqlpg001.d.ts +16 -0
- package/dist/lint/rules/sqlpg001.d.ts.map +1 -0
- package/dist/lint/rules/sqlpg002.d.ts +12 -0
- package/dist/lint/rules/sqlpg002.d.ts.map +1 -0
- package/dist/lint/rules/sqlpg003.d.ts +16 -0
- package/dist/lint/rules/sqlpg003.d.ts.map +1 -0
- package/dist/lint/rules/sqlpg004.d.ts +21 -0
- package/dist/lint/rules/sqlpg004.d.ts.map +1 -0
- package/dist/lint/rules/templates.d.ts +23 -0
- package/dist/lint/rules/templates.d.ts.map +1 -0
- package/dist/live-dialect.d.ts +25 -0
- package/dist/live-dialect.d.ts.map +1 -0
- package/dist/lsp/catalog.d.ts +22 -0
- package/dist/lsp/catalog.d.ts.map +1 -0
- package/dist/lsp/completions.d.ts +13 -0
- package/dist/lsp/completions.d.ts.map +1 -0
- package/dist/lsp/hover.d.ts +12 -0
- package/dist/lsp/hover.d.ts.map +1 -0
- package/dist/lsp/postgres-catalog.d.ts +85 -0
- package/dist/lsp/postgres-catalog.d.ts.map +1 -0
- package/dist/lsp/postgres-template.d.ts +35 -0
- package/dist/lsp/postgres-template.d.ts.map +1 -0
- package/dist/lsp/postgres.d.ts +20 -0
- package/dist/lsp/postgres.d.ts.map +1 -0
- package/dist/lsp/refs.d.ts +8 -0
- package/dist/lsp/refs.d.ts.map +1 -0
- package/dist/lsp/registry.d.ts +4 -0
- package/dist/lsp/registry.d.ts.map +1 -0
- package/dist/lsp/template.d.ts +34 -0
- package/dist/lsp/template.d.ts.map +1 -0
- package/dist/manifest.json +8 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/postgres.d.ts +32 -0
- package/dist/mcp/postgres.d.ts.map +1 -0
- package/dist/meta.json +67 -0
- package/dist/okf/index.md +67 -0
- package/dist/okf/rules/SQLCH001.md +11 -0
- package/dist/okf/rules/SQLCH002.md +11 -0
- package/dist/okf/rules/SQLCH003.md +11 -0
- package/dist/okf/rules/SQLCH101.md +15 -0
- package/dist/okf/rules/SQLCH102.md +11 -0
- package/dist/okf/rules/SQLCH103.md +11 -0
- package/dist/okf/rules/SQLCH104.md +11 -0
- package/dist/okf/rules/SQLCH105.md +11 -0
- package/dist/okf/rules/SQLCH106.md +11 -0
- package/dist/okf/rules/SQLCH107.md +11 -0
- package/dist/okf/rules/SQLCH108.md +15 -0
- package/dist/okf/rules/SQLCH109.md +11 -0
- package/dist/okf/rules/SQLCH110.md +11 -0
- package/dist/okf/rules/SQLCH111.md +11 -0
- package/dist/okf/rules/SQLCH112.md +11 -0
- package/dist/okf/rules/SQLCH113.md +11 -0
- package/dist/okf/rules/SQLCH114.md +11 -0
- package/dist/okf/rules/SQLCH115.md +11 -0
- package/dist/okf/rules/SQLCH116.md +11 -0
- package/dist/okf/rules/SQLCH117.md +15 -0
- package/dist/okf/rules/SQLCH118.md +15 -0
- package/dist/okf/rules/SQLCH119.md +15 -0
- package/dist/okf/rules/SQLCH120.md +15 -0
- package/dist/okf/rules/SQLPG001.md +11 -0
- package/dist/okf/rules/SQLPG002.md +11 -0
- package/dist/okf/rules/SQLPG003.md +11 -0
- package/dist/okf/rules/SQLPG004.md +11 -0
- package/dist/okf/rules/SQLPG101.md +11 -0
- package/dist/okf/rules/SQLPG102.md +11 -0
- package/dist/okf/rules/SQLPG103.md +11 -0
- package/dist/okf/rules/SQLPG104.md +11 -0
- package/dist/okf/rules/SQLPG105.md +11 -0
- package/dist/okf/rules/SQLPG106.md +11 -0
- package/dist/okf/rules/SQLPG107.md +11 -0
- package/dist/okf/rules/SQLPG108.md +11 -0
- package/dist/okf/rules/SQLPG109.md +11 -0
- package/dist/okf/rules/SQLPG110.md +11 -0
- package/dist/okf/rules/SQLPG111.md +11 -0
- package/dist/okf/rules/SQLPG112.md +11 -0
- package/dist/okf/rules/SQLPG113.md +24 -0
- package/dist/okf/rules/SQLPG114.md +11 -0
- package/dist/okf/rules/SQLPG115.md +11 -0
- package/dist/okf/rules/SQLPG116.md +15 -0
- package/dist/okf/rules/SQLPG117.md +11 -0
- package/dist/okf/rules/SQLPG118.md +11 -0
- package/dist/okf/types/Database.md +15 -0
- package/dist/okf/types/MaterializedView.md +14 -0
- package/dist/okf/types/PostgresDomain.md +13 -0
- package/dist/okf/types/PostgresEnum.md +13 -0
- package/dist/okf/types/PostgresExtension.md +13 -0
- package/dist/okf/types/PostgresIndex.md +9 -0
- package/dist/okf/types/PostgresMaterializedView.md +13 -0
- package/dist/okf/types/PostgresSchema.md +13 -0
- package/dist/okf/types/PostgresSequence.md +13 -0
- package/dist/okf/types/PostgresTable.md +13 -0
- package/dist/okf/types/PostgresView.md +13 -0
- package/dist/okf/types/Table.md +15 -0
- package/dist/okf/types/View.md +13 -0
- package/dist/op/activities/clickhouse-apply.d.ts +56 -0
- package/dist/op/activities/clickhouse-apply.d.ts.map +1 -0
- package/dist/op/activities/clickhouse-emulator.d.ts +26 -0
- package/dist/op/activities/clickhouse-emulator.d.ts.map +1 -0
- package/dist/op/activities/clickhouse-rebuild.d.ts +43 -0
- package/dist/op/activities/clickhouse-rebuild.d.ts.map +1 -0
- package/dist/op/activities/index.d.ts +19 -0
- package/dist/op/activities/index.d.ts.map +1 -0
- package/dist/op/activities/postgres-apply.d.ts +69 -0
- package/dist/op/activities/postgres-apply.d.ts.map +1 -0
- package/dist/op/activities/postgres-emulator.d.ts +33 -0
- package/dist/op/activities/postgres-emulator.d.ts.map +1 -0
- package/dist/op/activities/postgres-migration.d.ts +48 -0
- package/dist/op/activities/postgres-migration.d.ts.map +1 -0
- package/dist/op/activity-contracts.d.ts +464 -0
- package/dist/op/activity-contracts.d.ts.map +1 -0
- package/dist/package-cli.d.ts +3 -0
- package/dist/package-cli.d.ts.map +1 -0
- package/dist/plugin.d.ts +12 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/postgres/apply/apply.d.ts +163 -0
- package/dist/postgres/apply/apply.d.ts.map +1 -0
- package/dist/postgres/apply/statements.d.ts +138 -0
- package/dist/postgres/apply/statements.d.ts.map +1 -0
- package/dist/postgres/catalog-types.d.ts +50 -0
- package/dist/postgres/catalog-types.d.ts.map +1 -0
- package/dist/postgres/container.d.ts +23 -0
- package/dist/postgres/container.d.ts.map +1 -0
- package/dist/postgres/entities.d.ts +322 -0
- package/dist/postgres/entities.d.ts.map +1 -0
- package/dist/postgres/entity-types.d.ts +17 -0
- package/dist/postgres/entity-types.d.ts.map +1 -0
- package/dist/postgres/import/generator.d.ts +28 -0
- package/dist/postgres/import/generator.d.ts.map +1 -0
- package/dist/postgres/import/ir.d.ts +24 -0
- package/dist/postgres/import/ir.d.ts.map +1 -0
- package/dist/postgres/import/live-export.d.ts +26 -0
- package/dist/postgres/import/live-export.d.ts.map +1 -0
- package/dist/postgres/keywords.d.ts +22 -0
- package/dist/postgres/keywords.d.ts.map +1 -0
- package/dist/postgres/live/bind.d.ts +76 -0
- package/dist/postgres/live/bind.d.ts.map +1 -0
- package/dist/postgres/live/catalog.d.ts +98 -0
- package/dist/postgres/live/catalog.d.ts.map +1 -0
- package/dist/postgres/live/client.d.ts +32 -0
- package/dist/postgres/live/client.d.ts.map +1 -0
- package/dist/postgres/live/describe-resources.d.ts +41 -0
- package/dist/postgres/live/describe-resources.d.ts.map +1 -0
- package/dist/postgres/migrate/backfill.d.ts +103 -0
- package/dist/postgres/migrate/backfill.d.ts.map +1 -0
- package/dist/postgres/migrate/batches.d.ts +90 -0
- package/dist/postgres/migrate/batches.d.ts.map +1 -0
- package/dist/postgres/migrate/carry.d.ts +196 -0
- package/dist/postgres/migrate/carry.d.ts.map +1 -0
- package/dist/postgres/migrate/handoff.d.ts +46 -0
- package/dist/postgres/migrate/handoff.d.ts.map +1 -0
- package/dist/postgres/migrate/names.d.ts +55 -0
- package/dist/postgres/migrate/names.d.ts.map +1 -0
- package/dist/postgres/migrate/observe.d.ts +139 -0
- package/dist/postgres/migrate/observe.d.ts.map +1 -0
- package/dist/postgres/migrate/op.d.ts +128 -0
- package/dist/postgres/migrate/op.d.ts.map +1 -0
- package/dist/postgres/migrate/receipts.d.ts +63 -0
- package/dist/postgres/migrate/receipts.d.ts.map +1 -0
- package/dist/postgres/migrate/replication.d.ts +80 -0
- package/dist/postgres/migrate/replication.d.ts.map +1 -0
- package/dist/postgres/migrate/steps.d.ts +225 -0
- package/dist/postgres/migrate/steps.d.ts.map +1 -0
- package/dist/postgres/overlays/columns.d.ts +6 -0
- package/dist/postgres/overlays/columns.d.ts.map +1 -0
- package/dist/postgres/overlays/constraints.d.ts +8 -0
- package/dist/postgres/overlays/constraints.d.ts.map +1 -0
- package/dist/postgres/overlays/indexes.d.ts +8 -0
- package/dist/postgres/overlays/indexes.d.ts.map +1 -0
- package/dist/postgres/overlays/kinds.d.ts +48 -0
- package/dist/postgres/overlays/kinds.d.ts.map +1 -0
- package/dist/postgres/overlays/partitioning.d.ts +5 -0
- package/dist/postgres/overlays/partitioning.d.ts.map +1 -0
- package/dist/postgres/overlays/relations.d.ts +6 -0
- package/dist/postgres/overlays/relations.d.ts.map +1 -0
- package/dist/postgres/overlays/storage.d.ts +28 -0
- package/dist/postgres/overlays/storage.d.ts.map +1 -0
- package/dist/postgres/overlays/type-ddl.d.ts +7 -0
- package/dist/postgres/overlays/type-ddl.d.ts.map +1 -0
- package/dist/postgres/overlays/types.d.ts +24 -0
- package/dist/postgres/overlays/types.d.ts.map +1 -0
- package/dist/postgres/parser.d.ts +216 -0
- package/dist/postgres/parser.d.ts.map +1 -0
- package/dist/postgres/plan/commands.d.ts +61 -0
- package/dist/postgres/plan/commands.d.ts.map +1 -0
- package/dist/postgres/plan/deep.d.ts +33 -0
- package/dist/postgres/plan/deep.d.ts.map +1 -0
- package/dist/postgres/plan/diff.d.ts +45 -0
- package/dist/postgres/plan/diff.d.ts.map +1 -0
- package/dist/postgres/plan/disruption.d.ts +14 -0
- package/dist/postgres/plan/disruption.d.ts.map +1 -0
- package/dist/postgres/plan/normalize.d.ts +108 -0
- package/dist/postgres/plan/normalize.d.ts.map +1 -0
- package/dist/postgres/plan/report.d.ts +6 -0
- package/dist/postgres/plan/report.d.ts.map +1 -0
- package/dist/postgres/plan/rules.d.ts +84 -0
- package/dist/postgres/plan/rules.d.ts.map +1 -0
- package/dist/postgres/plan/schema.d.ts +50 -0
- package/dist/postgres/plan/schema.d.ts.map +1 -0
- package/dist/postgres/plan/server-normalize.d.ts +26 -0
- package/dist/postgres/plan/server-normalize.d.ts.map +1 -0
- package/dist/postgres/providers/aurora.d.ts +12 -0
- package/dist/postgres/providers/aurora.d.ts.map +1 -0
- package/dist/postgres/providers/azure.d.ts +14 -0
- package/dist/postgres/providers/azure.d.ts.map +1 -0
- package/dist/postgres/providers/cloud-sql.d.ts +11 -0
- package/dist/postgres/providers/cloud-sql.d.ts.map +1 -0
- package/dist/postgres/providers/index.d.ts +35 -0
- package/dist/postgres/providers/index.d.ts.map +1 -0
- package/dist/postgres/providers/neon.d.ts +13 -0
- package/dist/postgres/providers/neon.d.ts.map +1 -0
- package/dist/postgres/providers/rds.d.ts +10 -0
- package/dist/postgres/providers/rds.d.ts.map +1 -0
- package/dist/postgres/providers/supabase.d.ts +12 -0
- package/dist/postgres/providers/supabase.d.ts.map +1 -0
- package/dist/postgres/providers/types.d.ts +59 -0
- package/dist/postgres/providers/types.d.ts.map +1 -0
- package/dist/postgres/testing/fake-client.d.ts +38 -0
- package/dist/postgres/testing/fake-client.d.ts.map +1 -0
- package/dist/postgres/testing/migration.d.ts +25 -0
- package/dist/postgres/testing/migration.d.ts.map +1 -0
- package/dist/postgres/testing/roundtrip-schema.d.ts +11 -0
- package/dist/postgres/testing/roundtrip-schema.d.ts.map +1 -0
- package/dist/postgres/testing/server.d.ts +17 -0
- package/dist/postgres/testing/server.d.ts.map +1 -0
- package/dist/postgres/testing/writable-server.d.ts +45 -0
- package/dist/postgres/testing/writable-server.d.ts.map +1 -0
- package/dist/postgres/tokens.d.ts +26 -0
- package/dist/postgres/tokens.d.ts.map +1 -0
- package/dist/postgres.d.ts +13 -0
- package/dist/postgres.d.ts.map +1 -0
- package/dist/rules/audit-entries.ts +29 -0
- package/dist/rules/clickhouse-helpers.ts +206 -0
- package/dist/rules/postgres-audit-entries.ts +29 -0
- package/dist/rules/postgres-helpers.ts +126 -0
- package/dist/rules/postgres-templates.ts +36 -0
- package/dist/rules/sql-helpers.ts +53 -0
- package/dist/rules/sqlch001.ts +53 -0
- package/dist/rules/sqlch002.ts +115 -0
- package/dist/rules/sqlch003.ts +68 -0
- package/dist/rules/sqlch101.ts +35 -0
- package/dist/rules/sqlch102.ts +23 -0
- package/dist/rules/sqlch103.ts +45 -0
- package/dist/rules/sqlch104.ts +42 -0
- package/dist/rules/sqlch105.ts +35 -0
- package/dist/rules/sqlch106.ts +27 -0
- package/dist/rules/sqlch107.ts +35 -0
- package/dist/rules/sqlch108.ts +27 -0
- package/dist/rules/sqlch109.ts +21 -0
- package/dist/rules/sqlch110.ts +29 -0
- package/dist/rules/sqlch111.ts +40 -0
- package/dist/rules/sqlch112.ts +30 -0
- package/dist/rules/sqlch113.ts +20 -0
- package/dist/rules/sqlch114.ts +26 -0
- package/dist/rules/sqlch115.ts +31 -0
- package/dist/rules/sqlch116.ts +22 -0
- package/dist/rules/sqlch117.ts +25 -0
- package/dist/rules/sqlch118.ts +26 -0
- package/dist/rules/sqlch119.ts +31 -0
- package/dist/rules/sqlch120.ts +21 -0
- package/dist/rules/sqlpg001.ts +88 -0
- package/dist/rules/sqlpg002.ts +68 -0
- package/dist/rules/sqlpg003.ts +59 -0
- package/dist/rules/sqlpg004.ts +73 -0
- package/dist/rules/sqlpg101.ts +24 -0
- package/dist/rules/sqlpg102.ts +30 -0
- package/dist/rules/sqlpg103.ts +23 -0
- package/dist/rules/sqlpg104.ts +23 -0
- package/dist/rules/sqlpg105.ts +22 -0
- package/dist/rules/sqlpg106.ts +22 -0
- package/dist/rules/sqlpg107.ts +22 -0
- package/dist/rules/sqlpg108.ts +27 -0
- package/dist/rules/sqlpg109.ts +37 -0
- package/dist/rules/sqlpg110.ts +33 -0
- package/dist/rules/sqlpg111.ts +23 -0
- package/dist/rules/sqlpg112.ts +25 -0
- package/dist/rules/sqlpg113.ts +28 -0
- package/dist/rules/sqlpg114.ts +37 -0
- package/dist/rules/sqlpg115.ts +38 -0
- package/dist/rules/sqlpg116.ts +25 -0
- package/dist/rules/sqlpg117.ts +24 -0
- package/dist/rules/sqlpg118.ts +22 -0
- package/dist/rules/templates.ts +35 -0
- package/dist/serializer.d.ts +37 -0
- package/dist/serializer.d.ts.map +1 -0
- package/dist/skill-defs.d.ts +3 -0
- package/dist/skill-defs.d.ts.map +1 -0
- package/dist/spec/catalog.d.ts +125 -0
- package/dist/spec/catalog.d.ts.map +1 -0
- package/dist/spec/fetch.d.ts +43 -0
- package/dist/spec/fetch.d.ts.map +1 -0
- package/dist/spec/pin.d.ts +39 -0
- package/dist/spec/pin.d.ts.map +1 -0
- package/dist/spec/postgres-catalog.d.ts +108 -0
- package/dist/spec/postgres-catalog.d.ts.map +1 -0
- package/dist/spec/postgres-fetch.d.ts +46 -0
- package/dist/spec/postgres-fetch.d.ts.map +1 -0
- package/dist/spec/postgres-pin.d.ts +67 -0
- package/dist/spec/postgres-pin.d.ts.map +1 -0
- package/dist/types/index.d.ts +4386 -0
- package/dist/validate-cli.d.ts +3 -0
- package/dist/validate-cli.d.ts.map +1 -0
- package/dist/validate.d.ts +15 -0
- package/dist/validate.d.ts.map +1 -0
- package/package.json +74 -4
- package/src/clickhouse/apply/apply.ts +288 -0
- package/src/clickhouse/apply/mutations.ts +90 -0
- package/src/clickhouse/apply/statements.ts +393 -0
- package/src/clickhouse/catalog-types.ts +84 -0
- package/src/clickhouse/container.ts +176 -0
- package/src/clickhouse/engine-syntax.test.ts +53 -0
- package/src/clickhouse/engine-syntax.ts +173 -0
- package/src/clickhouse/entities.test.ts +188 -0
- package/src/clickhouse/entities.ts +425 -0
- package/src/clickhouse/http.ts +76 -0
- package/src/clickhouse/import/generator.ts +153 -0
- package/src/clickhouse/import/import.test.ts +157 -0
- package/src/clickhouse/import/ir.ts +171 -0
- package/src/clickhouse/import/live-export.ts +53 -0
- package/src/clickhouse/import/parser.ts +27 -0
- package/src/clickhouse/import/roundtrip.test.ts +90 -0
- package/src/clickhouse/live/bind.ts +126 -0
- package/src/clickhouse/live/catalog.ts +96 -0
- package/src/clickhouse/live/describe-resources.ts +98 -0
- package/src/clickhouse/live/live.test.ts +143 -0
- package/src/clickhouse/live/roundtrip.e2e.test.ts +93 -0
- package/src/clickhouse/overlays/codecs.ts +68 -0
- package/src/clickhouse/overlays/engines.ts +108 -0
- package/src/clickhouse/overlays/kinds.ts +38 -0
- package/src/clickhouse/overlays/projections.ts +36 -0
- package/src/clickhouse/overlays/skip-indexes.ts +44 -0
- package/src/clickhouse/overlays/ttl.ts +55 -0
- package/src/clickhouse/overlays/types.ts +58 -0
- package/src/clickhouse/ownership.test.ts +20 -0
- package/src/clickhouse/ownership.ts +103 -0
- package/src/clickhouse/parser.test.ts +166 -0
- package/src/clickhouse/parser.ts +459 -0
- package/src/clickhouse/plan/commands.ts +101 -0
- package/src/clickhouse/plan/deep.ts +124 -0
- package/src/clickhouse/plan/diff.ts +203 -0
- package/src/clickhouse/plan/disruption.ts +61 -0
- package/src/clickhouse/plan/normalize.ts +352 -0
- package/src/clickhouse/plan/plan-wiring.test.ts +77 -0
- package/src/clickhouse/plan/plan.e2e.test.ts +77 -0
- package/src/clickhouse/plan/plan.test.ts +201 -0
- package/src/clickhouse/plan/rebuild-handoff.ts +59 -0
- package/src/clickhouse/plan/report.ts +19 -0
- package/src/clickhouse/plan/rules.ts +241 -0
- package/src/clickhouse/plan/schema.ts +56 -0
- package/src/clickhouse/plan/server-format.ts +39 -0
- package/src/clickhouse/rebuild/backfill.ts +186 -0
- package/src/clickhouse/rebuild/observe.ts +380 -0
- package/src/clickhouse/rebuild/op.ts +206 -0
- package/src/clickhouse/rebuild/partitions.ts +62 -0
- package/src/clickhouse/rebuild/rebuild-replicated.e2e.test.ts +513 -0
- package/src/clickhouse/rebuild/rebuild.e2e.test.ts +351 -0
- package/src/clickhouse/rebuild/rebuild.test.ts +190 -0
- package/src/clickhouse/rebuild/receipts.ts +143 -0
- package/src/clickhouse/rebuild/replicas.test.ts +70 -0
- package/src/clickhouse/rebuild/replicas.ts +148 -0
- package/src/clickhouse/rebuild/steps.ts +382 -0
- package/src/clickhouse/rebuild/verify.ts +124 -0
- package/src/clickhouse/testdata/NOTICE +5 -0
- package/src/clickhouse/testdata/clickhouse-tests-corpus.json +302 -0
- package/src/clickhouse/testing/fake-server.ts +65 -0
- package/src/clickhouse/testing/roundtrip-schema.ts +25 -0
- package/src/clickhouse/testing/writable-server.ts +141 -0
- package/src/clickhouse/tokens.ts +28 -0
- package/src/clickhouse.ts +63 -0
- package/src/codegen/classifier-page.test.ts +16 -0
- package/src/codegen/classifier-page.ts +76 -0
- package/src/codegen/clickhouse-module.test.ts +63 -0
- package/src/codegen/clickhouse-module.ts +269 -0
- package/src/codegen/docs-cli.ts +4 -0
- package/src/codegen/docs.ts +225 -0
- package/src/codegen/generate-cli.ts +13 -0
- package/src/codegen/generate.ts +126 -0
- package/src/codegen/package.ts +36 -0
- package/src/codegen/postgres-classifier-page.ts +81 -0
- package/src/codegen/postgres-module.test.ts +77 -0
- package/src/codegen/postgres-module.ts +434 -0
- package/src/codegen/registry.ts +36 -0
- package/src/composites/audit-log-table.ts +54 -0
- package/src/composites/catalog.test.ts +61 -0
- package/src/composites/catalog.ts +529 -0
- package/src/composites/cdc-mirror.ts +54 -0
- package/src/composites/clickhouse.ts +7 -0
- package/src/composites/composites.test.ts +758 -0
- package/src/composites/events-table.ts +49 -0
- package/src/composites/index.ts +9 -0
- package/src/composites/join-table.ts +57 -0
- package/src/composites/postgres.ts +7 -0
- package/src/composites/refreshed-view.ts +46 -0
- package/src/composites/replacing-table.ts +49 -0
- package/src/composites/rollup-view.ts +55 -0
- package/src/composites/sharded-table.ts +49 -0
- package/src/composites/soft-delete-table.ts +61 -0
- package/src/composites/tenant-table.ts +50 -0
- package/src/config.ts +157 -0
- package/src/core/apply.ts +153 -0
- package/src/core/classifier.ts +186 -0
- package/src/core/container.ts +93 -0
- package/src/core/core.test.ts +254 -0
- package/src/core/cursor.ts +189 -0
- package/src/core/diff.ts +72 -0
- package/src/core/entity.ts +85 -0
- package/src/core/find-templates.ts +158 -0
- package/src/core/handoff.ts +44 -0
- package/src/core/index.ts +61 -0
- package/src/core/interpolation.ts +225 -0
- package/src/core/normalize.ts +39 -0
- package/src/core/ownership.test.ts +36 -0
- package/src/core/ownership.ts +133 -0
- package/src/core/receipts.ts +29 -0
- package/src/core/references.ts +74 -0
- package/src/core/template.ts +83 -0
- package/src/core/testing/http-stub.ts +33 -0
- package/src/core/tokens.ts +252 -0
- package/src/coverage.ts +64 -0
- package/src/detect.ts +32 -0
- package/src/dialects.ts +21 -0
- package/src/generated/clickhouse-types.ts +4386 -0
- package/src/generated/clickhouse.ts +2476 -0
- package/src/generated/index.d.ts +4386 -0
- package/src/generated/lexicon-sql.json +67 -0
- package/src/generated/postgres-types.ts +1190 -0
- package/src/generated/postgres.ts +1039 -0
- package/src/import-generator.ts +18 -0
- package/src/index.ts +21 -0
- package/src/init-templates.test.ts +108 -0
- package/src/init-templates.ts +327 -0
- package/src/lint/audit-catalog.ts +73 -0
- package/src/lint/audit-lineage.ts +47 -0
- package/src/lint/post-synth/audit-entries.ts +29 -0
- package/src/lint/post-synth/clickhouse-checks.test.ts +278 -0
- package/src/lint/post-synth/clickhouse-helpers.ts +206 -0
- package/src/lint/post-synth/index.ts +81 -0
- package/src/lint/post-synth/post-synth.test.ts +33 -0
- package/src/lint/post-synth/postgres-audit-entries.ts +29 -0
- package/src/lint/post-synth/postgres-checks.test.ts +257 -0
- package/src/lint/post-synth/postgres-helpers.ts +126 -0
- package/src/lint/post-synth/sql-helpers.ts +53 -0
- package/src/lint/post-synth/sqlch101.ts +35 -0
- package/src/lint/post-synth/sqlch102.ts +23 -0
- package/src/lint/post-synth/sqlch103.ts +45 -0
- package/src/lint/post-synth/sqlch104.ts +42 -0
- package/src/lint/post-synth/sqlch105.ts +35 -0
- package/src/lint/post-synth/sqlch106.ts +27 -0
- package/src/lint/post-synth/sqlch107.ts +35 -0
- package/src/lint/post-synth/sqlch108.ts +27 -0
- package/src/lint/post-synth/sqlch109.ts +21 -0
- package/src/lint/post-synth/sqlch110.ts +29 -0
- package/src/lint/post-synth/sqlch111.ts +40 -0
- package/src/lint/post-synth/sqlch112.ts +30 -0
- package/src/lint/post-synth/sqlch113.ts +20 -0
- package/src/lint/post-synth/sqlch114.ts +26 -0
- package/src/lint/post-synth/sqlch115.ts +31 -0
- package/src/lint/post-synth/sqlch116.ts +22 -0
- package/src/lint/post-synth/sqlch117.ts +25 -0
- package/src/lint/post-synth/sqlch118.ts +26 -0
- package/src/lint/post-synth/sqlch119.ts +31 -0
- package/src/lint/post-synth/sqlch120.ts +21 -0
- package/src/lint/post-synth/sqlpg101.ts +24 -0
- package/src/lint/post-synth/sqlpg102.ts +30 -0
- package/src/lint/post-synth/sqlpg103.ts +23 -0
- package/src/lint/post-synth/sqlpg104.ts +23 -0
- package/src/lint/post-synth/sqlpg105.ts +22 -0
- package/src/lint/post-synth/sqlpg106.ts +22 -0
- package/src/lint/post-synth/sqlpg107.ts +22 -0
- package/src/lint/post-synth/sqlpg108.ts +27 -0
- package/src/lint/post-synth/sqlpg109.ts +37 -0
- package/src/lint/post-synth/sqlpg110.ts +33 -0
- package/src/lint/post-synth/sqlpg111.ts +23 -0
- package/src/lint/post-synth/sqlpg112.ts +25 -0
- package/src/lint/post-synth/sqlpg113.ts +28 -0
- package/src/lint/post-synth/sqlpg114.ts +37 -0
- package/src/lint/post-synth/sqlpg115.ts +38 -0
- package/src/lint/post-synth/sqlpg116.ts +25 -0
- package/src/lint/post-synth/sqlpg117.ts +24 -0
- package/src/lint/post-synth/sqlpg118.ts +22 -0
- package/src/lint/rules/index.ts +13 -0
- package/src/lint/rules/postgres-templates.ts +36 -0
- package/src/lint/rules/rules.test.ts +228 -0
- package/src/lint/rules/sqlch001.ts +53 -0
- package/src/lint/rules/sqlch002.ts +115 -0
- package/src/lint/rules/sqlch003.ts +68 -0
- package/src/lint/rules/sqlpg001.ts +88 -0
- package/src/lint/rules/sqlpg002.ts +68 -0
- package/src/lint/rules/sqlpg003.ts +59 -0
- package/src/lint/rules/sqlpg004.ts +73 -0
- package/src/lint/rules/templates.ts +35 -0
- package/src/live-dialect.ts +37 -0
- package/src/lsp/catalog.ts +60 -0
- package/src/lsp/completions.test.ts +111 -0
- package/src/lsp/completions.ts +128 -0
- package/src/lsp/diagnostics.test.ts +26 -0
- package/src/lsp/hover.test.ts +90 -0
- package/src/lsp/hover.ts +113 -0
- package/src/lsp/postgres-catalog.ts +234 -0
- package/src/lsp/postgres-template.ts +161 -0
- package/src/lsp/postgres.test.ts +150 -0
- package/src/lsp/postgres.ts +270 -0
- package/src/lsp/refs.ts +53 -0
- package/src/lsp/registry.ts +19 -0
- package/src/lsp/template.ts +166 -0
- package/src/mcp/index.ts +304 -0
- package/src/mcp/mcp.test.ts +184 -0
- package/src/mcp/postgres.ts +125 -0
- package/src/op/activities/clickhouse-apply.e2e.test.ts +150 -0
- package/src/op/activities/clickhouse-apply.test.ts +265 -0
- package/src/op/activities/clickhouse-apply.ts +113 -0
- package/src/op/activities/clickhouse-emulator.test.ts +23 -0
- package/src/op/activities/clickhouse-emulator.ts +37 -0
- package/src/op/activities/clickhouse-rebuild.ts +136 -0
- package/src/op/activities/index.ts +50 -0
- package/src/op/activities/postgres-apply.e2e.test.ts +184 -0
- package/src/op/activities/postgres-apply.test.ts +304 -0
- package/src/op/activities/postgres-apply.ts +170 -0
- package/src/op/activities/postgres-emulator.test.ts +26 -0
- package/src/op/activities/postgres-emulator.ts +44 -0
- package/src/op/activities/postgres-migration.ts +182 -0
- package/src/op/activity-contracts.ts +210 -0
- package/src/package-cli.ts +17 -0
- package/src/plugin.test.ts +74 -0
- package/src/plugin.ts +242 -0
- package/src/postgres/apply/apply.ts +582 -0
- package/src/postgres/apply/statements.test.ts +155 -0
- package/src/postgres/apply/statements.ts +603 -0
- package/src/postgres/catalog-types.ts +59 -0
- package/src/postgres/container.ts +72 -0
- package/src/postgres/entities.test.ts +170 -0
- package/src/postgres/entities.ts +1016 -0
- package/src/postgres/entity-types.ts +18 -0
- package/src/postgres/import/generator.ts +176 -0
- package/src/postgres/import/import.test.ts +71 -0
- package/src/postgres/import/ir.ts +67 -0
- package/src/postgres/import/live-export.ts +53 -0
- package/src/postgres/import/live-warnings.test.ts +45 -0
- package/src/postgres/keywords.ts +40 -0
- package/src/postgres/live/bind.ts +146 -0
- package/src/postgres/live/catalog.ts +581 -0
- package/src/postgres/live/client.ts +84 -0
- package/src/postgres/live/describe-resources.ts +111 -0
- package/src/postgres/live/live.test.ts +198 -0
- package/src/postgres/live/roundtrip.e2e.test.ts +111 -0
- package/src/postgres/migrate/backfill.ts +233 -0
- package/src/postgres/migrate/batches.e2e.test.ts +163 -0
- package/src/postgres/migrate/batches.test.ts +36 -0
- package/src/postgres/migrate/batches.ts +159 -0
- package/src/postgres/migrate/carry.e2e.test.ts +335 -0
- package/src/postgres/migrate/carry.test.ts +103 -0
- package/src/postgres/migrate/carry.ts +653 -0
- package/src/postgres/migrate/handoff.ts +73 -0
- package/src/postgres/migrate/kinds.e2e.test.ts +204 -0
- package/src/postgres/migrate/migrate.e2e.test.ts +362 -0
- package/src/postgres/migrate/migrate.test.ts +322 -0
- package/src/postgres/migrate/names.ts +93 -0
- package/src/postgres/migrate/observe.ts +521 -0
- package/src/postgres/migrate/op.ts +242 -0
- package/src/postgres/migrate/receipts.ts +135 -0
- package/src/postgres/migrate/replication.ts +151 -0
- package/src/postgres/migrate/steps.ts +657 -0
- package/src/postgres/overlays/columns.ts +34 -0
- package/src/postgres/overlays/constraints.ts +56 -0
- package/src/postgres/overlays/indexes.ts +27 -0
- package/src/postgres/overlays/kinds.ts +53 -0
- package/src/postgres/overlays/partitioning.ts +26 -0
- package/src/postgres/overlays/relations.ts +29 -0
- package/src/postgres/overlays/storage.ts +75 -0
- package/src/postgres/overlays/type-ddl.ts +38 -0
- package/src/postgres/overlays/types.ts +56 -0
- package/src/postgres/parser.test.ts +214 -0
- package/src/postgres/parser.ts +1062 -0
- package/src/postgres/plan/commands.ts +124 -0
- package/src/postgres/plan/deep.ts +177 -0
- package/src/postgres/plan/diff.ts +323 -0
- package/src/postgres/plan/disruption.ts +52 -0
- package/src/postgres/plan/normalize.test.ts +148 -0
- package/src/postgres/plan/normalize.ts +542 -0
- package/src/postgres/plan/plan.e2e.test.ts +117 -0
- package/src/postgres/plan/plan.test.ts +244 -0
- package/src/postgres/plan/report.ts +24 -0
- package/src/postgres/plan/rules.ts +276 -0
- package/src/postgres/plan/schema.ts +114 -0
- package/src/postgres/plan/server-normalize.ts +123 -0
- package/src/postgres/providers/aurora.ts +45 -0
- package/src/postgres/providers/azure.ts +54 -0
- package/src/postgres/providers/cloud-sql.ts +42 -0
- package/src/postgres/providers/index.ts +90 -0
- package/src/postgres/providers/neon.ts +45 -0
- package/src/postgres/providers/providers.test.ts +136 -0
- package/src/postgres/providers/rds.ts +48 -0
- package/src/postgres/providers/supabase.ts +46 -0
- package/src/postgres/providers/types.ts +70 -0
- package/src/postgres/testdata/NOTICE +31 -0
- package/src/postgres/testdata/postgres-regress-corpus.json +460 -0
- package/src/postgres/testing/fake-client.ts +42 -0
- package/src/postgres/testing/migration.ts +52 -0
- package/src/postgres/testing/roundtrip-schema.ts +46 -0
- package/src/postgres/testing/server.ts +58 -0
- package/src/postgres/testing/writable-server.ts +188 -0
- package/src/postgres/tokens.ts +46 -0
- package/src/postgres.ts +75 -0
- package/src/serializer.test.ts +128 -0
- package/src/serializer.ts +148 -0
- package/src/skill-defs.test.ts +81 -0
- package/src/skill-defs.ts +102 -0
- package/src/skills/chant-sql-plan.md +123 -0
- package/src/skills/chant-sql-postgres-migration.md +126 -0
- package/src/skills/chant-sql-postgres-plan.md +194 -0
- package/src/skills/chant-sql-postgres.md +165 -0
- package/src/skills/chant-sql-rebuild.md +68 -0
- package/src/skills/chant-sql.md +123 -0
- package/src/spec/catalog.e2e.test.ts +29 -0
- package/src/spec/catalog.test.ts +56 -0
- package/src/spec/catalog.ts +311 -0
- package/src/spec/clickhouse-catalog.snapshot.json +5246 -0
- package/src/spec/fetch.test.ts +77 -0
- package/src/spec/fetch.ts +112 -0
- package/src/spec/pin.ts +47 -0
- package/src/spec/postgres-catalog-14.snapshot.json +3494 -0
- package/src/spec/postgres-catalog-15.snapshot.json +3529 -0
- package/src/spec/postgres-catalog-16.snapshot.json +3597 -0
- package/src/spec/postgres-catalog-17.snapshot.json +3656 -0
- package/src/spec/postgres-catalog-18.snapshot.json +3747 -0
- package/src/spec/postgres-catalog.test.ts +43 -0
- package/src/spec/postgres-catalog.ts +301 -0
- package/src/spec/postgres-fetch.test.ts +75 -0
- package/src/spec/postgres-fetch.ts +112 -0
- package/src/spec/postgres-pin.test.ts +64 -0
- package/src/spec/postgres-pin.ts +101 -0
- package/src/typecheck.test.ts +104 -0
- package/src/validate-cli.ts +6 -0
- package/src/validate.ts +149 -0
|
@@ -0,0 +1,758 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The sql composites (ClickHouse #3212, Postgres #3286): their props and defaults, the entity types they
|
|
3
|
+
* build, the references between members, the lexicon's own post-synth checks
|
|
4
|
+
* over what they build, and the provenance each field keeps (#3212).
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { afterAll, beforeAll, describe, expect, test } from "vitest";
|
|
8
|
+
import { mkdir, realpath, rm, writeFile } from "node:fs/promises";
|
|
9
|
+
import { dirname, join, resolve } from "node:path";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
11
|
+
import { expandComposite, type CompositeInstance } from "@intentius/chant/composite";
|
|
12
|
+
import { build } from "@intentius/chant/build";
|
|
13
|
+
import type { Declarable } from "@intentius/chant/declarable";
|
|
14
|
+
import type { SerializerResult } from "@intentius/chant/serializer";
|
|
15
|
+
import { makePostSynthCtx } from "@intentius/chant-test-utils";
|
|
16
|
+
import { AuditLogTable, CdcMirror, EventsTable, JoinTable, RefreshedView, ReplacingTable, RollupView, ShardedTable, SoftDeleteTable, TenantTable } from "./index";
|
|
17
|
+
import { schema, POSTGRES_ENTITY_TYPES, type PostgresTable } from "../postgres/entities";
|
|
18
|
+
import { table, CLICKHOUSE_ENTITY_TYPES, SqlTemplateError, type ClickHouseObject } from "../clickhouse/entities";
|
|
19
|
+
import { sqlSerializer } from "../serializer";
|
|
20
|
+
import { postSynthChecks } from "../lint/post-synth";
|
|
21
|
+
import { sqlPlugin } from "../plugin";
|
|
22
|
+
import { getProvenance, originOfPath } from "@intentius/chant/provenance";
|
|
23
|
+
import { resolveDriftedField } from "@intentius/chant/fold-provenance";
|
|
24
|
+
|
|
25
|
+
const flat = (ddl: string) => ddl.replace(/\s+/g, " ").trim();
|
|
26
|
+
const ddlOf = (entity: unknown) => flat((entity as ClickHouseObject & { props: { ddl: string } }).props.ddl);
|
|
27
|
+
const propsOf = (entity: unknown) => (entity as { props: Record<string, unknown> }).props;
|
|
28
|
+
|
|
29
|
+
const events = () =>
|
|
30
|
+
EventsTable({ name: "events", columns: "user_id UUID, kind LowCardinality(String)", orderBy: "(kind, user_id, ts)" });
|
|
31
|
+
|
|
32
|
+
describe("ReplacingTable", () => {
|
|
33
|
+
test("defaults: a UInt64 `version` column, the engine reading it, no partition", () => {
|
|
34
|
+
const { table: t } = ReplacingTable({ name: "users", columns: "id UInt64, email String", orderBy: "id" });
|
|
35
|
+
expect(t.entityType).toBe(CLICKHOUSE_ENTITY_TYPES.table);
|
|
36
|
+
expect(ddlOf(t)).toBe(
|
|
37
|
+
"CREATE TABLE users ( id UInt64, email String, version UInt64 ) ENGINE = ReplacingMergeTree(version) ORDER BY id",
|
|
38
|
+
);
|
|
39
|
+
expect(t.props.columns.map((c) => [c.name, c.type])).toEqual([
|
|
40
|
+
["id", "UInt64"],
|
|
41
|
+
["email", "String"],
|
|
42
|
+
["version", "UInt64"],
|
|
43
|
+
]);
|
|
44
|
+
expect(t.props.engine).toEqual({ name: "ReplacingMergeTree", args: ["version"] });
|
|
45
|
+
expect(t.props.partitionBy).toBeUndefined();
|
|
46
|
+
expect(Object.keys(t.columns)).toEqual(["id", "email", "version"]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("every optional prop reaches its field", () => {
|
|
50
|
+
const { table: t } = ReplacingTable({
|
|
51
|
+
name: "app.users",
|
|
52
|
+
columns: "id UInt64, email String, updated DateTime",
|
|
53
|
+
orderBy: "id",
|
|
54
|
+
version: "updated_at",
|
|
55
|
+
versionType: "DateTime64(3)",
|
|
56
|
+
partitionBy: "toYYYYMM(updated)",
|
|
57
|
+
});
|
|
58
|
+
expect(t.props.database).toBe("app");
|
|
59
|
+
expect(t.props.name).toBe("users");
|
|
60
|
+
expect(t.props.columns.at(-1)).toEqual({ name: "updated_at", type: "DateTime64(3)" });
|
|
61
|
+
expect(t.props.engine).toEqual({ name: "ReplacingMergeTree", args: ["updated_at"] });
|
|
62
|
+
expect(t.props.partitionBy).toBe("toYYYYMM(updated)");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
describe("EventsTable", () => {
|
|
67
|
+
test("defaults: a DateTime `ts`, monthly partitions, 90 days of TTL, whole parts dropped", () => {
|
|
68
|
+
const { table: t } = events();
|
|
69
|
+
expect(t.props.columns.at(-1)).toEqual({ name: "ts", type: "DateTime" });
|
|
70
|
+
expect(t.props.engine).toEqual({ name: "MergeTree" });
|
|
71
|
+
expect(t.props.partitionBy).toBe("toYYYYMM(ts)");
|
|
72
|
+
expect(t.props.orderBy).toBe("(kind, user_id, ts)");
|
|
73
|
+
expect(t.props.ttl).toBe("ts + INTERVAL 90 DAY");
|
|
74
|
+
expect(t.props.settings).toEqual({ ttl_only_drop_parts: "1" });
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test("the timestamp, its type, the TTL and the partition key are parameters", () => {
|
|
78
|
+
const { table: t } = EventsTable({
|
|
79
|
+
name: "clicks",
|
|
80
|
+
columns: "url String",
|
|
81
|
+
orderBy: "(url, at)",
|
|
82
|
+
timestamp: "at",
|
|
83
|
+
timestampType: "DateTime64(3)",
|
|
84
|
+
ttlDays: 30,
|
|
85
|
+
partitionBy: "toDate(at)",
|
|
86
|
+
});
|
|
87
|
+
expect(t.props.columns.at(-1)).toEqual({ name: "at", type: "DateTime64(3)" });
|
|
88
|
+
expect(t.props.ttl).toBe("at + INTERVAL 30 DAY");
|
|
89
|
+
expect(t.props.partitionBy).toBe("toDate(at)");
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
describe("RollupView", () => {
|
|
94
|
+
const rollup = (source = events().table) =>
|
|
95
|
+
RollupView({
|
|
96
|
+
name: "daily_kinds",
|
|
97
|
+
source,
|
|
98
|
+
columns: "day Date, kind LowCardinality(String), n UInt64",
|
|
99
|
+
select: "toDate(ts) AS day, kind, count() AS n",
|
|
100
|
+
groupBy: "day, kind",
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test("defaults: a SummingMergeTree target sorted by the grouping key, and a view named after it", () => {
|
|
104
|
+
const { table: target, view } = rollup();
|
|
105
|
+
expect(target.entityType).toBe(CLICKHOUSE_ENTITY_TYPES.table);
|
|
106
|
+
expect(target.props.engine).toEqual({ name: "SummingMergeTree" });
|
|
107
|
+
expect(target.props.orderBy).toBe("(day, kind)");
|
|
108
|
+
expect(view.entityType).toBe(CLICKHOUSE_ENTITY_TYPES.materializedView);
|
|
109
|
+
expect(view.props.name).toBe("daily_kinds_mv");
|
|
110
|
+
expect(view.props.lineage.map((e) => e.output)).toEqual(["day", "kind", "n"]);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("the view writes TO its target and reads the source, by reference", () => {
|
|
114
|
+
const source = events().table;
|
|
115
|
+
const { table: target, view } = rollup(source);
|
|
116
|
+
expect(view.props.to).toBe(target);
|
|
117
|
+
expect(view.props.reads).toEqual([source]);
|
|
118
|
+
expect(view.dependsOn).toEqual([target, source]);
|
|
119
|
+
expect(ddlOf(view)).toBe(
|
|
120
|
+
"CREATE MATERIALIZED VIEW daily_kinds_mv TO daily_kinds AS SELECT toDate(ts) AS day, kind, count() AS n FROM events GROUP BY day, kind",
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test("the engine, sort key and partition key are parameters", () => {
|
|
125
|
+
const { table: target } = RollupView({
|
|
126
|
+
name: "daily_users",
|
|
127
|
+
source: events().table,
|
|
128
|
+
columns: "day Date, users AggregateFunction(uniq, UUID)",
|
|
129
|
+
select: "toDate(ts) AS day, uniqState(user_id) AS users",
|
|
130
|
+
groupBy: "day",
|
|
131
|
+
engine: "AggregatingMergeTree",
|
|
132
|
+
orderBy: "day",
|
|
133
|
+
partitionBy: "toYYYYMM(day)",
|
|
134
|
+
});
|
|
135
|
+
expect(target.props.engine).toEqual({ name: "AggregatingMergeTree" });
|
|
136
|
+
expect(target.props.orderBy).toBe("day");
|
|
137
|
+
expect(target.props.partitionBy).toBe("toYYYYMM(day)");
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe("CdcMirror", () => {
|
|
142
|
+
test("defaults: `_version` and `_is_deleted` columns, both read by the engine, and a view of live rows", () => {
|
|
143
|
+
const { table: mirror, current } = CdcMirror({ name: "orders", columns: "id UInt64, total Decimal(12, 2)", primaryKey: "id" });
|
|
144
|
+
expect(mirror.props.columns.slice(-2)).toEqual([
|
|
145
|
+
{ name: "_version", type: "UInt64" },
|
|
146
|
+
{ name: "_is_deleted", type: "UInt8" },
|
|
147
|
+
]);
|
|
148
|
+
expect(mirror.props.engine).toEqual({ name: "ReplacingMergeTree", args: ["_version", "_is_deleted"] });
|
|
149
|
+
expect(mirror.props.orderBy).toBe("id");
|
|
150
|
+
expect(current.entityType).toBe(CLICKHOUSE_ENTITY_TYPES.view);
|
|
151
|
+
expect(ddlOf(current)).toBe(
|
|
152
|
+
"CREATE VIEW orders_current AS SELECT * EXCEPT (_version, _is_deleted) FROM orders FINAL WHERE _is_deleted = 0",
|
|
153
|
+
);
|
|
154
|
+
expect(current.dependsOn).toEqual([mirror]);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
test("the pipeline's own column names are parameters", () => {
|
|
158
|
+
const { table: mirror, current } = CdcMirror({
|
|
159
|
+
name: "orders",
|
|
160
|
+
columns: "id UInt64",
|
|
161
|
+
primaryKey: "id",
|
|
162
|
+
version: "_peerdb_version",
|
|
163
|
+
deleted: "_peerdb_is_deleted",
|
|
164
|
+
partitionBy: "intDiv(id, 1000000)",
|
|
165
|
+
});
|
|
166
|
+
expect(mirror.props.engine?.args).toEqual(["_peerdb_version", "_peerdb_is_deleted"]);
|
|
167
|
+
expect(mirror.props.partitionBy).toBe("intDiv(id, 1000000)");
|
|
168
|
+
expect(current.props.select).toContain("WHERE _peerdb_is_deleted = 0");
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
describe("ShardedTable", () => {
|
|
173
|
+
test("a local ReplicatedMergeTree table and a Distributed table over it, both ON CLUSTER", () => {
|
|
174
|
+
const { local, distributed } = ShardedTable({ name: "hits", cluster: "main", columns: "id UInt64, url String", orderBy: "id" });
|
|
175
|
+
expect(local.props.name).toBe("hits_local");
|
|
176
|
+
expect(local.props.onCluster).toBe("main");
|
|
177
|
+
expect(local.props.engine).toEqual({ name: "ReplicatedMergeTree" });
|
|
178
|
+
expect(distributed.props.onCluster).toBe("main");
|
|
179
|
+
expect(distributed.props.engine).toEqual({ name: "Distributed", args: ["main", "currentDatabase()", "hits_local", "rand()"] });
|
|
180
|
+
expect(distributed.props.columns).toEqual(local.props.columns);
|
|
181
|
+
expect(distributed.dependsOn).toEqual([local]);
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
test("the sharding key and partition key are parameters", () => {
|
|
185
|
+
const { local, distributed } = ShardedTable({
|
|
186
|
+
name: "hits",
|
|
187
|
+
cluster: "main",
|
|
188
|
+
columns: "id UInt64, user_id UInt64",
|
|
189
|
+
orderBy: "id",
|
|
190
|
+
shardingKey: "cityHash64(user_id)",
|
|
191
|
+
partitionBy: "intDiv(id, 1000000)",
|
|
192
|
+
});
|
|
193
|
+
expect(distributed.props.engine?.args?.at(-1)).toBe("cityHash64(user_id)");
|
|
194
|
+
expect(local.props.partitionBy).toBe("intDiv(id, 1000000)");
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("a prop that is not valid SQL is refused at the interpolation that carried it", () => {
|
|
199
|
+
expect(() => ReplacingTable({ name: "users", columns: "id UInt64, (", orderBy: "id" })).toThrow(SqlTemplateError);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
// ── What the lexicon's own checks say ──────────────────────────────────
|
|
203
|
+
|
|
204
|
+
describe("the composites pass the lexicon's post-synth checks", () => {
|
|
205
|
+
test("SQLCH101-120 find nothing in any of them", () => {
|
|
206
|
+
const source = events();
|
|
207
|
+
const instances: Array<[string, CompositeInstance]> = [
|
|
208
|
+
["users", ReplacingTable({ name: "users", columns: "id UInt64, email String", orderBy: "id" })],
|
|
209
|
+
["events", source],
|
|
210
|
+
[
|
|
211
|
+
"daily",
|
|
212
|
+
RollupView({
|
|
213
|
+
name: "daily_kinds",
|
|
214
|
+
source: source.table,
|
|
215
|
+
columns: "day Date, kind LowCardinality(String), n UInt64",
|
|
216
|
+
select: "toDate(ts) AS day, kind, count() AS n",
|
|
217
|
+
groupBy: "day, kind",
|
|
218
|
+
}),
|
|
219
|
+
],
|
|
220
|
+
["orders", CdcMirror({ name: "orders", columns: "id UInt64, total Decimal(12, 2)", primaryKey: "id" })],
|
|
221
|
+
["hits", ShardedTable({ name: "hits", cluster: "main", columns: "id UInt64, url String", orderBy: "id" })],
|
|
222
|
+
];
|
|
223
|
+
const entities = new Map<string, Declarable>();
|
|
224
|
+
for (const [name, instance] of instances) for (const [k, v] of expandComposite(name, instance)) entities.set(k, v);
|
|
225
|
+
|
|
226
|
+
const out = sqlSerializer.serialize(entities) as SerializerResult;
|
|
227
|
+
const doc = JSON.parse(out.primary) as { applyOrder: string[] };
|
|
228
|
+
expect(doc.applyOrder.indexOf("eventsTable")).toBeLessThan(doc.applyOrder.indexOf("dailyView"));
|
|
229
|
+
expect(doc.applyOrder.indexOf("dailyTable")).toBeLessThan(doc.applyOrder.indexOf("dailyView"));
|
|
230
|
+
expect(doc.applyOrder.indexOf("hitsLocal")).toBeLessThan(doc.applyOrder.indexOf("hitsDistributed"));
|
|
231
|
+
|
|
232
|
+
const ctx = makePostSynthCtx("sql", out.primary, entities);
|
|
233
|
+
const clickhouse = postSynthChecks.filter((c) => c.id.startsWith("SQLCH"));
|
|
234
|
+
const ids = clickhouse.map((c) => c.id).sort();
|
|
235
|
+
expect(ids[0]).toBe("SQLCH101");
|
|
236
|
+
expect(ids.at(-1)).toBe("SQLCH120");
|
|
237
|
+
expect(clickhouse.flatMap((check) => check.check(ctx))).toEqual([]);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// ── Provenance (#3212) ─────────────────────────────────────────────────
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Where a composite call and each of its arguments were written (chant#3597),
|
|
245
|
+
* read off the fixture text: the call starts at `needle`, and an argument is the
|
|
246
|
+
* `name: value` property between it and the call's closing `})`. A parameter
|
|
247
|
+
* the call does not write is located at the call, with no text.
|
|
248
|
+
*/
|
|
249
|
+
function callSite(file: string, source: string, needle: string) {
|
|
250
|
+
const start = source.indexOf(needle);
|
|
251
|
+
if (start < 0) throw new Error(`fixture has no ${needle}`);
|
|
252
|
+
const end = source.indexOf("})", start);
|
|
253
|
+
const at = (offset: number) => {
|
|
254
|
+
const before = source.slice(0, offset).split("\n");
|
|
255
|
+
return { file, line: before.length, column: before[before.length - 1].length + 1 };
|
|
256
|
+
};
|
|
257
|
+
const call = at(start);
|
|
258
|
+
const argument = (parameter: string) => {
|
|
259
|
+
const m = new RegExp(`\\b${parameter}: (?:"[^"]*"|[\\w.]+)`).exec(source.slice(start, end));
|
|
260
|
+
return m ? { parameter, ...at(start + m.index), text: m[0] } : { parameter, ...call };
|
|
261
|
+
};
|
|
262
|
+
return { call, argument };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
type CallSite = ReturnType<typeof callSite>;
|
|
266
|
+
|
|
267
|
+
/** The origin a parameter-fed field records, locations included. */
|
|
268
|
+
function paramAt(sites: Record<string, CallSite>) {
|
|
269
|
+
return (composite: string, instance: string, ...parameters: string[]) => ({
|
|
270
|
+
kind: "composite-parameter",
|
|
271
|
+
composite,
|
|
272
|
+
instance,
|
|
273
|
+
parameters,
|
|
274
|
+
call: sites[instance].call,
|
|
275
|
+
arguments: parameters.map((p) => sites[instance].argument(p)),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/** The origin a field the composite fixes records. */
|
|
280
|
+
function fixedAt(sites: Record<string, CallSite>) {
|
|
281
|
+
return (composite: string, instance: string) => ({ kind: "composite-literal", composite, instance, call: sites[instance].call });
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
285
|
+
const repoRoot = resolve(thisDir, "../../../..");
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* A project that defines nothing itself and calls the composites through the
|
|
289
|
+
* installed package's dialect subpath, as a user's project does. Core resolves
|
|
290
|
+
* the subpath through `node_modules` to the package's TypeScript source and
|
|
291
|
+
* follows `clickhouse.ts`'s `export * from "./composites"` and the composites
|
|
292
|
+
* barrel to `events-table.ts`, which it interprets (#3247).
|
|
293
|
+
*/
|
|
294
|
+
const EVENTS = `
|
|
295
|
+
import { EventsTable } from "@intentius/chant-lexicon-sql/clickhouse";
|
|
296
|
+
|
|
297
|
+
export const events = EventsTable({ name: "events", columns: "user_id UUID, kind LowCardinality(String)", orderBy: "(kind, user_id, ts)", ttlDays: 30 });
|
|
298
|
+
`;
|
|
299
|
+
|
|
300
|
+
const DAILY = `
|
|
301
|
+
import { RollupView } from "@intentius/chant-lexicon-sql/clickhouse";
|
|
302
|
+
import { events } from "./events";
|
|
303
|
+
|
|
304
|
+
export const daily = RollupView({
|
|
305
|
+
name: "daily_kinds",
|
|
306
|
+
source: events.table,
|
|
307
|
+
columns: "day Date, kind LowCardinality(String), n UInt64",
|
|
308
|
+
select: "toDate(ts) AS day, kind, count() AS n",
|
|
309
|
+
groupBy: "day, kind",
|
|
310
|
+
});
|
|
311
|
+
`;
|
|
312
|
+
|
|
313
|
+
describe("each field keeps its provenance when the composite is interpreted", () => {
|
|
314
|
+
let dir: string;
|
|
315
|
+
|
|
316
|
+
beforeAll(async () => {
|
|
317
|
+
const path = join(repoRoot, ".cache", `sql-3212-composites-${process.pid}`);
|
|
318
|
+
await rm(path, { recursive: true, force: true });
|
|
319
|
+
await mkdir(join(path, "src"), { recursive: true });
|
|
320
|
+
dir = await realpath(path);
|
|
321
|
+
await writeFile(join(dir, "src", "events.ts"), EVENTS);
|
|
322
|
+
await writeFile(join(dir, "src", "daily.ts"), DAILY);
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
afterAll(async () => {
|
|
326
|
+
await rm(dir, { recursive: true, force: true });
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
test("a field is the parameter that fed it, or fixed by the composite", async () => {
|
|
330
|
+
const result = await build(join(dir, "src"), [sqlSerializer], undefined, {
|
|
331
|
+
fold: true,
|
|
332
|
+
lexicons: ["sql"],
|
|
333
|
+
intrinsics: sqlPlugin.intrinsics?.() ?? [],
|
|
334
|
+
});
|
|
335
|
+
expect(result.errors).toEqual([]);
|
|
336
|
+
const src = join(dir, "src");
|
|
337
|
+
const sites = {
|
|
338
|
+
events: callSite(join(src, "events.ts"), EVENTS, "EventsTable({"),
|
|
339
|
+
daily: callSite(join(src, "daily.ts"), DAILY, "RollupView({"),
|
|
340
|
+
};
|
|
341
|
+
const param = paramAt(sites);
|
|
342
|
+
const fixed = fixedAt(sites);
|
|
343
|
+
|
|
344
|
+
const t = result.foldProvenance.eventsTable!.fields;
|
|
345
|
+
expect(t.name).toEqual(param("EventsTable", "events", "name"));
|
|
346
|
+
expect(t.ttl).toEqual(param("EventsTable", "events", "timestamp", "ttlDays"));
|
|
347
|
+
expect(t.partitionBy).toEqual(param("EventsTable", "events", "partitionBy", "timestamp"));
|
|
348
|
+
expect(t.orderBy).toEqual(param("EventsTable", "events", "orderBy"));
|
|
349
|
+
expect(t.columns).toEqual(param("EventsTable", "events", "columns", "timestamp", "timestampType"));
|
|
350
|
+
expect(t["engine.name"]).toEqual(fixed("EventsTable", "events"));
|
|
351
|
+
expect(t["settings.ttl_only_drop_parts"]).toEqual(fixed("EventsTable", "events"));
|
|
352
|
+
|
|
353
|
+
const v = result.foldProvenance.dailyView!.fields;
|
|
354
|
+
expect(v.name).toEqual(param("RollupView", "daily", "name"));
|
|
355
|
+
expect(v.select).toEqual(param("RollupView", "daily", "groupBy", "select"));
|
|
356
|
+
// `TO ${target}` and `FROM ${props.source}` are references, not text the
|
|
357
|
+
// author typed into the field, so neither governs `to` or `reads`.
|
|
358
|
+
expect(v.to).toEqual(fixed("RollupView", "daily"));
|
|
359
|
+
expect(result.foldProvenance.dailyTable!.fields.orderBy).toEqual(param("RollupView", "daily", "groupBy", "orderBy"));
|
|
360
|
+
|
|
361
|
+
// A drift on the TTL is a change to `ttlDays` at the `events` call; one on
|
|
362
|
+
// the engine is refused, because the composite fixes it.
|
|
363
|
+
const provenance = getProvenance(result.entities.get("eventsTable")!);
|
|
364
|
+
const drift = (path: string, declared: unknown, live: unknown) =>
|
|
365
|
+
resolveDriftedField({ entity: "eventsTable", path, declared, live, origin: originOfPath(provenance?.paths, path), provenance });
|
|
366
|
+
const ttl = drift("ttl", "ts + INTERVAL 30 DAY", "ts + INTERVAL 7 DAY").resolution;
|
|
367
|
+
expect(ttl).toMatchObject({ kind: "propose-parameter", parameters: ["timestamp", "ttlDays"], instance: "events" });
|
|
368
|
+
expect(ttl.sourceFile).toContain("events.ts");
|
|
369
|
+
expect(drift("engine.name", "MergeTree", "ReplacingMergeTree").resolution.kind).toBe("refuse-fixed");
|
|
370
|
+
|
|
371
|
+
// Interpreting the package's composites writes what calling them writes.
|
|
372
|
+
const run = await build(join(dir, "src"), [sqlSerializer], undefined, {
|
|
373
|
+
fold: false,
|
|
374
|
+
lexicons: ["sql"],
|
|
375
|
+
intrinsics: sqlPlugin.intrinsics?.() ?? [],
|
|
376
|
+
});
|
|
377
|
+
expect(run.errors).toEqual([]);
|
|
378
|
+
expect(result.outputs.get("sql")).toBeDefined();
|
|
379
|
+
expect(result.outputs.get("sql")).toEqual(run.outputs.get("sql"));
|
|
380
|
+
});
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// ── Postgres composites (#3286) ────────────────────────────────────────
|
|
384
|
+
|
|
385
|
+
describe("the Postgres composites", () => {
|
|
386
|
+
const pgTable = (e: unknown) => (e as PostgresTable).props;
|
|
387
|
+
const pgDdl = (e: unknown) => flat((e as { props: { ddl: string } }).props.ddl);
|
|
388
|
+
const users = () =>
|
|
389
|
+
SoftDeleteTable({ name: "users", schema: "app", columns: "id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, email text NOT NULL" });
|
|
390
|
+
|
|
391
|
+
describe("SoftDeleteTable", () => {
|
|
392
|
+
test("defaults: the three timestamp columns, a view and an index over the live rows, in the public schema", () => {
|
|
393
|
+
const { table: t, live, liveIndex } = SoftDeleteTable({ name: "teams", columns: "id bigint PRIMARY KEY, name text NOT NULL" });
|
|
394
|
+
expect(t.entityType).toBe(POSTGRES_ENTITY_TYPES.table);
|
|
395
|
+
expect(pgTable(t).schema).toBe("public");
|
|
396
|
+
expect(pgTable(t).columns.map((c) => c.name)).toEqual(["id", "name", "created_at", "updated_at", "deleted_at"]);
|
|
397
|
+
expect(pgTable(t).columns.slice(2).map((c) => [c.type, c.notNull ?? false, c.default])).toEqual([
|
|
398
|
+
["timestamptz", true, "now()"],
|
|
399
|
+
["timestamptz", true, "now()"],
|
|
400
|
+
["timestamptz", false, undefined],
|
|
401
|
+
]);
|
|
402
|
+
expect(live.entityType).toBe(POSTGRES_ENTITY_TYPES.view);
|
|
403
|
+
expect(pgDdl(live)).toBe(
|
|
404
|
+
"CREATE VIEW public.teams_live WITH (security_invoker = true) AS SELECT * FROM public.teams WHERE deleted_at IS NULL",
|
|
405
|
+
);
|
|
406
|
+
expect(liveIndex.props.name).toBe("teams_live_idx");
|
|
407
|
+
expect(liveIndex.props.where).toBe("deleted_at IS NULL");
|
|
408
|
+
expect(liveIndex.props.elements.map((e) => e.column)).toEqual(["id"]);
|
|
409
|
+
expect(live.dependsOn).toEqual([t]);
|
|
410
|
+
expect(liveIndex.dependsOn).toEqual([t]);
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
test("the schema, the column names, the live key and the comment are parameters", () => {
|
|
414
|
+
const app = schema`CREATE SCHEMA app`;
|
|
415
|
+
const { table: t, live, liveIndex } = SoftDeleteTable({
|
|
416
|
+
name: "users",
|
|
417
|
+
schema: app,
|
|
418
|
+
columns: "id bigint PRIMARY KEY, email text NOT NULL",
|
|
419
|
+
liveKey: "email",
|
|
420
|
+
createdAt: "made",
|
|
421
|
+
updatedAt: "touched",
|
|
422
|
+
deletedAt: "gone",
|
|
423
|
+
comment: "Accounts",
|
|
424
|
+
});
|
|
425
|
+
expect(pgTable(t).schema).toBe("app");
|
|
426
|
+
expect(pgTable(t).columns.slice(2).map((c) => c.name)).toEqual(["made", "touched", "gone"]);
|
|
427
|
+
expect(pgTable(t).comment).toBe("Accounts");
|
|
428
|
+
expect(pgDdl(live)).toContain("WHERE gone IS NULL");
|
|
429
|
+
expect(liveIndex.props.where).toBe("gone IS NULL");
|
|
430
|
+
expect(liveIndex.props.elements.map((e) => e.column)).toEqual(["email"]);
|
|
431
|
+
expect(t.dependsOn).toEqual([app]);
|
|
432
|
+
});
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
describe("AuditLogTable", () => {
|
|
436
|
+
test("defaults: range-partitioned by occurred_at, the key includes it, a default partition and an actor index", () => {
|
|
437
|
+
const { table: log, defaultPartition, actorIndex } = AuditLogTable({ name: "audit", schema: "app" });
|
|
438
|
+
expect(pgTable(log).partitionBy).toBe("RANGE (occurred_at)");
|
|
439
|
+
expect(pgTable(log).primaryKey?.columns).toEqual(["id", "occurred_at"]);
|
|
440
|
+
expect(pgTable(log).columns.map((c) => c.name)).toEqual(["id", "occurred_at", "actor", "action", "subject", "details"]);
|
|
441
|
+
expect(pgTable(defaultPartition).name).toBe("audit_default");
|
|
442
|
+
expect(pgTable(defaultPartition).partitionOf).toBe(log);
|
|
443
|
+
expect(pgTable(defaultPartition).partitionBound).toBe("DEFAULT");
|
|
444
|
+
expect(actorIndex.props.elements.map((e) => e.column)).toEqual(["actor", "occurred_at"]);
|
|
445
|
+
expect(defaultPartition.dependsOn).toContain(log);
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
test("the timestamp and actor columns are parameters", () => {
|
|
449
|
+
const { table: log, actorIndex } = AuditLogTable({ name: "audit", timestamp: "at", actor: "who" });
|
|
450
|
+
expect(pgTable(log).partitionBy).toBe("RANGE (at)");
|
|
451
|
+
expect(pgTable(log).primaryKey?.columns).toEqual(["id", "at"]);
|
|
452
|
+
expect(actorIndex.props.elements.map((e) => e.column)).toEqual(["who", "at"]);
|
|
453
|
+
});
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
describe("JoinTable", () => {
|
|
457
|
+
const sides = () => ({
|
|
458
|
+
left: TenantTable({ name: "people", columns: "id bigint NOT NULL", primaryKey: "id", indexOn: "id" }).table,
|
|
459
|
+
right: users().table,
|
|
460
|
+
});
|
|
461
|
+
|
|
462
|
+
test("defaults: bigint columns referencing id, cascade deletes, a composite key and the reverse index", () => {
|
|
463
|
+
const { left, right } = sides();
|
|
464
|
+
const { table: links, reverseIndex } = JoinTable({ name: "memberships", left, leftColumn: "person_id", right, rightColumn: "user_id" });
|
|
465
|
+
expect(pgTable(links).primaryKey?.columns).toEqual(["person_id", "user_id"]);
|
|
466
|
+
expect(pgTable(links).columns.map((c) => [c.name, c.type])).toEqual([
|
|
467
|
+
["person_id", "bigint"],
|
|
468
|
+
["user_id", "bigint"],
|
|
469
|
+
["created_at", "timestamptz"],
|
|
470
|
+
]);
|
|
471
|
+
expect(pgTable(links).foreignKeys.map((f) => [f.columns, f.refTable, f.refColumns, f.onDelete])).toEqual([
|
|
472
|
+
[["person_id"], "public.people", ["id"], "CASCADE"],
|
|
473
|
+
[["user_id"], "app.users", ["id"], "CASCADE"],
|
|
474
|
+
]);
|
|
475
|
+
expect(reverseIndex.props.name).toBe("memberships_reverse_idx");
|
|
476
|
+
expect(reverseIndex.props.elements.map((e) => e.column)).toEqual(["user_id", "person_id"]);
|
|
477
|
+
expect(links.dependsOn).toEqual(expect.arrayContaining([left, right]));
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
test("the keys, the types and the delete action are parameters", () => {
|
|
481
|
+
const { left, right } = sides();
|
|
482
|
+
const { table: links } = JoinTable({
|
|
483
|
+
name: "links",
|
|
484
|
+
left,
|
|
485
|
+
leftKey: "tenant_id",
|
|
486
|
+
leftColumn: "a",
|
|
487
|
+
leftType: "uuid",
|
|
488
|
+
right,
|
|
489
|
+
rightKey: "email",
|
|
490
|
+
rightColumn: "b",
|
|
491
|
+
rightType: "text",
|
|
492
|
+
onDelete: "RESTRICT",
|
|
493
|
+
});
|
|
494
|
+
expect(pgTable(links).columns.slice(0, 2).map((c) => c.type)).toEqual(["uuid", "text"]);
|
|
495
|
+
expect(pgTable(links).foreignKeys.map((f) => [f.refColumns, f.onDelete])).toEqual([
|
|
496
|
+
[["tenant_id"], "RESTRICT"],
|
|
497
|
+
[["email"], "RESTRICT"],
|
|
498
|
+
]);
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
describe("TenantTable", () => {
|
|
503
|
+
test("defaults: a uuid tenant_id first, leading the primary key and the index", () => {
|
|
504
|
+
const { table: t, index: byTenant } = TenantTable({
|
|
505
|
+
name: "notes",
|
|
506
|
+
schema: "app",
|
|
507
|
+
columns: "id bigint NOT NULL, body text",
|
|
508
|
+
primaryKey: "id",
|
|
509
|
+
indexOn: "id",
|
|
510
|
+
});
|
|
511
|
+
expect(pgTable(t).columns[0]).toMatchObject({ name: "tenant_id", type: "uuid", notNull: true });
|
|
512
|
+
expect(pgTable(t).primaryKey?.columns).toEqual(["tenant_id", "id"]);
|
|
513
|
+
expect(byTenant.props.name).toBe("notes_tenant_idx");
|
|
514
|
+
expect(byTenant.props.elements.map((e) => e.column)).toEqual(["tenant_id", "id"]);
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
test("the tenant column, its type and a compound key are parameters", () => {
|
|
518
|
+
const { table: t, index: byTenant } = TenantTable({
|
|
519
|
+
name: "notes",
|
|
520
|
+
columns: "a int NOT NULL, b int NOT NULL, at timestamptz",
|
|
521
|
+
primaryKey: "a, b",
|
|
522
|
+
indexOn: "at DESC",
|
|
523
|
+
tenant: "org_id",
|
|
524
|
+
tenantType: "bigint",
|
|
525
|
+
});
|
|
526
|
+
expect(pgTable(t).columns[0]).toMatchObject({ name: "org_id", type: "bigint" });
|
|
527
|
+
expect(pgTable(t).primaryKey?.columns).toEqual(["org_id", "a", "b"]);
|
|
528
|
+
expect(byTenant.props.elements.map((e) => e.column)).toEqual(["org_id", "at"]);
|
|
529
|
+
});
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
describe("RefreshedView", () => {
|
|
533
|
+
test("defaults: a materialized view over its source and a unique index on the grouping key", () => {
|
|
534
|
+
const source = users().table;
|
|
535
|
+
const { view, uniqueIndex } = RefreshedView({ name: "by_email", schema: "app", source, select: "email, count(*) AS n", groupBy: "email" });
|
|
536
|
+
expect(view.entityType).toBe(POSTGRES_ENTITY_TYPES.materializedView);
|
|
537
|
+
expect(pgDdl(view)).toBe("CREATE MATERIALIZED VIEW app.by_email AS SELECT email, count(*) AS n FROM app.users GROUP BY email");
|
|
538
|
+
expect(view.props.reads).toEqual([source]);
|
|
539
|
+
expect(view.dependsOn).toContain(source);
|
|
540
|
+
expect(uniqueIndex.props.unique).toBe(true);
|
|
541
|
+
expect(uniqueIndex.props.name).toBe("by_email_key");
|
|
542
|
+
expect(uniqueIndex.props.elements.map((e) => e.column)).toEqual(["email"]);
|
|
543
|
+
expect(uniqueIndex.dependsOn).toEqual([view]);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
test("the unique index's columns are a parameter", () => {
|
|
547
|
+
const { uniqueIndex } = RefreshedView({
|
|
548
|
+
name: "daily",
|
|
549
|
+
source: users().table,
|
|
550
|
+
select: "email, id, count(*) AS n",
|
|
551
|
+
groupBy: "email, id",
|
|
552
|
+
uniqueOn: "id, email",
|
|
553
|
+
});
|
|
554
|
+
expect(uniqueIndex.props.elements.map((e) => e.column)).toEqual(["id", "email"]);
|
|
555
|
+
});
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
test("a prop that is not valid SQL is refused at the interpolation that carried it", () => {
|
|
559
|
+
expect(() => TenantTable({ name: "notes", columns: "id bigint NOT NULL, (", primaryKey: "id", indexOn: "id" })).toThrow(SqlTemplateError);
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
test("SQLPG101 to SQLPG118 find nothing in any of them", () => {
|
|
563
|
+
const people = users();
|
|
564
|
+
const teams = SoftDeleteTable({ name: "teams", schema: "app", columns: "id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name text NOT NULL" });
|
|
565
|
+
const members = JoinTable({ name: "memberships", schema: "app", left: people.table, leftColumn: "user_id", right: teams.table, rightColumn: "team_id" });
|
|
566
|
+
const instances: Array<[string, CompositeInstance]> = [
|
|
567
|
+
["users", people],
|
|
568
|
+
["teams", teams],
|
|
569
|
+
["audit", AuditLogTable({ name: "audit", schema: "app" })],
|
|
570
|
+
["memberships", members],
|
|
571
|
+
[
|
|
572
|
+
"notes",
|
|
573
|
+
TenantTable({ name: "notes", schema: "app", columns: "id bigint NOT NULL, body text, created_at timestamptz", primaryKey: "id", indexOn: "created_at DESC" }),
|
|
574
|
+
],
|
|
575
|
+
["sizes", RefreshedView({ name: "team_sizes", schema: "app", source: members.table, select: "team_id, count(*) AS members", groupBy: "team_id" })],
|
|
576
|
+
];
|
|
577
|
+
const entities = new Map<string, Declarable>([["app", schema`CREATE SCHEMA app` as unknown as Declarable]]);
|
|
578
|
+
for (const [name, instance] of instances) for (const [k, v] of expandComposite(name, instance)) entities.set(k, v);
|
|
579
|
+
|
|
580
|
+
const out = sqlSerializer.serialize(entities) as SerializerResult;
|
|
581
|
+
const doc = JSON.parse(out.primary) as { applyOrder: string[]; dialect: string };
|
|
582
|
+
expect(doc.dialect).toBe("postgres");
|
|
583
|
+
const at = (n: string) => doc.applyOrder.indexOf(n);
|
|
584
|
+
expect(at("usersTable")).toBeLessThan(at("membershipsTable"));
|
|
585
|
+
expect(at("membershipsTable")).toBeLessThan(at("sizesView"));
|
|
586
|
+
expect(at("sizesView")).toBeLessThan(at("sizesUniqueIndex"));
|
|
587
|
+
expect(at("auditTable")).toBeLessThan(at("auditDefaultPartition"));
|
|
588
|
+
|
|
589
|
+
const ctx = makePostSynthCtx("sql", out.primary, entities);
|
|
590
|
+
const checks = postSynthChecks.filter((c) => c.id.startsWith("SQLPG"));
|
|
591
|
+
expect(checks).toHaveLength(18);
|
|
592
|
+
expect(checks.flatMap((check) => check.check(ctx).map((d) => `${check.id} ${d.message}`))).toEqual([]);
|
|
593
|
+
});
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
// Provenance through the package import (#3246, #3268)
|
|
597
|
+
|
|
598
|
+
const PG_APP = `
|
|
599
|
+
import { schema } from "@intentius/chant-lexicon-sql/postgres";
|
|
600
|
+
|
|
601
|
+
export const app = schema\`CREATE SCHEMA app\`;
|
|
602
|
+
`;
|
|
603
|
+
|
|
604
|
+
const PG_ACCOUNTS = `
|
|
605
|
+
import { SoftDeleteTable, TenantTable } from "@intentius/chant-lexicon-sql/postgres";
|
|
606
|
+
import { app } from "./app";
|
|
607
|
+
|
|
608
|
+
export const users = SoftDeleteTable({ name: "users", schema: app, columns: "id bigint PRIMARY KEY, email text NOT NULL", liveKey: "email", deletedAt: "gone_at" });
|
|
609
|
+
export const notes = TenantTable({ name: "notes", schema: app, columns: "id bigint NOT NULL, body text", primaryKey: "id", indexOn: "id", tenant: "org_id" });
|
|
610
|
+
`;
|
|
611
|
+
|
|
612
|
+
const PG_LINKS = `
|
|
613
|
+
import { JoinTable } from "@intentius/chant-lexicon-sql/postgres";
|
|
614
|
+
import { app } from "./app";
|
|
615
|
+
import { notes, users } from "./accounts";
|
|
616
|
+
|
|
617
|
+
export const links = JoinTable({ name: "note_users", schema: app, left: notes.table, leftColumn: "note_id", right: users.table, rightColumn: "user_id" });
|
|
618
|
+
`;
|
|
619
|
+
|
|
620
|
+
const PG_SIZES = `
|
|
621
|
+
import { RefreshedView } from "@intentius/chant-lexicon-sql/postgres";
|
|
622
|
+
import { app } from "./app";
|
|
623
|
+
import { links } from "./links";
|
|
624
|
+
|
|
625
|
+
export const sizes = RefreshedView({ name: "sizes", schema: app, source: links.table, select: "user_id, count(*) AS notes", groupBy: "user_id" });
|
|
626
|
+
`;
|
|
627
|
+
|
|
628
|
+
describe("each Postgres field keeps its provenance when the composite is interpreted", () => {
|
|
629
|
+
let dir: string;
|
|
630
|
+
|
|
631
|
+
beforeAll(async () => {
|
|
632
|
+
const path = join(repoRoot, ".cache", `sql-3286-composites-${process.pid}`);
|
|
633
|
+
await rm(path, { recursive: true, force: true });
|
|
634
|
+
await mkdir(join(path, "src"), { recursive: true });
|
|
635
|
+
dir = await realpath(path);
|
|
636
|
+
await writeFile(join(dir, "src", "app.ts"), PG_APP);
|
|
637
|
+
await writeFile(join(dir, "src", "accounts.ts"), PG_ACCOUNTS);
|
|
638
|
+
await writeFile(join(dir, "src", "links.ts"), PG_LINKS);
|
|
639
|
+
await writeFile(join(dir, "src", "sizes.ts"), PG_SIZES);
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
afterAll(async () => {
|
|
643
|
+
await rm(dir, { recursive: true, force: true });
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
test("a field is the parameter that fed it, or fixed by the composite", async () => {
|
|
647
|
+
const result = await build(join(dir, "src"), [sqlSerializer], undefined, {
|
|
648
|
+
fold: true,
|
|
649
|
+
lexicons: ["sql"],
|
|
650
|
+
intrinsics: sqlPlugin.intrinsics?.() ?? [],
|
|
651
|
+
});
|
|
652
|
+
expect(result.errors).toEqual([]);
|
|
653
|
+
const src = join(dir, "src");
|
|
654
|
+
const sites = {
|
|
655
|
+
users: callSite(join(src, "accounts.ts"), PG_ACCOUNTS, "SoftDeleteTable({"),
|
|
656
|
+
notes: callSite(join(src, "accounts.ts"), PG_ACCOUNTS, "TenantTable({"),
|
|
657
|
+
links: callSite(join(src, "links.ts"), PG_LINKS, "JoinTable({"),
|
|
658
|
+
sizes: callSite(join(src, "sizes.ts"), PG_SIZES, "RefreshedView({"),
|
|
659
|
+
};
|
|
660
|
+
const param = paramAt(sites);
|
|
661
|
+
const fixed = fixedAt(sites);
|
|
662
|
+
|
|
663
|
+
const u = result.foldProvenance.usersTable!.fields;
|
|
664
|
+
expect(u.name).toEqual(param("SoftDeleteTable", "users", "name"));
|
|
665
|
+
expect(u.columns).toEqual(param("SoftDeleteTable", "users", "columns", "createdAt", "deletedAt", "updatedAt"));
|
|
666
|
+
expect(u.ddl).toEqual(expect.objectContaining({ kind: "composite-parameter", composite: "SoftDeleteTable" }));
|
|
667
|
+
expect(result.foldProvenance.usersLiveIndex!.fields.where).toEqual(param("SoftDeleteTable", "users", "deletedAt"));
|
|
668
|
+
|
|
669
|
+
const t = result.foldProvenance.notesTable!.fields;
|
|
670
|
+
expect(t.name).toEqual(param("TenantTable", "notes", "name"));
|
|
671
|
+
expect(t["primaryKey.columns"]).toEqual(param("TenantTable", "notes", "primaryKey", "tenant"));
|
|
672
|
+
expect(result.foldProvenance.notesIndex!.fields.elements).toEqual(param("TenantTable", "notes", "indexOn", "tenant"));
|
|
673
|
+
|
|
674
|
+
const l = result.foldProvenance.linksTable!.fields;
|
|
675
|
+
expect(l.name).toEqual(param("JoinTable", "links", "name"));
|
|
676
|
+
expect(l.foreignKeys).toEqual(param("JoinTable", "links", "leftKey", "rightKey"));
|
|
677
|
+
expect(l["primaryKey.columns"]).toEqual(param("JoinTable", "links", "leftColumn", "rightColumn"));
|
|
678
|
+
expect(result.foldProvenance.sizesView!.fields.query).toEqual(param("RefreshedView", "sizes", "groupBy", "select"));
|
|
679
|
+
expect(result.foldProvenance.sizesUniqueIndex!.fields.unique).toEqual(fixed("RefreshedView", "sizes"));
|
|
680
|
+
|
|
681
|
+
// A drift on a column the composite fixes is refused; one on the live-row
|
|
682
|
+
// predicate is a change to `deletedAt` at the `users` call.
|
|
683
|
+
const provenance = getProvenance(result.entities.get("usersLiveIndex")!);
|
|
684
|
+
const drift = (path: string, declared: unknown, live: unknown) =>
|
|
685
|
+
resolveDriftedField({ entity: "usersLiveIndex", path, declared, live, origin: originOfPath(provenance?.paths, path), provenance });
|
|
686
|
+
const where = drift("where", "gone_at IS NULL", "deleted_at IS NULL").resolution;
|
|
687
|
+
expect(where).toMatchObject({ kind: "propose-parameter", parameters: ["deletedAt"], instance: "users" });
|
|
688
|
+
expect(where.sourceFile).toContain("accounts.ts");
|
|
689
|
+
|
|
690
|
+
// Interpreting the package's composites writes what calling them writes.
|
|
691
|
+
const run = await build(join(dir, "src"), [sqlSerializer], undefined, {
|
|
692
|
+
fold: false,
|
|
693
|
+
lexicons: ["sql"],
|
|
694
|
+
intrinsics: sqlPlugin.intrinsics?.() ?? [],
|
|
695
|
+
});
|
|
696
|
+
expect(run.errors).toEqual([]);
|
|
697
|
+
expect(result.outputs.get("sql")).toEqual(run.outputs.get("sql"));
|
|
698
|
+
});
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
// Same-file entities as composite arguments (#3325)
|
|
702
|
+
|
|
703
|
+
/**
|
|
704
|
+
* The schema, two composite calls and a third call reading their members, all
|
|
705
|
+
* in one file: each call folds as it does with the arguments imported.
|
|
706
|
+
*/
|
|
707
|
+
const PG_ONE_FILE = `
|
|
708
|
+
import { schema, JoinTable, SoftDeleteTable, TenantTable } from "@intentius/chant-lexicon-sql/postgres";
|
|
709
|
+
|
|
710
|
+
export const app = schema\`CREATE SCHEMA app\`;
|
|
711
|
+
export const users = SoftDeleteTable({ name: "users", schema: app, columns: "id bigint PRIMARY KEY, email text NOT NULL", liveKey: "email", deletedAt: "gone_at" });
|
|
712
|
+
export const notes = TenantTable({ name: "notes", schema: app, columns: "id bigint NOT NULL, body text", primaryKey: "id", indexOn: "id", tenant: "org_id" });
|
|
713
|
+
export const links = JoinTable({ name: "note_users", schema: app, left: notes.table, leftColumn: "note_id", right: users.table, rightColumn: "user_id" });
|
|
714
|
+
`;
|
|
715
|
+
|
|
716
|
+
describe("a composite call whose argument is a same-file entity folds (#3325)", () => {
|
|
717
|
+
let dir: string;
|
|
718
|
+
|
|
719
|
+
beforeAll(async () => {
|
|
720
|
+
const path = join(repoRoot, ".cache", `sql-3325-composites-${process.pid}`);
|
|
721
|
+
await rm(path, { recursive: true, force: true });
|
|
722
|
+
await mkdir(join(path, "src"), { recursive: true });
|
|
723
|
+
dir = await realpath(path);
|
|
724
|
+
await writeFile(join(dir, "src", "app.ts"), PG_ONE_FILE);
|
|
725
|
+
});
|
|
726
|
+
|
|
727
|
+
afterAll(async () => {
|
|
728
|
+
await rm(dir, { recursive: true, force: true });
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
test("each field keeps its parameter, and the output is what running writes", async () => {
|
|
732
|
+
const options = { lexicons: ["sql"], intrinsics: sqlPlugin.intrinsics?.() ?? [] };
|
|
733
|
+
const result = await build(join(dir, "src"), [sqlSerializer], undefined, { ...options, fold: true });
|
|
734
|
+
expect(result.errors).toEqual([]);
|
|
735
|
+
expect(result.foldDecisions.map((d) => [d.mode, d.reason])).toEqual([["fold", undefined]]);
|
|
736
|
+
const file = join(dir, "src", "app.ts");
|
|
737
|
+
const sites = {
|
|
738
|
+
users: callSite(file, PG_ONE_FILE, "SoftDeleteTable({"),
|
|
739
|
+
notes: callSite(file, PG_ONE_FILE, "TenantTable({"),
|
|
740
|
+
links: callSite(file, PG_ONE_FILE, "JoinTable({"),
|
|
741
|
+
};
|
|
742
|
+
const param = paramAt(sites);
|
|
743
|
+
|
|
744
|
+
const u = result.foldProvenance.usersTable!.fields;
|
|
745
|
+
expect(u.name).toEqual(param("SoftDeleteTable", "users", "name"));
|
|
746
|
+
expect(u.columns).toEqual(param("SoftDeleteTable", "users", "columns", "createdAt", "deletedAt", "updatedAt"));
|
|
747
|
+
expect(result.foldProvenance.usersLiveIndex!.fields.where).toEqual(param("SoftDeleteTable", "users", "deletedAt"));
|
|
748
|
+
expect(result.foldProvenance.notesTable!.fields["primaryKey.columns"]).toEqual(param("TenantTable", "notes", "primaryKey", "tenant"));
|
|
749
|
+
const l = result.foldProvenance.linksTable!.fields;
|
|
750
|
+
expect(l.name).toEqual(param("JoinTable", "links", "name"));
|
|
751
|
+
expect(l.foreignKeys).toEqual(param("JoinTable", "links", "leftKey", "rightKey"));
|
|
752
|
+
expect(l["primaryKey.columns"]).toEqual(param("JoinTable", "links", "leftColumn", "rightColumn"));
|
|
753
|
+
|
|
754
|
+
const run = await build(join(dir, "src"), [sqlSerializer], undefined, { ...options, fold: false });
|
|
755
|
+
expect(run.errors).toEqual([]);
|
|
756
|
+
expect(result.outputs.get("sql")).toEqual(run.outputs.get("sql"));
|
|
757
|
+
});
|
|
758
|
+
});
|