pgevolve_core/render/
sequence.rs1use crate::ir::sequence::Sequence;
4use crate::plan::rewrite::sql as rewrite_sql;
5
6#[must_use]
11pub fn render_sequence(s: &Sequence) -> String {
12 let mut out = rewrite_sql::create_sequence(s);
13 out.push('\n');
14 if let Some(comment) = &s.comment {
15 out.push_str(&rewrite_sql::comment_on_sequence(
16 &s.qname,
17 Some(comment.as_str()),
18 ));
19 out.push('\n');
20 }
21 out
22}
23
24#[cfg(test)]
25mod tests {
26 use super::*;
27 use crate::identifier::Identifier;
28 use crate::identifier::QualifiedName;
29 use crate::ir::column_type::ColumnType;
30 use crate::ir::sequence::{Sequence, SequenceOwner};
31
32 fn id(s: &str) -> Identifier {
33 Identifier::from_unquoted(s).unwrap()
34 }
35
36 fn qn(schema: &str, name: &str) -> QualifiedName {
37 QualifiedName::new(id(schema), id(name))
38 }
39
40 fn assert_pg_parseable(sql: &str) {
41 let r = pg_query::parse(sql);
42 assert!(r.is_ok(), "pg_query rejected SQL:\n{sql}\nerr: {r:?}");
43 }
44
45 fn base_seq() -> Sequence {
46 Sequence {
47 qname: qn("app", "users_id_seq"),
48 data_type: ColumnType::BigInt,
49 start: 1,
50 increment: 1,
51 min_value: None,
52 max_value: None,
53 cache: 1,
54 cycle: false,
55 owned_by: None,
56 comment: None,
57 owner: None,
58 grants: vec![],
59 }
60 }
61
62 #[test]
63 fn plain_sequence_renders() {
64 let sql = render_sequence(&base_seq());
65 assert!(sql.contains("CREATE SEQUENCE app.users_id_seq"));
66 assert!(sql.contains("AS bigint"));
67 assert!(!sql.contains("COMMENT"));
68 assert_pg_parseable(&sql);
69 }
70
71 #[test]
72 fn sequence_with_min_max_renders() {
73 let seq = Sequence {
74 min_value: Some(1),
75 max_value: Some(9_999_999),
76 ..base_seq()
77 };
78 let sql = render_sequence(&seq);
79 assert!(sql.contains("MINVALUE 1"));
80 assert!(sql.contains("MAXVALUE 9999999"));
81 assert_pg_parseable(&sql);
82 }
83
84 #[test]
85 fn sequence_with_no_minmax_renders() {
86 let sql = render_sequence(&base_seq());
87 assert!(sql.contains("NO MINVALUE"));
88 assert!(sql.contains("NO MAXVALUE"));
89 assert_pg_parseable(&sql);
90 }
91
92 #[test]
93 fn cycling_sequence_renders() {
94 let seq = Sequence {
95 cycle: true,
96 ..base_seq()
97 };
98 let sql = render_sequence(&seq);
99 assert!(sql.contains(" CYCLE"));
100 assert!(!sql.contains("NO CYCLE"));
101 assert_pg_parseable(&sql);
102 }
103
104 #[test]
105 fn sequence_with_owned_by_renders() {
106 let seq = Sequence {
107 owned_by: Some(SequenceOwner {
108 table: qn("app", "users"),
109 column: id("id"),
110 }),
111 ..base_seq()
112 };
113 let sql = render_sequence(&seq);
114 assert!(sql.contains("OWNED BY app.users.id"));
115 assert_pg_parseable(&sql);
116 }
117
118 #[test]
119 fn sequence_with_comment_renders() {
120 let seq = Sequence {
121 comment: Some("primary key sequence".into()),
122 ..base_seq()
123 };
124 let sql = render_sequence(&seq);
125 assert!(sql.contains("COMMENT ON SEQUENCE app.users_id_seq IS 'primary key sequence';"));
126 assert_pg_parseable(&sql);
127 }
128
129 #[test]
130 fn smallint_sequence_renders() {
131 let seq = Sequence {
132 data_type: ColumnType::SmallInt,
133 ..base_seq()
134 };
135 let sql = render_sequence(&seq);
136 assert!(sql.contains("AS smallint"));
137 assert_pg_parseable(&sql);
138 }
139
140 #[test]
141 fn integer_sequence_renders() {
142 let seq = Sequence {
143 data_type: ColumnType::Integer,
144 start: 100,
145 increment: 10,
146 cache: 5,
147 ..base_seq()
148 };
149 let sql = render_sequence(&seq);
150 assert!(sql.contains("AS integer"));
151 assert!(sql.contains("INCREMENT BY 10"));
152 assert!(sql.contains("START WITH 100"));
153 assert!(sql.contains("CACHE 5"));
154 assert_pg_parseable(&sql);
155 }
156}