Skip to content

Commit 540eb59

Browse files
committed
fix: accept proven dependency wildcards
1 parent 7577ebc commit 540eb59

2 files changed

Lines changed: 48 additions & 1 deletion

File tree

‎crates/sqlbuild-rules-native/src/engine/tests/test_evaluation.rs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,22 @@ fn given_enforced_contract_outputs_when_evaluating_explicit_type_rule_then_retur
347347
expected_fault_count: 1,
348348
expected_message_fragment: "wildcard output",
349349
},
350+
test_types::ExplicitOutputTypeTestCase {
351+
description: "proven dependency import wildcard",
352+
query_sql: "WITH final AS (SELECT * FROM __ref(\"orders\")) SELECT order_id FROM final",
353+
columns: json!([{"name": "order_id", "type": "INTEGER", "type_proven": true}]),
354+
contract: "enforced",
355+
expected_fault_count: 0,
356+
expected_message_fragment: "",
357+
},
358+
test_types::ExplicitOutputTypeTestCase {
359+
description: "unproven dependency import wildcard",
360+
query_sql: "WITH final AS (SELECT * FROM __ref(\"orders\")) SELECT order_id FROM final",
361+
columns: json!([{"name": "order_id", "type": "INTEGER", "type_proven": false}]),
362+
contract: "enforced",
363+
expected_fault_count: 1,
364+
expected_message_fragment: "wildcard output",
365+
},
350366
test_types::ExplicitOutputTypeTestCase {
351367
description: "positional set branches require casts",
352368
query_sql: "SELECT order_id FROM current_orders UNION ALL SELECT order_id FROM archived_orders",

‎crates/sqlbuild-rules-native/src/rules/_helpers/explicit_output_types.rs‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use crate::constants::ENFORCED_CONTRACT;
22
use crate::models::{Column, Fault, Model, RuleMetadata};
33
use crate::rules::_helpers::evaluation::{plain_select, root_select, sole_table_name, top_ctes};
44
use crate::rules::models::FaultCollector;
5-
use sqlparser::ast::{Expr, Query, Select, SelectItem, SetExpr, SetQuantifier, Spanned};
5+
use sqlparser::ast::{
6+
Expr, Query, Select, SelectItem, SetExpr, SetQuantifier, Spanned, TableFactor,
7+
};
68

79
#[derive(Clone, Copy)]
810
struct OutputScope<'a> {
@@ -95,6 +97,9 @@ impl OutputRule<'_> {
9597
item,
9698
SelectItem::Wildcard(_) | SelectItem::QualifiedWildcard(_, _)
9799
) {
100+
if proven_dependency_wildcard(select, scope.columns) {
101+
continue;
102+
}
98103
self.push(
99104
Some(source_position(item)),
100105
"wildcard output does not establish enforced contract types explicitly".into(),
@@ -168,6 +173,29 @@ impl OutputRule<'_> {
168173
}
169174
}
170175

176+
fn proven_dependency_wildcard(select: &Select, columns: &[Column]) -> bool {
177+
let Some(source) = select.from.first().filter(|_| select.from.len() == 1) else {
178+
return false;
179+
};
180+
if !plain_select(select, true) || !source.joins.is_empty() {
181+
return false;
182+
}
183+
let TableFactor::Table {
184+
name,
185+
args: Some(_),
186+
..
187+
} = &source.relation
188+
else {
189+
return false;
190+
};
191+
let dependency = name.to_string().to_ascii_lowercase();
192+
matches!(dependency.as_str(), "__ref" | "__source")
193+
&& columns
194+
.iter()
195+
.filter(|column| !column.data_type.is_empty())
196+
.all(|column| column.type_proven)
197+
}
198+
171199
fn final_cte_output_boundary<'a>(
172200
query: &'a Query,
173201
columns: &[Column],
@@ -234,6 +262,9 @@ fn columns_in_output_order_with_missing(
234262
let Some(output_names) = set_expression_output_names_with_missing(set_expr) else {
235263
return columns.to_vec();
236264
};
265+
if output_names.len() == 1 && output_names[0].is_none() {
266+
return columns.to_vec();
267+
}
237268
output_names
238269
.into_iter()
239270
.enumerate()

0 commit comments

Comments
 (0)