@intentius/chant-lexicon-sql 0.124.46 → 0.124.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/change-set.d.ts +1 -1
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +2 -1
- package/dist/clickhouse/apply/statements.d.ts +9 -0
- package/dist/clickhouse/apply/statements.d.ts.map +1 -1
- package/dist/clickhouse/apply/statements.js +24 -0
- package/dist/clickhouse/import/live-export.d.ts +7 -3
- package/dist/clickhouse/import/live-export.d.ts.map +1 -1
- package/dist/clickhouse/import/live-export.js +21 -5
- package/dist/clickhouse/live/named-collections.d.ts +27 -0
- package/dist/clickhouse/live/named-collections.d.ts.map +1 -0
- package/dist/clickhouse/live/named-collections.js +53 -0
- package/dist/clickhouse/live/undeclarable.d.ts +15 -3
- package/dist/clickhouse/live/undeclarable.d.ts.map +1 -1
- package/dist/clickhouse/live/undeclarable.js +18 -4
- package/dist/clickhouse/named-collections.d.ts +83 -0
- package/dist/clickhouse/named-collections.d.ts.map +1 -0
- package/dist/clickhouse/named-collections.js +203 -0
- package/dist/clickhouse/parser.d.ts.map +1 -1
- package/dist/clickhouse/parser.js +1 -1
- package/dist/clickhouse/plan/commands.d.ts +2 -1
- package/dist/clickhouse/plan/commands.d.ts.map +1 -1
- package/dist/clickhouse/plan/commands.js +17 -2
- package/dist/clickhouse/plan/diff.d.ts +15 -0
- package/dist/clickhouse/plan/diff.d.ts.map +1 -1
- package/dist/clickhouse/plan/diff.js +43 -1
- package/dist/clickhouse/plan/disruption.d.ts.map +1 -1
- package/dist/clickhouse/plan/disruption.js +5 -0
- package/dist/clickhouse/plan/rebuild-handoff.d.ts.map +1 -1
- package/dist/clickhouse/plan/rebuild-handoff.js +4 -0
- package/dist/clickhouse/plan/report.d.ts.map +1 -1
- package/dist/clickhouse/plan/report.js +6 -1
- package/dist/clickhouse/plan/rules.d.ts +5 -1
- package/dist/clickhouse/plan/rules.d.ts.map +1 -1
- package/dist/clickhouse/plan/rules.js +7 -3
- package/dist/clickhouse/plan/stream.d.ts +40 -0
- package/dist/clickhouse/plan/stream.d.ts.map +1 -0
- package/dist/clickhouse/plan/stream.js +107 -0
- package/dist/clickhouse/rebuild/observe.d.ts +3 -1
- package/dist/clickhouse/rebuild/observe.d.ts.map +1 -1
- package/dist/clickhouse/rebuild/observe.js +14 -1
- package/dist/clickhouse/review-catalog.d.ts +213 -0
- package/dist/clickhouse/review-catalog.d.ts.map +1 -0
- package/dist/clickhouse/review-catalog.js +330 -0
- package/dist/codegen/classifier-page.d.ts.map +1 -1
- package/dist/codegen/classifier-page.js +21 -4
- package/dist/codegen/clickhouse-module.d.ts.map +1 -1
- package/dist/codegen/clickhouse-module.js +3 -0
- package/dist/codegen/coverage-page.d.ts.map +1 -1
- package/dist/codegen/coverage-page.js +5 -3
- package/dist/codegen/docs.js +1 -1
- package/dist/codegen/postgres-classifier-page.js +1 -1
- package/dist/codegen/registry.d.ts.map +1 -1
- package/dist/codegen/registry.js +5 -0
- package/dist/composites/catalog.d.ts.map +1 -1
- package/dist/composites/catalog.js +100 -0
- package/dist/composites/clickhouse.d.ts +2 -0
- package/dist/composites/clickhouse.d.ts.map +1 -1
- package/dist/composites/clickhouse.js +2 -0
- package/dist/composites/otel-tables.d.ts +100 -0
- package/dist/composites/otel-tables.d.ts.map +1 -0
- package/dist/composites/otel-tables.js +282 -0
- package/dist/composites/stream-ingest.d.ts +63 -0
- package/dist/composites/stream-ingest.d.ts.map +1 -0
- package/dist/composites/stream-ingest.js +39 -0
- package/dist/coverage/clickhouse.json +1 -1
- package/dist/coverage/postgres.json +7 -7
- package/dist/coverage.d.ts +16 -6
- package/dist/coverage.d.ts.map +1 -1
- package/dist/coverage.js +10 -5
- package/dist/drizzle-command.d.ts +17 -0
- package/dist/drizzle-command.d.ts.map +1 -0
- package/dist/drizzle-command.js +91 -0
- package/dist/drizzle.d.ts +70 -0
- package/dist/drizzle.d.ts.map +1 -0
- package/dist/drizzle.js +684 -0
- package/dist/files/clickhouse.d.ts.map +1 -1
- package/dist/files/clickhouse.js +8 -1
- package/dist/files/common.d.ts +13 -0
- package/dist/files/common.d.ts.map +1 -1
- package/dist/files/common.js +5 -0
- package/dist/files/postgres.js +12 -2
- package/dist/generated/clickhouse.d.ts +2 -0
- package/dist/generated/clickhouse.d.ts.map +1 -1
- package/dist/generated/clickhouse.js +2 -0
- package/dist/import-parser.d.ts +21 -1
- package/dist/import-parser.d.ts.map +1 -1
- package/dist/import-parser.js +79 -5
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/integrity.json +6 -5
- package/dist/lint/post-synth/audit-entries.d.ts.map +1 -1
- package/dist/lint/post-synth/audit-entries.js +1 -0
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/index.js +2 -0
- package/dist/lint/post-synth/sqlch128.d.ts +18 -0
- package/dist/lint/post-synth/sqlch128.d.ts.map +1 -0
- package/dist/lint/post-synth/sqlch128.js +222 -0
- package/dist/lint/rules/postgres-templates.js +2 -2
- package/dist/lsp/postgres-template.d.ts.map +1 -1
- package/dist/lsp/postgres-template.js +11 -0
- package/dist/manifest.json +1 -1
- package/dist/mcp/postgres.js +1 -1
- package/dist/meta.json +25 -0
- package/dist/migrate/from-postgres/detect.d.ts +4 -0
- package/dist/migrate/from-postgres/detect.d.ts.map +1 -0
- package/dist/migrate/from-postgres/detect.js +7 -0
- package/dist/migrate/from-postgres/emit.d.ts +26 -0
- package/dist/migrate/from-postgres/emit.d.ts.map +1 -0
- package/dist/migrate/from-postgres/emit.js +86 -0
- package/dist/migrate/from-postgres/index.d.ts +51 -0
- package/dist/migrate/from-postgres/index.d.ts.map +1 -0
- package/dist/migrate/from-postgres/index.js +115 -0
- package/dist/migrate/from-postgres/translate.d.ts +73 -0
- package/dist/migrate/from-postgres/translate.d.ts.map +1 -0
- package/dist/migrate/from-postgres/translate.js +261 -0
- package/dist/migrate/from-postgres/types.d.ts +51 -0
- package/dist/migrate/from-postgres/types.d.ts.map +1 -0
- package/dist/migrate/from-postgres/types.js +211 -0
- package/dist/migration-replay.d.ts +73 -0
- package/dist/migration-replay.d.ts.map +1 -0
- package/dist/migration-replay.js +294 -0
- package/dist/okf/index.md +6 -0
- package/dist/okf/rules/SQLCH128.md +11 -0
- package/dist/okf/types/PostgresForeignDataWrapper.md +9 -0
- package/dist/okf/types/PostgresForeignServer.md +9 -0
- package/dist/okf/types/PostgresOperator.md +9 -0
- package/dist/okf/types/PostgresPublication.md +9 -0
- package/dist/okf/types/PostgresStatistics.md +9 -0
- package/dist/op/activities/postgres-migration.d.ts.map +1 -1
- package/dist/op/activities/postgres-migration.js +4 -0
- package/dist/op/activity-contracts.d.ts +20 -0
- package/dist/op/activity-contracts.d.ts.map +1 -1
- package/dist/op/activity-contracts.js +2 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +36 -2
- package/dist/postgres/apply/apply.js +8 -1
- package/dist/postgres/apply/statements.d.ts.map +1 -1
- package/dist/postgres/apply/statements.js +87 -2
- package/dist/postgres/constraint-names.d.ts +30 -0
- package/dist/postgres/constraint-names.d.ts.map +1 -0
- package/dist/postgres/constraint-names.js +72 -0
- package/dist/postgres/entities.d.ts +110 -1
- package/dist/postgres/entities.d.ts.map +1 -1
- package/dist/postgres/entities.js +146 -0
- package/dist/postgres/entity-types.d.ts +5 -0
- package/dist/postgres/entity-types.d.ts.map +1 -1
- package/dist/postgres/entity-types.js +5 -0
- package/dist/postgres/import/generator.d.ts.map +1 -1
- package/dist/postgres/import/generator.js +50 -2
- package/dist/postgres/import/live-export.d.ts.map +1 -1
- package/dist/postgres/import/live-export.js +2 -0
- package/dist/postgres/live/catalog-kinds.d.ts +14 -0
- package/dist/postgres/live/catalog-kinds.d.ts.map +1 -1
- package/dist/postgres/live/catalog-kinds.js +206 -0
- package/dist/postgres/live/catalog.d.ts +2 -0
- package/dist/postgres/live/catalog.d.ts.map +1 -1
- package/dist/postgres/live/catalog.js +3 -1
- package/dist/postgres/live/describe-resources.d.ts.map +1 -1
- package/dist/postgres/live/describe-resources.js +10 -2
- package/dist/postgres/migrate/backfill.d.ts +2 -0
- package/dist/postgres/migrate/backfill.d.ts.map +1 -1
- package/dist/postgres/migrate/backfill.js +7 -1
- package/dist/postgres/migrate/carry.d.ts +45 -1
- package/dist/postgres/migrate/carry.d.ts.map +1 -1
- package/dist/postgres/migrate/carry.js +72 -8
- package/dist/postgres/migrate/observe.d.ts +28 -4
- package/dist/postgres/migrate/observe.d.ts.map +1 -1
- package/dist/postgres/migrate/observe.js +41 -12
- package/dist/postgres/migrate/op.d.ts +26 -1
- package/dist/postgres/migrate/op.d.ts.map +1 -1
- package/dist/postgres/migrate/op.js +3 -1
- package/dist/postgres/migrate/steps.d.ts +35 -2
- package/dist/postgres/migrate/steps.d.ts.map +1 -1
- package/dist/postgres/migrate/steps.js +158 -12
- package/dist/postgres/parser.d.ts +72 -1
- package/dist/postgres/parser.d.ts.map +1 -1
- package/dist/postgres/parser.js +194 -2
- package/dist/postgres/plan/deep.d.ts.map +1 -1
- package/dist/postgres/plan/deep.js +29 -1
- package/dist/postgres/plan/diff.d.ts.map +1 -1
- package/dist/postgres/plan/diff.js +39 -1
- package/dist/postgres/plan/normalize.d.ts +17 -2
- package/dist/postgres/plan/normalize.d.ts.map +1 -1
- package/dist/postgres/plan/normalize.js +109 -1
- package/dist/postgres/plan/rules.d.ts +1 -0
- package/dist/postgres/plan/rules.d.ts.map +1 -1
- package/dist/postgres/plan/rules.js +3 -2
- package/dist/postgres/plan/schema.js +1 -1
- package/dist/postgres/secret-options.d.ts +10 -0
- package/dist/postgres/secret-options.d.ts.map +1 -0
- package/dist/postgres/secret-options.js +9 -0
- package/dist/postgres/testing/roundtrip-schema.d.ts +3 -2
- package/dist/postgres/testing/roundtrip-schema.d.ts.map +1 -1
- package/dist/postgres/testing/roundtrip-schema.js +13 -1
- package/dist/postgres.d.ts +1 -1
- package/dist/postgres.d.ts.map +1 -1
- package/dist/postgres.js +1 -1
- package/dist/rules/audit-entries.ts +1 -0
- package/dist/rules/postgres-templates.ts +2 -2
- package/dist/rules/sqlch128.ts +230 -0
- package/dist/serializer.d.ts +5 -0
- package/dist/serializer.d.ts.map +1 -1
- package/dist/serializer.js +13 -2
- package/dist/sql-types-command.d.ts +13 -0
- package/dist/sql-types-command.d.ts.map +1 -1
- package/dist/sql-types-command.js +31 -16
- package/dist/sql-types.d.ts +22 -0
- package/dist/sql-types.d.ts.map +1 -1
- package/dist/sql-types.js +10 -6
- package/dist/sqlserver/lexer.d.ts +37 -0
- package/dist/sqlserver/lexer.d.ts.map +1 -0
- package/dist/sqlserver/lexer.js +254 -0
- package/dist/sqlserver/parse.d.ts +185 -0
- package/dist/sqlserver/parse.d.ts.map +1 -0
- package/dist/sqlserver/parse.js +767 -0
- package/dist/sqlserver/translate.d.ts +34 -0
- package/dist/sqlserver/translate.d.ts.map +1 -0
- package/dist/sqlserver/translate.js +495 -0
- package/dist/sqlserver/types.d.ts +44 -0
- package/dist/sqlserver/types.d.ts.map +1 -0
- package/dist/sqlserver/types.js +133 -0
- package/dist/sqlserver/validate.d.ts +31 -0
- package/dist/sqlserver/validate.d.ts.map +1 -0
- package/dist/sqlserver/validate.js +67 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +5 -0
- package/package.json +2 -2
- package/src/change-set.ts +2 -1
- package/src/clickhouse/apply/statements.ts +25 -0
- package/src/clickhouse/import/live-export.ts +20 -5
- package/src/clickhouse/live/named-collections.e2e.test.ts +88 -0
- package/src/clickhouse/live/named-collections.ts +61 -0
- package/src/clickhouse/live/undeclarable.e2e.test.ts +5 -3
- package/src/clickhouse/live/undeclarable.ts +20 -4
- package/src/clickhouse/named-collections.test.ts +187 -0
- package/src/clickhouse/named-collections.ts +224 -0
- package/src/clickhouse/parser.ts +2 -1
- package/src/clickhouse/plan/commands.ts +17 -2
- package/src/clickhouse/plan/diff.ts +57 -1
- package/src/clickhouse/plan/disruption.ts +5 -0
- package/src/clickhouse/plan/rebuild-handoff.ts +3 -0
- package/src/clickhouse/plan/report.ts +6 -1
- package/src/clickhouse/plan/rules.ts +14 -4
- package/src/clickhouse/plan/stream-s3queue.e2e.test.ts +148 -0
- package/src/clickhouse/plan/stream.test.ts +237 -0
- package/src/clickhouse/plan/stream.ts +111 -0
- package/src/clickhouse/rebuild/observe.ts +15 -1
- package/src/clickhouse/review-catalog.test.ts +181 -0
- package/src/clickhouse/review-catalog.ts +489 -0
- package/src/codegen/classifier-page.ts +21 -4
- package/src/codegen/clickhouse-module.ts +3 -0
- package/src/codegen/coverage-page.ts +5 -3
- package/src/codegen/docs.ts +1 -1
- package/src/codegen/postgres-classifier-page.ts +1 -1
- package/src/codegen/registry.ts +5 -0
- package/src/composites/catalog.test.ts +6 -1
- package/src/composites/catalog.ts +100 -0
- package/src/composites/clickhouse.ts +2 -0
- package/src/composites/composites.test.ts +1 -1
- package/src/composites/otel-tables.test.ts +118 -0
- package/src/composites/otel-tables.ts +339 -0
- package/src/composites/stream-ingest.test.ts +114 -0
- package/src/composites/stream-ingest.ts +82 -0
- package/src/core/undeclarable.test.ts +6 -5
- package/src/coverage/clickhouse.json +1 -1
- package/src/coverage/postgres.json +7 -7
- package/src/coverage.test.ts +27 -2
- package/src/coverage.ts +18 -7
- package/src/drizzle-command.ts +94 -0
- package/src/drizzle-kit.e2e.test.ts +89 -0
- package/src/drizzle-types.e2e.test.ts +67 -0
- package/src/drizzle.test.ts +358 -0
- package/src/drizzle.ts +737 -0
- package/src/files/clickhouse.ts +8 -1
- package/src/files/common.ts +14 -1
- package/src/files/postgres.ts +12 -2
- package/src/generated/clickhouse.ts +3 -0
- package/src/generated/lexicon-sql.json +25 -0
- package/src/import-parser.sqlserver.test.ts +92 -0
- package/src/import-parser.ts +79 -5
- package/src/index.ts +1 -1
- package/src/lint/post-synth/audit-entries.ts +1 -0
- package/src/lint/post-synth/index.ts +2 -0
- package/src/lint/post-synth/sqlch128.test.ts +107 -0
- package/src/lint/post-synth/sqlch128.ts +230 -0
- package/src/lint/rules/postgres-templates.ts +2 -2
- package/src/lsp/postgres-template.ts +11 -0
- package/src/mcp/postgres.ts +1 -1
- package/src/migrate/from-postgres/cli.test.ts +165 -0
- package/src/migrate/from-postgres/detect.ts +7 -0
- package/src/migrate/from-postgres/emit.ts +96 -0
- package/src/migrate/from-postgres/example.test.ts +205 -0
- package/src/migrate/from-postgres/index.ts +122 -0
- package/src/migrate/from-postgres/translate.test.ts +242 -0
- package/src/migrate/from-postgres/translate.ts +359 -0
- package/src/migrate/from-postgres/types.test.ts +116 -0
- package/src/migrate/from-postgres/types.ts +236 -0
- package/src/migrate/from-postgres/validate.e2e.test.ts +44 -0
- package/src/migrate/from-postgres/workspace.e2e.test.ts +114 -0
- package/src/migration-replay.e2e.test.ts +155 -0
- package/src/migration-replay.test.ts +173 -0
- package/src/migration-replay.ts +289 -0
- package/src/op/__snapshots__/watch-pipeline.test.ts.snap +2 -2
- package/src/op/activities/postgres-migration.ts +4 -0
- package/src/op/activity-contracts.ts +2 -0
- package/src/plugin.ts +37 -2
- package/src/postgres/apply/apply.ts +9 -1
- package/src/postgres/apply/statements.ts +74 -1
- package/src/postgres/constraint-names.ts +71 -0
- package/src/postgres/database-kinds.test.ts +384 -0
- package/src/postgres/entities.ts +266 -1
- package/src/postgres/entity-types.ts +5 -0
- package/src/postgres/import/generator.ts +42 -2
- package/src/postgres/import/live-export.ts +1 -0
- package/src/postgres/live/catalog-kinds.ts +223 -0
- package/src/postgres/live/catalog.ts +6 -1
- package/src/postgres/live/database-kinds.e2e.test.ts +164 -0
- package/src/postgres/live/describe-resources.ts +11 -2
- package/src/postgres/live/undeclarable.e2e.test.ts +13 -6
- package/src/postgres/migrate/backfill.ts +13 -1
- package/src/postgres/migrate/carry.ts +103 -8
- package/src/postgres/migrate/followups.e2e.test.ts +218 -0
- package/src/postgres/migrate/followups.test.ts +199 -0
- package/src/postgres/migrate/kinds.e2e.test.ts +5 -5
- package/src/postgres/migrate/observe.ts +53 -14
- package/src/postgres/migrate/op.ts +28 -1
- package/src/postgres/migrate/partition.e2e.test.ts +129 -0
- package/src/postgres/migrate/partition.test.ts +206 -0
- package/src/postgres/migrate/steps.ts +157 -12
- package/src/postgres/parser.ts +234 -2
- package/src/postgres/plan/deep.ts +28 -1
- package/src/postgres/plan/diff.ts +36 -1
- package/src/postgres/plan/normalize.ts +122 -1
- package/src/postgres/plan/rules.ts +10 -3
- package/src/postgres/plan/schema.ts +1 -1
- package/src/postgres/secret-options.ts +10 -0
- package/src/postgres/testing/roundtrip-schema.ts +13 -1
- package/src/postgres.ts +16 -0
- package/src/serializer.ts +13 -2
- package/src/skills/chant-sql-postgres-migration.md +3 -3
- package/src/skills/chant-sql-postgres.md +6 -1
- package/src/skills/chant-sql.md +2 -1
- package/src/sql-types-command.ts +38 -16
- package/src/sql-types.ts +11 -6
- package/src/sqlserver/fixture.test.ts +186 -0
- package/src/sqlserver/import-cli.test.ts +61 -0
- package/src/sqlserver/lexer.ts +260 -0
- package/src/sqlserver/parse.ts +865 -0
- package/src/sqlserver/translate.test.ts +396 -0
- package/src/sqlserver/translate.ts +558 -0
- package/src/sqlserver/types.test.ts +102 -0
- package/src/sqlserver/types.ts +154 -0
- package/src/sqlserver/validate.e2e.test.ts +32 -0
- package/src/sqlserver/validate.test.ts +49 -0
- package/src/sqlserver/validate.ts +76 -0
- package/src/validate.ts +5 -0
- package/src/workspace-kinds.test.ts +11 -0
- package/workspace-kinds.json +100 -2
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named collections, referenced by name (#4395).
|
|
3
|
+
*
|
|
4
|
+
* A named collection holds an integration's connection settings and its
|
|
5
|
+
* credentials. Those are the environment's, so chant never declares one and
|
|
6
|
+
* never reads its values (the coverage table's `referenced` status,
|
|
7
|
+
* `../coverage/clickhouse.json`). A declaration may name one where the server
|
|
8
|
+
* takes a collection in place of inline arguments:
|
|
9
|
+
*
|
|
10
|
+
* - an integration engine's first argument: `ENGINE = S3(lake_creds, format = 'Parquet')`,
|
|
11
|
+
* `ENGINE = Kafka(kafka_creds)`, a database's `ENGINE = PostgreSQL(pg_creds)`;
|
|
12
|
+
* - a table function's first argument: `AS s3(lake_creds)`, `SELECT ... FROM mysql(mysql_creds, table = 't')`;
|
|
13
|
+
* - a dictionary source's `NAME`: `SOURCE(MYSQL(NAME mysql_creds))`.
|
|
14
|
+
*
|
|
15
|
+
* The build records each reference (`namedCollections` on the object and on
|
|
16
|
+
* the document, `../serializer.ts`), and `chant sql plan` checks that every
|
|
17
|
+
* one exists on the server by name (`./plan/commands.ts`).
|
|
18
|
+
*/
|
|
19
|
+
import { DATABASE_ENGINES, TABLE_ENGINES, TABLE_FUNCTIONS } from "../generated/clickhouse.js";
|
|
20
|
+
import { unquoteWith } from "../core/cursor.js";
|
|
21
|
+
import { isTrivia, tokenizeText } from "./tokens.js";
|
|
22
|
+
/**
|
|
23
|
+
* The table and database engines whose first argument may be a named
|
|
24
|
+
* collection, as the 26.8 reference documents them for each engine.
|
|
25
|
+
* Filtered to the engines the pinned server has.
|
|
26
|
+
*/
|
|
27
|
+
const COLLECTION_ENGINE_NAMES = [
|
|
28
|
+
"S3",
|
|
29
|
+
"S3Queue",
|
|
30
|
+
"AzureBlobStorage",
|
|
31
|
+
"AzureQueue",
|
|
32
|
+
"Iceberg",
|
|
33
|
+
"IcebergS3",
|
|
34
|
+
"IcebergAzure",
|
|
35
|
+
"DeltaLake",
|
|
36
|
+
"DeltaLakeS3",
|
|
37
|
+
"DeltaLakeAzure",
|
|
38
|
+
"Hudi",
|
|
39
|
+
"Paimon",
|
|
40
|
+
"PaimonS3",
|
|
41
|
+
"HDFS",
|
|
42
|
+
"URL",
|
|
43
|
+
"Kafka",
|
|
44
|
+
"RabbitMQ",
|
|
45
|
+
"NATS",
|
|
46
|
+
"MySQL",
|
|
47
|
+
"PostgreSQL",
|
|
48
|
+
"MaterializedPostgreSQL",
|
|
49
|
+
"MongoDB",
|
|
50
|
+
"Redis",
|
|
51
|
+
"ArrowFlight",
|
|
52
|
+
"YTsaurus",
|
|
53
|
+
"DataLakeCatalog",
|
|
54
|
+
];
|
|
55
|
+
const ENGINES = { ...TABLE_ENGINES, ...DATABASE_ENGINES };
|
|
56
|
+
/** The engines a named collection may be the first argument of. */
|
|
57
|
+
export const COLLECTION_ENGINES = new Set(COLLECTION_ENGINE_NAMES.filter((n) => n in ENGINES));
|
|
58
|
+
/**
|
|
59
|
+
* The table functions a named collection may be the first argument of, lower
|
|
60
|
+
* case. A `...Cluster` function's first argument is the cluster, so those are
|
|
61
|
+
* left out.
|
|
62
|
+
*/
|
|
63
|
+
export const COLLECTION_FUNCTIONS = new Set(TABLE_FUNCTIONS.filter((f) => !/Cluster$/.test(f) && /^(s3|gcs|oss|cosn|url|hdfs|mysql|postgresql|mongodb|redis|remote|azureblobstorage|iceberg|deltalake|hudi|paimon|arrowflight|ytsaurus)/i.test(f)).map((f) => f.toLowerCase()));
|
|
64
|
+
/** `lake_creds` or `` `lake creds` ``: an identifier, not a string, a call or `key = value`. */
|
|
65
|
+
function identifierName(text) {
|
|
66
|
+
const t = text.trim();
|
|
67
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*$/.test(t))
|
|
68
|
+
return t.toUpperCase() === "NOSIGN" ? undefined : t;
|
|
69
|
+
if (/^`(?:[^`\\]|\\.)+`$/.test(t))
|
|
70
|
+
return unquoteWith(t, "`");
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
/** The collection an engine names in its first argument, when it is one of the engines that take one. */
|
|
74
|
+
export function engineCollection(engine) {
|
|
75
|
+
if (!engine || !COLLECTION_ENGINES.has(engine.name) || !engine.args || engine.args.length === 0)
|
|
76
|
+
return undefined;
|
|
77
|
+
return identifierName(engine.args[0]);
|
|
78
|
+
}
|
|
79
|
+
const significant = (text) => {
|
|
80
|
+
try {
|
|
81
|
+
return tokenizeText(text, 0).filter((t) => !isTrivia(t));
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return [];
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
/** The collections a SQL text's table function calls name: `s3(lake_creds, ...)`, `mysql(mysql_creds)`. */
|
|
88
|
+
export function functionCollections(text) {
|
|
89
|
+
const tokens = significant(text);
|
|
90
|
+
const out = [];
|
|
91
|
+
for (let i = 0; i + 3 < tokens.length; i++) {
|
|
92
|
+
const [fn, open, arg, after] = [tokens[i], tokens[i + 1], tokens[i + 2], tokens[i + 3]];
|
|
93
|
+
if (fn.kind !== "ident" || !COLLECTION_FUNCTIONS.has(fn.text.toLowerCase()))
|
|
94
|
+
continue;
|
|
95
|
+
if (open.kind !== "punct" || open.text !== "(")
|
|
96
|
+
continue;
|
|
97
|
+
if (tokens[i - 1]?.kind === "punct" && tokens[i - 1].text === ".")
|
|
98
|
+
continue;
|
|
99
|
+
if (arg.kind !== "ident" && arg.kind !== "qident")
|
|
100
|
+
continue;
|
|
101
|
+
if (after.kind !== "punct" || (after.text !== "," && after.text !== ")"))
|
|
102
|
+
continue;
|
|
103
|
+
const name = identifierName(arg.text);
|
|
104
|
+
if (name)
|
|
105
|
+
out.push(name);
|
|
106
|
+
}
|
|
107
|
+
return out;
|
|
108
|
+
}
|
|
109
|
+
/** The collection a dictionary source names: `MYSQL(NAME mysql_creds)`. */
|
|
110
|
+
export function sourceCollections(dataSource) {
|
|
111
|
+
const tokens = significant(dataSource);
|
|
112
|
+
const out = [];
|
|
113
|
+
for (let i = 0; i + 1 < tokens.length; i++) {
|
|
114
|
+
if (tokens[i].kind !== "ident" || tokens[i].text.toUpperCase() !== "NAME")
|
|
115
|
+
continue;
|
|
116
|
+
const v = tokens[i + 1];
|
|
117
|
+
if (v.kind === "ident" || v.kind === "qident")
|
|
118
|
+
out.push(v.kind === "qident" ? unquoteWith(v.text, '`"') : v.text);
|
|
119
|
+
else if (v.kind === "string")
|
|
120
|
+
out.push(unquoteWith(v.text, "'"));
|
|
121
|
+
}
|
|
122
|
+
return out;
|
|
123
|
+
}
|
|
124
|
+
/** Every named collection an object names, once each, in the order written. */
|
|
125
|
+
export function namedCollectionReferences(o) {
|
|
126
|
+
const names = [
|
|
127
|
+
...(engineCollection(o.engine) !== undefined ? [engineCollection(o.engine)] : []),
|
|
128
|
+
...(o.asFunction ? functionCollections(o.asFunction) : []),
|
|
129
|
+
...(o.select ? functionCollections(o.select) : []),
|
|
130
|
+
...(o.dataSource ? sourceCollections(o.dataSource) : []),
|
|
131
|
+
];
|
|
132
|
+
return [...new Set(names)];
|
|
133
|
+
}
|
|
134
|
+
/** `CREATE NAMED COLLECTION [IF NOT EXISTS] name ...`: the name, or undefined for another statement. */
|
|
135
|
+
export function createdCollectionName(sql) {
|
|
136
|
+
const m = /^\s*CREATE\s+NAMED\s+COLLECTION\s+(?:IF\s+NOT\s+EXISTS\s+)?(`(?:[^`\\]|\\.)+`|"(?:[^"\\]|\\.)+"|[A-Za-z_][A-Za-z0-9_]*)/i.exec(sql);
|
|
137
|
+
return m ? unquoteWith(m[1], '`"') : undefined;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The collections a whole statement names, read off its tokens: what
|
|
141
|
+
* {@link namedCollectionReferences} reads from a parsed declaration, for a
|
|
142
|
+
* statement import has only as text (`SHOW CREATE`).
|
|
143
|
+
*/
|
|
144
|
+
export function statementCollections(ddl) {
|
|
145
|
+
const tokens = significant(ddl);
|
|
146
|
+
const out = [];
|
|
147
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
148
|
+
const t = tokens[i];
|
|
149
|
+
if (t.kind !== "ident")
|
|
150
|
+
continue;
|
|
151
|
+
const word = t.text.toUpperCase();
|
|
152
|
+
if (word === "ENGINE" && tokens[i + 1]?.text === "=" && tokens[i + 3]?.text === "(") {
|
|
153
|
+
const engine = tokens[i + 2];
|
|
154
|
+
const arg = tokens[i + 4];
|
|
155
|
+
const after = tokens[i + 5];
|
|
156
|
+
if (COLLECTION_ENGINES.has(engine.text) && arg && (arg.kind === "ident" || arg.kind === "qident") && (after?.text === "," || after?.text === ")")) {
|
|
157
|
+
const name = identifierName(arg.text);
|
|
158
|
+
if (name)
|
|
159
|
+
out.push(name);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
else if (word === "SOURCE" && tokens[i + 1]?.text === "(") {
|
|
163
|
+
let depth = 0;
|
|
164
|
+
let j = i + 1;
|
|
165
|
+
for (; j < tokens.length; j++) {
|
|
166
|
+
if (tokens[j].text === "(")
|
|
167
|
+
depth++;
|
|
168
|
+
else if (tokens[j].text === ")" && --depth === 0)
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
out.push(...sourceCollections(tokens.slice(i + 2, j).map((x) => x.text).join(" ")));
|
|
172
|
+
i = j;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
out.push(...functionCollections(ddl));
|
|
176
|
+
return [...new Set(out)];
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* The named collections an import found as prerequisites (#4395), each with
|
|
180
|
+
* the imported objects that name it, and a warning for each. A collection an
|
|
181
|
+
* imported object names that was not found is listed too: a live reader
|
|
182
|
+
* without `SHOW NAMED COLLECTIONS` sees none.
|
|
183
|
+
*/
|
|
184
|
+
export function namedCollectionPrerequisites(found, objects, wording) {
|
|
185
|
+
const by = new Map(found.map((o) => [o.name, []]));
|
|
186
|
+
for (const o of objects) {
|
|
187
|
+
for (const c of statementCollections(o.ddl)) {
|
|
188
|
+
if (!by.has(c))
|
|
189
|
+
by.set(c, []);
|
|
190
|
+
by.get(c).push(o.database ? `${o.database}.${o.name}` : o.name);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const prerequisites = [...by]
|
|
194
|
+
.sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
|
|
195
|
+
.map(([name, referencedBy]) => ({ kind: "named collection", name, referencedBy }));
|
|
196
|
+
const seen = new Set(found.map((o) => o.name));
|
|
197
|
+
const warnings = prerequisites.map((p) => {
|
|
198
|
+
const used = p.referencedBy.length > 0 ? `, named by ${p.referencedBy.join(", ")}` : "";
|
|
199
|
+
return (`named collection ${p.name} is a prerequisite${wording.of ? ` of ${wording.of}` : ""}${used}: ${seen.has(p.name) ? wording.found : wording.unseen}, ` +
|
|
200
|
+
"and chant does not declare it or read its values. Create it on every server the project applies to; chant sql plan checks that it exists");
|
|
201
|
+
});
|
|
202
|
+
return { prerequisites, warnings };
|
|
203
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/clickhouse/parser.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../src/clickhouse/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,7 +51,7 @@ export const REFUSED_CREATE_KINDS = [
|
|
|
51
51
|
{
|
|
52
52
|
words: ["NAMED", "COLLECTION"],
|
|
53
53
|
kind: "NAMED COLLECTION",
|
|
54
|
-
reason: "a named collection holds credentials (a password, a secret key), which are the environment's and never in a build
|
|
54
|
+
reason: "a named collection holds credentials (a password, a secret key), which are the environment's and never in a build. Create it on the server, and name it where it is used: ENGINE = S3(lake_creds, format = 'Parquet'), s3(lake_creds), SOURCE(MYSQL(NAME mysql_creds)). A plan checks that it exists",
|
|
55
55
|
},
|
|
56
56
|
{ words: ["MASKING", "POLICY"], kind: "MASKING POLICY", reason: "masking policies are available only in ClickHouse Cloud, not on the pinned server" },
|
|
57
57
|
{ words: ["WORKLOAD"], kind: "WORKLOAD", reason: "a workload is server-level scheduling, configured with the server, not a schema object" },
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* expressions the rules leave different. Both exit 2 when a change needs a
|
|
14
14
|
* rebuild, which a plan refuses to make in place, and `plan` also when the
|
|
15
15
|
* declared databases hold an object whose definition it cannot read (#3653),
|
|
16
|
-
* which it names
|
|
16
|
+
* which it names, or when the build references a named collection the
|
|
17
|
+
* server does not have (#4395), which it names; 0 otherwise. For each
|
|
17
18
|
* refused table they name the `ClickHouseRebuildOp` to run instead
|
|
18
19
|
* (`rebuildOps` in `--json`, `./rebuild-handoff.ts`).
|
|
19
20
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/commands.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AAC5F,OAAO,EAAe,KAAK,UAAU,EAAwB,MAAM,QAAQ,CAAC;AAM5E,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AA0D9C,wBAAsB,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBvE;AAED,mFAAmF;AACnF,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,CAAC,CAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CA4BvJ;AAED,wBAAsB,OAAO,CAAC,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAYvE;AAED,eAAO,MAAM,WAAW,EAAE,YAsBzB,CAAC"}
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
* expressions the rules leave different. Both exit 2 when a change needs a
|
|
14
14
|
* rebuild, which a plan refuses to make in place, and `plan` also when the
|
|
15
15
|
* declared databases hold an object whose definition it cannot read (#3653),
|
|
16
|
-
* which it names
|
|
16
|
+
* which it names, or when the build references a named collection the
|
|
17
|
+
* server does not have (#4395), which it names; 0 otherwise. For each
|
|
17
18
|
* refused table they name the `ClickHouseRebuildOp` to run instead
|
|
18
19
|
* (`rebuildOps` in `--json`, `./rebuild-handoff.ts`).
|
|
19
20
|
*
|
|
@@ -38,6 +39,7 @@ import { bindClickHouse } from "../live/bind.js";
|
|
|
38
39
|
import { rebuildOpSuggestions } from "./rebuild-handoff.js";
|
|
39
40
|
import { readFileSync } from "node:fs";
|
|
40
41
|
import { parseTopology } from "../topology.js";
|
|
42
|
+
import { checkNamedCollections, namedCollectionsFail, referencedCollectionsOf } from "../live/named-collections.js";
|
|
41
43
|
/** The dialect a build output names. */
|
|
42
44
|
function outputDialect(path) {
|
|
43
45
|
try {
|
|
@@ -81,7 +83,7 @@ async function runDiffStatements(before, after, json, topology) {
|
|
|
81
83
|
}
|
|
82
84
|
function emit(diff, json, title) {
|
|
83
85
|
console.log(json ? JSON.stringify(diff, null, 2) : renderDiff(diff, { title }));
|
|
84
|
-
return diff.rebuilds.length > 0 || (diff.unreadable?.length ?? 0) > 0 ? 2 : 0;
|
|
86
|
+
return diff.rebuilds.length > 0 || (diff.unreadable?.length ?? 0) > 0 || namedCollectionsFail(diff.namedCollections) ? 2 : 0;
|
|
85
87
|
}
|
|
86
88
|
export async function runDiff(ctx) {
|
|
87
89
|
const { positional, json, statements, topology: topologyArg } = split(ctx.rawArgs);
|
|
@@ -121,6 +123,8 @@ export async function planAgainstServer(environment, buildFile, options = {}) {
|
|
|
121
123
|
const diff = diffSchemas(live, declared);
|
|
122
124
|
const changes = await dropFormattingOnly(target.endpoint, diff.changes);
|
|
123
125
|
const rebuildOps = rebuildOpSuggestions({ ...diff, changes, rebuilds: changes.filter((c) => c.class === "rebuild") }, new Map(declared.map((o) => [o.key, o.canonical])), environment);
|
|
126
|
+
// Each named collection the build references must exist on the server, by name; its values are never read (#4395).
|
|
127
|
+
const namedCollections = await checkNamedCollections(target.endpoint, referencedCollectionsOf(buildFile));
|
|
124
128
|
const label = new Map(declared.map((o) => [o.key, o.exportName === o.key ? o.key : `${o.exportName} (${o.key})`]));
|
|
125
129
|
const relabel = changes.map((c) => ({ ...c, object: label.get(c.object) ?? c.object }));
|
|
126
130
|
return {
|
|
@@ -129,6 +133,7 @@ export async function planAgainstServer(environment, buildFile, options = {}) {
|
|
|
129
133
|
hints: unmanaged > 0 ? [...diff.hints, accessUnmanagedHint(unmanaged, environment)] : diff.hints,
|
|
130
134
|
...(rebuildOps.length > 0 ? { rebuildOps } : {}),
|
|
131
135
|
...(unreadable.length > 0 ? { unreadable } : {}),
|
|
136
|
+
...(namedCollections ? { namedCollections } : {}),
|
|
132
137
|
};
|
|
133
138
|
}
|
|
134
139
|
export async function runPlan(ctx) {
|
|
@@ -155,5 +160,15 @@ export const sqlCommands = {
|
|
|
155
160
|
description: "Write sql-types.d.ts: typed columns for each table, view and dictionary the build declares, for tags given their name (table<\"app.users\">) and RowOf; --output <path> writes it elsewhere; --check compares instead of writing and exits 1 when the file differs",
|
|
156
161
|
handler: async (ctx) => (await import("../../sql-types-command.js")).runTypes(ctx),
|
|
157
162
|
},
|
|
163
|
+
{
|
|
164
|
+
name: "replay",
|
|
165
|
+
description: "Replay a goose, golang-migrate, clickhouse-migrations or Flyway directory into the empty server --env binds, and record the tables and columns it makes as chant.replay.json; --check compares instead of writing",
|
|
166
|
+
handler: async (ctx) => (await import("../../migration-replay.js")).runReplay(ctx),
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "drizzle",
|
|
170
|
+
description: "Write a Drizzle schema module (drizzle-schema.ts) from a Postgres build: pgTable per table with columns, keys, indexes, enums, sequences and views, so an application queries with Drizzle's row types while chant owns the schema; --output <path> writes it elsewhere; --check compares instead of writing and exits 1 when the file differs; --bigint bigint reads bigint columns as bigint, not number",
|
|
171
|
+
handler: async (ctx) => (await import("../../drizzle-command.js")).runDrizzle(ctx),
|
|
172
|
+
},
|
|
158
173
|
],
|
|
159
174
|
};
|
|
@@ -33,6 +33,21 @@ export interface SchemaDiff extends ChangeSet<Change> {
|
|
|
33
33
|
* it out.
|
|
34
34
|
*/
|
|
35
35
|
unreadable?: UnreadableEntry[];
|
|
36
|
+
/**
|
|
37
|
+
* The named collections the build references, checked against the server
|
|
38
|
+
* by name (#4395). A plan with one `missing`, or whose check could not run
|
|
39
|
+
* (`unread`), fails naming it. Their values are never read.
|
|
40
|
+
*/
|
|
41
|
+
namedCollections?: NamedCollectionCheck;
|
|
42
|
+
}
|
|
43
|
+
/** What a plan found of the named collections a build references: each by name, never its values. */
|
|
44
|
+
export interface NamedCollectionCheck {
|
|
45
|
+
/** Every collection the build names, sorted. */
|
|
46
|
+
referenced: string[];
|
|
47
|
+
/** Those the server has no collection of, or that the plan's user may not see. */
|
|
48
|
+
missing: string[];
|
|
49
|
+
/** Why the server's collections could not be read, when they could not. */
|
|
50
|
+
unread?: string;
|
|
36
51
|
}
|
|
37
52
|
/** An object a plan could not read: `database.name`, its type and why. */
|
|
38
53
|
export interface UnreadableEntry {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,SAAS,CAAC;AACpF,OAAO,KAAK,EAAmB,eAAe,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAG7D,OAAO,EAAoB,KAAK,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAChG,OAAO,EAAmC,KAAK,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE9E,MAAM,MAAM,YAAY,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC;AAElD,MAAM,MAAM,MAAM,GAAG,gBAAgB,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;AAErE,MAAM,WAAW,UAAW,SAAQ,SAAS,CAAC,MAAM,CAAC;IACnD,wDAAwD;IACxD,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,6GAA6G;IAC7G,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC;;;;OAIG;IACH,UAAU,CAAC,EAAE,eAAe,EAAE,CAAC;IAC/B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,oBAAoB,CAAC;CACzC;AAED,qGAAqG;AACrG,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,kFAAkF;IAClF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,0EAA0E;AAC1E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AA4RD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,EAAE,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,UAAU,CAgCvG"}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { CLASSIFIER_RULES } from "./rules.js";
|
|
19
19
|
import { MERGE_TREE_SETTINGS } from "../../generated/clickhouse.js";
|
|
20
|
+
import { isStreamEngine, isStreamTable, positionWarnings, readsTable } from "./stream.js";
|
|
20
21
|
import { classifiedChange } from "../../core/classifier.js";
|
|
21
22
|
import { changedEntries, matchByIdentity } from "../../core/diff.js";
|
|
22
23
|
const qualified = (o) => (o.database ? `${o.database}.${o.name}` : o.name);
|
|
@@ -203,9 +204,14 @@ function diffObject(key, before, after, out, hints) {
|
|
|
203
204
|
diffTableFunction(key, before, after, out);
|
|
204
205
|
return;
|
|
205
206
|
}
|
|
207
|
+
// A stream table (#4396): replaced, not altered, and not rebuilt, since it holds no rows.
|
|
208
|
+
if (isStreamTable(before) && isStreamTable(after)) {
|
|
209
|
+
diffStreamTable(key, before, after, out);
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
206
212
|
// A table.
|
|
207
213
|
if (before.engine !== after.engine)
|
|
208
|
-
out.push(change(key, "engine", "SQLCH223", before.engine, after.engine));
|
|
214
|
+
out.push(change(key, "engine", "SQLCH223", before.engine, after.engine, isStreamEngine(before.engineName) || isStreamEngine(after.engineName) ? { note: "one side is a stream engine and the other is not, which is a different kind of table: neither the replace nor the rebuild applies" } : {}));
|
|
209
215
|
const added = diffColumns(key, before, after, out, hints);
|
|
210
216
|
const beforePk = before.primaryKey ?? before.orderBy;
|
|
211
217
|
const afterPk = after.primaryKey ?? after.orderBy;
|
|
@@ -234,6 +240,32 @@ function diffObject(key, before, after, out, hints) {
|
|
|
234
240
|
diffMap(key, "projections", before.projections, after.projections, "SQLCH214", out);
|
|
235
241
|
diffMap(key, "constraints", before.constraints, after.constraints, "SQLCH215", out);
|
|
236
242
|
}
|
|
243
|
+
/**
|
|
244
|
+
* A table on a stream engine, on both sides (#4396). Its engine, its settings
|
|
245
|
+
* and its columns are all replaced the same way (SQLCH225); the comment is
|
|
246
|
+
* compared before this. A change that loses the table's position says so in
|
|
247
|
+
* its note.
|
|
248
|
+
*/
|
|
249
|
+
function diffStreamTable(key, before, after, out) {
|
|
250
|
+
const start = out.length;
|
|
251
|
+
if (before.engine !== after.engine)
|
|
252
|
+
out.push(change(key, "engine", "SQLCH225", before.engine, after.engine));
|
|
253
|
+
for (const name of changedEntries(before.settings, after.settings))
|
|
254
|
+
out.push(change(key, `settings.${name}`, "SQLCH225", before.settings[name], after.settings[name]));
|
|
255
|
+
const column = (c) => [c.type, c.nullable ? "NULL" : "", c.defaultKind ?? "", c.defaultExpr ?? "", c.codec ? `CODEC(${c.codec})` : ""].filter(Boolean).join(" ");
|
|
256
|
+
const b = new Map(before.columns.map((c) => [c.name, column(c)]));
|
|
257
|
+
const a = new Map(after.columns.map((c) => [c.name, column(c)]));
|
|
258
|
+
for (const name of new Set([...b.keys(), ...a.keys()])) {
|
|
259
|
+
if (b.get(name) !== a.get(name))
|
|
260
|
+
out.push(change(key, `columns.${name}`, "SQLCH225", b.get(name), a.get(name)));
|
|
261
|
+
}
|
|
262
|
+
const order = (o) => o.columns.map((c) => c.name).join(", ");
|
|
263
|
+
if (order(before) !== order(after) && a.size === b.size && [...a.keys()].every((n) => b.has(n)))
|
|
264
|
+
out.push(change(key, "columns.order", "SQLCH225", order(before), order(after)));
|
|
265
|
+
const warnings = positionWarnings(before, after);
|
|
266
|
+
if (warnings.length > 0 && out.length > start)
|
|
267
|
+
out[start] = { ...out[start], note: `loses its position: ${warnings.join("; ")}` };
|
|
268
|
+
}
|
|
237
269
|
/**
|
|
238
270
|
* A table over a table function (#3911), on either side. It stores nothing,
|
|
239
271
|
* so every change but its comment replaces it (SQLCH219); a table with data
|
|
@@ -308,5 +340,15 @@ export function diffSchemas(before, after) {
|
|
|
308
340
|
changes.push(change(b.key, "object", "SQLCH250", qualified(b.canonical), undefined, { destructive: b.canonical.kind === "table" || b.canonical.kind === "materializedView" }));
|
|
309
341
|
}
|
|
310
342
|
}
|
|
343
|
+
// A replaced stream table is replaced around the views that read it (#4396): say which.
|
|
344
|
+
const replaced = new Set(changes.filter((c) => c.rule === "SQLCH225").map((c) => c.object));
|
|
345
|
+
for (const m of matches) {
|
|
346
|
+
if (m.kind !== "matched" || !replaced.has(m.after.key))
|
|
347
|
+
continue;
|
|
348
|
+
const readers = before.filter((o) => readsTable(o.canonical, m.before.canonical)).map((o) => qualified(o.canonical));
|
|
349
|
+
hints.push(readers.length > 0
|
|
350
|
+
? `${qualified(m.before.canonical)} is replaced: ${readers.join(", ")} ${readers.length === 1 ? "reads it and is" : "read it and are"} detached first and attached after`
|
|
351
|
+
: `${qualified(m.before.canonical)} is replaced; no materialized view reads it`);
|
|
352
|
+
}
|
|
311
353
|
return { changes, rebuilds: changes.filter((c) => c.class === "rebuild"), hints };
|
|
312
354
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disruption.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/disruption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"disruption.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/disruption.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;AA0ChG,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAWlI"}
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
import { MERGE_TREE_SETTINGS } from "../../generated/clickhouse.js";
|
|
13
13
|
import { classifyDisruptionWith } from "../../core/classifier.js";
|
|
14
14
|
import { CHANGE_CLASSES, CLASSIFIER_RULES } from "./rules.js";
|
|
15
|
+
/** Settings only a stream engine takes; the path alone cannot name the engine. */
|
|
16
|
+
const STREAM_SETTING = /^(?:kafka_|rabbitmq_|nats_|s3queue_|azure_queue_|keeper_path$)/;
|
|
15
17
|
function ruleFor(path) {
|
|
16
18
|
const root = path.split(/[.[]/)[0];
|
|
17
19
|
if (root === "name" || root === "database")
|
|
@@ -42,6 +44,9 @@ function ruleFor(path) {
|
|
|
42
44
|
return "SQLCH244";
|
|
43
45
|
if (root === "settings") {
|
|
44
46
|
const key = path.split(".")[1];
|
|
47
|
+
// A stream engine's own settings (Kafka, RabbitMQ, NATS, S3Queue's keeper_path) have no MODIFY SETTING: the table is replaced (#4396).
|
|
48
|
+
if (key !== undefined && STREAM_SETTING.test(key))
|
|
49
|
+
return "SQLCH225";
|
|
45
50
|
const spec = key ? MERGE_TREE_SETTINGS[key] : undefined;
|
|
46
51
|
return spec?.readonly ? "SQLCH218" : "SQLCH206";
|
|
47
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rebuild-handoff.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/rebuild-handoff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAuC,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"rebuild-handoff.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/rebuild-handoff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACzC,OAAO,EAAuC,KAAK,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAIrG,MAAM,WAAW,mBAAoB,SAAQ,qBAAqB;IAChE,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE;QAAE,IAAI,EAAE,mBAAmB,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC;IAClF,2GAA2G;IAC3G,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAID;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,mBAAmB,EAAE,CA4BzI;AAED,+CAA+C;AAC/C,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,SAAS,mBAAmB,EAAE,GAAG,MAAM,EAAE,CAG9E"}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* suggestion are ClickHouse's.
|
|
17
17
|
*/
|
|
18
18
|
import { migrationOpName, renderMigrationOps } from "../../core/handoff.js";
|
|
19
|
+
import { isStreamEngine } from "./stream.js";
|
|
19
20
|
import { collapsesRows } from "../rebuild/engines.js";
|
|
20
21
|
const TIME_TYPE = /^(?:Nullable\s*\(\s*)?(?:Date|Date32|DateTime|DateTime64)\b/;
|
|
21
22
|
/**
|
|
@@ -29,6 +30,9 @@ export function rebuildOpSuggestions(diff, declared, env) {
|
|
|
29
30
|
const c = declared.get(key);
|
|
30
31
|
if (!c || c.kind !== "table")
|
|
31
32
|
continue;
|
|
33
|
+
// The Op refuses a stream-engine table (#4396); a change to one that reaches here is a move to or from a stream engine, for review.
|
|
34
|
+
if (isStreamEngine(c.engineName))
|
|
35
|
+
continue;
|
|
32
36
|
const table = `${c.database ?? "default"}.${c.name}`;
|
|
33
37
|
const time = c.columns.find((col) => !col.nullable && TIME_TYPE.test(col.type) && (!col.defaultKind || col.defaultKind === "DEFAULT"));
|
|
34
38
|
const dualWrite = time ? { mode: "materialized-view", cutoverColumn: time.name } : { mode: "app" };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/report.ts"],"names":[],"mappings":"AAAA,qHAAqH;AAIrH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/report.ts"],"names":[],"mappings":"AAAA,qHAAqH;AAIrH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAIzC,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CA0BlF"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { renderChangeSet } from "../../core/classifier.js";
|
|
3
3
|
import { CHANGE_CLASSES, CLASSIFIER_RULES } from "./rules.js";
|
|
4
4
|
import { renderRebuildOps } from "./rebuild-handoff.js";
|
|
5
|
+
import { renderNamedCollections } from "../live/named-collections.js";
|
|
5
6
|
export function renderDiff(diff, opts = {}) {
|
|
6
7
|
const unreadable = diff.unreadable ?? [];
|
|
7
8
|
const refusedRead = unreadable.length > 0
|
|
@@ -13,6 +14,7 @@ export function renderDiff(diff, opts = {}) {
|
|
|
13
14
|
: [];
|
|
14
15
|
const trailer = [
|
|
15
16
|
...refusedRead,
|
|
17
|
+
...renderNamedCollections(diff.namedCollections),
|
|
16
18
|
...(diff.rebuilds.length > 0
|
|
17
19
|
? [
|
|
18
20
|
"",
|
|
@@ -22,5 +24,8 @@ export function renderDiff(diff, opts = {}) {
|
|
|
22
24
|
]
|
|
23
25
|
: []),
|
|
24
26
|
];
|
|
25
|
-
|
|
27
|
+
const text = renderChangeSet(diff, { ...(opts.title ? { title: opts.title } : {}), rules: CLASSIFIER_RULES, classes: CHANGE_CLASSES, trailer });
|
|
28
|
+
// The shared report prints no trailer under "No changes."; a missing named collection fails the plan all the same (#4395).
|
|
29
|
+
const missing = renderNamedCollections(diff.namedCollections);
|
|
30
|
+
return diff.changes.length === 0 && missing.length > 0 ? [text, ...missing].join("\n") : text;
|
|
26
31
|
}
|
|
@@ -10,13 +10,16 @@
|
|
|
10
10
|
* parts until `MATERIALIZE INDEX`).
|
|
11
11
|
* - `rewrite`: the change is a mutation that rewrites existing parts in the
|
|
12
12
|
* background (`system.mutations`), with no rollback.
|
|
13
|
+
* - `replace`: ClickHouse cannot alter the object, but it holds no rows to
|
|
14
|
+
* keep, so the applier drops and creates it, around the views that read it
|
|
15
|
+
* (a stream-engine table, #4396). Nothing is copied.
|
|
13
16
|
* - `rebuild`: ClickHouse cannot make the change to the table it has; the data
|
|
14
17
|
* has to be copied into a new table. A plan refuses to make one in place.
|
|
15
18
|
*
|
|
16
19
|
* Creating and dropping whole objects are classed `create` and `drop`.
|
|
17
20
|
*/
|
|
18
21
|
import { type ChangeClasses, type ClassifierRule as SqlClassifierRule } from "../../core/classifier.js";
|
|
19
|
-
export type ChangeClass = "metadata" | "rewrite" | "rebuild" | "create" | "drop";
|
|
22
|
+
export type ChangeClass = "metadata" | "rewrite" | "replace" | "rebuild" | "create" | "drop";
|
|
20
23
|
/** A ClickHouse rule: the shared core's rule shape over these classes, citing a clickhouse.com page. */
|
|
21
24
|
export type ClassifierRule = SqlClassifierRule<ChangeClass>;
|
|
22
25
|
/** The classes as data: report order and labels, and what each costs for `classifyDisruption()`. */
|
|
@@ -47,6 +50,7 @@ export declare const CLASSIFIER_RULES: {
|
|
|
47
50
|
readonly SQLCH222: ClassifierRule;
|
|
48
51
|
readonly SQLCH223: ClassifierRule;
|
|
49
52
|
readonly SQLCH224: ClassifierRule;
|
|
53
|
+
readonly SQLCH225: ClassifierRule;
|
|
50
54
|
readonly SQLCH230: ClassifierRule;
|
|
51
55
|
readonly SQLCH231: ClassifierRule;
|
|
52
56
|
readonly SQLCH232: ClassifierRule;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/rules.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAkB,KAAK,aAAa,EAAE,KAAK,cAAc,IAAI,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAErH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7F,wGAAwG;AACxG,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAC,WAAW,CAAC,CAAC;AAE5D,oGAAoG;AACpG,eAAO,MAAM,cAAc,EAAE,aAAa,CAAC,WAAW,CAIrD,CAAC;AAMF,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwRsB,CAAC;AAEpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,gBAAgB,CAAC"}
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
* parts until `MATERIALIZE INDEX`).
|
|
11
11
|
* - `rewrite`: the change is a mutation that rewrites existing parts in the
|
|
12
12
|
* background (`system.mutations`), with no rollback.
|
|
13
|
+
* - `replace`: ClickHouse cannot alter the object, but it holds no rows to
|
|
14
|
+
* keep, so the applier drops and creates it, around the views that read it
|
|
15
|
+
* (a stream-engine table, #4396). Nothing is copied.
|
|
13
16
|
* - `rebuild`: ClickHouse cannot make the change to the table it has; the data
|
|
14
17
|
* has to be copied into a new table. A plan refuses to make one in place.
|
|
15
18
|
*
|
|
@@ -18,9 +21,9 @@
|
|
|
18
21
|
import { classifierRule } from "../../core/classifier.js";
|
|
19
22
|
/** The classes as data: report order and labels, and what each costs for `classifyDisruption()`. */
|
|
20
23
|
export const CHANGE_CLASSES = {
|
|
21
|
-
order: ["create", "metadata", "rewrite", "rebuild", "drop"],
|
|
22
|
-
label: { create: "create", drop: "drop", metadata: "metadata only", rewrite: "background rewrite", rebuild: "REBUILD" },
|
|
23
|
-
disruption: { metadata: "in-place", rewrite: "rolling", rebuild: "replace", create: "in-place", drop: "destroy" },
|
|
24
|
+
order: ["create", "metadata", "rewrite", "replace", "rebuild", "drop"],
|
|
25
|
+
label: { create: "create", drop: "drop", metadata: "metadata only", rewrite: "background rewrite", replace: "replace table", rebuild: "REBUILD" },
|
|
26
|
+
disruption: { metadata: "in-place", rewrite: "rolling", replace: "replace", rebuild: "replace", create: "in-place", drop: "destroy" },
|
|
24
27
|
};
|
|
25
28
|
const DOCS = "https://clickhouse.com/docs/sql-reference/statements";
|
|
26
29
|
const rule = (id, cls, title, restriction, cite) => classifierRule(id, cls, title, restriction, cite);
|
|
@@ -50,6 +53,7 @@ export const CLASSIFIER_RULES = {
|
|
|
50
53
|
SQLCH222: rule("SQLCH222", "rebuild", "Change the partition key", "There is no ALTER for the partition key; parts are laid out by it when they are written.", `${DOCS}/alter`),
|
|
51
54
|
SQLCH223: rule("SQLCH223", "rebuild", "Change the table engine or its arguments", "There is no ALTER for a table's engine or its arguments (a ReplacingMergeTree version column, a Distributed sharding key); a different engine is a different table.", `${DOCS}/alter`),
|
|
52
55
|
SQLCH224: rule("SQLCH224", "rebuild", "Change what kind of object it is", "A table cannot become a view or a view a table; the old object is dropped and the new one created.", `${DOCS}/create`),
|
|
56
|
+
SQLCH225: rule("SQLCH225", "replace", "Change a stream table", "A Kafka, S3Queue, AzureQueue, RabbitMQ, NATS or FileLog table stores no rows and has no ALTER for its engine arguments, settings or columns; the views that read it are detached, the table is dropped and created, and the views are attached again. Its position (a Kafka group's offsets, an S3Queue's record of processed files) is kept by the broker or Keeper, not by the table.", `${DOCS}/create/table`),
|
|
53
57
|
SQLCH230: rule("SQLCH230", "metadata", "Rename or move a table or view", "RENAME TABLE changes the name, or moves the object to another database, in metadata on an Atomic database.", `${DOCS}/rename`),
|
|
54
58
|
SQLCH231: rule("SQLCH231", "metadata", "Rename a database", "RENAME DATABASE is metadata only, for an Atomic database.", `${DOCS}/rename`),
|
|
55
59
|
SQLCH232: rule("SQLCH232", "rebuild", "Change a database's engine", "A database's engine is fixed at creation; there is no ALTER for it.", `${DOCS}/create/database`),
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream engines (#4396): Kafka, S3Queue, AzureQueue, RabbitMQ, NATS and
|
|
3
|
+
* FileLog. A table on one of them stores no rows. It is a consumer: the
|
|
4
|
+
* materialized views that read it pull messages (or files) through it into a
|
|
5
|
+
* target, and the position it has reached lives outside the table, in the
|
|
6
|
+
* broker's committed offsets or in Keeper.
|
|
7
|
+
*
|
|
8
|
+
* What follows from that, and what this file holds:
|
|
9
|
+
*
|
|
10
|
+
* - There is no ALTER for the engine's arguments, and nothing to copy to a
|
|
11
|
+
* new table, so a change is neither `metadata` nor a `rebuild`: the table is
|
|
12
|
+
* replaced, with the views that read it detached around the replacement
|
|
13
|
+
* (SQLCH225, `./rules.ts`).
|
|
14
|
+
* - A replacement can lose the table's position. The two changes that do
|
|
15
|
+
* are found here and reported on the change as a note.
|
|
16
|
+
*/
|
|
17
|
+
import type { CanonicalObject } from "./normalize.js";
|
|
18
|
+
/** The stream engines, as `system.tables.engine` names them. */
|
|
19
|
+
export declare const STREAM_ENGINES: ReadonlySet<string>;
|
|
20
|
+
/** Whether an engine name is a stream engine. */
|
|
21
|
+
export declare const isStreamEngine: (engine: string | undefined) => boolean;
|
|
22
|
+
/** Whether a canonical table is on a stream engine. */
|
|
23
|
+
export declare const isStreamTable: (o: CanonicalObject) => boolean;
|
|
24
|
+
/** The arguments inside an engine's parentheses, split at top-level commas, string quotes removed. Empty when it has none. */
|
|
25
|
+
export declare function streamEngineArguments(engine: string | undefined): string[];
|
|
26
|
+
/**
|
|
27
|
+
* What a replacement would lose, in a sentence each (#4396):
|
|
28
|
+
*
|
|
29
|
+
* - a different `kafka_group_name` is a different consumer group: it starts
|
|
30
|
+
* from the group's committed offsets, or from the topic's start when the
|
|
31
|
+
* group has none (`auto.offset.reset`);
|
|
32
|
+
* - a different S3Queue `keeper_path` is a different place for the table's
|
|
33
|
+
* record of processed files, so every file already seen is processed again.
|
|
34
|
+
*
|
|
35
|
+
* Neither is a refusal: a new group or path is sometimes the point.
|
|
36
|
+
*/
|
|
37
|
+
export declare function positionWarnings(before: CanonicalObject, after: CanonicalObject): string[];
|
|
38
|
+
/** Whether a materialized view reads from the table: its SELECT names the table, qualified or, in the table's own database, bare. */
|
|
39
|
+
export declare function readsTable(view: CanonicalObject, table: CanonicalObject): boolean;
|
|
40
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../src/clickhouse/plan/stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,gEAAgE;AAChE,eAAO,MAAM,cAAc,EAAE,WAAW,CAAC,MAAM,CAA8E,CAAC;AAE9H,iDAAiD;AACjD,eAAO,MAAM,cAAc,GAAI,QAAQ,MAAM,GAAG,SAAS,KAAG,OAA6D,CAAC;AAE1H,uDAAuD;AACvD,eAAO,MAAM,aAAa,GAAI,GAAG,eAAe,KAAG,OAA6D,CAAC;AAEjH,8HAA8H;AAC9H,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CA0B1E;AAWD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,CAsB1F;AAED,qIAAqI;AACrI,wBAAgB,UAAU,CAAC,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,GAAG,OAAO,CAQjF"}
|