use std::fmt;
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlProgram {
pub(crate) query: SqlQuery,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlQuery {
pub(crate) select: SqlSelectClause,
pub(crate) from: Option<SqlFromClause>,
pub(crate) where_clause: Option<SqlWhereClause>,
pub(crate) group_by: Option<SqlGroupByClause>,
pub(crate) order_by: Option<SqlOrderByClause>,
pub(crate) offset_limit: Option<SqlOffsetLimitClause>,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlSelectClause {
pub(crate) distinct: bool,
pub(crate) top: Option<SqlTopSpec>,
pub(crate) spec: SqlSelectSpec,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) enum SqlSelectSpec {
Star,
List(Vec<SqlSelectItem>),
Value(Box<SqlScalarExpression>),
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlSelectItem {
pub(crate) expression: SqlScalarExpression,
pub(crate) alias: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) enum SqlTopSpec {
Literal(i64),
Parameter(String),
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlFromClause {
pub(crate) collection: SqlCollectionExpression,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlWhereClause {
pub(crate) expression: SqlScalarExpression,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlGroupByClause {
pub(crate) expressions: Vec<SqlScalarExpression>,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlOrderByClause {
pub(crate) items: Vec<SqlOrderByItem>,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlOrderByItem {
pub(crate) expression: SqlScalarExpression,
pub(crate) order: SqlSortOrder,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub(crate) enum SqlSortOrder {
Unspecified,
Ascending,
Descending,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlOffsetLimitClause {
pub(crate) offset: SqlOffsetSpec,
pub(crate) limit: SqlLimitSpec,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) enum SqlOffsetSpec {
Literal(i64),
Parameter(String),
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) enum SqlLimitSpec {
Literal(i64),
Parameter(String),
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) enum SqlCollectionExpression {
Aliased {
collection: SqlCollection,
alias: Option<String>,
},
ArrayIterator {
identifier: String,
collection: SqlCollection,
},
Join {
left: Box<SqlCollectionExpression>,
right: Box<SqlCollectionExpression>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub(crate) enum SqlCollection {
Path {
root: String,
path: Vec<SqlPathSegment>,
},
Subquery(Box<SqlQuery>),
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) enum SqlPathSegment {
Identifier(String),
Index(i64),
StringIndex(String),
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) enum SqlScalarExpression {
Literal(SqlLiteral),
PropertyRef(String),
MemberRef {
source: Box<SqlScalarExpression>,
member: String,
},
MemberIndexer {
source: Box<SqlScalarExpression>,
index: Box<SqlScalarExpression>,
},
Binary {
op: SqlBinaryOp,
left: Box<SqlScalarExpression>,
right: Box<SqlScalarExpression>,
},
Unary {
op: SqlUnaryOp,
operand: Box<SqlScalarExpression>,
},
FunctionCall {
name: String,
args: Vec<SqlScalarExpression>,
is_udf: bool,
},
Between {
expression: Box<SqlScalarExpression>,
low: Box<SqlScalarExpression>,
high: Box<SqlScalarExpression>,
not: bool,
},
In {
expression: Box<SqlScalarExpression>,
items: Vec<SqlScalarExpression>,
not: bool,
},
Like {
expression: Box<SqlScalarExpression>,
pattern: Box<SqlScalarExpression>,
escape: Option<String>,
not: bool,
},
Conditional {
condition: Box<SqlScalarExpression>,
if_true: Box<SqlScalarExpression>,
if_false: Box<SqlScalarExpression>,
},
Coalesce {
left: Box<SqlScalarExpression>,
right: Box<SqlScalarExpression>,
},
Exists(Box<SqlQuery>),
Subquery(Box<SqlQuery>),
Array(Box<SqlQuery>),
ArrayCreate(Vec<SqlScalarExpression>),
ObjectCreate(Vec<SqlObjectProperty>),
ParameterRef(String),
IsNull {
expression: Box<SqlScalarExpression>,
not: bool,
},
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) struct SqlObjectProperty {
pub(crate) name: String,
pub(crate) expression: SqlScalarExpression,
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub(crate) enum SqlLiteral {
String(String),
Number(f64),
Integer(i64),
Boolean(bool),
Null,
Undefined,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub(crate) enum SqlBinaryOp {
Add,
Subtract,
Multiply,
Divide,
Modulo,
Equal,
NotEqual,
LessThan,
GreaterThan,
LessThanOrEqual,
GreaterThanOrEqual,
And,
Or,
BitwiseAnd,
BitwiseOr,
BitwiseXor,
LeftShift,
RightShift,
ZeroFillRightShift,
StringConcat,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub(crate) enum SqlUnaryOp {
Not,
Minus,
Plus,
BitwiseNot,
}
impl fmt::Display for SqlBinaryOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::Add => "+",
Self::Subtract => "-",
Self::Multiply => "*",
Self::Divide => "/",
Self::Modulo => "%",
Self::Equal => "=",
Self::NotEqual => "!=",
Self::LessThan => "<",
Self::GreaterThan => ">",
Self::LessThanOrEqual => "<=",
Self::GreaterThanOrEqual => ">=",
Self::And => "AND",
Self::Or => "OR",
Self::BitwiseAnd => "&",
Self::BitwiseOr => "|",
Self::BitwiseXor => "^",
Self::LeftShift => "<<",
Self::RightShift => ">>",
Self::ZeroFillRightShift => ">>>",
Self::StringConcat => "||",
};
write!(f, "{s}")
}
}
impl fmt::Display for SqlUnaryOp {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
Self::Not => "NOT",
Self::Minus => "-",
Self::Plus => "+",
Self::BitwiseNot => "~",
};
write!(f, "{s}")
}
}