跳轉至

組態參考

Provisa 透過 YAML 檔案組態(預設:config/provisa.yaml)。(REQ-528)

數據來源

sources:
  - id: sales-pg           # unique identifier
    type: postgresql
    host: postgres
    port: 5432
    database: provisa
    username: provisa
    password: ${env:PG_PASSWORD}  # secret resolution
    pool_min: 1
    pool_max: 5
    use_pgbouncer: false
    pgbouncer_port: 6432

所有數據來源共用一組通用欄位。[tool-verified: provisa/core/models.py:129-212]

欄位 預設 備註
id 必填 英數字、連字號、底線
type 必填 見下表
host "" 主機名稱或 IP
port 0 0 表示由各連接器提供自己的預設值 — 沒有集中的預設連接埠對應表
database ""
username ""
password "" 支援 ${env:VAR}${secret:NAME} 認證參照 — 見密鑰
path null 檔案型數據來源的檔案路徑或 URI
base_url null API 數據來源的基底 URL
pool_min / pool_max 1 / 5 連線集區上下限
cache_enabled true 切換此數據來源所有表的快取
cache_ttl null 秒;null 沿用全域預設
federation_hints {} 各連接器的延伸參數(dict[str,str]);見下方類型參考。REQ-281
mapping {} redis、elasticsearch、prometheus 的對應 DSL。REQ-251
allowed_domains [] 將此數據來源限制於特定網域 ID;空值 = 不限制
description ""

支援的數據來源類型 [tool-verified: provisa/core/models.py:36-101]

類型 連線方式 備註
RDBMS
postgresql host/port Asyncpg 集區;透過 use_pgbouncer 選用 PgBouncer
mysql host/port
mariadb host/port
singlestore host/port
sqlserver host/port
oracle host/port
firebird host + path(DB 檔案) DuckDB firebird 社群擴充功能 (REQ-899)
duckdb host/port
cockroachdb host/port 沿用 PostgreSQL 驅動程式/方言 (REQ-950)
yugabytedb host/port 沿用 PostgreSQL 驅動程式/方言 (REQ-950)
greenplum host/port 沿用 PostgreSQL 驅動程式/方言 (REQ-950)
tidb host/port 沿用 MySQL 驅動程式/方言 (REQ-950)
Cloud DW
snowflake host/port + federation_hints hints 中必須有 account
bigquery federation_hints 必須有 project;透過 GOOGLE_APPLICATION_CREDENTIALS 驗證
databricks host + federation_hints hints 中必須有 http_path
fabric 環境變數或 PROVISA_ENGINE_URL 透過 TDS 的 T-SQL,Azure AD 驗證
synapse 環境變數或 PROVISA_ENGINE_URL 透過 TDS 的 T-SQL,Azure AD 驗證
redshift host/port
OLAP
clickhouse host/port + federation_hints secure 提示切換 TLS;連接埠預設 8123/8443
elasticsearch host/port + mapping DSL
pinot host/port Controller REST 端點
druid host/port Broker Avatica 端點
exasol host/port
Data Lake
delta_lake path(表 URI) DuckDB delta_scan;物件儲存體存取透過 federation_hints
iceberg path(表 URI) DuckDB iceberg_scan;物件儲存體存取透過 federation_hints
hudi path(表 URI) ClickHouse Hudi 引擎,零複製 (REQ-1178)
hive host/port(metastore) + mapping.storage 儲存體後端位於 mapping["storage"]:hadoop/hdfs/local/s3/azure/adls
hive_s3 host/port(metastore) + mapping S3 鍵 獨立類型;一律使用 S3 儲存體 (REQ-229)
NoSQL
mongodb host/port 純連線欄位;不使用對應 DSL
cassandra host/port 純連線欄位;不使用對應 DSL
redis host/port + mapping DSL
Streaming
kafka 僅供註冊 真正的組態位於 kafka_sources[];見下方 §Kafka
websocket host/port/path + federation_hints 外部 WebSocket 摘要
rss host/port/path + federation_hints RSS 2.0 / Atom 摘要
Graph/Semantic
neo4j [UNVERIFIED end-to-end mapping]
sparql [UNVERIFIED end-to-end mapping]
File
sqlite path 一律經由引擎路由(無直接集區)
csv path
parquet path
files path(目錄) Glob 爬取器;將 CSV/Parquet/XLSX/JSON 呈現為表
API/Remote
google_sheets federation_hints.spreadsheet_id
prometheus host/port 或 mapping.url + mapping DSL
graphql_remote base_url + 選用 mapping 標頭、轉送用戶端標頭、逾時皆在 mapping
openapi base_url
grpc_remote [UNVERIFIED end-to-end mapping]
airport base_url(Flight 位置) DuckDB airport 擴充功能 (REQ-899)
ingest 推送接收器 外部服務 POST JSON 事件
SaaS
sharepoint base_urlhost + mapping 透過 mapping.auth_type 驗證
splunk host/portbase_url + mapping
GovData
govdata subject + domain_id 獨立的 GovDataSource 模型;見下方 §GovData
Data Quality
soda 指向 Provisa pgwire 的 host/port 需要 soda extra;Elastic License 2.0,僅限自行託管 (REQ-1443)
great_expectations 指向 Provisa pgwire 的 host/port 需要 gx extra;Apache 2.0 (REQ-1443)

數據來源類型參考

組態不夠直觀的類型各有一段簡短說明。RDBMS 類型(postgresql、mysql 等)只用到上述通用欄位 — 不需額外章節。

GovData [tool-verified: provisa/core/models.py:953-983]

govdata 數據來源使用獨立的頂層模型 GovDataSource,而非通用的 Source。(REQ-540) 存取按主題分組劃分。

sources:
  - id: federal-data
    type: govdata
    subject: COMMERCE
    domain_id: federal-analytics
    api_key: ${env:GOVDATA_API_KEY}   # optional
    start_year: 2020                   # optional year filter
    end_year: 2024                     # optional year filter

每個主題對應一個或多個 GovData 結構描述。以某主題組態 govdata 數據來源,會自動公開該主題的所有結構描述。(REQ-540)

主題 結構描述
COMMERCE sec, patents
ECONOMY econ, econ_reference
EDUCATION census, edu
HEALTH health
CYBER cyber_threat, cyber_vuln
PUBLIC_SAFETY crime
ENVIRONMENT lands
WEATHER weather
ENERGY energy
GOVERNMENT fedregister, fec

refgeo 結構描述一律作為連結結構描述納入 — 不可組態,也未列於上表。(REQ-541) 使用主題 ALL 可授予所有結構描述的存取權。[tool-verified: provisa/core/models.py:961-963]

Kafka [tool-verified: provisa/federation/trino_connectors.py:497-502, provisa/api/app_loaders.py:113-118]

sources: 中的 kafka 項目僅供註冊。其連接器的 details() 回傳 {} — 真正的組態位於頂層 kafka_sources[] 區塊,而非 sources: 項目。Kafka 一律是 VIRTUAL_SOURCE(經由引擎路由;無直接集區)。[tool-verified: provisa/transpiler/router.py:44-63]

kafka_sources:
  - id: event-stream
    bootstrap_servers: kafka:9092
    schema_registry_url: http://schema-registry:8081  # optional
    topics:
      - id: order-created
        topic: orders.events
        default_window: 1h          # auto-injected time bound
        schema_source: manual       # manual, registry, or sample
        value_format: json
        discriminator:              # filter shared topic by message type
          field: event_type
          value: OrderCreated
        columns:
          - name: event_type
            type: varchar
          - name: order_id
            type: integer
          - name: amount
            type: double
          - name: metadata
            type: varchar           # raw JSON for complex nested data
      - id: order-shipped
        topic: orders.events        # same physical topic
        default_window: 1h
        discriminator:
          field: event_type
          value: OrderShipped
        columns:
          - name: event_type
            type: varchar
          - name: order_id
            type: integer
          - name: shipped_at
            type: timestamp

時間窗default_window 將每個查詢限制在近期的一段時間內,避免對高流量主題進行無邊界讀取。(REQ-148) 格式:1h30m7d60s。預設為 1h。自動注入為 WHERE _timestamp >= CURRENT_TIMESTAMP - INTERVAL '1' HOUR。用戶端可在 GraphQL where 引數中以自己的 _timestamp 篩選條件覆寫。

判別器 — 多個主題組態可指向同一個實體 Kafka 主題但使用不同的 discriminator 值,產生各自獨立的 GraphQL 類型。(REQ-149) 判別器會自動注入為 WHERE 子句。

結構描述來源

行為
registry 從 Confluent Schema Registry 取得結構描述
manual 在組態中內嵌定義欄位(不需 Schema Registry)
sample 從樣本訊息自動探索

Snowflake [tool-verified: provisa/executor/drivers/snowflake.py:48-62]

federation_hints 中必須有 accountwarehouseroleschema 為選用。

sources:
  - id: my-snowflake
    type: snowflake
    host: org.snowflakecomputing.com
    username: svc_provisa
    password: ${env:SNOWFLAKE_PASSWORD}
    database: MY_DB
    federation_hints:
      account: myorg-myaccount     # required
      warehouse: COMPUTE_WH
      role: PROVISA_ROLE
      schema: PUBLIC               # remote schema override

Databricks [tool-verified: provisa/executor/drivers/databricks.py:34-52]

federation_hints 中必須有 http_pathpassword 攜帶個人存取權杖。catalog 為選用(由 SQL/hints 攜帶,不在 database 欄位)。

sources:
  - id: my-databricks
    type: databricks
    host: my-workspace.azuredatabricks.net
    password: ${env:DATABRICKS_TOKEN}
    federation_hints:
      http_path: /sql/1.0/warehouses/xxxx   # required
      catalog: my_unity_catalog              # optional

BigQuery [tool-verified: provisa/federation/connector_duckdb.py:238]

federation_hints 中必須有 project。驗證使用 GOOGLE_APPLICATION_CREDENTIALS(服務帳戶金鑰檔案的路徑)或引擎環境中的應用程式預設認證。

sources:
  - id: my-bigquery
    type: bigquery
    federation_hints:
      project: my-gcp-project     # required

Fabric / Synapse [tool-verified: provisa/core/models.py:56-57]

兩者皆使用透過 TDS 的 T-SQL 搭配 Azure AD 驗證。以 az login(開發者)或受控識別(生產環境)進行驗證 — 引擎透過 azure-identityDefaultAzureCredential 讀取認證。連線詳細資料來自環境變數:FABRIC_SQL_SERVER / FABRIC_DATABASE(Fabric)或 SYNAPSE_SQL_SERVER / SYNAPSE_DATABASE(Synapse),或透過 PROVISA_ENGINE_URL

sources:
  - id: my-fabric
    type: fabric
    # host/database read from FABRIC_SQL_SERVER / FABRIC_DATABASE when not set here

ClickHouse [tool-verified: provisa/executor/drivers/clickhouse.py:49-59]

federation_hints 中的 secure 會在 HTTP 介面上啟用 TLS。連接埠預設為 8123(純文字)或 8443(當 secure: "true")。federation_hints 中的 schema 會覆寫遠端結構描述。[tool-verified: provisa/federation/connector_duckdb.py:378-379]

sources:
  - id: my-clickhouse
    type: clickhouse
    host: ch.example.com
    password: ${env:CLICKHOUSE_PASSWORD}
    federation_hints:
      secure: "true"    # uses port 8443; omit to use 8123
      schema: analytics

Delta Lake / Iceberg [tool-verified: provisa/federation/connector_duckdb.py:291-327]

path 是表的 URI(S3、GCS、ADLS 或本機)。物件儲存體存取需要 federation_hints 認證。若使用 Cloudflare R2,請加上 account_id

sources:
  - id: events-delta
    type: delta_lake
    path: s3://my-bucket/data/events
    federation_hints:
      access_key_id: ${env:S3_ACCESS_KEY}
      secret_access_key: ${env:S3_SECRET}

  - id: r2-parquet
    type: parquet
    path: s3://my-bucket/data/events.parquet
    federation_hints:
      access_key_id: ${env:R2_ACCESS_KEY}
      secret_access_key: ${env:R2_SECRET}
      account_id: ${env:R2_ACCOUNT_ID}   # Cloudflare R2 account (S3-compatible)

Hive / Hive S3 [tool-verified: provisa/federation/trino_connectors.py:244-363]

hostport 指向 Hive Thrift metastore(預設連接埠 9083)。對 hive 而言,設定 mapping["storage"] 以選擇物件儲存體後端。缺少必要的鍵會明確失敗 — 沒有後備值。[tool-verified: provisa/federation/trino_connectors.py:328-331]

hive_s3 是一個獨立類型,一律宣告 S3 儲存體 (REQ-229);不需 mapping.storage

sources:
  - id: hive-s3-lake
    type: hive
    host: metastore.internal
    port: 9083
    mapping:
      storage: s3
      endpoint: https://s3.us-east-1.amazonaws.com
      access_key_id: ${env:AWS_ACCESS_KEY_ID}
      secret_access_key: ${env:AWS_SECRET_ACCESS_KEY}
      region: us-east-1
      path_style: true           # required for MinIO and non-AWS S3-compatible endpoints

  - id: hive-adls-lake
    type: hive
    host: metastore.internal
    port: 9083
    mapping:
      storage: adls
      storage_account: mystorageaccount
      access_key: ${env:ADLS_ACCESS_KEY}
      # sas_token: ${env:ADLS_SAS_TOKEN}   # alternative to access_key

mapping.storage 可接受的值:hadoop(預設)、hdfslocals3azureadls。S3 對應鍵:endpointaccess_key_idsecret_access_keyregionpath_style。ADLS 對應鍵:storage_accountaccess_keysas_token

Redis [tool-verified: provisa/core/trino_catalog_files.py:54-75]

使用 mapping DSL。mongodbcassandra 使用純連線欄位,不使用對應 DSL。

sources:
  - id: my-redis
    type: redis
    host: redis.internal
    port: 6379
    password: ${env:REDIS_PASSWORD}
    mapping:
      tables:
        - name: sessions
          key_pattern: "sessions:*"
          key_column: key           # default "key"
          value_type: hash          # hash | string | zset | list; default hash
          columns:
            - name: user_id
              data_type: VARCHAR
              field: user_id        # Redis hash field name
            - name: expires_at
              data_type: BIGINT
              field: expires_at

Elasticsearch [tool-verified: provisa/core/trino_catalog_files.py:78-104]

sources:
  - id: my-es
    type: elasticsearch
    host: es.internal
    port: 9200
    username: elastic
    password: ${env:ES_PASSWORD}
    mapping:
      tls: true
      tables:
        - name: logs
          index: app-logs-*
          discover: false
          columns:
            - name: timestamp
              data_type: TIMESTAMP
              path: "@timestamp"
            - name: level
              data_type: VARCHAR
              path: level
            - name: message
              data_type: VARCHAR
              path: message

Prometheus [tool-verified: provisa/core/trino_catalog_files.py:107-124]

mapping.urlhost:port 同時存在時,前者優先。

sources:
  - id: my-prometheus
    type: prometheus
    mapping:
      url: http://prometheus.internal:9090
      tables:
        - name: http_requests
          metric: http_requests_total
          labels_as_columns: [method, status, handler]
          value_column: value      # default "value"
          default_range: 1h        # default "1h"

Google Sheets [tool-verified: provisa/federation/connector_duckdb.py:273-275]

federation_hints 中必須有 spreadsheet_id。驗證使用在附加時佈建的 DuckDB gsheet SECRET。

sources:
  - id: my-sheet
    type: google_sheets
    federation_hints:
      spreadsheet_id: 1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms

檔案數據來源(csv / parquet / sqlite / files)

必須有 pathfiles 會爬取目錄中的 CSV、Parquet、XLSX 與 JSON 檔案,將每個檔案呈現為一個表。所有檔案型數據來源都是 VIRTUAL(經由引擎路由;無直接集區)。[tool-verified: provisa/transpiler/router.py:44-48]

sources:
  - id: orders-csv
    type: csv
    path: /data/orders.csv

  - id: data-lake-dir
    type: files
    path: /data/lake/         # directory; each file becomes a table

API/遠端數據來源

openapi — 將 base_url 設為 OpenAPI 基底 URL。結構描述探索會在啟動時讀取 OpenAPI 規格。

sources:
  - id: payment-api
    type: openapi
    base_url: https://api.payments.example.com/v1

graphql_remote — 設定 base_url。選用的 mapping 鍵:headers(靜態標頭字典)、forward_client_headers(bool)、timeout_seconds(int)。[tool-verified: provisa/hasura_v2/mapper.py:129-152]

sources:
  - id: orders-gql
    type: graphql_remote
    base_url: https://orders.internal/graphql
    mapping:
      headers:
        X-Api-Key: ${env:ORDERS_API_KEY}
      forward_client_headers: true
      timeout_seconds: 30

airportbase_url 是 Arrow Flight 伺服器位置。DuckDB airport 擴充功能 (REQ-899)。[tool-verified: provisa/federation/connector_duckdb.py:285-288]

sources:
  - id: flight-source
    type: airport
    base_url: grpc://flight.internal:8815

websocket / rss — 使用 hostportpathfederation_hints。[tool-verified: provisa/api/data/subscribe.py:85-129]

sources:
  - id: market-feed
    type: websocket
    host: feed.example.com
    port: 443
    path: /ws/v1
    federation_hints:
      use_ssl: "true"
      subscribe_payload: '{"action":"subscribe","channels":["ticker"]}'
      event_path: data

  - id: news-rss
    type: rss
    host: feeds.example.com
    port: 443
    path: /rss/latest
    federation_hints:
      use_ssl: "true"
      poll_interval: "300"      # seconds
      # feed_url: https://...  # overrides host/port/path when set

sharepoint [tool-verified: provisa/federation/trino_connectors.py:394-423]

sources:
  - id: my-sharepoint
    type: sharepoint
    base_url: https://myorg.sharepoint.com/sites/data
    username: ${env:SP_CLIENT_ID}
    password: ${env:SP_CLIENT_SECRET}
    database: ${env:SP_TENANT_ID}
    mapping:
      auth_type: CLIENT_CREDENTIALS   # default
      # certificate_path: /path/to/cert.pem
      # certificate_password: ${env:CERT_PASSWORD}

splunk [tool-verified: provisa/federation/trino_connectors.py:426-457]

sources:
  - id: my-splunk
    type: splunk
    host: splunk.internal
    port: 8089
    password: ${env:SPLUNK_TOKEN}
    database: search           # Splunk app name (optional)
    mapping:
      use_token: true          # default; false = username/password auth
      datamodel_filter: ""     # optional Splunk Data Model filter
      disable_ssl_validation: false

數據品質檢查器(soda / great_expectations)

[tool-verified: provisa/dq/registration.py, provisa/events/source_loader.py make_dq_loader]

檢查器數據來源指向 Provisa 自己的 pgwire 端點,因此單一個 postgres 驅動程式即可掃描以 Snowflake 或 Iceberg 為底的表的聯邦檢視。掃描身分是宣告出來的,不是繼承來的 — 原則套用於該連線,而經過篩選的資料列集合不得產生一項悄悄通過的檢查。連線鍵來自 mappinghostportdatabaseuserpassword

sources:
  - id: dq
    type: soda                 # or great_expectations
    domain_id: sales-analytics
    mapping:
      host: localhost
      port: 5439               # Provisa's pgwire endpoint
      database: provisa
      user: dq_scanner
      password: ${env:PROVISA_DQ_PASSWORD}

每個結果表都帶有 dq_contract — 逐字保留的 Soda 合約 YAML 或 Great Expectations 套件 JSON。欄位、水位與晉升皆由它衍生;完整衍生方式見數據品質檢查器

安裝期選擇。 檢查器並未連結進來 — 掃描在子解譯器中執行,而程式庫只在操作者指名時才安裝。每條安裝路徑(install.shpackaging/linux/first-launch.sh,以及 macOS 精靈透過 PROVISA_DQ_CHECKER)都會把選擇寫入 ~/.provisa/config.yaml

dq_checker: none        # none | soda | gx

scripts/provisa 讀取該鍵並匯出 PROVISA_EXTRASdocker-compose.app.yml 再把它當作建置引數傳給 DockerfileARG PROVISA_EXTRAS:[tool-verified: scripts/provisa:69-79]

dq_checker PROVISA_EXTRAS(Docker 層) 原生 venv 安裝
none firebase,vector provisa[embedded]
soda firebase,vector,soda provisa[embedded,soda]
gx firebase,vector,gx provisa[embedded,gx]

安裝示範數據集會把 none 提升為 gx 並明說此事,因為示範組態在 pet_store.pets 上註冊了一個 Great Expectations 套件,否則其品質計分卡將無內容可顯示。指名 soda 則維持 soda

以 pip 而非安裝程式取得示範會跳過該精靈步驟,所以 demo extra 帶有同一個檢查器:pip install 'provisa[embedded,demo]' 正是 provisa run --demo 執行掃描所需。缺少它,掃描會回報 data-quality checker 'great_expectations' is not installed,並指出安裝指令。

任何其他值都會讓啟動器停止,而不是在缺少操作者指定的檢查器的情況下啟動。soda extra 會拉入 soda-postgresgx 拉入 great-expectations[postgresql]。Soda Core 採用 Elastic License 2.0 — config/capabilities.yaml 將該選項標記為 cloud_eligible: false,託管平面會拒絕它。

網域

domains:
  - id: sales-analytics
    description: Sales operational data

命名

naming:
  convention: apollo_graphql   # snake, hasura_graphql, apollo_graphql (default)
  domain_prefix: true          # prepend domain_id__ to all GraphQL names
  rules:
    - pattern: "^prod_pg_"
      replace: ""

命名慣例

命名權威是面向用戶端名稱的單一事實來源;實體後端欄位名稱永不對用戶端公開。(REQ-194) 每種查詢語言皆從欄位的 column.alias(若已設定)取得名稱,否則依其組態的慣例從實體欄位名稱衍生。(REQ-194)

GraphQL 慣例是三個預設列舉之一。(REQ-416) 舊有的自由格式字串(nonesnake_casecamelCasePascalCase)已淘汰。(REQ-416)

預設 預設值 類型名稱 欄位名稱 變更操作名稱
apollo_graphql PascalCase camelCase camelCase
hasura_graphql PascalCase camelCase snake_case
snake PascalCase snake_case snake_case

預設的 GraphQL 慣例是 apollo_graphql,產生 camelCase 的欄位與變更操作名稱。(REQ-194, REQ-416) SQL 慣例是分開的,預設為 snake_case,透過 apply_sql_name() 套用;GraphQL 慣例透過 apply_gql_name() 套用,而 CQL 名稱由 GraphQL 名稱衍生。(REQ-194)

domain_prefix: bool 是正交選項,不論選用哪個預設都適用。(REQ-416)

明確的 column.alias 是正規名稱:SQL 逐字使用它且不套用任何慣例,GraphQL 對它套用自身慣例,CQL 則由 GraphQL 名稱衍生。(REQ-194)

各數據來源覆寫:

sources:
  - id: legacy-db
    naming_convention: hasura_graphql  # overrides global for this source

各表覆寫:

tables:
  - source_id: legacy-db
    table: orders
    naming_convention: snake  # overrides source for this table

網域前置詞

domain_prefix: true 時,所有 GraphQL 欄位與類型名稱都會以網域 ID 加上雙底線分隔符作為前置詞:(REQ-154)

網域 欄位名稱
orders sales-analytics sales_analytics__orders
customer_segments customer-insights customer_insights__customer_segments

這可避免不同網域中同名的表發生名稱衝突,也讓查詢本身具備說明性。

命名規則

產生 GraphQL 欄位名稱時套用於表名稱的正規表示式規則。在唯一性解析之前依序套用。(REQ-542)

tables:
  - source_id: sales-pg
    domain_id: sales-analytics
    schema: public
    table: orders
    alias: purchase_orders     # optional: override GraphQL name
    description: "Customer purchase orders"  # optional: GraphQL description
    columns:
      - name: id
        visible_to: [admin, analyst]
        writable_by: []           # read-only (empty = no writes)
      - name: email
        visible_to: [admin, analyst]
        writable_by: [admin]      # only admin can mutate
        unmasked_to: [admin]      # admin sees raw, analyst sees masked
        mask_type: regex
        mask_pattern: "^(.{2}).*(@.*)$"
        mask_replace: "$1***$2"
        alias: email_address      # optional: override GraphQL field name
        description: "Primary email address"  # optional: appears in SDL
      - name: amount
        visible_to: [admin]
        writable_by: [admin]
        unmasked_to: [admin]
        mask_type: constant
        mask_value: "0"
      - name: created_at
        visible_to: [admin, analyst]
        writable_by: []           # nobody can write
        unmasked_to: [admin]
        mask_type: truncate
        mask_precision: month
    column_presets:               # auto-set values on insert/update
      - column: created_by
        source: header            # from request header
        name: X-User-ID
      - column: updated_at
        source: now               # current timestamp

別名

表與欄位別名會覆寫預設的 GraphQL 名稱。(REQ-155) 適用於:

  • 重新命名難懂的資料庫名稱(例如 tbl_cust_segcustomer_segments
  • 避免在 API 層出現縮寫
  • 建立乾淨、貼近網域的詞彙

描述

表與欄位的描述會納入產生的 GraphQL SDL。(REQ-156) 它們會出現在 GraphiQL 的文件探索工具與自省查詢中。可在組態 YAML 或透過管理員 UI 設定。

Path(計算式 JSON 擷取)

欄位可使用點記法 path 從 JSON/JSONB 來源欄位擷取值。(REQ-151) 這對 Kafka 訊息、MongoDB 文件或 PostgreSQL JSONB 欄位中的半結構化數據很有用。

columns:
  - name: payload
    type: varchar
    visible_to: []            # hide the raw JSON column
  - name: order_id
    type: integer
    path: payload.order_id    # extracts from payload column
    visible_to: [admin, analyst]
  - name: customer_name
    type: varchar
    path: payload.customer.name
    visible_to: [admin, analyst]

path 格式為 source_column.key1.key2...。編譯器會在 SQL 中產生 json_extract_scalar(source_column, '$.key1.key2')。(REQ-151)

路由影響: path 欄位使用 PostgreSQL JSON 運算子(->>),直接 PG 路由原生支援。(REQ-152) 對於非 PostgreSQL 數據來源(MySQL、SQL Server 等),含 path 欄位的查詢會自動經由聯邦引擎路由。(REQ-152) 變更操作不受影響,因為 path 欄位是唯讀的計算欄位。(REQ-153)

遮罩類型

類型 欄位 描述
regex pattern, replace REGEXP_REPLACE(僅限字串欄位)
constant value 字面值取代(NULL、0、MAX、MIN、自訂)
truncate precision DATE_TRUNC(僅限日期/時間戳記欄位)

關係

relationships:
  - id: orders-to-customers
    source_table_id: orders
    target_table_id: customers
    source_column: customer_id
    target_column: id
    cardinality: many-to-one   # or: one-to-many

  - id: orders-to-reviews
    source_table_id: orders        # sales-pg source
    target_table_id: product_reviews  # reviews-mongo source
    source_column: product_id
    target_column: product_id
    cardinality: one-to-many
    materialize: true              # auto-create MV for this cross-source join
    refresh_interval: 600          # refresh every 10 minutes

自動具體化

在關係上設定 materialize: true,即可為跨數據來源的 JOIN 自動產生具體化檢視。(REQ-158) 這藉由預先計算 JOIN 結果來避免昂貴的聯邦查詢。

  • 只有跨數據來源的關係會產生 MV(同一數據來源的 JOIN 本來就很快)(REQ-159)
  • 在由聯結資料表支撐的關係上,MV 涵蓋的是兩跳走訪——來源端跳、聯結跳、判別欄,以及聯結資料表自身的欄位作為邊屬性。聯結資料表算作一條腿,因此只要三張資料表中任何一張位於不同的數據來源,這條邊就是跨數據來源的(REQ-1586
  • MV 起初是過時的,由背景重新整理迴圈填入 (REQ-160)
  • 對任一方來源表的變更操作會將 MV 標記為過時以便重新整理 (REQ-543)
  • refresh_interval 預設為 300 秒(5 分鐘)(REQ-543)

角色

roles:
  - id: admin
    capabilities:
      - source_registration
      - table_registration
      - relationship_registration
      - security_config
      - query_development
      - full_results
      - admin
    domain_access: ["*"]
  - id: analyst
    capabilities: [query_development]
    domain_access: [sales-analytics]
  - id: junior_analyst
    capabilities: []
    domain_access: [sales-analytics]
    parent_role_id: analyst      # inherits query_development + sales-analytics

具有 parent_role_id 的角色會從父角色繼承能力與網域存取權。(REQ-215) 階層在啟動時被攤平。(REQ-215)

能力

能力 描述
source_registration 註冊數據來源
table_registration 註冊表
relationship_registration 定義關係
security_config 組態 RLS、遮罩
query_development 執行查詢
full_results 略過抽樣限制
admin 所有能力

RLS 規則

rls_rules:
  - table_id: orders
    role_id: analyst
    filter: "region = current_setting('provisa.user_region')"

具體化檢視

materialized_views:
  - id: mv-orders-customers
    source_tables: [orders, customers]
    join_pattern:
      left_table: orders
      left_column: customer_id
      right_table: customers
      right_column: id
      join_type: left
      # REQ-1586: add via_table with via_left_column/via_right_column (and
      # via_type_column/via_type_value when the junction is discriminated) to
      # cover a two-hop junction traversal instead of a direct join.
    target_catalog: postgresql
    target_schema: mv_cache
    refresh_interval: 300
    enabled: true

檢視(受治理的計算式數據集)

檢視是以 SQL 定義的計算式數據集,具備完整的欄位級治理。(REQ-133) 它們是在語意層加入彙總、轉換與衍生指標的受治理機制。(REQ-136)

views:
  - id: monthly-revenue
    sql: |
      SELECT DATE_TRUNC('month', created_at) AS month,
             region,
             SUM(amount) AS revenue,
             COUNT(*) AS order_count
      FROM orders
      GROUP BY 1, 2
    description: "Monthly revenue by region"
    domain_id: sales-analytics
    materialize: true
    refresh_interval: 3600
    columns:
      - name: month
        visible_to: [admin, analyst]
      - name: region
        visible_to: [admin, analyst]
      - name: revenue
        visible_to: [admin]
      - name: order_count
        visible_to: [admin, analyst]
欄位 必填 描述
id 唯一的檢視識別碼
sql 定義該檢視的 SQL SELECT 陳述式
domain_id 結構描述可見性所屬的網域
materialize true = 定期 CTAS 重新整理,false = 即時聯邦檢視
refresh_interval 兩次重新整理之間的秒數(僅具體化檢視,預設 300)
description 出現在 GraphQL SDL 中
alias 覆寫 GraphQL 名稱
columns 含可見性、遮罩與描述的欄位定義

具體化與即時

  • materialize: true:Provisa 透過 CTAS 建立一個表,並依排程重新整理。(REQ-135) 查詢較快,但數據最多可能過時 refresh_interval 秒。
  • materialize: false:Provisa 建立一個聯邦檢視。(REQ-135) 查詢一律回傳即時數據,但複雜彙總可能較慢。

檢視與表走同一條治理管線 — RLS、遮罩、抽樣與角色型可見性。(REQ-134) 這確保平台上不會在缺乏數據管家監督的情況下加入新語意。(REQ-136)

僅供查詢的檢視

materialize: truematerialize: false 的檢視都以僅供查詢的方式公開其 GraphQL 類型。以 view_sql 為底的關聯不會產生 insert、upsert、update 或 delete 變更操作。(REQ-1157) [tool-verified: provisa/compiler/schema_gen.py:184, provisa/compiler/schema_types.py:79]

快取

cache:
  enabled: true
  redis_url: ${env:REDIS_URL}
  default_ttl: 300

快取階層

TTL 解析順序(最明確者勝出): > 數據來源 > 全域預設。(REQ-544) 採用第一個非 null 的值。

cache:
  enabled: true
  redis_url: ${env:REDIS_URL}
  default_ttl: 300              # global fallback: 5 minutes

sources:
  - id: sales-pg
    cache_enabled: true          # toggle caching for all tables in this source
    cache_ttl: 600               # source override: 10 minutes

tables:
  - source_id: sales-pg
    table: orders
    cache_ttl: 60                # table override: 1 minute (frequently changing)
  - source_id: sales-pg
    table: customers
    # no cache_ttl → inherits source TTL (600s)

在數據來源上設定 cache_enabled: false 會停用該數據來源所有表的快取,不論表層級的 TTL 為何。(REQ-544) 快取鍵一律包含 role_id 加 RLS 內容值,以達成安全分區。(REQ-544)

驗證

auth:
  provider: simple           # none, firebase, keycloak, oauth, simple
  superuser:
    username: admin
    password: ${env:PROVISA_SUPERUSER_PASSWORD}
  simple:
    allow: true
    jwt_secret: ${env:PROVISA_JWT_SECRET}
    users:
      - username: admin
        password_hash: "$2b$12$..."
        roles: [admin]
  role_mapping:
    - claim: groups
      contains: data-analysts
      provisa_role: analyst
    default_role: analyst

驗證提供者類型

提供者 使用情境 權杖驗證
simple 本機開發/測試。使用者定義於 YAML。 PROVISA_JWT_SECRET 簽署的 JWT
firebase Firebase Authentication(所有方式)。 firebase-admin SDK verify_id_token()
keycloak Keycloak OIDC。對應租用戶與用戶端角色。 以 JWKS 為基礎的 JWT 驗證
oauth 通用 OIDC(Okta、Azure AD、Auth0、PingFederate)。 來自探索 URL 的 JWKS
basic 自足式部署。帳戶存放於 Provisa 自己的儲存區。 bcrypt 密碼,或 pgwire 上的 SCRAM-SHA-256

超級使用者認證(superuser 區塊)可搭配任何提供者使用,並一律解析為具備所有能力的 admin 角色。(REQ-125) 用於在外部驗證組態完成前的初始設定。

SCRAM-SHA-256(auth.scram

auth:
  provider: basic
  scram: true

讓 pgwire 以 SCRAM-SHA-256 公告 SASL,因此密碼是被證明而非以明文傳送。(REQ-1394) 它僅適用於 basic 提供者 — 其他提供者都不持有 SCRAM 所需的 RFC 5802 驗證子 — 且不提供通道繫結。

驗證子無法從既有的 bcrypt 雜湊衍生。每當密碼以純文字經過時就會寫入一個,因此每位使用者的第一次 SCRAM 連線發生在其下一次註冊、登入、變更密碼或管理員重設之後。在那之前,該使用者的連線會回退為經 TLS 的明文交換;線路上不會顯示誰已遷移。

登入節流(auth.login_throttle

auth:
  login_throttle:
    max_attempts: 5      # failures within the window before lockout
    window_seconds: 300  # how far back failures are counted
    lockout_seconds: 900 # how long a locked-out subject is refused

預設以所示值啟用;此區塊只用來調整。(REQ-1393) 計數器位於認證驗證層,因此經由 HTTP、pgwire 與 Bolt 的失敗會累加到同一個主體上,而鎖定在每個介面上都成立。它是每個處理程序各自計算:多個 API 工作處理程序各自允許至多 max_attempts 次。

個人存取權杖

PAT 不需組態區塊 — 它們一律被接受,且其儲存區隨控制平面結構描述一併建立。(REQ-1263) 可組態的是使用者在簽發時可要求的到期時間:1 至 366 天,或不設到期的永久權杖。見安全模型

雙向 TLS

用戶端憑證驗證是以環境變數組態,而非在 provisa.yaml 中,與它所延伸的 TLS 憑證設定並列。(REQ-1228)

變數 預設 意義
PROVISA_MTLS_CLIENT_CA 未設定 獲准簽署用戶端憑證的 CA 的 PEM 套件。設定它即開啟用戶端憑證驗證
PROVISA_MTLS_MODE 設定 CA 後為 required requiredoptional
PROVISA_MTLS_BIND_PRINCIPAL false 要求憑證的一般名稱等於該連線驗證所用的使用者名稱

每一項都可依協定覆寫,命名方式與 TLS 設定相同。設定了模式卻沒有 CA,或模式不是這兩個值之一,都會拒絕啟動,而不是提供操作者以為已驗證的連線。

透過 TLS 指向某個組織

無需組態。在多組織部署上,pgwire 與 Bolt 從用戶端撥接的主機名稱讀取組織,該名稱由 TLS ClientHello 攜帶,正如 HTTP 從 Host 標頭讀取一樣。(REQ-1234) 連線到 acme.provisa.dev 的用戶端即請求組織 acme;除非通過驗證的主體是其成員,否則請求會被拒絕。以 IP 位址連線則不請求任何組織,這正是單組織部署上的每一條連線。

完整驗證組態範例(已註解)

# auth:
#   provider: firebase
#
#   superuser:
#     username: admin
#     password: ${env:PROVISA_SUPERUSER_PASSWORD}
#
#   firebase:
#     project_id: ${env:FIREBASE_PROJECT_ID}
#     service_account_key: ${env:FIREBASE_SERVICE_ACCOUNT}
#
#   # keycloak:
#   #   server_url: https://keycloak.example.com
#   #   # kc-tenant: set to your Keycloak tenant name (e.g. provisa)
#   #   client_id: provisa-app
#   #   client_secret: ${env:KEYCLOAK_CLIENT_SECRET}
#
#   # oauth:
#   #   discovery_url: https://login.example.com/.well-known/openid-configuration
#   #   client_id: provisa
#   #   client_secret: ${env:OAUTH_CLIENT_SECRET}
#   #   role_claim: groups
#   #   audience: provisa-api
#
#   role_mapping:
#     - claim: custom_claims.role
#       value: admin
#       provisa_role: admin
#     - claim: groups
#       contains: data-analysts
#       provisa_role: analyst
#     default_role: analyst

Upsert 變更操作

對於具有主索引鍵的表,Provisa 會自動產生 upsert_<table> 變更操作欄位。(REQ-212) 它們會編譯成目標方言的 upsert — PostgreSQL 上的 INSERT ... ON CONFLICT (pk) DO UPDATE SET ...,MySQL 上的 ON DUPLICATE KEY UPDATE。(REQ-212)

mutation {
  upsert_orders(objects: [{id: 1, amount: 150.00, region: "us"}]) {
    affected_rows
  }
}

衝突欄位由 PK 中繼資料衍生。(REQ-212) 所有欄位可見性與寫入權限規則均適用。

Distinct On

distinct_on 引數會針對指定欄位的每個相異值選出第一列。(REQ-213) 可用於根查詢欄位。

{
  orders(distinct_on: [region], order_by: [{region: asc, created_at: desc}]) {
    region
    amount
    created_at
  }
}

在 PostgreSQL 中編譯成 SELECT DISTINCT ON (region) ...。(REQ-213) 對非 PG 方言則使用視窗函式的替代做法。(REQ-213)

欄位預設值

在插入/更新時自動注入值到欄位。(REQ-214) 於組態中按表定義。

tables:
  - source_id: sales-pg
    table: orders
    column_presets:
      - column: created_by
        source: header           # from request header
        name: X-User-ID
      - column: updated_at
        source: now              # current timestamp
      - column: source_system
        source: literal          # constant value
        value: "provisa"
來源 行為
header 從指名的 HTTP 請求標頭注入值
now 注入 NOW()(目前時間戳記)
literal 注入常數值

預設欄位在變更操作編譯期間、SQL 產生之前注入。(REQ-214) 它們不會出現在變更操作的輸入類型中。(REQ-214)

繼承角色

角色可透過 parent_role_id 從父角色繼承能力與網域存取權。(REQ-215) 階層在啟動時被攤平。(REQ-215)

roles:
  - id: admin
    capabilities: [admin]
    domain_access: ["*"]
  - id: analyst
    capabilities: [query_development]
    domain_access: [sales-analytics]
  - id: junior_analyst
    capabilities: []
    domain_access: []
    parent_role_id: analyst      # inherits query_development + sales-analytics
  - id: intern
    capabilities: []
    domain_access: []
    parent_role_id: junior_analyst  # inherits from junior_analyst (and transitively analyst)

支援多層繼承。(REQ-215) 子角色明確設定的 capabilities 與 domain_access 會與父角色的合併。(REQ-215)

排程觸發器

依排程呼叫 webhook URL 的 cron 型觸發器。(REQ-216) 使用 APScheduler。(REQ-216)

scheduled_triggers:
  - name: daily-report
    cron: "0 8 * * *"           # 8:00 AM daily
    webhook_url: https://hooks.example.com/daily-report
    enabled: true
  - name: hourly-sync
    cron: "0 * * * *"           # every hour
    webhook_url: https://hooks.example.com/sync
    enabled: false

排程工作透過管理員 UI(啟用/停用切換)或 toggle_scheduled_task 管理員變更操作管理。(REQ-216)

OrderBy 格式

OrderBy 使用 {column: direction} 格式,方向為六值列舉:(REQ-200, REQ-201)

{
  orders(order_by: [{created_at: desc_nulls_last}, {amount: asc}]) {
    id
    created_at
    amount
  }
}
方向 SQL
asc ASC
desc DESC
asc_nulls_first ASC NULLS FIRST
asc_nulls_last ASC NULLS LAST
desc_nulls_first DESC NULLS FIRST
desc_nulls_last DESC NULLS LAST

透過巢狀物件支援關係排序:(REQ-202)

{
  orders(order_by: [{customers: {name: asc}}]) {
    id
    customers { name }
  }
}

可觀測性

observability:
  endpoint: "http://localhost:4319"   # OTLP collector; env OTEL_EXPORTER_OTLP_ENDPOINT overrides
  service_name: provisa               # env OTEL_SERVICE_NAME overrides
  sample_rate: 1.0                    # 0.0–1.0; TraceIdRatioBased sampler
  log_level: WARNING                  # env OTEL_LOG_LEVEL overrides
  compact_batch_size: 1000
  telemetry_filter:
    redact_sql_literals: false        # strip literal values from db.statement before export
    redact_attributes: []             # attribute keys dropped entirely before export
  # support_endpoint: ""              # env PROVISA_SUPPORT_OTLP_ENDPOINT; off by default
  support_telemetry_filter:
    redact_sql_literals: true         # default on — strip literals before sending to support
    redact_attributes: []             # additional keys dropped before sending to support

遙測篩選器 [tool-verified]

Provisa 執行兩條獨立的 OTLP 匯出路徑:你的內部收集器,以及選用的 Provisa 支援端點。(REQ-545) 每條路徑各有自己的篩選器。篩選器在跨距離開處理程序之前,於包覆的 _FilteringExporter 內執行 — 原始跨距物件永不被變更。(REQ-546) [tool-verified: provisa/api/otel_setup.py lines 156–207]

telemetry_filter — 控制哪些內容到達你的內部收集器。

類型 預設 描述
redact_sql_literals bool false db.statement 中的字串與數值字面值取代為 ?
redact_attributes list[str] [] 從每個跨距中完全移除的屬性鍵

support_telemetry_filter — 控制哪些內容到達 Provisa 支援端點。這條路徑上的 SQL 字面值編修預設為 true,因為查詢數據屬於你。(REQ-547) [tool-verified: provisa/api/otel_setup.py line 240]

類型 預設 描述
redact_sql_literals bool true db.statement 中的字串與數值字面值取代為 ?
redact_attributes list[str] [] 從每個跨距中完全移除的屬性鍵

編修後的 db.statement 範例 — 在 redact_sql_literals: true 之下,這個跨距屬性:

db.statement: SELECT * FROM orders WHERE region = 'us-west' AND amount > 500

會變成:

db.statement: SELECT * FROM orders WHERE region = ? AND amount > ?

支援端點 [tool-verified]

support_endpoint(或環境變數 PROVISA_SUPPORT_OTLP_ENDPOINT)會將遙測轉送給 Provisa 支援以供診斷。(REQ-548) 未設定時,沒有數據會經由這條路徑離開你的基礎架構。(REQ-548) 支援篩選器獨立於內部篩選器運作 — 你可以在兩邊匯出中都編修 SQL 字面值,同時仍與支援分享跨距時間與錯誤數據。(REQ-545) [tool-verified: provisa/api/otel_setup.py lines 238–288]

端點協定偵測 [tool-verified]

Provisa 從端點 URL 的配置選擇 OTLP/HTTP 或 OTLP/gRPC。(REQ-549) 以 http://https:// 開頭的 URL 使用 OTLP/HTTP,並自動附加 /v1/traces/v1/metrics/v1/logs。(REQ-549) 其他任何配置皆使用 OTLP/gRPC 並帶 insecure=True。(REQ-549) [tool-verified: provisa/api/otel_setup.py lines 60–70]

聯邦引擎

組態聯邦引擎是選用的。預設為 duckdb — 零組態、行程內、不需外部服務 (REQ-989)。當你需要 MPP 規模,或想沿用既有的數據倉庫時,才選擇其他引擎。

優先順序:PROVISA_ENGINE 環境變數 → 持久化的管理員 UI federation_engine 組態欄位 → duckdb。變更於服務重新啟動時生效。[tool-verified: engine.py build_engine]

引擎總覽 [tool-verified: engine.py ENGINE_REGISTRY, _ENGINE_BUILDERS]

引擎鍵 標籤 方言 MPP 外部連結機制 驗證
trino Provisa Federation Engine Trino SQL Trino 目錄(廣泛的連接器集合) JDBC 認證
trino-byo Trino Trino SQL trino;非受管協調器 JDBC 認證
pg PostgreSQL PostgreSQL FDW / pg_duckdb PostgreSQL 認證
duckdb DuckDB DuckDB 擴充功能原生的 ATTACH 無(行程內)
clickhouse ClickHouse (embedded) ClickHouse S3 / IcebergS3 / DeltaLake 表引擎 chdb(行程內,無驗證)
clickhouse-server ClickHouse (Server / Cloud) ClickHouse S3 / IcebergS3 / DeltaLake 表引擎 ClickHouse 認證
snowflake Snowflake Snowflake 外部暫存區 + 外部表 PROVISA_ENGINE_URL
databricks Databricks Databricks SQL 透過 REST 的 Unity Catalog 外部表 PROVISA_ENGINE_URL(持有人權杖 + http_path
bigquery BigQuery BigQuery BigQuery 外部/BigLake 表 GOOGLE_APPLICATION_CREDENTIALS
fabric Microsoft Fabric T-SQL OneLake 捷徑 → OPENROWSET Azure AD(az login 或受控識別)
synapse Azure Synapse T-SQL ADLS OPENROWSET/外部表 Azure AD
mysql MySQL 依方言 無(僅落地) 依方言的認證
mariadb MariaDB 依方言 無(僅落地) 依方言的認證
oracle Oracle Database 依方言 無(僅落地) 依方言的認證
mssql Microsoft SQL Server 依方言 無(僅落地) 依方言的認證
db2 IBM Db2 依方言 無(僅落地) 依方言的認證
redshift Amazon Redshift 依方言 無(僅落地) 依方言的認證
greenplum Greenplum 依方言 無(僅落地) 依方言的認證
cockroachdb CockroachDB 依方言 無(僅落地) 依方言的認證
yugabytedb YugabyteDB 依方言 無(僅落地) 依方言的認證
opengauss openGauss 依方言 無(僅落地) 依方言的認證
tidb TiDB 依方言 無(僅落地) 依方言的認證
singlestore SingleStore 依方言 無(僅落地) 依方言的認證
vertica Vertica 依方言 無(僅落地) 依方言的認證
exasol Exasol 依方言 無(僅落地) 依方言的認證
teradata Teradata Vantage 依方言 無(僅落地) 依方言的認證
saphana SAP HANA 依方言 無(僅落地) 依方言的認證
sapase SAP ASE (Sybase) 依方言 無(僅落地) 依方言的認證
sqlanywhere SAP SQL Anywhere 依方言 無(僅落地) 依方言的認證
monetdb MonetDB 依方言 無(僅落地) 依方言的認證
firebird Firebird 依方言 無(僅落地) 依方言的認證
sqlalchemy 其他關聯式資料庫(以連線 URL 指定) 依方言 無(僅落地) 依方言的認證

引擎參考

trino / trino-byo

trino 是受管的 Provisa 協調器;trino-byo 連接你自己的 Trino 叢集。兩者皆使用 Trino SQL,且數據來源類型的觸及範圍最廣。

PROVISA_ENGINE=trino
TRINO_HOST=trino.internal
TRINO_PORT=8080

具體化儲存區預設為 TENANT_DATABASE_URL(PostgreSQL)。

pg

透過 postgres_fdw(SQL/MED)與 pg_duckdb 擴充功能進行聯邦。單節點;無 MPP。當你的數據已存放在 PostgreSQL 中,而你想併入少數幾個遠端數據來源時最合適。

PROVISA_ENGINE=pg
# Connection uses the standard PG_* env vars

具體化儲存區預設為 TENANT_DATABASE_URL

duckdb

行程內;無外部服務。預設引擎 (REQ-989)。PROVISA_DATA_DIR 控制內嵌儲存區的位置(預設 ~/.provisa)。

PROVISA_ENGINE=duckdb   # or omit — this is the default

具體化儲存區預設為 ~/.provisa/materialize.duckdb — 唯一預設儲存區不是 PostgreSQL 的引擎。

clickhouse (embedded) / clickhouse-server

clickhouse 使用 chdb(行程內)。clickhouse-server 連接外部 ClickHouse 執行個體或 ClickHouse Cloud。兩者皆透過原生 ClickHouse 表引擎直接讀取 Delta Lake、Iceberg 與 Hudi。

# External server
PROVISA_ENGINE=clickhouse-server
PROVISA_ENGINE_URL="clickhouse://user:pass@host:9000/db"

具體化儲存區預設為 TENANT_DATABASE_URL

snowflake

引擎即數據倉庫:由 Snowflake 執行查詢;Provisa 透過外部暫存區把數據來源的數據推送過去。

PROVISA_ENGINE=snowflake
PROVISA_ENGINE_URL="snowflake://user:pass@account/db/schema?warehouse=WH"

具體化儲存區預設為 TENANT_DATABASE_URL

databricks

Unity Catalog 外部表把 Provisa 管理的數據來源橋接進 Databricks SQL。

PROVISA_ENGINE=databricks
PROVISA_ENGINE_URL="databricks://token:TOKEN@my-workspace.azuredatabricks.net?http_path=/sql/1.0/warehouses/xxxx"

具體化儲存區預設為 TENANT_DATABASE_URL

bigquery

BigQuery 外部表與 BigLake 表。專案來自 URL 或 GOOGLE_CLOUD_PROJECT;以服務帳戶金鑰驗證。

PROVISA_ENGINE=bigquery
PROVISA_ENGINE_URL="bigquery://my-project?location=US"
# GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json

具體化儲存區預設為 TENANT_DATABASE_URL

fabric / synapse

兩者皆使用透過 TDS 的 T-SQL 搭配 Azure AD 驗證(az login 或受控識別)。省略 PROVISA_ENGINE_URL 即改從環境變數讀取連線詳細資料。

PROVISA_ENGINE=fabric
# FABRIC_SQL_SERVER=...   FABRIC_DATABASE=...
# or: PROVISA_ENGINE_URL set explicitly

PROVISA_ENGINE=synapse
# SYNAPSE_SQL_SERVER=...  SYNAPSE_DATABASE=...

具體化儲存區預設為 TENANT_DATABASE_URL

關聯式資料庫引擎(mysql、mariadb、oracle、mssql、db2、redshift、greenplum、cockroachdb、yugabytedb、opengauss、tidb、singlestore、vertica、exasol、teradata、saphana、sapase、sqlanywhere、monetdb、firebird)與 sqlalchemy

每個可透過網路定址的關聯式資料庫各有一個鍵,全都跑在同一套僅落地的執行環境上(不聯邦到外部數據來源):每個數據來源都落地到儲存區,並在那裡被查詢。鍵用來選擇資料庫;PROVISA_ENGINE_URL 攜帶其方言所接受的 DSN。sqlalchemy 是沒有專屬鍵的資料庫的萬用選項。不提供檔案內嵌式儲存區(SQLite、Access)— 伺服器必須可透過網路連達。

PROVISA_ENGINE=mysql
PROVISA_ENGINE_URL="mysql+pymysql://user:pass@host:3306/db"

具體化儲存區預設為 TENANT_DATABASE_URL

具體化儲存區

當某個數據來源無法即時附加(所選引擎沒有對應的 ATTACH 連接器)時,它會落地到該引擎的具體化儲存區。解析順序:明確的 PROVISA_MATERIALIZE_URL → 引擎宣告的預設值 → 直接報錯(不會悄悄退回)。[tool-verified: engine.py materialize_store]

DuckDB 宣告其內嵌檔案(~/.provisa/materialize.duckdb)為預設值。其他所有引擎皆預設為 TENANT_DATABASE_URL(PostgreSQL)。任一引擎都可用 PROVISA_MATERIALIZE_URL 覆寫。

各數據來源的聯邦提示

標準 host/port/user/password 欄位無法攜帶的延伸連線參數,放在數據來源的 federation_hints 中。各類型的提示鍵見上方的數據來源類型參考。一個整合的範例:

sources:
  - id: my-databricks
    type: databricks
    host: my-workspace.azuredatabricks.net
    password: ${env:DATABRICKS_TOKEN}
    federation_hints:
      http_path: /sql/1.0/warehouses/xxxx   # required for Databricks sources

  - id: my-snowflake
    type: snowflake
    host: org.snowflakecomputing.com
    username: svc_provisa
    password: ${env:SNOWFLAKE_PASSWORD}
    federation_hints:
      account: myorg-myaccount
      warehouse: COMPUTE_WH

  - id: my-clickhouse
    type: clickhouse
    host: ch.example.com
    port: 8123
    password: ${env:CLICKHOUSE_PASSWORD}
    federation_hints:
      secure: "true"           # enable TLS on the HTTP interface

  - id: r2-parquet
    type: parquet
    path: s3://my-bucket/data/events.parquet
    federation_hints:
      access_key_id: ${env:R2_ACCESS_KEY}
      secret_access_key: ${env:R2_SECRET}
      account_id: ${env:R2_ACCOUNT_ID}   # Cloudflare R2 account (S3-compatible)

若使用 Google Cloud 數據來源,請將 GOOGLE_APPLICATION_CREDENTIALS 設為服務帳戶金鑰檔案的路徑。若使用 Fabric 與 Synapse,請以 az login(開發者)或受控識別(生產環境)驗證 — 引擎透過 azure-identityDefaultAzureCredential 讀取認證。

環境變數

變數 預設 描述
PROVISA_CONFIG config/provisa.yaml 組態檔路徑
TENANT_DATABASE_URL postgresql+asyncpg://provisa:provisa@localhost:5432/provisa 控制平面儲存區 URI(SQLAlchemy async);內嵌桌面儲存區接受 sqlite+aiosqlite://… / duckdb://… (REQ-828, REQ-850)
PLATFORM_DATABASE_URL 平台登錄 URI(租用戶目錄、引擎登錄);啟動時必要,無後備值 (REQ-837)
PROVISA_REDIS_EMBEDDED 1/true 改用內嵌的 fakeredis 而非 Redis 伺服器 — 不需 Docker (REQ-829)
PG_HOST localhost PostgreSQL 主機
PG_PORT 5432 PostgreSQL 連接埠
PG_DATABASE provisa PostgreSQL 資料庫
PG_USER provisa PostgreSQL 使用者
PG_PASSWORD provisa PostgreSQL 密碼
PROVISA_ENGINE duckdb 聯邦引擎鍵 (REQ-989, REQ-916)
PROVISA_ENGINE_URL URL 驅動引擎的連線 URL(Snowflake、Databricks、ClickHouse Server、BigQuery、SQLAlchemy)
PROVISA_MATERIALIZE_URL 覆寫具體化儲存區 DSN(預設為引擎宣告的預設值)
PROVISA_DATA_DIR ~/.provisa 內嵌 DuckDB 儲存區的數據目錄 (REQ-989)
TRINO_HOST localhost Trino 協調器主機
TRINO_PORT 8080 Trino 協調器 HTTP 連接埠
GOOGLE_APPLICATION_CREDENTIALS GCP 服務帳戶金鑰 JSON 的路徑(BigQuery 引擎/數據來源)
GOOGLE_CLOUD_PROJECT 預設 GCP 專案(BigQuery;由 URL 覆寫)
FABRIC_SQL_SERVER Fabric Warehouse SQL 端點(PROVISA_ENGINE_URL 的替代方式)
FABRIC_DATABASE Fabric Warehouse 資料庫名稱
SYNAPSE_SQL_SERVER Synapse 無伺服器 SQL 端點
SYNAPSE_DATABASE Synapse 資料庫名稱
REDIS_URL Redis 連線 URL
PROVISA_SAMPLE_SIZE 10000 預設抽樣上限
PROVISA_DEFAULT_ROW_LIMIT 100 查詢未提供明確 LIMIT 時的資料列上限
PROVISA_RETRY_BUDGET_SECS 30 第一層讀取重試預算(秒);指數輪詢退避搭配完全抖動 (REQ-703)
ZAYCHIK_PORT 8480 Zaychik Flight SQL 代理連接埠
FLIGHT_PORT 8815 Provisa Arrow Flight 伺服器連接埠
GRPC_PORT 50051 Provisa Protobuf gRPC 伺服器連接埠
PROVISA_REDIRECT_ENABLED false 啟用伺服器端門檻重新導向
PROVISA_REDIRECT_THRESHOLD 1000 預設資料列數門檻
PROVISA_REDIRECT_FORMAT parquet 預設重新導向格式
PROVISA_REDIRECT_BUCKET provisa-results 存放重新導向結果的 S3 貯體
PROVISA_REDIRECT_ENDPOINT S3 相容端點 URL
PROVISA_REDIRECT_ACCESS_KEY S3 存取金鑰
PROVISA_REDIRECT_SECRET_KEY S3 密鑰
PROVISA_REDIRECT_TTL 3600 預先簽署 URL 的 TTL(秒)
PROVISA_MTLS_CLIENT_CA 獲准簽署用戶端憑證的 CA 的 PEM 套件;設定它會在 pgwire、Bolt、gRPC 與 Flight 上開啟用戶端憑證驗證 (REQ-1228)
PROVISA_MTLS_MODE 設定 CA 後為 required requiredoptional;其他任何值都會拒絕啟動 (REQ-1228)
PROVISA_MTLS_BIND_PRINCIPAL false 要求憑證的一般名稱等於進行驗證的使用者名稱 (REQ-1228)
PROVISA_BOLT_ALLOWED_ORIGINS 以逗號分隔、獲准從瀏覽器開啟 Bolt WebSocket 的站台;未設定則拒絕每一個瀏覽器來源 (REQ-802)
PROVISA_EXTRAS firebase,vector 烘焙進應用程式映像的 pyproject extras;scripts/provisa~/.provisa/config.yaml 中的 dq_checker 推導 (REQ-1443)
PROVISA_DQ_CHECKER none 僅供安裝程式使用:none/soda/gx,由 first-launch.sh 在非互動模式下讀取,並以 dq_checker 寫入 config.yaml (REQ-1443)
ANTHROPIC_API_KEY Claude API 金鑰(探索)
OTEL_EXPORTER_OTLP_ENDPOINT 覆寫 observability.endpoint
OTEL_SERVICE_NAME provisa 覆寫 observability.service_name
OTEL_LOG_LEVEL WARNING 覆寫 observability.log_level
OTEL_COMPACT_BATCH_SIZE 10 覆寫 observability.compact_batch_size
OTEL_SPAN_EXPORT_DELAY_MILLIS 1000 批次跨距處理器的排清延遲
PROVISA_SUPPORT_OTLP_ENDPOINT 覆寫 observability.support_endpoint