pub mod check;
pub mod fmt;
use std::{num::NonZeroU32, sync::Arc};
use crate::lexer::is_quotable_keyword;
use strum_macros::{EnumIter, EnumString};
#[derive(Default)]
pub struct ParameterInfo {
pub count: u32,
pub names: Vec<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Cmd {
Explain(Stmt),
ExplainQueryPlan(Stmt),
Stmt(Stmt),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CreateVirtualTable {
pub if_not_exists: bool,
pub tbl_name: QualifiedName,
pub module_name: Name,
pub args: Vec<String>, }
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Update {
pub with: Option<With>,
pub or_conflict: Option<ResolveType>,
pub tbl_name: QualifiedName,
pub indexed: Option<Indexed>,
pub sets: Vec<Set>,
pub from: Option<FromClause>,
pub where_clause: Option<Box<Expr>>,
pub returning: Vec<ResultColumn>,
pub order_by: Vec<SortedColumn>,
pub limit: Option<Limit>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AlterTable {
pub name: QualifiedName,
pub body: AlterTableBody,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Stmt {
AlterTable(AlterTable),
Analyze {
name: Option<QualifiedName>,
},
Attach {
expr: Box<Expr>,
db_name: Box<Expr>,
key: Option<Box<Expr>>,
},
Begin {
typ: Option<TransactionType>,
name: Option<Name>,
},
Commit {
name: Option<Name>,
}, CreateIndex {
unique: bool,
if_not_exists: bool,
idx_name: QualifiedName,
tbl_name: Name,
using: Option<Name>,
columns: Vec<SortedColumn>,
with_clause: Vec<(Name, Box<Expr>)>,
where_clause: Option<Box<Expr>>,
},
CreateTable {
temporary: bool, if_not_exists: bool,
tbl_name: QualifiedName,
body: CreateTableBody,
},
CreateTrigger {
temporary: bool,
if_not_exists: bool,
trigger_name: QualifiedName,
time: Option<TriggerTime>,
event: TriggerEvent,
tbl_name: QualifiedName,
for_each_row: bool,
when_clause: Option<Box<Expr>>,
commands: Vec<TriggerCmd>,
},
CreateView {
temporary: bool,
if_not_exists: bool,
view_name: QualifiedName,
columns: Vec<IndexedColumn>,
select: Select,
},
CreateMaterializedView {
if_not_exists: bool,
view_name: QualifiedName,
columns: Vec<IndexedColumn>,
select: Select,
},
CreateVirtualTable(CreateVirtualTable),
CreateType {
if_not_exists: bool,
type_name: String,
body: CreateTypeBody,
},
CreateDomain {
if_not_exists: bool,
domain_name: String,
base_type: String,
default: Option<Box<Expr>>,
not_null: bool,
constraints: Vec<DomainConstraint>,
},
Delete {
with: Option<With>,
tbl_name: QualifiedName,
indexed: Option<Indexed>,
where_clause: Option<Box<Expr>>,
returning: Vec<ResultColumn>,
order_by: Vec<SortedColumn>,
limit: Option<Limit>,
},
Detach {
name: Box<Expr>,
}, DropIndex {
if_exists: bool,
idx_name: QualifiedName,
},
DropTable {
if_exists: bool,
tbl_name: QualifiedName,
},
DropTrigger {
if_exists: bool,
trigger_name: QualifiedName,
},
DropView {
if_exists: bool,
view_name: QualifiedName,
},
DropType {
if_exists: bool,
type_name: String,
},
DropDomain {
if_exists: bool,
domain_name: String,
},
Insert {
with: Option<With>,
or_conflict: Option<ResolveType>, tbl_name: QualifiedName,
columns: Vec<Name>,
body: InsertBody,
returning: Vec<ResultColumn>,
},
Pragma {
name: QualifiedName,
body: Option<PragmaBody>,
},
Reindex {
name: Option<QualifiedName>,
},
Release {
name: Name,
}, Rollback {
tx_name: Option<Name>,
savepoint_name: Option<Name>, },
Savepoint {
name: Name,
},
Select(Select),
Update(Update),
Vacuum {
name: Option<Name>,
into: Option<Box<Expr>>,
},
Optimize {
idx_name: Option<QualifiedName>,
},
}
#[repr(transparent)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TableInternalId(usize);
impl TableInternalId {
pub const SELF_TABLE: Self = Self(0);
pub const fn is_self_table(&self) -> bool {
self.0 == 0
}
}
impl Default for TableInternalId {
fn default() -> Self {
Self(1)
}
}
impl From<usize> for TableInternalId {
fn from(value: usize) -> Self {
Self(value)
}
}
impl std::ops::AddAssign<usize> for TableInternalId {
fn add_assign(&mut self, rhs: usize) {
self.0 += rhs;
}
}
impl From<TableInternalId> for usize {
fn from(value: TableInternalId) -> Self {
value.0
}
}
impl std::fmt::Display for TableInternalId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "t{}", self.0)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FieldAccessResolution {
StructField { field_index: usize },
UnionVariant { tag_index: u8 },
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Expr {
Between {
lhs: Box<Expr>,
not: bool,
start: Box<Expr>,
end: Box<Expr>,
},
Binary(Box<Expr>, Operator, Box<Expr>),
Register(usize),
Case {
base: Option<Box<Expr>>,
when_then_pairs: Vec<(Box<Expr>, Box<Expr>)>,
else_expr: Option<Box<Expr>>,
},
Cast {
expr: Box<Expr>,
type_name: Option<Type>,
},
Collate(Box<Expr>, Name),
DoublyQualified(Name, Name, Name),
Exists(Select),
FieldAccess {
base: Box<Expr>,
field: Name,
resolved: Option<FieldAccessResolution>,
},
FunctionCall {
name: Name,
distinctness: Option<Distinctness>,
args: Vec<Box<Expr>>,
order_by: Vec<SortedColumn>,
filter_over: FunctionTail,
},
FunctionCallStar {
name: Name,
filter_over: FunctionTail,
},
Id(Name),
Column {
database: Option<usize>,
table: TableInternalId,
column: usize,
is_rowid_alias: bool,
},
RowId {
database: Option<usize>,
table: TableInternalId,
},
InList {
lhs: Box<Expr>,
not: bool,
rhs: Vec<Box<Expr>>,
},
InSelect {
lhs: Box<Expr>,
not: bool,
rhs: Select,
},
InTable {
lhs: Box<Expr>,
not: bool,
rhs: QualifiedName,
args: Vec<Box<Expr>>,
},
IsNull(Box<Expr>),
Like {
lhs: Box<Expr>,
not: bool,
op: LikeOperator,
rhs: Box<Expr>,
escape: Option<Box<Expr>>,
},
Literal(Literal),
Name(Name),
NotNull(Box<Expr>),
Parenthesized(Vec<Box<Expr>>),
Qualified(Name, Name),
Raise(ResolveType, Option<Box<Expr>>),
Subquery(Select),
Unary(UnaryOperator, Box<Expr>),
Variable(Variable),
SubqueryResult {
subquery_id: TableInternalId,
lhs: Option<Box<Expr>>,
not_in: bool,
query_type: SubqueryType,
},
Default,
Array {
elements: Vec<Box<Expr>>,
},
Subscript {
base: Box<Expr>,
index: Box<Expr>,
},
}
impl Default for Expr {
fn default() -> Self {
Self::Literal(Literal::Null)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Variable {
pub index: NonZeroU32,
pub name: Option<Box<str>>,
pub col_type: Option<Box<str>>,
}
impl Variable {
pub fn indexed(index: NonZeroU32) -> Self {
Self {
index,
name: None,
col_type: None,
}
}
pub fn indexed_typed(index: NonZeroU32, col_type: &str) -> Self {
Self {
index,
name: None,
col_type: if col_type.is_empty() {
None
} else {
Some(col_type.into())
},
}
}
pub fn named(name: impl Into<Box<str>>, index: NonZeroU32) -> Self {
Self {
index,
name: Some(name.into()),
col_type: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SubqueryType {
Exists { result_reg: usize },
RowValue {
result_reg_start: usize,
num_regs: usize,
},
In {
cursor_id: usize,
affinity_str: Arc<String>,
},
}
impl Expr {
pub fn into_boxed(self) -> Box<Expr> {
Box::new(self)
}
pub fn unary(operator: UnaryOperator, expr: Expr) -> Expr {
Expr::Unary(operator, Box::new(expr))
}
pub fn binary(lhs: Expr, operator: Operator, rhs: Expr) -> Expr {
Expr::Binary(Box::new(lhs), operator, Box::new(rhs))
}
pub fn not_null(expr: Expr) -> Expr {
Expr::NotNull(Box::new(expr))
}
pub fn between(lhs: Expr, not: bool, start: Expr, end: Expr) -> Expr {
Expr::Between {
lhs: Box::new(lhs),
not,
start: Box::new(start),
end: Box::new(end),
}
}
pub fn in_select(lhs: Expr, not: bool, select: Select) -> Expr {
Expr::InSelect {
lhs: Box::new(lhs),
not,
rhs: select,
}
}
pub fn like(
lhs: Expr,
not: bool,
operator: LikeOperator,
rhs: Expr,
escape: Option<Expr>,
) -> Expr {
Expr::Like {
lhs: Box::new(lhs),
not,
op: operator,
rhs: Box::new(rhs),
escape: escape.map(Box::new),
}
}
pub fn is_null(expr: Expr) -> Expr {
Expr::IsNull(Box::new(expr))
}
pub fn collate(expr: Expr, name: Name) -> Expr {
Expr::Collate(Box::new(expr), name)
}
pub fn cast(expr: Expr, type_name: Option<Type>) -> Expr {
Expr::Cast {
expr: Box::new(expr),
type_name,
}
}
pub fn raise(resolve_type: ResolveType, expr: Option<Expr>) -> Expr {
Expr::Raise(resolve_type, expr.map(Box::new))
}
pub const fn can_be_null(&self) -> bool {
match self {
Expr::Literal(literal) => !matches!(
literal,
Literal::Numeric(_) | Literal::String(_) | Literal::Blob(_)
),
_ => true,
}
}
}
#[derive(Clone, Default, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Literal {
Numeric(String),
String(String),
Blob(String),
Keyword(String),
#[default]
Null,
True,
False,
CurrentDate,
CurrentTime,
CurrentTimestamp,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum LikeOperator {
Glob,
Like,
Match,
Regexp,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Operator {
Add,
And,
ArrowRight,
ArrowRightShift,
BitwiseAnd,
BitwiseOr,
BitwiseNot,
Concat,
Equals,
Divide,
Greater,
GreaterEquals,
Is,
IsNot,
LeftShift,
Less,
LessEquals,
Modulus,
Multiply,
NotEquals,
Or,
RightShift,
Subtract,
ArrayContains,
ArrayOverlap,
}
impl Operator {
pub const fn is_commutative(&self) -> bool {
matches!(
self,
Operator::Add
| Operator::Multiply
| Operator::BitwiseAnd
| Operator::BitwiseOr
| Operator::Equals
| Operator::NotEquals
)
}
pub const fn is_comparison(&self) -> bool {
matches!(
self,
Self::Equals
| Self::NotEquals
| Self::Less
| Self::LessEquals
| Self::Greater
| Self::GreaterEquals
| Self::Is
| Self::IsNot
)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UnaryOperator {
BitwiseNot,
Negative,
Not,
Positive,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Select {
pub with: Option<With>,
pub body: SelectBody,
pub order_by: Vec<SortedColumn>, pub limit: Option<Limit>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SelectBody {
pub select: OneSelect,
pub compounds: Vec<CompoundSelect>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CompoundSelect {
pub operator: CompoundOperator,
pub select: OneSelect,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CompoundOperator {
Union,
UnionAll,
Except,
Intersect,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum OneSelect {
Select {
distinctness: Option<Distinctness>,
columns: Vec<ResultColumn>,
from: Option<FromClause>,
where_clause: Option<Box<Expr>>,
group_by: Option<GroupBy>,
window_clause: Vec<WindowDef>,
},
Values(Vec<Vec<Box<Expr>>>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FromClause {
pub select: Box<SelectTable>, pub joins: Vec<JoinedSelectTable>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Distinctness {
Distinct,
All,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ResultColumn {
Expr(Box<Expr>, Option<As>),
Star,
TableStar(Name),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum As {
As(Name),
Elided(Name), ImplicitColumnName(Name),
}
impl As {
pub fn name(&self) -> &Name {
match self {
As::As(name) | As::Elided(name) | As::ImplicitColumnName(name) => name,
}
}
pub fn is_explicit(&self) -> bool {
matches!(self, As::As(_) | As::Elided(_))
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct JoinedSelectTable {
pub operator: JoinOperator,
pub table: Box<SelectTable>,
pub constraint: Option<JoinConstraint>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SelectTable {
Table(QualifiedName, Option<As>, Option<Indexed>),
TableCall(QualifiedName, Vec<Box<Expr>>, Option<As>),
Select(Select, Option<As>),
Sub(FromClause, Option<As>),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum JoinOperator {
Comma,
TypedJoin(Option<JoinType>),
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct JoinType: u8 {
const INNER = 0x01;
const CROSS = 0x02;
const NATURAL = 0x04;
const LEFT = 0x08;
const RIGHT = 0x10;
const OUTER = 0x20;
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum JoinConstraint {
On(Box<Expr>),
Using(Vec<Name>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct GroupBy {
pub exprs: Vec<Box<Expr>>,
pub having: Option<Box<Expr>>, }
#[derive(Clone, Debug, Eq)]
pub struct Name {
quote: Option<char>,
value: String,
}
impl PartialEq for Name {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl std::hash::Hash for Name {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.value.hash(state);
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for Name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.value)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct NameVisitor;
impl<'de> serde::de::Visitor<'de> for NameVisitor {
type Value = Name;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a string")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(Name::from_bytes(v.as_bytes()))
}
}
deserializer.deserialize_str(NameVisitor)
}
}
impl Name {
pub fn exact(s: String) -> Self {
Self {
value: s,
quote: None,
}
}
pub fn from_bytes(s: &[u8]) -> Self {
Self::from_string(unsafe { std::str::from_utf8_unchecked(s) })
}
pub const fn empty() -> Self {
Self {
value: String::new(),
quote: None,
}
}
pub fn from_string(s: impl AsRef<str>) -> Self {
let s = s.as_ref();
let bytes = s.as_bytes();
if s.is_empty() {
return Name::exact(s.to_string());
}
if matches!(bytes[0], b'"' | b'\'' | b'`') {
assert!(s.len() >= 2);
assert!(bytes[bytes.len() - 1] == bytes[0]);
let s = match bytes[0] {
b'"' => s[1..s.len() - 1].replace("\"\"", "\""),
b'\'' => s[1..s.len() - 1].replace("''", "'"),
b'`' => s[1..s.len() - 1].replace("``", "`"),
_ => unreachable!(),
};
Name {
value: s,
quote: Some(bytes[0] as char),
}
} else if bytes[0] == b'[' {
assert!(s.len() >= 2);
assert!(bytes[bytes.len() - 1] == b']');
Name::exact(s[1..s.len() - 1].to_string())
} else {
Name::exact(s.to_string())
}
}
pub fn as_str(&self) -> &str {
&self.value
}
pub fn as_literal(&self) -> String {
format!("'{}'", self.value.replace("'", "''"))
}
pub fn as_ident(&self) -> String {
if let Some(quote) = self.quote {
let single = quote.to_string();
let double = single.clone() + &single;
return quote.to_string()
+ self.value.replace(&single, &double).as_str()
+ quote.to_string().as_str();
}
let value = self.value.as_bytes();
let safe_char = |&c: &u8| c.is_ascii_alphanumeric() || c == b'_';
if !value.is_empty() && value.iter().all(safe_char) && !is_quotable_keyword(value) {
self.value.clone()
} else {
format!("\"{}\"", self.value.replace("\"", "\"\""))
}
}
pub fn quoted_with(&self, quote: char) -> bool {
self.quote == Some(quote)
}
pub const fn quoted(&self) -> bool {
self.quote.is_some()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct QualifiedName {
pub db_name: Option<Name>,
pub name: Name,
pub alias: Option<Name>, }
impl QualifiedName {
pub const fn single(name: Name) -> Self {
Self {
db_name: None,
name,
alias: None,
}
}
pub const fn fullname(db_name: Name, name: Name) -> Self {
Self {
db_name: Some(db_name),
name,
alias: None,
}
}
pub const fn xfullname(db_name: Name, name: Name, alias: Name) -> Self {
Self {
db_name: Some(db_name),
name,
alias: Some(alias),
}
}
pub const fn alias(name: Name, alias: Name) -> Self {
Self {
db_name: None,
name,
alias: Some(alias),
}
}
pub fn identifier(&self) -> String {
self.alias.as_ref().map_or_else(
|| self.name.as_str().to_string(),
|alias| alias.as_str().to_string(),
)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum AlterTableBody {
RenameTo(Name),
AddColumn(ColumnDefinition), AlterColumn { old: Name, new: ColumnDefinition },
RenameColumn {
old: Name,
new: Name,
},
DropColumn(Name), }
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TypeOperator {
pub op: String,
pub func_name: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TypeParam {
pub name: String,
pub ty: Option<String>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DomainConstraint {
pub name: Option<String>,
pub check: Box<Expr>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CreateTypeBody {
CustomType {
params: Vec<TypeParam>,
base: String,
encode: Option<Box<Expr>>,
decode: Option<Box<Expr>>,
operators: Vec<TypeOperator>,
default: Option<Box<Expr>>,
},
Struct(Vec<TypeField>),
Union(Vec<TypeField>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum CreateTableBody {
ColumnsAndConstraints {
columns: Vec<ColumnDefinition>,
constraints: Vec<NamedTableConstraint>,
options: TableOptions,
},
AsSelect(Select),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ColumnDefinition {
pub col_name: Name,
pub col_type: Option<Type>,
pub constraints: Vec<NamedColumnConstraint>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct NamedColumnConstraint {
pub name: Option<Name>,
pub constraint: ColumnConstraint,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "simulator", derive(strum::EnumDiscriminants))]
#[cfg_attr(
feature = "simulator",
strum_discriminants(derive(strum::VariantArray))
)]
pub enum ColumnConstraint {
PrimaryKey {
order: Option<SortOrder>,
conflict_clause: Option<ResolveType>,
auto_increment: bool,
},
NotNull {
nullable: bool,
conflict_clause: Option<ResolveType>,
},
Unique(Option<ResolveType>),
Check(Box<Expr>),
Default(Box<Expr>),
Collate {
collation_name: Name, },
ForeignKey {
clause: ForeignKeyClause,
defer_clause: Option<DeferSubclause>,
},
Generated {
expr: Box<Expr>,
typ: Option<GeneratedColumnType>,
},
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum GeneratedColumnType {
Stored,
Virtual,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct NamedTableConstraint {
pub name: Option<Name>,
pub constraint: TableConstraint,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TableConstraint {
PrimaryKey {
columns: Vec<SortedColumn>,
auto_increment: bool,
conflict_clause: Option<ResolveType>,
},
Unique {
columns: Vec<SortedColumn>,
conflict_clause: Option<ResolveType>,
},
Check(Box<Expr>),
ForeignKey {
columns: Vec<IndexedColumn>,
clause: ForeignKeyClause,
defer_clause: Option<DeferSubclause>,
},
}
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TableOptions {
pub without_rowid_text: Option<String>,
pub strict_text: Option<String>,
}
impl TableOptions {
pub fn empty() -> Self {
Self {
without_rowid_text: None,
strict_text: None,
}
}
pub fn contains_without_rowid(&self) -> bool {
self.without_rowid_text.is_some()
}
pub fn contains_strict(&self) -> bool {
self.strict_text.is_some()
}
pub fn contains(&self, flag: TableOptionsFlag) -> bool {
match flag {
TableOptionsFlag::WithoutRowid => self.contains_without_rowid(),
TableOptionsFlag::Strict => self.contains_strict(),
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum TableOptionsFlag {
WithoutRowid,
Strict,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum SortOrder {
Asc,
Desc,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum NullsOrder {
First,
Last,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ForeignKeyClause {
pub tbl_name: Name,
pub columns: Vec<IndexedColumn>,
pub args: Vec<RefArg>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum RefArg {
OnDelete(RefAct),
OnInsert(RefAct),
OnUpdate(RefAct),
Match(Name),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum RefAct {
SetNull,
SetDefault,
Cascade,
Restrict,
NoAction,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct DeferSubclause {
pub deferrable: bool,
pub init_deferred: Option<InitDeferredPred>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum InitDeferredPred {
InitiallyDeferred,
InitiallyImmediate, }
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct IndexedColumn {
pub col_name: Name,
pub collation_name: Option<Name>, pub order: Option<SortOrder>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Indexed {
IndexedBy(Name),
NotIndexed,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SortedColumn {
pub expr: Box<Expr>,
pub order: Option<SortOrder>,
pub nulls: Option<NullsOrder>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Limit {
pub expr: Box<Expr>,
pub offset: Option<Box<Expr>>, }
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[allow(clippy::large_enum_variant)]
pub enum InsertBody {
Select(Select, Option<Box<Upsert>>),
DefaultValues,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Set {
pub col_names: Vec<Name>,
pub expr: Box<Expr>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum PragmaBody {
Equals(PragmaValue),
Call(PragmaValue),
}
pub type PragmaValue = Box<Expr>;
#[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 {
ApplicationId,
AutoVacuum,
BusyTimeout,
CacheSize,
CacheSpill,
#[strum(serialize = "cipher")]
#[cfg_attr(feature = "serde", serde(rename = "cipher"))]
EncryptionCipher,
DataSyncRetry,
DatabaseList,
Encoding,
FreelistCount,
ForeignKeys,
ForeignKeyList,
FullColumnNames,
FunctionList,
#[cfg(target_vendor = "apple")]
Fullfsync,
IgnoreCheckConstraints,
IntegrityCheck,
JournalMode,
LockingMode,
QuickCheck,
#[strum(serialize = "hexkey")]
#[cfg_attr(feature = "serde", serde(rename = "hexkey"))]
EncryptionKey,
LegacyFileFormat,
MaxPageCount,
ModuleList,
PageCount,
PageSize,
QueryOnly,
SchemaVersion,
ShortColumnNames,
IAmADummy,
RequireWhere,
Synchronous,
TempStore,
IndexInfo,
IndexXinfo,
IndexList,
TableList,
TableInfo,
TableXinfo,
CaptureDataChangesConn,
UnstableCaptureDataChangesConn,
UserVersion,
WalCheckpoint,
MvccCheckpointThreshold,
ListTypes,
EmptyResultCallbacks,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TriggerTime {
Before, After,
InsteadOf,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TriggerEvent {
Delete,
Insert,
Update,
UpdateOf(Vec<Name>),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TriggerCmd {
Update {
or_conflict: Option<ResolveType>,
tbl_name: Name,
sets: Vec<Set>,
from: Option<FromClause>,
where_clause: Option<Box<Expr>>,
},
Insert {
or_conflict: Option<ResolveType>,
tbl_name: Name,
col_names: Vec<Name>,
select: Select,
upsert: Option<Box<Upsert>>,
returning: Vec<ResultColumn>,
},
Delete {
tbl_name: Name,
where_clause: Option<Box<Expr>>,
},
Select(Select),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ResolveType {
Rollback,
Abort, Fail,
Ignore,
Replace,
}
impl ResolveType {
pub fn bit_value(&self) -> usize {
match self {
ResolveType::Rollback => 1,
ResolveType::Abort => 2,
ResolveType::Fail => 3,
ResolveType::Ignore => 4,
ResolveType::Replace => 5,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct With {
pub recursive: bool,
pub ctes: Vec<CommonTableExpr>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Materialized {
Any,
Yes,
No,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CommonTableExpr {
pub tbl_name: Name,
pub columns: Vec<IndexedColumn>, pub materialized: Materialized,
pub select: Select,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TypeField {
pub name: Name,
pub field_type: Type,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Type {
pub name: String, pub size: Option<TypeSize>,
pub array_dimensions: u32,
}
impl Type {
pub fn is_array(&self) -> bool {
self.array_dimensions > 0
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TypeSize {
MaxSize(Box<Expr>),
TypeSize(Box<Expr>, Box<Expr>),
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum TransactionType {
Deferred, Immediate,
Exclusive,
Concurrent,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Upsert {
pub index: Option<UpsertIndex>,
pub do_clause: UpsertDo,
pub next: Option<Box<Upsert>>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UpsertIndex {
pub targets: Vec<SortedColumn>,
pub where_clause: Option<Box<Expr>>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UpsertDo {
Set {
sets: Vec<Set>,
where_clause: Option<Box<Expr>>,
},
Nothing,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FunctionTail {
pub filter_clause: Option<Box<Expr>>,
pub over_clause: Option<Over>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Over {
Window(Window),
Name(Name),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct WindowDef {
pub name: Name,
pub window: Window,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Window {
pub base: Option<Name>,
pub partition_by: Vec<Box<Expr>>,
pub order_by: Vec<SortedColumn>,
pub frame_clause: Option<FrameClause>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FrameClause {
pub mode: FrameMode,
pub start: FrameBound,
pub end: Option<FrameBound>,
pub exclude: Option<FrameExclude>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FrameMode {
Groups,
Range,
Rows,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FrameBound {
CurrentRow,
Following(Box<Expr>),
Preceding(Box<Expr>),
UnboundedFollowing,
UnboundedPreceding,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum FrameExclude {
NoOthers,
CurrentRow,
Group,
Ties,
}