1use std::fmt::Write;
2
3use crate::create_column::{CreateColumn, CreateColumnImpl};
4use crate::error::Error;
5use crate::Value;
6
7pub trait CreateTable<'until_build, 'post_build> {
11 fn add_column(self, column: CreateColumnImpl<'until_build, 'post_build>) -> Self;
15
16 fn if_not_exists(self) -> Self;
20
21 fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error>;
28}
29
30pub struct CreateTableData<'until_build, 'post_build> {
34 pub(crate) name: &'until_build str,
35 pub(crate) columns: Vec<CreateColumnImpl<'until_build, 'post_build>>,
36 pub(crate) if_not_exists: bool,
37 pub(crate) lookup: Vec<Value<'post_build>>,
38 pub(crate) pre_statements: Vec<(String, Vec<Value<'post_build>>)>,
39 pub(crate) statements: Vec<(String, Vec<Value<'post_build>>)>,
40}
41
42pub enum CreateTableImpl<'until_build, 'post_build> {
48 #[cfg(feature = "sqlite")]
52 SQLite(CreateTableData<'until_build, 'post_build>),
53 #[cfg(feature = "postgres")]
57 Postgres(CreateTableData<'until_build, 'post_build>),
58}
59
60impl<'until_build, 'post_build> CreateTable<'until_build, 'post_build>
61 for CreateTableImpl<'until_build, 'post_build>
62{
63 fn add_column(mut self, column: CreateColumnImpl<'until_build, 'post_build>) -> Self {
64 match self {
65 #[cfg(feature = "sqlite")]
66 CreateTableImpl::SQLite(ref mut d) => d.columns.push(column),
67 #[cfg(feature = "postgres")]
68 CreateTableImpl::Postgres(ref mut d) => d.columns.push(column),
69 }
70 self
71 }
72
73 fn if_not_exists(mut self) -> Self {
74 match self {
75 #[cfg(feature = "sqlite")]
76 CreateTableImpl::SQLite(ref mut d) => d.if_not_exists = true,
77 #[cfg(feature = "postgres")]
78 CreateTableImpl::Postgres(ref mut d) => d.if_not_exists = true,
79 }
80 self
81 }
82
83 fn build(self) -> Result<Vec<(String, Vec<Value<'post_build>>)>, Error> {
84 match self {
85 #[cfg(feature = "sqlite")]
86 CreateTableImpl::SQLite(mut d) => {
87 let mut s = format!(
88 "CREATE TABLE{} \"{}\" (",
89 if d.if_not_exists {
90 " IF NOT EXISTS"
91 } else {
92 ""
93 },
94 d.name
95 );
96
97 let columns_len = d.columns.len() - 1;
98 for (idx, mut x) in d.columns.into_iter().enumerate() {
99 if let CreateColumnImpl::SQLite(cci) = &mut x {
100 cci.statements = Some(&mut d.statements)
101 }
102
103 x.build(&mut s)?;
104
105 if idx != columns_len {
106 write!(s, ", ").unwrap();
107 }
108 }
109
110 write!(s, ") STRICT; ").unwrap();
111
112 let mut statements = vec![(s, d.lookup)];
113 statements.extend(d.statements);
114
115 Ok(statements)
116 }
117 #[cfg(feature = "postgres")]
118 CreateTableImpl::Postgres(mut d) => {
119 let mut s = format!(
120 "CREATE TABLE{} \"{}\" (",
121 if d.if_not_exists {
122 " IF NOT EXISTS"
123 } else {
124 ""
125 },
126 d.name
127 );
128
129 let columns_len = d.columns.len() - 1;
130 for (idx, mut x) in d.columns.into_iter().enumerate() {
131 #[allow(irrefutable_let_patterns)]
132 if let CreateColumnImpl::Postgres(cci) = &mut x {
133 cci.pre_statements = Some(&mut d.pre_statements);
134 cci.statements = Some(&mut d.statements);
135 }
136
137 x.build(&mut s)?;
138
139 if idx != columns_len {
140 write!(s, ", ").unwrap();
141 }
142 }
143
144 write!(s, "); ").unwrap();
145
146 let mut statements = d.pre_statements;
147 statements.push((s, d.lookup));
148 statements.extend(d.statements);
149
150 Ok(statements)
151 }
152 }
153 }
154}