///|
pub(all) enum Statement {
Select(SelectStmt)
// Insert(InsertStmt)
// Update(UpdateStmt)
// Delete(DeleteStmt)
} derive(Eq)
///|
pub impl Show for Statement with output(self, logger) {
match self {
Statement::Select(stmt) => stmt.output(logger)
// Statement::Insert(stmt) => logger.write("Insert: \{stmt}"),
// Statement::Update(stmt) => logger.write("Update: \{stmt}"),
// Statement::Delete(stmt) => logger.write("Delete: \{stmt}"),
}
}
///|
pub struct SelectStmt {
// SELECT
projections : Array[Projection]
// FROM
from : Array[TableRef]
// WHERE
where_clause : Expr?
// GROUP BY
group_by : Array[Expr]
having : Expr?
// ORDER BY
order_by : Array[OrderByExpr]
limit : Int?
offset : Int?
} derive(Eq)
///|
impl Show for SelectStmt with output(self, logger) {
logger.write_string("SELECT ")
for i = 0; i < self.projections.length(); i = i + 1 {
if i > 0 {
logger.write_string(", ")
}
self.projections[i].output(logger)
}
logger.write_string(" FROM ")
for i = 0; i < self.from.length(); i = i + 1 {
if i > 0 {
logger.write_string(", ")
}
self.from[i].output(logger)
}
if self.where_clause is Some(selection) {
logger.write_string(" WHERE ")
selection.output(logger)
}
if self.group_by.length() > 0 {
logger.write_string(" GROUP BY ")
for i = 0; i < self.group_by.length(); i = i + 1 {
if i > 0 {
logger.write_string(", ")
}
self.group_by[i].output(logger)
}
}
if self.order_by.length() > 0 {
logger.write_string(" ORDER BY ")
for i = 0; i < self.order_by.length(); i = i + 1 {
if i > 0 {
logger.write_string(", ")
}
self.order_by[i].output(logger)
}
}
logger.write_string(";")
}
///|
pub(all) enum Projection {
Wildcard
UnamedExpr(Expr)
AliasedExpr(Expr, String)
} derive(Eq)
///|
impl Show for Projection with output(self, logger) {
match self {
Projection::Wildcard => logger.write_string("*")
Projection::UnamedExpr(expr) => expr.output(logger)
Projection::AliasedExpr(expr, alias_name) => {
expr.output(logger)
logger.write_string(" AS ")
logger.write_string(alias_name)
}
}
}
///|
pub(all) enum Expr {
Identifier(String)
Literal(Literal)
BinaryOperation(Expr, BinaryOperator, Expr)
UnaryOperation(UnaryOperator, Expr)
FunctionCall(String, Array[Expr])
Wildcard
// DATE '1998-05-19'
// TODO: parse the date string
Datetime(String)
// INTERVAL '1 day' YEAR TO MONTH
Interval(String, IntervalQualifier)
} derive(Eq)
///|
impl Show for Expr with output(self, logger) {
match self {
Expr::Identifier(name) => logger.write_string(name)
Expr::Literal(lit) => lit.output(logger)
Expr::BinaryOperation(left, op, right) => {
logger.write_string("(")
left.output(logger)
logger.write_string(" \{op} ")
right.output(logger)
logger.write_string(")")
}
Expr::UnaryOperation(op, expr) => {
logger.write_string("\{op} ")
expr.output(logger)
}
Expr::FunctionCall(name, args) => {
logger.write_string(name)
logger.write_string("(")
for i = 0; i < args.length(); i = i + 1 {
if i > 0 {
logger.write_string(", ")
}
args[i].output(logger)
}
logger.write_string(")")
}
Expr::Wildcard => logger.write_string("*")
Datetime(s) => {
logger.write_string("DATE '")
logger.write_string(s)
logger.write_string("'")
}
Interval(s, qualifier) => {
logger.write_string("INTERVAL '")
logger.write_string(s)
logger.write_string("' ")
qualifier.output(logger)
}
}
}
///|
pub(all) enum Literal {
Integer(Int)
Double(Double) // TODO: float32
String(String)
Boolean(Bool)
Null
} derive(Eq)
///|
impl Show for Literal with output(self, logger) {
match self {
Literal::Integer(value) => logger.write_string("\{value}")
Literal::Double(value) => logger.write_string("\{value}")
Literal::String(value) => logger.write_string("\"" + value + "\"")
Literal::Boolean(value) =>
logger.write_string(if value { "TRUE" } else { "FALSE" })
Literal::Null => logger.write_string("NULL")
}
}
///|
pub(all) enum BinaryOperator {
Eq
Neq
Lt
Gt
LtEq
GtEq
Spaceship
Plus
Minus
Mul
Div
Mod
} derive(Eq)
///|
impl Show for BinaryOperator with output(self, logger) {
match self {
BinaryOperator::Eq => logger.write_string("=")
BinaryOperator::Neq => logger.write_string("!=")
BinaryOperator::Lt => logger.write_string("<")
BinaryOperator::Gt => logger.write_string(">")
BinaryOperator::LtEq => logger.write_string("<=")
BinaryOperator::GtEq => logger.write_string(">=")
BinaryOperator::Spaceship => logger.write_string("<=>")
BinaryOperator::Plus => logger.write_string("+")
BinaryOperator::Minus => logger.write_string("-")
BinaryOperator::Mul => logger.write_string("*")
BinaryOperator::Div => logger.write_string("/")
BinaryOperator::Mod => logger.write_string("%")
}
}
///|
pub(all) enum UnaryOperator {
Negate
Not
} derive(Eq)
///|
impl Show for UnaryOperator with output(self, logger) {
match self {
UnaryOperator::Negate => logger.write_string("-")
UnaryOperator::Not => logger.write_string("NOT ")
}
}
///|
pub struct OrderByExpr {
// ORDER BY
expr : Expr
// ASC | DESC
asc : Bool?
// NULLS FIRST | NULLS LAST
nulls_first : Bool?
} derive(Eq)
///|
impl Show for OrderByExpr with output(self, logger) {
self.expr.output(logger)
if self.asc is Some(b) {
logger.write_string(
match b {
true => " ASC"
false => " DESC"
},
)
}
if self.nulls_first is Some(b) {
logger.write_string(
match b {
true => " NULLS FIRST"
false => " NULLS LAST"
},
)
}
}
///|
pub(all) enum Asc {
Ascending
Descending
} derive(Eq)
///|
pub(all) enum TableRef {
Table(String)
TableAlias(String, String)
SubQuery(SelectStmt, String)
} derive(Eq)
///|
impl Show for TableRef with output(self, logger) {
match self {
TableRef::Table(name) => logger.write_string(name)
TableRef::TableAlias(name, alias_name) => {
logger.write_string(name)
logger.write_string(" AS ")
logger.write_string(alias_name)
}
TableRef::SubQuery(stmt, alias_name) => {
logger.write_string("(")
stmt.output(logger)
logger.write_string(") AS ")
logger.write_string(alias_name)
}
}
}
///|
pub(all) enum IntervalQualifier {
// YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
Single(PrimaryDatetimeField)
// TO
Range(PrimaryDatetimeField, PrimaryDatetimeField)
} derive(Eq)
///|
struct PrimaryDatetimeField {
// YEAR, MONTH, DAY, HOUR, MINUTE, SECOND
field : DatetimeUnit
// (3)
precision : Int?
} derive(Eq)
///|
impl Show for PrimaryDatetimeField with output(self, logger) {
self.field.output(logger)
if self.precision is Some(p) {
logger.write_string(" (\{p})")
}
}
///|
pub(all) enum DatetimeUnit {
Year
Month
Day
Hour
Minute
Second
} derive(Eq)
///|
impl Show for DatetimeUnit with output(self, logger) {
match self {
DatetimeUnit::Year => logger.write_string("YEAR")
DatetimeUnit::Month => logger.write_string("MONTH")
DatetimeUnit::Day => logger.write_string("DAY")
DatetimeUnit::Hour => logger.write_string("HOUR")
DatetimeUnit::Minute => logger.write_string("MINUTE")
DatetimeUnit::Second => logger.write_string("SECOND")
}
}
///|
impl Show for IntervalQualifier with output(self, logger) {
match self {
IntervalQualifier::Single(field) => field.output(logger)
IntervalQualifier::Range(from, to) => {
from.output(logger)
logger.write_string(" TO ")
to.output(logger)
}
}
}