@intentius/chant-lexicon-sql 0.0.0-stage → 0.112.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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,115 @@
|
|
|
1
|
+
import type { LintContext, LintDiagnostic, LintRule } from "@intentius/chant/lint/rule";
|
|
2
|
+
import { parseCreate, unquote, type ColumnNode, type CreateNode, type Span } from "../../clickhouse/parser";
|
|
3
|
+
import { isTrivia, SqlSyntaxError, type Token } from "../../clickhouse/tokens";
|
|
4
|
+
import { findTemplates, tokenPosition, tokensOf } from "./templates";
|
|
5
|
+
|
|
6
|
+
/** The column's type, as written, reads `Nullable(...)`, also inside `LowCardinality(...)`. */
|
|
7
|
+
function isNullable(tokens: Token[], c: ColumnNode): boolean {
|
|
8
|
+
if (c.nullable === true) return true;
|
|
9
|
+
if (!c.type) return false;
|
|
10
|
+
const words = tokens.slice(c.type.from, c.type.to).filter((t) => t.kind === "ident").map((t) => t.text.toLowerCase());
|
|
11
|
+
return words[0] === "nullable" || (words[0] === "lowcardinality" && words[1] === "nullable");
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The column names a key names as a key part: bare, or inside the key's tuple
|
|
16
|
+
* parentheses, not an argument of a function (`ifNull(a, '')` makes a
|
|
17
|
+
* non-Nullable key part of a Nullable column) and not a qualified part.
|
|
18
|
+
*/
|
|
19
|
+
function keyColumns(tokens: Token[], span: Span): Array<{ name: string; token: Token }> {
|
|
20
|
+
const sig = tokens.slice(span.from, span.to).filter((t) => !isTrivia(t));
|
|
21
|
+
const out: Array<{ name: string; token: Token }> = [];
|
|
22
|
+
const frames: boolean[] = []; // true for a function call's parentheses
|
|
23
|
+
sig.forEach((t, i) => {
|
|
24
|
+
const prev = sig[i - 1];
|
|
25
|
+
if (t.kind === "punct" && t.text === "(") {
|
|
26
|
+
frames.push(prev !== undefined && (prev.kind === "ident" || prev.kind === "qident"));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (t.kind === "punct" && t.text === ")") {
|
|
30
|
+
frames.pop();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (t.kind !== "ident" && t.kind !== "qident") return;
|
|
34
|
+
if (frames.includes(true)) return;
|
|
35
|
+
const next = sig[i + 1];
|
|
36
|
+
if (next?.kind === "punct" && next.text === "(") return;
|
|
37
|
+
if (prev?.kind === "punct" && prev.text === ".") return;
|
|
38
|
+
out.push({ name: unquote(t.text), token: t });
|
|
39
|
+
});
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function allowsNullableKey(tokens: Token[], node: CreateNode): boolean {
|
|
44
|
+
if (node.statement === "database" || !node.settings) return false;
|
|
45
|
+
const s = node.settings.find((x) => x.key === "allow_nullable_key");
|
|
46
|
+
if (!s) return false;
|
|
47
|
+
const v = tokens.slice(s.value.from, s.value.to).map((t) => t.text).join("").trim().toLowerCase().replace(/'/g, "");
|
|
48
|
+
return v === "1" || v === "true";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* SQLCH002: a `Nullable` column in a table's sort key or primary key.
|
|
53
|
+
*
|
|
54
|
+
* ClickHouse refuses to create the table ("Sorting key contains nullable
|
|
55
|
+
* columns") unless the table sets `allow_nullable_key = 1`, and with it a
|
|
56
|
+
* `NULL` sorts as a value of its own. The rule reads the types written in the
|
|
57
|
+
* column list; a key over a column of an inferred type is left to the server.
|
|
58
|
+
*/
|
|
59
|
+
export const sqlch002: LintRule = {
|
|
60
|
+
id: "SQLCH002",
|
|
61
|
+
severity: "error",
|
|
62
|
+
category: "correctness",
|
|
63
|
+
description: "A Nullable column in a ClickHouse sort key or primary key",
|
|
64
|
+
|
|
65
|
+
check(context: LintContext): LintDiagnostic[] {
|
|
66
|
+
const source = context.sourceFile;
|
|
67
|
+
const out: LintDiagnostic[] = [];
|
|
68
|
+
for (const found of findTemplates(source)) {
|
|
69
|
+
const tokens = tokensOf(found);
|
|
70
|
+
let node: CreateNode;
|
|
71
|
+
try {
|
|
72
|
+
node = parseCreate(tokens);
|
|
73
|
+
} catch (err) {
|
|
74
|
+
if (err instanceof SqlSyntaxError) continue; // SQLCH001 reports it
|
|
75
|
+
throw err;
|
|
76
|
+
}
|
|
77
|
+
if (node.statement === "database" || allowsNullableKey(tokens, node)) continue;
|
|
78
|
+
const nullable = new Set(node.columns.filter((c) => c.name && isNullable(tokens, c)).map((c) => c.name));
|
|
79
|
+
if (nullable.size === 0) continue;
|
|
80
|
+
const reported = new Set<string>();
|
|
81
|
+
for (const [clause, span] of [
|
|
82
|
+
["sort key", node.orderBy],
|
|
83
|
+
["primary key", node.primaryKey],
|
|
84
|
+
] as const) {
|
|
85
|
+
if (!span) continue;
|
|
86
|
+
for (const { name, token } of keyColumns(tokens, span)) {
|
|
87
|
+
if (!nullable.has(name) || reported.has(`${clause}:${name}`)) continue;
|
|
88
|
+
reported.add(`${clause}:${name}`);
|
|
89
|
+
out.push({
|
|
90
|
+
ruleId: "SQLCH002",
|
|
91
|
+
severity: "error",
|
|
92
|
+
message:
|
|
93
|
+
`column "${name}" is Nullable and is in the ${clause}; ClickHouse refuses this unless the table ` +
|
|
94
|
+
"sets allow_nullable_key = 1. Make the column non-Nullable (a default such as '' or 0 in place of NULL), " +
|
|
95
|
+
"or drop it from the key",
|
|
96
|
+
file: context.filePath,
|
|
97
|
+
...tokenPosition(source, found, token),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
for (const c of node.columns) {
|
|
102
|
+
if (c.primaryKey && nullable.has(c.name)) {
|
|
103
|
+
out.push({
|
|
104
|
+
ruleId: "SQLCH002",
|
|
105
|
+
severity: "error",
|
|
106
|
+
message: `column "${c.name}" is Nullable and is declared PRIMARY KEY; ClickHouse refuses this unless the table sets allow_nullable_key = 1`,
|
|
107
|
+
file: context.filePath,
|
|
108
|
+
...tokenPosition(source, found, tokens[c.nameSpan.from]!),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return out;
|
|
114
|
+
},
|
|
115
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
import type { LintContext, LintDiagnostic, LintRule } from "@intentius/chant/lint/rule";
|
|
3
|
+
import { findTemplates } from "./templates";
|
|
4
|
+
|
|
5
|
+
/** The entity's own members: an interpolation of one of them is never a column. */
|
|
6
|
+
const OWN_MEMBERS = new Set(["kind", "lexicon", "entityType", "props", "sqlName", "dependsOn"]);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Identifiers that hold a ClickHouse entity, as far as one file can tell:
|
|
10
|
+
* bound to a sql tag here, or imported from another file of the project.
|
|
11
|
+
*/
|
|
12
|
+
function entityBindings(source: ts.SourceFile, tagged: Set<ts.Node>): Set<string> {
|
|
13
|
+
const out = new Set<string>();
|
|
14
|
+
for (const stmt of source.statements) {
|
|
15
|
+
if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier) && stmt.moduleSpecifier.text.startsWith(".")) {
|
|
16
|
+
const named = stmt.importClause?.namedBindings;
|
|
17
|
+
if (named && ts.isNamedImports(named)) for (const el of named.elements) out.add(el.name.text);
|
|
18
|
+
}
|
|
19
|
+
if (ts.isVariableStatement(stmt)) {
|
|
20
|
+
for (const d of stmt.declarationList.declarations) {
|
|
21
|
+
if (ts.isIdentifier(d.name) && d.initializer && tagged.has(d.initializer)) out.add(d.name.text);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* SQLCH003: a column written as `${events.kind}` instead of `${events.columns.kind}`.
|
|
30
|
+
*
|
|
31
|
+
* Columns are reached through `.columns`. `kind`, `lexicon`, `entityType`,
|
|
32
|
+
* `props`, `sqlName` and `dependsOn` are the entity's own fields, so
|
|
33
|
+
* `${events.kind}` is the string `"resource"`, which the tag splices in as SQL
|
|
34
|
+
* text: the statement builds and means something else. This rule flags it for
|
|
35
|
+
* an entity the file declares or imports from another project file.
|
|
36
|
+
*/
|
|
37
|
+
export const sqlch003: LintRule = {
|
|
38
|
+
id: "SQLCH003",
|
|
39
|
+
severity: "error",
|
|
40
|
+
category: "correctness",
|
|
41
|
+
description: "A column interpolated without .columns reads the entity's own field instead",
|
|
42
|
+
|
|
43
|
+
check(context: LintContext): LintDiagnostic[] {
|
|
44
|
+
const source = context.sourceFile;
|
|
45
|
+
const found = findTemplates(source);
|
|
46
|
+
if (found.length === 0) return [];
|
|
47
|
+
const entities = entityBindings(source, new Set(found.map((f) => f.node)));
|
|
48
|
+
const out: LintDiagnostic[] = [];
|
|
49
|
+
for (const f of found) {
|
|
50
|
+
for (const expr of f.expressions) {
|
|
51
|
+
if (!ts.isPropertyAccessExpression(expr) || !ts.isIdentifier(expr.expression)) continue;
|
|
52
|
+
const owner = expr.expression.text;
|
|
53
|
+
const member = expr.name.text;
|
|
54
|
+
if (!entities.has(owner) || !OWN_MEMBERS.has(member)) continue;
|
|
55
|
+
const { line, character } = source.getLineAndCharacterOfPosition(expr.getStart(source));
|
|
56
|
+
out.push({
|
|
57
|
+
ruleId: "SQLCH003",
|
|
58
|
+
severity: "error",
|
|
59
|
+
message: `\${${owner}.${member}} is the entity's own "${member}" field, not a column; write \${${owner}.columns.${member}}`,
|
|
60
|
+
file: context.filePath,
|
|
61
|
+
line: line + 1,
|
|
62
|
+
column: character + 1,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { LintContext, LintDiagnostic, LintRule } from "@intentius/chant/lint/rule";
|
|
2
|
+
import { parseStatements, SqlSyntaxError } from "../../postgres/parser";
|
|
3
|
+
import { STATEMENT_NAMES, type PostgresTag } from "../../postgres/entities";
|
|
4
|
+
import { findPostgresTemplates, postgresTokensOf, templatePosition, tokenPosition } from "./postgres-templates";
|
|
5
|
+
|
|
6
|
+
/** The statement each tag holds. */
|
|
7
|
+
const STATEMENT: Record<PostgresTag, string> = {
|
|
8
|
+
schema: "schema",
|
|
9
|
+
table: "table",
|
|
10
|
+
index: "index",
|
|
11
|
+
view: "view",
|
|
12
|
+
sequence: "sequence",
|
|
13
|
+
type: "enum",
|
|
14
|
+
domain: "domain",
|
|
15
|
+
extension: "extension",
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const TAG_OF: Record<string, PostgresTag> = Object.fromEntries(Object.entries(STATEMENT).map(([tag, statement]) => [statement, tag as PostgresTag]));
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* SQLPG001: the DDL in a Postgres template does not parse, or does not hold
|
|
22
|
+
* what its tag declares.
|
|
23
|
+
*
|
|
24
|
+
* The same parse runs when the build calls the tag, and fails the build there.
|
|
25
|
+
* This rule reports it in the editor and in `chant lint`, at the token, as a
|
|
26
|
+
* line and column of the `.ts` file, before anything is built. It also reports
|
|
27
|
+
* what the tag refuses after parsing: another statement than the tag's, a
|
|
28
|
+
* second CREATE in one template, and an index with no name (its name is its
|
|
29
|
+
* identity on the server). Interpolations are references here, since lint
|
|
30
|
+
* cannot know their values, so an error inside text a string interpolation
|
|
31
|
+
* supplies is left to the build.
|
|
32
|
+
*/
|
|
33
|
+
export const sqlpg001: LintRule = {
|
|
34
|
+
id: "SQLPG001",
|
|
35
|
+
severity: "error",
|
|
36
|
+
category: "correctness",
|
|
37
|
+
description: "Postgres DDL in a tagged template does not parse, or holds another statement than its tag",
|
|
38
|
+
|
|
39
|
+
check(context: LintContext): LintDiagnostic[] {
|
|
40
|
+
const source = context.sourceFile;
|
|
41
|
+
const out: LintDiagnostic[] = [];
|
|
42
|
+
const report = (message: string, at: { line: number; column: number }) =>
|
|
43
|
+
out.push({ ruleId: "SQLPG001", severity: "error", message, file: context.filePath, ...at });
|
|
44
|
+
for (const found of findPostgresTemplates(source)) {
|
|
45
|
+
const tokens = (() => {
|
|
46
|
+
try {
|
|
47
|
+
return postgresTokensOf(found);
|
|
48
|
+
} catch (err) {
|
|
49
|
+
if (!(err instanceof SqlSyntaxError)) throw err;
|
|
50
|
+
report(`Postgres DDL does not parse: ${err.message}`, templatePosition(source, found, err.part, err.offset));
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
})();
|
|
54
|
+
if (!tokens) continue;
|
|
55
|
+
try {
|
|
56
|
+
const [node, ...rest] = parseStatements(tokens);
|
|
57
|
+
if (node!.statement !== STATEMENT[found.tag]) {
|
|
58
|
+
const use = TAG_OF[node!.statement];
|
|
59
|
+
report(
|
|
60
|
+
use
|
|
61
|
+
? `${found.tag}\`...\` holds a ${STATEMENT_NAMES[node!.statement]}; use the ${use} tag`
|
|
62
|
+
: `${found.tag}\`...\` starts with a COMMENT ON; it goes after the CREATE it comments on`,
|
|
63
|
+
templatePosition(source, found, 0, 0),
|
|
64
|
+
);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const stray = rest.find((n) => n.statement !== "comment");
|
|
68
|
+
if (stray) {
|
|
69
|
+
report(
|
|
70
|
+
`${found.tag}\`...\` holds a second statement (${STATEMENT_NAMES[stray.statement]}); a template declares one object, followed only by COMMENT ON statements for it`,
|
|
71
|
+
templatePosition(source, found, 0, 0),
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
if (node!.statement === "index" && !node!.name) {
|
|
75
|
+
const on = tokens.find((t) => t.kind === "ident" && t.text.toUpperCase() === "ON");
|
|
76
|
+
report(
|
|
77
|
+
"an index needs a name: the name is its identity on the server, and an unnamed index gets a generated one",
|
|
78
|
+
on ? tokenPosition(source, found, on) : templatePosition(source, found, 0, 0),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
} catch (err) {
|
|
82
|
+
if (!(err instanceof SqlSyntaxError)) throw err;
|
|
83
|
+
report(`Postgres DDL does not parse: ${err.message}`, err.token ? tokenPosition(source, found, err.token) : templatePosition(source, found, err.part, err.offset));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return out;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as ts from "typescript";
|
|
2
|
+
import type { LintContext, LintDiagnostic, LintRule } from "@intentius/chant/lint/rule";
|
|
3
|
+
import { findPostgresTemplates as findTemplates } from "./postgres-templates";
|
|
4
|
+
|
|
5
|
+
/** The entity's own members: an interpolation of one of them is never a column. */
|
|
6
|
+
const OWN_MEMBERS = new Set(["kind", "lexicon", "entityType", "props", "sqlName", "dependsOn"]);
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Identifiers that hold a Postgres entity, as far as one file can tell:
|
|
10
|
+
* bound to a sql tag here, or imported from another file of the project.
|
|
11
|
+
*/
|
|
12
|
+
function entityBindings(source: ts.SourceFile, tagged: Set<ts.Node>): Set<string> {
|
|
13
|
+
const out = new Set<string>();
|
|
14
|
+
for (const stmt of source.statements) {
|
|
15
|
+
if (ts.isImportDeclaration(stmt) && ts.isStringLiteral(stmt.moduleSpecifier) && stmt.moduleSpecifier.text.startsWith(".")) {
|
|
16
|
+
const named = stmt.importClause?.namedBindings;
|
|
17
|
+
if (named && ts.isNamedImports(named)) for (const el of named.elements) out.add(el.name.text);
|
|
18
|
+
}
|
|
19
|
+
if (ts.isVariableStatement(stmt)) {
|
|
20
|
+
for (const d of stmt.declarationList.declarations) {
|
|
21
|
+
if (ts.isIdentifier(d.name) && d.initializer && tagged.has(d.initializer)) out.add(d.name.text);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* SQLPG002: a column written as `${events.kind}` instead of `${events.columns.kind}`.
|
|
30
|
+
*
|
|
31
|
+
* Columns are reached through `.columns`. `kind`, `lexicon`, `entityType`,
|
|
32
|
+
* `props`, `sqlName` and `dependsOn` are the entity's own fields, so
|
|
33
|
+
* `${events.kind}` is the string `"resource"`, which the tag splices in as SQL
|
|
34
|
+
* text: the statement builds and means something else. This rule flags it for
|
|
35
|
+
* an entity the file declares or imports from another project file.
|
|
36
|
+
*/
|
|
37
|
+
export const sqlpg002: LintRule = {
|
|
38
|
+
id: "SQLPG002",
|
|
39
|
+
severity: "error",
|
|
40
|
+
category: "correctness",
|
|
41
|
+
description: "A column interpolated without .columns reads the entity's own field instead",
|
|
42
|
+
|
|
43
|
+
check(context: LintContext): LintDiagnostic[] {
|
|
44
|
+
const source = context.sourceFile;
|
|
45
|
+
const found = findTemplates(source);
|
|
46
|
+
if (found.length === 0) return [];
|
|
47
|
+
const entities = entityBindings(source, new Set(found.map((f) => f.node)));
|
|
48
|
+
const out: LintDiagnostic[] = [];
|
|
49
|
+
for (const f of found) {
|
|
50
|
+
for (const expr of f.expressions) {
|
|
51
|
+
if (!ts.isPropertyAccessExpression(expr) || !ts.isIdentifier(expr.expression)) continue;
|
|
52
|
+
const owner = expr.expression.text;
|
|
53
|
+
const member = expr.name.text;
|
|
54
|
+
if (!entities.has(owner) || !OWN_MEMBERS.has(member)) continue;
|
|
55
|
+
const { line, character } = source.getLineAndCharacterOfPosition(expr.getStart(source));
|
|
56
|
+
out.push({
|
|
57
|
+
ruleId: "SQLPG002",
|
|
58
|
+
severity: "error",
|
|
59
|
+
message: `\${${owner}.${member}} is the entity's own "${member}" field, not a column; write \${${owner}.columns.${member}}`,
|
|
60
|
+
file: context.filePath,
|
|
61
|
+
line: line + 1,
|
|
62
|
+
column: character + 1,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { LintContext, LintDiagnostic, LintRule } from "@intentius/chant/lint/rule";
|
|
2
|
+
import { isTrivia, SqlSyntaxError } from "../../postgres/tokens";
|
|
3
|
+
import { findPostgresTemplates, postgresTokensOf, tokenPosition } from "./postgres-templates";
|
|
4
|
+
|
|
5
|
+
const REGCLASS_FUNCTIONS = ["NEXTVAL", "CURRVAL", "SETVAL"];
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* SQLPG003: an object named in a string where Postgres reads a `regclass`:
|
|
9
|
+
* `nextval('app.ticket_seq')`, `currval(...)`, `setval(...)`, or
|
|
10
|
+
* `'app.ticket_seq'::regclass`.
|
|
11
|
+
*
|
|
12
|
+
* A name inside a string is text to the build, so it records no reference:
|
|
13
|
+
* the table does not depend on the sequence, the creation order can put the
|
|
14
|
+
* table first, and the create fails. Interpolating the object instead,
|
|
15
|
+
* `nextval(${ticketSeq})`, renders the same `regclass` literal the catalog
|
|
16
|
+
* prints (`nextval('app.ticket_seq'::regclass)`) and keeps the edge. A
|
|
17
|
+
* sequence another tool owns is the exception, which is why this is a
|
|
18
|
+
* warning.
|
|
19
|
+
*/
|
|
20
|
+
export const sqlpg003: LintRule = {
|
|
21
|
+
id: "SQLPG003",
|
|
22
|
+
severity: "warning",
|
|
23
|
+
category: "correctness",
|
|
24
|
+
description: "A sequence or relation named in a regclass string makes no reference; interpolate the object",
|
|
25
|
+
|
|
26
|
+
check(context: LintContext): LintDiagnostic[] {
|
|
27
|
+
const source = context.sourceFile;
|
|
28
|
+
const out: LintDiagnostic[] = [];
|
|
29
|
+
for (const found of findPostgresTemplates(source)) {
|
|
30
|
+
let tokens;
|
|
31
|
+
try {
|
|
32
|
+
tokens = postgresTokensOf(found);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
if (err instanceof SqlSyntaxError) continue;
|
|
35
|
+
throw err;
|
|
36
|
+
}
|
|
37
|
+
const sig = tokens.filter((t) => !isTrivia(t));
|
|
38
|
+
sig.forEach((t, k) => {
|
|
39
|
+
if (t.kind !== "string" || !t.text.startsWith("'")) return;
|
|
40
|
+
const prev = sig[k - 1];
|
|
41
|
+
const fn = sig[k - 2];
|
|
42
|
+
const inCall =
|
|
43
|
+
prev?.kind === "punct" && prev.text === "(" && fn?.kind === "ident" && REGCLASS_FUNCTIONS.includes(fn.text.toUpperCase());
|
|
44
|
+
const cast = sig[k + 1]?.kind === "op" && sig[k + 1]!.text === "::" && sig[k + 2]?.kind === "ident" && sig[k + 2]!.text.toLowerCase() === "regclass";
|
|
45
|
+
if (!inCall && !cast) return;
|
|
46
|
+
const named = t.text.slice(1, -1).replace(/''/g, "'");
|
|
47
|
+
const how = inCall ? `${fn!.text}(\${...})` : "${...}::regclass";
|
|
48
|
+
out.push({
|
|
49
|
+
ruleId: "SQLPG003",
|
|
50
|
+
severity: "warning",
|
|
51
|
+
message: `'${named}' names an object in a string, which records no reference, so the build can create this object before it; interpolate the declared object instead: ${how}`,
|
|
52
|
+
file: context.filePath,
|
|
53
|
+
...tokenPosition(source, found, t),
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
},
|
|
59
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { LintContext, LintDiagnostic, LintRule } from "@intentius/chant/lint/rule";
|
|
2
|
+
import { isTrivia, SqlSyntaxError, type Token } from "../../postgres/tokens";
|
|
3
|
+
import { isPostgresProvider, providerAllowsExtension, providerData } from "../../postgres/providers";
|
|
4
|
+
import type { PostgresProvider } from "../../postgres/providers";
|
|
5
|
+
import { findPostgresTemplates, postgresTokensOf, tokenPosition } from "./postgres-templates";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The provider a lint run is for: `sql.provider`, else the one provider every
|
|
9
|
+
* profile that names one agrees on. No answer (self-hosted, or profiles that
|
|
10
|
+
* disagree) leaves the rule silent. The lint engine passes the whole project
|
|
11
|
+
* config as `projectConfig`.
|
|
12
|
+
*/
|
|
13
|
+
export function providerFromConfig(config: unknown): PostgresProvider | undefined {
|
|
14
|
+
const sql = (config as { sql?: { provider?: unknown; profiles?: Record<string, { provider?: unknown }> } } | undefined)?.sql;
|
|
15
|
+
if (!sql) return undefined;
|
|
16
|
+
if (isPostgresProvider(sql.provider)) return sql.provider;
|
|
17
|
+
const named = new Set(Object.values(sql.profiles ?? {}).map((p) => p.provider).filter(isPostgresProvider));
|
|
18
|
+
return named.size === 1 ? [...named][0] : undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const unquote = (t: Token): string => (t.kind === "qident" ? t.text.slice(1, -1).replace(/""/g, '"') : t.text.toLowerCase());
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* SQLPG004: a declared extension the configured provider does not allow.
|
|
25
|
+
*
|
|
26
|
+
* `extension\`CREATE EXTENSION pg_stat_monitor\`` builds, and fails when
|
|
27
|
+
* applied to a provider whose list lacks it. The lists are the providers'
|
|
28
|
+
* documentation snapshots (see postgres/providers/types.ts), so a provider
|
|
29
|
+
* that added an extension since reports it here until the list is refreshed;
|
|
30
|
+
* disable the rule for that line. When a provider's list is partial, a name
|
|
31
|
+
* outside it is not reported.
|
|
32
|
+
*/
|
|
33
|
+
export const sqlpg004: LintRule = {
|
|
34
|
+
id: "SQLPG004",
|
|
35
|
+
severity: "error",
|
|
36
|
+
category: "correctness",
|
|
37
|
+
description: "A declared extension the configured Postgres provider does not allow",
|
|
38
|
+
|
|
39
|
+
check(context: LintContext): LintDiagnostic[] {
|
|
40
|
+
const provider = providerFromConfig(context.projectConfig);
|
|
41
|
+
if (!provider) return [];
|
|
42
|
+
const label = providerData(provider).label;
|
|
43
|
+
const source = context.sourceFile;
|
|
44
|
+
const out: LintDiagnostic[] = [];
|
|
45
|
+
for (const found of findPostgresTemplates(source)) {
|
|
46
|
+
if (found.tag !== "extension") continue;
|
|
47
|
+
let tokens: Token[];
|
|
48
|
+
try {
|
|
49
|
+
tokens = postgresTokensOf(found);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
if (err instanceof SqlSyntaxError) continue;
|
|
52
|
+
throw err;
|
|
53
|
+
}
|
|
54
|
+
const sig = tokens.filter((t) => !isTrivia(t));
|
|
55
|
+
const word = (k: number) => (sig[k]?.kind === "ident" ? sig[k]!.text.toUpperCase() : "");
|
|
56
|
+
if (word(0) !== "CREATE" || word(1) !== "EXTENSION") continue;
|
|
57
|
+
let k = 2;
|
|
58
|
+
if (word(k) === "IF" && word(k + 1) === "NOT" && word(k + 2) === "EXISTS") k += 3;
|
|
59
|
+
const nameToken = sig[k];
|
|
60
|
+
if (!nameToken || (nameToken.kind !== "ident" && nameToken.kind !== "qident")) continue;
|
|
61
|
+
const name = unquote(nameToken);
|
|
62
|
+
if (providerAllowsExtension(provider, name) !== false) continue;
|
|
63
|
+
out.push({
|
|
64
|
+
ruleId: "SQLPG004",
|
|
65
|
+
severity: "error",
|
|
66
|
+
message: `${label} does not allow the extension "${name}"; CREATE EXTENSION would fail there. Use an extension it lists, or change sql.provider`,
|
|
67
|
+
file: context.filePath,
|
|
68
|
+
...tokenPosition(source, found, nameToken),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
},
|
|
73
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Finding the ClickHouse tags in a source file, for the source-level rules
|
|
3
|
+
* (and the editor). A rule reads the template's raw parts straight from the
|
|
4
|
+
* TypeScript AST and parses them the way the tag does, with every
|
|
5
|
+
* interpolation left a reference: lint cannot know the values. The finder is
|
|
6
|
+
* the shared core's (`../../core/find-templates.ts`); a tag is ClickHouse's
|
|
7
|
+
* because of the module it is imported from.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type * as ts from "typescript";
|
|
11
|
+
import { tokenize, type Token } from "../../clickhouse/tokens";
|
|
12
|
+
import { findSqlTemplates, type FoundTemplate as SqlFoundTemplate, type TemplateSource } from "../../core/find-templates";
|
|
13
|
+
|
|
14
|
+
export { templatePosition, tokenPosition } from "../../core/find-templates";
|
|
15
|
+
|
|
16
|
+
export type SqlTag = "database" | "table" | "view";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The ClickHouse tags, by the modules they are imported from. The package
|
|
20
|
+
* root still exports them, so it counts as ClickHouse too.
|
|
21
|
+
*/
|
|
22
|
+
export const CLICKHOUSE_TEMPLATE_SOURCE: TemplateSource<SqlTag> = {
|
|
23
|
+
dialect: "clickhouse",
|
|
24
|
+
modules: ["@intentius/chant-lexicon-sql", "@intentius/chant-lexicon-sql/clickhouse"],
|
|
25
|
+
tags: ["database", "table", "view"],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type FoundTemplate = SqlFoundTemplate<SqlTag>;
|
|
29
|
+
|
|
30
|
+
/** Every ClickHouse template in the file (the shared core's finder). */
|
|
31
|
+
export function findTemplates(source: ts.SourceFile): FoundTemplate[] {
|
|
32
|
+
return findSqlTemplates(source, [CLICKHOUSE_TEMPLATE_SOURCE]);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const tokensOf = (found: FoundTemplate): Token[] => tokenize(found.parts);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which dialect a live read is for. A build holds one dialect, so a read of
|
|
3
|
+
* declared entities follows their types; a read with nothing declared (import)
|
|
4
|
+
* follows the binding: the environment's profile URL (`postgres://` is
|
|
5
|
+
* Postgres), else `sql.dialect`, else whichever of `POSTGRES_URL` and
|
|
6
|
+
* `CLICKHOUSE_URL` is set, else ClickHouse, the first dialect.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ChantConfig } from "@intentius/chant/config";
|
|
10
|
+
import type { SqlDialect } from "./dialects";
|
|
11
|
+
import { isPostgresUrl, loadSqlConfig } from "./postgres/live/bind";
|
|
12
|
+
|
|
13
|
+
export function dialectOfEntities(entities: ReadonlyMap<string, { entityType: string }> | undefined): SqlDialect {
|
|
14
|
+
for (const e of entities?.values() ?? []) if (e.entityType.startsWith("Postgres::")) return "postgres";
|
|
15
|
+
return "clickhouse";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function dialectOfBinding(input: {
|
|
19
|
+
environment?: string;
|
|
20
|
+
config?: Pick<ChantConfig, "sql">;
|
|
21
|
+
env?: Record<string, string | undefined>;
|
|
22
|
+
}): SqlDialect {
|
|
23
|
+
const env = input.env ?? process.env;
|
|
24
|
+
const profile = input.environment !== undefined ? input.config?.sql?.profiles?.[input.environment] : undefined;
|
|
25
|
+
if (profile) return isPostgresUrl(profile.url) ? "postgres" : "clickhouse";
|
|
26
|
+
const configured = input.config?.sql?.dialect;
|
|
27
|
+
const named = Array.isArray(configured) ? (configured.length === 1 ? configured[0] : undefined) : configured;
|
|
28
|
+
if (named) return named;
|
|
29
|
+
if (env.POSTGRES_URL && !env.CLICKHOUSE_URL) return "postgres";
|
|
30
|
+
return "clickhouse";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** The binding's dialect, loading the project config from `cwd` when none is passed. */
|
|
34
|
+
export async function resolveBindingDialect(options: { environment?: string; config?: Pick<ChantConfig, "sql">; cwd?: string; env?: Record<string, string | undefined> }): Promise<SqlDialect> {
|
|
35
|
+
const config = options.config ?? (await loadSqlConfig(options.cwd ?? process.cwd()));
|
|
36
|
+
return dialectOfBinding({ environment: options.environment, config, env: options.env });
|
|
37
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The ClickHouse catalog the editor and the MCP tools read: the committed
|
|
3
|
+
* snapshot of the pinned server's `system.*` tables, parsed once and indexed
|
|
4
|
+
* by name. No server is needed; the snapshot is what generation reads too.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFileSync } from "fs";
|
|
8
|
+
import { dirname, join } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
import { parseCatalog, type ClickHouseCatalog, type SettingRow } from "../spec/catalog";
|
|
11
|
+
|
|
12
|
+
const SNAPSHOT = join(dirname(fileURLToPath(import.meta.url)), "..", "spec", "clickhouse-catalog.snapshot.json");
|
|
13
|
+
|
|
14
|
+
export interface CatalogIndex {
|
|
15
|
+
catalog: ClickHouseCatalog;
|
|
16
|
+
/** Name lookups. Names a server treats case-insensitively are also keyed lowercased. */
|
|
17
|
+
engines: Map<string, ClickHouseCatalog["tableEngines"][number]>;
|
|
18
|
+
databaseEngines: Map<string, ClickHouseCatalog["databaseEngines"][number]>;
|
|
19
|
+
types: Map<string, ClickHouseCatalog["typeFamilies"][number]>;
|
|
20
|
+
codecs: Map<string, ClickHouseCatalog["codecs"][number]>;
|
|
21
|
+
indexTypes: Map<string, ClickHouseCatalog["skipIndexTypes"][number]>;
|
|
22
|
+
mergeTreeSettings: Map<string, SettingRow>;
|
|
23
|
+
querySettings: Map<string, SettingRow>;
|
|
24
|
+
functions: Map<string, ClickHouseCatalog["functions"][number]>;
|
|
25
|
+
formats: Map<string, ClickHouseCatalog["formats"][number]>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let cached: CatalogIndex | null = null;
|
|
29
|
+
|
|
30
|
+
const byName = <T extends { name: string }>(rows: readonly T[], foldCase?: (row: T) => boolean): Map<string, T> => {
|
|
31
|
+
const map = new Map<string, T>();
|
|
32
|
+
for (const row of rows) {
|
|
33
|
+
map.set(row.name, row);
|
|
34
|
+
if (foldCase?.(row)) map.set(row.name.toLowerCase(), row);
|
|
35
|
+
}
|
|
36
|
+
return map;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/** The catalog, or undefined when the snapshot cannot be read. */
|
|
40
|
+
export function catalogIndex(): CatalogIndex | undefined {
|
|
41
|
+
if (cached) return cached;
|
|
42
|
+
try {
|
|
43
|
+
const catalog = parseCatalog(readFileSync(SNAPSHOT, "utf-8"));
|
|
44
|
+
cached = {
|
|
45
|
+
catalog,
|
|
46
|
+
engines: byName(catalog.tableEngines),
|
|
47
|
+
databaseEngines: byName(catalog.databaseEngines),
|
|
48
|
+
types: byName(catalog.typeFamilies, (t) => t.caseInsensitive),
|
|
49
|
+
codecs: byName(catalog.codecs),
|
|
50
|
+
indexTypes: byName(catalog.skipIndexTypes),
|
|
51
|
+
mergeTreeSettings: byName(catalog.mergeTreeSettings),
|
|
52
|
+
querySettings: byName(catalog.querySettings),
|
|
53
|
+
functions: byName(catalog.functions, (f) => f.caseInsensitive),
|
|
54
|
+
formats: byName(catalog.formats),
|
|
55
|
+
};
|
|
56
|
+
return cached;
|
|
57
|
+
} catch {
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
}
|