diff --git a/notes/trading/system-docs/d1d2-schema-contract/SCHEMA_AUTHORITY.md b/notes/trading/system-docs/d1d2-schema-contract/SCHEMA_AUTHORITY.md new file mode 100644 index 0000000..84595da --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/SCHEMA_AUTHORITY.md @@ -0,0 +1,105 @@ +# D1/D2 — Canonical Schema Contract & Fingerprint Tooling (SoT) + +**Status:** FORMALLY PERSISTED — authoritative origin/main +**Datum:** 2026-09-08 +**Verdict:** D1+D2 FORMALLY PERSISTED TO AUTHORITATIVE SOT + +--- + +## 1. Zweck + +Dieses Verzeichnis materialisiert den **CURRENT VERIFIED PRODUCTION SCHEMA CONTRACT (L0)** +als kanonische, deterministisch fingerprintbare Autorität. Es ist das Ergebnis der +D1/D2-Remediation (Schema-Contract + deterministischer Fingerprint) und wurde durch den +unabhängigen D1+D2-Checker mit **Verdict A** bestätigt. + +## 2. Canonical Fingerprint + +``` +b49f64337ffafc0e73d46e009aa802cd0172d59421b7df61d3eb198775c1986d +``` + +Dieser Fingerprint ist deterministisch (H1==H2==H3), sensitiv auf alle semantischen +Schema-Änderungen (type, nullable, default, PK, UNIQUE, FK, CHECK, index), und fail-closed. + +## 3. DR-Reproducibility (ehrlich getrennt) + +| Aspekt | Status | +|--------|--------| +| **CURRENT-STATE SCHEMA REPRODUCIBLE FROM L0** | **YES** — frische DB aus L0-SQL rekonstruiert, REBUILT_HASH == PRODUCTION_HASH == b49f6433…, Semantic-Diff TOTAL_MISMATCH=0 | +| **HISTORICAL EVOLUTION REPRODUCIBLE** | **NO** — historische DDL-Chronologie (Wave1→WaveD→Closure) bleibt nicht aus L0 rekonstruierbar | + +Der L0-Contract beansprucht ausschliesslich **CURRENT PRODUCTION TRUTH**, nicht historische +Migrationschronologie. Historische Artefakte bleiben immutable. + +## 4. Canonical Contract Semantics + +| Tabelle | Spalten | +|---------|---------| +| historical_bar | 41 | +| derived_bar | 35 | +| data_ingestion_run | 29 | +| dataset_version | 23 | +| ingestion_provenance | 41 | + +**Semantic Overrides (Owner-Canonical):** +- `last_successful_chunk` = **timestamp with time zone / timestamptz** (Production + Owner-Entscheidung) +- `interrupt_reason` = **text** · PRESERVED · origin unknown · do not remove +- `technical_quality` = **text** · nullable · default `'VALID'` + +## 5. Historische Wahrheit (nicht rückwirkend ändern) + +- **WaveD historisches Artefakt:** `last_successful_chunk = text` (immutable Evidence) +- **Owner/current canonical contract:** `last_successful_chunk = timestamptz` +- Historische Artefakte: Wave1 `6983526da3ca51fd2ececffbef0ccbd66b048a3d11c228000011aaba3e1d6bc5`, + WaveD `7aa4e2a10c98fa327e000a49f6a497efb5814c8808dba429dfebfc90c544a02b`, + Closure `e56567f7cfae68da70c11ece6f576e974488f343` — **unverändert**. + +## 6. Open Debts (nicht fälschlich geschlossen) + +| Debt | Status | +|------|--------| +| **Debt A** — Current-state DR/schema reproducibility gap | **CLOSED** by D1/D2 | +| **Debt A** — Historical DDL evolution provenance gap | **REMAINS OPEN** | +| **Debt B** — interrupt_reason origin unknown | **OPEN** (non-blocking) | +| **Debt C** — WaveD text vs current Owner-canonical timestamptz | **OPEN** (non-blocking) | + +## 7. SoT-Layout + +``` +d1d2-schema-contract/ +├── SCHEMA_AUTHORITY.md # dieses Dokument +├── contract/ +│ ├── historical_v2_schema.sql # L0-Schema-Contract (schema-only) +│ ├── historical_v2_schema.json # maschinenlesbares kanonisches Modell +│ ├── historical_v2_schema.sha256 # deterministischer Fingerprint +│ └── README.md # Contract-Dokumentation +└── tools/ + ├── canonical_schema.py # Kanonisierungs-Implementierung + ├── capture_schema.py # Capture-Parser (read-only) + ├── compare_schema.py # Semantic-Diff-CLI + ├── fingerprint_schema.py # Fingerprint-CLI + └── gen_l0_sql.py # L0-SQL-Generator +``` + +**Nicht persistiert:** Maker-Evidence, Checker-Evidence, temporäre DBs, /tmp-Dateien, +raw Scratch Outputs, runtime-spezifische Dateien, Credentials/Secrets, Transport-Manifeste, +`gen_evidence.py` (enthält hardcodierte Maker-Pfade, nicht environment-neutral). + +## 8. Tooling-Nutzung + +```bash +# Fingerprint aus machine contract +python3 tools/fingerprint_schema.py contract/historical_v2_schema.json +# → b49f64337ffafc0e73d46e009aa802cd0172d59421b7df61d3eb198775c1986d + +# Semantic-Diff (expected vs actual) +python3 tools/compare_schema.py contract/historical_v2_schema.json +# → TOTAL_MISMATCH=0 bei Übereinstimmung; Exit 1 bei Drift (fail-closed) + +# L0-SQL generieren +python3 tools/gen_l0_sql.py contract/historical_v2_schema.json --out /tmp/l0.sql +``` + +Alle Tools sind environment-neutral (keine absoluten Pfade, keine DB-Credentials, +keine mutierenden Production-SQL-Pfade). Read-only. diff --git a/notes/trading/system-docs/d1d2-schema-contract/contract/README.md b/notes/trading/system-docs/d1d2-schema-contract/contract/README.md new file mode 100644 index 0000000..6bd8d2d --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/contract/README.md @@ -0,0 +1,20 @@ +# Historical V2 — Canonical Current Schema Contract (L0) + +Diese Artefakte materialisieren den **CURRENT VERIFIED PRODUCTION SCHEMA CONTRACT** +als kanonische L0-Autorität (D1/D2 Remediation, forward-only). + +- `historical_v2_schema.sql` — schema-only PostgreSQL-Contract (kein DML/Secrets/volatile Artefakte) +- `historical_v2_schema.json` — maschinenlesbares kanonisches Modell +- `historical_v2_schema.sha256` — deterministischer SHA-256-Fingerprint +- Kanonischer Fingerprint: `b49f64337ffafc0e73d46e009aa802cd0172d59421b7df61d3eb198775c1986d` + +Dies ist KEINE historische Migrationskette. DO NOT INVENT HISTORY: der L0-Contract +beansprucht ausschliesslich CURRENT PRODUCTION TRUTH (§1). +Historische Artefakte (Wave1 `6983526da3ca51fd2ececffbef0ccbd66b048a3d11c228000011aaba3e1d6bc5`, WaveD `7aa4e2a10c98fa327e000a49f6a497efb5814c8808dba429dfebfc90c544a02b`) bleiben unverändert. + +**Semantic Overrides (§4):** +- last_successful_chunk = timestamp with time zone (Production+Owner; WaveD-historical text bleibt immutable Evidence) +- interrupt_reason = text (preserved, origin unknown, do not remove) +- technical_quality = text nullable default 'VALID' (historical provenance debt OPEN) + +**SoT:** origin/main = `e56567f7cfae68da70c11ece6f576e974488f343` diff --git a/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.json b/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.json new file mode 100644 index 0000000..ff2552c --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.json @@ -0,0 +1,4122 @@ +{ + "check_constraints": [ + { + "constraint": "2200_16679_1_not_null", + "definition": "event_id IS NOT NULL", + "table": "calendar_event" + }, + { + "constraint": "2200_16679_2_not_null", + "definition": "calendar_id IS NOT NULL", + "table": "calendar_event" + }, + { + "constraint": "2200_16679_3_not_null", + "definition": "event_date IS NOT NULL", + "table": "calendar_event" + }, + { + "constraint": "2200_16679_4_not_null", + "definition": "kind IS NOT NULL", + "table": "calendar_event" + }, + { + "constraint": "2200_16679_9_not_null", + "definition": "created_at IS NOT NULL", + "table": "calendar_event" + }, + { + "constraint": "2200_16567_1_not_null", + "definition": "action_id IS NOT NULL", + "table": "corporate_action" + }, + { + "constraint": "2200_16567_2_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "corporate_action" + }, + { + "constraint": "2200_16567_3_not_null", + "definition": "action_type IS NOT NULL", + "table": "corporate_action" + }, + { + "constraint": "2200_16567_4_not_null", + "definition": "ex_date IS NOT NULL", + "table": "corporate_action" + }, + { + "constraint": "2200_16696_19_not_null", + "definition": "status IS NOT NULL", + "table": "daily_quality_report" + }, + { + "constraint": "2200_16696_1_not_null", + "definition": "report_id IS NOT NULL", + "table": "daily_quality_report" + }, + { + "constraint": "2200_16696_23_not_null", + "definition": "generated_at IS NOT NULL", + "table": "daily_quality_report" + }, + { + "constraint": "2200_16696_2_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "daily_quality_report" + }, + { + "constraint": "2200_16696_3_not_null", + "definition": "provider_id IS NOT NULL", + "table": "daily_quality_report" + }, + { + "constraint": "2200_16696_4_not_null", + "definition": "report_date IS NOT NULL", + "table": "daily_quality_report" + }, + { + "constraint": "2200_16613_1_not_null", + "definition": "gap_id IS NOT NULL", + "table": "data_gap" + }, + { + "constraint": "2200_16613_2_not_null", + "definition": "provider_id IS NOT NULL", + "table": "data_gap" + }, + { + "constraint": "2200_16613_3_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "data_gap" + }, + { + "constraint": "2200_16613_4_not_null", + "definition": "timeframe IS NOT NULL", + "table": "data_gap" + }, + { + "constraint": "2200_16613_5_not_null", + "definition": "start_utc IS NOT NULL", + "table": "data_gap" + }, + { + "constraint": "2200_16613_6_not_null", + "definition": "end_utc IS NOT NULL", + "table": "data_gap" + }, + { + "constraint": "2200_16613_7_not_null", + "definition": "kind IS NOT NULL", + "table": "data_gap" + }, + { + "constraint": "2200_16613_8_not_null", + "definition": "backfilled IS NOT NULL", + "table": "data_gap" + }, + { + "constraint": "2200_16588_10_not_null", + "definition": "started_at IS NOT NULL", + "table": "data_ingestion_run" + }, + { + "constraint": "2200_16588_1_not_null", + "definition": "ingestion_id IS NOT NULL", + "table": "data_ingestion_run" + }, + { + "constraint": "2200_16588_2_not_null", + "definition": "provider_id IS NOT NULL", + "table": "data_ingestion_run" + }, + { + "constraint": "2200_16588_3_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "data_ingestion_run" + }, + { + "constraint": "2200_16588_4_not_null", + "definition": "timeframe IS NOT NULL", + "table": "data_ingestion_run" + }, + { + "constraint": "2200_16588_9_not_null", + "definition": "status IS NOT NULL", + "table": "data_ingestion_run" + }, + { + "constraint": "2200_16633_1_not_null", + "definition": "issue_id IS NOT NULL", + "table": "data_quality_issue" + }, + { + "constraint": "2200_16633_2_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "data_quality_issue" + }, + { + "constraint": "2200_16633_3_not_null", + "definition": "timeframe IS NOT NULL", + "table": "data_quality_issue" + }, + { + "constraint": "2200_16633_5_not_null", + "definition": "severity IS NOT NULL", + "table": "data_quality_issue" + }, + { + "constraint": "2200_16633_6_not_null", + "definition": "issue_type IS NOT NULL", + "table": "data_quality_issue" + }, + { + "constraint": "2200_16633_8_not_null", + "definition": "resolved IS NOT NULL", + "table": "data_quality_issue" + }, + { + "constraint": "2200_16633_9_not_null", + "definition": "created_at IS NOT NULL", + "table": "data_quality_issue" + }, + { + "constraint": "2200_16430_1_not_null", + "definition": "dataset_id IS NOT NULL", + "table": "dataset" + }, + { + "constraint": "2200_16430_2_not_null", + "definition": "name IS NOT NULL", + "table": "dataset" + }, + { + "constraint": "2200_16430_3_not_null", + "definition": "provider_id IS NOT NULL", + "table": "dataset" + }, + { + "constraint": "2200_16430_4_not_null", + "definition": "feed_type IS NOT NULL", + "table": "dataset" + }, + { + "constraint": "2200_16430_6_not_null", + "definition": "created_at IS NOT NULL", + "table": "dataset" + }, + { + "constraint": "2200_16447_10_not_null", + "definition": "raw_source IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_11_not_null", + "definition": "normalization_version IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_13_not_null", + "definition": "quality_version IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_14_not_null", + "definition": "dataset_version_hash IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_15_not_null", + "definition": "data_as_of IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_17_not_null", + "definition": "created_at IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_1_not_null", + "definition": "dataset_version_id IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_23_not_null", + "definition": "is_fixture IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_2_not_null", + "definition": "dataset_id IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_3_not_null", + "definition": "version_label IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_4_not_null", + "definition": "provider_id IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_5_not_null", + "definition": "feed_type IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_6_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_7_not_null", + "definition": "timeframe IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_8_not_null", + "definition": "start_utc IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16447_9_not_null", + "definition": "end_utc IS NOT NULL", + "table": "dataset_version" + }, + { + "constraint": "2200_16508_1_not_null", + "definition": "derived_bar_id IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_24_not_null", + "definition": "quality_status IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_26_not_null", + "definition": "dataset_version_id IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_2_not_null", + "definition": "provider_id IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_3_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_4_not_null", + "definition": "feed_type IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_5_not_null", + "definition": "price_basis IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_6_not_null", + "definition": "timeframe IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_7_not_null", + "definition": "ts_utc IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_8_not_null", + "definition": "source_timeframe IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16508_9_not_null", + "definition": "aggregation_version IS NOT NULL", + "table": "derived_bar" + }, + { + "constraint": "2200_16474_1_not_null", + "definition": "bar_id IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_25_not_null", + "definition": "quality_status IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_28_not_null", + "definition": "ingested_at IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_29_not_null", + "definition": "dataset_version_id IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_2_not_null", + "definition": "provider_id IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_3_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_4_not_null", + "definition": "feed_type IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_5_not_null", + "definition": "price_basis IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_6_not_null", + "definition": "timeframe IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_7_not_null", + "definition": "ts_utc IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16474_8_not_null", + "definition": "raw_or_derived IS NOT NULL", + "table": "historical_bar" + }, + { + "constraint": "2200_16539_10_not_null", + "definition": "dataset_version_id IS NOT NULL", + "table": "historical_tick" + }, + { + "constraint": "2200_16539_1_not_null", + "definition": "tick_id IS NOT NULL", + "table": "historical_tick" + }, + { + "constraint": "2200_16539_2_not_null", + "definition": "provider_id IS NOT NULL", + "table": "historical_tick" + }, + { + "constraint": "2200_16539_3_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "historical_tick" + }, + { + "constraint": "2200_16539_4_not_null", + "definition": "feed_type IS NOT NULL", + "table": "historical_tick" + }, + { + "constraint": "2200_16539_5_not_null", + "definition": "ts_utc IS NOT NULL", + "table": "historical_tick" + }, + { + "constraint": "2200_16741_10_not_null", + "definition": "asset_class IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_11_not_null", + "definition": "request_start IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_12_not_null", + "definition": "request_end IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_13_not_null", + "definition": "actual_start IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_14_not_null", + "definition": "actual_end IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_15_not_null", + "definition": "request_timestamp IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_16_not_null", + "definition": "response_timestamp IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_17_not_null", + "definition": "http_status IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_1_not_null", + "definition": "provenance_id IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_20_not_null", + "definition": "raw_payload_sha256 IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_21_not_null", + "definition": "raw_content_length IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_22_not_null", + "definition": "compression IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_24_not_null", + "definition": "parser_version IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_25_not_null", + "definition": "adapter_version IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_26_not_null", + "definition": "normalization_version IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_27_not_null", + "definition": "timezone_source IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_28_not_null", + "definition": "timezone_target IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_29_not_null", + "definition": "timezone_transform_version IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_2_not_null", + "definition": "ingestion_run_id IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_30_not_null", + "definition": "price_type IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_31_not_null", + "definition": "granularity IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_32_not_null", + "definition": "correction_status IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_33_not_null", + "definition": "license_class IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_34_not_null", + "definition": "software_git_commit IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_35_not_null", + "definition": "software_image_id IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_37_not_null", + "definition": "request_identity_hash IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_3_not_null", + "definition": "provider_id IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_41_not_null", + "definition": "created_at IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_4_not_null", + "definition": "provider_name_snapshot IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_5_not_null", + "definition": "provider_environment_class IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_6_not_null", + "definition": "provider_dataset IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_7_not_null", + "definition": "provider_feed IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_8_not_null", + "definition": "provider_instrument_id IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16741_9_not_null", + "definition": "canonical_instrument_id IS NOT NULL", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_actual_range", + "definition": "((actual_end >= actual_start))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_compression", + "definition": "((compression = ANY (ARRAY['none'::text, 'lzma'::text, 'gzip'::text, 'zstd'::text, 'deflate'::text, 'unknown'::text])))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_content_length", + "definition": "((raw_content_length >= 0))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_correction", + "definition": "((correction_status = ANY (ARRAY['ORIGINAL'::text, 'CORRECTED'::text, 'SUPERSEDED'::text, 'UNKNOWN'::text])))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_env_class", + "definition": "((provider_environment_class = ANY (ARRAY['PROD'::text, 'SANDBOX'::text, 'TEST'::text, 'UNKNOWN'::text])))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_http_status", + "definition": "(((http_status >= 100) AND (http_status <= 599)))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_license", + "definition": "((license_class = ANY (ARRAY['UNKNOWN'::text, 'PRIVATE_INTERNAL'::text, 'INTERNAL_DERIVED_ALLOWED'::text, 'STORAGE_RESTRICTED'::text, 'REDISTRIBUTION_RESTRICTED'::text, 'EXPIRED'::text, 'REVOKED'::text])))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_price_type", + "definition": "((price_type = ANY (ARRAY['bid'::text, 'ask'::text, 'mid'::text, 'bid_ask'::text, 'last'::text, 'unknown'::text])))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_sha256", + "definition": "((raw_payload_sha256 ~ '^[0-9a-f]{64}$'::text))", + "table": "ingestion_provenance" + }, + { + "constraint": "chk_prov_time_range", + "definition": "((request_end >= request_start))", + "table": "ingestion_provenance" + }, + { + "constraint": "2200_16386_12_not_null", + "definition": "active IS NOT NULL", + "table": "instrument" + }, + { + "constraint": "2200_16386_13_not_null", + "definition": "created_at IS NOT NULL", + "table": "instrument" + }, + { + "constraint": "2200_16386_1_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "instrument" + }, + { + "constraint": "2200_16386_2_not_null", + "definition": "symbol IS NOT NULL", + "table": "instrument" + }, + { + "constraint": "2200_16386_3_not_null", + "definition": "asset_class IS NOT NULL", + "table": "instrument" + }, + { + "constraint": "2200_16667_12_not_null", + "definition": "calendar_version IS NOT NULL", + "table": "market_calendar" + }, + { + "constraint": "2200_16667_13_not_null", + "definition": "created_at IS NOT NULL", + "table": "market_calendar" + }, + { + "constraint": "2200_16667_1_not_null", + "definition": "calendar_id IS NOT NULL", + "table": "market_calendar" + }, + { + "constraint": "2200_16667_2_not_null", + "definition": "calendar_name IS NOT NULL", + "table": "market_calendar" + }, + { + "constraint": "2200_16667_3_not_null", + "definition": "asset_class IS NOT NULL", + "table": "market_calendar" + }, + { + "constraint": "2200_16667_5_not_null", + "definition": "timezone IS NOT NULL", + "table": "market_calendar" + }, + { + "constraint": "2200_16399_1_not_null", + "definition": "provider_id IS NOT NULL", + "table": "provider" + }, + { + "constraint": "2200_16399_2_not_null", + "definition": "provider_key IS NOT NULL", + "table": "provider" + }, + { + "constraint": "2200_16399_3_not_null", + "definition": "name IS NOT NULL", + "table": "provider" + }, + { + "constraint": "2200_16399_4_not_null", + "definition": "data_type IS NOT NULL", + "table": "provider" + }, + { + "constraint": "2200_16409_1_not_null", + "definition": "provider_id IS NOT NULL", + "table": "provider_instrument" + }, + { + "constraint": "2200_16409_2_not_null", + "definition": "instrument_id IS NOT NULL", + "table": "provider_instrument" + }, + { + "constraint": "2200_16409_3_not_null", + "definition": "provider_symbol IS NOT NULL", + "table": "provider_instrument" + }, + { + "constraint": "2200_16409_6_not_null", + "definition": "active IS NOT NULL", + "table": "provider_instrument" + } + ], + "columns": [ + { + "column": "event_id", + "default": "nextval('calendar_event_event_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "calendar_event", + "type": "bigint", + "udt": "int8" + }, + { + "column": "calendar_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "calendar_event", + "type": "bigint", + "udt": "int8" + }, + { + "column": "event_date", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "calendar_event", + "type": "date", + "udt": "date" + }, + { + "column": "kind", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "calendar_event", + "type": "text", + "udt": "text" + }, + { + "column": "reason", + "default": null, + "nullable": true, + "ordinal": 5, + "table": "calendar_event", + "type": "text", + "udt": "text" + }, + { + "column": "session_phase_override", + "default": null, + "nullable": true, + "ordinal": 6, + "table": "calendar_event", + "type": "text", + "udt": "text" + }, + { + "column": "source", + "default": null, + "nullable": true, + "ordinal": 7, + "table": "calendar_event", + "type": "text", + "udt": "text" + }, + { + "column": "notes", + "default": null, + "nullable": true, + "ordinal": 8, + "table": "calendar_event", + "type": "text", + "udt": "text" + }, + { + "column": "created_at", + "default": "now()", + "nullable": false, + "ordinal": 9, + "table": "calendar_event", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "action_id", + "default": "nextval('corporate_action_action_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "corporate_action", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "corporate_action", + "type": "bigint", + "udt": "int8" + }, + { + "column": "action_type", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "corporate_action", + "type": "text", + "udt": "text" + }, + { + "column": "ex_date", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "corporate_action", + "type": "date", + "udt": "date" + }, + { + "column": "ratio_num", + "default": null, + "nullable": true, + "ordinal": 5, + "table": "corporate_action", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ratio_denom", + "default": null, + "nullable": true, + "ordinal": 6, + "table": "corporate_action", + "type": "double precision", + "udt": "float8" + }, + { + "column": "dividend", + "default": null, + "nullable": true, + "ordinal": 7, + "table": "corporate_action", + "type": "double precision", + "udt": "float8" + }, + { + "column": "currency", + "default": null, + "nullable": true, + "ordinal": 8, + "table": "corporate_action", + "type": "text", + "udt": "text" + }, + { + "column": "provider_id", + "default": null, + "nullable": true, + "ordinal": 9, + "table": "corporate_action", + "type": "bigint", + "udt": "int8" + }, + { + "column": "report_id", + "default": "nextval('daily_quality_report_report_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "report_date", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "daily_quality_report", + "type": "date", + "udt": "date" + }, + { + "column": "feed_type", + "default": "'REFERENCE'::text", + "nullable": true, + "ordinal": 5, + "table": "daily_quality_report", + "type": "text", + "udt": "text" + }, + { + "column": "expected_m1", + "default": null, + "nullable": true, + "ordinal": 6, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "received_m1", + "default": null, + "nullable": true, + "ordinal": 7, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "eligible", + "default": null, + "nullable": true, + "ordinal": 8, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "excluded", + "default": null, + "nullable": true, + "ordinal": 9, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "conditional", + "default": null, + "nullable": true, + "ordinal": 10, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "stale_count", + "default": null, + "nullable": true, + "ordinal": 11, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "zero_volume", + "default": null, + "nullable": true, + "ordinal": 12, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "spread_median_price", + "default": null, + "nullable": true, + "ordinal": 13, + "table": "daily_quality_report", + "type": "double precision", + "udt": "float8" + }, + { + "column": "spread_p95_price", + "default": null, + "nullable": true, + "ordinal": 14, + "table": "daily_quality_report", + "type": "double precision", + "udt": "float8" + }, + { + "column": "spread_p99_price", + "default": null, + "nullable": true, + "ordinal": 15, + "table": "daily_quality_report", + "type": "double precision", + "udt": "float8" + }, + { + "column": "gaps_count", + "default": null, + "nullable": true, + "ordinal": 16, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "coverage_ratio", + "default": null, + "nullable": true, + "ordinal": 17, + "table": "daily_quality_report", + "type": "double precision", + "udt": "float8" + }, + { + "column": "session_anomalies", + "default": null, + "nullable": true, + "ordinal": 18, + "table": "daily_quality_report", + "type": "bigint", + "udt": "int8" + }, + { + "column": "status", + "default": null, + "nullable": false, + "ordinal": 19, + "table": "daily_quality_report", + "type": "text", + "udt": "text" + }, + { + "column": "quality_model_version", + "default": null, + "nullable": true, + "ordinal": 20, + "table": "daily_quality_report", + "type": "text", + "udt": "text" + }, + { + "column": "session_model_version", + "default": null, + "nullable": true, + "ordinal": 21, + "table": "daily_quality_report", + "type": "text", + "udt": "text" + }, + { + "column": "calendar_version", + "default": null, + "nullable": true, + "ordinal": 22, + "table": "daily_quality_report", + "type": "text", + "udt": "text" + }, + { + "column": "generated_at", + "default": "now()", + "nullable": false, + "ordinal": 23, + "table": "daily_quality_report", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "gap_id", + "default": "nextval('data_gap_gap_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "data_gap", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "data_gap", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "data_gap", + "type": "bigint", + "udt": "int8" + }, + { + "column": "timeframe", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "data_gap", + "type": "text", + "udt": "text" + }, + { + "column": "start_utc", + "default": null, + "nullable": false, + "ordinal": 5, + "table": "data_gap", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "end_utc", + "default": null, + "nullable": false, + "ordinal": 6, + "table": "data_gap", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "kind", + "default": null, + "nullable": false, + "ordinal": 7, + "table": "data_gap", + "type": "text", + "udt": "text" + }, + { + "column": "backfilled", + "default": "false", + "nullable": false, + "ordinal": 8, + "table": "data_gap", + "type": "boolean", + "udt": "bool" + }, + { + "column": "filled_at", + "default": null, + "nullable": true, + "ordinal": 9, + "table": "data_gap", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "ingestion_id", + "default": "nextval('data_ingestion_run_ingestion_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "timeframe", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "data_ingestion_run", + "type": "text", + "udt": "text" + }, + { + "column": "start_utc", + "default": null, + "nullable": true, + "ordinal": 5, + "table": "data_ingestion_run", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "end_utc", + "default": null, + "nullable": true, + "ordinal": 6, + "table": "data_ingestion_run", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "rows_inserted", + "default": "0", + "nullable": true, + "ordinal": 7, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_skipped", + "default": "0", + "nullable": true, + "ordinal": 8, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "status", + "default": "'RUNNING'::text", + "nullable": false, + "ordinal": 9, + "table": "data_ingestion_run", + "type": "text", + "udt": "text" + }, + { + "column": "started_at", + "default": "now()", + "nullable": false, + "ordinal": 10, + "table": "data_ingestion_run", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "finished_at", + "default": null, + "nullable": true, + "ordinal": 11, + "table": "data_ingestion_run", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "checkpoint", + "default": null, + "nullable": true, + "ordinal": 12, + "table": "data_ingestion_run", + "type": "jsonb", + "udt": "jsonb" + }, + { + "column": "status_fsm", + "default": "'PENDING'::text", + "nullable": true, + "ordinal": 13, + "table": "data_ingestion_run", + "type": "text", + "udt": "text" + }, + { + "column": "rows_downloaded", + "default": "0", + "nullable": true, + "ordinal": 14, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_decoded", + "default": "0", + "nullable": true, + "ordinal": 15, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_valid", + "default": "0", + "nullable": true, + "ordinal": 16, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_suspect", + "default": "0", + "nullable": true, + "ordinal": 17, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_excluded", + "default": "0", + "nullable": true, + "ordinal": 18, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_derived", + "default": "0", + "nullable": true, + "ordinal": 19, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "last_successful_chunk", + "default": null, + "nullable": true, + "ordinal": 20, + "table": "data_ingestion_run", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "last_timestamp", + "default": null, + "nullable": true, + "ordinal": 21, + "table": "data_ingestion_run", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "updated_at", + "default": "now()", + "nullable": true, + "ordinal": 22, + "table": "data_ingestion_run", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "interrupt_reason", + "default": null, + "nullable": true, + "ordinal": 23, + "table": "data_ingestion_run", + "type": "text", + "udt": "text" + }, + { + "column": "rows_existing", + "default": "0", + "nullable": true, + "ordinal": 24, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_deduplicated", + "default": "0", + "nullable": true, + "ordinal": 25, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_404", + "default": "0", + "nullable": true, + "ordinal": 26, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_503", + "default": "0", + "nullable": true, + "ordinal": 27, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_provider_unavailable", + "default": "0", + "nullable": true, + "ordinal": 28, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "rows_failed", + "default": "0", + "nullable": true, + "ordinal": 29, + "table": "data_ingestion_run", + "type": "bigint", + "udt": "int8" + }, + { + "column": "issue_id", + "default": "nextval('data_quality_issue_issue_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "data_quality_issue", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "data_quality_issue", + "type": "bigint", + "udt": "int8" + }, + { + "column": "timeframe", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "data_quality_issue", + "type": "text", + "udt": "text" + }, + { + "column": "ts_utc", + "default": null, + "nullable": true, + "ordinal": 4, + "table": "data_quality_issue", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "severity", + "default": null, + "nullable": false, + "ordinal": 5, + "table": "data_quality_issue", + "type": "text", + "udt": "text" + }, + { + "column": "issue_type", + "default": null, + "nullable": false, + "ordinal": 6, + "table": "data_quality_issue", + "type": "text", + "udt": "text" + }, + { + "column": "detail", + "default": null, + "nullable": true, + "ordinal": 7, + "table": "data_quality_issue", + "type": "jsonb", + "udt": "jsonb" + }, + { + "column": "resolved", + "default": "false", + "nullable": false, + "ordinal": 8, + "table": "data_quality_issue", + "type": "boolean", + "udt": "bool" + }, + { + "column": "created_at", + "default": "now()", + "nullable": false, + "ordinal": 9, + "table": "data_quality_issue", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "dataset_id", + "default": "nextval('dataset_dataset_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "dataset", + "type": "bigint", + "udt": "int8" + }, + { + "column": "name", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "dataset", + "type": "text", + "udt": "text" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "dataset", + "type": "bigint", + "udt": "int8" + }, + { + "column": "feed_type", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "dataset", + "type": "text", + "udt": "text" + }, + { + "column": "description", + "default": null, + "nullable": true, + "ordinal": 5, + "table": "dataset", + "type": "text", + "udt": "text" + }, + { + "column": "created_at", + "default": "now()", + "nullable": false, + "ordinal": 6, + "table": "dataset", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "dataset_version_id", + "default": "nextval('dataset_version_dataset_version_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "dataset_version", + "type": "bigint", + "udt": "int8" + }, + { + "column": "dataset_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "dataset_version", + "type": "bigint", + "udt": "int8" + }, + { + "column": "version_label", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "dataset_version", + "type": "bigint", + "udt": "int8" + }, + { + "column": "feed_type", + "default": null, + "nullable": false, + "ordinal": 5, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 6, + "table": "dataset_version", + "type": "bigint", + "udt": "int8" + }, + { + "column": "timeframe", + "default": null, + "nullable": false, + "ordinal": 7, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "start_utc", + "default": null, + "nullable": false, + "ordinal": 8, + "table": "dataset_version", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "end_utc", + "default": null, + "nullable": false, + "ordinal": 9, + "table": "dataset_version", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "raw_source", + "default": null, + "nullable": false, + "ordinal": 10, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "normalization_version", + "default": null, + "nullable": false, + "ordinal": 11, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "aggregation_version", + "default": null, + "nullable": true, + "ordinal": 12, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "quality_version", + "default": null, + "nullable": false, + "ordinal": 13, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "dataset_version_hash", + "default": null, + "nullable": false, + "ordinal": 14, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "data_as_of", + "default": null, + "nullable": false, + "ordinal": 15, + "table": "dataset_version", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "notes", + "default": null, + "nullable": true, + "ordinal": 16, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "created_at", + "default": "now()", + "nullable": false, + "ordinal": 17, + "table": "dataset_version", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "quality_model_version", + "default": null, + "nullable": true, + "ordinal": 18, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "stale_model_version", + "default": null, + "nullable": true, + "ordinal": 19, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "session_model_version", + "default": null, + "nullable": true, + "ordinal": 20, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "calendar_version", + "default": null, + "nullable": true, + "ordinal": 21, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "eligibility_model_version", + "default": null, + "nullable": true, + "ordinal": 22, + "table": "dataset_version", + "type": "text", + "udt": "text" + }, + { + "column": "is_fixture", + "default": "false", + "nullable": false, + "ordinal": 23, + "table": "dataset_version", + "type": "boolean", + "udt": "bool" + }, + { + "column": "derived_bar_id", + "default": "nextval('derived_bar_derived_bar_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "derived_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "derived_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "derived_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "feed_type", + "default": "'REFERENCE'::text", + "nullable": false, + "ordinal": 4, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "price_basis", + "default": "'bid_ask'::text", + "nullable": false, + "ordinal": 5, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "timeframe", + "default": null, + "nullable": false, + "ordinal": 6, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "ts_utc", + "default": null, + "nullable": false, + "ordinal": 7, + "table": "derived_bar", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "source_timeframe", + "default": null, + "nullable": false, + "ordinal": 8, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "aggregation_version", + "default": null, + "nullable": false, + "ordinal": 9, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "bid_open", + "default": null, + "nullable": true, + "ordinal": 10, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "bid_high", + "default": null, + "nullable": true, + "ordinal": 11, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "bid_low", + "default": null, + "nullable": true, + "ordinal": 12, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "bid_close", + "default": null, + "nullable": true, + "ordinal": 13, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask_open", + "default": null, + "nullable": true, + "ordinal": 14, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask_high", + "default": null, + "nullable": true, + "ordinal": 15, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask_low", + "default": null, + "nullable": true, + "ordinal": 16, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask_close", + "default": null, + "nullable": true, + "ordinal": 17, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "mid_open", + "default": null, + "nullable": true, + "ordinal": 18, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "mid_high", + "default": null, + "nullable": true, + "ordinal": 19, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "mid_low", + "default": null, + "nullable": true, + "ordinal": 20, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "mid_close", + "default": null, + "nullable": true, + "ordinal": 21, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "volume", + "default": null, + "nullable": true, + "ordinal": 22, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "volume_type", + "default": "'tick'::text", + "nullable": true, + "ordinal": 23, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "quality_status", + "default": "'VALID'::text", + "nullable": false, + "ordinal": 24, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "quality_flags", + "default": null, + "nullable": true, + "ordinal": 25, + "table": "derived_bar", + "type": "ARRAY", + "udt": "_text" + }, + { + "column": "dataset_version_id", + "default": null, + "nullable": false, + "ordinal": 26, + "table": "derived_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "expected_bar_count", + "default": null, + "nullable": true, + "ordinal": 27, + "table": "derived_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "actual_bar_count", + "default": null, + "nullable": true, + "ordinal": 28, + "table": "derived_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "eligible_bar_count", + "default": null, + "nullable": true, + "ordinal": 29, + "table": "derived_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "excluded_bar_count", + "default": null, + "nullable": true, + "ordinal": 30, + "table": "derived_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "coverage_ratio", + "default": null, + "nullable": true, + "ordinal": 31, + "table": "derived_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "aggregation_quality", + "default": null, + "nullable": true, + "ordinal": 32, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "eligibility_model_version", + "default": "'eligibility_v1'::text", + "nullable": true, + "ordinal": 33, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "session_model_version", + "default": "'fx_session_v1'::text", + "nullable": true, + "ordinal": 34, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "calendar_version", + "default": "'fx_cal_v1'::text", + "nullable": true, + "ordinal": 35, + "table": "derived_bar", + "type": "text", + "udt": "text" + }, + { + "column": "bar_id", + "default": "nextval('historical_bar_bar_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "historical_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "historical_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "historical_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "feed_type", + "default": "'REFERENCE'::text", + "nullable": false, + "ordinal": 4, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "price_basis", + "default": "'bid_ask'::text", + "nullable": false, + "ordinal": 5, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "timeframe", + "default": null, + "nullable": false, + "ordinal": 6, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "ts_utc", + "default": null, + "nullable": false, + "ordinal": 7, + "table": "historical_bar", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "raw_or_derived", + "default": "'raw'::text", + "nullable": false, + "ordinal": 8, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "source_timeframe", + "default": null, + "nullable": true, + "ordinal": 9, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "aggregation_version", + "default": null, + "nullable": true, + "ordinal": 10, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "bid_open", + "default": null, + "nullable": true, + "ordinal": 11, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "bid_high", + "default": null, + "nullable": true, + "ordinal": 12, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "bid_low", + "default": null, + "nullable": true, + "ordinal": 13, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "bid_close", + "default": null, + "nullable": true, + "ordinal": 14, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask_open", + "default": null, + "nullable": true, + "ordinal": 15, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask_high", + "default": null, + "nullable": true, + "ordinal": 16, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask_low", + "default": null, + "nullable": true, + "ordinal": 17, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask_close", + "default": null, + "nullable": true, + "ordinal": 18, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "mid_open", + "default": null, + "nullable": true, + "ordinal": 19, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "mid_high", + "default": null, + "nullable": true, + "ordinal": 20, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "mid_low", + "default": null, + "nullable": true, + "ordinal": 21, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "mid_close", + "default": null, + "nullable": true, + "ordinal": 22, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "volume", + "default": null, + "nullable": true, + "ordinal": 23, + "table": "historical_bar", + "type": "double precision", + "udt": "float8" + }, + { + "column": "volume_type", + "default": "'tick'::text", + "nullable": true, + "ordinal": 24, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "quality_status", + "default": "'VALID'::text", + "nullable": false, + "ordinal": 25, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "quality_flags", + "default": null, + "nullable": true, + "ordinal": 26, + "table": "historical_bar", + "type": "ARRAY", + "udt": "_text" + }, + { + "column": "source_timestamp", + "default": null, + "nullable": true, + "ordinal": 27, + "table": "historical_bar", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "ingested_at", + "default": "now()", + "nullable": false, + "ordinal": 28, + "table": "historical_bar", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "dataset_version_id", + "default": null, + "nullable": false, + "ordinal": 29, + "table": "historical_bar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "technical_quality", + "default": "'VALID'::text", + "nullable": true, + "ordinal": 30, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "market_quality", + "default": null, + "nullable": true, + "ordinal": 31, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "session_state", + "default": null, + "nullable": true, + "ordinal": 32, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "session_phase", + "default": null, + "nullable": true, + "ordinal": 33, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "eligibility", + "default": "'ELIGIBLE'::text", + "nullable": true, + "ordinal": 34, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "exclusion_reason", + "default": null, + "nullable": true, + "ordinal": 35, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "quality_model_version", + "default": "'quality_v1'::text", + "nullable": true, + "ordinal": 36, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "session_model_version", + "default": null, + "nullable": true, + "ordinal": 37, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "calendar_version", + "default": null, + "nullable": true, + "ordinal": 38, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "eligibility_model_version", + "default": "'eligibility_v1'::text", + "nullable": true, + "ordinal": 39, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "effective_eligibility", + "default": null, + "nullable": true, + "ordinal": 40, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "stale_model_version", + "default": null, + "nullable": true, + "ordinal": 41, + "table": "historical_bar", + "type": "text", + "udt": "text" + }, + { + "column": "tick_id", + "default": "nextval('historical_tick_tick_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "historical_tick", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "historical_tick", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "historical_tick", + "type": "bigint", + "udt": "int8" + }, + { + "column": "feed_type", + "default": "'REFERENCE'::text", + "nullable": false, + "ordinal": 4, + "table": "historical_tick", + "type": "text", + "udt": "text" + }, + { + "column": "ts_utc", + "default": null, + "nullable": false, + "ordinal": 5, + "table": "historical_tick", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "bid", + "default": null, + "nullable": true, + "ordinal": 6, + "table": "historical_tick", + "type": "double precision", + "udt": "float8" + }, + { + "column": "ask", + "default": null, + "nullable": true, + "ordinal": 7, + "table": "historical_tick", + "type": "double precision", + "udt": "float8" + }, + { + "column": "last", + "default": null, + "nullable": true, + "ordinal": 8, + "table": "historical_tick", + "type": "double precision", + "udt": "float8" + }, + { + "column": "volume", + "default": null, + "nullable": true, + "ordinal": 9, + "table": "historical_tick", + "type": "double precision", + "udt": "float8" + }, + { + "column": "dataset_version_id", + "default": null, + "nullable": false, + "ordinal": 10, + "table": "historical_tick", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provenance_id", + "default": null, + "nullable": false, + "ordinal": 1, + "table": "ingestion_provenance", + "type": "bigint", + "udt": "int8" + }, + { + "column": "ingestion_run_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "ingestion_provenance", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "ingestion_provenance", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_name_snapshot", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "provider_environment_class", + "default": null, + "nullable": false, + "ordinal": 5, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "provider_dataset", + "default": null, + "nullable": false, + "ordinal": 6, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "provider_feed", + "default": null, + "nullable": false, + "ordinal": 7, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "provider_instrument_id", + "default": null, + "nullable": false, + "ordinal": 8, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "canonical_instrument_id", + "default": null, + "nullable": false, + "ordinal": 9, + "table": "ingestion_provenance", + "type": "bigint", + "udt": "int8" + }, + { + "column": "asset_class", + "default": null, + "nullable": false, + "ordinal": 10, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "request_start", + "default": null, + "nullable": false, + "ordinal": 11, + "table": "ingestion_provenance", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "request_end", + "default": null, + "nullable": false, + "ordinal": 12, + "table": "ingestion_provenance", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "actual_start", + "default": null, + "nullable": false, + "ordinal": 13, + "table": "ingestion_provenance", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "actual_end", + "default": null, + "nullable": false, + "ordinal": 14, + "table": "ingestion_provenance", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "request_timestamp", + "default": null, + "nullable": false, + "ordinal": 15, + "table": "ingestion_provenance", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "response_timestamp", + "default": null, + "nullable": false, + "ordinal": 16, + "table": "ingestion_provenance", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "http_status", + "default": null, + "nullable": false, + "ordinal": 17, + "table": "ingestion_provenance", + "type": "integer", + "udt": "int4" + }, + { + "column": "provider_metadata", + "default": null, + "nullable": true, + "ordinal": 18, + "table": "ingestion_provenance", + "type": "jsonb", + "udt": "jsonb" + }, + { + "column": "provider_version", + "default": null, + "nullable": true, + "ordinal": 19, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "raw_payload_sha256", + "default": null, + "nullable": false, + "ordinal": 20, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "raw_content_length", + "default": null, + "nullable": false, + "ordinal": 21, + "table": "ingestion_provenance", + "type": "bigint", + "udt": "int8" + }, + { + "column": "compression", + "default": null, + "nullable": false, + "ordinal": 22, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "content_type", + "default": null, + "nullable": true, + "ordinal": 23, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "parser_version", + "default": null, + "nullable": false, + "ordinal": 24, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "adapter_version", + "default": null, + "nullable": false, + "ordinal": 25, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "normalization_version", + "default": null, + "nullable": false, + "ordinal": 26, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "timezone_source", + "default": null, + "nullable": false, + "ordinal": 27, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "timezone_target", + "default": null, + "nullable": false, + "ordinal": 28, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "timezone_transform_version", + "default": null, + "nullable": false, + "ordinal": 29, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "price_type", + "default": null, + "nullable": false, + "ordinal": 30, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "granularity", + "default": null, + "nullable": false, + "ordinal": 31, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "correction_status", + "default": "'ORIGINAL'::text", + "nullable": false, + "ordinal": 32, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "license_class", + "default": "'UNKNOWN'::text", + "nullable": false, + "ordinal": 33, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "software_git_commit", + "default": null, + "nullable": false, + "ordinal": 34, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "software_image_id", + "default": null, + "nullable": false, + "ordinal": 35, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "software_build_input_sha", + "default": null, + "nullable": true, + "ordinal": 36, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "request_identity_hash", + "default": null, + "nullable": false, + "ordinal": 37, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "supersedes_provenance_id", + "default": null, + "nullable": true, + "ordinal": 38, + "table": "ingestion_provenance", + "type": "bigint", + "udt": "int8" + }, + { + "column": "raw_storage_ref", + "default": null, + "nullable": true, + "ordinal": 39, + "table": "ingestion_provenance", + "type": "text", + "udt": "text" + }, + { + "column": "extra", + "default": null, + "nullable": true, + "ordinal": 40, + "table": "ingestion_provenance", + "type": "jsonb", + "udt": "jsonb" + }, + { + "column": "created_at", + "default": "now()", + "nullable": false, + "ordinal": 41, + "table": "ingestion_provenance", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "instrument_id", + "default": "nextval('instrument_instrument_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "instrument", + "type": "bigint", + "udt": "int8" + }, + { + "column": "symbol", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "instrument", + "type": "text", + "udt": "text" + }, + { + "column": "asset_class", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "instrument", + "type": "text", + "udt": "text" + }, + { + "column": "name", + "default": null, + "nullable": true, + "ordinal": 4, + "table": "instrument", + "type": "text", + "udt": "text" + }, + { + "column": "currency", + "default": null, + "nullable": true, + "ordinal": 5, + "table": "instrument", + "type": "text", + "udt": "text" + }, + { + "column": "exchange", + "default": null, + "nullable": true, + "ordinal": 6, + "table": "instrument", + "type": "text", + "udt": "text" + }, + { + "column": "mic", + "default": null, + "nullable": true, + "ordinal": 7, + "table": "instrument", + "type": "text", + "udt": "text" + }, + { + "column": "isin", + "default": null, + "nullable": true, + "ordinal": 8, + "table": "instrument", + "type": "text", + "udt": "text" + }, + { + "column": "tick_size", + "default": null, + "nullable": true, + "ordinal": 9, + "table": "instrument", + "type": "double precision", + "udt": "float8" + }, + { + "column": "contract_size", + "default": null, + "nullable": true, + "ordinal": 10, + "table": "instrument", + "type": "double precision", + "udt": "float8" + }, + { + "column": "min_deal_size", + "default": null, + "nullable": true, + "ordinal": 11, + "table": "instrument", + "type": "double precision", + "udt": "float8" + }, + { + "column": "active", + "default": "true", + "nullable": false, + "ordinal": 12, + "table": "instrument", + "type": "boolean", + "udt": "bool" + }, + { + "column": "created_at", + "default": "now()", + "nullable": false, + "ordinal": 13, + "table": "instrument", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "calendar_id", + "default": "nextval('market_calendar_calendar_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "market_calendar", + "type": "bigint", + "udt": "int8" + }, + { + "column": "calendar_name", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "asset_class", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "venue_exchange", + "default": null, + "nullable": true, + "ordinal": 4, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "timezone", + "default": null, + "nullable": false, + "ordinal": 5, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "week_open_utc", + "default": null, + "nullable": true, + "ordinal": 6, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "week_close_utc", + "default": null, + "nullable": true, + "ordinal": 7, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "rollover_utc", + "default": null, + "nullable": true, + "ordinal": 8, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "session_open_utc", + "default": null, + "nullable": true, + "ordinal": 9, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "session_close_utc", + "default": null, + "nullable": true, + "ordinal": 10, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "notes", + "default": null, + "nullable": true, + "ordinal": 11, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "calendar_version", + "default": null, + "nullable": false, + "ordinal": 12, + "table": "market_calendar", + "type": "text", + "udt": "text" + }, + { + "column": "created_at", + "default": "now()", + "nullable": false, + "ordinal": 13, + "table": "market_calendar", + "type": "timestamp with time zone", + "udt": "timestamptz" + }, + { + "column": "provider_id", + "default": "nextval('provider_provider_id_seq'::regclass)", + "nullable": false, + "ordinal": 1, + "table": "provider", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_key", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "provider", + "type": "text", + "udt": "text" + }, + { + "column": "name", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "provider", + "type": "text", + "udt": "text" + }, + { + "column": "data_type", + "default": null, + "nullable": false, + "ordinal": 4, + "table": "provider", + "type": "text", + "udt": "text" + }, + { + "column": "pricing_plan", + "default": null, + "nullable": true, + "ordinal": 5, + "table": "provider", + "type": "text", + "udt": "text" + }, + { + "column": "license_terms", + "default": null, + "nullable": true, + "ordinal": 6, + "table": "provider", + "type": "text", + "udt": "text" + }, + { + "column": "provider_id", + "default": null, + "nullable": false, + "ordinal": 1, + "table": "provider_instrument", + "type": "bigint", + "udt": "int8" + }, + { + "column": "instrument_id", + "default": null, + "nullable": false, + "ordinal": 2, + "table": "provider_instrument", + "type": "bigint", + "udt": "int8" + }, + { + "column": "provider_symbol", + "default": null, + "nullable": false, + "ordinal": 3, + "table": "provider_instrument", + "type": "text", + "udt": "text" + }, + { + "column": "broker_epic", + "default": null, + "nullable": true, + "ordinal": 4, + "table": "provider_instrument", + "type": "text", + "udt": "text" + }, + { + "column": "extra_metadata", + "default": null, + "nullable": true, + "ordinal": 5, + "table": "provider_instrument", + "type": "jsonb", + "udt": "jsonb" + }, + { + "column": "active", + "default": "true", + "nullable": false, + "ordinal": 6, + "table": "provider_instrument", + "type": "boolean", + "udt": "bool" + } + ], + "foreign_keys": [ + { + "columns": [ + "calendar_id" + ], + "constraint": "calendar_event_calendar_id_fkey", + "ref_columns": [ + "calendar_id" + ], + "ref_table": "market_calendar", + "table": "calendar_event" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "corporate_action_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "corporate_action" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "corporate_action_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "corporate_action" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "daily_quality_report_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "daily_quality_report" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "daily_quality_report_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "daily_quality_report" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "data_gap_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "data_gap" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "data_gap_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "data_gap" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "data_ingestion_run_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "data_ingestion_run" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "data_ingestion_run_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "data_ingestion_run" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "data_quality_issue_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "data_quality_issue" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "dataset_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "dataset" + }, + { + "columns": [ + "dataset_id" + ], + "constraint": "dataset_version_dataset_id_fkey", + "ref_columns": [ + "dataset_id" + ], + "ref_table": "dataset", + "table": "dataset_version" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "dataset_version_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "dataset_version" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "dataset_version_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "dataset_version" + }, + { + "columns": [ + "dataset_version_id" + ], + "constraint": "derived_bar_dataset_version_id_fkey", + "ref_columns": [ + "dataset_version_id" + ], + "ref_table": "dataset_version", + "table": "derived_bar" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "derived_bar_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "derived_bar" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "derived_bar_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "derived_bar" + }, + { + "columns": [ + "dataset_version_id" + ], + "constraint": "historical_bar_dataset_version_id_fkey", + "ref_columns": [ + "dataset_version_id" + ], + "ref_table": "dataset_version", + "table": "historical_bar" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "historical_bar_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "historical_bar" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "historical_bar_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "historical_bar" + }, + { + "columns": [ + "dataset_version_id" + ], + "constraint": "historical_tick_dataset_version_id_fkey", + "ref_columns": [ + "dataset_version_id" + ], + "ref_table": "dataset_version", + "table": "historical_tick" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "historical_tick_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "historical_tick" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "historical_tick_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "historical_tick" + }, + { + "columns": [ + "canonical_instrument_id" + ], + "constraint": "ingestion_provenance_canonical_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "ingestion_provenance" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "ingestion_provenance_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "ingestion_provenance" + }, + { + "columns": [ + "supersedes_provenance_id" + ], + "constraint": "ingestion_provenance_supersedes_fkey", + "ref_columns": [ + "provenance_id" + ], + "ref_table": "ingestion_provenance", + "table": "ingestion_provenance" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "provider_instrument_instrument_id_fkey", + "ref_columns": [ + "instrument_id" + ], + "ref_table": "instrument", + "table": "provider_instrument" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "provider_instrument_provider_id_fkey", + "ref_columns": [ + "provider_id" + ], + "ref_table": "provider", + "table": "provider_instrument" + } + ], + "indexes": [ + { + "definition": "CREATE UNIQUE INDEX calendar_event_calendar_id_event_date_kind_key ON public.calendar_event USING btree (calendar_id, event_date, kind)", + "index": "calendar_event_calendar_id_event_date_kind_key", + "table": "calendar_event" + }, + { + "definition": "CREATE UNIQUE INDEX calendar_event_pkey ON public.calendar_event USING btree (event_id)", + "index": "calendar_event_pkey", + "table": "calendar_event" + }, + { + "definition": "CREATE UNIQUE INDEX corporate_action_instrument_id_action_type_ex_date_provider_key ON public.corporate_action USING btree (instrument_id, action_type, ex_date, provider_id)", + "index": "corporate_action_instrument_id_action_type_ex_date_provider_key", + "table": "corporate_action" + }, + { + "definition": "CREATE UNIQUE INDEX corporate_action_pkey ON public.corporate_action USING btree (action_id)", + "index": "corporate_action_pkey", + "table": "corporate_action" + }, + { + "definition": "CREATE UNIQUE INDEX daily_quality_report_instrument_id_provider_id_report_date__key ON public.daily_quality_report USING btree (instrument_id, provider_id, report_date, feed_type)", + "index": "daily_quality_report_instrument_id_provider_id_report_date__key", + "table": "daily_quality_report" + }, + { + "definition": "CREATE UNIQUE INDEX daily_quality_report_pkey ON public.daily_quality_report USING btree (report_id)", + "index": "daily_quality_report_pkey", + "table": "daily_quality_report" + }, + { + "definition": "CREATE UNIQUE INDEX data_gap_pkey ON public.data_gap USING btree (gap_id)", + "index": "data_gap_pkey", + "table": "data_gap" + }, + { + "definition": "CREATE UNIQUE INDEX data_gap_unique ON public.data_gap USING btree (provider_id, instrument_id, timeframe, start_utc, end_utc, kind)", + "index": "data_gap_unique", + "table": "data_gap" + }, + { + "definition": "CREATE UNIQUE INDEX data_ingestion_run_pkey ON public.data_ingestion_run USING btree (ingestion_id)", + "index": "data_ingestion_run_pkey", + "table": "data_ingestion_run" + }, + { + "definition": "CREATE UNIQUE INDEX data_ingestion_run_provider_id_instrument_id_timeframe_star_key ON public.data_ingestion_run USING btree (provider_id, instrument_id, timeframe, started_at)", + "index": "data_ingestion_run_provider_id_instrument_id_timeframe_star_key", + "table": "data_ingestion_run" + }, + { + "definition": "CREATE UNIQUE INDEX data_quality_issue_pkey ON public.data_quality_issue USING btree (issue_id)", + "index": "data_quality_issue_pkey", + "table": "data_quality_issue" + }, + { + "definition": "CREATE UNIQUE INDEX dataset_name_key ON public.dataset USING btree (name)", + "index": "dataset_name_key", + "table": "dataset" + }, + { + "definition": "CREATE UNIQUE INDEX dataset_pkey ON public.dataset USING btree (dataset_id)", + "index": "dataset_pkey", + "table": "dataset" + }, + { + "definition": "CREATE UNIQUE INDEX dataset_version_dataset_version_hash_key ON public.dataset_version USING btree (dataset_version_hash)", + "index": "dataset_version_dataset_version_hash_key", + "table": "dataset_version" + }, + { + "definition": "CREATE UNIQUE INDEX dataset_version_pkey ON public.dataset_version USING btree (dataset_version_id)", + "index": "dataset_version_pkey", + "table": "dataset_version" + }, + { + "definition": "CREATE UNIQUE INDEX derived_bar_pkey ON public.derived_bar USING btree (derived_bar_id)", + "index": "derived_bar_pkey", + "table": "derived_bar" + }, + { + "definition": "CREATE UNIQUE INDEX derived_bar_provider_id_instrument_id_feed_type_price_basis_key ON public.derived_bar USING btree (provider_id, instrument_id, feed_type, price_basis, timeframe, ts_utc, aggregation_version)", + "index": "derived_bar_provider_id_instrument_id_feed_type_price_basis_key", + "table": "derived_bar" + }, + { + "definition": "CREATE INDEX idx_derived_inst_tf_ts ON public.derived_bar USING btree (instrument_id, timeframe, ts_utc)", + "index": "idx_derived_inst_tf_ts", + "table": "derived_bar" + }, + { + "definition": "CREATE UNIQUE INDEX historical_bar_pkey ON public.historical_bar USING btree (bar_id)", + "index": "historical_bar_pkey", + "table": "historical_bar" + }, + { + "definition": "CREATE UNIQUE INDEX historical_bar_provider_id_instrument_id_feed_type_price_ba_key ON public.historical_bar USING btree (provider_id, instrument_id, feed_type, price_basis, timeframe, ts_utc, raw_or_derived)", + "index": "historical_bar_provider_id_instrument_id_feed_type_price_ba_key", + "table": "historical_bar" + }, + { + "definition": "CREATE INDEX idx_bar_dsver ON public.historical_bar USING btree (dataset_version_id)", + "index": "idx_bar_dsver", + "table": "historical_bar" + }, + { + "definition": "CREATE INDEX idx_bar_elig ON public.historical_bar USING btree (eligibility)", + "index": "idx_bar_elig", + "table": "historical_bar" + }, + { + "definition": "CREATE INDEX idx_bar_inst_tf_ts ON public.historical_bar USING btree (instrument_id, timeframe, ts_utc)", + "index": "idx_bar_inst_tf_ts", + "table": "historical_bar" + }, + { + "definition": "CREATE INDEX idx_bar_sess_ts ON public.historical_bar USING btree (session_state, instrument_id, ts_utc)", + "index": "idx_bar_sess_ts", + "table": "historical_bar" + }, + { + "definition": "CREATE INDEX idx_bar_session ON public.historical_bar USING btree (session_state, session_phase)", + "index": "idx_bar_session", + "table": "historical_bar" + }, + { + "definition": "CREATE INDEX idx_bar_techq ON public.historical_bar USING btree (technical_quality)", + "index": "idx_bar_techq", + "table": "historical_bar" + }, + { + "definition": "CREATE INDEX idx_historical_bar_market_quality ON public.historical_bar USING btree (instrument_id, market_quality)", + "index": "idx_historical_bar_market_quality", + "table": "historical_bar" + }, + { + "definition": "CREATE INDEX idx_historical_bar_session_state ON public.historical_bar USING btree (instrument_id, session_state)", + "index": "idx_historical_bar_session_state", + "table": "historical_bar" + }, + { + "definition": "CREATE UNIQUE INDEX historical_tick_pkey ON public.historical_tick USING btree (tick_id)", + "index": "historical_tick_pkey", + "table": "historical_tick" + }, + { + "definition": "CREATE UNIQUE INDEX historical_tick_provider_id_instrument_id_feed_type_ts_utc__key ON public.historical_tick USING btree (provider_id, instrument_id, feed_type, ts_utc, bid, ask)", + "index": "historical_tick_provider_id_instrument_id_feed_type_ts_utc__key", + "table": "historical_tick" + }, + { + "definition": "CREATE INDEX idx_tick_inst_ts ON public.historical_tick USING btree (instrument_id, ts_utc)", + "index": "idx_tick_inst_ts", + "table": "historical_tick" + }, + { + "definition": "CREATE INDEX idx_prov_adapter_version ON public.ingestion_provenance USING btree (adapter_version)", + "index": "idx_prov_adapter_version", + "table": "ingestion_provenance" + }, + { + "definition": "CREATE INDEX idx_prov_instrument ON public.ingestion_provenance USING btree (canonical_instrument_id)", + "index": "idx_prov_instrument", + "table": "ingestion_provenance" + }, + { + "definition": "CREATE INDEX idx_prov_provider_feed ON public.ingestion_provenance USING btree (provider_id, provider_feed)", + "index": "idx_prov_provider_feed", + "table": "ingestion_provenance" + }, + { + "definition": "CREATE INDEX idx_prov_raw_sha ON public.ingestion_provenance USING btree (raw_payload_sha256)", + "index": "idx_prov_raw_sha", + "table": "ingestion_provenance" + }, + { + "definition": "CREATE INDEX idx_prov_request_identity ON public.ingestion_provenance USING btree (request_identity_hash)", + "index": "idx_prov_request_identity", + "table": "ingestion_provenance" + }, + { + "definition": "CREATE INDEX idx_prov_time_range ON public.ingestion_provenance USING btree (request_start, request_end)", + "index": "idx_prov_time_range", + "table": "ingestion_provenance" + }, + { + "definition": "CREATE UNIQUE INDEX ingestion_provenance_ingestion_run_id_key ON public.ingestion_provenance USING btree (ingestion_run_id)", + "index": "ingestion_provenance_ingestion_run_id_key", + "table": "ingestion_provenance" + }, + { + "definition": "CREATE UNIQUE INDEX ingestion_provenance_pkey ON public.ingestion_provenance USING btree (provenance_id)", + "index": "ingestion_provenance_pkey", + "table": "ingestion_provenance" + }, + { + "definition": "CREATE UNIQUE INDEX instrument_pkey ON public.instrument USING btree (instrument_id)", + "index": "instrument_pkey", + "table": "instrument" + }, + { + "definition": "CREATE UNIQUE INDEX instrument_symbol_key ON public.instrument USING btree (symbol)", + "index": "instrument_symbol_key", + "table": "instrument" + }, + { + "definition": "CREATE UNIQUE INDEX market_calendar_calendar_name_key ON public.market_calendar USING btree (calendar_name)", + "index": "market_calendar_calendar_name_key", + "table": "market_calendar" + }, + { + "definition": "CREATE UNIQUE INDEX market_calendar_pkey ON public.market_calendar USING btree (calendar_id)", + "index": "market_calendar_pkey", + "table": "market_calendar" + }, + { + "definition": "CREATE UNIQUE INDEX provider_pkey ON public.provider USING btree (provider_id)", + "index": "provider_pkey", + "table": "provider" + }, + { + "definition": "CREATE UNIQUE INDEX provider_provider_key_key ON public.provider USING btree (provider_key)", + "index": "provider_provider_key_key", + "table": "provider" + }, + { + "definition": "CREATE UNIQUE INDEX provider_instrument_pkey ON public.provider_instrument USING btree (provider_id, instrument_id)", + "index": "provider_instrument_pkey", + "table": "provider_instrument" + }, + { + "definition": "CREATE UNIQUE INDEX provider_instrument_provider_id_provider_symbol_key ON public.provider_instrument USING btree (provider_id, provider_symbol)", + "index": "provider_instrument_provider_id_provider_symbol_key", + "table": "provider_instrument" + } + ], + "primary_keys": [ + { + "columns": [ + "event_id" + ], + "constraint": "calendar_event_pkey", + "table": "calendar_event" + }, + { + "columns": [ + "action_id" + ], + "constraint": "corporate_action_pkey", + "table": "corporate_action" + }, + { + "columns": [ + "report_id" + ], + "constraint": "daily_quality_report_pkey", + "table": "daily_quality_report" + }, + { + "columns": [ + "gap_id" + ], + "constraint": "data_gap_pkey", + "table": "data_gap" + }, + { + "columns": [ + "ingestion_id" + ], + "constraint": "data_ingestion_run_pkey", + "table": "data_ingestion_run" + }, + { + "columns": [ + "issue_id" + ], + "constraint": "data_quality_issue_pkey", + "table": "data_quality_issue" + }, + { + "columns": [ + "dataset_id" + ], + "constraint": "dataset_pkey", + "table": "dataset" + }, + { + "columns": [ + "dataset_version_id" + ], + "constraint": "dataset_version_pkey", + "table": "dataset_version" + }, + { + "columns": [ + "derived_bar_id" + ], + "constraint": "derived_bar_pkey", + "table": "derived_bar" + }, + { + "columns": [ + "bar_id" + ], + "constraint": "historical_bar_pkey", + "table": "historical_bar" + }, + { + "columns": [ + "tick_id" + ], + "constraint": "historical_tick_pkey", + "table": "historical_tick" + }, + { + "columns": [ + "provenance_id" + ], + "constraint": "ingestion_provenance_pkey", + "table": "ingestion_provenance" + }, + { + "columns": [ + "instrument_id" + ], + "constraint": "instrument_pkey", + "table": "instrument" + }, + { + "columns": [ + "calendar_id" + ], + "constraint": "market_calendar_pkey", + "table": "market_calendar" + }, + { + "columns": [ + "provider_id" + ], + "constraint": "provider_pkey", + "table": "provider" + }, + { + "columns": [ + "provider_id", + "instrument_id" + ], + "constraint": "provider_instrument_pkey", + "table": "provider_instrument" + } + ], + "sequences": [ + "calendar_event_event_id_seq", + "corporate_action_action_id_seq", + "daily_quality_report_report_id_seq", + "data_gap_gap_id_seq", + "data_ingestion_run_ingestion_id_seq", + "data_quality_issue_issue_id_seq", + "dataset_dataset_id_seq", + "dataset_version_dataset_version_id_seq", + "derived_bar_derived_bar_id_seq", + "historical_bar_bar_id_seq", + "historical_tick_tick_id_seq", + "ingestion_provenance_provenance_id_seq", + "instrument_instrument_id_seq", + "market_calendar_calendar_id_seq", + "provider_provider_id_seq" + ], + "tables": [ + "calendar_event", + "corporate_action", + "daily_quality_report", + "data_gap", + "data_ingestion_run", + "data_quality_issue", + "dataset", + "dataset_version", + "derived_bar", + "historical_bar", + "historical_tick", + "ingestion_provenance", + "instrument", + "market_calendar", + "provider", + "provider_instrument" + ], + "unique_constraints": [ + { + "columns": [ + "calendar_id", + "event_date", + "kind" + ], + "constraint": "calendar_event_calendar_id_event_date_kind_key", + "table": "calendar_event" + }, + { + "columns": [ + "instrument_id", + "action_type", + "ex_date", + "provider_id" + ], + "constraint": "corporate_action_instrument_id_action_type_ex_date_provider_key", + "table": "corporate_action" + }, + { + "columns": [ + "instrument_id", + "provider_id", + "report_date", + "feed_type" + ], + "constraint": "daily_quality_report_instrument_id_provider_id_report_date__key", + "table": "daily_quality_report" + }, + { + "columns": [ + "provider_id", + "instrument_id", + "timeframe", + "start_utc", + "end_utc", + "kind" + ], + "constraint": "data_gap_unique", + "table": "data_gap" + }, + { + "columns": [ + "provider_id", + "instrument_id", + "timeframe", + "started_at" + ], + "constraint": "data_ingestion_run_provider_id_instrument_id_timeframe_star_key", + "table": "data_ingestion_run" + }, + { + "columns": [ + "name" + ], + "constraint": "dataset_name_key", + "table": "dataset" + }, + { + "columns": [ + "dataset_version_hash" + ], + "constraint": "dataset_version_dataset_version_hash_key", + "table": "dataset_version" + }, + { + "columns": [ + "provider_id", + "instrument_id", + "feed_type", + "price_basis", + "timeframe", + "ts_utc", + "aggregation_version" + ], + "constraint": "derived_bar_provider_id_instrument_id_feed_type_price_basis_key", + "table": "derived_bar" + }, + { + "columns": [ + "provider_id", + "instrument_id", + "feed_type", + "price_basis", + "timeframe", + "ts_utc", + "raw_or_derived" + ], + "constraint": "historical_bar_provider_id_instrument_id_feed_type_price_ba_key", + "table": "historical_bar" + }, + { + "columns": [ + "provider_id", + "instrument_id", + "feed_type", + "ts_utc", + "bid", + "ask" + ], + "constraint": "historical_tick_provider_id_instrument_id_feed_type_ts_utc__key", + "table": "historical_tick" + }, + { + "columns": [ + "ingestion_run_id" + ], + "constraint": "ingestion_provenance_ingestion_run_id_key", + "table": "ingestion_provenance" + }, + { + "columns": [ + "symbol" + ], + "constraint": "instrument_symbol_key", + "table": "instrument" + }, + { + "columns": [ + "calendar_name" + ], + "constraint": "market_calendar_calendar_name_key", + "table": "market_calendar" + }, + { + "columns": [ + "provider_key" + ], + "constraint": "provider_provider_key_key", + "table": "provider" + }, + { + "columns": [ + "provider_id", + "provider_symbol" + ], + "constraint": "provider_instrument_provider_id_provider_symbol_key", + "table": "provider_instrument" + } + ] +} \ No newline at end of file diff --git a/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.sha256 b/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.sha256 new file mode 100644 index 0000000..b7a7aac --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.sha256 @@ -0,0 +1 @@ +b49f64337ffafc0e73d46e009aa802cd0172d59421b7df61d3eb198775c1986d diff --git a/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.sql b/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.sql new file mode 100644 index 0000000..fa2b12e --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/contract/historical_v2_schema.sql @@ -0,0 +1,601 @@ +-- ============================================================ +-- CANONICAL CURRENT PRODUCTION SCHEMA CONTRACT (L0) +-- db: historical · schema: public +-- Auto-generated by gen_l0_sql.py from read-only capture +-- Modus: CURRENT VERIFIED PRODUCTION TRUTH — NICHT historische Migration +-- ============================================================ + +-- SEMANTIC OVERRIDES (Owner-Canonical) +-- last_successful_chunk = timestamp with time zone (Production + Owner decision) +-- interrupt_reason = text · PRESERVED CURRENT CONTRACT · origin unknown · do not remove +-- technical_quality = text · nullable · default 'VALID' · historical provenance debt OPEN + +CREATE SEQUENCE IF NOT EXISTS "calendar_event_event_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "corporate_action_action_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "daily_quality_report_report_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "data_gap_gap_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "data_ingestion_run_ingestion_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "data_quality_issue_issue_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "dataset_dataset_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "dataset_version_dataset_version_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "derived_bar_derived_bar_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "historical_bar_bar_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "historical_tick_tick_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "ingestion_provenance_provenance_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "instrument_instrument_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "market_calendar_calendar_id_seq"; +CREATE SEQUENCE IF NOT EXISTS "provider_provider_id_seq"; + +-- Table: calendar_event (9 cols) +CREATE TABLE IF NOT EXISTS "calendar_event" ( + "event_id" bigint NOT NULL DEFAULT nextval('calendar_event_event_id_seq'::regclass), + "calendar_id" bigint NOT NULL, + "event_date" date NOT NULL, + "kind" text NOT NULL, + "reason" text, + "session_phase_override" text, + "source" text, + "notes" text, + "created_at" timestamp with time zone NOT NULL DEFAULT now() +); + +-- Table: corporate_action (9 cols) +CREATE TABLE IF NOT EXISTS "corporate_action" ( + "action_id" bigint NOT NULL DEFAULT nextval('corporate_action_action_id_seq'::regclass), + "instrument_id" bigint NOT NULL, + "action_type" text NOT NULL, + "ex_date" date NOT NULL, + "ratio_num" double precision, + "ratio_denom" double precision, + "dividend" double precision, + "currency" text, + "provider_id" bigint +); + +-- Table: daily_quality_report (23 cols) +CREATE TABLE IF NOT EXISTS "daily_quality_report" ( + "report_id" bigint NOT NULL DEFAULT nextval('daily_quality_report_report_id_seq'::regclass), + "instrument_id" bigint NOT NULL, + "provider_id" bigint NOT NULL, + "report_date" date NOT NULL, + "feed_type" text DEFAULT 'REFERENCE'::text, + "expected_m1" bigint, + "received_m1" bigint, + "eligible" bigint, + "excluded" bigint, + "conditional" bigint, + "stale_count" bigint, + "zero_volume" bigint, + "spread_median_price" double precision, + "spread_p95_price" double precision, + "spread_p99_price" double precision, + "gaps_count" bigint, + "coverage_ratio" double precision, + "session_anomalies" bigint, + "status" text NOT NULL, + "quality_model_version" text, + "session_model_version" text, + "calendar_version" text, + "generated_at" timestamp with time zone NOT NULL DEFAULT now() +); + +-- Table: data_gap (9 cols) +CREATE TABLE IF NOT EXISTS "data_gap" ( + "gap_id" bigint NOT NULL DEFAULT nextval('data_gap_gap_id_seq'::regclass), + "provider_id" bigint NOT NULL, + "instrument_id" bigint NOT NULL, + "timeframe" text NOT NULL, + "start_utc" timestamp with time zone NOT NULL, + "end_utc" timestamp with time zone NOT NULL, + "kind" text NOT NULL, + "backfilled" boolean NOT NULL DEFAULT false, + "filled_at" timestamp with time zone +); + +-- Table: data_ingestion_run (29 cols) +CREATE TABLE IF NOT EXISTS "data_ingestion_run" ( + "ingestion_id" bigint NOT NULL DEFAULT nextval('data_ingestion_run_ingestion_id_seq'::regclass), + "provider_id" bigint NOT NULL, + "instrument_id" bigint NOT NULL, + "timeframe" text NOT NULL, + "start_utc" timestamp with time zone, + "end_utc" timestamp with time zone, + "rows_inserted" bigint DEFAULT 0, + "rows_skipped" bigint DEFAULT 0, + "status" text NOT NULL DEFAULT 'RUNNING'::text, + "started_at" timestamp with time zone NOT NULL DEFAULT now(), + "finished_at" timestamp with time zone, + "checkpoint" jsonb, + "status_fsm" text DEFAULT 'PENDING'::text, + "rows_downloaded" bigint DEFAULT 0, + "rows_decoded" bigint DEFAULT 0, + "rows_valid" bigint DEFAULT 0, + "rows_suspect" bigint DEFAULT 0, + "rows_excluded" bigint DEFAULT 0, + "rows_derived" bigint DEFAULT 0, + "last_successful_chunk" timestamp with time zone, + "last_timestamp" timestamp with time zone, + "updated_at" timestamp with time zone DEFAULT now(), + "interrupt_reason" text, + "rows_existing" bigint DEFAULT 0, + "rows_deduplicated" bigint DEFAULT 0, + "rows_404" bigint DEFAULT 0, + "rows_503" bigint DEFAULT 0, + "rows_provider_unavailable" bigint DEFAULT 0, + "rows_failed" bigint DEFAULT 0 +); + +-- Table: data_quality_issue (9 cols) +CREATE TABLE IF NOT EXISTS "data_quality_issue" ( + "issue_id" bigint NOT NULL DEFAULT nextval('data_quality_issue_issue_id_seq'::regclass), + "instrument_id" bigint NOT NULL, + "timeframe" text NOT NULL, + "ts_utc" timestamp with time zone, + "severity" text NOT NULL, + "issue_type" text NOT NULL, + "detail" jsonb, + "resolved" boolean NOT NULL DEFAULT false, + "created_at" timestamp with time zone NOT NULL DEFAULT now() +); + +-- Table: dataset (6 cols) +CREATE TABLE IF NOT EXISTS "dataset" ( + "dataset_id" bigint NOT NULL DEFAULT nextval('dataset_dataset_id_seq'::regclass), + "name" text NOT NULL, + "provider_id" bigint NOT NULL, + "feed_type" text NOT NULL, + "description" text, + "created_at" timestamp with time zone NOT NULL DEFAULT now() +); + +-- Table: dataset_version (23 cols) +CREATE TABLE IF NOT EXISTS "dataset_version" ( + "dataset_version_id" bigint NOT NULL DEFAULT nextval('dataset_version_dataset_version_id_seq'::regclass), + "dataset_id" bigint NOT NULL, + "version_label" text NOT NULL, + "provider_id" bigint NOT NULL, + "feed_type" text NOT NULL, + "instrument_id" bigint NOT NULL, + "timeframe" text NOT NULL, + "start_utc" timestamp with time zone NOT NULL, + "end_utc" timestamp with time zone NOT NULL, + "raw_source" text NOT NULL, + "normalization_version" text NOT NULL, + "aggregation_version" text, + "quality_version" text NOT NULL, + "dataset_version_hash" text NOT NULL, + "data_as_of" timestamp with time zone NOT NULL, + "notes" text, + "created_at" timestamp with time zone NOT NULL DEFAULT now(), + "quality_model_version" text, + "stale_model_version" text, + "session_model_version" text, + "calendar_version" text, + "eligibility_model_version" text, + "is_fixture" boolean NOT NULL DEFAULT false +); + +-- Table: derived_bar (35 cols) +CREATE TABLE IF NOT EXISTS "derived_bar" ( + "derived_bar_id" bigint NOT NULL DEFAULT nextval('derived_bar_derived_bar_id_seq'::regclass), + "provider_id" bigint NOT NULL, + "instrument_id" bigint NOT NULL, + "feed_type" text NOT NULL DEFAULT 'REFERENCE'::text, + "price_basis" text NOT NULL DEFAULT 'bid_ask'::text, + "timeframe" text NOT NULL, + "ts_utc" timestamp with time zone NOT NULL, + "source_timeframe" text NOT NULL, + "aggregation_version" text NOT NULL, + "bid_open" double precision, + "bid_high" double precision, + "bid_low" double precision, + "bid_close" double precision, + "ask_open" double precision, + "ask_high" double precision, + "ask_low" double precision, + "ask_close" double precision, + "mid_open" double precision, + "mid_high" double precision, + "mid_low" double precision, + "mid_close" double precision, + "volume" double precision, + "volume_type" text DEFAULT 'tick'::text, + "quality_status" text NOT NULL DEFAULT 'VALID'::text, + "quality_flags" _text, + "dataset_version_id" bigint NOT NULL, + "expected_bar_count" bigint, + "actual_bar_count" bigint, + "eligible_bar_count" bigint, + "excluded_bar_count" bigint, + "coverage_ratio" double precision, + "aggregation_quality" text, + "eligibility_model_version" text DEFAULT 'eligibility_v1'::text, + "session_model_version" text DEFAULT 'fx_session_v1'::text, + "calendar_version" text DEFAULT 'fx_cal_v1'::text +); + +-- Table: historical_bar (41 cols) +CREATE TABLE IF NOT EXISTS "historical_bar" ( + "bar_id" bigint NOT NULL DEFAULT nextval('historical_bar_bar_id_seq'::regclass), + "provider_id" bigint NOT NULL, + "instrument_id" bigint NOT NULL, + "feed_type" text NOT NULL DEFAULT 'REFERENCE'::text, + "price_basis" text NOT NULL DEFAULT 'bid_ask'::text, + "timeframe" text NOT NULL, + "ts_utc" timestamp with time zone NOT NULL, + "raw_or_derived" text NOT NULL DEFAULT 'raw'::text, + "source_timeframe" text, + "aggregation_version" text, + "bid_open" double precision, + "bid_high" double precision, + "bid_low" double precision, + "bid_close" double precision, + "ask_open" double precision, + "ask_high" double precision, + "ask_low" double precision, + "ask_close" double precision, + "mid_open" double precision, + "mid_high" double precision, + "mid_low" double precision, + "mid_close" double precision, + "volume" double precision, + "volume_type" text DEFAULT 'tick'::text, + "quality_status" text NOT NULL DEFAULT 'VALID'::text, + "quality_flags" _text, + "source_timestamp" timestamp with time zone, + "ingested_at" timestamp with time zone NOT NULL DEFAULT now(), + "dataset_version_id" bigint NOT NULL, + "technical_quality" text DEFAULT 'VALID'::text, + "market_quality" text, + "session_state" text, + "session_phase" text, + "eligibility" text DEFAULT 'ELIGIBLE'::text, + "exclusion_reason" text, + "quality_model_version" text DEFAULT 'quality_v1'::text, + "session_model_version" text, + "calendar_version" text, + "eligibility_model_version" text DEFAULT 'eligibility_v1'::text, + "effective_eligibility" text, + "stale_model_version" text +); + +-- Table: historical_tick (10 cols) +CREATE TABLE IF NOT EXISTS "historical_tick" ( + "tick_id" bigint NOT NULL DEFAULT nextval('historical_tick_tick_id_seq'::regclass), + "provider_id" bigint NOT NULL, + "instrument_id" bigint NOT NULL, + "feed_type" text NOT NULL DEFAULT 'REFERENCE'::text, + "ts_utc" timestamp with time zone NOT NULL, + "bid" double precision, + "ask" double precision, + "last" double precision, + "volume" double precision, + "dataset_version_id" bigint NOT NULL +); + +-- Table: ingestion_provenance (41 cols) +CREATE TABLE IF NOT EXISTS "ingestion_provenance" ( + "provenance_id" bigint NOT NULL, + "ingestion_run_id" bigint NOT NULL, + "provider_id" bigint NOT NULL, + "provider_name_snapshot" text NOT NULL, + "provider_environment_class" text NOT NULL, + "provider_dataset" text NOT NULL, + "provider_feed" text NOT NULL, + "provider_instrument_id" text NOT NULL, + "canonical_instrument_id" bigint NOT NULL, + "asset_class" text NOT NULL, + "request_start" timestamp with time zone NOT NULL, + "request_end" timestamp with time zone NOT NULL, + "actual_start" timestamp with time zone NOT NULL, + "actual_end" timestamp with time zone NOT NULL, + "request_timestamp" timestamp with time zone NOT NULL, + "response_timestamp" timestamp with time zone NOT NULL, + "http_status" integer NOT NULL, + "provider_metadata" jsonb, + "provider_version" text, + "raw_payload_sha256" text NOT NULL, + "raw_content_length" bigint NOT NULL, + "compression" text NOT NULL, + "content_type" text, + "parser_version" text NOT NULL, + "adapter_version" text NOT NULL, + "normalization_version" text NOT NULL, + "timezone_source" text NOT NULL, + "timezone_target" text NOT NULL, + "timezone_transform_version" text NOT NULL, + "price_type" text NOT NULL, + "granularity" text NOT NULL, + "correction_status" text NOT NULL DEFAULT 'ORIGINAL'::text, + "license_class" text NOT NULL DEFAULT 'UNKNOWN'::text, + "software_git_commit" text NOT NULL, + "software_image_id" text NOT NULL, + "software_build_input_sha" text, + "request_identity_hash" text NOT NULL, + "supersedes_provenance_id" bigint, + "raw_storage_ref" text, + "extra" jsonb, + "created_at" timestamp with time zone NOT NULL DEFAULT now() +); + +-- Table: instrument (13 cols) +CREATE TABLE IF NOT EXISTS "instrument" ( + "instrument_id" bigint NOT NULL DEFAULT nextval('instrument_instrument_id_seq'::regclass), + "symbol" text NOT NULL, + "asset_class" text NOT NULL, + "name" text, + "currency" text, + "exchange" text, + "mic" text, + "isin" text, + "tick_size" double precision, + "contract_size" double precision, + "min_deal_size" double precision, + "active" boolean NOT NULL DEFAULT true, + "created_at" timestamp with time zone NOT NULL DEFAULT now() +); + +-- Table: market_calendar (13 cols) +CREATE TABLE IF NOT EXISTS "market_calendar" ( + "calendar_id" bigint NOT NULL DEFAULT nextval('market_calendar_calendar_id_seq'::regclass), + "calendar_name" text NOT NULL, + "asset_class" text NOT NULL, + "venue_exchange" text, + "timezone" text NOT NULL, + "week_open_utc" text, + "week_close_utc" text, + "rollover_utc" text, + "session_open_utc" text, + "session_close_utc" text, + "notes" text, + "calendar_version" text NOT NULL, + "created_at" timestamp with time zone NOT NULL DEFAULT now() +); + +-- Table: provider (6 cols) +CREATE TABLE IF NOT EXISTS "provider" ( + "provider_id" bigint NOT NULL DEFAULT nextval('provider_provider_id_seq'::regclass), + "provider_key" text NOT NULL, + "name" text NOT NULL, + "data_type" text NOT NULL, + "pricing_plan" text, + "license_terms" text +); + +-- Table: provider_instrument (6 cols) +CREATE TABLE IF NOT EXISTS "provider_instrument" ( + "provider_id" bigint NOT NULL, + "instrument_id" bigint NOT NULL, + "provider_symbol" text NOT NULL, + "broker_epic" text, + "extra_metadata" jsonb, + "active" boolean NOT NULL DEFAULT true +); + +ALTER TABLE "calendar_event" ADD CONSTRAINT "calendar_event_pkey" PRIMARY KEY ("event_id"); +ALTER TABLE "corporate_action" ADD CONSTRAINT "corporate_action_pkey" PRIMARY KEY ("action_id"); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "daily_quality_report_pkey" PRIMARY KEY ("report_id"); +ALTER TABLE "data_gap" ADD CONSTRAINT "data_gap_pkey" PRIMARY KEY ("gap_id"); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "data_ingestion_run_pkey" PRIMARY KEY ("ingestion_id"); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "data_quality_issue_pkey" PRIMARY KEY ("issue_id"); +ALTER TABLE "dataset" ADD CONSTRAINT "dataset_pkey" PRIMARY KEY ("dataset_id"); +ALTER TABLE "dataset_version" ADD CONSTRAINT "dataset_version_pkey" PRIMARY KEY ("dataset_version_id"); +ALTER TABLE "derived_bar" ADD CONSTRAINT "derived_bar_pkey" PRIMARY KEY ("derived_bar_id"); +ALTER TABLE "historical_bar" ADD CONSTRAINT "historical_bar_pkey" PRIMARY KEY ("bar_id"); +ALTER TABLE "historical_tick" ADD CONSTRAINT "historical_tick_pkey" PRIMARY KEY ("tick_id"); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "ingestion_provenance_pkey" PRIMARY KEY ("provenance_id"); +ALTER TABLE "instrument" ADD CONSTRAINT "instrument_pkey" PRIMARY KEY ("instrument_id"); +ALTER TABLE "market_calendar" ADD CONSTRAINT "market_calendar_pkey" PRIMARY KEY ("calendar_id"); +ALTER TABLE "provider" ADD CONSTRAINT "provider_pkey" PRIMARY KEY ("provider_id"); +ALTER TABLE "provider_instrument" ADD CONSTRAINT "provider_instrument_pkey" PRIMARY KEY ("provider_id", "instrument_id"); + +ALTER TABLE "calendar_event" ADD CONSTRAINT "calendar_event_calendar_id_event_date_kind_key" UNIQUE ("calendar_id", "event_date", "kind"); +ALTER TABLE "corporate_action" ADD CONSTRAINT "corporate_action_instrument_id_action_type_ex_date_provider_key" UNIQUE ("instrument_id", "action_type", "ex_date", "provider_id"); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "daily_quality_report_instrument_id_provider_id_report_date__key" UNIQUE ("instrument_id", "provider_id", "report_date", "feed_type"); +ALTER TABLE "data_gap" ADD CONSTRAINT "data_gap_unique" UNIQUE ("provider_id", "instrument_id", "timeframe", "start_utc", "end_utc", "kind"); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "data_ingestion_run_provider_id_instrument_id_timeframe_star_key" UNIQUE ("provider_id", "instrument_id", "timeframe", "started_at"); +ALTER TABLE "dataset" ADD CONSTRAINT "dataset_name_key" UNIQUE ("name"); +ALTER TABLE "dataset_version" ADD CONSTRAINT "dataset_version_dataset_version_hash_key" UNIQUE ("dataset_version_hash"); +ALTER TABLE "derived_bar" ADD CONSTRAINT "derived_bar_provider_id_instrument_id_feed_type_price_basis_key" UNIQUE ("provider_id", "instrument_id", "feed_type", "price_basis", "timeframe", "ts_utc", "aggregation_version"); +ALTER TABLE "historical_bar" ADD CONSTRAINT "historical_bar_provider_id_instrument_id_feed_type_price_ba_key" UNIQUE ("provider_id", "instrument_id", "feed_type", "price_basis", "timeframe", "ts_utc", "raw_or_derived"); +ALTER TABLE "historical_tick" ADD CONSTRAINT "historical_tick_provider_id_instrument_id_feed_type_ts_utc__key" UNIQUE ("provider_id", "instrument_id", "feed_type", "ts_utc", "bid", "ask"); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "ingestion_provenance_ingestion_run_id_key" UNIQUE ("ingestion_run_id"); +ALTER TABLE "instrument" ADD CONSTRAINT "instrument_symbol_key" UNIQUE ("symbol"); +ALTER TABLE "market_calendar" ADD CONSTRAINT "market_calendar_calendar_name_key" UNIQUE ("calendar_name"); +ALTER TABLE "provider" ADD CONSTRAINT "provider_provider_key_key" UNIQUE ("provider_key"); +ALTER TABLE "provider_instrument" ADD CONSTRAINT "provider_instrument_provider_id_provider_symbol_key" UNIQUE ("provider_id", "provider_symbol"); + +ALTER TABLE "calendar_event" ADD CONSTRAINT "calendar_event_calendar_id_fkey" FOREIGN KEY ("calendar_id") REFERENCES "market_calendar" ("calendar_id"); +ALTER TABLE "corporate_action" ADD CONSTRAINT "corporate_action_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "corporate_action" ADD CONSTRAINT "corporate_action_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "daily_quality_report_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "daily_quality_report_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "data_gap" ADD CONSTRAINT "data_gap_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "data_gap" ADD CONSTRAINT "data_gap_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "data_ingestion_run_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "data_ingestion_run_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "data_quality_issue_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "dataset" ADD CONSTRAINT "dataset_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "dataset_version" ADD CONSTRAINT "dataset_version_dataset_id_fkey" FOREIGN KEY ("dataset_id") REFERENCES "dataset" ("dataset_id"); +ALTER TABLE "dataset_version" ADD CONSTRAINT "dataset_version_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "dataset_version" ADD CONSTRAINT "dataset_version_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "derived_bar" ADD CONSTRAINT "derived_bar_dataset_version_id_fkey" FOREIGN KEY ("dataset_version_id") REFERENCES "dataset_version" ("dataset_version_id"); +ALTER TABLE "derived_bar" ADD CONSTRAINT "derived_bar_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "derived_bar" ADD CONSTRAINT "derived_bar_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "historical_bar" ADD CONSTRAINT "historical_bar_dataset_version_id_fkey" FOREIGN KEY ("dataset_version_id") REFERENCES "dataset_version" ("dataset_version_id"); +ALTER TABLE "historical_bar" ADD CONSTRAINT "historical_bar_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "historical_bar" ADD CONSTRAINT "historical_bar_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "historical_tick" ADD CONSTRAINT "historical_tick_dataset_version_id_fkey" FOREIGN KEY ("dataset_version_id") REFERENCES "dataset_version" ("dataset_version_id"); +ALTER TABLE "historical_tick" ADD CONSTRAINT "historical_tick_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "historical_tick" ADD CONSTRAINT "historical_tick_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "ingestion_provenance_canonical_instrument_id_fkey" FOREIGN KEY ("canonical_instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "ingestion_provenance_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "ingestion_provenance_supersedes_fkey" FOREIGN KEY ("supersedes_provenance_id") REFERENCES "ingestion_provenance" ("provenance_id"); +ALTER TABLE "provider_instrument" ADD CONSTRAINT "provider_instrument_instrument_id_fkey" FOREIGN KEY ("instrument_id") REFERENCES "instrument" ("instrument_id"); +ALTER TABLE "provider_instrument" ADD CONSTRAINT "provider_instrument_provider_id_fkey" FOREIGN KEY ("provider_id") REFERENCES "provider" ("provider_id"); + +ALTER TABLE "calendar_event" ADD CONSTRAINT "2200_16679_1_not_null" CHECK (event_id IS NOT NULL); +ALTER TABLE "calendar_event" ADD CONSTRAINT "2200_16679_2_not_null" CHECK (calendar_id IS NOT NULL); +ALTER TABLE "calendar_event" ADD CONSTRAINT "2200_16679_3_not_null" CHECK (event_date IS NOT NULL); +ALTER TABLE "calendar_event" ADD CONSTRAINT "2200_16679_4_not_null" CHECK (kind IS NOT NULL); +ALTER TABLE "calendar_event" ADD CONSTRAINT "2200_16679_9_not_null" CHECK (created_at IS NOT NULL); +ALTER TABLE "corporate_action" ADD CONSTRAINT "2200_16567_1_not_null" CHECK (action_id IS NOT NULL); +ALTER TABLE "corporate_action" ADD CONSTRAINT "2200_16567_2_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "corporate_action" ADD CONSTRAINT "2200_16567_3_not_null" CHECK (action_type IS NOT NULL); +ALTER TABLE "corporate_action" ADD CONSTRAINT "2200_16567_4_not_null" CHECK (ex_date IS NOT NULL); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "2200_16696_19_not_null" CHECK (status IS NOT NULL); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "2200_16696_1_not_null" CHECK (report_id IS NOT NULL); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "2200_16696_23_not_null" CHECK (generated_at IS NOT NULL); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "2200_16696_2_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "2200_16696_3_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "daily_quality_report" ADD CONSTRAINT "2200_16696_4_not_null" CHECK (report_date IS NOT NULL); +ALTER TABLE "data_gap" ADD CONSTRAINT "2200_16613_1_not_null" CHECK (gap_id IS NOT NULL); +ALTER TABLE "data_gap" ADD CONSTRAINT "2200_16613_2_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "data_gap" ADD CONSTRAINT "2200_16613_3_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "data_gap" ADD CONSTRAINT "2200_16613_4_not_null" CHECK (timeframe IS NOT NULL); +ALTER TABLE "data_gap" ADD CONSTRAINT "2200_16613_5_not_null" CHECK (start_utc IS NOT NULL); +ALTER TABLE "data_gap" ADD CONSTRAINT "2200_16613_6_not_null" CHECK (end_utc IS NOT NULL); +ALTER TABLE "data_gap" ADD CONSTRAINT "2200_16613_7_not_null" CHECK (kind IS NOT NULL); +ALTER TABLE "data_gap" ADD CONSTRAINT "2200_16613_8_not_null" CHECK (backfilled IS NOT NULL); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "2200_16588_10_not_null" CHECK (started_at IS NOT NULL); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "2200_16588_1_not_null" CHECK (ingestion_id IS NOT NULL); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "2200_16588_2_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "2200_16588_3_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "2200_16588_4_not_null" CHECK (timeframe IS NOT NULL); +ALTER TABLE "data_ingestion_run" ADD CONSTRAINT "2200_16588_9_not_null" CHECK (status IS NOT NULL); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "2200_16633_1_not_null" CHECK (issue_id IS NOT NULL); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "2200_16633_2_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "2200_16633_3_not_null" CHECK (timeframe IS NOT NULL); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "2200_16633_5_not_null" CHECK (severity IS NOT NULL); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "2200_16633_6_not_null" CHECK (issue_type IS NOT NULL); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "2200_16633_8_not_null" CHECK (resolved IS NOT NULL); +ALTER TABLE "data_quality_issue" ADD CONSTRAINT "2200_16633_9_not_null" CHECK (created_at IS NOT NULL); +ALTER TABLE "dataset" ADD CONSTRAINT "2200_16430_1_not_null" CHECK (dataset_id IS NOT NULL); +ALTER TABLE "dataset" ADD CONSTRAINT "2200_16430_2_not_null" CHECK (name IS NOT NULL); +ALTER TABLE "dataset" ADD CONSTRAINT "2200_16430_3_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "dataset" ADD CONSTRAINT "2200_16430_4_not_null" CHECK (feed_type IS NOT NULL); +ALTER TABLE "dataset" ADD CONSTRAINT "2200_16430_6_not_null" CHECK (created_at IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_10_not_null" CHECK (raw_source IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_11_not_null" CHECK (normalization_version IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_13_not_null" CHECK (quality_version IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_14_not_null" CHECK (dataset_version_hash IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_15_not_null" CHECK (data_as_of IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_17_not_null" CHECK (created_at IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_1_not_null" CHECK (dataset_version_id IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_23_not_null" CHECK (is_fixture IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_2_not_null" CHECK (dataset_id IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_3_not_null" CHECK (version_label IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_4_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_5_not_null" CHECK (feed_type IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_6_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_7_not_null" CHECK (timeframe IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_8_not_null" CHECK (start_utc IS NOT NULL); +ALTER TABLE "dataset_version" ADD CONSTRAINT "2200_16447_9_not_null" CHECK (end_utc IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_1_not_null" CHECK (derived_bar_id IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_24_not_null" CHECK (quality_status IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_26_not_null" CHECK (dataset_version_id IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_2_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_3_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_4_not_null" CHECK (feed_type IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_5_not_null" CHECK (price_basis IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_6_not_null" CHECK (timeframe IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_7_not_null" CHECK (ts_utc IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_8_not_null" CHECK (source_timeframe IS NOT NULL); +ALTER TABLE "derived_bar" ADD CONSTRAINT "2200_16508_9_not_null" CHECK (aggregation_version IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_1_not_null" CHECK (bar_id IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_25_not_null" CHECK (quality_status IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_28_not_null" CHECK (ingested_at IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_29_not_null" CHECK (dataset_version_id IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_2_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_3_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_4_not_null" CHECK (feed_type IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_5_not_null" CHECK (price_basis IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_6_not_null" CHECK (timeframe IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_7_not_null" CHECK (ts_utc IS NOT NULL); +ALTER TABLE "historical_bar" ADD CONSTRAINT "2200_16474_8_not_null" CHECK (raw_or_derived IS NOT NULL); +ALTER TABLE "historical_tick" ADD CONSTRAINT "2200_16539_10_not_null" CHECK (dataset_version_id IS NOT NULL); +ALTER TABLE "historical_tick" ADD CONSTRAINT "2200_16539_1_not_null" CHECK (tick_id IS NOT NULL); +ALTER TABLE "historical_tick" ADD CONSTRAINT "2200_16539_2_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "historical_tick" ADD CONSTRAINT "2200_16539_3_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "historical_tick" ADD CONSTRAINT "2200_16539_4_not_null" CHECK (feed_type IS NOT NULL); +ALTER TABLE "historical_tick" ADD CONSTRAINT "2200_16539_5_not_null" CHECK (ts_utc IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_10_not_null" CHECK (asset_class IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_11_not_null" CHECK (request_start IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_12_not_null" CHECK (request_end IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_13_not_null" CHECK (actual_start IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_14_not_null" CHECK (actual_end IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_15_not_null" CHECK (request_timestamp IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_16_not_null" CHECK (response_timestamp IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_17_not_null" CHECK (http_status IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_1_not_null" CHECK (provenance_id IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_20_not_null" CHECK (raw_payload_sha256 IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_21_not_null" CHECK (raw_content_length IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_22_not_null" CHECK (compression IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_24_not_null" CHECK (parser_version IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_25_not_null" CHECK (adapter_version IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_26_not_null" CHECK (normalization_version IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_27_not_null" CHECK (timezone_source IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_28_not_null" CHECK (timezone_target IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_29_not_null" CHECK (timezone_transform_version IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_2_not_null" CHECK (ingestion_run_id IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_30_not_null" CHECK (price_type IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_31_not_null" CHECK (granularity IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_32_not_null" CHECK (correction_status IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_33_not_null" CHECK (license_class IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_34_not_null" CHECK (software_git_commit IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_35_not_null" CHECK (software_image_id IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_37_not_null" CHECK (request_identity_hash IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_3_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_41_not_null" CHECK (created_at IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_4_not_null" CHECK (provider_name_snapshot IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_5_not_null" CHECK (provider_environment_class IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_6_not_null" CHECK (provider_dataset IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_7_not_null" CHECK (provider_feed IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_8_not_null" CHECK (provider_instrument_id IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "2200_16741_9_not_null" CHECK (canonical_instrument_id IS NOT NULL); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_actual_range" CHECK (((actual_end >= actual_start))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_compression" CHECK (((compression = ANY (ARRAY['none'::text, 'lzma'::text, 'gzip'::text, 'zstd'::text, 'deflate'::text, 'unknown'::text])))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_content_length" CHECK (((raw_content_length >= 0))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_correction" CHECK (((correction_status = ANY (ARRAY['ORIGINAL'::text, 'CORRECTED'::text, 'SUPERSEDED'::text, 'UNKNOWN'::text])))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_env_class" CHECK (((provider_environment_class = ANY (ARRAY['PROD'::text, 'SANDBOX'::text, 'TEST'::text, 'UNKNOWN'::text])))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_http_status" CHECK ((((http_status >= 100) AND (http_status <= 599)))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_license" CHECK (((license_class = ANY (ARRAY['UNKNOWN'::text, 'PRIVATE_INTERNAL'::text, 'INTERNAL_DERIVED_ALLOWED'::text, 'STORAGE_RESTRICTED'::text, 'REDISTRIBUTION_RESTRICTED'::text, 'EXPIRED'::text, 'REVOKED'::text])))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_price_type" CHECK (((price_type = ANY (ARRAY['bid'::text, 'ask'::text, 'mid'::text, 'bid_ask'::text, 'last'::text, 'unknown'::text])))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_sha256" CHECK (((raw_payload_sha256 ~ '^[0-9a-f]{64}$'::text))); +ALTER TABLE "ingestion_provenance" ADD CONSTRAINT "chk_prov_time_range" CHECK (((request_end >= request_start))); +ALTER TABLE "instrument" ADD CONSTRAINT "2200_16386_12_not_null" CHECK (active IS NOT NULL); +ALTER TABLE "instrument" ADD CONSTRAINT "2200_16386_13_not_null" CHECK (created_at IS NOT NULL); +ALTER TABLE "instrument" ADD CONSTRAINT "2200_16386_1_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "instrument" ADD CONSTRAINT "2200_16386_2_not_null" CHECK (symbol IS NOT NULL); +ALTER TABLE "instrument" ADD CONSTRAINT "2200_16386_3_not_null" CHECK (asset_class IS NOT NULL); +ALTER TABLE "market_calendar" ADD CONSTRAINT "2200_16667_12_not_null" CHECK (calendar_version IS NOT NULL); +ALTER TABLE "market_calendar" ADD CONSTRAINT "2200_16667_13_not_null" CHECK (created_at IS NOT NULL); +ALTER TABLE "market_calendar" ADD CONSTRAINT "2200_16667_1_not_null" CHECK (calendar_id IS NOT NULL); +ALTER TABLE "market_calendar" ADD CONSTRAINT "2200_16667_2_not_null" CHECK (calendar_name IS NOT NULL); +ALTER TABLE "market_calendar" ADD CONSTRAINT "2200_16667_3_not_null" CHECK (asset_class IS NOT NULL); +ALTER TABLE "market_calendar" ADD CONSTRAINT "2200_16667_5_not_null" CHECK (timezone IS NOT NULL); +ALTER TABLE "provider" ADD CONSTRAINT "2200_16399_1_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "provider" ADD CONSTRAINT "2200_16399_2_not_null" CHECK (provider_key IS NOT NULL); +ALTER TABLE "provider" ADD CONSTRAINT "2200_16399_3_not_null" CHECK (name IS NOT NULL); +ALTER TABLE "provider" ADD CONSTRAINT "2200_16399_4_not_null" CHECK (data_type IS NOT NULL); +ALTER TABLE "provider_instrument" ADD CONSTRAINT "2200_16409_1_not_null" CHECK (provider_id IS NOT NULL); +ALTER TABLE "provider_instrument" ADD CONSTRAINT "2200_16409_2_not_null" CHECK (instrument_id IS NOT NULL); +ALTER TABLE "provider_instrument" ADD CONSTRAINT "2200_16409_3_not_null" CHECK (provider_symbol IS NOT NULL); +ALTER TABLE "provider_instrument" ADD CONSTRAINT "2200_16409_6_not_null" CHECK (active IS NOT NULL); + +CREATE INDEX idx_bar_dsver ON public.historical_bar USING btree (dataset_version_id); +CREATE INDEX idx_bar_elig ON public.historical_bar USING btree (eligibility); +CREATE INDEX idx_bar_inst_tf_ts ON public.historical_bar USING btree (instrument_id, timeframe, ts_utc); +CREATE INDEX idx_bar_sess_ts ON public.historical_bar USING btree (session_state, instrument_id, ts_utc); +CREATE INDEX idx_bar_session ON public.historical_bar USING btree (session_state, session_phase); +CREATE INDEX idx_bar_techq ON public.historical_bar USING btree (technical_quality); +CREATE INDEX idx_derived_inst_tf_ts ON public.derived_bar USING btree (instrument_id, timeframe, ts_utc); +CREATE INDEX idx_historical_bar_market_quality ON public.historical_bar USING btree (instrument_id, market_quality); +CREATE INDEX idx_historical_bar_session_state ON public.historical_bar USING btree (instrument_id, session_state); +CREATE INDEX idx_prov_adapter_version ON public.ingestion_provenance USING btree (adapter_version); +CREATE INDEX idx_prov_instrument ON public.ingestion_provenance USING btree (canonical_instrument_id); +CREATE INDEX idx_prov_provider_feed ON public.ingestion_provenance USING btree (provider_id, provider_feed); +CREATE INDEX idx_prov_raw_sha ON public.ingestion_provenance USING btree (raw_payload_sha256); +CREATE INDEX idx_prov_request_identity ON public.ingestion_provenance USING btree (request_identity_hash); +CREATE INDEX idx_prov_time_range ON public.ingestion_provenance USING btree (request_start, request_end); +CREATE INDEX idx_tick_inst_ts ON public.historical_tick USING btree (instrument_id, ts_utc); diff --git a/notes/trading/system-docs/d1d2-schema-contract/tools/canonical_schema.py b/notes/trading/system-docs/d1d2-schema-contract/tools/canonical_schema.py new file mode 100644 index 0000000..c2e9272 --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/tools/canonical_schema.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +""" +D2 — canonical_schema.py +Deterministischer Schema-Kanonisierer + Fingerprint für das Historical V2 Subsystem. + +Liefert EINE autoritative Kanonisierungsfunktion, die aus einem Captured-Schema-Modell +(JSON, wie von capture_schema.py erzeugt) eine deterministische semantische +Serialisierung baut und daraus den SHA-256-Fingerprint berechnet. + +Kanonisierungsregeln (siehe Mission §7): +- Schemas/Tabellen alphabetisch +- Spalten nach ordinal_position +- Constraints deterministisch nach (type, name, content) +- Indexe deterministisch +- Whitespace/Identifier-Quoting normalisiert, aber keine semantischen Unterschiede weggewaschen + +Fingerprint-Coverage (§8): Tabellenexistenz, Spaltenname, ordinal_position, +Datentyp, Nullability, Default, Primary Key, UNIQUE, FK, CHECK, Index-Definitionen. +""" +import hashlib +import json + + +def _norm_whitespace(s): + """Normalisiere Whitespace; reduziere Wiederholungen, aber erhalte Wörter/Zeichen.""" + if s is None: + return None + return " ".join(str(s).split()) + + +def sorted_cols(columns): + """Spalten einer Tabelle, sortiert nach ordinal_position.""" + return sorted(columns, key=lambda c: (c.get("ordinal", 0), c.get("column", ""))) + + +def canonical_columns(columns): + """Spalten → deterministische Liste von Tuplen.""" + out = [] + for c in sorted_cols(columns): + out.append(( + c["column"], + int(c.get("ordinal", 0)), + _norm_whitespace(c.get("type")), + _norm_whitespace(c.get("udt")), + bool(c.get("nullable")), + _norm_whitespace(c.get("default")), + )) + return out + + +def canonical_constraints(constraints, kind): + """Constraints eines Typs (PRIMARY KEY, UNIQUE) → sortierte Liste.""" + out = [] + for con in constraints: + cols = tuple(c for c in con.get("columns") or []) + out.append(( + con.get("table", ""), + con.get("constraint", ""), + cols, + )) + return sorted(out, key=lambda x: (x[0], x[1], x[2])) + + +def canonical_fks(fks): + """FK → sortierte Liste inkl. ref_table und ref_columns.""" + out = [] + for fk in fks: + out.append(( + fk.get("table", ""), + fk.get("constraint", ""), + tuple(fk.get("columns") or []), + fk.get("ref_table", ""), + tuple(fk.get("ref_columns") or []), + )) + return sorted(out, key=lambda x: (x[0], x[1])) + + +def canonical_checks(checks): + """CHECK-Constraints → sortierte Liste mit normierter Definition. + + Auto-generierte PostgreSQL 'NOT NULL'-Checks (CONSTRAINT-Name endet auf + '_not_null', von PostgreSQL automatisch pro NOT-NULL-Spalte erzeugt) werden + AUSGESCHLOSSEN: sie sind redundant zu 'nullable' und ihre Definition + unterscheidet sich zwischen DBs (Production 'x IS NOT NULL' vs. Checker + '((x IS NOT NULL))') → semantisches Rauschen. Zuverlässige Erkennung NUR + über den Namenssuffix '_not_null'. Explizit benannte User-Checks + (chk_* etc.) bleiben erhalten. + """ + out = [] + for chk in checks: + name = chk.get("constraint", "") + if name.endswith("_not_null"): + continue + out.append(( + chk.get("table", ""), + name, + _norm_whitespace(chk.get("definition")) or "", + )) + return sorted(out, key=lambda x: (x[0], x[1], x[2])) + + +def canonical_indexes(indexes): + """Index-Definitionen → sortierte Liste mit normierter Definition.""" + out = [] + for idx in indexes: + out.append(( + idx.get("table", ""), + idx.get("index", ""), + _norm_whitespace(idx.get("definition")), + )) + return sorted(out, key=lambda x: (x[0], x[1], x[2])) + + +def canonical_sequences(sequences): + """Sequenzen → sortierte Liste (nur Existenz/Name).""" + return sorted(sequences or []) + + +def canonical_document(model): + """Baue die vollständige deterministische semantische Serialisierung.""" + tables = sorted(model.get("tables") or []) + cols_by_table = {} + for c in model.get("columns") or []: + cols_by_table.setdefault(c["table"], []).append(c) + + pks = canonical_constraints(model.get("primary_keys") or [], "PRIMARY KEY") + uniques = canonical_constraints(model.get("unique_constraints") or [], "UNIQUE") + fks = canonical_fks(model.get("foreign_keys") or []) + checks = canonical_checks(model.get("check_constraints") or []) + indexes = canonical_indexes(model.get("indexes") or []) + sequences = canonical_sequences(model.get("sequences") or []) + + doc = [] + doc.append("schema=public") + doc.append("sequences=" + "|".join(sequences)) + doc.append("tables=" + "|".join(tables)) + for t in tables: + doc.append(f"table:{t}:cols=" + ";".join( + f"{name}|{ordp}|{typ}|{udt}|{'n' if nul else 'y'}|{dflt}" + for (name, ordp, typ, udt, nul, dflt) in canonical_columns(cols_by_table.get(t, [])) + )) + doc.append("pk=" + ";".join( + f"{t}|{n}|{','.join(c)}" + for (t, n, c) in pks + )) + doc.append("unique=" + ";".join( + f"{t}|{n}|{','.join(c)}" + for (t, n, c) in uniques + )) + doc.append("fk=" + ";".join( + f"{t}|{n}|{','.join(c)}->{rt}|{','.join(rc)}" + for (t, n, c, rt, rc) in fks + )) + doc.append("check=" + ";".join( + f"{t}|{n}|{d}" + for (t, n, d) in checks + )) + doc.append("index=" + ";".join( + f"{t}|{n}|{d}" + for (t, n, d) in indexes + )) + return "\n".join(doc) + + +def fingerprint(model): + """SHA-256 über die kanonische Serialisierung.""" + doc = canonical_document(model) + return hashlib.sha256(doc.encode("utf-8")).hexdigest(), doc + + +def load_model(path): + """Lade ein Captured-Schema-Modell (JSON).""" + with open(path) as f: + return json.load(f) diff --git a/notes/trading/system-docs/d1d2-schema-contract/tools/capture_schema.py b/notes/trading/system-docs/d1d2-schema-contract/tools/capture_schema.py new file mode 100644 index 0000000..7a39a65 --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/tools/capture_schema.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +""" +D2 — capture_schema.py +Liest Schema-Metadaten (read-only) von einer DB und erzeugt das kanonische Modell-JSON. + +Quellenmodus: Erwartet eine Datei mit den 7 JSON-Aggregaten aus dem Capture-SQL +(der read-only psql-Ausgabe), ODER ein bereits geparstes Modell-JSON. + +Usage: + capture_schema.py --from-capture --out + capture_schema.py --from-model --out # Normalisierung + +Der DB-Zugriff selbst erfolgt ausschließlich über das read-only Capture-SQL +(BEGIN TRANSACTION READ ONLY). Dieses Tool verarbeitet nur die Ergebnisse. +""" +import json +import sys +import argparse + +AGG_NAMES = ["columns", "primary_keys", "unique_constraints", + "foreign_keys", "check_constraints", "indexes", "tables", + "sequences"] + + +def strip_psql_noise(text): + """Entferne psql-Kontrollzeilen (BEGIN/on/COMMIT/leer/--).""" + out = [] + for line in text.splitlines(): + s = line.strip() + if s and s not in ("BEGIN", "on", "COMMIT") and not s.startswith("--"): + out.append(s) + return out + + +def parse_raw_capture(text): + """Extrahiere die N JSON-Aggregate aus der psql-Ausgabe. + + psql splittet große JSON-Arrays über mehrere Zeilen; daher wird nicht + zeilenzählend, sondern per JSON-Streaming (raw_decode) geparst. + """ + data = "\n".join(strip_psql_noise(text)) + decoder = json.JSONDecoder() + aggs = [] + i = 0 + n = len(data) + while i < n and len(aggs) < len(AGG_NAMES): + while i < n and data[i] in " \t\r\n": + i += 1 + if i >= n: + break + if data[i] not in "[{": + # non-JSON noise (z.B. Fehlermeldung) -> nächste Position + i += 1 + continue + try: + val, end = decoder.raw_decode(data, i) + except json.JSONDecodeError as e: + raise SystemExit(f"FEHLER: JSON-Parse bei {i}: {e}") + aggs.append(val if val is not None else []) + i = end + if len(aggs) != len(AGG_NAMES): + raise SystemExit( + f"FEHLER: erwartete {len(AGG_NAMES)} JSON-Aggregate, fand {len(aggs)}") + return dict(zip(AGG_NAMES, aggs)) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--from-capture", help="Rohe read-only psql-Capture-Datei (7 Aggregate)") + ap.add_argument("--from-model", help="Bereits geparstes Modell-JSON") + ap.add_argument("--out", required=True, help="Ziel-Modell-JSON") + args = ap.parse_args() + + if args.from_capture: + with open(args.from_capture) as f: + model = parse_raw_capture(f.read()) + elif args.from_model: + with open(args.from_model) as f: + model = json.load(f) + else: + raise SystemExit("FEHLER: --from-capture oder --from-model erforderlich") + + # Konsistenz: columns/tables müssen übereinstimmen + col_tables = sorted({c["table"] for c in model["columns"]}) + model["tables"] = sorted(model.get("tables") or col_tables) + + with open(args.out, "w") as f: + json.dump(model, f, indent=2, sort_keys=True) + print(f"Modell geschrieben: {args.out}") + print(f"Tabellen: {len(model['tables'])} | Spalten: {len(model['columns'])}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/notes/trading/system-docs/d1d2-schema-contract/tools/compare_schema.py b/notes/trading/system-docs/d1d2-schema-contract/tools/compare_schema.py new file mode 100644 index 0000000..91f0bf0 --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/tools/compare_schema.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python3 +""" +D2 — compare_schema.py +Vergleicht zwei Schema-Modelle (Soll = kanonischer L0-Contract, Ist = tatsächlich). + +Semantische Diff-Dimensionen (§12): + fehlende/extras Tabellen, Spalten, Typ-Mismatches, Nullable-Mismatches, + Default-Mismatches, PK, UNIQUE, FK, CHECK, Index-Mismatches. + +Fail-closed: exit-Nonzero bei beliebigem semantischem Mismatch. +Acceptance: alle Mismatch-Counts == 0. +""" +import sys +import json +import argparse +from canonical_schema import (canonical_columns, canonical_constraints, + canonical_fks, canonical_checks, canonical_indexes) + + +def diff_counts(actual, expected): + """Liefert dict mit Mismatch-Counts. 0 = keine.""" + counts = { + "missing_tables": 0, "extra_tables": 0, + "missing_columns": 0, "extra_columns": 0, + "type_mismatch": 0, "nullable_mismatch": 0, "default_mismatch": 0, + "pk_mismatch": 0, "unique_mismatch": 0, "fk_mismatch": 0, + "check_mismatch": 0, "index_mismatch": 0, + } + # Tabellen + a_tbl = set((actual.get("tables") or [])) + e_tbl = set((expected.get("tables") or [])) + counts["missing_tables"] = len(e_tbl - a_tbl) + counts["extra_tables"] = len(a_tbl - e_tbl) + + # Spalten je Tabelle + a_cols = {} + for c in actual.get("columns") or []: + a_cols.setdefault(c["table"], []).append(c) + e_cols = {} + for c in expected.get("columns") or []: + e_cols.setdefault(c["table"], []).append(c) + for tbl in e_tbl: + ec = {c["column"]: c for c in e_cols.get(tbl, [])} + ac = {c["column"]: c for c in a_cols.get(tbl, [])} + for cname, cexp in ec.items(): + if cname not in ac: + counts["missing_columns"] += 1 + continue + cact = ac[cname] + if _n(cact.get("type")) != _n(cexp.get("type")): + counts["type_mismatch"] += 1 + if bool(cact.get("nullable")) != bool(cexp.get("nullable")): + counts["nullable_mismatch"] += 1 + if _n(cact.get("default")) != _n(cexp.get("default")): + counts["default_mismatch"] += 1 + for cname in ac: + if cname not in ec: + counts["extra_columns"] += 1 + + # Constraints + if canonical_constraints(actual.get("primary_keys") or [], "PK") != \ + canonical_constraints(expected.get("primary_keys") or [], "PK"): + counts["pk_mismatch"] += 1 + if canonical_constraints(actual.get("unique_constraints") or [], "UNIQUE") != \ + canonical_constraints(expected.get("unique_constraints") or [], "UNIQUE"): + counts["unique_mismatch"] += 1 + if canonical_fks(actual.get("foreign_keys") or []) != \ + canonical_fks(expected.get("foreign_keys") or []): + counts["fk_mismatch"] += 1 + if canonical_checks(actual.get("check_constraints") or []) != \ + canonical_checks(expected.get("check_constraints") or []): + counts["check_mismatch"] += 1 + if canonical_indexes(actual.get("indexes") or []) != \ + canonical_indexes(expected.get("indexes") or []): + counts["index_mismatch"] += 1 + + return counts + + +def _n(x): + return None if x is None else " ".join(str(x).split()) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("expected", help="Kanonisches L0-Contract-Modell") + ap.add_argument("actual", help="Tatsächlich gecaptures Modell") + args = ap.parse_args() + + with open(args.expected) as f: + expected = json.load(f) + with open(args.actual) as f: + actual = json.load(f) + + counts = diff_counts(actual, expected) + total = sum(counts.values()) + print(json.dumps(counts, indent=2)) + print(f"TOTAL_MISMATCH={total}") + + if total == 0: + print("PASS: Semantic diff = 0") + return 0 + print("FAIL: semantic drift detected", file=sys.stderr) + return 1 # FAIL CLOSED + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/notes/trading/system-docs/d1d2-schema-contract/tools/fingerprint_schema.py b/notes/trading/system-docs/d1d2-schema-contract/tools/fingerprint_schema.py new file mode 100644 index 0000000..838c00b --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/tools/fingerprint_schema.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 +""" +D2 — fingerprint_schema.py +Deterministischer SHA-256 über ein Captured-Schema-Modell. + +Usage: + fingerprint_schema.py + → schreibt nur den Hex-Digest auf stdout (fail-closed: exit 0 bei Erfolg) + fingerprint_schema.py --expect + → exit 0 wenn MATCH, sonst exit 1 (FAIL CLOSED) + +Der Fingerprint deckt ab: Tabellenexistenz, Spaltenname, ordinal_position, +Datentyp, Nullability, Default, PK, UNIQUE, FK, CHECK, Index-Definitionen (§8). +""" +import sys +import argparse +from canonical_schema import fingerprint, load_model + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("model") + ap.add_argument("--expect", default=None, help="Erwarteter Digest (fail-closed Vergleich)") + ap.add_argument("--no-hash", action="store_true", help="Nur kanonische Serialisierung ausgeben") + args = ap.parse_args() + + model = load_model(args.model) + digest, doc = fingerprint(model) + + if args.no_hash: + print(doc) + return 0 + + if args.expect: + if digest == args.expect: + print(f"MATCH {digest}") + return 0 + else: + print(f"MISMATCH expected={args.expect} actual={digest}", file=sys.stderr) + return 1 # FAIL CLOSED + + print(digest) + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/notes/trading/system-docs/d1d2-schema-contract/tools/gen_l0_sql.py b/notes/trading/system-docs/d1d2-schema-contract/tools/gen_l0_sql.py new file mode 100644 index 0000000..74ac50e --- /dev/null +++ b/notes/trading/system-docs/d1d2-schema-contract/tools/gen_l0_sql.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +""" +D2 — gen_l0_sql.py +Erzeugt den kanonischen L0-SQL-Contract (schema-only) aus einem Captured-Schema-Modell. + +Repräsentiert die aktuelle kanonische Production-Truth. Enthält KEINE: + data rows, credentials, volatile timestamps, container IDs, host paths, secrets. +Kein CREATE DATABASE, keine Grant/GRANT-relevanten Owner, keine Umgebungs-Sequenzen. + +Semantische Overrides (§4) werden als Kommentar-Blöcke dokumentiert: + last_successful_chunk = timestamp with time zone (Owner-canonical) + interrupt_reason = text (preserved current contract) + technical_quality = text nullable default 'VALID' +""" +import json +import sys +import argparse + +TYPE_MAP = { + 'bigint': 'bigint', 'integer': 'integer', 'smallint': 'smallint', + 'numeric': 'numeric', 'timestamp with time zone': 'timestamp with time zone', + 'boolean': 'boolean', 'text': 'text', 'date': 'date', 'double precision': 'double precision', + 'jsonb': 'jsonb', 'real': 'real', 'character varying': 'character varying', +} + + +def ident(s): + return '"' + str(s).replace('"', '""') + '"' + + +def col_def(c): + typ = TYPE_MAP.get(c.get('type'), c.get('udt', c.get('type', 'text'))) + nullable = '' if not c.get('nullable') else '' + notnull = ' NOT NULL' if not c.get('nullable') else '' + dflt = c.get('default') + default_part = '' + if dflt: + default_part = ' DEFAULT ' + dflt + return f" {ident(c['column'])} {typ}{notnull}{default_part}" + + +def build_sql(model, dbname="historical"): + out = [] + out.append("-- ============================================================") + out.append(f"-- CANONICAL CURRENT PRODUCTION SCHEMA CONTRACT (L0)") + out.append(f"-- db: {dbname} · schema: public") + out.append("-- Auto-generated by gen_l0_sql.py from read-only capture") + out.append("-- Modus: CURRENT VERIFIED PRODUCTION TRUTH — NICHT historische Migration") + out.append("-- ============================================================") + out.append("") + out.append("-- SEMANTIC OVERRIDES (Owner-Canonical)") + out.append("-- last_successful_chunk = timestamp with time zone (Production + Owner decision)") + out.append("-- interrupt_reason = text · PRESERVED CURRENT CONTRACT · origin unknown · do not remove") + out.append("-- technical_quality = text · nullable · default 'VALID' · historical provenance debt OPEN") + out.append("") + # Sequenzen (für nextval-Defaults) + for seq in sorted(model.get("sequences") or []): + out.append(f"CREATE SEQUENCE IF NOT EXISTS {ident(seq)};") + if model.get("sequences"): + out.append("") + + tables = sorted(model.get("tables") or []) + cols_by_table = {} + for c in model.get("columns") or []: + cols_by_table.setdefault(c["table"], []).append(c) + + pks = {} + for pk in model.get("primary_keys") or []: + cols = sorted(pk.get("columns") or [], key=lambda x: 0) + pks[pk["table"]] = [pk.get("columns") or []] + + for t in tables: + cols = sorted(cols_by_table.get(t, []), key=lambda c: c.get("ordinal", 0)) + out.append(f"-- Table: {t} ({len(cols)} cols)") + out.append(f"CREATE TABLE IF NOT EXISTS {ident(t)} (") + body_lines = [col_def(c) for c in cols] + out.append(",\n".join(body_lines)) + out.append(");") + out.append("") + + # PKs + for t in tables: + for pk in model.get("primary_keys") or []: + if pk["table"] == t: + colstr = ", ".join(ident(c) for c in pk.get("columns") or []) + out.append(f"ALTER TABLE {ident(t)} ADD CONSTRAINT {ident(pk['constraint'])} PRIMARY KEY ({colstr});") + out.append("") + + # UNIQUE + for uq in sorted(model.get("unique_constraints") or [], key=lambda x: x["table"]): + colstr = ", ".join(ident(c) for c in uq.get("columns") or []) + out.append(f"ALTER TABLE {ident(uq['table'])} ADD CONSTRAINT {ident(uq['constraint'])} UNIQUE ({colstr});") + out.append("") + + # FK + for fk in sorted(model.get("foreign_keys") or [], key=lambda x: x["table"]): + colstr = ", ".join(ident(c) for c in fk.get("columns") or []) + rcolstr = ", ".join(ident(c) for c in fk.get("ref_columns") or []) + out.append(f"ALTER TABLE {ident(fk['table'])} ADD CONSTRAINT {ident(fk['constraint'])} FOREIGN KEY ({colstr}) REFERENCES {ident(fk['ref_table'])} ({rcolstr});") + out.append("") + + # CHECK - semantische Definition + for chk in sorted(model.get("check_constraints") or [], key=lambda x: (x["table"], x["constraint"])): + out.append(f"ALTER TABLE {ident(chk['table'])} ADD CONSTRAINT {ident(chk['constraint'])} CHECK ({chk.get('definition','')});") + out.append("") + + # Indexe (non-PK/UNIQUE) + idx_set = set() + for pk in model.get("primary_keys") or []: + idx_set.add(pk["constraint"]) + for uq in model.get("unique_constraints") or []: + idx_set.add(uq["constraint"]) + for idx in sorted(model.get("indexes") or [], key=lambda x: x["index"]): + if idx["index"] in idx_set: + continue + out.append(f"{idx['definition']};") + out.append("") + return "\n".join(out) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("model") + ap.add_argument("--out", required=True) + args = ap.parse_args() + with open(args.model) as f: + model = json.load(f) + sql = build_sql(model) + with open(args.out, "w") as f: + f.write(sql) + print(f"L0 SQL-Contract geschrieben: {args.out} ({len(sql)} B)") + return 0 + + +if __name__ == "__main__": + sys.exit(main())