1use crate::{
9 ast::{ColumnDef, TableKeyConstraint, TableKeyConstraintKind},
10 SQLError,
11};
12pub struct AddedKeyRelation<'a> {
14 pub table: &'a str,
15 pub columns: &'a [ColumnDef],
16 pub keys: &'a [TableKeyConstraint],
17 pub partition: Option<&'a crate::ast::PartitionSpec>,
19}
20
21pub fn validate_added_key(
23 relation: &AddedKeyRelation<'_>,
24 key: &TableKeyConstraint,
25) -> Result<(), SQLError> {
26 if let Some(column) = key
27 .columns
28 .iter()
29 .enumerate()
30 .find_map(|(position, column)| key.columns[..position].contains(column).then_some(column))
31 {
32 return Err(definition::repeated_key_column(key.kind, column));
33 }
34 let column = |name: &str| relation.columns.iter().find(|column| column.name == name);
35 let system = definition::is_system_column;
36 if key.without_overlaps {
37 if let Some(period) = key.columns.last() {
38 if let Some(found) = column(period) {
39 definition::validate_overlaps_column(period, Some(&found.ty))?;
40 } else if system(period) {
41 definition::validate_overlaps_column(period, None)?;
42 }
43 }
44 }
45 definition::validate_overlaps_key_length(key)?;
46 if key.kind == TableKeyConstraintKind::PrimaryKey {
47 for name in &key.columns {
48 if column(name).is_some() {
49 continue;
50 }
51 if system(name) {
52 return Err(SQLError::Routine {
53 sqlstate: "0A000".into(),
54 message: format!("cannot add not-null constraint on system column \"{name}\""),
55 });
56 }
57 let local = uqa_core::RelationIdentity::from_legacy_name(relation.table)
58 .map_err(SQLError::Internal)?;
59 return Err(SQLError::Routine {
60 sqlstate: "42703".into(),
61 message: format!(
62 "column \"{name}\" of relation \"{}\" does not exist",
63 local.name
64 ),
65 });
66 }
67 }
68 definition::validate_key_definition(
69 &definition::KeyRelation {
70 table: relation.table,
71 columns: relation.columns,
72 partition: relation.partition,
73 has_primary_key: relation
74 .keys
75 .iter()
76 .any(|existing| existing.kind == TableKeyConstraintKind::PrimaryKey),
77 },
78 key,
79 )
80}
81
82pub fn transform_column_keys(
84 relation: &str,
85 keys: &[TableKeyConstraint],
86) -> Result<Vec<TableKeyConstraint>, SQLError> {
87 if keys
88 .iter()
89 .filter(|key| key.kind == TableKeyConstraintKind::PrimaryKey)
90 .count()
91 > 1
92 {
93 return Err(definition::multiple_primary_keys(relation));
94 }
95 Ok(definition::index_order(keys.to_vec()))
96}
97
98pub fn apply_primary_key_columns(
100 table: &str,
101 constraint: &TableKeyConstraint,
102 columns: &mut [ColumnDef],
103) -> Result<(), String> {
104 if constraint.kind == TableKeyConstraintKind::PrimaryKey {
105 for key_column in &constraint.columns {
106 let column = columns
107 .iter_mut()
108 .find(|column| column.name == *key_column)
109 .ok_or_else(|| {
110 format!("column `{key_column}` does not exist on table `{table}`")
111 })?;
112 column.not_null = true;
113 }
114 }
115 Ok(())
116}
117
118pub mod definition;
119
120#[cfg(test)]
121mod tests;