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