sql_fun_sqlast/sem/constraint/
primary.rs1use sql_fun_core::IVec;
2
3use crate::{
4 sem::{
5 AnalysisError, AnalysisProblem, ColumnName, Constraint, CreateIndex, ImplicitChange,
6 ParseContext, TableName, create_index::IndexElementCollection,
7 },
8 syn::ListOpt,
9};
10
11use super::AnalizeConstraint;
12
13#[derive(Debug, Clone)]
15pub struct PrimaryKeyConstraint {
16 name: String,
17 table: Option<TableName>,
18 keys: IVec<ColumnName>,
19}
20
21impl PrimaryKeyConstraint {
22 #[must_use]
24 pub fn name(&self) -> &str {
25 &self.name
26 }
27
28 pub fn implicit_changes(&self) -> Result<Vec<ImplicitChange>, AnalysisError> {
30 let Some(table) = &self.table else {
31 AnalysisError::raise_unexpected_none("constraint.table")?
32 };
33 let key_columns = IndexElementCollection::from_column_names(&self.keys);
34
35 Ok(vec![ImplicitChange::from(CreateIndex::new(
36 &self.name,
37 table,
38 &key_columns,
39 ))])
40 }
41
42 #[must_use]
44 pub fn keys(&self) -> &IVec<ColumnName> {
45 &self.keys
46 }
47}
48
49impl<TParseContext> AnalizeConstraint<TParseContext> for PrimaryKeyConstraint
50where
51 TParseContext: ParseContext,
52{
53 fn analyze(
54 context: &mut TParseContext,
55 target_table: Option<&TableName>,
56 constraint: crate::syn::Constraint,
57 ) -> Result<Constraint, AnalysisError> {
58 let name = constraint.get_conname();
59 let Some(keys) = constraint
60 .get_keys()
61 .map_values(|v| v.as_string().get_sval())
62 else {
63 AnalysisError::raise_unexpected_none("constraint.keys")?
64 };
65 let keys: Vec<_> = keys.into_iter().map(ColumnName::from).collect();
66
67 if let Some(table_name) = target_table {
68 if let Some(table) = context.get_table(table_name).cloned() {
69 for key_col_name in &keys {
70 if !table.has_column(key_col_name) {
71 context.report_problem(AnalysisProblem::column_not_found_in_table(
72 table_name,
73 key_col_name,
74 ))?;
75 }
76 }
77 } else {
78 context.report_problem(AnalysisProblem::relation_not_found(table_name))?;
79 }
80 }
81
82 Ok(Constraint::PrimaryKey(Self {
83 name,
84 table: target_table.cloned(),
85 keys: keys.into(),
86 }))
87 }
88}