uqa_sql/semantics/rules/
insert_inputs.rs1use crate::{
9 plan::InsertPlan,
10 semantics::{
11 rules::analysis::RuleAnalysisContext,
12 view_rewrite::context::{stored_view_schema, ViewRewriteContext},
13 },
14 ColumnType, SQLError,
15};
16use std::collections::BTreeSet;
17pub fn view_rule_insert_column_type(
18 context: ViewRewriteContext<'_>,
19 stmt: &InsertPlan,
20 input_position: usize,
21) -> Result<Option<ColumnType>, SQLError> {
22 for plan in &stmt.view_rule_insert_plans {
23 let Some(column) = plan.supplied_columns.get(input_position) else {
24 continue;
25 };
26 let definition = context
27 .catalog
28 .view_definition(&plan.relation)?
29 .ok_or_else(|| SQLError::UnknownTable(plan.relation.clone()))?;
30 let schema = stored_view_schema(context, &definition)?;
31 let Some(position) =
32 schema
33 .columns()
34 .iter()
35 .enumerate()
36 .find_map(|(position, internal)| {
37 let public = schema.public_name(position).unwrap_or(internal);
38 (public == column).then_some(position)
39 })
40 else {
41 return Err(SQLError::UnknownColumn(format!(
42 "{}.{}",
43 plan.relation, column
44 )));
45 };
46 return Ok(schema.column_type(position).cloned());
47 }
48 Ok(None)
49}
50
51pub fn required_view_rule_insert_input_positions(
52 context: RuleAnalysisContext<'_>,
53 stmt: &InsertPlan,
54) -> Result<Option<BTreeSet<usize>>, SQLError> {
55 let mut required = BTreeSet::new();
56 for plan in &stmt.view_rule_insert_plans {
57 let Some(columns) = super::analysis::relation_rule_row_columns(
58 context,
59 &plan.relation,
60 crate::ast::RuleEvent::Insert,
61 )?
62 else {
63 return Ok(None);
64 };
65 required.extend(
66 plan.supplied_columns
67 .iter()
68 .enumerate()
69 .filter_map(|(position, column)| columns.contains(column).then_some(position)),
70 );
71 if super::analysis::relation_suppresses_original_query(
72 context,
73 &plan.relation,
74 crate::ast::RuleEvent::Insert,
75 )? {
76 break;
77 }
78 }
79 Ok(Some(required))
80}