Skip to main content

limbo_sqlite3_parser/parser/ast/
check.rs

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