uqa_sql/schema/sequences/
actions.rs1use crate::ast::{RelationPersistence, SequenceBound, SequenceRestart, TableLockMode};
9use crate::SQLError;
10
11pub fn sequence_alter_lock_mode(alter: &crate::ast::AlterSequence) -> TableLockMode {
12 if alter.role_owner.is_some()
13 || alter.persistence.is_some()
14 || alter.lifecycle != crate::ast::SequenceLifecycle::Unchanged
15 {
16 TableLockMode::AccessExclusive
17 } else {
18 TableLockMode::ShareRowExclusive
19 }
20}
21
22pub fn altered_sequence_persistence(
23 alter: &crate::ast::AlterSequence,
24 current: RelationPersistence,
25 relation_name: &str,
26) -> Result<RelationPersistence, SQLError> {
27 match alter.persistence {
28 None => Ok(current),
29 Some(RelationPersistence::Permanent | RelationPersistence::Unlogged)
30 if current == RelationPersistence::Temporary =>
31 {
32 Err(SQLError::Routine {
33 sqlstate: "42P16".into(),
34 message: format!(
35 "cannot change logged status of table \"{relation_name}\" because it is temporary"
36 ),
37 })
38 }
39 Some(requested @ (RelationPersistence::Permanent | RelationPersistence::Unlogged)) => {
40 Ok(requested)
41 }
42 Some(RelationPersistence::Temporary) => Err(SQLError::Internal(
43 "ALTER SEQUENCE cannot request temporary persistence".into(),
44 )),
45 }
46}
47
48pub fn sequence_alter_is_persistence_only(alter: &crate::ast::AlterSequence) -> bool {
49 alter.persistence.is_some()
50 && alter.role_owner.is_none()
51 && !sequence_alter_changes_value_parameters(alter)
52 && alter.ownership == crate::ast::SequenceOwnership::Unchanged
53}
54
55pub fn sequence_alter_changes_value_parameters(alter: &crate::ast::AlterSequence) -> bool {
57 alter.restart != SequenceRestart::Unchanged
58 || alter.increment.is_some()
59 || alter.start.is_some()
60 || alter.data_type.is_some()
61 || alter.min_value != SequenceBound::Unchanged
62 || alter.max_value != SequenceBound::Unchanged
63 || alter.cycle.is_some()
64 || alter.cache_size.is_some()
65}
66
67pub fn validate_sequence_role_owner_shape(
68 alter: &crate::ast::AlterSequence,
69) -> Result<(), SQLError> {
70 if sequence_alter_changes_value_parameters(alter)
71 || alter.ownership != crate::ast::SequenceOwnership::Unchanged
72 || alter.persistence.is_some()
73 || alter.lifecycle != crate::ast::SequenceLifecycle::Unchanged
74 {
75 return Err(SQLError::Internal(
76 "ALTER SEQUENCE OWNER TO cannot contain another action".into(),
77 ));
78 }
79 Ok(())
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85
86 #[test]
87 fn sequence_definition_and_relation_lifecycle_select_distinct_lock_modes() {
88 for (suffix, mode) in [
89 ("INCREMENT BY 2", TableLockMode::ShareRowExclusive),
90 ("CACHE 1", TableLockMode::ShareRowExclusive),
91 ("RESTART", TableLockMode::ShareRowExclusive),
92 ("OWNED BY NONE", TableLockMode::ShareRowExclusive),
93 ("OWNER TO owner", TableLockMode::AccessExclusive),
94 ("RENAME TO renamed", TableLockMode::AccessExclusive),
95 ("SET SCHEMA archive", TableLockMode::AccessExclusive),
96 ("SET LOGGED", TableLockMode::AccessExclusive),
97 ("SET UNLOGGED", TableLockMode::AccessExclusive),
98 ] {
99 let sql = format!("ALTER SEQUENCE ids {suffix}");
100 let crate::Statement::AlterSequence(alter) = crate::compile(&sql).unwrap().remove(0)
101 else {
102 panic!("expected ALTER SEQUENCE: {sql}");
103 };
104 assert_eq!(sequence_alter_lock_mode(&alter), mode, "{sql}");
105 }
106 }
107
108 #[test]
109 fn sequence_value_generation_distinguishes_explicit_options_from_owner_and_name_changes() {
110 for (suffix, expected) in [
111 ("AS bigint", true),
112 ("INCREMENT BY 1", true),
113 ("START WITH 1", true),
114 ("RESTART", true),
115 ("RESTART WITH 1", true),
116 ("MINVALUE 1", true),
117 ("NO MINVALUE", true),
118 ("MAXVALUE 10", true),
119 ("NO MAXVALUE", true),
120 ("CYCLE", true),
121 ("NO CYCLE", true),
122 ("CACHE 1", true),
123 ("OWNED BY items.id CACHE 3", true),
124 ("OWNED BY NONE", false),
125 ("OWNED BY items.id", false),
126 ("OWNER TO owner", false),
127 ("RENAME TO renamed", false),
128 ("SET SCHEMA archive", false),
129 ("SET LOGGED", false),
130 ] {
131 let sql = format!("ALTER SEQUENCE ids {suffix}");
132 let crate::Statement::AlterSequence(alter) = crate::compile(&sql).unwrap().remove(0)
133 else {
134 panic!("expected an ALTER SEQUENCE statement: {sql}");
135 };
136 assert_eq!(
137 sequence_alter_changes_value_parameters(&alter),
138 expected,
139 "{sql}"
140 );
141 }
142 }
143}