use std::str::{self, Bytes}; use strum_macros::{EnumIter, EnumString}; /// `?` or `$` Prepared statement arg placeholder(s) #[derive(Default)] pub struct ParameterInfo { /// Number of SQL parameters in a prepared statement, like `sqlite3_bind_parameter_count` pub count: u32, /// Parameter name(s) if any pub names: Vec, } /// Statement or Explain statement // https://sqlite.org/syntax/sql-stmt.html #[derive(Clone, Debug, PartialEq, Eq)] pub enum Cmd { /// `EXPLAIN` statement Explain(Stmt), /// `EXPLAIN QUERY PLAN` statement ExplainQueryPlan(Stmt), /// statement Stmt(Stmt), } /// SQL statement // https://sqlite.org/syntax/sql-stmt.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Stmt { /// `ALTER TABLE`: table name, body AlterTable { // table name name: QualifiedName, // `ALTER TABLE` body body: AlterTableBody, }, /// `ANALYSE`: object name Analyze { // object name name: Option, }, /// `ATTACH DATABASE` Attach { /// filename // TODO distinction between ATTACH and ATTACH DATABASE expr: Box, /// schema name db_name: Box, /// password key: Option>, }, /// `BEGIN`: tx type, tx name Begin { // transaction type typ: Option, // transaction name name: Option, }, /// `COMMIT`/`END`: tx name Commit { // tx name name: Option, }, // TODO distinction between COMMIT and END /// `CREATE INDEX` CreateIndex { /// `UNIQUE` unique: bool, /// `IF NOT EXISTS` if_not_exists: bool, /// index name idx_name: QualifiedName, /// table name tbl_name: Name, /// indexed columns or expressions columns: Vec, /// partial index where_clause: Option>, }, /// `CREATE TABLE` CreateTable { /// `TEMPORARY` temporary: bool, // TODO distinction between TEMP and TEMPORARY /// `IF NOT EXISTS` if_not_exists: bool, /// table name tbl_name: QualifiedName, /// table body body: CreateTableBody, }, /// `CREATE TRIGGER` CreateTrigger { /// `TEMPORARY` temporary: bool, /// `IF NOT EXISTS` if_not_exists: bool, /// trigger name trigger_name: QualifiedName, /// `BEFORE`/`AFTER`/`INSTEAD OF` time: Option, /// `DELETE`/`INSERT`/`UPDATE` event: TriggerEvent, /// table name tbl_name: QualifiedName, /// `FOR EACH ROW` for_each_row: bool, /// `WHEN` when_clause: Option>, /// statements commands: Vec, }, /// `CREATE VIEW` CreateView { /// `TEMPORARY` temporary: bool, /// `IF NOT EXISTS` if_not_exists: bool, /// view name view_name: QualifiedName, /// columns columns: Option>, /// query select: Select, }, /// `CREATE VIRTUAL TABLE` CreateVirtualTable { /// `IF NOT EXISTS` if_not_exists: bool, /// table name tbl_name: QualifiedName, /// module name module_name: Name, /// args args: Option>, // TODO smol str }, /// `DELETE` Delete { /// CTE with: Option, /// `FROM` table name tbl_name: QualifiedName, /// `INDEXED` indexed: Option, /// `WHERE` clause where_clause: Option>, /// `RETURNING` returning: Option>, /// `ORDER BY` order_by: Option>, /// `LIMIT` limit: Option, }, /// `DETACH DATABASE`: db name Detach { // db name name: Box, }, // TODO distinction between DETACH and DETACH DATABASE /// `DROP INDEX` DropIndex { /// `IF EXISTS` if_exists: bool, /// index name idx_name: QualifiedName, }, /// `DROP TABLE` DropTable { /// `IF EXISTS` if_exists: bool, /// table name tbl_name: QualifiedName, }, /// `DROP TRIGGER` DropTrigger { /// `IF EXISTS` if_exists: bool, /// trigger name trigger_name: QualifiedName, }, /// `DROP VIEW` DropView { /// `IF EXISTS` if_exists: bool, /// view name view_name: QualifiedName, }, /// `INSERT` Insert { /// CTE with: Option, /// `OR` or_conflict: Option, // TODO distinction between REPLACE and INSERT OR REPLACE /// table name tbl_name: QualifiedName, /// `COLUMNS` columns: Option>, /// `VALUES` or `SELECT` body: InsertBody, /// `RETURNING` returning: Option>, }, /// `PRAGMA`: pragma name, body Pragma { // pragma name name: QualifiedName, // pragma body body: Option, }, /// `REINDEX` Reindex { /// collation or index or table name name: Option, }, /// `RELEASE`: savepoint name Release { // savepoint name name: Name, }, // TODO distinction between RELEASE and RELEASE SAVEPOINT /// `ROLLBACK` Rollback { /// transaction name tx_name: Option, /// savepoint name savepoint_name: Option, // TODO distinction between TO and TO SAVEPOINT }, /// `SAVEPOINT`: savepoint name Savepoint { // savepoint name name: Name, }, /// `SELECT` Select(Select), /// `UPDATE` Update { /// CTE with: Option, /// `OR` or_conflict: Option, /// table name tbl_name: QualifiedName, /// `INDEXED` indexed: Option, /// `SET` assignments sets: Vec, /// `FROM` from: Option, /// `WHERE` clause where_clause: Option>, /// `RETURNING` returning: Option>, /// `ORDER BY` order_by: Option>, /// `LIMIT` limit: Option, }, /// `VACUUM`: database name, into expr Vacuum { // database name name: Option, // into expression into: Option>, }, } #[repr(transparent)] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] /// Internal ID of a table reference. /// /// Used by [Expr::Column] and [Expr::RowId] to refer to a table. /// E.g. in 'SELECT * FROM t UNION ALL SELECT * FROM t', there are two table references, /// so there are two TableInternalIds. /// /// FIXME: rename this to TableReferenceId. pub struct TableInternalId(usize); /// SQL expression // https://sqlite.org/syntax/expr.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Expr { /// `BETWEEN` Between { /// expression lhs: Box, /// `NOT` not: bool, /// start start: Box, /// end end: Box, }, /// binary expression Binary(Box, Operator, Box), /// `CASE` expression Case { /// operand base: Option>, /// `WHEN` condition `THEN` result when_then_pairs: Vec<(Box, Box)>, /// `ELSE` result else_expr: Option>, }, /// CAST expression Cast { /// expression expr: Box, /// `AS` type name type_name: Option, }, /// `COLLATE`: expression Collate(Box, String), /// schema-name.table-name.column-name DoublyQualified(Name, Name, Name), /// `EXISTS` subquery Exists(Select), /// call to a built-in function FunctionCall { /// function name name: Name, /// `DISTINCT` distinctness: Option, /// arguments args: Option>>, /// `ORDER BY` order_by: Option>, /// `FILTER` filter_over: Option, }, /// Function call expression with '*' as arg FunctionCallStar { /// function name name: Name, /// `FILTER` filter_over: Option, }, /// Identifier Id(Name), /// Column Column { /// the x in `x.y.z`. index of the db in catalog. database: Option, /// the y in `x.y.z`. index of the table in catalog. table: TableInternalId, /// the z in `x.y.z`. index of the column in the table. column: usize, /// is the column a rowid alias is_rowid_alias: bool, }, /// `ROWID` RowId { /// the x in `x.y.z`. index of the db in catalog. database: Option, /// the y in `x.y.z`. index of the table in catalog. table: TableInternalId, }, /// `IN` InList { /// expression lhs: Box, /// `NOT` not: bool, /// values rhs: Option>>, }, /// `IN` subselect InSelect { /// expression lhs: Box, /// `NOT` not: bool, /// subquery rhs: Select, }, /// `IN` table name / function InTable { /// expression lhs: Box, /// `NOT` not: bool, /// table name rhs: QualifiedName, /// table function arguments args: Option>>, }, /// `IS NULL` IsNull(Box), /// `LIKE` Like { /// expression lhs: Box, /// `NOT` not: bool, /// operator op: LikeOperator, /// pattern rhs: Box, /// `ESCAPE` char escape: Option>, }, /// Literal expression Literal(Literal), /// Name Name(Name), /// `NOT NULL` or `NOTNULL` NotNull(Box), /// Parenthesized subexpression Parenthesized(Vec>), /// Qualified name Qualified(Name, Name), /// `RAISE` function call Raise(ResolveType, Option>), /// Subquery expression Subquery(Select), /// Unary expression Unary(UnaryOperator, Box), /// Parameters Variable(String), } /// SQL literal #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Literal { /// Number Numeric(String), /// String // TODO Check that string is already quoted and correctly escaped String(String), /// BLOB // TODO Check that string is valid (only hexa) Blob(String), /// Keyword Keyword(String), /// `NULL` Null, /// `CURRENT_DATE` CurrentDate, /// `CURRENT_TIME` CurrentTime, /// `CURRENT_TIMESTAMP` CurrentTimestamp, } /// Textual comparison operator in an expression #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum LikeOperator { /// `GLOB` Glob, /// `LIKE` Like, /// `MATCH` Match, /// `REGEXP` Regexp, } /// SQL operators #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Operator { /// `+` Add, /// `AND` And, /// `->` ArrowRight, /// `->>` ArrowRightShift, /// `&` BitwiseAnd, /// `|` BitwiseOr, /// `~` BitwiseNot, /// String concatenation (`||`) Concat, /// `=` or `==` Equals, /// `/` Divide, /// `>` Greater, /// `>=` GreaterEquals, /// `IS` Is, /// `IS NOT` IsNot, /// `<<` LeftShift, /// `<` Less, /// `<=` LessEquals, /// `%` Modulus, /// `*` Multiply, /// `!=` or `<>` NotEquals, /// `OR` Or, /// `>>` RightShift, /// `-` Subtract, } /// Unary operators #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum UnaryOperator { /// bitwise negation (`~`) BitwiseNot, /// negative-sign Negative, /// `NOT` Not, /// positive-sign Positive, } /// `SELECT` statement // https://sqlite.org/lang_select.html // https://sqlite.org/syntax/factored-select-stmt.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Select { /// CTE pub with: Option, /// body pub body: SelectBody, /// `ORDER BY` pub order_by: Option>, // ORDER BY term does not match any column in the result set /// `LIMIT` pub limit: Option, } /// `SELECT` body #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SelectBody { /// first select pub select: OneSelect, /// compounds pub compounds: Option>, } /// Compound select #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CompoundSelect { /// operator pub operator: CompoundOperator, /// select pub select: OneSelect, } /// Compound operators // https://sqlite.org/syntax/compound-operator.html #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum CompoundOperator { /// `UNION` Union, /// `UNION ALL` UnionAll, /// `EXCEPT` Except, /// `INTERSECT` Intersect, } /// `SELECT` core // https://sqlite.org/syntax/select-core.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum OneSelect { /// `SELECT` Select(SelectInner), /// `VALUES` Values(Vec>>), } #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] /// `SELECT` core pub struct SelectInner { /// `DISTINCT` pub distinctness: Option, /// columns pub columns: Vec, /// `FROM` clause pub from: Option, /// `WHERE` clause pub where_clause: Option>, /// `GROUP BY` pub group_by: Option, /// `WINDOW` definition pub window_clause: Option>, } /// `SELECT` ... `FROM` clause // https://sqlite.org/syntax/join-clause.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FromClause { /// table pub select: Option>, // FIXME mandatory /// `JOIN`ed tabled pub joins: Option>, /// A default join operator pub op: Option, // FIXME transient } /// `SELECT` distinctness #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Distinctness { /// `DISTINCT` Distinct, /// `ALL` All, } /// `SELECT` or `RETURNING` result column // https://sqlite.org/syntax/result-column.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ResultColumn { /// expression Expr(Box, Option), /// `*` Star, /// table name.`*` TableStar(Name), } /// Alias #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum As { /// `AS` As(Name), /// no `AS` Elided(Name), // FIXME Ids } /// `JOIN` clause // https://sqlite.org/syntax/join-clause.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct JoinedSelectTable { /// operator pub operator: JoinOperator, /// table pub table: Box, /// constraint pub constraint: Option, } /// Table or subquery // https://sqlite.org/syntax/table-or-subquery.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum SelectTable { /// table Table(QualifiedName, Option, Option), /// table function call TableCall(QualifiedName, Option>>, Option), /// `SELECT` subquery Select(Select, Option), /// subquery Sub(FromClause, Option), } /// Join operators // https://sqlite.org/syntax/join-operator.html #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum JoinOperator { /// `,` Comma, /// `JOIN` TypedJoin(Option), } // https://github.com/sqlite/sqlite/blob/80511f32f7e71062026edd471913ef0455563964/src/select.c#L197-L257 bitflags::bitflags! { /// `JOIN` types #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct JoinType: u8 { /// `INNER` const INNER = 0x01; /// `CROSS` => INNER|CROSS const CROSS = 0x02; /// `NATURAL` const NATURAL = 0x04; /// `LEFT` => LEFT|OUTER const LEFT = 0x08; /// `RIGHT` => RIGHT|OUTER const RIGHT = 0x10; /// `OUTER` const OUTER = 0x20; } } /// `JOIN` constraint #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum JoinConstraint { /// `ON` On(Box), /// `USING`: col names Using(Vec), } /// `GROUP BY` #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct GroupBy { /// expressions pub exprs: Vec>, /// `HAVING` pub having: Option>, // HAVING clause on a non-aggregate query } /// identifier or string or `CROSS` or `FULL` or `INNER` or `LEFT` or `NATURAL` or `OUTER` or `RIGHT`. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Name { /// Identifier Ident(String), /// Quoted values Quoted(String), } /// Qualified name #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct QualifiedName { /// schema pub db_name: Option, /// object name pub name: Name, /// alias pub alias: Option, // FIXME restrict alias usage (fullname vs xfullname) } /// `ALTER TABLE` body // https://sqlite.org/lang_altertable.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AlterTableBody { /// `RENAME TO`: new table name RenameTo(Name), /// `ADD COLUMN` AddColumn(ColumnDefinition), // TODO distinction between ADD and ADD COLUMN /// `RENAME COLUMN` RenameColumn { /// old name old: Name, /// new name new: Name, }, /// `DROP COLUMN` DropColumn(Name), // TODO distinction between DROP and DROP COLUMN } /// `CREATE TABLE` body // https://sqlite.org/lang_createtable.html // https://sqlite.org/syntax/create-table-stmt.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum CreateTableBody { /// columns and constraints ColumnsAndConstraints { /// table column definitions columns: Vec, /// table constraints constraints: Option>, /// table options options: TableOptions, }, /// `AS` select AsSelect(Select), } /// Table column definition // https://sqlite.org/syntax/column-def.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ColumnDefinition { /// column name pub col_name: Name, /// column type pub col_type: Option, /// column constraints pub constraints: Vec, } /// Named column constraint // https://sqlite.org/syntax/column-constraint.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct NamedColumnConstraint { /// constraint name pub name: Option, /// constraint pub constraint: ColumnConstraint, } /// Column constraint // https://sqlite.org/syntax/column-constraint.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ColumnConstraint { /// `PRIMARY KEY` PrimaryKey { /// `ASC` / `DESC` order: Option, /// `ON CONFLICT` clause conflict_clause: Option, /// `AUTOINCREMENT` auto_increment: bool, }, /// `NULL` NotNull { /// `NOT` nullable: bool, /// `ON CONFLICT` clause conflict_clause: Option, }, /// `UNIQUE` Unique(Option), /// `CHECK` Check(Box), /// `DEFAULT` Default(Box), /// `DEFERRABLE` Defer(DeferSubclause), // FIXME /// `COLLATE` Collate { /// collation name collation_name: Name, // FIXME Ids }, /// `REFERENCES` foreign-key clause ForeignKey { /// clause clause: ForeignKeyClause, /// `DEFERRABLE` deref_clause: Option, }, /// `GENERATED` Generated { /// expression expr: Box, /// `STORED` / `VIRTUAL` typ: Option, }, } /// Named table constraint // https://sqlite.org/syntax/table-constraint.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct NamedTableConstraint { /// constraint name pub name: Option, /// constraint pub constraint: TableConstraint, } /// Table constraint // https://sqlite.org/syntax/table-constraint.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TableConstraint { /// `PRIMARY KEY` PrimaryKey { /// columns columns: Vec, /// `AUTOINCREMENT` auto_increment: bool, /// `ON CONFLICT` clause conflict_clause: Option, }, /// `UNIQUE` Unique { /// columns columns: Vec, /// `ON CONFLICT` clause conflict_clause: Option, }, /// `CHECK` Check(Box), /// `FOREIGN KEY` ForeignKey { /// columns columns: Vec, /// `REFERENCES` clause: ForeignKeyClause, /// `DEFERRABLE` deref_clause: Option, }, } bitflags::bitflags! { /// `CREATE TABLE` options #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TableOptions: u8 { /// None const NONE = 0; /// `WITHOUT ROWID` const WITHOUT_ROWID = 1; /// `STRICT` const STRICT = 2; } } /// Sort orders #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum SortOrder { /// `ASC` Asc, /// `DESC` Desc, } /// `NULLS FIRST` or `NULLS LAST` #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum NullsOrder { /// `NULLS FIRST` First, /// `NULLS LAST` Last, } /// `REFERENCES` clause // https://sqlite.org/syntax/foreign-key-clause.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ForeignKeyClause { /// foreign table name pub tbl_name: Name, /// foreign table columns pub columns: Option>, /// referential action(s) / deferrable option(s) pub args: Vec, } /// foreign-key reference args #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum RefArg { /// `ON DELETE` OnDelete(RefAct), /// `ON INSERT` OnInsert(RefAct), /// `ON UPDATE` OnUpdate(RefAct), /// `MATCH` Match(Name), } /// foreign-key reference actions #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum RefAct { /// `SET NULL` SetNull, /// `SET DEFAULT` SetDefault, /// `CASCADE` Cascade, /// `RESTRICT` Restrict, /// `NO ACTION` NoAction, } /// foreign-key defer clause #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DeferSubclause { /// `DEFERRABLE` pub deferrable: bool, /// `INITIALLY` `DEFERRED` / `IMMEDIATE` pub init_deferred: Option, } /// `INITIALLY` `DEFERRED` / `IMMEDIATE` #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum InitDeferredPred { /// `INITIALLY DEFERRED` InitiallyDeferred, /// `INITIALLY IMMEDIATE` InitiallyImmediate, // default } /// Indexed column // https://sqlite.org/syntax/indexed-column.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct IndexedColumn { /// column name pub col_name: Name, /// `COLLATE` pub collation_name: Option, // FIXME Ids /// `ORDER BY` pub order: Option, } /// `INDEXED BY` / `NOT INDEXED` #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Indexed { /// `INDEXED BY`: idx name IndexedBy(Name), /// `NOT INDEXED` NotIndexed, } /// Sorted column #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SortedColumn { /// expression pub expr: Box, /// `ASC` / `DESC` pub order: Option, /// `NULLS FIRST` / `NULLS LAST` pub nulls: Option, } /// `LIMIT` #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Limit { /// count pub expr: Box, /// `OFFSET` pub offset: Option>, // TODO distinction between LIMIT offset, count and LIMIT count OFFSET offset } /// `INSERT` body // https://sqlite.org/lang_insert.html // https://sqlite.org/syntax/insert-stmt.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum InsertBody { /// `SELECT` or `VALUES` Select(Select, Option>), /// `DEFAULT VALUES` DefaultValues, } /// `UPDATE ... SET` #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Set { /// column name(s) pub col_names: Vec, /// expression pub expr: Box, } /// `PRAGMA` body // https://sqlite.org/syntax/pragma-stmt.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum PragmaBody { /// `=` Equals(PragmaValue), /// function call Call(PragmaValue), } /// `PRAGMA` value // https://sqlite.org/syntax/pragma-value.html pub type PragmaValue = Expr; // TODO /// `PRAGMA` value // https://sqlite.org/pragma.html #[derive(Clone, Debug, PartialEq, Eq, EnumIter, EnumString, strum::Display)] #[strum(serialize_all = "snake_case")] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum PragmaName { /// Returns the application ID of the database file. ApplicationId, /// set the autovacuum mode AutoVacuum, /// `cache_size` pragma CacheSize, /// List databases DatabaseList, /// Encoding - only support utf8 Encoding, /// Run integrity check on the database file IntegrityCheck, /// `journal_mode` pragma JournalMode, /// Noop as per SQLite docs LegacyFileFormat, /// Return the total number of pages in the database file. PageCount, /// Return the page size of the database in bytes. PageSize, /// Returns schema version of the database file. SchemaVersion, /// returns information about the columns of a table TableInfo, /// enable capture-changes logic for the connection UnstableCaptureDataChangesConn, /// Returns the user version of the database file. UserVersion, /// trigger a checkpoint to run on database(s) if WAL is enabled WalCheckpoint, } /// `CREATE TRIGGER` time #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TriggerTime { /// `BEFORE` Before, // default /// `AFTER` After, /// `INSTEAD OF` InsteadOf, } /// `CREATE TRIGGER` event #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TriggerEvent { /// `DELETE` Delete, /// `INSERT` Insert, /// `UPDATE` Update, /// `UPDATE OF`: col names UpdateOf(Vec), } /// `CREATE TRIGGER` command // https://sqlite.org/lang_createtrigger.html // https://sqlite.org/syntax/create-trigger-stmt.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TriggerCmd { /// `UPDATE` Update(TriggerCmdUpdate), /// `INSERT` Insert(TriggerCmdInsert), /// `DELETE` Delete(TriggerCmdDelete), /// `SELECT` Select(Select), } /// `UPDATE` trigger command #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TriggerCmdUpdate { /// `OR` pub or_conflict: Option, /// table name pub tbl_name: Name, /// `SET` assignments pub sets: Vec, /// `FROM` pub from: Option, /// `WHERE` clause pub where_clause: Option>, } /// `INSERT` trigger command #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TriggerCmdInsert { /// `OR` pub or_conflict: Option, /// table name pub tbl_name: Name, /// `COLUMNS` pub col_names: Option>, /// `SELECT` or `VALUES` pub select: Select, /// `ON CONFLICT` clause pub upsert: Option>, /// `RETURNING` pub returning: Option>, } /// `DELETE` trigger command #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TriggerCmdDelete { /// table name pub tbl_name: Name, /// `WHERE` clause pub where_clause: Option>, } /// Conflict resolution types #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ResolveType { /// `ROLLBACK` Rollback, /// `ABORT` Abort, // default /// `FAIL` Fail, /// `IGNORE` Ignore, /// `REPLACE` Replace, } impl ResolveType { /// Get the OE_XXX bit value pub fn bit_value(&self) -> usize { match self { ResolveType::Rollback => 1, ResolveType::Abort => 2, ResolveType::Fail => 3, ResolveType::Ignore => 4, ResolveType::Replace => 5, } } } /// `WITH` clause // https://sqlite.org/lang_with.html // https://sqlite.org/syntax/with-clause.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct With { /// `RECURSIVE` pub recursive: bool, /// CTEs pub ctes: Vec, } /// CTE materialization #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Materialized { /// No hint Any, /// `MATERIALIZED` Yes, /// `NOT MATERIALIZED` No, } /// CTE // https://sqlite.org/syntax/common-table-expression.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CommonTableExpr { /// table name pub tbl_name: Name, /// table columns pub columns: Option>, // check no duplicate /// `MATERIALIZED` pub materialized: Materialized, /// query pub select: Select, } /// Column type // https://sqlite.org/syntax/type-name.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Type { /// type name pub name: String, // TODO Validate: Ids+ /// type size pub size: Option, } /// Column type size limit(s) // https://sqlite.org/syntax/type-name.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TypeSize { /// maximum size MaxSize(Box), /// precision TypeSize(Box, Box), } /// Transaction types #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TransactionType { /// `DEFERRED` Deferred, // default /// `IMMEDIATE` Immediate, /// `EXCLUSIVE` Exclusive, } /// Upsert clause // https://sqlite.org/lang_upsert.html // https://sqlite.org/syntax/upsert-clause.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Upsert { /// conflict targets pub index: Option, /// `DO` clause pub do_clause: UpsertDo, /// next upsert pub next: Option>, } /// Upsert conflict targets #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct UpsertIndex { /// columns pub targets: Vec, /// `WHERE` clause pub where_clause: Option>, } /// Upsert `DO` action #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum UpsertDo { /// `SET` Set { /// assignments sets: Vec, /// `WHERE` clause where_clause: Option>, }, /// `NOTHING` Nothing, } /// Function call tail #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FunctionTail { /// `FILTER` clause pub filter_clause: Option>, /// `OVER` clause pub over_clause: Option>, } /// Function call `OVER` clause // https://sqlite.org/syntax/over-clause.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Over { /// Window definition Window(Window), /// Window name Name(Name), } /// `OVER` window definition #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct WindowDef { /// window name pub name: Name, /// window definition pub window: Window, } /// Window definition // https://sqlite.org/syntax/window-defn.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Window { /// base window name pub base: Option, /// `PARTITION BY` pub partition_by: Option>>, /// `ORDER BY` pub order_by: Option>, /// frame spec pub frame_clause: Option, } /// Frame specification // https://sqlite.org/syntax/frame-spec.html #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FrameClause { /// unit pub mode: FrameMode, /// start bound pub start: FrameBound, /// end bound pub end: Option, /// `EXCLUDE` pub exclude: Option, } /// Frame modes #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FrameMode { /// `GROUPS` Groups, /// `RANGE` Range, /// `ROWS` Rows, } /// Frame bounds #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FrameBound { /// `CURRENT ROW` CurrentRow, /// `FOLLOWING` Following(Box), /// `PRECEDING` Preceding(Box), /// `UNBOUNDED FOLLOWING` UnboundedFollowing, /// `UNBOUNDED PRECEDING` UnboundedPreceding, } /// Frame exclusions #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FrameExclude { /// `NO OTHERS` NoOthers, /// `CURRENT ROW` CurrentRow, /// `GROUP` Group, /// `TIES` Ties, }