#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
Select(SelectStmt),
Insert(InsertStmt),
Update(UpdateStmt),
Delete(DeleteStmt),
Group(GroupStmt),
With(WithStmt),
For(ForStmt),
Analyze(Box<Stmt>),
}
#[derive(Debug, Clone, PartialEq)]
pub struct GroupStmt {
pub subject: Expr,
pub shape: Option<Vec<ShapeElement>>,
pub using: Vec<(String, Expr)>,
pub by: Vec<Expr>,
pub filter: Option<Expr>,
pub order_by: Vec<SortExpr>,
pub offset: Option<Expr>,
pub limit: Option<Expr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct WithStmt {
pub aliases: Vec<CteDef>,
pub stmt: Box<Stmt>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct CteDef {
pub name: String,
pub expr: Expr,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ForStmt {
pub var: String,
pub optional: bool,
pub iterator: Expr,
pub body: Box<Stmt>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct SelectStmt {
pub result: Expr,
pub filter: Option<Expr>,
pub order_by: Vec<SortExpr>,
pub offset: Option<Expr>,
pub limit: Option<Expr>,
pub lock: Option<LockClause>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct LockClause {
pub strength: LockStrength,
pub wait: LockWait,
}
#[derive(Debug, Clone, PartialEq)]
pub enum LockStrength {
Update,
NoKeyUpdate,
Share,
KeyShare,
}
#[derive(Debug, Clone, PartialEq)]
pub enum LockWait {
Block,
NoWait,
SkipLocked,
}
#[derive(Debug, Clone, PartialEq)]
pub struct InsertStmt {
pub subject: ObjectRef,
pub shape: Vec<ShapeElement>,
pub unless_conflict: Option<UnlessConflict>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnlessConflict {
pub on: Option<Expr>,
pub else_: Option<Expr>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct UpdateStmt {
pub subject: Expr,
pub filter: Option<Expr>,
pub shape: Vec<ShapeElement>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct DeleteStmt {
pub subject: Expr,
pub filter: Option<Expr>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Expr {
Path(Path),
Shape(Box<ShapeExpr>),
BinOp(Box<BinOp>),
UnaryOp(Box<UnaryOp>),
FunctionCall(FunctionCall),
TypeCast(Box<TypeCast>),
IfElse(Box<IfElse>),
Literal(Literal),
Parameter(String),
Tuple(Vec<Expr>),
NamedTuple(Vec<(String, Expr)>),
Array(Vec<Expr>),
Set(Vec<Expr>),
SubQuery(Box<Stmt>),
Union(Box<Expr>, Box<Expr>),
Except(Box<Expr>, Box<Expr>),
Intersect(Box<Expr>, Box<Expr>),
Global(String),
Index {
expr: Box<Expr>,
index: Box<Expr>,
},
Slice {
expr: Box<Expr>,
lower: Option<Box<Expr>>,
upper: Option<Box<Expr>>,
},
FieldAccess {
expr: Box<Expr>,
field: String,
},
PathStepOn {
expr: Box<Expr>,
step: Box<PathStep>,
},
TupleIndex {
expr: Box<Expr>,
index: usize,
},
Detached(Box<Expr>),
TypeIs {
expr: Box<Expr>,
ty: TypeExpr,
},
}
#[derive(Debug, Clone, PartialEq)]
pub struct Path {
pub steps: Vec<PathStep>,
pub partial: bool,
}
impl Path {
pub fn absolute(name: impl Into<String>) -> Self {
Path {
steps: vec![PathStep::Name(name.into())],
partial: false,
}
}
pub fn relative(name: impl Into<String>) -> Self {
Path {
steps: vec![PathStep::Name(name.into())],
partial: true,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum PathStep {
Name(String),
TypeIntersection(ObjectRef),
LinkProp(String),
Backlink(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct ObjectRef {
pub module: Option<String>,
pub name: String,
}
impl ObjectRef {
pub fn unqualified(name: impl Into<String>) -> Self {
ObjectRef {
module: None,
name: name.into(),
}
}
pub fn qualified(module: impl Into<String>, name: impl Into<String>) -> Self {
ObjectRef {
module: Some(module.into()),
name: name.into(),
}
}
pub fn qualified_name(&self) -> String {
match &self.module {
Some(module) => format!("{module}::{}", self.name),
None => self.name.clone(),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum ShapeOp {
Assign,
Append,
Remove,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ShapeExpr {
pub expr: Option<Expr>,
pub elements: Vec<ShapeElement>,
pub marker_offset: Option<usize>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Splat {
Shallow,
Deep,
}
#[derive(Debug, Clone, PartialEq)]
pub struct ShapeElement {
pub path: Path,
pub splat: Option<Splat>,
pub nested: Option<Vec<ShapeElement>>,
pub compexpr: Option<Expr>,
pub op: ShapeOp,
pub filter: Option<Expr>,
pub order_by: Vec<SortExpr>,
pub offset: Option<Expr>,
pub limit: Option<Expr>,
pub marker_offset: Option<usize>,
}
impl ShapeElement {
pub fn splat(kind: Splat) -> Self {
ShapeElement {
path: Path {
steps: vec![],
partial: true,
},
splat: Some(kind),
nested: None,
compexpr: None,
op: ShapeOp::Assign,
filter: None,
order_by: vec![],
offset: None,
limit: None,
marker_offset: None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct BinOp {
pub left: Expr,
pub op: BinOpKind,
pub right: Expr,
}
#[derive(Debug, Clone, PartialEq)]
pub enum BinOpKind {
Add,
Sub,
Mul,
Div,
FloorDiv,
Mod,
Pow,
Eq,
Ne,
Lt,
Le,
Gt,
Ge,
And,
Or,
Like,
Ilike,
NotLike,
NotIlike,
In,
NotIn,
Coalesce,
CoalesceEq,
CoalesceNe,
Concat,
}
impl std::fmt::Display for BinOpKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
Self::Add => "+",
Self::Sub => "-",
Self::Mul => "*",
Self::Div => "/",
Self::FloorDiv => "//",
Self::Mod => "%",
Self::Pow => "^",
Self::Eq => "=",
Self::Ne => "!=",
Self::CoalesceEq => "?=",
Self::CoalesceNe => "?!=",
Self::Lt => "<",
Self::Le => "<=",
Self::Gt => ">",
Self::Ge => ">=",
Self::And => "and",
Self::Or => "or",
Self::Like => "like",
Self::Ilike => "ilike",
Self::NotLike => "not like",
Self::NotIlike => "not ilike",
Self::In => "in",
Self::NotIn => "not in",
Self::Coalesce => "??",
Self::Concat => "++",
})
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct UnaryOp {
pub op: UnaryOpKind,
pub operand: Expr,
}
#[derive(Debug, Clone, PartialEq)]
pub enum UnaryOpKind {
Not,
Minus,
Exists,
Distinct,
}
#[derive(Debug, Clone, PartialEq)]
pub struct FunctionCall {
pub module: Option<String>,
pub name: String,
pub args: Vec<Expr>,
pub kwargs: Vec<(String, Expr)>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct TypeCast {
pub expr: Expr,
pub ty: TypeExpr,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TypeExpr {
Named { module: Option<String>, name: String },
Tuple { elements: Vec<TupleTypeElement> },
Array { element: Box<TypeExpr> },
}
#[derive(Debug, Clone, PartialEq)]
pub struct TupleTypeElement {
pub name: Option<String>,
pub ty: Box<TypeExpr>,
}
impl TypeExpr {
pub fn named(module: Option<String>, name: impl Into<String>) -> Self {
TypeExpr::Named {
module,
name: name.into(),
}
}
pub fn as_named(&self) -> Option<(Option<&str>, &str)> {
match self {
TypeExpr::Named { module, name } => Some((module.as_deref(), name.as_str())),
TypeExpr::Tuple { .. } | TypeExpr::Array { .. } => None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct IfElse {
pub if_expr: Expr,
pub condition: Expr,
pub else_expr: Expr,
}
#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
Str(String),
Int(i64),
Float(f64),
Bool(bool),
}
#[derive(Debug, Clone, PartialEq)]
pub struct SortExpr {
pub expr: Expr,
pub direction: SortDirection,
pub nones: NonesOrder,
}
#[derive(Debug, Clone, PartialEq)]
pub enum SortDirection {
Asc,
Desc,
}
#[derive(Debug, Clone, PartialEq)]
pub enum NonesOrder {
First,
Last,
}