@intentius/chant-lexicon-sql 0.124.46 → 0.124.49
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/statements.d.ts +29 -0
- package/dist/clickhouse/plan/statements.d.ts.map +1 -0
- package/dist/clickhouse/plan/statements.js +334 -0
- 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 +44 -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 +2 -2
- package/dist/codegen/registry.d.ts.map +1 -1
- package/dist/codegen/registry.js +10 -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/core/statement-class.d.ts +55 -0
- package/dist/core/statement-class.d.ts.map +1 -0
- package/dist/core/statement-class.js +43 -0
- package/dist/coverage/clickhouse.json +1 -1
- package/dist/coverage/postgres.json +12 -12
- 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 +689 -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.d.ts.map +1 -1
- package/dist/files/postgres.js +35 -3
- 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 +7 -6
- 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/postgres-names.d.ts.map +1 -1
- package/dist/lint/post-synth/postgres-names.js +3 -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 +21 -0
- package/dist/manifest.json +1 -1
- package/dist/mcp/postgres.js +1 -1
- package/dist/meta.json +50 -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-classify.d.ts +23 -0
- package/dist/migration-classify.d.ts.map +1 -0
- package/dist/migration-classify.js +44 -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 +11 -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/PostgresForeignTable.md +9 -0
- package/dist/okf/types/PostgresOperator.md +9 -0
- package/dist/okf/types/PostgresOperatorClass.md +9 -0
- package/dist/okf/types/PostgresOperatorFamily.md +9 -0
- package/dist/okf/types/PostgresPublication.md +9 -0
- package/dist/okf/types/PostgresStatistics.md +9 -0
- package/dist/okf/types/PostgresTextSearchConfiguration.md +9 -0
- package/dist/okf/types/PostgresTextSearchDictionary.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 +49 -2
- package/dist/postgres/access/acl.js +1 -1
- package/dist/postgres/access/import.js +1 -1
- package/dist/postgres/apply/apply.js +13 -1
- package/dist/postgres/apply/statements.d.ts.map +1 -1
- package/dist/postgres/apply/statements.js +243 -4
- 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 +229 -2
- package/dist/postgres/entities.d.ts.map +1 -1
- package/dist/postgres/entities.js +326 -5
- package/dist/postgres/entity-types.d.ts +10 -0
- package/dist/postgres/entity-types.d.ts.map +1 -1
- package/dist/postgres/entity-types.js +10 -0
- package/dist/postgres/import/generator.d.ts.map +1 -1
- package/dist/postgres/import/generator.js +65 -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 +20 -0
- package/dist/postgres/live/catalog-kinds.d.ts.map +1 -1
- package/dist/postgres/live/catalog-kinds.js +452 -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 +12 -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 +45 -13
- 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/replication.d.ts +42 -0
- package/dist/postgres/migrate/replication.d.ts.map +1 -1
- package/dist/postgres/migrate/replication.js +53 -0
- 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 +144 -1
- package/dist/postgres/parser.d.ts.map +1 -1
- package/dist/postgres/parser.js +370 -4
- package/dist/postgres/plan/deep.d.ts.map +1 -1
- package/dist/postgres/plan/deep.js +43 -4
- package/dist/postgres/plan/diff.d.ts.map +1 -1
- package/dist/postgres/plan/diff.js +154 -1
- package/dist/postgres/plan/normalize.d.ts +28 -2
- package/dist/postgres/plan/normalize.d.ts.map +1 -1
- package/dist/postgres/plan/normalize.js +260 -1
- package/dist/postgres/plan/rules.d.ts +4 -0
- package/dist/postgres/plan/rules.d.ts.map +1 -1
- package/dist/postgres/plan/rules.js +6 -2
- package/dist/postgres/plan/schema.js +1 -1
- package/dist/postgres/plan/statements.d.ts +26 -0
- package/dist/postgres/plan/statements.d.ts.map +1 -0
- package/dist/postgres/plan/statements.js +364 -0
- 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 +4 -2
- package/dist/postgres/testing/roundtrip-schema.d.ts.map +1 -1
- package/dist/postgres/testing/roundtrip-schema.js +24 -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-names.ts +2 -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 +10 -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/statements.test.ts +61 -0
- package/src/clickhouse/plan/statements.ts +306 -0
- 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 +44 -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 +2 -2
- package/src/codegen/registry.ts +10 -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/statement-class.ts +88 -0
- package/src/core/undeclarable.test.ts +6 -5
- package/src/coverage/clickhouse.json +1 -1
- package/src/coverage/postgres.json +12 -12
- 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 +742 -0
- package/src/files/clickhouse.ts +8 -1
- package/src/files/common.ts +14 -1
- package/src/files/postgres.ts +34 -3
- package/src/generated/clickhouse.ts +3 -0
- package/src/generated/lexicon-sql.json +50 -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/postgres-checks.test.ts +8 -1
- package/src/lint/post-synth/postgres-names.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 +20 -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-classify.test.ts +150 -0
- package/src/migration-classify.ts +45 -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/op/watch-pipeline.test.ts +8 -1
- package/src/plugin.ts +51 -2
- package/src/postgres/access/acl.ts +1 -1
- package/src/postgres/access/import.ts +1 -1
- package/src/postgres/apply/apply.ts +14 -1
- package/src/postgres/apply/statements.ts +225 -4
- package/src/postgres/constraint-names.ts +71 -0
- package/src/postgres/database-kinds.test.ts +865 -0
- package/src/postgres/entities.ts +541 -5
- package/src/postgres/entity-types.ts +10 -0
- package/src/postgres/import/generator.ts +54 -2
- package/src/postgres/import/live-export.ts +1 -0
- package/src/postgres/live/catalog-kinds.ts +494 -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 +13 -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 +56 -15
- 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/replication.ts +66 -0
- package/src/postgres/migrate/steps.ts +157 -12
- package/src/postgres/migrate/subscriber.e2e.test.ts +141 -0
- package/src/postgres/migrate/subscriber.test.ts +59 -0
- package/src/postgres/parser.ts +455 -4
- package/src/postgres/plan/deep.ts +42 -4
- package/src/postgres/plan/diff.ts +137 -1
- package/src/postgres/plan/normalize.ts +277 -1
- package/src/postgres/plan/rules.ts +32 -4
- package/src/postgres/plan/schema.ts +1 -1
- package/src/postgres/plan/statements.test.ts +78 -0
- package/src/postgres/plan/statements.ts +299 -0
- package/src/postgres/secret-options.ts +10 -0
- package/src/postgres/testing/roundtrip-schema.ts +24 -1
- package/src/postgres.ts +33 -0
- package/src/serializer.ts +13 -2
- package/src/skills/chant-sql-postgres-migration.md +4 -3
- package/src/skills/chant-sql-postgres.md +11 -1
- package/src/skills/chant-sql.md +2 -1
- package/src/sql-files.test.ts +33 -0
- 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 +10 -0
- package/src/workspace-kinds.test.ts +11 -0
- package/workspace-kinds.json +100 -2
package/src/postgres/parser.ts
CHANGED
|
@@ -113,6 +113,8 @@ export interface ColumnNode {
|
|
|
113
113
|
notNullName?: string;
|
|
114
114
|
default?: Span;
|
|
115
115
|
generated?: { kind: "stored" | "virtual" | "identity"; expr?: Span; always: boolean; options?: Span };
|
|
116
|
+
/** A foreign table column's `OPTIONS (...)`. */
|
|
117
|
+
options?: GenericOption[];
|
|
116
118
|
/** Column constraints other than NOT NULL, NULL, DEFAULT and GENERATED. */
|
|
117
119
|
constraints: ConstraintNode[];
|
|
118
120
|
}
|
|
@@ -271,6 +273,129 @@ export interface EventTriggerNode {
|
|
|
271
273
|
function: NameNode;
|
|
272
274
|
}
|
|
273
275
|
|
|
276
|
+
/** `CREATE OPERATOR [schema.]symbol (FUNCTION = f, LEFTARG = type, RIGHTARG = type, ...)`. */
|
|
277
|
+
export interface OperatorNode {
|
|
278
|
+
statement: "operator";
|
|
279
|
+
/** The schema, when written, then the operator's symbol. */
|
|
280
|
+
name: NameNode;
|
|
281
|
+
options: DefElem[];
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/** `CREATE STATISTICS [IF NOT EXISTS] name [(kind, ...)] ON target, ... FROM table`. */
|
|
285
|
+
export interface StatisticsNode {
|
|
286
|
+
statement: "statistics";
|
|
287
|
+
ifNotExists: boolean;
|
|
288
|
+
name: NameNode;
|
|
289
|
+
/** `ndistinct`, `dependencies`, `mcv`, folded; empty when the server picks them all. */
|
|
290
|
+
kinds: string[];
|
|
291
|
+
/** Each column or parenthesized expression. */
|
|
292
|
+
targets: Span[];
|
|
293
|
+
table: NameNode;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/** One `name 'value'` of an `OPTIONS (...)` list. */
|
|
297
|
+
export interface GenericOption {
|
|
298
|
+
name: string;
|
|
299
|
+
nameSpan: Span;
|
|
300
|
+
value: Span;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/** `CREATE FOREIGN TABLE [IF NOT EXISTS] name (columns) SERVER server [OPTIONS (...)]`. */
|
|
304
|
+
export interface ForeignTableNode {
|
|
305
|
+
statement: "foreignTable";
|
|
306
|
+
/** Clauses the parser does not know (#3872), kept in the DDL as written; absent when there are none. */
|
|
307
|
+
unknown?: UnknownClause[];
|
|
308
|
+
ifNotExists: boolean;
|
|
309
|
+
name: NameNode;
|
|
310
|
+
columns: ColumnNode[];
|
|
311
|
+
constraints: ConstraintNode[];
|
|
312
|
+
server: NameNode;
|
|
313
|
+
options: GenericOption[];
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/** One member of an operator class: an operator, a support function, or the storage type. */
|
|
317
|
+
export type OperatorClassItem =
|
|
318
|
+
| { kind: "operator"; number: Span; operator: NameNode; types?: Span; orderBy?: NameNode }
|
|
319
|
+
| { kind: "function"; number: Span; types?: Span; function: NameNode; args: Span }
|
|
320
|
+
| { kind: "storage"; type: Span };
|
|
321
|
+
|
|
322
|
+
/** `CREATE OPERATOR CLASS name [DEFAULT] FOR TYPE type USING method [FAMILY family] AS item, ...`. */
|
|
323
|
+
export interface OperatorClassNode {
|
|
324
|
+
statement: "operatorClass";
|
|
325
|
+
name: NameNode;
|
|
326
|
+
default: boolean;
|
|
327
|
+
type: Span;
|
|
328
|
+
/** The index access method, folded. */
|
|
329
|
+
method: string;
|
|
330
|
+
family?: NameNode;
|
|
331
|
+
items: OperatorClassItem[];
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/** `CREATE OPERATOR FAMILY name USING method`. */
|
|
335
|
+
export interface OperatorFamilyNode {
|
|
336
|
+
statement: "operatorFamily";
|
|
337
|
+
name: NameNode;
|
|
338
|
+
method: string;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/** `CREATE TEXT SEARCH DICTIONARY name (TEMPLATE = t [, option = value, ...])`; the template is the `template` option. */
|
|
342
|
+
export interface TextSearchDictionaryNode {
|
|
343
|
+
statement: "textSearchDictionary";
|
|
344
|
+
name: NameNode;
|
|
345
|
+
options: DefElem[];
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** `CREATE TEXT SEARCH CONFIGURATION name (PARSER = p)`. */
|
|
349
|
+
export interface TextSearchConfigurationNode {
|
|
350
|
+
statement: "textSearchConfiguration";
|
|
351
|
+
name: NameNode;
|
|
352
|
+
options: DefElem[];
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/** `ALTER TEXT SEARCH CONFIGURATION name ADD MAPPING FOR token_type, ... WITH dictionary, ...`: a configuration's mapping, written after its CREATE. */
|
|
356
|
+
export interface TextSearchMappingNode {
|
|
357
|
+
statement: "textSearchMapping";
|
|
358
|
+
name: NameNode;
|
|
359
|
+
tokens: Array<{ name: string; span: Span }>;
|
|
360
|
+
dictionaries: NameNode[];
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/** `CREATE FOREIGN DATA WRAPPER name [HANDLER f | NO HANDLER] [VALIDATOR f | NO VALIDATOR] [OPTIONS (...)]`. */
|
|
364
|
+
export interface ForeignDataWrapperNode {
|
|
365
|
+
statement: "foreignDataWrapper";
|
|
366
|
+
name: NameNode;
|
|
367
|
+
/** The handler function; `null` for `NO HANDLER`. */
|
|
368
|
+
handler?: NameNode | null;
|
|
369
|
+
/** The validator function; `null` for `NO VALIDATOR`. */
|
|
370
|
+
validator?: NameNode | null;
|
|
371
|
+
options: GenericOption[];
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/** `CREATE SERVER [IF NOT EXISTS] name [TYPE 't'] [VERSION 'v'] FOREIGN DATA WRAPPER w [OPTIONS (...)]`. */
|
|
375
|
+
export interface ForeignServerNode {
|
|
376
|
+
statement: "foreignServer";
|
|
377
|
+
ifNotExists: boolean;
|
|
378
|
+
name: NameNode;
|
|
379
|
+
type?: Span;
|
|
380
|
+
version?: Span;
|
|
381
|
+
wrapper: NameNode;
|
|
382
|
+
options: GenericOption[];
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** One member of a publication: a table (with its column list and row filter) or every table of a schema. */
|
|
386
|
+
export type PublicationItem =
|
|
387
|
+
| { kind: "table"; table: NameNode; columns?: Array<{ name: string; span: Span }>; where?: Span }
|
|
388
|
+
| { kind: "schema"; schema: NameNode };
|
|
389
|
+
|
|
390
|
+
/** `CREATE PUBLICATION name [FOR ALL TABLES | FOR TABLE ... | FOR TABLES IN SCHEMA ...] [WITH (...)]`. */
|
|
391
|
+
export interface PublicationNode {
|
|
392
|
+
statement: "publication";
|
|
393
|
+
name: NameNode;
|
|
394
|
+
allTables: boolean;
|
|
395
|
+
items: PublicationItem[];
|
|
396
|
+
options: DefElem[];
|
|
397
|
+
}
|
|
398
|
+
|
|
274
399
|
export interface DomainNode {
|
|
275
400
|
statement: "domain";
|
|
276
401
|
name: NameNode;
|
|
@@ -399,6 +524,8 @@ export interface CommentNode {
|
|
|
399
524
|
on?: NameNode;
|
|
400
525
|
/** For `COMMENT ON FUNCTION f(...)` and `AGGREGATE a(...)`: the parameter list, parentheses excluded. */
|
|
401
526
|
args?: Span;
|
|
527
|
+
/** For `COMMENT ON OPERATOR CLASS c USING m` and `OPERATOR FAMILY`: the index method, folded. */
|
|
528
|
+
using?: string;
|
|
402
529
|
/** For `COMMENT ON CAST (source AS target)`: the two types. */
|
|
403
530
|
cast?: { source: Span; target: Span };
|
|
404
531
|
/** The comment, a string, or undefined for `IS NULL`. */
|
|
@@ -418,6 +545,17 @@ export type StatementNode =
|
|
|
418
545
|
| CollationNode
|
|
419
546
|
| CastNode
|
|
420
547
|
| EventTriggerNode
|
|
548
|
+
| OperatorNode
|
|
549
|
+
| OperatorClassNode
|
|
550
|
+
| OperatorFamilyNode
|
|
551
|
+
| ForeignTableNode
|
|
552
|
+
| TextSearchDictionaryNode
|
|
553
|
+
| TextSearchConfigurationNode
|
|
554
|
+
| TextSearchMappingNode
|
|
555
|
+
| StatisticsNode
|
|
556
|
+
| ForeignDataWrapperNode
|
|
557
|
+
| ForeignServerNode
|
|
558
|
+
| PublicationNode
|
|
421
559
|
| DomainNode
|
|
422
560
|
| ExtensionNode
|
|
423
561
|
| RoutineNode
|
|
@@ -503,6 +641,15 @@ export const AGGREGATE_OPTIONS = [
|
|
|
503
641
|
/** `CREATE COLLATION`'s options (sql-createcollation). */
|
|
504
642
|
export const COLLATION_OPTIONS = ["locale", "lc_collate", "lc_ctype", "provider", "deterministic", "rules", "version"];
|
|
505
643
|
|
|
644
|
+
/** `CREATE OPERATOR`'s options (sql-createoperator); `procedure` is the old spelling of `function`. */
|
|
645
|
+
export const OPERATOR_OPTIONS = ["function", "procedure", "leftarg", "rightarg", "commutator", "negator", "restrict", "join", "hashes", "merges"];
|
|
646
|
+
|
|
647
|
+
/** `CREATE STATISTICS`'s kinds (sql-createstatistics). */
|
|
648
|
+
export const STATISTICS_KINDS = ["ndistinct", "dependencies", "mcv"];
|
|
649
|
+
|
|
650
|
+
/** `CREATE PUBLICATION ... WITH (...)`'s options (sql-createpublication); `publish_generated_columns` is 18's. */
|
|
651
|
+
export const PUBLICATION_OPTIONS = ["publish", "publish_via_partition_root", "publish_generated_columns"];
|
|
652
|
+
|
|
506
653
|
/** What may follow `IS` inside a `b_expr`. */
|
|
507
654
|
const B_EXPR_IS = [["DISTINCT", "FROM"], ["NOT", "DISTINCT", "FROM"], ["DOCUMENT"], ["NOT", "DOCUMENT"]];
|
|
508
655
|
|
|
@@ -768,7 +915,7 @@ class PgParser extends SqlCursor {
|
|
|
768
915
|
return node;
|
|
769
916
|
}
|
|
770
917
|
|
|
771
|
-
private column(typed: boolean): ColumnNode {
|
|
918
|
+
private column(typed: boolean, foreign = false): ColumnNode {
|
|
772
919
|
const { text, span } = this.nameTok("a column name");
|
|
773
920
|
const col: ColumnNode = { name: text, nameSpan: span, constraints: [] };
|
|
774
921
|
if (!typed) this.acceptSeq("WITH", "OPTIONS");
|
|
@@ -777,7 +924,10 @@ class PgParser extends SqlCursor {
|
|
|
777
924
|
if (typed && !bare && !this.stopsAt(COLUMN_CLAUSE)) col.type = this.typeName();
|
|
778
925
|
else if (typed) this.fail("expected a column type");
|
|
779
926
|
for (;;) {
|
|
780
|
-
if (this.
|
|
927
|
+
if (foreign && kw(this.peek(), "OPTIONS") && this.isPunct("(", 1)) {
|
|
928
|
+
this.p++;
|
|
929
|
+
col.options = this.genericOptions();
|
|
930
|
+
} else if (this.accept("COMPRESSION")) col.compression = this.expr(COLUMN_CLAUSE);
|
|
781
931
|
else if (this.accept("STORAGE")) col.storage = this.expr(COLUMN_CLAUSE);
|
|
782
932
|
else if (this.accept("COLLATE")) col.collate = this.expr(COLUMN_CLAUSE);
|
|
783
933
|
else if (!this.columnConstraint(col) && !this.unknownClause(COLUMN_WORDS, { inList: true, column: text || undefined })) break;
|
|
@@ -993,6 +1143,7 @@ class PgParser extends SqlCursor {
|
|
|
993
1143
|
if (this.accept("GRANT")) return this.grant(false, false);
|
|
994
1144
|
if (this.accept("REVOKE")) return this.grant(true, false);
|
|
995
1145
|
if (this.acceptSeq("ALTER", "DEFAULT", "PRIVILEGES")) return this.defaultPrivileges();
|
|
1146
|
+
if (this.acceptSeq("ALTER", "TEXT", "SEARCH", "CONFIGURATION")) return this.textSearchMapping();
|
|
996
1147
|
if (this.acceptSeq("ALTER", "TABLE")) return this.rowSecurity();
|
|
997
1148
|
this.expect("CREATE");
|
|
998
1149
|
const orReplace = this.acceptSeq("OR", "REPLACE");
|
|
@@ -1012,6 +1163,24 @@ class PgParser extends SqlCursor {
|
|
|
1012
1163
|
if (this.accept("COLLATION")) return this.collation();
|
|
1013
1164
|
if (this.accept("CAST")) return this.cast();
|
|
1014
1165
|
if (this.acceptSeq("EVENT", "TRIGGER")) return this.eventTrigger();
|
|
1166
|
+
if (this.accept("OPERATOR")) {
|
|
1167
|
+
// CLASS and FAMILY are words an operator's schema may be named: `class.+` is still an operator.
|
|
1168
|
+
if (kw(this.peek(), "CLASS") && !this.isPunct(".", 1)) {
|
|
1169
|
+
this.p++;
|
|
1170
|
+
return this.operatorClass();
|
|
1171
|
+
}
|
|
1172
|
+
if (kw(this.peek(), "FAMILY") && !this.isPunct(".", 1)) {
|
|
1173
|
+
this.p++;
|
|
1174
|
+
return this.operatorFamily();
|
|
1175
|
+
}
|
|
1176
|
+
return this.operator();
|
|
1177
|
+
}
|
|
1178
|
+
if (this.acceptSeq("TEXT", "SEARCH")) return this.textSearch();
|
|
1179
|
+
if (this.accept("STATISTICS")) return this.statistics();
|
|
1180
|
+
if (this.acceptSeq("FOREIGN", "TABLE")) return this.foreignTable();
|
|
1181
|
+
if (this.acceptSeq("FOREIGN", "DATA", "WRAPPER")) return this.foreignDataWrapper();
|
|
1182
|
+
if (this.accept("SERVER")) return this.foreignServer();
|
|
1183
|
+
if (this.accept("PUBLICATION")) return this.publication();
|
|
1015
1184
|
if (kw(this.peek(), "UNIQUE", "INDEX")) return this.index();
|
|
1016
1185
|
}
|
|
1017
1186
|
const persistence = this.persistence();
|
|
@@ -1021,7 +1190,7 @@ class PgParser extends SqlCursor {
|
|
|
1021
1190
|
const recursive = this.accept("RECURSIVE");
|
|
1022
1191
|
if (!orReplace && !recursive && persistence === undefined && this.acceptSeq("MATERIALIZED", "VIEW")) return this.view(true, false, false, false);
|
|
1023
1192
|
if (this.accept("VIEW")) return this.view(false, orReplace, persistence === "temporary", recursive);
|
|
1024
|
-
return this.fail("expected SCHEMA, TABLE, INDEX, VIEW, MATERIALIZED VIEW, SEQUENCE, TYPE, DOMAIN, EXTENSION, FUNCTION, PROCEDURE, AGGREGATE, TRIGGER, EVENT TRIGGER, COLLATION, CAST, POLICY or ROLE");
|
|
1193
|
+
return this.fail("expected SCHEMA, TABLE, INDEX, VIEW, MATERIALIZED VIEW, SEQUENCE, TYPE, DOMAIN, EXTENSION, FUNCTION, PROCEDURE, AGGREGATE, TRIGGER, EVENT TRIGGER, COLLATION, CAST, OPERATOR, OPERATOR CLASS, OPERATOR FAMILY, TEXT SEARCH CONFIGURATION, TEXT SEARCH DICTIONARY, STATISTICS, FOREIGN TABLE, FOREIGN DATA WRAPPER, SERVER, PUBLICATION, POLICY or ROLE");
|
|
1025
1194
|
}
|
|
1026
1195
|
|
|
1027
1196
|
private schema(): SchemaNode {
|
|
@@ -1239,6 +1408,260 @@ class PgParser extends SqlCursor {
|
|
|
1239
1408
|
return node;
|
|
1240
1409
|
}
|
|
1241
1410
|
|
|
1411
|
+
/** An unqualified, database-wide object's name (a wrapper, a server, a publication). */
|
|
1412
|
+
private databaseName(what: string): NameNode {
|
|
1413
|
+
const { text, span } = this.nameTok(what);
|
|
1414
|
+
if (this.isPunct(".")) this.fail(`expected ${what} without a schema (it belongs to the database)`);
|
|
1415
|
+
return { pieces: [text], span };
|
|
1416
|
+
}
|
|
1417
|
+
|
|
1418
|
+
/** `( name 'value' [, ...] )`: a foreign data wrapper's or server's options. */
|
|
1419
|
+
private genericOptions(): GenericOption[] {
|
|
1420
|
+
this.expectPunct("(");
|
|
1421
|
+
const out: GenericOption[] = [];
|
|
1422
|
+
const seen = new Set<string>();
|
|
1423
|
+
for (;;) {
|
|
1424
|
+
const t = this.next();
|
|
1425
|
+
if (t.kind !== "ident" && t.kind !== "qident") this.fail("expected an option name", t);
|
|
1426
|
+
const nameSpan = this.span(this.idx(-1), []);
|
|
1427
|
+
const name = identValue(t);
|
|
1428
|
+
if (seen.has(name)) this.fail(`${name} is given twice`, t);
|
|
1429
|
+
seen.add(name);
|
|
1430
|
+
const v = this.next();
|
|
1431
|
+
if (v.kind !== "string" && v.kind !== "ref") this.fail("expected the option's value, a string", v);
|
|
1432
|
+
out.push({ name, nameSpan, value: this.span(this.idx(-1), v.kind === "ref" ? [v.part] : []) });
|
|
1433
|
+
if (this.acceptPunct(",")) continue;
|
|
1434
|
+
this.expectPunct(")");
|
|
1435
|
+
return out;
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
|
|
1439
|
+
/** `[schema.]symbol`: an operator's name, its symbol made of operator characters. */
|
|
1440
|
+
private operatorName(): NameNode {
|
|
1441
|
+
const from = this.idx();
|
|
1442
|
+
const refs: number[] = [];
|
|
1443
|
+
const pieces: string[] = [];
|
|
1444
|
+
const symbol = (): void => {
|
|
1445
|
+
const t = this.next();
|
|
1446
|
+
if (t.kind !== "op") this.fail("expected the operator's symbol (operator characters, such as ===)", t);
|
|
1447
|
+
pieces.push(t.text);
|
|
1448
|
+
};
|
|
1449
|
+
if (this.peek()?.kind === "op") symbol();
|
|
1450
|
+
else {
|
|
1451
|
+
const t = this.next();
|
|
1452
|
+
this.colId(t, "a schema name");
|
|
1453
|
+
if (t.kind === "ref") refs.push(t.part);
|
|
1454
|
+
pieces.push(t.kind === "ref" ? "" : identValue(t));
|
|
1455
|
+
this.expectPunct(".");
|
|
1456
|
+
symbol();
|
|
1457
|
+
}
|
|
1458
|
+
return { pieces, span: this.span(from, refs) };
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
private operator(): OperatorNode {
|
|
1462
|
+
const name = this.operatorName();
|
|
1463
|
+
const options = this.definition("an operator option");
|
|
1464
|
+
this.checkDefinition(options, OPERATOR_OPTIONS, [], "an operator");
|
|
1465
|
+
if (!options.some((o) => o.name === "function" || o.name === "procedure")) this.fail("expected FUNCTION (an operator needs the function it calls)", this.lastSeen());
|
|
1466
|
+
return { statement: "operator", name, options };
|
|
1467
|
+
}
|
|
1468
|
+
|
|
1469
|
+
/** The member list of `CREATE OPERATOR CLASS ... AS`: an operator, a support function or the storage type. */
|
|
1470
|
+
private operatorClassItem(): OperatorClassItem {
|
|
1471
|
+
const number = (): Span => {
|
|
1472
|
+
const t = this.next();
|
|
1473
|
+
if (t.kind !== "number" && t.kind !== "ref") this.fail("expected the strategy or support number", t);
|
|
1474
|
+
return this.span(this.idx(-1), t.kind === "ref" ? [t.part] : []);
|
|
1475
|
+
};
|
|
1476
|
+
if (this.accept("OPERATOR")) {
|
|
1477
|
+
const item: Extract<OperatorClassItem, { kind: "operator" }> = { kind: "operator", number: number(), operator: this.operatorName() };
|
|
1478
|
+
if (this.isPunct("(")) item.types = this.parenthesized();
|
|
1479
|
+
if (this.accept("FOR")) {
|
|
1480
|
+
if (this.accept("SEARCH")) return item;
|
|
1481
|
+
if (!this.acceptSeq("ORDER", "BY")) this.fail("expected SEARCH or ORDER BY");
|
|
1482
|
+
item.orderBy = this.qualifiedName("a sort operator family");
|
|
1483
|
+
}
|
|
1484
|
+
return item;
|
|
1485
|
+
}
|
|
1486
|
+
if (this.accept("FUNCTION")) {
|
|
1487
|
+
const n = number();
|
|
1488
|
+
const types = this.isPunct("(") ? this.parenthesized() : undefined;
|
|
1489
|
+
const fn = this.qualifiedName("a function name");
|
|
1490
|
+
if (!this.isPunct("(")) this.fail("expected '(' and the function's argument types");
|
|
1491
|
+
return { kind: "function", number: n, ...(types ? { types } : {}), function: fn, args: this.parenthesized() };
|
|
1492
|
+
}
|
|
1493
|
+
if (this.accept("STORAGE")) return { kind: "storage", type: this.typeName() };
|
|
1494
|
+
return this.fail("expected OPERATOR, FUNCTION or STORAGE");
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
private operatorClass(): OperatorClassNode {
|
|
1498
|
+
const name = this.qualifiedName("an operator class name");
|
|
1499
|
+
const isDefault = this.accept("DEFAULT");
|
|
1500
|
+
this.expect("FOR");
|
|
1501
|
+
this.expect("TYPE");
|
|
1502
|
+
const type = this.typeName();
|
|
1503
|
+
this.expect("USING");
|
|
1504
|
+
const method = this.nameTok("an index access method").text;
|
|
1505
|
+
const node: OperatorClassNode = { statement: "operatorClass", name, default: isDefault, type, method, items: [] };
|
|
1506
|
+
if (this.accept("FAMILY")) node.family = this.qualifiedName("an operator family name");
|
|
1507
|
+
this.expect("AS");
|
|
1508
|
+
do node.items.push(this.operatorClassItem());
|
|
1509
|
+
while (this.acceptPunct(","));
|
|
1510
|
+
return node;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
private operatorFamily(): OperatorFamilyNode {
|
|
1514
|
+
const name = this.qualifiedName("an operator family name");
|
|
1515
|
+
this.expect("USING");
|
|
1516
|
+
return { statement: "operatorFamily", name, method: this.nameTok("an index access method").text };
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
/** After `CREATE TEXT SEARCH`: a dictionary or a configuration. A parser and a template are C code. */
|
|
1520
|
+
private textSearch(): TextSearchDictionaryNode | TextSearchConfigurationNode {
|
|
1521
|
+
if (this.accept("DICTIONARY")) {
|
|
1522
|
+
const name = this.qualifiedName("a text search dictionary name");
|
|
1523
|
+
const options = this.definition("a dictionary option");
|
|
1524
|
+
// The options past TEMPLATE belong to the template; a name given twice is still wrong.
|
|
1525
|
+
this.checkDefinition(options, options.map((o) => o.name), ["template"], "a text search dictionary");
|
|
1526
|
+
return { statement: "textSearchDictionary", name, options };
|
|
1527
|
+
}
|
|
1528
|
+
if (this.accept("CONFIGURATION")) {
|
|
1529
|
+
const name = this.qualifiedName("a text search configuration name");
|
|
1530
|
+
const options = this.definition("a configuration option");
|
|
1531
|
+
this.checkDefinition(options, ["parser", "copy"], [], "a text search configuration");
|
|
1532
|
+
if (options.some((o) => o.name === "copy")) this.fail("expected PARSER (COPY copies mappings chant does not read; name the parser and write the mappings)", this.tokens[options.find((o) => o.name === "copy")!.nameSpan.from]);
|
|
1533
|
+
if (!options.some((o) => o.name === "parser")) this.fail("expected PARSER (a configuration needs the parser that splits text into tokens)", this.lastSeen());
|
|
1534
|
+
return { statement: "textSearchConfiguration", name, options };
|
|
1535
|
+
}
|
|
1536
|
+
return this.fail("expected DICTIONARY or CONFIGURATION (a text search parser and a text search template are C code an extension installs)");
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
/** `ALTER TEXT SEARCH CONFIGURATION name ADD MAPPING FOR token_type [, ...] WITH dictionary [, ...]`. */
|
|
1540
|
+
private textSearchMapping(): TextSearchMappingNode {
|
|
1541
|
+
const name = this.qualifiedName("a text search configuration name");
|
|
1542
|
+
if (!this.acceptSeq("ADD", "MAPPING")) this.fail("expected ADD MAPPING (a configuration's mappings are declared with ADD MAPPING after its CREATE)");
|
|
1543
|
+
this.expect("FOR");
|
|
1544
|
+
const node: TextSearchMappingNode = { statement: "textSearchMapping", name, tokens: [], dictionaries: [] };
|
|
1545
|
+
do node.tokens.push((({ text, span }) => ({ name: text, span }))(this.nameTok("a token type")));
|
|
1546
|
+
while (this.acceptPunct(","));
|
|
1547
|
+
this.expect("WITH");
|
|
1548
|
+
do node.dictionaries.push(this.qualifiedName("a text search dictionary name"));
|
|
1549
|
+
while (this.acceptPunct(","));
|
|
1550
|
+
return node;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/** `CREATE FOREIGN TABLE`: the column list form. A key, a generated column, INHERITS and PARTITION OF are not declared. */
|
|
1554
|
+
private foreignTable(): ForeignTableNode {
|
|
1555
|
+
const ifNotExists = this.ifNotExists();
|
|
1556
|
+
const name = this.qualifiedName("a foreign table name");
|
|
1557
|
+
if (kw(this.peek(), "PARTITION")) this.fail("expected the column list (a foreign table that is a partition, PARTITION OF, is not declared here)");
|
|
1558
|
+
const node: ForeignTableNode = { statement: "foreignTable", ifNotExists, name, columns: [], constraints: [], server: { pieces: [], span: this.span(this.idx(), []) }, options: [] };
|
|
1559
|
+
this.expectPunct("(");
|
|
1560
|
+
if (!this.acceptPunct(")")) {
|
|
1561
|
+
for (;;) {
|
|
1562
|
+
if (kw(this.peek(), "LIKE")) this.fail("LIKE is not declared on a foreign table; write its columns");
|
|
1563
|
+
const c = this.tableConstraint();
|
|
1564
|
+
if (c) node.constraints.push(c);
|
|
1565
|
+
else node.columns.push(this.column(true, true));
|
|
1566
|
+
if (this.acceptPunct(",")) continue;
|
|
1567
|
+
this.expectPunct(")");
|
|
1568
|
+
break;
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
if (kw(this.peek(), "INHERITS")) this.fail("expected SERVER (INHERITS is not declared on a foreign table)");
|
|
1572
|
+
this.expect("SERVER");
|
|
1573
|
+
node.server = this.databaseName("a server name");
|
|
1574
|
+
if (this.accept("OPTIONS")) node.options = this.genericOptions();
|
|
1575
|
+
// A foreign table has CHECK and NOT NULL constraints and a default; Postgres refuses the rest, and a generated column is not read.
|
|
1576
|
+
const bad = (c: ConstraintNode, what: string): never => this.fail(`${what} (a foreign table holds CHECK and NOT NULL constraints only; the remote server keeps the rest)`, this.tokens[c.span.from]);
|
|
1577
|
+
for (const c of [...node.constraints, ...node.columns.flatMap((x) => x.constraints)]) {
|
|
1578
|
+
if (c.kind !== "CHECK" && c.kind !== "NOT NULL") bad(c, `expected CHECK or NOT NULL, not ${c.kind}`);
|
|
1579
|
+
if (c.notEnforced !== undefined) bad(c, "ENFORCED and NOT ENFORCED are 18's and are not declared on a foreign table");
|
|
1580
|
+
}
|
|
1581
|
+
for (const col of node.columns) if (col.generated) this.fail(`expected no generated column (${col.name} is GENERATED ${col.generated.kind.toUpperCase()}; a foreign table's generated columns are not declared)`, this.tokens[col.nameSpan.from]);
|
|
1582
|
+
return node;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
private statistics(): StatisticsNode {
|
|
1586
|
+
const ifNotExists = this.ifNotExists();
|
|
1587
|
+
const name = this.qualifiedName("a statistics name");
|
|
1588
|
+
const kinds: string[] = [];
|
|
1589
|
+
if (this.isPunct("(")) {
|
|
1590
|
+
for (const k of this.nameList("a statistics kind")) {
|
|
1591
|
+
if (!STATISTICS_KINDS.includes(k.name)) this.fail(`expected a statistics kind (${STATISTICS_KINDS.join(", ")})`, this.tokens[k.span.from]);
|
|
1592
|
+
kinds.push(k.name);
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
this.expect("ON");
|
|
1596
|
+
const targets: Span[] = [];
|
|
1597
|
+
do targets.push(this.expr(["FROM"]));
|
|
1598
|
+
while (this.acceptPunct(","));
|
|
1599
|
+
this.expect("FROM");
|
|
1600
|
+
const table = this.qualifiedName("a table name");
|
|
1601
|
+
return { statement: "statistics", ifNotExists, name, kinds, targets, table };
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
private foreignDataWrapper(): ForeignDataWrapperNode {
|
|
1605
|
+
const node: ForeignDataWrapperNode = { statement: "foreignDataWrapper", name: this.databaseName("a foreign data wrapper name"), options: [] };
|
|
1606
|
+
for (;;) {
|
|
1607
|
+
if (this.accept("HANDLER")) node.handler = this.qualifiedName("a handler function");
|
|
1608
|
+
else if (this.acceptSeq("NO", "HANDLER")) node.handler = null;
|
|
1609
|
+
else if (this.accept("VALIDATOR")) node.validator = this.qualifiedName("a validator function");
|
|
1610
|
+
else if (this.acceptSeq("NO", "VALIDATOR")) node.validator = null;
|
|
1611
|
+
else if (this.accept("OPTIONS")) node.options = this.genericOptions();
|
|
1612
|
+
else return node;
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
private foreignServer(): ForeignServerNode {
|
|
1617
|
+
const ifNotExists = this.ifNotExists();
|
|
1618
|
+
const name = this.databaseName("a server name");
|
|
1619
|
+
const node: Partial<ForeignServerNode> & { statement: "foreignServer" } = { statement: "foreignServer", ifNotExists, name, options: [] };
|
|
1620
|
+
const string = (what: string): Span => {
|
|
1621
|
+
const t = this.next();
|
|
1622
|
+
if (t.kind !== "string" && t.kind !== "ref") this.fail(`expected ${what} as a string`, t);
|
|
1623
|
+
return this.span(this.idx(-1), t.kind === "ref" ? [t.part] : []);
|
|
1624
|
+
};
|
|
1625
|
+
if (this.accept("TYPE")) node.type = string("the server type");
|
|
1626
|
+
if (this.accept("VERSION")) node.version = string("the server version");
|
|
1627
|
+
if (!this.acceptSeq("FOREIGN", "DATA", "WRAPPER")) this.fail("expected FOREIGN DATA WRAPPER (a server names the wrapper it is for)");
|
|
1628
|
+
node.wrapper = this.qualifiedName("a foreign data wrapper name");
|
|
1629
|
+
if (this.accept("OPTIONS")) node.options = this.genericOptions();
|
|
1630
|
+
return node as ForeignServerNode;
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
private publication(): PublicationNode {
|
|
1634
|
+
const node: PublicationNode = { statement: "publication", name: this.databaseName("a publication name"), allTables: false, items: [], options: [] };
|
|
1635
|
+
if (this.accept("FOR")) {
|
|
1636
|
+
if (this.acceptSeq("ALL", "TABLES")) node.allTables = true;
|
|
1637
|
+
else {
|
|
1638
|
+
let mode: "table" | "schema" | undefined;
|
|
1639
|
+
do {
|
|
1640
|
+
if (this.accept("TABLE")) mode = "table";
|
|
1641
|
+
else if (this.acceptSeq("TABLES", "IN", "SCHEMA")) mode = "schema";
|
|
1642
|
+
else if (mode === undefined) this.fail("expected ALL TABLES, TABLE or TABLES IN SCHEMA");
|
|
1643
|
+
if (mode === "schema") {
|
|
1644
|
+
node.items.push({ kind: "schema", schema: this.qualifiedName("a schema name") });
|
|
1645
|
+
continue;
|
|
1646
|
+
}
|
|
1647
|
+
this.accept("ONLY");
|
|
1648
|
+
const table = this.qualifiedName("a table name");
|
|
1649
|
+
if (this.isOp("*")) this.p++;
|
|
1650
|
+
const item: PublicationItem = { kind: "table", table };
|
|
1651
|
+
if (this.isPunct("(")) item.columns = this.nameList("a column name");
|
|
1652
|
+
if (this.accept("WHERE")) item.where = this.checkedParens();
|
|
1653
|
+
node.items.push(item);
|
|
1654
|
+
} while (this.acceptPunct(","));
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
if (kw(this.peek(), "WITH") && this.isPunct("(", 1)) {
|
|
1658
|
+
this.p++;
|
|
1659
|
+
node.options = this.definition("a publication option");
|
|
1660
|
+
this.checkDefinition(node.options, PUBLICATION_OPTIONS, [], "a publication");
|
|
1661
|
+
}
|
|
1662
|
+
return node;
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1242
1665
|
private table(persistence: TableNode["persistence"]): TableNode {
|
|
1243
1666
|
const ifNotExists = this.ifNotExists();
|
|
1244
1667
|
const node: TableNode = { statement: "table", persistence, ifNotExists, name: this.qualifiedName("a table name"), columns: [], constraints: [], like: [] };
|
|
@@ -1850,6 +2273,34 @@ class PgParser extends SqlCursor {
|
|
|
1850
2273
|
const node: CommentNode = { statement: "comment", objectType, target, cast: { source, target: castTarget } };
|
|
1851
2274
|
if (!this.accept("NULL")) node.text = this.commentText();
|
|
1852
2275
|
return node;
|
|
2276
|
+
} else if (this.acceptSeq("FOREIGN", "DATA", "WRAPPER")) {
|
|
2277
|
+
objectType = "FOREIGN DATA WRAPPER";
|
|
2278
|
+
target = this.qualifiedName("a foreign data wrapper name");
|
|
2279
|
+
} else if (kw(this.peek(), "OPERATOR") && kw(this.peek(1), "CLASS", "FAMILY") && !this.isPunct(".", 2)) {
|
|
2280
|
+
this.p++;
|
|
2281
|
+
objectType = `OPERATOR ${this.next().text.toUpperCase()}`;
|
|
2282
|
+
target = this.qualifiedName(`an ${objectType.toLowerCase()} name`);
|
|
2283
|
+
this.expect("USING");
|
|
2284
|
+
const using = this.nameTok("an index access method").text;
|
|
2285
|
+
this.expect("IS");
|
|
2286
|
+
const node: CommentNode = { statement: "comment", objectType, target, using };
|
|
2287
|
+
if (!this.accept("NULL")) node.text = this.commentText();
|
|
2288
|
+
return node;
|
|
2289
|
+
} else if (this.acceptSeq("TEXT", "SEARCH")) {
|
|
2290
|
+
if (!this.accept("CONFIGURATION", "DICTIONARY")) this.fail("expected CONFIGURATION or DICTIONARY");
|
|
2291
|
+
objectType = `TEXT SEARCH ${this.lastSeen()!.text.toUpperCase()}`;
|
|
2292
|
+
target = this.qualifiedName(`a ${objectType.toLowerCase()} name`);
|
|
2293
|
+
} else if (this.acceptSeq("FOREIGN", "TABLE")) {
|
|
2294
|
+
objectType = "FOREIGN TABLE";
|
|
2295
|
+
target = this.qualifiedName("a foreign table name");
|
|
2296
|
+
} else if (this.accept("OPERATOR")) {
|
|
2297
|
+
objectType = "OPERATOR";
|
|
2298
|
+
target = this.operatorName();
|
|
2299
|
+
if (!this.isPunct("(")) this.fail("expected '(' and the operator's operand types");
|
|
2300
|
+
args = this.parenthesized();
|
|
2301
|
+
} else if (this.accept("SERVER", "PUBLICATION", "STATISTICS")) {
|
|
2302
|
+
objectType = this.lastSeen()!.text.toUpperCase();
|
|
2303
|
+
target = this.qualifiedName(`a ${objectType.toLowerCase()} name`);
|
|
1853
2304
|
} else if (this.accept("AGGREGATE", "COLLATION")) {
|
|
1854
2305
|
objectType = this.lastSeen()!.text.toUpperCase();
|
|
1855
2306
|
target = this.qualifiedName(`an ${objectType.toLowerCase()} name`);
|
|
@@ -1861,7 +2312,7 @@ class PgParser extends SqlCursor {
|
|
|
1861
2312
|
if (this.acceptSeq("MATERIALIZED", "VIEW")) objectType = "MATERIALIZED VIEW";
|
|
1862
2313
|
else if (this.accept("TABLE", "COLUMN", "INDEX", "VIEW", "SEQUENCE", "TYPE", "DOMAIN", "SCHEMA", "EXTENSION", "FUNCTION", "PROCEDURE")) {
|
|
1863
2314
|
objectType = this.tokens[this.idx(-1)]!.text.toUpperCase();
|
|
1864
|
-
} else return this.fail("expected TABLE, COLUMN, INDEX, VIEW, MATERIALIZED VIEW, SEQUENCE, TYPE, DOMAIN, SCHEMA, EXTENSION, FUNCTION, PROCEDURE, AGGREGATE, COLLATION, CAST, TRIGGER, EVENT TRIGGER, POLICY, ROLE or CONSTRAINT");
|
|
2315
|
+
} else return this.fail("expected TABLE, COLUMN, INDEX, VIEW, MATERIALIZED VIEW, SEQUENCE, TYPE, DOMAIN, SCHEMA, EXTENSION, FUNCTION, PROCEDURE, AGGREGATE, COLLATION, CAST, OPERATOR, TRIGGER, EVENT TRIGGER, STATISTICS, FOREIGN TABLE, FOREIGN DATA WRAPPER, SERVER, PUBLICATION, OPERATOR CLASS, OPERATOR FAMILY, TEXT SEARCH CONFIGURATION, TEXT SEARCH DICTIONARY, POLICY, ROLE or CONSTRAINT");
|
|
1865
2316
|
target = this.qualifiedName("an object name");
|
|
1866
2317
|
if ((objectType === "FUNCTION" || objectType === "PROCEDURE") && this.isPunct("(")) args = this.parenthesized();
|
|
1867
2318
|
}
|
|
@@ -43,6 +43,16 @@ const TAG: Record<string, (s: TemplateStringsArray) => { props: object }> = {
|
|
|
43
43
|
[POSTGRES_ENTITY_TYPES.collation]: tags.collation,
|
|
44
44
|
[POSTGRES_ENTITY_TYPES.cast]: tags.cast,
|
|
45
45
|
[POSTGRES_ENTITY_TYPES.eventTrigger]: tags.eventTrigger,
|
|
46
|
+
[POSTGRES_ENTITY_TYPES.operator]: tags.operator,
|
|
47
|
+
[POSTGRES_ENTITY_TYPES.operatorClass]: tags.operatorClass,
|
|
48
|
+
[POSTGRES_ENTITY_TYPES.operatorFamily]: tags.operatorFamily,
|
|
49
|
+
[POSTGRES_ENTITY_TYPES.foreignTable]: tags.foreignTable,
|
|
50
|
+
[POSTGRES_ENTITY_TYPES.textSearchConfiguration]: tags.textSearchConfiguration,
|
|
51
|
+
[POSTGRES_ENTITY_TYPES.textSearchDictionary]: tags.textSearchDictionary,
|
|
52
|
+
[POSTGRES_ENTITY_TYPES.statistics]: tags.statistics,
|
|
53
|
+
[POSTGRES_ENTITY_TYPES.foreignDataWrapper]: tags.foreignDataWrapper,
|
|
54
|
+
[POSTGRES_ENTITY_TYPES.foreignServer]: tags.foreignServer,
|
|
55
|
+
[POSTGRES_ENTITY_TYPES.publication]: tags.publication,
|
|
46
56
|
[POSTGRES_ENTITY_TYPES.extension]: tags.extension,
|
|
47
57
|
[POSTGRES_ENTITY_TYPES.function]: tags.func,
|
|
48
58
|
[POSTGRES_ENTITY_TYPES.procedure]: tags.procedure,
|
|
@@ -137,6 +147,24 @@ const PROP_OF_FIELD: Record<string, string[]> = {
|
|
|
137
147
|
context: ["context"],
|
|
138
148
|
event: ["event"],
|
|
139
149
|
tags: ["tags"],
|
|
150
|
+
targets: ["targets"],
|
|
151
|
+
kinds: ["kinds"],
|
|
152
|
+
handler: ["handler", "handlerName", "noHandler"],
|
|
153
|
+
validator: ["validator", "validatorName", "noValidator"],
|
|
154
|
+
serverType: ["serverType"],
|
|
155
|
+
wrapper: ["wrapper", "wrapperName"],
|
|
156
|
+
server: ["serverName"],
|
|
157
|
+
family: ["family"],
|
|
158
|
+
items: ["items"],
|
|
159
|
+
template: ["template"],
|
|
160
|
+
parser: ["parser"],
|
|
161
|
+
mappings: ["mappings"],
|
|
162
|
+
allTables: ["allTables"],
|
|
163
|
+
tables: ["tables"],
|
|
164
|
+
schemas: ["schemas"],
|
|
165
|
+
publish: [],
|
|
166
|
+
viaRoot: [],
|
|
167
|
+
generatedColumns: [],
|
|
140
168
|
};
|
|
141
169
|
|
|
142
170
|
/** Props keys that hold constraints, by constraint kind. */
|
|
@@ -159,6 +187,7 @@ export function inDeclaredVocabulary(declared: Props, live: Props, d: CanonicalP
|
|
|
159
187
|
if (d.schema === l.schema) adopt("schema");
|
|
160
188
|
// An aggregate's argument types and a cast's two types are its identity: the same, they are the declaration's.
|
|
161
189
|
if (d.kind === "aggregate" && d.signature === l.signature) for (const key of ["args", "orderBy"]) adopt(key);
|
|
190
|
+
if (d.kind === "operator" && d.signature === l.signature) for (const key of ["leftArg", "rightArg"]) adopt(key);
|
|
162
191
|
if (d.kind === "cast" && d.name === l.name) for (const key of ["sourceType", "targetType"]) adopt(key);
|
|
163
192
|
|
|
164
193
|
const fieldKeys = new Set([...Object.keys(d.fields), ...Object.keys(l.fields)]);
|
|
@@ -172,7 +201,7 @@ export function inDeclaredVocabulary(declared: Props, live: Props, d: CanonicalP
|
|
|
172
201
|
if (!fieldKeys.has(f)) for (const key of keys) if (f !== "schema" || d.kind === "extension") adopt(key);
|
|
173
202
|
}
|
|
174
203
|
|
|
175
|
-
if (d.kind === "table") {
|
|
204
|
+
if (d.kind === "table" || d.kind === "foreignTable") {
|
|
176
205
|
const declaredColumns = (declared.columns as unknown[] | undefined) ?? [];
|
|
177
206
|
const liveColumns = (live.columns as unknown[] | undefined) ?? [];
|
|
178
207
|
// Columns are matched by name and listed in the declaration's order, the
|
|
@@ -193,7 +222,16 @@ export function inDeclaredVocabulary(declared: Props, live: Props, d: CanonicalP
|
|
|
193
222
|
].map((c) => c.value);
|
|
194
223
|
}
|
|
195
224
|
// An aggregate's or a collation's `options` is the declaration's only when every field read from it is the same (a role's `options` shares the key).
|
|
196
|
-
const optionFields =
|
|
225
|
+
const optionFields =
|
|
226
|
+
d.kind === "aggregate" || d.kind === "operator"
|
|
227
|
+
? ["definition"]
|
|
228
|
+
: d.kind === "collation"
|
|
229
|
+
? ["provider", "lcCollate", "lcCtype", "locale", "nondeterministic", "rules"]
|
|
230
|
+
: d.kind === "foreignDataWrapper" || d.kind === "foreignServer" || d.kind === "foreignTable" || d.kind === "textSearchDictionary"
|
|
231
|
+
? ["options"]
|
|
232
|
+
: d.kind === "publication"
|
|
233
|
+
? ["publish", "viaRoot", "generatedColumns"]
|
|
234
|
+
: undefined;
|
|
197
235
|
if (optionFields) {
|
|
198
236
|
if (optionFields.every((f) => JSON.stringify(d.fields[f]) === JSON.stringify(l.fields[f]))) adopt("options");
|
|
199
237
|
else out.options = live.options;
|
|
@@ -203,9 +241,9 @@ export function inDeclaredVocabulary(declared: Props, live: Props, d: CanonicalP
|
|
|
203
241
|
out.method = live.method;
|
|
204
242
|
out.functionArgs = live.functionArgs;
|
|
205
243
|
}
|
|
206
|
-
if (d.kind === "table" || d.kind === "domain") {
|
|
244
|
+
if (d.kind === "table" || d.kind === "domain" || d.kind === "foreignTable") {
|
|
207
245
|
// A constraint the declaration says the same as the server is the declaration's (its name included or left out).
|
|
208
|
-
const kinds = d.kind === "
|
|
246
|
+
const kinds = d.kind === "table" ? Object.keys(CONSTRAINT_PROPS) : ["CHECK"];
|
|
209
247
|
for (const kind of kinds) {
|
|
210
248
|
const key = CONSTRAINT_PROPS[kind]!;
|
|
211
249
|
const dl = d.constraints.filter((c) => c.kind === kind);
|