validation done.

This commit is contained in:
dal 2025-02-11 12:26:07 -07:00
parent aee795b07b
commit 32efa01b51
No known key found for this signature in database
GPG Key ID: 16F4B0E1E9F61122
3 changed files with 90 additions and 65 deletions

View File

@ -99,7 +99,7 @@ models:
expr: "created_at::date"
type: "date"
description: "Date when customer signed up"
stored_values: true # Enable value caching
searchable: true # Enable value caching
# Define measures
measures:
@ -197,7 +197,7 @@ dimensions:
- name: country
expr: "country_code"
type: "string"
stored_values: true # Values will be cached
searchable: true # Values will be cached
```
### Default SQL Generation

View File

@ -30,8 +30,11 @@ pub struct Model {
schema: Option<String>,
description: String,
model: Option<String>,
#[serde(default)]
entities: Vec<Entity>,
#[serde(default)]
dimensions: Vec<Dimension>,
#[serde(default)]
measures: Vec<Measure>,
}
@ -56,7 +59,7 @@ pub struct Dimension {
dimension_type: String,
description: String,
#[serde(default = "bool::default")]
stored_values: bool,
searchable: bool,
}
#[derive(Debug, Deserialize, Serialize)]
@ -334,16 +337,18 @@ impl ModelFile {
// If no project_path, the model should exist in the current project
if entity.project_path.is_none() && !model_names.contains(referenced_model) {
errors.push(format!(
"Model '{}' references non-existent model '{}' in expression '{}'",
model.name, referenced_model, entity.expr
errors.push(format!(
"Model '{}' references non-existent model '{}' (via {})",
model.name,
referenced_model,
if entity.ref_.is_some() { "ref" } else { "name" }
));
}
}
}
}
}
// Warnings
// Warnings
for model in &self.model.models {
if model.description.is_empty() {
println!("⚠️ Warning: Model '{}' has no description", model.name);
@ -571,18 +576,37 @@ impl ModelFile {
})
.collect::<Vec<_>>();
println!("🔍 Searching for model '{}' in directory: {}",
entity.ref_.as_ref().unwrap_or(&entity.name),
target_path.display()
);
println!(" Found {} YAML files to search", model_files.len());
let mut found_model = false;
for model_file in model_files {
println!(" Checking file: {}", model_file.path().display());
if let Ok(content) = std::fs::read_to_string(model_file.path()) {
if let Ok(model_def) = serde_yaml::from_str::<BusterModel>(&content) {
// Extract model name from entity.expr (assuming format "model_name.field")
if let Some(referenced_model) = entity.ref_.as_ref().unwrap_or(&entity.name).split('.').next() {
if model_def.models.iter().any(|m| m.name == referenced_model) {
match serde_yaml::from_str::<BusterModel>(&content) {
Ok(model_def) => {
// Get the model reference from ref_ field if present, otherwise use name
let referenced_model = entity.ref_.as_ref().unwrap_or(&entity.name);
println!(" - Found {} models in file", model_def.models.len());
for m in &model_def.models {
println!(" - Checking model: {}", m.name);
}
if model_def.models.iter().any(|m| m.name == *referenced_model) {
found_model = true;
println!(" ✅ Found matching model!");
break;
}
}
Err(e) => {
println!(" ⚠️ Failed to parse YAML content: {}", e);
println!(" Content:\n{}", content);
}
}
} else {
println!(" ⚠️ Failed to read file content");
}
}
@ -590,13 +614,14 @@ impl ModelFile {
validation_errors.push(ValidationError {
error_type: ValidationErrorType::ModelNotFound,
message: format!(
"Referenced model from expression '{}' not found in project '{}'",
entity.expr, project_path_display
"Referenced model '{}' not found in project '{}'",
entity.ref_.as_ref().unwrap_or(&entity.name),
project_path_display
),
column_name: None,
suggestion: Some(format!(
"Verify that the model referenced in '{}' exists in the target project",
entity.expr
"Verify that the model '{}' exists in the target project",
entity.ref_.as_ref().unwrap_or(&entity.name)
)),
});
}
@ -611,8 +636,8 @@ impl ModelFile {
suggestion: Some("Add data_source_name to the referenced project's buster.yml".to_string()),
});
}
}
Err(e) => {
}
Err(e) => {
validation_errors.push(ValidationError {
error_type: ValidationErrorType::InvalidBusterYml,
message: format!(
@ -1037,8 +1062,8 @@ mod tests {
// Create buster.yml
let buster_yml = r#"
data_source_name: "test_source"
schema: "test_schema"
data_source_name: "test_source"
schema: "test_schema"
"#;
create_test_yaml(temp_dir.path(), "buster.yml", buster_yml).await?;
@ -1206,21 +1231,21 @@ mod tests {
// Create multiple model files
for i in 1..=3 {
let model_yml = format!(r#"
version: 1
models:
version: 1
models:
- name: test_model_{}
description: "Test model {}"
entities: []
dimensions:
- name: dim1
expr: "col1"
type: "string"
description: "First dimension"
measures:
- name: measure1
expr: "col2"
agg: "sum"
description: "First measure"
entities: []
dimensions:
- name: dim1
expr: "col1"
type: "string"
description: "First dimension"
measures:
- name: measure1
expr: "col2"
agg: "sum"
description: "First measure"
"#, i, i);
create_test_yaml(temp_dir.path(), &format!("test_model_{}.yml", i), &model_yml).await?;
}
@ -1238,8 +1263,8 @@ mod tests {
// Create buster.yml
let buster_yml = r#"
data_source_name: "test_source"
schema: "test_schema"
data_source_name: "test_source"
schema: "test_schema"
"#;
create_test_yaml(temp_dir.path(), "buster.yml", buster_yml).await?;
@ -1260,8 +1285,8 @@ mod tests {
// Create buster.yml
let buster_yml = r#"
data_source_name: "test_source"
schema: "test_schema"
data_source_name: "test_source"
schema: "test_schema"
"#;
create_test_yaml(temp_dir.path(), "buster.yml", buster_yml).await?;
@ -1308,7 +1333,7 @@ mod tests {
// Create buster.yml
let buster_yml = r#"
data_source_name: "test_source"
schema: "test_schema"
schema: "test_schema"
"#;
create_test_yaml(temp_dir.path(), "buster.yml", buster_yml).await?;

View File

@ -57,7 +57,7 @@ pub struct Dimension {
pub dimension_type: String,
pub description: String,
#[serde(default = "bool::default")]
pub stored_values: bool,
pub searchable: bool,
}
#[derive(Debug, Serialize, Deserialize)]