mirror of https://github.com/buster-so/buster.git
111 lines
4.9 KiB
Rust
111 lines
4.9 KiB
Rust
use serde::Deserialize;
|
|
use std::collections::HashMap;
|
|
|
|
// Struct definitions for parsing dbt's catalog.json (v1 schema)
|
|
|
|
#[derive(Debug, Deserialize, Clone, Default)]
|
|
pub struct DbtCatalog {
|
|
// metadata is required by schema, but use Option + default for robustness if block is missing
|
|
#[serde(default)]
|
|
pub metadata: Option<CatalogMetadata>,
|
|
#[serde(default)] // nodes map is required, default handles if key is missing (empty map)
|
|
pub nodes: HashMap<String, CatalogNode>,
|
|
#[serde(default)] // sources map is required
|
|
pub sources: HashMap<String, CatalogSource>,
|
|
#[serde(default)]
|
|
pub errors: Option<Vec<String>>, // errors: string[] | null
|
|
|
|
// --- Fields kept for potential compatibility or future use, not strictly in v1 catalog properties like nodes/sources/metadata ---
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub macros: Option<HashMap<String, serde_json::Value>>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub exposures: Option<HashMap<String, serde_json::Value>>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub metrics: Option<HashMap<String, serde_json::Value>>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub selectors: Option<HashMap<String, serde_json::Value>>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub disabled: Option<HashMap<String, Vec<serde_json::Value>>>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub parent_map: Option<HashMap<String, Vec<String>>>,
|
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
pub child_map: Option<HashMap<String, Vec<String>>>,
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone, Default)]
|
|
pub struct CatalogMetadata { // Was DbtCatalogMetadata; matches schema.metadata
|
|
#[serde(default)] // Though schema implies required, default if block is imperfect
|
|
pub dbt_schema_version: String,
|
|
#[serde(default)]
|
|
pub dbt_version: Option<String>, // Defaulted in schema "1.10.0a1" but can be other string
|
|
#[serde(default)]
|
|
pub generated_at: Option<String>, // Is string in schema, but make Option for safety
|
|
#[serde(default)]
|
|
pub invocation_id: Option<String>, // string | null
|
|
#[serde(default)]
|
|
pub invocation_started_at: Option<String>, // string | null (from schema)
|
|
#[serde(default)]
|
|
pub env: HashMap<String, String>, // From schema
|
|
}
|
|
|
|
// Represents a "CatalogTable" from the dbt schema (for nodes and sources)
|
|
#[derive(Debug, Deserialize, Clone, Default)]
|
|
pub struct CatalogNode { // Was DbtNode; represents schema.nodes.<node_name>
|
|
// metadata, columns, stats are required per schema for a CatalogTable
|
|
// Using Option + default for robustness if a catalog is malformed,
|
|
// but downstream code will need to handle None for these.
|
|
#[serde(default)]
|
|
pub metadata: Option<TableMetadata>,
|
|
#[serde(default)]
|
|
pub columns: HashMap<String, ColumnMetadata>,
|
|
#[serde(default)]
|
|
pub stats: HashMap<String, StatsItem>,
|
|
#[serde(default)]
|
|
pub unique_id: Option<String>, // string | null
|
|
|
|
// --- Fields to be populated by post-processing in lib.rs ---
|
|
// These are not directly from catalog.json node structure
|
|
#[serde(skip_deserializing, skip_serializing_if = "Option::is_none")]
|
|
pub derived_resource_type: Option<String>,
|
|
#[serde(skip_deserializing, skip_serializing_if = "Option::is_none")]
|
|
pub derived_model_name_from_file: Option<String>, // Name derived from SQL filename
|
|
}
|
|
|
|
// Using CatalogNode for sources as well, as their structure is CatalogTable
|
|
pub type CatalogSource = CatalogNode;
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone, Default)]
|
|
pub struct TableMetadata { // Was DbtNodeMetadata; matches schema.nodes.<node_name>.metadata
|
|
#[serde(rename = "type")]
|
|
pub type_: String, // Required: database object type (e.g. "TABLE", "VIEW")
|
|
pub schema: String, // Required
|
|
pub name: String, // Required: relation name in the database
|
|
#[serde(default)]
|
|
pub database: Option<String>, // string | null
|
|
#[serde(default)]
|
|
pub comment: Option<String>, // string | null
|
|
#[serde(default)]
|
|
pub owner: Option<String>, // string | null
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone, Default)]
|
|
pub struct ColumnMetadata { // Was DbtColumn; matches schema.nodes.<node_name>.columns.<col_name>
|
|
#[serde(rename = "type")]
|
|
pub type_: String, // Required: database column type
|
|
pub index: u32, // Required
|
|
pub name: String, // Required
|
|
#[serde(default)]
|
|
pub comment: Option<String>, // string | null
|
|
}
|
|
|
|
#[derive(Debug, Deserialize, Clone, Default)]
|
|
pub struct StatsItem { // matches schema.nodes.<node_name>.stats.<stat_name>
|
|
pub id: String, // Required
|
|
pub label: String, // Required
|
|
#[serde(default)]
|
|
pub value: serde_json::Value, // anyOf: boolean, string, number, null. Required.
|
|
pub include: bool, // Required
|
|
#[serde(default)]
|
|
pub description: Option<String>, // string | null
|
|
}
|