limbo_sqlite3_parser/parser/ast/
check.rs1use crate::ast::*;
3use crate::custom_err;
4use std::fmt::{Display, Formatter};
5
6impl Cmd {
7 pub fn stmt(&self) -> &Stmt {
9 match self {
10 Self::Explain(stmt) => stmt,
11 Self::ExplainQueryPlan(stmt) => stmt,
12 Self::Stmt(stmt) => stmt,
13 }
14 }
15 pub fn column_count(&self) -> ColumnCount {
17 match self {
18 Self::Explain(_) => ColumnCount::Fixed(8),
19 Self::ExplainQueryPlan(_) => ColumnCount::Fixed(4),
20 Self::Stmt(stmt) => stmt.column_count(),
21 }
22 }
23 pub fn is_explain(&self) -> bool {
25 matches!(self, Self::Explain(_) | Self::ExplainQueryPlan(_))
26 }
27 pub fn readonly(&self) -> bool {
29 self.stmt().readonly()
30 }
31 pub fn check(&self) -> Result<(), ParserError> {
33 self.stmt().check()
34 }
35}
36
37pub enum ColumnCount {
39 Dynamic,
41 Fixed(usize),
43 None,
45}
46
47impl ColumnCount {
48 fn incr(&mut self) {
49 if let Self::Fixed(n) = self {
50 *n += 1;
51 }
52 }
53}
54
55impl Stmt {
56 pub fn column_count(&self) -> ColumnCount {
58 match self {
59 Self::Delete(delete) => {
60 let Delete { returning, .. } = &**delete;
61 match returning {
62 Some(returning) => column_count(returning),
63 None => ColumnCount::None,
64 }
65 }
66 Self::Insert(insert) => {
67 let Insert { returning, .. } = &**insert;
68 match returning {
69 Some(returning) => column_count(returning),
70 None => ColumnCount::None,
71 }
72 }
73 Self::Pragma(..) => ColumnCount::Dynamic,
74 Self::Select(s) => s.column_count(),
75 Self::Update(update) => {
76 let Update { returning, .. } = &**update;
77 match returning {
78 Some(returning) => column_count(returning),
79 None => ColumnCount::None,
80 }
81 }
82 _ => ColumnCount::None,
83 }
84 }
85
86 pub fn readonly(&self) -> bool {
88 match self {
89 Self::Attach { .. } => true,
90 Self::Begin(..) => true,
91 Self::Commit(..) => true,
92 Self::Detach(..) => true,
93 Self::Pragma(..) => true, Self::Reindex { .. } => true,
95 Self::Release(..) => true,
96 Self::Rollback { .. } => true,
97 Self::Savepoint(..) => true,
98 Self::Select(..) => true,
99 _ => false,
100 }
101 }
102
103 pub fn check(&self) -> Result<(), ParserError> {
105 match self {
106 Self::AlterTable(alter_table) => {
107 let (_, body) = &**alter_table;
108 match body {
109 AlterTableBody::AddColumn(cd) => {
110 for c in cd {
111 if let ColumnConstraint::PrimaryKey { .. } = c {
112 return Err(custom_err!("Cannot add a PRIMARY KEY column"));
113 }
114 if let ColumnConstraint::Unique(..) = c {
115 return Err(custom_err!("Cannot add a UNIQUE column"));
116 }
117 }
118 }
119 _ => {}
120 }
121 Ok(())
122 }
123 Self::CreateTable {
124 temporary,
125 tbl_name,
126 body,
127 ..
128 } => {
129 if *temporary {
130 if let Some(ref db_name) = tbl_name.db_name {
131 if db_name != "TEMP" {
132 return Err(custom_err!("temporary table name must be unqualified"));
133 }
134 }
135 }
136 body.check(tbl_name)
137 }
138 Self::CreateView {
139 view_name,
140 columns: Some(columns),
141 select,
142 ..
143 } => {
144 for (i, c) in columns.iter().enumerate() {
146 for o in &columns[i + 1..] {
147 if c.col_name == o.col_name {
148 return Err(custom_err!("duplicate column name: {}", c.col_name,));
149 }
150 }
151 }
152 match select.column_count() {
154 ColumnCount::Fixed(n) if n != columns.len() => Err(custom_err!(
155 "expected {} columns for {} but got {}",
156 columns.len(),
157 view_name,
158 n
159 )),
160 _ => Ok(()),
161 }
162 }
163 Self::Delete(delete) => {
164 let Delete {
165 order_by, limit, ..
166 } = &**delete;
167 if let Some(_) = order_by {
168 if limit.is_none() {
169 return Err(custom_err!("ORDER BY without LIMIT on DELETE"));
170 }
171 }
172 Ok(())
173 }
174 Self::Insert(insert) => {
175 let Insert { columns, body, .. } = &**insert;
176 if columns.is_none() {
177 return Ok(());
178 }
179 let columns = columns.as_ref().unwrap();
180 match &*body {
181 InsertBody::Select(select, ..) => match select.body.select.column_count() {
182 ColumnCount::Fixed(n) if n != columns.len() => {
183 Err(custom_err!("{} values for {} columns", n, columns.len()))
184 }
185 _ => Ok(()),
186 },
187 InsertBody::DefaultValues => {
188 Err(custom_err!("0 values for {} columns", columns.len()))
189 }
190 }
191 }
192 Self::Update(update) => {
193 let Update {
194 order_by, limit, ..
195 } = &**update;
196 if let Some(_) = order_by {
197 if limit.is_none() {
198 return Err(custom_err!("ORDER BY without LIMIT on UPDATE"));
199 }
200 }
201
202 Ok(())
203 }
204 _ => Ok(()),
205 }
206 }
207}
208
209impl CreateTableBody {
210 pub fn check(&self, tbl_name: &QualifiedName) -> Result<(), ParserError> {
212 if let Self::ColumnsAndConstraints {
213 columns,
214 constraints: _,
215 options,
216 } = self
217 {
218 let mut generated_count = 0;
219 for c in columns.values() {
220 if c.col_name == "rowid" {
221 return Err(custom_err!("cannot use reserved word: ROWID"));
222 }
223 for cs in &c.constraints {
224 if let ColumnConstraint::Generated { .. } = cs.constraint {
225 generated_count += 1;
226 }
227 }
228 }
229 if generated_count == columns.len() {
230 return Err(custom_err!("must have at least one non-generated column"));
231 }
232
233 if options.contains(TableOptions::STRICT) {
234 for c in columns.values() {
235 match &c.col_type {
236 Some(Type { name, .. }) => {
237 if !(name.eq_ignore_ascii_case("INT")
239 || name.eq_ignore_ascii_case("INTEGER")
240 || name.eq_ignore_ascii_case("REAL")
241 || name.eq_ignore_ascii_case("TEXT")
242 || name.eq_ignore_ascii_case("BLOB")
243 || name.eq_ignore_ascii_case("ANY"))
244 {
245 return Err(custom_err!(
246 "unknown datatype for {}.{}: \"{}\"",
247 tbl_name,
248 c.col_name,
249 name
250 ));
251 }
252 }
253 _ => {
254 return Err(custom_err!(
256 "missing datatype for {}.{}",
257 tbl_name,
258 c.col_name
259 ));
260 }
261 }
262 }
263 }
264 if options.contains(TableOptions::WITHOUT_ROWID) && !self.has_primary_key() {
265 return Err(custom_err!("PRIMARY KEY missing on table {}", tbl_name,));
266 }
267 }
268 Ok(())
269 }
270
271 pub fn has_primary_key(&self) -> bool {
273 if let Self::ColumnsAndConstraints {
274 columns,
275 constraints,
276 ..
277 } = self
278 {
279 for col in columns.values() {
280 for c in col {
281 if let ColumnConstraint::PrimaryKey { .. } = c {
282 return true;
283 }
284 }
285 }
286 if let Some(constraints) = constraints {
287 for c in constraints {
288 if let TableConstraint::PrimaryKey { .. } = c.constraint {
289 return true;
290 }
291 }
292 }
293 }
294 false
295 }
296}
297
298impl<'a> IntoIterator for &'a ColumnDefinition {
299 type Item = &'a ColumnConstraint;
300 type IntoIter = std::iter::Map<
301 std::slice::Iter<'a, NamedColumnConstraint>,
302 fn(&'a NamedColumnConstraint) -> &'a ColumnConstraint,
303 >;
304
305 fn into_iter(self) -> Self::IntoIter {
306 self.constraints.iter().map(|nc| &nc.constraint)
307 }
308}
309
310impl Select {
311 pub fn column_count(&self) -> ColumnCount {
313 self.body.select.column_count()
314 }
315}
316
317impl OneSelect {
318 pub fn column_count(&self) -> ColumnCount {
320 match self {
321 Self::Select(select) => {
322 let SelectInner { columns, .. } = &**select;
323 column_count(columns)
324 }
325 Self::Values(values) => {
326 assert!(!values.is_empty()); ColumnCount::Fixed(values[0].len())
328 }
329 }
330 }
331 pub fn push(values: &mut Vec<Vec<Expr>>, v: Vec<Expr>) -> Result<(), ParserError> {
333 if values[0].len() != v.len() {
334 return Err(custom_err!("all VALUES must have the same number of terms"));
335 }
336 values.push(v);
337 Ok(())
338 }
339}
340
341impl Display for QualifiedName {
342 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
343 self.to_fmt(f)
344 }
345}
346
347impl ResultColumn {
348 fn column_count(&self) -> ColumnCount {
349 match self {
350 Self::Expr(..) => ColumnCount::Fixed(1),
351 _ => ColumnCount::Dynamic,
352 }
353 }
354}
355fn column_count(cols: &[ResultColumn]) -> ColumnCount {
356 assert!(!cols.is_empty());
357 let mut count = ColumnCount::Fixed(0);
358 for col in cols {
359 match col.column_count() {
360 ColumnCount::Fixed(_) => count.incr(),
361 _ => return ColumnCount::Dynamic,
362 }
363 }
364 count
365}