data_modelling_sdk/import/
mod.rs

1//! Import functionality
2//!
3//! Provides parsers for importing data models from various formats:
4//! - SQL (CREATE TABLE statements)
5//! - ODCS (Open Data Contract Standard) v3.1.0 YAML format (legacy ODCL formats supported for import)
6//! - JSON Schema
7//! - AVRO
8//! - Protobuf
9//! - Decision (MADR-compliant decision records)
10//! - Knowledge (Knowledge Base articles)
11
12pub mod avro;
13#[cfg(feature = "bpmn")]
14pub mod bpmn;
15pub mod cads;
16pub mod decision;
17#[cfg(feature = "dmn")]
18pub mod dmn;
19pub mod json_schema;
20pub mod knowledge;
21pub mod odcl;
22pub mod odcs;
23pub mod odcs_shared;
24pub mod odps;
25#[cfg(feature = "openapi")]
26pub mod openapi;
27pub mod protobuf;
28pub mod sql;
29
30// anyhow::Result not currently used in this module
31
32/// Result of an import operation.
33///
34/// Contains extracted tables and any errors/warnings from the import process.
35#[derive(Debug, serde::Serialize, serde::Deserialize)]
36#[must_use = "import results should be processed or errors checked"]
37pub struct ImportResult {
38    /// Tables extracted from the import
39    pub tables: Vec<TableData>,
40    /// Tables that require name input (for SQL imports with unnamed tables)
41    pub tables_requiring_name: Vec<TableRequiringName>,
42    /// Parse errors/warnings
43    pub errors: Vec<ImportError>,
44    /// Whether AI suggestions are available
45    pub ai_suggestions: Option<Vec<serde_json::Value>>,
46}
47
48/// Error during import
49#[derive(Debug, thiserror::Error, serde::Serialize, serde::Deserialize)]
50pub enum ImportError {
51    #[error("Parse error: {0}")]
52    ParseError(String),
53    #[error("Validation error: {0}")]
54    ValidationError(String),
55    #[error("IO error: {0}")]
56    IoError(String),
57    #[error("BPMN validation error: {0}")]
58    BPMNValidationError(String),
59    #[error("DMN validation error: {0}")]
60    DMNValidationError(String),
61    #[error("OpenAPI validation error: {0}")]
62    OpenAPIValidationError(String),
63    #[error("BPMN parse error: {0}")]
64    BPMNParseError(String),
65    #[error("DMN parse error: {0}")]
66    DMNParseError(String),
67    #[error("OpenAPI parse error: {0}")]
68    OpenAPIParseError(String),
69}
70
71/// Table data from import
72#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
73pub struct TableData {
74    pub table_index: usize,
75    pub name: Option<String>,
76    pub columns: Vec<ColumnData>,
77    // Additional fields can be added as needed
78}
79
80/// Column data from import - mirrors Column struct exactly to preserve all ODCS v3.1.0 fields
81#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
82#[serde(rename_all = "camelCase")]
83pub struct ColumnData {
84    // === Core Identity Fields ===
85    /// Stable technical identifier (ODCS: id)
86    #[serde(skip_serializing_if = "Option::is_none")]
87    pub id: Option<String>,
88    /// Column name (ODCS: name)
89    pub name: String,
90    /// Business name for the column (ODCS: businessName)
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub business_name: Option<String>,
93    /// Column description/documentation (ODCS: description)
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub description: Option<String>,
96
97    // === Type Information ===
98    /// Logical data type (ODCS: logicalType)
99    #[serde(rename = "dataType")]
100    pub data_type: String,
101    /// Physical database type (ODCS: physicalType)
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub physical_type: Option<String>,
104    /// Physical name in the data source (ODCS: physicalName)
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub physical_name: Option<String>,
107    /// Additional type options (ODCS: logicalTypeOptions)
108    #[serde(skip_serializing_if = "Option::is_none")]
109    pub logical_type_options: Option<crate::models::LogicalTypeOptions>,
110
111    // === Key Constraints ===
112    /// Whether this column is part of the primary key (ODCS: primaryKey)
113    #[serde(default)]
114    pub primary_key: bool,
115    /// Position in composite primary key, 1-based (ODCS: primaryKeyPosition)
116    #[serde(skip_serializing_if = "Option::is_none")]
117    pub primary_key_position: Option<i32>,
118    /// Whether the column contains unique values (ODCS: unique)
119    #[serde(default)]
120    pub unique: bool,
121    /// Whether the column allows NULL values (inverse of ODCS: required)
122    #[serde(default = "default_true")]
123    pub nullable: bool,
124
125    // === Partitioning & Clustering ===
126    /// Whether the column is used for partitioning (ODCS: partitioned)
127    #[serde(default)]
128    pub partitioned: bool,
129    /// Position in partition key, 1-based (ODCS: partitionKeyPosition)
130    #[serde(skip_serializing_if = "Option::is_none")]
131    pub partition_key_position: Option<i32>,
132    /// Whether the column is used for clustering
133    #[serde(default)]
134    pub clustered: bool,
135
136    // === Data Classification & Security ===
137    /// Data classification level (ODCS: classification)
138    #[serde(skip_serializing_if = "Option::is_none")]
139    pub classification: Option<String>,
140    /// Whether this is a critical data element (ODCS: criticalDataElement)
141    #[serde(default)]
142    pub critical_data_element: bool,
143    /// Name of the encrypted version of this column (ODCS: encryptedName)
144    #[serde(skip_serializing_if = "Option::is_none")]
145    pub encrypted_name: Option<String>,
146
147    // === Transformation Metadata ===
148    /// Source objects used in transformation (ODCS: transformSourceObjects)
149    #[serde(default, skip_serializing_if = "Vec::is_empty")]
150    pub transform_source_objects: Vec<String>,
151    /// Transformation logic/expression (ODCS: transformLogic)
152    #[serde(skip_serializing_if = "Option::is_none")]
153    pub transform_logic: Option<String>,
154    /// Human-readable transformation description (ODCS: transformDescription)
155    #[serde(skip_serializing_if = "Option::is_none")]
156    pub transform_description: Option<String>,
157
158    // === Examples & Documentation ===
159    /// Example values for this column (ODCS: examples)
160    #[serde(default, skip_serializing_if = "Vec::is_empty")]
161    pub examples: Vec<serde_json::Value>,
162    /// Default value for the column
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub default_value: Option<serde_json::Value>,
165
166    // === Relationships & References ===
167    /// ODCS v3.1.0 relationships (property-level references)
168    #[serde(default, skip_serializing_if = "Vec::is_empty")]
169    pub relationships: Vec<crate::models::PropertyRelationship>,
170    /// Authoritative definitions (ODCS: authoritativeDefinitions)
171    #[serde(default, skip_serializing_if = "Vec::is_empty")]
172    pub authoritative_definitions: Vec<crate::models::AuthoritativeDefinition>,
173
174    // === Quality & Validation ===
175    /// Quality rules and checks (ODCS: quality)
176    #[serde(skip_serializing_if = "Option::is_none")]
177    pub quality: Option<Vec<std::collections::HashMap<String, serde_json::Value>>>,
178    /// Enum values if this column is an enumeration type
179    #[serde(skip_serializing_if = "Option::is_none")]
180    pub enum_values: Option<Vec<String>>,
181
182    // === Tags & Custom Properties ===
183    /// Property-level tags (ODCS: tags)
184    #[serde(default, skip_serializing_if = "Vec::is_empty")]
185    pub tags: Vec<String>,
186    /// Custom properties for format-specific metadata
187    #[serde(default, skip_serializing_if = "std::collections::HashMap::is_empty")]
188    pub custom_properties: std::collections::HashMap<String, serde_json::Value>,
189}
190
191fn default_true() -> bool {
192    true
193}
194
195impl Default for ColumnData {
196    fn default() -> Self {
197        Self {
198            // Core Identity
199            id: None,
200            name: String::new(),
201            business_name: None,
202            description: None,
203            // Type Information
204            data_type: String::new(),
205            physical_type: None,
206            physical_name: None,
207            logical_type_options: None,
208            // Key Constraints
209            primary_key: false,
210            primary_key_position: None,
211            unique: false,
212            nullable: true,
213            // Partitioning & Clustering
214            partitioned: false,
215            partition_key_position: None,
216            clustered: false,
217            // Data Classification & Security
218            classification: None,
219            critical_data_element: false,
220            encrypted_name: None,
221            // Transformation Metadata
222            transform_source_objects: Vec::new(),
223            transform_logic: None,
224            transform_description: None,
225            // Examples & Documentation
226            examples: Vec::new(),
227            default_value: None,
228            // Relationships & References
229            relationships: Vec::new(),
230            authoritative_definitions: Vec::new(),
231            // Quality & Validation
232            quality: None,
233            enum_values: None,
234            // Tags & Custom Properties
235            tags: Vec::new(),
236            custom_properties: std::collections::HashMap::new(),
237        }
238    }
239}
240
241// Re-export for convenience
242pub use avro::AvroImporter;
243pub use cads::CADSImporter;
244pub use decision::DecisionImporter;
245pub use json_schema::JSONSchemaImporter;
246pub use knowledge::KnowledgeImporter;
247pub use odcl::ODCLImporter;
248pub use odcs::ODCSImporter;
249pub use odcs_shared::ParserError;
250pub use odps::ODPSImporter;
251pub use protobuf::ProtobufImporter;
252pub use sql::SQLImporter;
253
254/// Table requiring name input (for SQL imports)
255#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
256pub struct TableRequiringName {
257    pub table_index: usize,
258    pub suggested_name: Option<String>,
259}