@dotdo/postgres 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +868 -0
- package/dist/cdc/change-stream.d.ts +44 -0
- package/dist/cdc/change-stream.d.ts.map +1 -0
- package/dist/cdc/change-stream.js +95 -0
- package/dist/cdc/change-stream.js.map +1 -0
- package/dist/cdc/filter.d.ts +58 -0
- package/dist/cdc/filter.d.ts.map +1 -0
- package/dist/cdc/filter.js +520 -0
- package/dist/cdc/filter.js.map +1 -0
- package/dist/cdc/index.d.ts +47 -0
- package/dist/cdc/index.d.ts.map +1 -0
- package/dist/cdc/index.js +50 -0
- package/dist/cdc/index.js.map +1 -0
- package/dist/cdc/resume-token.d.ts +60 -0
- package/dist/cdc/resume-token.d.ts.map +1 -0
- package/dist/cdc/resume-token.js +228 -0
- package/dist/cdc/resume-token.js.map +1 -0
- package/dist/cdc/transport/index.d.ts +7 -0
- package/dist/cdc/transport/index.d.ts.map +1 -0
- package/dist/cdc/transport/index.js +7 -0
- package/dist/cdc/transport/index.js.map +1 -0
- package/dist/cdc/transport/sse.d.ts +120 -0
- package/dist/cdc/transport/sse.d.ts.map +1 -0
- package/dist/cdc/transport/sse.js +590 -0
- package/dist/cdc/transport/sse.js.map +1 -0
- package/dist/cdc/transport/websocket.d.ts +130 -0
- package/dist/cdc/transport/websocket.d.ts.map +1 -0
- package/dist/cdc/transport/websocket.js +688 -0
- package/dist/cdc/transport/websocket.js.map +1 -0
- package/dist/cdc/types.d.ts +306 -0
- package/dist/cdc/types.d.ts.map +1 -0
- package/dist/cdc/types.js +8 -0
- package/dist/cdc/types.js.map +1 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +25 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/memory.d.ts +139 -0
- package/dist/config/memory.d.ts.map +1 -0
- package/dist/config/memory.js +157 -0
- package/dist/config/memory.js.map +1 -0
- package/dist/config/storage.d.ts +157 -0
- package/dist/config/storage.d.ts.map +1 -0
- package/dist/config/storage.js +178 -0
- package/dist/config/storage.js.map +1 -0
- package/dist/config/streaming.d.ts +117 -0
- package/dist/config/streaming.d.ts.map +1 -0
- package/dist/config/streaming.js +132 -0
- package/dist/config/streaming.js.map +1 -0
- package/dist/config/timeouts.d.ts +168 -0
- package/dist/config/timeouts.d.ts.map +1 -0
- package/dist/config/timeouts.js +192 -0
- package/dist/config/timeouts.js.map +1 -0
- package/dist/extensions/config.d.ts +89 -0
- package/dist/extensions/config.d.ts.map +1 -0
- package/dist/extensions/config.js +216 -0
- package/dist/extensions/config.js.map +1 -0
- package/dist/extensions/geo.d.ts +452 -0
- package/dist/extensions/geo.d.ts.map +1 -0
- package/dist/extensions/geo.js +583 -0
- package/dist/extensions/geo.js.map +1 -0
- package/dist/extensions/index.d.ts +167 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +99 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/loader.d.ts +226 -0
- package/dist/extensions/loader.d.ts.map +1 -0
- package/dist/extensions/loader.js +456 -0
- package/dist/extensions/loader.js.map +1 -0
- package/dist/extensions/pgmq-lite.d.ts +330 -0
- package/dist/extensions/pgmq-lite.d.ts.map +1 -0
- package/dist/extensions/pgmq-lite.js +648 -0
- package/dist/extensions/pgmq-lite.js.map +1 -0
- package/dist/extensions/plugins.d.ts +260 -0
- package/dist/extensions/plugins.d.ts.map +1 -0
- package/dist/extensions/plugins.js +535 -0
- package/dist/extensions/plugins.js.map +1 -0
- package/dist/extensions/registry.d.ts +93 -0
- package/dist/extensions/registry.d.ts.map +1 -0
- package/dist/extensions/registry.js +182 -0
- package/dist/extensions/registry.js.map +1 -0
- package/dist/extensions/vector.d.ts +106 -0
- package/dist/extensions/vector.d.ts.map +1 -0
- package/dist/extensions/vector.js +129 -0
- package/dist/extensions/vector.js.map +1 -0
- package/dist/iceberg/analytics.d.ts +279 -0
- package/dist/iceberg/analytics.d.ts.map +1 -0
- package/dist/iceberg/analytics.js +448 -0
- package/dist/iceberg/analytics.js.map +1 -0
- package/dist/iceberg/catalog-api.d.ts +39 -0
- package/dist/iceberg/catalog-api.d.ts.map +1 -0
- package/dist/iceberg/catalog-api.js +388 -0
- package/dist/iceberg/catalog-api.js.map +1 -0
- package/dist/iceberg/catalog.d.ts +401 -0
- package/dist/iceberg/catalog.d.ts.map +1 -0
- package/dist/iceberg/catalog.js +677 -0
- package/dist/iceberg/catalog.js.map +1 -0
- package/dist/iceberg/duckdb-wasm.d.ts +447 -0
- package/dist/iceberg/duckdb-wasm.d.ts.map +1 -0
- package/dist/iceberg/duckdb-wasm.js +600 -0
- package/dist/iceberg/duckdb-wasm.js.map +1 -0
- package/dist/iceberg/index.d.ts +92 -0
- package/dist/iceberg/index.d.ts.map +1 -0
- package/dist/iceberg/index.js +119 -0
- package/dist/iceberg/index.js.map +1 -0
- package/dist/iceberg/metadata.d.ts +214 -0
- package/dist/iceberg/metadata.d.ts.map +1 -0
- package/dist/iceberg/metadata.js +535 -0
- package/dist/iceberg/metadata.js.map +1 -0
- package/dist/iceberg/optimizer.d.ts +296 -0
- package/dist/iceberg/optimizer.d.ts.map +1 -0
- package/dist/iceberg/optimizer.js +889 -0
- package/dist/iceberg/optimizer.js.map +1 -0
- package/dist/iceberg/parquet.d.ts +447 -0
- package/dist/iceberg/parquet.d.ts.map +1 -0
- package/dist/iceberg/parquet.js +1225 -0
- package/dist/iceberg/parquet.js.map +1 -0
- package/dist/iceberg/r2-organization.d.ts +422 -0
- package/dist/iceberg/r2-organization.d.ts.map +1 -0
- package/dist/iceberg/r2-organization.js +672 -0
- package/dist/iceberg/r2-organization.js.map +1 -0
- package/dist/iceberg/scheduler-do-example.d.ts +158 -0
- package/dist/iceberg/scheduler-do-example.d.ts.map +1 -0
- package/dist/iceberg/scheduler-do-example.js +261 -0
- package/dist/iceberg/scheduler-do-example.js.map +1 -0
- package/dist/iceberg/scheduler.d.ts +434 -0
- package/dist/iceberg/scheduler.d.ts.map +1 -0
- package/dist/iceberg/scheduler.js +818 -0
- package/dist/iceberg/scheduler.js.map +1 -0
- package/dist/iceberg/schema.d.ts +149 -0
- package/dist/iceberg/schema.d.ts.map +1 -0
- package/dist/iceberg/schema.js +525 -0
- package/dist/iceberg/schema.js.map +1 -0
- package/dist/iceberg/snapshot-manager.d.ts +406 -0
- package/dist/iceberg/snapshot-manager.d.ts.map +1 -0
- package/dist/iceberg/snapshot-manager.js +934 -0
- package/dist/iceberg/snapshot-manager.js.map +1 -0
- package/dist/iceberg/sql-router.d.ts +194 -0
- package/dist/iceberg/sql-router.d.ts.map +1 -0
- package/dist/iceberg/sql-router.js +180 -0
- package/dist/iceberg/sql-router.js.map +1 -0
- package/dist/iceberg/test-fixtures.d.ts +151 -0
- package/dist/iceberg/test-fixtures.d.ts.map +1 -0
- package/dist/iceberg/test-fixtures.js +446 -0
- package/dist/iceberg/test-fixtures.js.map +1 -0
- package/dist/iceberg/time-travel-api.d.ts +102 -0
- package/dist/iceberg/time-travel-api.d.ts.map +1 -0
- package/dist/iceberg/time-travel-api.js +437 -0
- package/dist/iceberg/time-travel-api.js.map +1 -0
- package/dist/iceberg/time-travel.d.ts +293 -0
- package/dist/iceberg/time-travel.d.ts.map +1 -0
- package/dist/iceberg/time-travel.js +689 -0
- package/dist/iceberg/time-travel.js.map +1 -0
- package/dist/iceberg/transformer.d.ts +356 -0
- package/dist/iceberg/transformer.d.ts.map +1 -0
- package/dist/iceberg/transformer.js +770 -0
- package/dist/iceberg/transformer.js.map +1 -0
- package/dist/iceberg/types.d.ts +318 -0
- package/dist/iceberg/types.d.ts.map +1 -0
- package/dist/iceberg/types.js +9 -0
- package/dist/iceberg/types.js.map +1 -0
- package/dist/iceberg/writer.d.ts +144 -0
- package/dist/iceberg/writer.d.ts.map +1 -0
- package/dist/iceberg/writer.js +452 -0
- package/dist/iceberg/writer.js.map +1 -0
- package/dist/index.d.ts +50 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/dist/lineage/index.d.ts +11 -0
- package/dist/lineage/index.d.ts.map +1 -0
- package/dist/lineage/index.js +11 -0
- package/dist/lineage/index.js.map +1 -0
- package/dist/lineage/integration.d.ts +134 -0
- package/dist/lineage/integration.d.ts.map +1 -0
- package/dist/lineage/integration.js +258 -0
- package/dist/lineage/integration.js.map +1 -0
- package/dist/lineage/tracker.d.ts +189 -0
- package/dist/lineage/tracker.d.ts.map +1 -0
- package/dist/lineage/tracker.js +1352 -0
- package/dist/lineage/tracker.js.map +1 -0
- package/dist/lineage/types.d.ts +318 -0
- package/dist/lineage/types.d.ts.map +1 -0
- package/dist/lineage/types.js +9 -0
- package/dist/lineage/types.js.map +1 -0
- package/dist/middleware/index.d.ts +11 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +16 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/rate-limit.d.ts +397 -0
- package/dist/middleware/rate-limit.d.ts.map +1 -0
- package/dist/middleware/rate-limit.js +507 -0
- package/dist/middleware/rate-limit.js.map +1 -0
- package/dist/migration-tooling/external-migration.d.ts +601 -0
- package/dist/migration-tooling/external-migration.d.ts.map +1 -0
- package/dist/migration-tooling/external-migration.js +1612 -0
- package/dist/migration-tooling/external-migration.js.map +1 -0
- package/dist/migration-tooling/index.d.ts +19 -0
- package/dist/migration-tooling/index.d.ts.map +1 -0
- package/dist/migration-tooling/index.js +19 -0
- package/dist/migration-tooling/index.js.map +1 -0
- package/dist/migrations/auto-migrator.d.ts +289 -0
- package/dist/migrations/auto-migrator.d.ts.map +1 -0
- package/dist/migrations/auto-migrator.js +396 -0
- package/dist/migrations/auto-migrator.js.map +1 -0
- package/dist/migrations/bulk-orchestrator.d.ts +403 -0
- package/dist/migrations/bulk-orchestrator.d.ts.map +1 -0
- package/dist/migrations/bulk-orchestrator.js +646 -0
- package/dist/migrations/bulk-orchestrator.js.map +1 -0
- package/dist/migrations/compatibility.d.ts +216 -0
- package/dist/migrations/compatibility.d.ts.map +1 -0
- package/dist/migrations/compatibility.js +651 -0
- package/dist/migrations/compatibility.js.map +1 -0
- package/dist/migrations/do-migrations.d.ts +101 -0
- package/dist/migrations/do-migrations.d.ts.map +1 -0
- package/dist/migrations/do-migrations.js +1060 -0
- package/dist/migrations/do-migrations.js.map +1 -0
- package/dist/migrations/do-migrations.types.d.ts +550 -0
- package/dist/migrations/do-migrations.types.d.ts.map +1 -0
- package/dist/migrations/do-migrations.types.js +15 -0
- package/dist/migrations/do-migrations.types.js.map +1 -0
- package/dist/migrations/drizzle-compat.d.ts +163 -0
- package/dist/migrations/drizzle-compat.d.ts.map +1 -0
- package/dist/migrations/drizzle-compat.js +273 -0
- package/dist/migrations/drizzle-compat.js.map +1 -0
- package/dist/migrations/index.d.ts +109 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +127 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/migrations/migration-api.d.ts +161 -0
- package/dist/migrations/migration-api.d.ts.map +1 -0
- package/dist/migrations/migration-api.js +499 -0
- package/dist/migrations/migration-api.js.map +1 -0
- package/dist/migrations/progress-tracker-do.d.ts +195 -0
- package/dist/migrations/progress-tracker-do.d.ts.map +1 -0
- package/dist/migrations/progress-tracker-do.js +339 -0
- package/dist/migrations/progress-tracker-do.js.map +1 -0
- package/dist/migrations/progress-tracker-kv.d.ts +103 -0
- package/dist/migrations/progress-tracker-kv.d.ts.map +1 -0
- package/dist/migrations/progress-tracker-kv.js +231 -0
- package/dist/migrations/progress-tracker-kv.js.map +1 -0
- package/dist/migrations/progress-tracker.d.ts +320 -0
- package/dist/migrations/progress-tracker.d.ts.map +1 -0
- package/dist/migrations/progress-tracker.js +443 -0
- package/dist/migrations/progress-tracker.js.map +1 -0
- package/dist/migrations/registry.d.ts +231 -0
- package/dist/migrations/registry.d.ts.map +1 -0
- package/dist/migrations/registry.js +376 -0
- package/dist/migrations/registry.js.map +1 -0
- package/dist/migrations/runner.d.ts +197 -0
- package/dist/migrations/runner.d.ts.map +1 -0
- package/dist/migrations/runner.js +1167 -0
- package/dist/migrations/runner.js.map +1 -0
- package/dist/migrations/schema-generator.d.ts +111 -0
- package/dist/migrations/schema-generator.d.ts.map +1 -0
- package/dist/migrations/schema-generator.js +335 -0
- package/dist/migrations/schema-generator.js.map +1 -0
- package/dist/migrations/testing.d.ts +321 -0
- package/dist/migrations/testing.d.ts.map +1 -0
- package/dist/migrations/testing.js +645 -0
- package/dist/migrations/testing.js.map +1 -0
- package/dist/migrations/types.d.ts +503 -0
- package/dist/migrations/types.d.ts.map +1 -0
- package/dist/migrations/types.js +11 -0
- package/dist/migrations/types.js.map +1 -0
- package/dist/migrations/validator.d.ts +215 -0
- package/dist/migrations/validator.d.ts.map +1 -0
- package/dist/migrations/validator.js +494 -0
- package/dist/migrations/validator.js.map +1 -0
- package/dist/observability/alerting.d.ts +116 -0
- package/dist/observability/alerting.d.ts.map +1 -0
- package/dist/observability/alerting.js +353 -0
- package/dist/observability/alerting.js.map +1 -0
- package/dist/observability/analytics-engine.d.ts +357 -0
- package/dist/observability/analytics-engine.d.ts.map +1 -0
- package/dist/observability/analytics-engine.js +430 -0
- package/dist/observability/analytics-engine.js.map +1 -0
- package/dist/observability/cost-metrics.d.ts +269 -0
- package/dist/observability/cost-metrics.d.ts.map +1 -0
- package/dist/observability/cost-metrics.js +560 -0
- package/dist/observability/cost-metrics.js.map +1 -0
- package/dist/observability/cross-do-tracing.d.ts +305 -0
- package/dist/observability/cross-do-tracing.d.ts.map +1 -0
- package/dist/observability/cross-do-tracing.js +431 -0
- package/dist/observability/cross-do-tracing.js.map +1 -0
- package/dist/observability/error-rate-collector.d.ts +163 -0
- package/dist/observability/error-rate-collector.d.ts.map +1 -0
- package/dist/observability/error-rate-collector.js +306 -0
- package/dist/observability/error-rate-collector.js.map +1 -0
- package/dist/observability/exporters.d.ts +231 -0
- package/dist/observability/exporters.d.ts.map +1 -0
- package/dist/observability/exporters.js +479 -0
- package/dist/observability/exporters.js.map +1 -0
- package/dist/observability/health-check.d.ts +106 -0
- package/dist/observability/health-check.d.ts.map +1 -0
- package/dist/observability/health-check.js +243 -0
- package/dist/observability/health-check.js.map +1 -0
- package/dist/observability/index.d.ts +297 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +455 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/instrumentation.d.ts +222 -0
- package/dist/observability/instrumentation.d.ts.map +1 -0
- package/dist/observability/instrumentation.js +532 -0
- package/dist/observability/instrumentation.js.map +1 -0
- package/dist/observability/memory-metrics.d.ts +227 -0
- package/dist/observability/memory-metrics.d.ts.map +1 -0
- package/dist/observability/memory-metrics.js +688 -0
- package/dist/observability/memory-metrics.js.map +1 -0
- package/dist/observability/metrics-endpoint.d.ts +91 -0
- package/dist/observability/metrics-endpoint.d.ts.map +1 -0
- package/dist/observability/metrics-endpoint.js +246 -0
- package/dist/observability/metrics-endpoint.js.map +1 -0
- package/dist/observability/metrics.d.ts +88 -0
- package/dist/observability/metrics.d.ts.map +1 -0
- package/dist/observability/metrics.js +253 -0
- package/dist/observability/metrics.js.map +1 -0
- package/dist/observability/observability-features.d.ts +488 -0
- package/dist/observability/observability-features.d.ts.map +1 -0
- package/dist/observability/observability-features.js +773 -0
- package/dist/observability/observability-features.js.map +1 -0
- package/dist/observability/prometheus.d.ts +39 -0
- package/dist/observability/prometheus.d.ts.map +1 -0
- package/dist/observability/prometheus.js +120 -0
- package/dist/observability/prometheus.js.map +1 -0
- package/dist/observability/propagation.d.ts +126 -0
- package/dist/observability/propagation.d.ts.map +1 -0
- package/dist/observability/propagation.js +234 -0
- package/dist/observability/propagation.js.map +1 -0
- package/dist/observability/query-latency.d.ts +243 -0
- package/dist/observability/query-latency.d.ts.map +1 -0
- package/dist/observability/query-latency.js +292 -0
- package/dist/observability/query-latency.js.map +1 -0
- package/dist/observability/query-performance.d.ts +169 -0
- package/dist/observability/query-performance.d.ts.map +1 -0
- package/dist/observability/query-performance.js +290 -0
- package/dist/observability/query-performance.js.map +1 -0
- package/dist/observability/storage-tier-metrics.d.ts +174 -0
- package/dist/observability/storage-tier-metrics.d.ts.map +1 -0
- package/dist/observability/storage-tier-metrics.js +306 -0
- package/dist/observability/storage-tier-metrics.js.map +1 -0
- package/dist/observability/tier-cost-optimizer.d.ts +155 -0
- package/dist/observability/tier-cost-optimizer.d.ts.map +1 -0
- package/dist/observability/tier-cost-optimizer.js +536 -0
- package/dist/observability/tier-cost-optimizer.js.map +1 -0
- package/dist/observability/tracer.d.ts +149 -0
- package/dist/observability/tracer.d.ts.map +1 -0
- package/dist/observability/tracer.js +435 -0
- package/dist/observability/tracer.js.map +1 -0
- package/dist/observability/types.d.ts +402 -0
- package/dist/observability/types.d.ts.map +1 -0
- package/dist/observability/types.js +103 -0
- package/dist/observability/types.js.map +1 -0
- package/dist/pglite/workers-pglite.d.ts +138 -0
- package/dist/pglite/workers-pglite.d.ts.map +1 -0
- package/dist/pglite/workers-pglite.js +143 -0
- package/dist/pglite/workers-pglite.js.map +1 -0
- package/dist/pglite-assets/pglite.data +0 -0
- package/dist/pglite-assets/pglite.wasm +0 -0
- package/dist/playground/index.d.ts +52 -0
- package/dist/playground/index.d.ts.map +1 -0
- package/dist/playground/index.js +55 -0
- package/dist/playground/index.js.map +1 -0
- package/dist/playground/keyboard-shortcuts.d.ts +116 -0
- package/dist/playground/keyboard-shortcuts.d.ts.map +1 -0
- package/dist/playground/keyboard-shortcuts.js +588 -0
- package/dist/playground/keyboard-shortcuts.js.map +1 -0
- package/dist/playground/playground.d.ts +82 -0
- package/dist/playground/playground.d.ts.map +1 -0
- package/dist/playground/playground.js +271 -0
- package/dist/playground/playground.js.map +1 -0
- package/dist/playground/query-executor.d.ts +115 -0
- package/dist/playground/query-executor.d.ts.map +1 -0
- package/dist/playground/query-executor.js +558 -0
- package/dist/playground/query-executor.js.map +1 -0
- package/dist/playground/query-history.d.ts +92 -0
- package/dist/playground/query-history.d.ts.map +1 -0
- package/dist/playground/query-history.js +259 -0
- package/dist/playground/query-history.js.map +1 -0
- package/dist/playground/result-formatter.d.ts +59 -0
- package/dist/playground/result-formatter.d.ts.map +1 -0
- package/dist/playground/result-formatter.js +341 -0
- package/dist/playground/result-formatter.js.map +1 -0
- package/dist/playground/sample-datasets.d.ts +77 -0
- package/dist/playground/sample-datasets.d.ts.map +1 -0
- package/dist/playground/sample-datasets.js +641 -0
- package/dist/playground/sample-datasets.js.map +1 -0
- package/dist/playground/sample-queries.d.ts +73 -0
- package/dist/playground/sample-queries.d.ts.map +1 -0
- package/dist/playground/sample-queries.js +1095 -0
- package/dist/playground/sample-queries.js.map +1 -0
- package/dist/playground/schema-explorer.d.ts +55 -0
- package/dist/playground/schema-explorer.d.ts.map +1 -0
- package/dist/playground/schema-explorer.js +473 -0
- package/dist/playground/schema-explorer.js.map +1 -0
- package/dist/playground/types.d.ts +430 -0
- package/dist/playground/types.d.ts.map +1 -0
- package/dist/playground/types.js +10 -0
- package/dist/playground/types.js.map +1 -0
- package/dist/readonly/cache-reader.d.ts +145 -0
- package/dist/readonly/cache-reader.d.ts.map +1 -0
- package/dist/readonly/cache-reader.js +198 -0
- package/dist/readonly/cache-reader.js.map +1 -0
- package/dist/readonly/config.d.ts +74 -0
- package/dist/readonly/config.d.ts.map +1 -0
- package/dist/readonly/config.js +67 -0
- package/dist/readonly/config.js.map +1 -0
- package/dist/readonly/index.d.ts +22 -0
- package/dist/readonly/index.d.ts.map +1 -0
- package/dist/readonly/index.js +17 -0
- package/dist/readonly/index.js.map +1 -0
- package/dist/readonly/pglite-wrapper.d.ts +82 -0
- package/dist/readonly/pglite-wrapper.d.ts.map +1 -0
- package/dist/readonly/pglite-wrapper.js +123 -0
- package/dist/readonly/pglite-wrapper.js.map +1 -0
- package/dist/readonly/worker.d.ts +142 -0
- package/dist/readonly/worker.d.ts.map +1 -0
- package/dist/readonly/worker.js +187 -0
- package/dist/readonly/worker.js.map +1 -0
- package/dist/readonly/write-blocker.d.ts +47 -0
- package/dist/readonly/write-blocker.d.ts.map +1 -0
- package/dist/readonly/write-blocker.js +136 -0
- package/dist/readonly/write-blocker.js.map +1 -0
- package/dist/recovery/disaster-recovery.d.ts +326 -0
- package/dist/recovery/disaster-recovery.d.ts.map +1 -0
- package/dist/recovery/disaster-recovery.js +799 -0
- package/dist/recovery/disaster-recovery.js.map +1 -0
- package/dist/recovery/index.d.ts +12 -0
- package/dist/recovery/index.d.ts.map +1 -0
- package/dist/recovery/index.js +12 -0
- package/dist/recovery/index.js.map +1 -0
- package/dist/recovery/parquet-parser.d.ts +321 -0
- package/dist/recovery/parquet-parser.d.ts.map +1 -0
- package/dist/recovery/parquet-parser.js +797 -0
- package/dist/recovery/parquet-parser.js.map +1 -0
- package/dist/retention/index.d.ts +50 -0
- package/dist/retention/index.d.ts.map +1 -0
- package/dist/retention/index.js +50 -0
- package/dist/retention/index.js.map +1 -0
- package/dist/retention/policy.d.ts +344 -0
- package/dist/retention/policy.d.ts.map +1 -0
- package/dist/retention/policy.js +472 -0
- package/dist/retention/policy.js.map +1 -0
- package/dist/retention/purger.d.ts +187 -0
- package/dist/retention/purger.d.ts.map +1 -0
- package/dist/retention/purger.js +411 -0
- package/dist/retention/purger.js.map +1 -0
- package/dist/rls/auth-integration.d.ts +280 -0
- package/dist/rls/auth-integration.d.ts.map +1 -0
- package/dist/rls/auth-integration.js +399 -0
- package/dist/rls/auth-integration.js.map +1 -0
- package/dist/rls/generator.d.ts +249 -0
- package/dist/rls/generator.d.ts.map +1 -0
- package/dist/rls/generator.js +495 -0
- package/dist/rls/generator.js.map +1 -0
- package/dist/rls/index.d.ts +26 -0
- package/dist/rls/index.d.ts.map +1 -0
- package/dist/rls/index.js +58 -0
- package/dist/rls/index.js.map +1 -0
- package/dist/rls/policy.d.ts +116 -0
- package/dist/rls/policy.d.ts.map +1 -0
- package/dist/rls/policy.js +77 -0
- package/dist/rls/policy.js.map +1 -0
- package/dist/rls/validator.d.ts +155 -0
- package/dist/rls/validator.d.ts.map +1 -0
- package/dist/rls/validator.js +792 -0
- package/dist/rls/validator.js.map +1 -0
- package/dist/routing/adaptive-router.d.ts +317 -0
- package/dist/routing/adaptive-router.d.ts.map +1 -0
- package/dist/routing/adaptive-router.js +554 -0
- package/dist/routing/adaptive-router.js.map +1 -0
- package/dist/routing/circuit-breaker.d.ts +339 -0
- package/dist/routing/circuit-breaker.d.ts.map +1 -0
- package/dist/routing/circuit-breaker.js +620 -0
- package/dist/routing/circuit-breaker.js.map +1 -0
- package/dist/routing/cost-metrics.d.ts +133 -0
- package/dist/routing/cost-metrics.d.ts.map +1 -0
- package/dist/routing/cost-metrics.js +259 -0
- package/dist/routing/cost-metrics.js.map +1 -0
- package/dist/routing/do-connection-pool.d.ts +243 -0
- package/dist/routing/do-connection-pool.d.ts.map +1 -0
- package/dist/routing/do-connection-pool.js +572 -0
- package/dist/routing/do-connection-pool.js.map +1 -0
- package/dist/routing/index.d.ts +59 -0
- package/dist/routing/index.d.ts.map +1 -0
- package/dist/routing/index.js +59 -0
- package/dist/routing/index.js.map +1 -0
- package/dist/routing/query-complexity-estimator.d.ts +73 -0
- package/dist/routing/query-complexity-estimator.d.ts.map +1 -0
- package/dist/routing/query-complexity-estimator.js +327 -0
- package/dist/routing/query-complexity-estimator.js.map +1 -0
- package/dist/routing/request-coalescing.d.ts +178 -0
- package/dist/routing/request-coalescing.d.ts.map +1 -0
- package/dist/routing/request-coalescing.js +325 -0
- package/dist/routing/request-coalescing.js.map +1 -0
- package/dist/routing/runtime-router.d.ts +107 -0
- package/dist/routing/runtime-router.d.ts.map +1 -0
- package/dist/routing/runtime-router.js +246 -0
- package/dist/routing/runtime-router.js.map +1 -0
- package/dist/routing/tenant-router.d.ts +848 -0
- package/dist/routing/tenant-router.d.ts.map +1 -0
- package/dist/routing/tenant-router.js +1056 -0
- package/dist/routing/tenant-router.js.map +1 -0
- package/dist/routing/websocket-pool.d.ts +119 -0
- package/dist/routing/websocket-pool.d.ts.map +1 -0
- package/dist/routing/websocket-pool.js +436 -0
- package/dist/routing/websocket-pool.js.map +1 -0
- package/dist/storage/cache-layer.d.ts +159 -0
- package/dist/storage/cache-layer.d.ts.map +1 -0
- package/dist/storage/cache-layer.js +245 -0
- package/dist/storage/cache-layer.js.map +1 -0
- package/dist/storage/cost-aware-tiering.d.ts +258 -0
- package/dist/storage/cost-aware-tiering.d.ts.map +1 -0
- package/dist/storage/cost-aware-tiering.js +526 -0
- package/dist/storage/cost-aware-tiering.js.map +1 -0
- package/dist/storage/index.d.ts +87 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +78 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/interfaces.d.ts +856 -0
- package/dist/storage/interfaces.d.ts.map +1 -0
- package/dist/storage/interfaces.js +69 -0
- package/dist/storage/interfaces.js.map +1 -0
- package/dist/storage/r2-layer.d.ts +226 -0
- package/dist/storage/r2-layer.d.ts.map +1 -0
- package/dist/storage/r2-layer.js +307 -0
- package/dist/storage/r2-layer.js.map +1 -0
- package/dist/storage/r2-overflow.d.ts +344 -0
- package/dist/storage/r2-overflow.d.ts.map +1 -0
- package/dist/storage/r2-overflow.js +730 -0
- package/dist/storage/r2-overflow.js.map +1 -0
- package/dist/storage/r2-page-vfs.d.ts +374 -0
- package/dist/storage/r2-page-vfs.d.ts.map +1 -0
- package/dist/storage/r2-page-vfs.js +754 -0
- package/dist/storage/r2-page-vfs.js.map +1 -0
- package/dist/storage/swr-cache.d.ts +181 -0
- package/dist/storage/swr-cache.d.ts.map +1 -0
- package/dist/storage/swr-cache.js +295 -0
- package/dist/storage/swr-cache.js.map +1 -0
- package/dist/storage/tiered-orchestrator.d.ts +951 -0
- package/dist/storage/tiered-orchestrator.d.ts.map +1 -0
- package/dist/storage/tiered-orchestrator.js +1731 -0
- package/dist/storage/tiered-orchestrator.js.map +1 -0
- package/dist/storage/tiered-vfs-swr.d.ts +279 -0
- package/dist/storage/tiered-vfs-swr.d.ts.map +1 -0
- package/dist/storage/tiered-vfs-swr.js +584 -0
- package/dist/storage/tiered-vfs-swr.js.map +1 -0
- package/dist/storage/tiered-vfs.d.ts +405 -0
- package/dist/storage/tiered-vfs.d.ts.map +1 -0
- package/dist/storage/tiered-vfs.js +833 -0
- package/dist/storage/tiered-vfs.js.map +1 -0
- package/dist/streaming/backpressure-controller.d.ts +173 -0
- package/dist/streaming/backpressure-controller.d.ts.map +1 -0
- package/dist/streaming/backpressure-controller.js +344 -0
- package/dist/streaming/backpressure-controller.js.map +1 -0
- package/dist/streaming/buffer-pool.d.ts +241 -0
- package/dist/streaming/buffer-pool.d.ts.map +1 -0
- package/dist/streaming/buffer-pool.js +381 -0
- package/dist/streaming/buffer-pool.js.map +1 -0
- package/dist/streaming/cdc-iceberg-connector.d.ts +272 -0
- package/dist/streaming/cdc-iceberg-connector.d.ts.map +1 -0
- package/dist/streaming/cdc-iceberg-connector.js +408 -0
- package/dist/streaming/cdc-iceberg-connector.js.map +1 -0
- package/dist/streaming/index.d.ts +111 -0
- package/dist/streaming/index.d.ts.map +1 -0
- package/dist/streaming/index.js +128 -0
- package/dist/streaming/index.js.map +1 -0
- package/dist/streaming/live-cdc-stream.d.ts +400 -0
- package/dist/streaming/live-cdc-stream.d.ts.map +1 -0
- package/dist/streaming/live-cdc-stream.js +703 -0
- package/dist/streaming/live-cdc-stream.js.map +1 -0
- package/dist/streaming/memory-bounded-stream.d.ts +207 -0
- package/dist/streaming/memory-bounded-stream.d.ts.map +1 -0
- package/dist/streaming/memory-bounded-stream.js +340 -0
- package/dist/streaming/memory-bounded-stream.js.map +1 -0
- package/dist/streaming/query-streamer.d.ts +379 -0
- package/dist/streaming/query-streamer.d.ts.map +1 -0
- package/dist/streaming/query-streamer.js +495 -0
- package/dist/streaming/query-streamer.js.map +1 -0
- package/dist/streaming/response-streaming.d.ts +203 -0
- package/dist/streaming/response-streaming.d.ts.map +1 -0
- package/dist/streaming/response-streaming.js +449 -0
- package/dist/streaming/response-streaming.js.map +1 -0
- package/dist/types/branded.d.ts +859 -0
- package/dist/types/branded.d.ts.map +1 -0
- package/dist/types/branded.js +891 -0
- package/dist/types/branded.js.map +1 -0
- package/dist/types/utilities.d.ts +757 -0
- package/dist/types/utilities.d.ts.map +1 -0
- package/dist/types/utilities.js +447 -0
- package/dist/types/utilities.js.map +1 -0
- package/dist/wal/replay-engine.d.ts +344 -0
- package/dist/wal/replay-engine.d.ts.map +1 -0
- package/dist/wal/replay-engine.js +975 -0
- package/dist/wal/replay-engine.js.map +1 -0
- package/dist/worker/__mocks__/capnweb.d.ts +13 -0
- package/dist/worker/__mocks__/capnweb.d.ts.map +1 -0
- package/dist/worker/__mocks__/capnweb.js +15 -0
- package/dist/worker/__mocks__/capnweb.js.map +1 -0
- package/dist/worker/__mocks__/cloudflare-workers.d.ts +31 -0
- package/dist/worker/__mocks__/cloudflare-workers.d.ts.map +1 -0
- package/dist/worker/__mocks__/cloudflare-workers.js +33 -0
- package/dist/worker/__mocks__/cloudflare-workers.js.map +1 -0
- package/dist/worker/__mocks__/pglite.data.d.ts +3 -0
- package/dist/worker/__mocks__/pglite.data.d.ts.map +1 -0
- package/dist/worker/__mocks__/pglite.data.js +20 -0
- package/dist/worker/__mocks__/pglite.data.js.map +1 -0
- package/dist/worker/__mocks__/pglite.wasm.d.ts +3 -0
- package/dist/worker/__mocks__/pglite.wasm.d.ts.map +1 -0
- package/dist/worker/__mocks__/pglite.wasm.js +30 -0
- package/dist/worker/__mocks__/pglite.wasm.js.map +1 -0
- package/dist/worker/auth-rate-limiter.d.ts +270 -0
- package/dist/worker/auth-rate-limiter.d.ts.map +1 -0
- package/dist/worker/auth-rate-limiter.js +332 -0
- package/dist/worker/auth-rate-limiter.js.map +1 -0
- package/dist/worker/auth.d.ts +345 -0
- package/dist/worker/auth.d.ts.map +1 -0
- package/dist/worker/auth.js +837 -0
- package/dist/worker/auth.js.map +1 -0
- package/dist/worker/cdc-backpressure.d.ts +338 -0
- package/dist/worker/cdc-backpressure.d.ts.map +1 -0
- package/dist/worker/cdc-backpressure.js +619 -0
- package/dist/worker/cdc-backpressure.js.map +1 -0
- package/dist/worker/cdc-sse.d.ts +277 -0
- package/dist/worker/cdc-sse.d.ts.map +1 -0
- package/dist/worker/cdc-sse.js +528 -0
- package/dist/worker/cdc-sse.js.map +1 -0
- package/dist/worker/cdc-websocket.d.ts +252 -0
- package/dist/worker/cdc-websocket.d.ts.map +1 -0
- package/dist/worker/cdc-websocket.js +940 -0
- package/dist/worker/cdc-websocket.js.map +1 -0
- package/dist/worker/cdc.d.ts +95 -0
- package/dist/worker/cdc.d.ts.map +1 -0
- package/dist/worker/cdc.js +211 -0
- package/dist/worker/cdc.js.map +1 -0
- package/dist/worker/concerns/auth-concern.d.ts +50 -0
- package/dist/worker/concerns/auth-concern.d.ts.map +1 -0
- package/dist/worker/concerns/auth-concern.js +131 -0
- package/dist/worker/concerns/auth-concern.js.map +1 -0
- package/dist/worker/concerns/cdc-concern.d.ts +99 -0
- package/dist/worker/concerns/cdc-concern.d.ts.map +1 -0
- package/dist/worker/concerns/cdc-concern.js +137 -0
- package/dist/worker/concerns/cdc-concern.js.map +1 -0
- package/dist/worker/concerns/index.d.ts +22 -0
- package/dist/worker/concerns/index.d.ts.map +1 -0
- package/dist/worker/concerns/index.js +13 -0
- package/dist/worker/concerns/index.js.map +1 -0
- package/dist/worker/concerns/query-execution-concern.d.ts +104 -0
- package/dist/worker/concerns/query-execution-concern.d.ts.map +1 -0
- package/dist/worker/concerns/query-execution-concern.js +95 -0
- package/dist/worker/concerns/query-execution-concern.js.map +1 -0
- package/dist/worker/concerns/storage-orchestration-concern.d.ts +78 -0
- package/dist/worker/concerns/storage-orchestration-concern.d.ts.map +1 -0
- package/dist/worker/concerns/storage-orchestration-concern.js +240 -0
- package/dist/worker/concerns/storage-orchestration-concern.js.map +1 -0
- package/dist/worker/do-auth-manager.d.ts +108 -0
- package/dist/worker/do-auth-manager.d.ts.map +1 -0
- package/dist/worker/do-auth-manager.js +212 -0
- package/dist/worker/do-auth-manager.js.map +1 -0
- package/dist/worker/do-pglite-manager.d.ts +137 -0
- package/dist/worker/do-pglite-manager.d.ts.map +1 -0
- package/dist/worker/do-pglite-manager.js +228 -0
- package/dist/worker/do-pglite-manager.js.map +1 -0
- package/dist/worker/do.d.ts +556 -0
- package/dist/worker/do.d.ts.map +1 -0
- package/dist/worker/do.js +1441 -0
- package/dist/worker/do.js.map +1 -0
- package/dist/worker/entry.d.ts +23 -0
- package/dist/worker/entry.d.ts.map +1 -0
- package/dist/worker/entry.js +362 -0
- package/dist/worker/entry.js.map +1 -0
- package/dist/worker/errors.d.ts +106 -0
- package/dist/worker/errors.d.ts.map +1 -0
- package/dist/worker/errors.js +178 -0
- package/dist/worker/errors.js.map +1 -0
- package/dist/worker/health-check-manager.d.ts +141 -0
- package/dist/worker/health-check-manager.d.ts.map +1 -0
- package/dist/worker/health-check-manager.js +145 -0
- package/dist/worker/health-check-manager.js.map +1 -0
- package/dist/worker/index.d.ts +60 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +67 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker/memory-pressure.d.ts +892 -0
- package/dist/worker/memory-pressure.d.ts.map +1 -0
- package/dist/worker/memory-pressure.js +1990 -0
- package/dist/worker/memory-pressure.js.map +1 -0
- package/dist/worker/migration-manager.d.ts +153 -0
- package/dist/worker/migration-manager.d.ts.map +1 -0
- package/dist/worker/migration-manager.js +461 -0
- package/dist/worker/migration-manager.js.map +1 -0
- package/dist/worker/plugin-manager.d.ts +147 -0
- package/dist/worker/plugin-manager.d.ts.map +1 -0
- package/dist/worker/plugin-manager.js +408 -0
- package/dist/worker/plugin-manager.js.map +1 -0
- package/dist/worker/proxy.d.ts +330 -0
- package/dist/worker/proxy.d.ts.map +1 -0
- package/dist/worker/proxy.js +504 -0
- package/dist/worker/proxy.js.map +1 -0
- package/dist/worker/query-execution-manager.d.ts +107 -0
- package/dist/worker/query-execution-manager.d.ts.map +1 -0
- package/dist/worker/query-execution-manager.js +155 -0
- package/dist/worker/query-execution-manager.js.map +1 -0
- package/dist/worker/query-executor.d.ts +163 -0
- package/dist/worker/query-executor.d.ts.map +1 -0
- package/dist/worker/query-executor.js +413 -0
- package/dist/worker/query-executor.js.map +1 -0
- package/dist/worker/query-stats-manager.d.ts +117 -0
- package/dist/worker/query-stats-manager.d.ts.map +1 -0
- package/dist/worker/query-stats-manager.js +162 -0
- package/dist/worker/query-stats-manager.js.map +1 -0
- package/dist/worker/result-handler.d.ts +192 -0
- package/dist/worker/result-handler.d.ts.map +1 -0
- package/dist/worker/result-handler.js +346 -0
- package/dist/worker/result-handler.js.map +1 -0
- package/dist/worker/routes.d.ts +135 -0
- package/dist/worker/routes.d.ts.map +1 -0
- package/dist/worker/routes.js +460 -0
- package/dist/worker/routes.js.map +1 -0
- package/dist/worker/rpc-methods-manager.d.ts +142 -0
- package/dist/worker/rpc-methods-manager.d.ts.map +1 -0
- package/dist/worker/rpc-methods-manager.js +195 -0
- package/dist/worker/rpc-methods-manager.js.map +1 -0
- package/dist/worker/rpc.d.ts +259 -0
- package/dist/worker/rpc.d.ts.map +1 -0
- package/dist/worker/rpc.js +398 -0
- package/dist/worker/rpc.js.map +1 -0
- package/dist/worker/schema-version.d.ts +209 -0
- package/dist/worker/schema-version.d.ts.map +1 -0
- package/dist/worker/schema-version.js +450 -0
- package/dist/worker/schema-version.js.map +1 -0
- package/dist/worker/session-manager.d.ts +282 -0
- package/dist/worker/session-manager.d.ts.map +1 -0
- package/dist/worker/session-manager.js +523 -0
- package/dist/worker/session-manager.js.map +1 -0
- package/dist/worker/shutdown-manager.d.ts +188 -0
- package/dist/worker/shutdown-manager.d.ts.map +1 -0
- package/dist/worker/shutdown-manager.js +347 -0
- package/dist/worker/shutdown-manager.js.map +1 -0
- package/dist/worker/sql-transform.d.ts +61 -0
- package/dist/worker/sql-transform.d.ts.map +1 -0
- package/dist/worker/sql-transform.js +312 -0
- package/dist/worker/sql-transform.js.map +1 -0
- package/dist/worker/types.d.ts +738 -0
- package/dist/worker/types.d.ts.map +1 -0
- package/dist/worker/types.js +6 -0
- package/dist/worker/types.js.map +1 -0
- package/dist/worker/user-routes.d.ts +76 -0
- package/dist/worker/user-routes.d.ts.map +1 -0
- package/dist/worker/user-routes.js +188 -0
- package/dist/worker/user-routes.js.map +1 -0
- package/dist/worker/wal-facade.d.ts +138 -0
- package/dist/worker/wal-facade.d.ts.map +1 -0
- package/dist/worker/wal-facade.js +184 -0
- package/dist/worker/wal-facade.js.map +1 -0
- package/dist/worker/wal-r2.d.ts +271 -0
- package/dist/worker/wal-r2.d.ts.map +1 -0
- package/dist/worker/wal-r2.js +689 -0
- package/dist/worker/wal-r2.js.map +1 -0
- package/dist/worker/wal-replay.d.ts +361 -0
- package/dist/worker/wal-replay.d.ts.map +1 -0
- package/dist/worker/wal-replay.js +628 -0
- package/dist/worker/wal-replay.js.map +1 -0
- package/dist/worker/wal-retention.d.ts +389 -0
- package/dist/worker/wal-retention.d.ts.map +1 -0
- package/dist/worker/wal-retention.js +763 -0
- package/dist/worker/wal-retention.js.map +1 -0
- package/dist/worker/wal.d.ts +278 -0
- package/dist/worker/wal.d.ts.map +1 -0
- package/dist/worker/wal.js +467 -0
- package/dist/worker/wal.js.map +1 -0
- package/dist/worker/websocket.d.ts +85 -0
- package/dist/worker/websocket.d.ts.map +1 -0
- package/dist/worker/websocket.js +227 -0
- package/dist/worker/websocket.js.map +1 -0
- package/package.json +108 -0
- package/src/cdc/change-stream.ts +137 -0
- package/src/cdc/filter.ts +646 -0
- package/src/cdc/index.ts +112 -0
- package/src/cdc/resume-token.ts +280 -0
- package/src/cdc/transport/index.ts +7 -0
- package/src/cdc/transport/sse.ts +723 -0
- package/src/cdc/transport/websocket.ts +873 -0
- package/src/cdc/types.ts +346 -0
- package/src/config/index.ts +25 -0
- package/src/config/memory.ts +177 -0
- package/src/config/storage.ts +204 -0
- package/src/config/streaming.ts +147 -0
- package/src/config/timeouts.ts +221 -0
- package/src/extensions/config.test.ts +187 -0
- package/src/extensions/config.ts +278 -0
- package/src/extensions/geo.test.ts +455 -0
- package/src/extensions/geo.ts +858 -0
- package/src/extensions/index.test.ts +259 -0
- package/src/extensions/index.ts +227 -0
- package/src/extensions/loader.test.ts +555 -0
- package/src/extensions/loader.ts +588 -0
- package/src/extensions/pgmq-lite.test.ts +727 -0
- package/src/extensions/pgmq-lite.ts +770 -0
- package/src/extensions/plugins.test.ts +528 -0
- package/src/extensions/plugins.ts +718 -0
- package/src/extensions/registry.test.ts +202 -0
- package/src/extensions/registry.ts +267 -0
- package/src/extensions/vector.test.ts +195 -0
- package/src/extensions/vector.ts +217 -0
- package/src/iceberg/SCHEDULER.md +580 -0
- package/src/iceberg/analytics.test.ts +703 -0
- package/src/iceberg/analytics.ts +727 -0
- package/src/iceberg/catalog-api.test.ts +838 -0
- package/src/iceberg/catalog-api.ts +520 -0
- package/src/iceberg/catalog.test.ts +680 -0
- package/src/iceberg/catalog.ts +1007 -0
- package/src/iceberg/iceberg.test.ts +705 -0
- package/src/iceberg/index.ts +406 -0
- package/src/iceberg/metadata.test.ts +632 -0
- package/src/iceberg/metadata.ts +649 -0
- package/src/iceberg/optimizer.test.ts +868 -0
- package/src/iceberg/optimizer.ts +1287 -0
- package/src/iceberg/parquet.test.ts +899 -0
- package/src/iceberg/parquet.ts +1640 -0
- package/src/iceberg/r2-organization.test.ts +615 -0
- package/src/iceberg/r2-organization.ts +951 -0
- package/src/iceberg/scheduler-do-example.ts +364 -0
- package/src/iceberg/scheduler.test.ts +861 -0
- package/src/iceberg/scheduler.ts +1201 -0
- package/src/iceberg/schema.test.ts +547 -0
- package/src/iceberg/schema.ts +616 -0
- package/src/iceberg/snapshot-manager.test.ts +919 -0
- package/src/iceberg/snapshot-manager.ts +1369 -0
- package/src/iceberg/sql-router.test.ts +334 -0
- package/src/iceberg/sql-router.ts +337 -0
- package/src/iceberg/test-fixtures.ts +605 -0
- package/src/iceberg/time-travel-api.test.ts +1029 -0
- package/src/iceberg/time-travel-api.ts +731 -0
- package/src/iceberg/time-travel.test.ts +1218 -0
- package/src/iceberg/time-travel.ts +1052 -0
- package/src/iceberg/transformer.test.ts +689 -0
- package/src/iceberg/transformer.ts +1029 -0
- package/src/iceberg/types.ts +373 -0
- package/src/iceberg/writer.test.ts +716 -0
- package/src/iceberg/writer.ts +590 -0
- package/src/index.ts +212 -0
- package/src/lineage/index.ts +42 -0
- package/src/lineage/integration.ts +334 -0
- package/src/lineage/tracker.ts +1618 -0
- package/src/lineage/types.ts +354 -0
- package/src/middleware/index.ts +36 -0
- package/src/middleware/rate-limit-concurrent.test.ts +794 -0
- package/src/middleware/rate-limit.test.ts +1568 -0
- package/src/middleware/rate-limit.ts +840 -0
- package/src/migration-tooling/external-migration.test.ts +1864 -0
- package/src/migration-tooling/external-migration.ts +2355 -0
- package/src/migration-tooling/index.ts +19 -0
- package/src/migrations/ARCHITECTURE.md +474 -0
- package/src/migrations/PROGRESS_TRACKING.md +485 -0
- package/src/migrations/auto-migrator.test.ts +732 -0
- package/src/migrations/auto-migrator.ts +531 -0
- package/src/migrations/bulk-orchestrator.test.ts +801 -0
- package/src/migrations/bulk-orchestrator.ts +1039 -0
- package/src/migrations/compatibility.test.ts +958 -0
- package/src/migrations/compatibility.ts +902 -0
- package/src/migrations/do-migrations.test.ts +2620 -0
- package/src/migrations/do-migrations.ts +1289 -0
- package/src/migrations/do-migrations.types.ts +715 -0
- package/src/migrations/drizzle-compat.test.ts +210 -0
- package/src/migrations/drizzle-compat.ts +337 -0
- package/src/migrations/index.ts +334 -0
- package/src/migrations/migration-api.test.ts +438 -0
- package/src/migrations/migration-api.ts +704 -0
- package/src/migrations/progress-tracker-do.ts +518 -0
- package/src/migrations/progress-tracker-kv.ts +305 -0
- package/src/migrations/progress-tracker.test.ts +937 -0
- package/src/migrations/progress-tracker.ts +665 -0
- package/src/migrations/registry.test.ts +331 -0
- package/src/migrations/registry.ts +468 -0
- package/src/migrations/rollback.test.ts +644 -0
- package/src/migrations/runner.test.ts +807 -0
- package/src/migrations/runner.test.ts.backup +759 -0
- package/src/migrations/runner.ts +1459 -0
- package/src/migrations/schema-generator.test.ts +649 -0
- package/src/migrations/schema-generator.ts +513 -0
- package/src/migrations/testing.ts +1037 -0
- package/src/migrations/types.ts +573 -0
- package/src/migrations/validator.test.ts +660 -0
- package/src/migrations/validator.ts +741 -0
- package/src/observability/alerting.test.ts +1133 -0
- package/src/observability/alerting.ts +455 -0
- package/src/observability/analytics-engine.ts +733 -0
- package/src/observability/cost-metrics.ts +804 -0
- package/src/observability/cross-do-tracing.test.ts +516 -0
- package/src/observability/cross-do-tracing.ts +588 -0
- package/src/observability/dashboards/postgres-do-overview.json +1656 -0
- package/src/observability/error-rate-collector.test.ts +977 -0
- package/src/observability/error-rate-collector.ts +518 -0
- package/src/observability/exporters.test.ts +365 -0
- package/src/observability/exporters.ts +650 -0
- package/src/observability/health-check.test.ts +353 -0
- package/src/observability/health-check.ts +341 -0
- package/src/observability/index.test.ts +298 -0
- package/src/observability/index.ts +885 -0
- package/src/observability/instrumentation.test.ts +428 -0
- package/src/observability/instrumentation.ts +788 -0
- package/src/observability/memory-metrics.test.ts +355 -0
- package/src/observability/memory-metrics.ts +990 -0
- package/src/observability/metrics-endpoint.test.ts +402 -0
- package/src/observability/metrics-endpoint.ts +374 -0
- package/src/observability/metrics.test.ts +291 -0
- package/src/observability/metrics.ts +315 -0
- package/src/observability/observability-features.ts +1296 -0
- package/src/observability/prometheus.test.ts +292 -0
- package/src/observability/prometheus.ts +170 -0
- package/src/observability/propagation.test.ts +417 -0
- package/src/observability/propagation.ts +294 -0
- package/src/observability/query-latency.ts +586 -0
- package/src/observability/query-performance.test.ts +406 -0
- package/src/observability/query-performance.ts +491 -0
- package/src/observability/storage-tier-metrics.test.ts +633 -0
- package/src/observability/storage-tier-metrics.ts +570 -0
- package/src/observability/tier-cost-optimizer.ts +740 -0
- package/src/observability/tracer.test.ts +346 -0
- package/src/observability/tracer.ts +585 -0
- package/src/observability/types.test.ts +726 -0
- package/src/observability/types.ts +434 -0
- package/src/pglite/auto-demotion.test.ts +477 -0
- package/src/pglite/auto-demotion.ts +385 -0
- package/src/pglite/auto-promotion.test.ts +824 -0
- package/src/pglite/auto-promotion.ts +547 -0
- package/src/pglite/cache-layer.test.ts +469 -0
- package/src/pglite/cache-layer.ts +271 -0
- package/src/pglite/cold-start-manager.ts +1260 -0
- package/src/pglite/cold-start-optimizer.test.ts +937 -0
- package/src/pglite/cold-start-optimizer.ts +1895 -0
- package/src/pglite/dovfs-adapter.ts +1122 -0
- package/src/pglite/dovfs.ts +1258 -0
- package/src/pglite/etag-cache.test.ts +844 -0
- package/src/pglite/etag-cache.ts +526 -0
- package/src/pglite/index.ts +442 -0
- package/src/pglite/init.test.ts +455 -0
- package/src/pglite/init.ts +574 -0
- package/src/pglite/lifecycle.test.ts +599 -0
- package/src/pglite/lifecycle.ts +704 -0
- package/src/pglite/parallel-loader.test.ts +586 -0
- package/src/pglite/parallel-loader.ts +481 -0
- package/src/pglite/production-pglite.test.ts +666 -0
- package/src/pglite/production-pglite.ts +537 -0
- package/src/pglite/query-executor.ts +614 -0
- package/src/pglite/r2-layer.test.ts +501 -0
- package/src/pglite/r2-layer.ts +322 -0
- package/src/pglite/tiered-init.test.ts +725 -0
- package/src/pglite/tiered-init.ts +556 -0
- package/src/pglite/tiered-vfs.test.ts +726 -0
- package/src/pglite/tiered-vfs.ts +33 -0
- package/src/pglite/tiering-stats.test.ts +531 -0
- package/src/pglite/tiering-stats.ts +407 -0
- package/src/pglite/transaction-hooks.ts +343 -0
- package/src/pglite/warm-loader.test.ts +1701 -0
- package/src/pglite/warm-loader.ts +528 -0
- package/src/pglite/workers-pglite.ts +224 -0
- package/src/pglite-assets/pglite.data +0 -0
- package/src/pglite-assets/pglite.wasm +0 -0
- package/src/pglite.d.ts +47 -0
- package/src/playground/index.ts +137 -0
- package/src/playground/keyboard-shortcuts.ts +677 -0
- package/src/playground/playground.ts +323 -0
- package/src/playground/query-executor.ts +669 -0
- package/src/playground/query-history.ts +328 -0
- package/src/playground/result-formatter.ts +420 -0
- package/src/playground/sample-datasets.ts +674 -0
- package/src/playground/sample-queries.ts +1168 -0
- package/src/playground/schema-explorer.ts +558 -0
- package/src/playground/types.ts +518 -0
- package/src/readonly/cache-reader.test.ts +460 -0
- package/src/readonly/cache-reader.ts +313 -0
- package/src/readonly/config.test.ts +187 -0
- package/src/readonly/config.ts +128 -0
- package/src/readonly/index.ts +50 -0
- package/src/readonly/pglite-wrapper.test.ts +278 -0
- package/src/readonly/pglite-wrapper.ts +184 -0
- package/src/readonly/worker.test.ts +533 -0
- package/src/readonly/worker.ts +341 -0
- package/src/readonly/write-blocker.test.ts +459 -0
- package/src/readonly/write-blocker.ts +175 -0
- package/src/recovery/disaster-recovery.test.ts +618 -0
- package/src/recovery/disaster-recovery.ts +1181 -0
- package/src/recovery/index.ts +43 -0
- package/src/recovery/parquet-parser.ts +974 -0
- package/src/retention/index.ts +74 -0
- package/src/retention/policy.test.ts +571 -0
- package/src/retention/policy.ts +774 -0
- package/src/retention/purger.test.ts +465 -0
- package/src/retention/purger.ts +558 -0
- package/src/rls/auth-integration.test.ts +752 -0
- package/src/rls/auth-integration.ts +533 -0
- package/src/rls/generator.test.ts +829 -0
- package/src/rls/generator.ts +573 -0
- package/src/rls/index.ts +128 -0
- package/src/rls/policy.ts +208 -0
- package/src/rls/rls.test.ts +1071 -0
- package/src/rls/validator.test.ts +930 -0
- package/src/rls/validator.ts +895 -0
- package/src/routing/adaptive-router.test.ts +884 -0
- package/src/routing/adaptive-router.ts +845 -0
- package/src/routing/circuit-breaker.test.ts +1505 -0
- package/src/routing/circuit-breaker.ts +852 -0
- package/src/routing/cost-metrics.test.ts +565 -0
- package/src/routing/cost-metrics.ts +408 -0
- package/src/routing/do-connection-pool.test.ts +1109 -0
- package/src/routing/do-connection-pool.ts +828 -0
- package/src/routing/index.ts +158 -0
- package/src/routing/query-complexity-estimator.test.ts +356 -0
- package/src/routing/query-complexity-estimator.ts +444 -0
- package/src/routing/request-coalescing.test.ts +738 -0
- package/src/routing/request-coalescing.ts +475 -0
- package/src/routing/runtime-router.test.ts +436 -0
- package/src/routing/runtime-router.ts +357 -0
- package/src/routing/tenant-router.test.ts +2493 -0
- package/src/routing/tenant-router.ts +1908 -0
- package/src/routing/websocket-pool.test.ts +551 -0
- package/src/routing/websocket-pool.ts +577 -0
- package/src/storage/access-pattern-tracker.test.ts +874 -0
- package/src/storage/cache-layer.test.ts +560 -0
- package/src/storage/cache-layer.ts +328 -0
- package/src/storage/cost-aware-tiering.test.ts +652 -0
- package/src/storage/cost-aware-tiering.ts +794 -0
- package/src/storage/do-sqlite-blobs.test.ts +937 -0
- package/src/storage/index.ts +272 -0
- package/src/storage/interfaces.ts +974 -0
- package/src/storage/r2-layer.test.ts +653 -0
- package/src/storage/r2-layer.ts +434 -0
- package/src/storage/r2-overflow.ts +920 -0
- package/src/storage/r2-page-vfs.test.ts +2348 -0
- package/src/storage/r2-page-vfs.ts +1054 -0
- package/src/storage/swr-cache.test.ts +832 -0
- package/src/storage/swr-cache.ts +398 -0
- package/src/storage/swr-tiered-integration.test.ts +617 -0
- package/src/storage/tiered-orchestrator.test.ts +2441 -0
- package/src/storage/tiered-orchestrator.ts +2081 -0
- package/src/storage/tiered-vfs-swr.test.ts +736 -0
- package/src/storage/tiered-vfs-swr.ts +735 -0
- package/src/storage/tiered-vfs.test.ts +793 -0
- package/src/storage/tiered-vfs.ts +1082 -0
- package/src/streaming/backpressure-controller.ts +452 -0
- package/src/streaming/buffer-pool.ts +484 -0
- package/src/streaming/cdc-iceberg-connector.ts +605 -0
- package/src/streaming/index.ts +225 -0
- package/src/streaming/live-cdc-stream.ts +985 -0
- package/src/streaming/memory-bounded-stream.ts +443 -0
- package/src/streaming/query-streamer.ts +662 -0
- package/src/streaming/response-streaming.ts +557 -0
- package/src/types/branded.ts +1075 -0
- package/src/types/branded.ts.backup +273 -0
- package/src/types/utilities.ts +1023 -0
- package/src/types/wasm.d.ts +30 -0
- package/src/validation/typed-errors.test.ts +420 -0
- package/src/wal/replay-engine.ts +1264 -0
- package/src/worker/__mocks__/capnweb.ts +15 -0
- package/src/worker/__mocks__/pglite.data.ts +22 -0
- package/src/worker/__mocks__/pglite.wasm.ts +33 -0
- package/src/worker/auth-rate-limiter.test.ts +272 -0
- package/src/worker/auth-rate-limiter.ts +448 -0
- package/src/worker/auth.security-red.test.ts +1236 -0
- package/src/worker/auth.security.test.ts +822 -0
- package/src/worker/auth.test.ts +469 -0
- package/src/worker/auth.ts +1104 -0
- package/src/worker/cdc-backpressure.test.ts +726 -0
- package/src/worker/cdc-backpressure.ts +866 -0
- package/src/worker/cdc-sse.test.ts +780 -0
- package/src/worker/cdc-sse.ts +728 -0
- package/src/worker/cdc-websocket.ts +1229 -0
- package/src/worker/cdc-ws.test.ts +1009 -0
- package/src/worker/cdc.test.ts +327 -0
- package/src/worker/cdc.ts +289 -0
- package/src/worker/concerns/auth-concern.ts +179 -0
- package/src/worker/concerns/cdc-concern.ts +247 -0
- package/src/worker/concerns/index.ts +58 -0
- package/src/worker/concerns/query-execution-concern.ts +194 -0
- package/src/worker/concerns/storage-orchestration-concern.ts +373 -0
- package/src/worker/discriminated-types.test.ts +280 -0
- package/src/worker/do-auth-manager.ts +257 -0
- package/src/worker/do-decomposition.test.ts +1236 -0
- package/src/worker/do-pglite-manager.ts +302 -0
- package/src/worker/do.test.ts +2254 -0
- package/src/worker/do.ts +1878 -0
- package/src/worker/entry.ts +417 -0
- package/src/worker/errors.ts +285 -0
- package/src/worker/health-check-manager.test.ts +261 -0
- package/src/worker/health-check-manager.ts +231 -0
- package/src/worker/index.ts +389 -0
- package/src/worker/memory-pressure.test.ts +1460 -0
- package/src/worker/memory-pressure.ts +2650 -0
- package/src/worker/migration-manager.ts +582 -0
- package/src/worker/neon-compat.test.ts +332 -0
- package/src/worker/plugin-manager.ts +485 -0
- package/src/worker/postgres.do-rpc.d.ts +76 -0
- package/src/worker/proxy.ts +694 -0
- package/src/worker/query-execution-manager.test.ts +303 -0
- package/src/worker/query-execution-manager.ts +219 -0
- package/src/worker/query-executor.test.ts +282 -0
- package/src/worker/query-executor.ts +560 -0
- package/src/worker/query-stats-manager.ts +229 -0
- package/src/worker/result-handler.test.ts +364 -0
- package/src/worker/result-handler.ts +510 -0
- package/src/worker/routes.test.ts +795 -0
- package/src/worker/routes.ts +650 -0
- package/src/worker/rpc-methods-manager.test.ts +326 -0
- package/src/worker/rpc-methods-manager.ts +276 -0
- package/src/worker/rpc.ts +524 -0
- package/src/worker/schema-version.ts +605 -0
- package/src/worker/session-manager.test.ts +506 -0
- package/src/worker/session-manager.ts +732 -0
- package/src/worker/shutdown-manager.ts +469 -0
- package/src/worker/sql-transform.test.ts +286 -0
- package/src/worker/sql-transform.ts +368 -0
- package/src/worker/supabase-compat.test.ts +621 -0
- package/src/worker/types.test.ts +292 -0
- package/src/worker/types.ts +873 -0
- package/src/worker/user-routes.test.ts +703 -0
- package/src/worker/user-routes.ts +303 -0
- package/src/worker/wal-facade.ts +235 -0
- package/src/worker/wal-r2.test.ts +570 -0
- package/src/worker/wal-r2.ts +930 -0
- package/src/worker/wal-replay.test.ts +845 -0
- package/src/worker/wal-replay.ts +897 -0
- package/src/worker/wal-retention.test.ts +758 -0
- package/src/worker/wal-retention.ts +1075 -0
- package/src/worker/wal.test.ts +618 -0
- package/src/worker/wal.ts +697 -0
- package/src/worker/websocket.test.ts +296 -0
- package/src/worker/websocket.ts +284 -0
|
@@ -0,0 +1,1352 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data Lineage Tracker
|
|
3
|
+
* Task: postgres-zce - Data lineage tracking
|
|
4
|
+
*
|
|
5
|
+
* Tracks data origin and transformations across tables, integrating with WAL capture
|
|
6
|
+
* and Iceberg storage for complete lineage history.
|
|
7
|
+
*/
|
|
8
|
+
import { parseWriteOperation } from '../worker/wal';
|
|
9
|
+
/**
|
|
10
|
+
* Default lineage tracker configuration
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_CONFIG = {
|
|
13
|
+
enabled: true,
|
|
14
|
+
trackColumns: true,
|
|
15
|
+
trackRows: false,
|
|
16
|
+
maxDepth: 10,
|
|
17
|
+
includeTables: [],
|
|
18
|
+
excludeTables: [],
|
|
19
|
+
operations: [],
|
|
20
|
+
storeInIceberg: true,
|
|
21
|
+
useSeparateCatalog: false,
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Generate a unique node ID
|
|
25
|
+
*/
|
|
26
|
+
function generateNodeId(schema, table) {
|
|
27
|
+
return `${schema}.${table}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate a unique edge ID
|
|
31
|
+
*/
|
|
32
|
+
function generateEdgeId(sourceId, targetId, timestamp) {
|
|
33
|
+
return `${sourceId}->${targetId}@${timestamp}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Parse SQL to extract lineage information
|
|
37
|
+
*/
|
|
38
|
+
export function parseLineage(sql) {
|
|
39
|
+
// Normalize SQL
|
|
40
|
+
const normalized = sql.trim().replace(/\s+/g, ' ');
|
|
41
|
+
const upperSql = normalized.toUpperCase();
|
|
42
|
+
// Parse CTEs first (WITH clause) - extract source tables from CTEs
|
|
43
|
+
const ctes = extractCTEs(normalized);
|
|
44
|
+
const cteSourceTables = ctes.flatMap((cte) => cte.sourceTables);
|
|
45
|
+
const cteNames = new Set(ctes.map((cte) => cte.name));
|
|
46
|
+
// For CTEs, we need to get the SQL after the CTE definitions for main operation detection
|
|
47
|
+
const mainSql = stripCTEs(normalized);
|
|
48
|
+
const mainUpperSql = mainSql.toUpperCase();
|
|
49
|
+
// Parse INSERT INTO ... SELECT FROM
|
|
50
|
+
if (upperSql.includes('INSERT INTO') && upperSql.includes('SELECT')) {
|
|
51
|
+
const result = parseInsertSelect(normalized);
|
|
52
|
+
if (result) {
|
|
53
|
+
// Add CTE source tables
|
|
54
|
+
result.sourceTables = [...result.sourceTables, ...cteSourceTables];
|
|
55
|
+
// Add aggregations if present
|
|
56
|
+
result.aggregations = extractAggregations(normalized);
|
|
57
|
+
}
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
// Parse UPDATE ... FROM
|
|
61
|
+
if (upperSql.includes('UPDATE') && upperSql.includes('FROM')) {
|
|
62
|
+
const result = parseUpdateFrom(normalized);
|
|
63
|
+
if (result) {
|
|
64
|
+
result.sourceTables = [...result.sourceTables, ...cteSourceTables];
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
// Parse CREATE TABLE AS SELECT (CTAS)
|
|
69
|
+
if (upperSql.includes('CREATE TABLE') && upperSql.includes('AS') && upperSql.includes('SELECT')) {
|
|
70
|
+
return parseCreateTableAs(normalized);
|
|
71
|
+
}
|
|
72
|
+
// Parse DELETE with subqueries - must check before generic subquery handler
|
|
73
|
+
if (mainUpperSql.startsWith('DELETE')) {
|
|
74
|
+
const writeOp = parseWriteOperation(sql);
|
|
75
|
+
if (writeOp && writeOp.operation === 'DELETE') {
|
|
76
|
+
// Extract source tables from subqueries
|
|
77
|
+
const subqueries = extractSubqueries(normalized);
|
|
78
|
+
const subquerySourceTables = subqueries.flatMap((sq) => sq.sourceTables);
|
|
79
|
+
return {
|
|
80
|
+
operation: 'DELETE',
|
|
81
|
+
targetTable: {
|
|
82
|
+
schema: writeOp.schema,
|
|
83
|
+
table: writeOp.table,
|
|
84
|
+
},
|
|
85
|
+
sourceTables: [
|
|
86
|
+
{
|
|
87
|
+
schema: writeOp.schema,
|
|
88
|
+
table: writeOp.table,
|
|
89
|
+
},
|
|
90
|
+
...subquerySourceTables,
|
|
91
|
+
...cteSourceTables,
|
|
92
|
+
],
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Parse SELECT with JOINs
|
|
97
|
+
if (upperSql.includes('SELECT') && upperSql.includes('JOIN')) {
|
|
98
|
+
const result = parseSelectJoin(normalized);
|
|
99
|
+
if (result) {
|
|
100
|
+
result.sourceTables = [...result.sourceTables, ...cteSourceTables];
|
|
101
|
+
result.aggregations = extractAggregations(normalized);
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
// Parse SELECT with aggregations (GROUP BY)
|
|
106
|
+
if (upperSql.includes('SELECT') && (upperSql.includes('GROUP BY') || hasAggregateFunction(upperSql))) {
|
|
107
|
+
const result = parseSelectAggregate(normalized);
|
|
108
|
+
if (result) {
|
|
109
|
+
result.sourceTables = [...result.sourceTables, ...cteSourceTables];
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
// Parse SELECT with subqueries - check if main statement (not in CTE) starts with SELECT
|
|
114
|
+
// For CTEs followed by SELECT, we should return SELECT not SUBQUERY
|
|
115
|
+
if (upperSql.includes('SELECT') && normalized.includes('(SELECT')) {
|
|
116
|
+
// If we have CTEs and main SQL starts with SELECT (e.g., WITH ... SELECT), preserve SELECT operation
|
|
117
|
+
// But only if the (SELECT is part of a CTE definition, not a subquery in WHERE/FROM
|
|
118
|
+
if (ctes.length > 0 && mainUpperSql.startsWith('SELECT') && !mainSql.includes('(SELECT')) {
|
|
119
|
+
const sourceTables = extractSourceTables(mainSql);
|
|
120
|
+
// Filter out CTE names from source tables
|
|
121
|
+
const filteredSourceTables = sourceTables.filter((t) => !cteNames.has(t.table.toLowerCase()));
|
|
122
|
+
return {
|
|
123
|
+
operation: 'SELECT',
|
|
124
|
+
sourceTables: [...filteredSourceTables, ...cteSourceTables],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const result = parseSelectSubquery(normalized);
|
|
128
|
+
if (result) {
|
|
129
|
+
result.sourceTables = [...result.sourceTables, ...cteSourceTables];
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
// Parse simple SELECT (including CTEs followed by SELECT)
|
|
134
|
+
if (mainUpperSql.startsWith('SELECT') && mainUpperSql.includes('FROM')) {
|
|
135
|
+
const sourceTables = extractSourceTables(mainSql);
|
|
136
|
+
// Filter out CTE names from source tables
|
|
137
|
+
const filteredSourceTables = sourceTables.filter((t) => !cteNames.has(t.table.toLowerCase()));
|
|
138
|
+
if (filteredSourceTables.length > 0 || cteSourceTables.length > 0) {
|
|
139
|
+
return {
|
|
140
|
+
operation: 'SELECT',
|
|
141
|
+
sourceTables: [...filteredSourceTables, ...cteSourceTables],
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Parse simple INSERT - use local parsing for embedded quotes support
|
|
146
|
+
const simpleInsertResult = parseSimpleInsert(normalized);
|
|
147
|
+
if (simpleInsertResult) {
|
|
148
|
+
return {
|
|
149
|
+
...simpleInsertResult,
|
|
150
|
+
sourceTables: [...simpleInsertResult.sourceTables, ...cteSourceTables],
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// Parse simple UPDATE
|
|
154
|
+
const writeOp = parseWriteOperation(sql);
|
|
155
|
+
if (writeOp && writeOp.operation === 'UPDATE') {
|
|
156
|
+
return {
|
|
157
|
+
operation: 'UPDATE',
|
|
158
|
+
targetTable: {
|
|
159
|
+
schema: writeOp.schema,
|
|
160
|
+
table: writeOp.table,
|
|
161
|
+
},
|
|
162
|
+
sourceTables: [
|
|
163
|
+
{
|
|
164
|
+
schema: writeOp.schema,
|
|
165
|
+
table: writeOp.table,
|
|
166
|
+
},
|
|
167
|
+
...cteSourceTables,
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
// Parse simple DELETE
|
|
172
|
+
if (writeOp && writeOp.operation === 'DELETE') {
|
|
173
|
+
return {
|
|
174
|
+
operation: 'DELETE',
|
|
175
|
+
targetTable: {
|
|
176
|
+
schema: writeOp.schema,
|
|
177
|
+
table: writeOp.table,
|
|
178
|
+
},
|
|
179
|
+
sourceTables: [
|
|
180
|
+
{
|
|
181
|
+
schema: writeOp.schema,
|
|
182
|
+
table: writeOp.table,
|
|
183
|
+
},
|
|
184
|
+
...cteSourceTables,
|
|
185
|
+
],
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Strip CTE definitions from SQL to get the main statement
|
|
192
|
+
*/
|
|
193
|
+
function stripCTEs(sql) {
|
|
194
|
+
// Match WITH clause and all CTE definitions
|
|
195
|
+
const ctePattern = /^WITH\s+(?:RECURSIVE\s+)?(?:[a-z_][a-z0-9_]*\s+AS\s*\([^)]+\)\s*,?\s*)+/i;
|
|
196
|
+
return sql.replace(ctePattern, '').trim();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Parse simple INSERT statement with embedded quote support
|
|
200
|
+
*/
|
|
201
|
+
function parseSimpleInsert(sql) {
|
|
202
|
+
// Match INSERT INTO with support for:
|
|
203
|
+
// - [catalog.][schema.]table (3-part or 2-part names)
|
|
204
|
+
// - "Table""Name" (embedded quotes)
|
|
205
|
+
const insertMatch = sql.match(/^INSERT\s+INTO\s+(?:([a-z_][a-z0-9_]*)\s*\.\s*)?(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"(?:[^"]|"")+")(?:\s|$|\()/i);
|
|
206
|
+
if (!insertMatch)
|
|
207
|
+
return null;
|
|
208
|
+
// Handle 3-part names: catalog.schema.table vs 2-part: schema.table vs 1-part: table
|
|
209
|
+
let targetSchema;
|
|
210
|
+
let targetTable;
|
|
211
|
+
if (insertMatch[2]) {
|
|
212
|
+
// 3-part name: insertMatch[1] is catalog, [2] is schema, [3] is table
|
|
213
|
+
// Or 2-part: [1] is schema, [2] is extra (shouldn't happen with this regex)
|
|
214
|
+
targetSchema = insertMatch[2].toLowerCase();
|
|
215
|
+
targetTable = unquoteIdentifier(insertMatch[3]);
|
|
216
|
+
}
|
|
217
|
+
else if (insertMatch[1]) {
|
|
218
|
+
targetSchema = insertMatch[1].toLowerCase();
|
|
219
|
+
targetTable = unquoteIdentifier(insertMatch[3]);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
targetSchema = 'public';
|
|
223
|
+
targetTable = unquoteIdentifier(insertMatch[3]);
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
operation: 'INSERT',
|
|
227
|
+
targetTable: {
|
|
228
|
+
schema: targetSchema,
|
|
229
|
+
table: targetTable,
|
|
230
|
+
},
|
|
231
|
+
sourceTables: [],
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Check if SQL contains aggregate functions
|
|
236
|
+
*/
|
|
237
|
+
function hasAggregateFunction(upperSql) {
|
|
238
|
+
const aggregateFunctions = ['COUNT(', 'SUM(', 'AVG(', 'MIN(', 'MAX(', 'ARRAY_AGG(', 'STRING_AGG(', 'JSON_AGG(', 'JSONB_AGG('];
|
|
239
|
+
return aggregateFunctions.some((fn) => upperSql.includes(fn));
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Parse INSERT INTO ... SELECT FROM statement
|
|
243
|
+
*/
|
|
244
|
+
function parseInsertSelect(sql) {
|
|
245
|
+
const insertMatch = sql.match(/INSERT\s+INTO\s+(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"[^"]+")/i);
|
|
246
|
+
if (!insertMatch)
|
|
247
|
+
return null;
|
|
248
|
+
const targetSchema = insertMatch[1]?.toLowerCase() ?? 'public';
|
|
249
|
+
const targetTable = unquoteIdentifier(insertMatch[2]);
|
|
250
|
+
// Extract source tables from SELECT clause
|
|
251
|
+
const sourceTables = extractSourceTables(sql);
|
|
252
|
+
return {
|
|
253
|
+
operation: 'INSERT',
|
|
254
|
+
targetTable: {
|
|
255
|
+
schema: targetSchema,
|
|
256
|
+
table: targetTable,
|
|
257
|
+
},
|
|
258
|
+
sourceTables,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Parse UPDATE ... FROM statement
|
|
263
|
+
*/
|
|
264
|
+
function parseUpdateFrom(sql) {
|
|
265
|
+
const updateMatch = sql.match(/UPDATE\s+(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"[^"]+")/i);
|
|
266
|
+
if (!updateMatch)
|
|
267
|
+
return null;
|
|
268
|
+
const targetSchema = updateMatch[1]?.toLowerCase() ?? 'public';
|
|
269
|
+
const targetTable = unquoteIdentifier(updateMatch[2]);
|
|
270
|
+
// Extract source tables from FROM clause
|
|
271
|
+
const sourceTables = extractSourceTables(sql);
|
|
272
|
+
return {
|
|
273
|
+
operation: 'UPDATE',
|
|
274
|
+
targetTable: {
|
|
275
|
+
schema: targetSchema,
|
|
276
|
+
table: targetTable,
|
|
277
|
+
},
|
|
278
|
+
sourceTables,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Parse SELECT with JOIN
|
|
283
|
+
*/
|
|
284
|
+
function parseSelectJoin(sql) {
|
|
285
|
+
// Extract source tables
|
|
286
|
+
const sourceTables = extractSourceTables(sql);
|
|
287
|
+
// Extract JOIN dependencies
|
|
288
|
+
const joins = extractJoins(sql);
|
|
289
|
+
// Extract WHERE filter
|
|
290
|
+
const whereFilter = extractWhereFilter(sql);
|
|
291
|
+
return {
|
|
292
|
+
operation: 'SELECT',
|
|
293
|
+
sourceTables,
|
|
294
|
+
joins,
|
|
295
|
+
whereFilter,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Parse CREATE TABLE AS SELECT (CTAS)
|
|
300
|
+
*/
|
|
301
|
+
function parseCreateTableAs(sql) {
|
|
302
|
+
// Match CREATE TABLE [schema.]table AS SELECT
|
|
303
|
+
const createMatch = sql.match(/CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"[^"]+")\s+AS\s+SELECT/i);
|
|
304
|
+
if (!createMatch)
|
|
305
|
+
return null;
|
|
306
|
+
const targetSchema = createMatch[1]?.toLowerCase() ?? 'public';
|
|
307
|
+
const targetTable = unquoteIdentifier(createMatch[2]);
|
|
308
|
+
// Extract source tables from the SELECT part
|
|
309
|
+
const sourceTables = extractSourceTables(sql);
|
|
310
|
+
// Extract joins if present
|
|
311
|
+
const joins = extractJoins(sql);
|
|
312
|
+
// Extract aggregations if present
|
|
313
|
+
const aggregations = extractAggregations(sql);
|
|
314
|
+
return {
|
|
315
|
+
operation: 'INSERT', // CTAS is effectively an INSERT
|
|
316
|
+
targetTable: {
|
|
317
|
+
schema: targetSchema,
|
|
318
|
+
table: targetTable,
|
|
319
|
+
},
|
|
320
|
+
sourceTables,
|
|
321
|
+
joins: joins.length > 0 ? joins : undefined,
|
|
322
|
+
aggregations: aggregations.length > 0 ? aggregations : undefined,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Parse SELECT with aggregations
|
|
327
|
+
*/
|
|
328
|
+
function parseSelectAggregate(sql) {
|
|
329
|
+
// Extract source tables
|
|
330
|
+
const sourceTables = extractSourceTables(sql);
|
|
331
|
+
// Extract aggregations
|
|
332
|
+
const aggregations = extractAggregations(sql);
|
|
333
|
+
// Extract WHERE filter
|
|
334
|
+
const whereFilter = extractWhereFilter(sql);
|
|
335
|
+
return {
|
|
336
|
+
operation: 'AGGREGATE',
|
|
337
|
+
sourceTables,
|
|
338
|
+
aggregations: aggregations.length > 0 ? aggregations : undefined,
|
|
339
|
+
whereFilter,
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Parse SELECT with subqueries
|
|
344
|
+
*/
|
|
345
|
+
function parseSelectSubquery(sql) {
|
|
346
|
+
// Extract main source tables
|
|
347
|
+
const sourceTables = extractSourceTables(sql);
|
|
348
|
+
// Extract subqueries and their source tables
|
|
349
|
+
const subqueries = extractSubqueries(sql);
|
|
350
|
+
const subquerySourceTables = subqueries.flatMap((sq) => sq.sourceTables);
|
|
351
|
+
// Combine all source tables (deduplicated)
|
|
352
|
+
const allSourceTables = [...sourceTables];
|
|
353
|
+
const seen = new Set(sourceTables.map((t) => `${t.schema}.${t.table}`));
|
|
354
|
+
for (const st of subquerySourceTables) {
|
|
355
|
+
const key = `${st.schema}.${st.table}`;
|
|
356
|
+
if (!seen.has(key)) {
|
|
357
|
+
seen.add(key);
|
|
358
|
+
allSourceTables.push(st);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
operation: 'SUBQUERY',
|
|
363
|
+
sourceTables: allSourceTables,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Extract WHERE filter from SQL
|
|
368
|
+
*/
|
|
369
|
+
function extractWhereFilter(sql) {
|
|
370
|
+
const whereMatch = sql.match(/WHERE\s+([^;]+?)(?:\s+GROUP|\s+ORDER|\s+LIMIT|\s+HAVING|\s*$|\s*;)/i);
|
|
371
|
+
if (whereMatch) {
|
|
372
|
+
return whereMatch[1].trim();
|
|
373
|
+
}
|
|
374
|
+
return undefined;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Extract source tables from SQL
|
|
378
|
+
*/
|
|
379
|
+
function extractSourceTables(sql) {
|
|
380
|
+
const tables = [];
|
|
381
|
+
const seen = new Set();
|
|
382
|
+
// Match FROM clause - capture everything until WHERE, GROUP, ORDER, LIMIT, JOIN, UNION, INTERSECT, EXCEPT, or end
|
|
383
|
+
// Use a non-greedy match and explicitly handle the end case
|
|
384
|
+
// Updated regex to allow dots in table names (for schema.table)
|
|
385
|
+
const fromMatch = sql.match(/FROM\s+((?:[a-z_][a-z0-9_.]*(?:\s+(?:AS\s+)?[a-z_][a-z0-9_]*)?(?:\s*,\s*)?)+)(?:\s+WHERE|\s+GROUP|\s+ORDER|\s+LIMIT|\s+(?:INNER|LEFT|RIGHT|FULL|CROSS)?\s*JOIN|\s+UNION|\s+INTERSECT|\s+EXCEPT|\s*$|\s*;)/i);
|
|
386
|
+
if (fromMatch) {
|
|
387
|
+
const fromClause = fromMatch[1];
|
|
388
|
+
if (!fromClause)
|
|
389
|
+
return tables;
|
|
390
|
+
// Match schema.table or just table, with optional alias
|
|
391
|
+
const tablePattern = /(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"[^"]+")(?:\s+(?:AS\s+)?([a-z_][a-z0-9_]*))?/gi;
|
|
392
|
+
const tableMatches = fromClause.matchAll(tablePattern);
|
|
393
|
+
for (const match of tableMatches) {
|
|
394
|
+
const schema = match[1]?.toLowerCase() ?? 'public';
|
|
395
|
+
const table = unquoteIdentifier(match[2]);
|
|
396
|
+
const alias = match[3]?.toLowerCase();
|
|
397
|
+
const key = `${schema}.${table}`;
|
|
398
|
+
if (!seen.has(key)) {
|
|
399
|
+
seen.add(key);
|
|
400
|
+
tables.push({ schema, table, ...(alias !== undefined && { alias }) });
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Match JOIN clauses - extract all JOINed tables
|
|
405
|
+
const joinPattern = /(?:INNER|LEFT|RIGHT|FULL|CROSS)?\s*JOIN\s+(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"[^"]+")(?:\s+(?:AS\s+)?([a-z_][a-z0-9_]*))?/gi;
|
|
406
|
+
const joinMatches = sql.matchAll(joinPattern);
|
|
407
|
+
for (const match of joinMatches) {
|
|
408
|
+
const schema = match[1]?.toLowerCase() ?? 'public';
|
|
409
|
+
const table = unquoteIdentifier(match[2]);
|
|
410
|
+
const alias = match[3]?.toLowerCase();
|
|
411
|
+
const key = `${schema}.${table}`;
|
|
412
|
+
if (!seen.has(key)) {
|
|
413
|
+
seen.add(key);
|
|
414
|
+
tables.push({ schema, table, ...(alias !== undefined && { alias }) });
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
// Match UNION/INTERSECT/EXCEPT source tables - find nested SELECTs
|
|
418
|
+
const unionPattern = /(?:UNION|INTERSECT|EXCEPT)(?:\s+ALL)?\s+SELECT\s+.*?\s+FROM\s+(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"[^"]+")/gi;
|
|
419
|
+
const unionMatches = sql.matchAll(unionPattern);
|
|
420
|
+
for (const match of unionMatches) {
|
|
421
|
+
const schema = match[1]?.toLowerCase() ?? 'public';
|
|
422
|
+
const table = unquoteIdentifier(match[2]);
|
|
423
|
+
const key = `${schema}.${table}`;
|
|
424
|
+
if (!seen.has(key)) {
|
|
425
|
+
seen.add(key);
|
|
426
|
+
tables.push({ schema, table });
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return tables;
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Extract JOIN dependencies from SQL with proper left table tracking
|
|
433
|
+
*/
|
|
434
|
+
function extractJoins(sql) {
|
|
435
|
+
const joins = [];
|
|
436
|
+
const tables = extractSourceTables(sql);
|
|
437
|
+
// Extract the primary table from the FROM clause (first table)
|
|
438
|
+
let currentLeftTable = tables[0] ?? { schema: 'public', table: 'unknown' };
|
|
439
|
+
// Enhanced JOIN pattern with ON clause capture
|
|
440
|
+
const joinPattern = /(INNER|LEFT|RIGHT|FULL|CROSS)?\s*JOIN\s+(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"[^"]+")(?:\s+(?:AS\s+)?([a-z_][a-z0-9_]*))?\s+ON\s+([^;]+?)(?=\s+(?:INNER|LEFT|RIGHT|FULL|CROSS)?\s*JOIN|\s+WHERE|\s+GROUP|\s+ORDER|\s+LIMIT|\s*$|\s*;)/gi;
|
|
441
|
+
const matches = sql.matchAll(joinPattern);
|
|
442
|
+
for (const match of matches) {
|
|
443
|
+
const joinType = (match[1]?.toUpperCase() || 'INNER');
|
|
444
|
+
const schema = match[2]?.toLowerCase() ?? 'public';
|
|
445
|
+
const table = unquoteIdentifier(match[3]);
|
|
446
|
+
const alias = match[4]?.toLowerCase();
|
|
447
|
+
const onClause = match[5];
|
|
448
|
+
// Parse join columns from ON clause
|
|
449
|
+
const joinColumns = extractJoinColumns(onClause, currentLeftTable, { schema, table, ...(alias !== undefined && { alias }) });
|
|
450
|
+
joins.push({
|
|
451
|
+
joinType,
|
|
452
|
+
leftTable: { schema: currentLeftTable.schema, table: currentLeftTable.table },
|
|
453
|
+
rightTable: { schema, table },
|
|
454
|
+
joinColumns,
|
|
455
|
+
timestamp: Date.now(),
|
|
456
|
+
});
|
|
457
|
+
// Update current left table for chained joins
|
|
458
|
+
currentLeftTable = { schema, table, ...(alias !== undefined && { alias }) };
|
|
459
|
+
}
|
|
460
|
+
// If no ON clause detected, try simpler pattern
|
|
461
|
+
if (joins.length === 0) {
|
|
462
|
+
const simpleJoinPattern = /(INNER|LEFT|RIGHT|FULL|CROSS)?\s*JOIN\s+(?:([a-z_][a-z0-9_]*)\s*\.\s*)?([a-z_][a-z0-9_]*|"[^"]+")/gi;
|
|
463
|
+
const simpleMatches = sql.matchAll(simpleJoinPattern);
|
|
464
|
+
for (const match of simpleMatches) {
|
|
465
|
+
const joinType = (match[1]?.toUpperCase() || 'INNER');
|
|
466
|
+
const schema = match[2]?.toLowerCase() ?? 'public';
|
|
467
|
+
const table = unquoteIdentifier(match[3]);
|
|
468
|
+
joins.push({
|
|
469
|
+
joinType,
|
|
470
|
+
leftTable: { schema: currentLeftTable.schema, table: currentLeftTable.table },
|
|
471
|
+
rightTable: { schema, table },
|
|
472
|
+
joinColumns: [],
|
|
473
|
+
timestamp: Date.now(),
|
|
474
|
+
});
|
|
475
|
+
currentLeftTable = { schema, table };
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
return joins;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
481
|
+
* Extract join columns from ON clause
|
|
482
|
+
*/
|
|
483
|
+
function extractJoinColumns(onClause, leftTable, rightTable) {
|
|
484
|
+
const columns = [];
|
|
485
|
+
// Pattern to match column comparisons: table.column = table.column
|
|
486
|
+
const comparisonPattern = /([a-z_][a-z0-9_]*(?:\.[a-z_][a-z0-9_]*)?)\s*=\s*([a-z_][a-z0-9_]*(?:\.[a-z_][a-z0-9_]*)?)/gi;
|
|
487
|
+
const matches = onClause.matchAll(comparisonPattern);
|
|
488
|
+
const leftNames = [leftTable.table, leftTable.alias].filter(Boolean);
|
|
489
|
+
const rightNames = [rightTable.table, rightTable.alias].filter(Boolean);
|
|
490
|
+
for (const match of matches) {
|
|
491
|
+
const col1 = match[1].toLowerCase();
|
|
492
|
+
const col2 = match[2].toLowerCase();
|
|
493
|
+
// Determine which column belongs to which table
|
|
494
|
+
const col1Parts = col1.split('.');
|
|
495
|
+
const col2Parts = col2.split('.');
|
|
496
|
+
let leftCol;
|
|
497
|
+
let rightCol;
|
|
498
|
+
// Check if col1 belongs to left or right table
|
|
499
|
+
if (col1Parts.length === 2) {
|
|
500
|
+
if (leftNames.includes(col1Parts[0])) {
|
|
501
|
+
leftCol = col1Parts[1];
|
|
502
|
+
}
|
|
503
|
+
else if (rightNames.includes(col1Parts[0])) {
|
|
504
|
+
rightCol = col1Parts[1];
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
if (col2Parts.length === 2) {
|
|
508
|
+
if (leftNames.includes(col2Parts[0])) {
|
|
509
|
+
leftCol = leftCol || col2Parts[1];
|
|
510
|
+
}
|
|
511
|
+
else if (rightNames.includes(col2Parts[0])) {
|
|
512
|
+
rightCol = rightCol || col2Parts[1];
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
// If both columns identified, add to result
|
|
516
|
+
if (leftCol && rightCol) {
|
|
517
|
+
columns.push({ left: leftCol, right: rightCol });
|
|
518
|
+
}
|
|
519
|
+
else if (col1Parts.length === 1 && col2Parts.length === 1) {
|
|
520
|
+
// Unqualified columns - assume same column name on both sides
|
|
521
|
+
columns.push({ left: col1Parts[0], right: col2Parts[0] });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return columns;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Extract aggregations from SQL
|
|
528
|
+
*/
|
|
529
|
+
function extractAggregations(sql) {
|
|
530
|
+
const aggregations = [];
|
|
531
|
+
const upperSql = sql.toUpperCase();
|
|
532
|
+
// Check if this is an aggregation query
|
|
533
|
+
const aggregateFunctions = ['COUNT', 'SUM', 'AVG', 'MIN', 'MAX', 'ARRAY_AGG', 'STRING_AGG', 'JSON_AGG', 'JSONB_AGG'];
|
|
534
|
+
const hasAggregation = aggregateFunctions.some((fn) => upperSql.includes(fn + '('));
|
|
535
|
+
if (!hasAggregation) {
|
|
536
|
+
return aggregations;
|
|
537
|
+
}
|
|
538
|
+
// Extract source tables
|
|
539
|
+
const sourceTables = extractSourceTables(sql);
|
|
540
|
+
if (sourceTables.length === 0) {
|
|
541
|
+
return aggregations;
|
|
542
|
+
}
|
|
543
|
+
// Extract aggregate columns
|
|
544
|
+
const aggregatedColumns = [];
|
|
545
|
+
for (const fn of aggregateFunctions) {
|
|
546
|
+
// Match aggregation function calls: FUNC(column) AS alias or FUNC(column)
|
|
547
|
+
const fnPattern = new RegExp(`${fn}\\s*\\(\\s*(?:DISTINCT\\s+)?([a-z_][a-z0-9_]*(?:\\.[a-z_][a-z0-9_]*)?|\\*)\\s*\\)(?:\\s+AS\\s+([a-z_][a-z0-9_]*))?`, 'gi');
|
|
548
|
+
const matches = sql.matchAll(fnPattern);
|
|
549
|
+
for (const match of matches) {
|
|
550
|
+
const column = match[1].toLowerCase();
|
|
551
|
+
const alias = match[2]?.toLowerCase();
|
|
552
|
+
aggregatedColumns.push({
|
|
553
|
+
column,
|
|
554
|
+
function: fn,
|
|
555
|
+
...(alias !== undefined && { alias }),
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
// Extract GROUP BY columns
|
|
560
|
+
const groupByColumns = [];
|
|
561
|
+
const groupByMatch = sql.match(/GROUP\s+BY\s+([^;]+?)(?:\s+HAVING|\s+ORDER|\s+LIMIT|\s*$|\s*;)/i);
|
|
562
|
+
if (groupByMatch) {
|
|
563
|
+
const groupByClause = groupByMatch[1];
|
|
564
|
+
// Split by comma and extract column names
|
|
565
|
+
const cols = groupByClause.split(',').map((c) => c.trim().toLowerCase());
|
|
566
|
+
groupByColumns.push(...cols);
|
|
567
|
+
}
|
|
568
|
+
// Extract HAVING filter
|
|
569
|
+
let havingFilter;
|
|
570
|
+
const havingMatch = sql.match(/HAVING\s+([^;]+?)(?:\s+ORDER|\s+LIMIT|\s*$|\s*;)/i);
|
|
571
|
+
if (havingMatch) {
|
|
572
|
+
havingFilter = havingMatch[1].trim();
|
|
573
|
+
}
|
|
574
|
+
// Create aggregation dependency for each source table
|
|
575
|
+
for (const sourceTable of sourceTables) {
|
|
576
|
+
aggregations.push({
|
|
577
|
+
sourceTable: {
|
|
578
|
+
schema: sourceTable.schema,
|
|
579
|
+
table: sourceTable.table,
|
|
580
|
+
},
|
|
581
|
+
aggregatedColumns,
|
|
582
|
+
groupByColumns,
|
|
583
|
+
havingFilter,
|
|
584
|
+
timestamp: Date.now(),
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
return aggregations;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Extract CTEs (Common Table Expressions) from SQL
|
|
591
|
+
*/
|
|
592
|
+
function extractCTEs(sql) {
|
|
593
|
+
const ctes = [];
|
|
594
|
+
// Match WITH clause CTEs
|
|
595
|
+
const ctePattern = /WITH\s+(?:RECURSIVE\s+)?([a-z_][a-z0-9_]*)\s+AS\s*\(\s*(SELECT[^)]+)\)/gi;
|
|
596
|
+
const matches = sql.matchAll(ctePattern);
|
|
597
|
+
for (const match of matches) {
|
|
598
|
+
const cteName = match[1].toLowerCase();
|
|
599
|
+
const cteQuery = match[2];
|
|
600
|
+
// Extract source tables from CTE query
|
|
601
|
+
const sourceTables = extractSourceTables(cteQuery);
|
|
602
|
+
ctes.push({
|
|
603
|
+
name: cteName,
|
|
604
|
+
sourceTables,
|
|
605
|
+
});
|
|
606
|
+
}
|
|
607
|
+
return ctes;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Extract subqueries from SQL
|
|
611
|
+
*/
|
|
612
|
+
function extractSubqueries(sql) {
|
|
613
|
+
const subqueries = [];
|
|
614
|
+
// Match subqueries in FROM clause: (SELECT ...) AS alias
|
|
615
|
+
const subqueryPattern = /\(\s*(SELECT[^)]+)\s*\)\s*(?:AS\s+)?([a-z_][a-z0-9_]*)?/gi;
|
|
616
|
+
const matches = sql.matchAll(subqueryPattern);
|
|
617
|
+
for (const match of matches) {
|
|
618
|
+
const subquery = match[1];
|
|
619
|
+
const alias = match[2]?.toLowerCase();
|
|
620
|
+
// Extract source tables from subquery
|
|
621
|
+
const sourceTables = extractSourceTables(subquery);
|
|
622
|
+
if (sourceTables.length > 0) {
|
|
623
|
+
subqueries.push({
|
|
624
|
+
sourceTables,
|
|
625
|
+
...(alias !== undefined && { alias }),
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return subqueries;
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Remove quotes from an identifier
|
|
633
|
+
*/
|
|
634
|
+
function unquoteIdentifier(identifier) {
|
|
635
|
+
if (identifier.startsWith('"') && identifier.endsWith('"')) {
|
|
636
|
+
return identifier.slice(1, -1).replace(/""/g, '"');
|
|
637
|
+
}
|
|
638
|
+
return identifier.toLowerCase();
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Data Lineage Tracker
|
|
642
|
+
*
|
|
643
|
+
* Tracks data flow between tables, records transformations,
|
|
644
|
+
* and provides lineage queries for any row.
|
|
645
|
+
*/
|
|
646
|
+
export class LineageTracker {
|
|
647
|
+
config;
|
|
648
|
+
graph;
|
|
649
|
+
rowLineageMap = new Map();
|
|
650
|
+
constructor(config = {}) {
|
|
651
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
652
|
+
this.graph = {
|
|
653
|
+
nodes: new Map(),
|
|
654
|
+
edges: new Map(),
|
|
655
|
+
sourceIndex: new Map(),
|
|
656
|
+
targetIndex: new Map(),
|
|
657
|
+
};
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* Get current configuration
|
|
661
|
+
*/
|
|
662
|
+
getConfig() {
|
|
663
|
+
return { ...this.config };
|
|
664
|
+
}
|
|
665
|
+
/**
|
|
666
|
+
* Update configuration
|
|
667
|
+
*/
|
|
668
|
+
setConfig(config) {
|
|
669
|
+
this.config = { ...this.config, ...config };
|
|
670
|
+
}
|
|
671
|
+
/**
|
|
672
|
+
* Check if lineage tracking is enabled
|
|
673
|
+
*/
|
|
674
|
+
isEnabled() {
|
|
675
|
+
return this.config.enabled;
|
|
676
|
+
}
|
|
677
|
+
/**
|
|
678
|
+
* Enable or disable lineage tracking
|
|
679
|
+
*/
|
|
680
|
+
setEnabled(enabled) {
|
|
681
|
+
this.config.enabled = enabled;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Track a WAL entry for lineage
|
|
685
|
+
*/
|
|
686
|
+
trackWALEntry(entry) {
|
|
687
|
+
if (!this.config.enabled)
|
|
688
|
+
return;
|
|
689
|
+
// Check table filters
|
|
690
|
+
if (this.config.includeTables.length > 0 && !this.config.includeTables.includes(entry.table)) {
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
if (this.config.excludeTables.includes(entry.table)) {
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
// Ensure target node exists
|
|
697
|
+
this.ensureNode(entry.schema, entry.table, 'table');
|
|
698
|
+
// Parse SQL for lineage if available
|
|
699
|
+
if (entry.sql) {
|
|
700
|
+
const lineage = parseLineage(entry.sql);
|
|
701
|
+
if (lineage) {
|
|
702
|
+
this.trackLineage(lineage, entry);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
// Track row-level lineage if enabled
|
|
706
|
+
if (this.config.trackRows && entry.primaryKey) {
|
|
707
|
+
this.trackRowLineage(entry);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Track lineage from parsed SQL
|
|
712
|
+
*/
|
|
713
|
+
trackLineage(lineage, entry) {
|
|
714
|
+
if (!lineage.targetTable)
|
|
715
|
+
return;
|
|
716
|
+
const targetNodeId = generateNodeId(lineage.targetTable.schema, lineage.targetTable.table);
|
|
717
|
+
// Track source tables
|
|
718
|
+
for (const source of lineage.sourceTables) {
|
|
719
|
+
const sourceNodeId = generateNodeId(source.schema, source.table);
|
|
720
|
+
// Ensure source node exists
|
|
721
|
+
this.ensureNode(source.schema, source.table, 'table');
|
|
722
|
+
// Create edge
|
|
723
|
+
this.addEdge({
|
|
724
|
+
id: generateEdgeId(sourceNodeId, targetNodeId, Date.now()),
|
|
725
|
+
sourceId: sourceNodeId,
|
|
726
|
+
targetId: targetNodeId,
|
|
727
|
+
operation: lineage.operation,
|
|
728
|
+
timestamp: entry.timestamp,
|
|
729
|
+
lsn: entry.lsn,
|
|
730
|
+
transactionId: entry.transactionId,
|
|
731
|
+
sql: entry.sql,
|
|
732
|
+
joinDependency: lineage.joins?.[0],
|
|
733
|
+
aggregateDependency: lineage.aggregations?.[0],
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Track row-level lineage
|
|
739
|
+
*/
|
|
740
|
+
trackRowLineage(entry) {
|
|
741
|
+
if (!entry.primaryKey)
|
|
742
|
+
return;
|
|
743
|
+
const rowKey = this.getRowKey(entry.schema, entry.table, entry.primaryKey);
|
|
744
|
+
const rowLineage = {
|
|
745
|
+
targetTable: {
|
|
746
|
+
schema: entry.schema,
|
|
747
|
+
table: entry.table,
|
|
748
|
+
},
|
|
749
|
+
targetPrimaryKey: entry.primaryKey,
|
|
750
|
+
sourceRows: [],
|
|
751
|
+
operation: entry.operation,
|
|
752
|
+
timestamp: entry.timestamp,
|
|
753
|
+
lsn: entry.lsn,
|
|
754
|
+
transactionId: entry.transactionId,
|
|
755
|
+
};
|
|
756
|
+
// For UPDATE operations, track the old row as source
|
|
757
|
+
if (entry.operation === 'UPDATE' && entry.oldRow) {
|
|
758
|
+
rowLineage.sourceRows.push({
|
|
759
|
+
table: {
|
|
760
|
+
schema: entry.schema,
|
|
761
|
+
table: entry.table,
|
|
762
|
+
},
|
|
763
|
+
primaryKey: entry.primaryKey,
|
|
764
|
+
contributionType: 'direct',
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
// Store row lineage
|
|
768
|
+
if (!this.rowLineageMap.has(rowKey)) {
|
|
769
|
+
this.rowLineageMap.set(rowKey, []);
|
|
770
|
+
}
|
|
771
|
+
this.rowLineageMap.get(rowKey).push(rowLineage);
|
|
772
|
+
}
|
|
773
|
+
/**
|
|
774
|
+
* Get row key for lineage map
|
|
775
|
+
*/
|
|
776
|
+
getRowKey(schema, table, primaryKey) {
|
|
777
|
+
return `${schema}.${table}:${JSON.stringify(primaryKey)}`;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Ensure a node exists in the graph
|
|
781
|
+
*/
|
|
782
|
+
ensureNode(schema, table, type) {
|
|
783
|
+
const nodeId = generateNodeId(schema, table);
|
|
784
|
+
if (!this.graph.nodes.has(nodeId)) {
|
|
785
|
+
const now = Date.now();
|
|
786
|
+
this.graph.nodes.set(nodeId, {
|
|
787
|
+
id: nodeId,
|
|
788
|
+
type,
|
|
789
|
+
schema,
|
|
790
|
+
name: table,
|
|
791
|
+
createdAt: now,
|
|
792
|
+
updatedAt: now,
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
// Update timestamp
|
|
797
|
+
const node = this.graph.nodes.get(nodeId);
|
|
798
|
+
node.updatedAt = Date.now();
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Add an edge to the graph
|
|
803
|
+
*/
|
|
804
|
+
addEdge(edge) {
|
|
805
|
+
// Add edge
|
|
806
|
+
this.graph.edges.set(edge.id, edge);
|
|
807
|
+
// Update source index
|
|
808
|
+
if (!this.graph.sourceIndex.has(edge.sourceId)) {
|
|
809
|
+
this.graph.sourceIndex.set(edge.sourceId, new Set());
|
|
810
|
+
}
|
|
811
|
+
this.graph.sourceIndex.get(edge.sourceId).add(edge.id);
|
|
812
|
+
// Update target index
|
|
813
|
+
if (!this.graph.targetIndex.has(edge.targetId)) {
|
|
814
|
+
this.graph.targetIndex.set(edge.targetId, new Set());
|
|
815
|
+
}
|
|
816
|
+
this.graph.targetIndex.get(edge.targetId).add(edge.id);
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Get lineage for a specific table
|
|
820
|
+
*/
|
|
821
|
+
getTableLineage(schema, table) {
|
|
822
|
+
const nodeId = generateNodeId(schema, table);
|
|
823
|
+
// Get upstream (sources)
|
|
824
|
+
const upstreamEdgeIds = this.graph.targetIndex.get(nodeId) || new Set();
|
|
825
|
+
const upstreamTables = new Set();
|
|
826
|
+
const edges = [];
|
|
827
|
+
for (const edgeId of upstreamEdgeIds) {
|
|
828
|
+
const edge = this.graph.edges.get(edgeId);
|
|
829
|
+
if (edge) {
|
|
830
|
+
upstreamTables.add(edge.sourceId);
|
|
831
|
+
edges.push(edge);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
// Get downstream (targets)
|
|
835
|
+
const downstreamEdgeIds = this.graph.sourceIndex.get(nodeId) || new Set();
|
|
836
|
+
const downstreamTables = new Set();
|
|
837
|
+
for (const edgeId of downstreamEdgeIds) {
|
|
838
|
+
const edge = this.graph.edges.get(edgeId);
|
|
839
|
+
if (edge) {
|
|
840
|
+
downstreamTables.add(edge.targetId);
|
|
841
|
+
edges.push(edge);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
return {
|
|
845
|
+
upstreamTables: Array.from(upstreamTables),
|
|
846
|
+
downstreamTables: Array.from(downstreamTables),
|
|
847
|
+
edges,
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
/**
|
|
851
|
+
* Query lineage for a specific row
|
|
852
|
+
*/
|
|
853
|
+
queryRowLineage(schema, table, primaryKey) {
|
|
854
|
+
if (!this.config.trackRows) {
|
|
855
|
+
throw new Error('Row-level lineage tracking is not enabled');
|
|
856
|
+
}
|
|
857
|
+
const rowKey = this.getRowKey(schema, table, primaryKey);
|
|
858
|
+
const lineagePath = this.rowLineageMap.get(rowKey);
|
|
859
|
+
if (!lineagePath) {
|
|
860
|
+
return null;
|
|
861
|
+
}
|
|
862
|
+
// Calculate depth and source tables
|
|
863
|
+
const depth = lineagePath.length;
|
|
864
|
+
const sourceTables = new Set();
|
|
865
|
+
for (const lineage of lineagePath) {
|
|
866
|
+
for (const source of lineage.sourceRows) {
|
|
867
|
+
sourceTables.add(`${source.table.schema}.${source.table.table}`);
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
return {
|
|
871
|
+
row: {
|
|
872
|
+
schema,
|
|
873
|
+
table,
|
|
874
|
+
primaryKey,
|
|
875
|
+
},
|
|
876
|
+
lineagePath,
|
|
877
|
+
depth,
|
|
878
|
+
sourceTables: Array.from(sourceTables)
|
|
879
|
+
.map((id) => {
|
|
880
|
+
const [schema, table] = id.split('.');
|
|
881
|
+
return schema && table ? { schema, table } : null;
|
|
882
|
+
})
|
|
883
|
+
.filter((t) => t !== null),
|
|
884
|
+
};
|
|
885
|
+
}
|
|
886
|
+
/**
|
|
887
|
+
* Visualize lineage graph for a table
|
|
888
|
+
*/
|
|
889
|
+
visualizeLineage(schema, table, maxDepth) {
|
|
890
|
+
// Use provided maxDepth, or fallback to config. When maxDepth is explicitly 0, use 0.
|
|
891
|
+
const depth = maxDepth !== undefined ? maxDepth : this.config.maxDepth;
|
|
892
|
+
const nodeId = generateNodeId(schema, table);
|
|
893
|
+
const visitedNodes = new Set();
|
|
894
|
+
const visitedEdges = new Set();
|
|
895
|
+
const nodes = [];
|
|
896
|
+
const edges = [];
|
|
897
|
+
const rootNodes = new Set();
|
|
898
|
+
const leafNodes = new Set();
|
|
899
|
+
// Get the starting node
|
|
900
|
+
const startingNode = this.graph.nodes.get(nodeId);
|
|
901
|
+
if (!startingNode) {
|
|
902
|
+
return {
|
|
903
|
+
nodes: [],
|
|
904
|
+
edges: [],
|
|
905
|
+
maxDepth: 0,
|
|
906
|
+
rootNodes: [],
|
|
907
|
+
leafNodes: [],
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
// Add starting node
|
|
911
|
+
nodes.push({
|
|
912
|
+
id: startingNode.id,
|
|
913
|
+
label: startingNode.name,
|
|
914
|
+
type: startingNode.type,
|
|
915
|
+
schema: startingNode.schema,
|
|
916
|
+
table: startingNode.name,
|
|
917
|
+
level: 0,
|
|
918
|
+
});
|
|
919
|
+
// If maxDepth is 0, only return the starting node
|
|
920
|
+
if (depth === 0) {
|
|
921
|
+
// Check if starting node is root or leaf
|
|
922
|
+
const hasUpstream = (this.graph.targetIndex.get(nodeId)?.size || 0) > 0;
|
|
923
|
+
const hasDownstream = (this.graph.sourceIndex.get(nodeId)?.size || 0) > 0;
|
|
924
|
+
if (!hasUpstream)
|
|
925
|
+
rootNodes.add(nodeId);
|
|
926
|
+
if (!hasDownstream)
|
|
927
|
+
leafNodes.add(nodeId);
|
|
928
|
+
return {
|
|
929
|
+
nodes,
|
|
930
|
+
edges: [],
|
|
931
|
+
maxDepth: 0,
|
|
932
|
+
rootNodes: Array.from(rootNodes),
|
|
933
|
+
leafNodes: Array.from(leafNodes),
|
|
934
|
+
};
|
|
935
|
+
}
|
|
936
|
+
// BFS traversal
|
|
937
|
+
const queue = [
|
|
938
|
+
{ nodeId, level: 0, direction: 'up' },
|
|
939
|
+
{ nodeId, level: 0, direction: 'down' },
|
|
940
|
+
];
|
|
941
|
+
while (queue.length > 0) {
|
|
942
|
+
const { nodeId: currentId, level, direction } = queue.shift();
|
|
943
|
+
if (level >= depth)
|
|
944
|
+
continue;
|
|
945
|
+
if (visitedNodes.has(`${currentId}:${direction}`))
|
|
946
|
+
continue;
|
|
947
|
+
visitedNodes.add(`${currentId}:${direction}`);
|
|
948
|
+
const node = this.graph.nodes.get(currentId);
|
|
949
|
+
if (!node)
|
|
950
|
+
continue;
|
|
951
|
+
// Add node to visualization (skip if already added as starting node)
|
|
952
|
+
if (!nodes.find((n) => n.id === currentId)) {
|
|
953
|
+
nodes.push({
|
|
954
|
+
id: node.id,
|
|
955
|
+
label: node.name,
|
|
956
|
+
type: node.type,
|
|
957
|
+
schema: node.schema,
|
|
958
|
+
table: node.name,
|
|
959
|
+
level,
|
|
960
|
+
});
|
|
961
|
+
}
|
|
962
|
+
// Traverse edges
|
|
963
|
+
if (direction === 'up') {
|
|
964
|
+
// Upstream (sources)
|
|
965
|
+
const edgeIds = this.graph.targetIndex.get(currentId) || new Set();
|
|
966
|
+
if (edgeIds.size === 0) {
|
|
967
|
+
rootNodes.add(currentId);
|
|
968
|
+
}
|
|
969
|
+
for (const edgeId of edgeIds) {
|
|
970
|
+
if (visitedEdges.has(edgeId))
|
|
971
|
+
continue;
|
|
972
|
+
visitedEdges.add(edgeId);
|
|
973
|
+
const edge = this.graph.edges.get(edgeId);
|
|
974
|
+
if (!edge)
|
|
975
|
+
continue;
|
|
976
|
+
edges.push({
|
|
977
|
+
id: edge.id,
|
|
978
|
+
source: edge.sourceId,
|
|
979
|
+
target: edge.targetId,
|
|
980
|
+
operation: edge.operation,
|
|
981
|
+
label: edge.operation,
|
|
982
|
+
});
|
|
983
|
+
queue.push({ nodeId: edge.sourceId, level: level + 1, direction: 'up' });
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
else {
|
|
987
|
+
// Downstream (targets)
|
|
988
|
+
const edgeIds = this.graph.sourceIndex.get(currentId) || new Set();
|
|
989
|
+
if (edgeIds.size === 0) {
|
|
990
|
+
leafNodes.add(currentId);
|
|
991
|
+
}
|
|
992
|
+
for (const edgeId of edgeIds) {
|
|
993
|
+
if (visitedEdges.has(edgeId))
|
|
994
|
+
continue;
|
|
995
|
+
visitedEdges.add(edgeId);
|
|
996
|
+
const edge = this.graph.edges.get(edgeId);
|
|
997
|
+
if (!edge)
|
|
998
|
+
continue;
|
|
999
|
+
edges.push({
|
|
1000
|
+
id: edge.id,
|
|
1001
|
+
source: edge.sourceId,
|
|
1002
|
+
target: edge.targetId,
|
|
1003
|
+
operation: edge.operation,
|
|
1004
|
+
label: edge.operation,
|
|
1005
|
+
});
|
|
1006
|
+
queue.push({ nodeId: edge.targetId, level: level + 1, direction: 'down' });
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
return {
|
|
1011
|
+
nodes,
|
|
1012
|
+
edges,
|
|
1013
|
+
maxDepth: nodes.length > 0 ? Math.max(...nodes.map((n) => n.level)) : 0,
|
|
1014
|
+
rootNodes: Array.from(rootNodes),
|
|
1015
|
+
leafNodes: Array.from(leafNodes),
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
/**
|
|
1019
|
+
* Get statistics about tracked lineage
|
|
1020
|
+
*/
|
|
1021
|
+
getStats() {
|
|
1022
|
+
let totalDepth = 0;
|
|
1023
|
+
let depthCount = 0;
|
|
1024
|
+
// Calculate average depth by sampling nodes
|
|
1025
|
+
for (const [nodeId] of this.graph.nodes) {
|
|
1026
|
+
const depth = this.calculateNodeDepth(nodeId);
|
|
1027
|
+
totalDepth += depth;
|
|
1028
|
+
depthCount++;
|
|
1029
|
+
}
|
|
1030
|
+
// Estimate memory usage
|
|
1031
|
+
const graphSize = JSON.stringify(Array.from(this.graph.nodes.values())).length +
|
|
1032
|
+
JSON.stringify(Array.from(this.graph.edges.values())).length;
|
|
1033
|
+
const rowLineageSize = JSON.stringify(Array.from(this.rowLineageMap.values())).length;
|
|
1034
|
+
return {
|
|
1035
|
+
totalNodes: this.graph.nodes.size,
|
|
1036
|
+
totalEdges: this.graph.edges.size,
|
|
1037
|
+
trackedTables: this.graph.nodes.size,
|
|
1038
|
+
transformationCount: Array.from(this.graph.edges.values()).filter((e) => e.operation === 'JOIN' || e.operation === 'AGGREGATE').length,
|
|
1039
|
+
avgGraphDepth: depthCount > 0 ? totalDepth / depthCount : 0,
|
|
1040
|
+
lastUpdateAt: this.getLastUpdateTimestamp(),
|
|
1041
|
+
memoryBytes: graphSize + rowLineageSize,
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* Calculate the depth of a node in the graph
|
|
1046
|
+
*/
|
|
1047
|
+
calculateNodeDepth(nodeId) {
|
|
1048
|
+
let maxDepth = 0;
|
|
1049
|
+
const visited = new Set();
|
|
1050
|
+
const queue = [{ id: nodeId, depth: 0 }];
|
|
1051
|
+
while (queue.length > 0) {
|
|
1052
|
+
const { id, depth } = queue.shift();
|
|
1053
|
+
if (visited.has(id))
|
|
1054
|
+
continue;
|
|
1055
|
+
visited.add(id);
|
|
1056
|
+
maxDepth = Math.max(maxDepth, depth);
|
|
1057
|
+
const edgeIds = this.graph.targetIndex.get(id) || new Set();
|
|
1058
|
+
for (const edgeId of edgeIds) {
|
|
1059
|
+
const edge = this.graph.edges.get(edgeId);
|
|
1060
|
+
if (edge) {
|
|
1061
|
+
queue.push({ id: edge.sourceId, depth: depth + 1 });
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
return maxDepth;
|
|
1066
|
+
}
|
|
1067
|
+
/**
|
|
1068
|
+
* Get the last update timestamp
|
|
1069
|
+
*/
|
|
1070
|
+
getLastUpdateTimestamp() {
|
|
1071
|
+
let lastUpdate = null;
|
|
1072
|
+
for (const [, node] of this.graph.nodes) {
|
|
1073
|
+
if (lastUpdate === null || node.updatedAt > lastUpdate) {
|
|
1074
|
+
lastUpdate = node.updatedAt;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
return lastUpdate;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Export lineage metadata for Iceberg table properties
|
|
1081
|
+
*/
|
|
1082
|
+
exportIcebergMetadata(schema, table) {
|
|
1083
|
+
const lineage = this.getTableLineage(schema, table);
|
|
1084
|
+
return {
|
|
1085
|
+
'lineage.version': '1.0',
|
|
1086
|
+
'lineage.sources': lineage.upstreamTables.join(','),
|
|
1087
|
+
'lineage.operations': lineage.edges.map((e) => e.operation).join(','),
|
|
1088
|
+
'lineage.updated-at': new Date().toISOString(),
|
|
1089
|
+
'lineage.graph': JSON.stringify({
|
|
1090
|
+
upstreamTables: lineage.upstreamTables,
|
|
1091
|
+
downstreamTables: lineage.downstreamTables,
|
|
1092
|
+
edges: lineage.edges.map((e) => ({
|
|
1093
|
+
source: e.sourceId,
|
|
1094
|
+
target: e.targetId,
|
|
1095
|
+
operation: e.operation,
|
|
1096
|
+
})),
|
|
1097
|
+
}),
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Import lineage metadata from Iceberg table properties
|
|
1102
|
+
*/
|
|
1103
|
+
importIcebergMetadata(schema, table, metadata) {
|
|
1104
|
+
if (!metadata['lineage.graph'])
|
|
1105
|
+
return;
|
|
1106
|
+
try {
|
|
1107
|
+
const graph = JSON.parse(metadata['lineage.graph']);
|
|
1108
|
+
// Ensure the target node exists
|
|
1109
|
+
this.ensureNode(schema, table, 'table');
|
|
1110
|
+
// Import edges
|
|
1111
|
+
for (const edge of graph.edges || []) {
|
|
1112
|
+
const [sourceSchema, sourceTable] = edge.source.split('.');
|
|
1113
|
+
this.ensureNode(sourceSchema, sourceTable, 'table');
|
|
1114
|
+
this.addEdge({
|
|
1115
|
+
id: generateEdgeId(edge.source, edge.target, Date.now()),
|
|
1116
|
+
sourceId: edge.source,
|
|
1117
|
+
targetId: edge.target,
|
|
1118
|
+
operation: edge.operation,
|
|
1119
|
+
timestamp: new Date(metadata['lineage.updated-at']).getTime(),
|
|
1120
|
+
});
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
catch (error) {
|
|
1124
|
+
console.error('Failed to import lineage metadata:', error);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
/**
|
|
1128
|
+
* Query all upstream tables (data sources) for a given table
|
|
1129
|
+
* Traverses the graph recursively to find all tables that feed into this one
|
|
1130
|
+
*/
|
|
1131
|
+
queryUpstreamLineage(schema, table, maxDepth) {
|
|
1132
|
+
// Use provided maxDepth, or fallback to config. When maxDepth is explicitly 0, use 0.
|
|
1133
|
+
const depth = maxDepth !== undefined ? maxDepth : this.config.maxDepth;
|
|
1134
|
+
const nodeId = generateNodeId(schema, table);
|
|
1135
|
+
const tables = [];
|
|
1136
|
+
const edges = [];
|
|
1137
|
+
const visited = new Set();
|
|
1138
|
+
const visitedEdges = new Set();
|
|
1139
|
+
// If maxDepth is 0, return empty results (no traversal)
|
|
1140
|
+
if (depth === 0) {
|
|
1141
|
+
return { tables, edges, totalDepth: 0 };
|
|
1142
|
+
}
|
|
1143
|
+
const queue = [{ id: nodeId, depth: 0 }];
|
|
1144
|
+
let totalDepth = 0;
|
|
1145
|
+
while (queue.length > 0) {
|
|
1146
|
+
const { id, depth: currentDepth } = queue.shift();
|
|
1147
|
+
if (visited.has(id) || currentDepth >= depth)
|
|
1148
|
+
continue;
|
|
1149
|
+
visited.add(id);
|
|
1150
|
+
// Get upstream edges (edges where this node is the target)
|
|
1151
|
+
const upstreamEdgeIds = this.graph.targetIndex.get(id) || new Set();
|
|
1152
|
+
for (const edgeId of upstreamEdgeIds) {
|
|
1153
|
+
if (visitedEdges.has(edgeId))
|
|
1154
|
+
continue;
|
|
1155
|
+
visitedEdges.add(edgeId);
|
|
1156
|
+
const edge = this.graph.edges.get(edgeId);
|
|
1157
|
+
if (!edge)
|
|
1158
|
+
continue;
|
|
1159
|
+
edges.push(edge);
|
|
1160
|
+
// Add source node to results
|
|
1161
|
+
const sourceNode = this.graph.nodes.get(edge.sourceId);
|
|
1162
|
+
if (sourceNode && !visited.has(edge.sourceId)) {
|
|
1163
|
+
tables.push({
|
|
1164
|
+
schema: sourceNode.schema,
|
|
1165
|
+
table: sourceNode.name,
|
|
1166
|
+
depth: currentDepth + 1,
|
|
1167
|
+
});
|
|
1168
|
+
totalDepth = Math.max(totalDepth, currentDepth + 1);
|
|
1169
|
+
queue.push({ id: edge.sourceId, depth: currentDepth + 1 });
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
return { tables, edges, totalDepth };
|
|
1174
|
+
}
|
|
1175
|
+
/**
|
|
1176
|
+
* Query all downstream tables (data consumers) for a given table
|
|
1177
|
+
* Traverses the graph recursively to find all tables that are derived from this one
|
|
1178
|
+
*/
|
|
1179
|
+
queryDownstreamLineage(schema, table, maxDepth) {
|
|
1180
|
+
const depth = maxDepth || this.config.maxDepth;
|
|
1181
|
+
const nodeId = generateNodeId(schema, table);
|
|
1182
|
+
const tables = [];
|
|
1183
|
+
const edges = [];
|
|
1184
|
+
const visited = new Set();
|
|
1185
|
+
const visitedEdges = new Set();
|
|
1186
|
+
const queue = [{ id: nodeId, depth: 0 }];
|
|
1187
|
+
let totalDepth = 0;
|
|
1188
|
+
while (queue.length > 0) {
|
|
1189
|
+
const { id, depth: currentDepth } = queue.shift();
|
|
1190
|
+
if (visited.has(id) || currentDepth > depth)
|
|
1191
|
+
continue;
|
|
1192
|
+
visited.add(id);
|
|
1193
|
+
// Get downstream edges (edges where this node is the source)
|
|
1194
|
+
const downstreamEdgeIds = this.graph.sourceIndex.get(id) || new Set();
|
|
1195
|
+
for (const edgeId of downstreamEdgeIds) {
|
|
1196
|
+
if (visitedEdges.has(edgeId))
|
|
1197
|
+
continue;
|
|
1198
|
+
visitedEdges.add(edgeId);
|
|
1199
|
+
const edge = this.graph.edges.get(edgeId);
|
|
1200
|
+
if (!edge)
|
|
1201
|
+
continue;
|
|
1202
|
+
edges.push(edge);
|
|
1203
|
+
// Add target node to results
|
|
1204
|
+
const targetNode = this.graph.nodes.get(edge.targetId);
|
|
1205
|
+
if (targetNode && !visited.has(edge.targetId)) {
|
|
1206
|
+
tables.push({
|
|
1207
|
+
schema: targetNode.schema,
|
|
1208
|
+
table: targetNode.name,
|
|
1209
|
+
depth: currentDepth + 1,
|
|
1210
|
+
});
|
|
1211
|
+
totalDepth = Math.max(totalDepth, currentDepth + 1);
|
|
1212
|
+
queue.push({ id: edge.targetId, depth: currentDepth + 1 });
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
return { tables, edges, totalDepth };
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Find the shortest path between two tables in the lineage graph
|
|
1220
|
+
*/
|
|
1221
|
+
findLineagePath(sourceSchema, sourceTable, targetSchema, targetTable) {
|
|
1222
|
+
const sourceId = generateNodeId(sourceSchema, sourceTable);
|
|
1223
|
+
const targetId = generateNodeId(targetSchema, targetTable);
|
|
1224
|
+
if (!this.graph.nodes.has(sourceId) || !this.graph.nodes.has(targetId)) {
|
|
1225
|
+
return null;
|
|
1226
|
+
}
|
|
1227
|
+
// BFS to find shortest path
|
|
1228
|
+
const visited = new Set();
|
|
1229
|
+
const parent = new Map();
|
|
1230
|
+
const queue = [sourceId];
|
|
1231
|
+
visited.add(sourceId);
|
|
1232
|
+
while (queue.length > 0) {
|
|
1233
|
+
const current = queue.shift();
|
|
1234
|
+
if (current === targetId) {
|
|
1235
|
+
// Reconstruct path
|
|
1236
|
+
const path = [];
|
|
1237
|
+
const edges = [];
|
|
1238
|
+
let node = targetId;
|
|
1239
|
+
while (node !== sourceId) {
|
|
1240
|
+
path.unshift(node);
|
|
1241
|
+
const parentInfo = parent.get(node);
|
|
1242
|
+
edges.unshift(parentInfo.edge);
|
|
1243
|
+
node = parentInfo.nodeId;
|
|
1244
|
+
}
|
|
1245
|
+
path.unshift(sourceId);
|
|
1246
|
+
return { path, edges };
|
|
1247
|
+
}
|
|
1248
|
+
// Explore downstream edges
|
|
1249
|
+
const downstreamEdgeIds = this.graph.sourceIndex.get(current) || new Set();
|
|
1250
|
+
for (const edgeId of downstreamEdgeIds) {
|
|
1251
|
+
const edge = this.graph.edges.get(edgeId);
|
|
1252
|
+
if (edge && !visited.has(edge.targetId)) {
|
|
1253
|
+
visited.add(edge.targetId);
|
|
1254
|
+
parent.set(edge.targetId, { nodeId: current, edge });
|
|
1255
|
+
queue.push(edge.targetId);
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return null; // No path found
|
|
1260
|
+
}
|
|
1261
|
+
/**
|
|
1262
|
+
* Get impact analysis: all tables that would be affected by changes to a source table
|
|
1263
|
+
*/
|
|
1264
|
+
getImpactAnalysis(schema, table) {
|
|
1265
|
+
const downstream = this.queryDownstreamLineage(schema, table);
|
|
1266
|
+
const directlyAffected = downstream.tables
|
|
1267
|
+
.filter((t) => t.depth === 1)
|
|
1268
|
+
.map((t) => ({ schema: t.schema, table: t.table }));
|
|
1269
|
+
const transitivelyAffected = downstream.tables
|
|
1270
|
+
.filter((t) => t.depth > 1)
|
|
1271
|
+
.map((t) => ({ schema: t.schema, table: t.table, hops: t.depth }));
|
|
1272
|
+
return {
|
|
1273
|
+
directlyAffected,
|
|
1274
|
+
transitivelyAffected,
|
|
1275
|
+
totalAffected: downstream.tables.length,
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* Get data provenance: full lineage history for understanding data origin
|
|
1280
|
+
*/
|
|
1281
|
+
getDataProvenance(schema, table) {
|
|
1282
|
+
const upstream = this.queryUpstreamLineage(schema, table);
|
|
1283
|
+
// Find root sources (tables with no upstream dependencies)
|
|
1284
|
+
const rootSources = [];
|
|
1285
|
+
for (const t of upstream.tables) {
|
|
1286
|
+
const nodeId = generateNodeId(t.schema, t.table);
|
|
1287
|
+
const hasUpstream = (this.graph.targetIndex.get(nodeId)?.size || 0) > 0;
|
|
1288
|
+
if (!hasUpstream) {
|
|
1289
|
+
rootSources.push({ schema: t.schema, table: t.table });
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
// Build transformation chain
|
|
1293
|
+
const transformationChain = upstream.edges
|
|
1294
|
+
.sort((a, b) => a.timestamp - b.timestamp)
|
|
1295
|
+
.map((e) => ({
|
|
1296
|
+
table: e.targetId,
|
|
1297
|
+
operation: e.operation,
|
|
1298
|
+
timestamp: e.timestamp,
|
|
1299
|
+
}));
|
|
1300
|
+
return {
|
|
1301
|
+
rootSources,
|
|
1302
|
+
transformationChain,
|
|
1303
|
+
depth: upstream.totalDepth,
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
/**
|
|
1307
|
+
* List all tracked tables
|
|
1308
|
+
*/
|
|
1309
|
+
listTrackedTables() {
|
|
1310
|
+
const tables = [];
|
|
1311
|
+
for (const [, node] of this.graph.nodes) {
|
|
1312
|
+
tables.push({
|
|
1313
|
+
schema: node.schema,
|
|
1314
|
+
table: node.name,
|
|
1315
|
+
type: node.type,
|
|
1316
|
+
});
|
|
1317
|
+
}
|
|
1318
|
+
return tables;
|
|
1319
|
+
}
|
|
1320
|
+
/**
|
|
1321
|
+
* Get node by ID
|
|
1322
|
+
*/
|
|
1323
|
+
getNode(schema, table) {
|
|
1324
|
+
const nodeId = generateNodeId(schema, table);
|
|
1325
|
+
return this.graph.nodes.get(nodeId) || null;
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Clear all lineage data
|
|
1329
|
+
*/
|
|
1330
|
+
clear() {
|
|
1331
|
+
this.graph = {
|
|
1332
|
+
nodes: new Map(),
|
|
1333
|
+
edges: new Map(),
|
|
1334
|
+
sourceIndex: new Map(),
|
|
1335
|
+
targetIndex: new Map(),
|
|
1336
|
+
};
|
|
1337
|
+
this.rowLineageMap.clear();
|
|
1338
|
+
}
|
|
1339
|
+
/**
|
|
1340
|
+
* Get the full lineage graph
|
|
1341
|
+
*/
|
|
1342
|
+
getGraph() {
|
|
1343
|
+
return this.graph;
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
/**
|
|
1347
|
+
* Create a lineage tracker with default configuration
|
|
1348
|
+
*/
|
|
1349
|
+
export function createLineageTracker(config) {
|
|
1350
|
+
return new LineageTracker(config);
|
|
1351
|
+
}
|
|
1352
|
+
//# sourceMappingURL=tracker.js.map
|