#[cfg(not(feature = "std"))]
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
use core::fmt;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "visitor")]
use sqlparser_derive::{Visit, VisitMut};
pub use self::data_type::{
CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, TimezoneInfo,
};
pub use self::ddl::{
AlterColumnOperation, AlterIndexOperation, AlterTableOperation, ColumnDef, ColumnOption,
ColumnOptionDef, IndexType, KeyOrIndexDisplay, ReferentialAction, TableConstraint,
};
pub use self::operator::{BinaryOperator, UnaryOperator};
pub use self::query::{
Cte, ExceptSelectItem, ExcludeSelectItem, Fetch, IdentWithAlias, Join, JoinConstraint,
JoinOperator, LateralView, LockClause, LockType, NonBlock, Offset, OffsetRows, OrderByExpr,
Query, RenameSelectItem, Select, SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier,
Table, TableAlias, TableFactor, TableWithJoins, Top, Values, WildcardAdditionalOptions, With,
};
pub use self::value::{
escape_quoted_string, DateTimeField, DollarQuotedString, TrimWhereField, Value,
};
#[cfg(feature = "visitor")]
pub use visitor::*;
mod data_type;
mod ddl;
pub mod helpers;
mod operator;
mod query;
mod value;
#[cfg(feature = "visitor")]
mod visitor;
struct DisplaySeparated<'a, T>
where
T: fmt::Display,
{
slice: &'a [T],
sep: &'static str,
}
impl<'a, T> fmt::Display for DisplaySeparated<'a, T>
where
T: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut delim = "";
for t in self.slice {
write!(f, "{}", delim)?;
delim = self.sep;
write!(f, "{}", t)?;
}
Ok(())
}
}
fn display_separated<'a, T>(slice: &'a [T], sep: &'static str) -> DisplaySeparated<'a, T>
where
T: fmt::Display,
{
DisplaySeparated { slice, sep }
}
fn display_comma_separated<T>(slice: &[T]) -> DisplaySeparated<'_, T>
where
T: fmt::Display,
{
DisplaySeparated { slice, sep: ", " }
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct Ident {
pub value: String,
pub quote_style: Option<char>,
}
impl Ident {
pub fn new<S>(value: S) -> Self
where
S: Into<String>,
{
Ident {
value: value.into(),
quote_style: None,
}
}
pub fn with_quote<S>(quote: char, value: S) -> Self
where
S: Into<String>,
{
assert!(quote == '\'' || quote == '"' || quote == '`' || quote == '[');
Ident {
value: value.into(),
quote_style: Some(quote),
}
}
}
impl From<&str> for Ident {
fn from(value: &str) -> Self {
Ident {
value: value.to_string(),
quote_style: None,
}
}
}
impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.quote_style {
Some(q) if q == '"' || q == '\'' || q == '`' => {
let escaped = value::escape_quoted_string(&self.value, q);
write!(f, "{}{}{}", q, escaped, q)
}
Some(q) if q == '[' => write!(f, "[{}]", self.value),
None => f.write_str(&self.value),
_ => panic!("unexpected quote style"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct ObjectName(pub Vec<Ident>);
impl fmt::Display for ObjectName {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", display_separated(&self.0, "."))
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct Array {
pub elem: Vec<Expr>,
pub named: bool,
}
impl fmt::Display for Array {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}[{}]",
if self.named { "ARRAY" } else { "" },
display_comma_separated(&self.elem)
)
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum JsonOperator {
Arrow,
LongArrow,
HashArrow,
HashLongArrow,
Colon,
AtArrow,
ArrowAt,
HashMinus,
AtQuestion,
AtAt,
}
impl fmt::Display for JsonOperator {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
JsonOperator::Arrow => {
write!(f, "->")
}
JsonOperator::LongArrow => {
write!(f, "->>")
}
JsonOperator::HashArrow => {
write!(f, "#>")
}
JsonOperator::HashLongArrow => {
write!(f, "#>>")
}
JsonOperator::Colon => {
write!(f, ":")
}
JsonOperator::AtArrow => {
write!(f, "@>")
}
JsonOperator::ArrowAt => write!(f, "<@"),
JsonOperator::HashMinus => write!(f, "#-"),
JsonOperator::AtQuestion => write!(f, "@?"),
JsonOperator::AtAt => write!(f, "@@"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "visitor",
derive(Visit, VisitMut),
visit(with = "visit_expr")
)]
pub enum Expr {
Identifier(Ident),
CompoundIdentifier(Vec<Ident>),
JsonAccess {
left: Box<Expr>,
operator: JsonOperator,
right: Box<Expr>,
},
CompositeAccess { expr: Box<Expr>, key: Ident },
IsFalse(Box<Expr>),
IsNotFalse(Box<Expr>),
IsTrue(Box<Expr>),
IsNotTrue(Box<Expr>),
IsNull(Box<Expr>),
IsNotNull(Box<Expr>),
IsUnknown(Box<Expr>),
IsNotUnknown(Box<Expr>),
IsDistinctFrom(Box<Expr>, Box<Expr>),
IsNotDistinctFrom(Box<Expr>, Box<Expr>),
InList {
expr: Box<Expr>,
list: Vec<Expr>,
negated: bool,
},
InSubquery {
expr: Box<Expr>,
subquery: Box<Query>,
negated: bool,
},
InUnnest {
expr: Box<Expr>,
array_expr: Box<Expr>,
negated: bool,
},
Between {
expr: Box<Expr>,
negated: bool,
low: Box<Expr>,
high: Box<Expr>,
},
BinaryOp {
left: Box<Expr>,
op: BinaryOperator,
right: Box<Expr>,
},
Like {
negated: bool,
expr: Box<Expr>,
pattern: Box<Expr>,
escape_char: Option<char>,
},
ILike {
negated: bool,
expr: Box<Expr>,
pattern: Box<Expr>,
escape_char: Option<char>,
},
SimilarTo {
negated: bool,
expr: Box<Expr>,
pattern: Box<Expr>,
escape_char: Option<char>,
},
AnyOp(Box<Expr>),
AllOp(Box<Expr>),
UnaryOp { op: UnaryOperator, expr: Box<Expr> },
Cast {
expr: Box<Expr>,
data_type: DataType,
},
TryCast {
expr: Box<Expr>,
data_type: DataType,
},
SafeCast {
expr: Box<Expr>,
data_type: DataType,
},
AtTimeZone {
timestamp: Box<Expr>,
time_zone: String,
},
Extract {
field: DateTimeField,
expr: Box<Expr>,
},
Ceil {
expr: Box<Expr>,
field: DateTimeField,
},
Floor {
expr: Box<Expr>,
field: DateTimeField,
},
Position { expr: Box<Expr>, r#in: Box<Expr> },
Substring {
expr: Box<Expr>,
substring_from: Option<Box<Expr>>,
substring_for: Option<Box<Expr>>,
},
Trim {
expr: Box<Expr>,
trim_where: Option<TrimWhereField>,
trim_what: Option<Box<Expr>>,
},
Overlay {
expr: Box<Expr>,
overlay_what: Box<Expr>,
overlay_from: Box<Expr>,
overlay_for: Option<Box<Expr>>,
},
Collate {
expr: Box<Expr>,
collation: ObjectName,
},
Nested(Box<Expr>),
Value(Value),
TypedString { data_type: DataType, value: String },
MapAccess { column: Box<Expr>, keys: Vec<Expr> },
Function(Function),
AggregateExpressionWithFilter { expr: Box<Expr>, filter: Box<Expr> },
Case {
operand: Option<Box<Expr>>,
conditions: Vec<Expr>,
results: Vec<Expr>,
else_result: Option<Box<Expr>>,
},
Exists { subquery: Box<Query>, negated: bool },
Subquery(Box<Query>),
ArraySubquery(Box<Query>),
ListAgg(ListAgg),
ArrayAgg(ArrayAgg),
GroupingSets(Vec<Vec<Expr>>),
Cube(Vec<Vec<Expr>>),
Rollup(Vec<Vec<Expr>>),
Tuple(Vec<Expr>),
ArrayIndex { obj: Box<Expr>, indexes: Vec<Expr> },
Array(Array),
Interval {
value: Box<Expr>,
leading_field: Option<DateTimeField>,
leading_precision: Option<u64>,
last_field: Option<DateTimeField>,
fractional_seconds_precision: Option<u64>,
},
MatchAgainst {
columns: Vec<Ident>,
match_value: Value,
opt_search_modifier: Option<SearchModifier>,
},
}
impl fmt::Display for Expr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Expr::Identifier(s) => write!(f, "{}", s),
Expr::MapAccess { column, keys } => {
write!(f, "{}", column)?;
for k in keys {
match k {
k @ Expr::Value(Value::Number(_, _)) => write!(f, "[{}]", k)?,
Expr::Value(Value::SingleQuotedString(s)) => write!(f, "[\"{}\"]", s)?,
_ => write!(f, "[{}]", k)?,
}
}
Ok(())
}
Expr::CompoundIdentifier(s) => write!(f, "{}", display_separated(s, ".")),
Expr::IsTrue(ast) => write!(f, "{} IS TRUE", ast),
Expr::IsNotTrue(ast) => write!(f, "{} IS NOT TRUE", ast),
Expr::IsFalse(ast) => write!(f, "{} IS FALSE", ast),
Expr::IsNotFalse(ast) => write!(f, "{} IS NOT FALSE", ast),
Expr::IsNull(ast) => write!(f, "{} IS NULL", ast),
Expr::IsNotNull(ast) => write!(f, "{} IS NOT NULL", ast),
Expr::IsUnknown(ast) => write!(f, "{} IS UNKNOWN", ast),
Expr::IsNotUnknown(ast) => write!(f, "{} IS NOT UNKNOWN", ast),
Expr::InList {
expr,
list,
negated,
} => write!(
f,
"{} {}IN ({})",
expr,
if *negated { "NOT " } else { "" },
display_comma_separated(list)
),
Expr::InSubquery {
expr,
subquery,
negated,
} => write!(
f,
"{} {}IN ({})",
expr,
if *negated { "NOT " } else { "" },
subquery
),
Expr::InUnnest {
expr,
array_expr,
negated,
} => write!(
f,
"{} {}IN UNNEST({})",
expr,
if *negated { "NOT " } else { "" },
array_expr
),
Expr::Between {
expr,
negated,
low,
high,
} => write!(
f,
"{} {}BETWEEN {} AND {}",
expr,
if *negated { "NOT " } else { "" },
low,
high
),
Expr::BinaryOp { left, op, right } => write!(f, "{} {} {}", left, op, right),
Expr::Like {
negated,
expr,
pattern,
escape_char,
} => match escape_char {
Some(ch) => write!(
f,
"{} {}LIKE {} ESCAPE '{}'",
expr,
if *negated { "NOT " } else { "" },
pattern,
ch
),
_ => write!(
f,
"{} {}LIKE {}",
expr,
if *negated { "NOT " } else { "" },
pattern
),
},
Expr::ILike {
negated,
expr,
pattern,
escape_char,
} => match escape_char {
Some(ch) => write!(
f,
"{} {}ILIKE {} ESCAPE '{}'",
expr,
if *negated { "NOT " } else { "" },
pattern,
ch
),
_ => write!(
f,
"{} {}ILIKE {}",
expr,
if *negated { "NOT " } else { "" },
pattern
),
},
Expr::SimilarTo {
negated,
expr,
pattern,
escape_char,
} => match escape_char {
Some(ch) => write!(
f,
"{} {}SIMILAR TO {} ESCAPE '{}'",
expr,
if *negated { "NOT " } else { "" },
pattern,
ch
),
_ => write!(
f,
"{} {}SIMILAR TO {}",
expr,
if *negated { "NOT " } else { "" },
pattern
),
},
Expr::AnyOp(expr) => write!(f, "ANY({})", expr),
Expr::AllOp(expr) => write!(f, "ALL({})", expr),
Expr::UnaryOp { op, expr } => {
if op == &UnaryOperator::PGPostfixFactorial {
write!(f, "{}{}", expr, op)
} else if op == &UnaryOperator::Not {
write!(f, "{} {}", op, expr)
} else {
write!(f, "{}{}", op, expr)
}
}
Expr::Cast { expr, data_type } => write!(f, "CAST({} AS {})", expr, data_type),
Expr::TryCast { expr, data_type } => write!(f, "TRY_CAST({} AS {})", expr, data_type),
Expr::SafeCast { expr, data_type } => write!(f, "SAFE_CAST({} AS {})", expr, data_type),
Expr::Extract { field, expr } => write!(f, "EXTRACT({} FROM {})", field, expr),
Expr::Ceil { expr, field } => {
if field == &DateTimeField::NoDateTime {
write!(f, "CEIL({})", expr)
} else {
write!(f, "CEIL({} TO {})", expr, field)
}
}
Expr::Floor { expr, field } => {
if field == &DateTimeField::NoDateTime {
write!(f, "FLOOR({})", expr)
} else {
write!(f, "FLOOR({} TO {})", expr, field)
}
}
Expr::Position { expr, r#in } => write!(f, "POSITION({} IN {})", expr, r#in),
Expr::Collate { expr, collation } => write!(f, "{} COLLATE {}", expr, collation),
Expr::Nested(ast) => write!(f, "({})", ast),
Expr::Value(v) => write!(f, "{}", v),
Expr::TypedString { data_type, value } => {
write!(f, "{}", data_type)?;
write!(f, " '{}'", &value::escape_single_quote_string(value))
}
Expr::Function(fun) => write!(f, "{}", fun),
Expr::AggregateExpressionWithFilter { expr, filter } => {
write!(f, "{} FILTER (WHERE {})", expr, filter)
}
Expr::Case {
operand,
conditions,
results,
else_result,
} => {
write!(f, "CASE")?;
if let Some(operand) = operand {
write!(f, " {}", operand)?;
}
for (c, r) in conditions.iter().zip(results) {
write!(f, " WHEN {} THEN {}", c, r)?;
}
if let Some(else_result) = else_result {
write!(f, " ELSE {}", else_result)?;
}
write!(f, " END")
}
Expr::Exists { subquery, negated } => write!(
f,
"{}EXISTS ({})",
if *negated { "NOT " } else { "" },
subquery
),
Expr::Subquery(s) => write!(f, "({})", s),
Expr::ArraySubquery(s) => write!(f, "ARRAY({})", s),
Expr::ListAgg(listagg) => write!(f, "{}", listagg),
Expr::ArrayAgg(arrayagg) => write!(f, "{}", arrayagg),
Expr::GroupingSets(sets) => {
write!(f, "GROUPING SETS (")?;
let mut sep = "";
for set in sets {
write!(f, "{}", sep)?;
sep = ", ";
write!(f, "({})", display_comma_separated(set))?;
}
write!(f, ")")
}
Expr::Cube(sets) => {
write!(f, "CUBE (")?;
let mut sep = "";
for set in sets {
write!(f, "{}", sep)?;
sep = ", ";
if set.len() == 1 {
write!(f, "{}", set[0])?;
} else {
write!(f, "({})", display_comma_separated(set))?;
}
}
write!(f, ")")
}
Expr::Rollup(sets) => {
write!(f, "ROLLUP (")?;
let mut sep = "";
for set in sets {
write!(f, "{}", sep)?;
sep = ", ";
if set.len() == 1 {
write!(f, "{}", set[0])?;
} else {
write!(f, "({})", display_comma_separated(set))?;
}
}
write!(f, ")")
}
Expr::Substring {
expr,
substring_from,
substring_for,
} => {
write!(f, "SUBSTRING({}", expr)?;
if let Some(from_part) = substring_from {
write!(f, " FROM {}", from_part)?;
}
if let Some(for_part) = substring_for {
write!(f, " FOR {}", for_part)?;
}
write!(f, ")")
}
Expr::Overlay {
expr,
overlay_what,
overlay_from,
overlay_for,
} => {
write!(
f,
"OVERLAY({} PLACING {} FROM {}",
expr, overlay_what, overlay_from
)?;
if let Some(for_part) = overlay_for {
write!(f, " FOR {}", for_part)?;
}
write!(f, ")")
}
Expr::IsDistinctFrom(a, b) => write!(f, "{} IS DISTINCT FROM {}", a, b),
Expr::IsNotDistinctFrom(a, b) => write!(f, "{} IS NOT DISTINCT FROM {}", a, b),
Expr::Trim {
expr,
trim_where,
trim_what,
} => {
write!(f, "TRIM(")?;
if let Some(ident) = trim_where {
write!(f, "{} ", ident)?;
}
if let Some(trim_char) = trim_what {
write!(f, "{} FROM {}", trim_char, expr)?;
} else {
write!(f, "{}", expr)?;
}
write!(f, ")")
}
Expr::Tuple(exprs) => {
write!(f, "({})", display_comma_separated(exprs))
}
Expr::ArrayIndex { obj, indexes } => {
write!(f, "{}", obj)?;
for i in indexes {
write!(f, "[{}]", i)?;
}
Ok(())
}
Expr::Array(set) => {
write!(f, "{}", set)
}
Expr::JsonAccess {
left,
operator,
right,
} => {
if operator == &JsonOperator::Colon {
write!(f, "{}{}{}", left, operator, right)
} else {
write!(f, "{} {} {}", left, operator, right)
}
}
Expr::CompositeAccess { expr, key } => {
write!(f, "{}.{}", expr, key)
}
Expr::AtTimeZone {
timestamp,
time_zone,
} => {
write!(f, "{} AT TIME ZONE '{}'", timestamp, time_zone)
}
Expr::Interval {
value,
leading_field: Some(DateTimeField::Second),
leading_precision: Some(leading_precision),
last_field,
fractional_seconds_precision: Some(fractional_seconds_precision),
} => {
assert!(last_field.is_none());
write!(
f,
"INTERVAL {} SECOND ({}, {})",
value, leading_precision, fractional_seconds_precision
)
}
Expr::Interval {
value,
leading_field,
leading_precision,
last_field,
fractional_seconds_precision,
} => {
write!(f, "INTERVAL {}", value)?;
if let Some(leading_field) = leading_field {
write!(f, " {}", leading_field)?;
}
if let Some(leading_precision) = leading_precision {
write!(f, " ({})", leading_precision)?;
}
if let Some(last_field) = last_field {
write!(f, " TO {}", last_field)?;
}
if let Some(fractional_seconds_precision) = fractional_seconds_precision {
write!(f, " ({})", fractional_seconds_precision)?;
}
Ok(())
}
Expr::MatchAgainst {
columns,
match_value: match_expr,
opt_search_modifier,
} => {
write!(f, "MATCH ({}) AGAINST ", display_comma_separated(columns),)?;
if let Some(search_modifier) = opt_search_modifier {
write!(f, "({match_expr} {search_modifier})")?;
} else {
write!(f, "({match_expr})")?;
}
Ok(())
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct WindowSpec {
pub partition_by: Vec<Expr>,
pub order_by: Vec<OrderByExpr>,
pub window_frame: Option<WindowFrame>,
}
impl fmt::Display for WindowSpec {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut delim = "";
if !self.partition_by.is_empty() {
delim = " ";
write!(
f,
"PARTITION BY {}",
display_comma_separated(&self.partition_by)
)?;
}
if !self.order_by.is_empty() {
f.write_str(delim)?;
delim = " ";
write!(f, "ORDER BY {}", display_comma_separated(&self.order_by))?;
}
if let Some(window_frame) = &self.window_frame {
f.write_str(delim)?;
if let Some(end_bound) = &window_frame.end_bound {
write!(
f,
"{} BETWEEN {} AND {}",
window_frame.units, window_frame.start_bound, end_bound
)?;
} else {
write!(f, "{} {}", window_frame.units, window_frame.start_bound)?;
}
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct WindowFrame {
pub units: WindowFrameUnits,
pub start_bound: WindowFrameBound,
pub end_bound: Option<WindowFrameBound>,
}
impl Default for WindowFrame {
fn default() -> Self {
Self {
units: WindowFrameUnits::Range,
start_bound: WindowFrameBound::Preceding(None),
end_bound: None,
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum WindowFrameUnits {
Rows,
Range,
Groups,
}
impl fmt::Display for WindowFrameUnits {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self {
WindowFrameUnits::Rows => "ROWS",
WindowFrameUnits::Range => "RANGE",
WindowFrameUnits::Groups => "GROUPS",
})
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum WindowFrameBound {
CurrentRow,
Preceding(Option<Box<Expr>>),
Following(Option<Box<Expr>>),
}
impl fmt::Display for WindowFrameBound {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
WindowFrameBound::CurrentRow => f.write_str("CURRENT ROW"),
WindowFrameBound::Preceding(None) => f.write_str("UNBOUNDED PRECEDING"),
WindowFrameBound::Following(None) => f.write_str("UNBOUNDED FOLLOWING"),
WindowFrameBound::Preceding(Some(n)) => write!(f, "{} PRECEDING", n),
WindowFrameBound::Following(Some(n)) => write!(f, "{} FOLLOWING", n),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum AddDropSync {
ADD,
DROP,
SYNC,
}
impl fmt::Display for AddDropSync {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AddDropSync::SYNC => f.write_str("SYNC PARTITIONS"),
AddDropSync::DROP => f.write_str("DROP PARTITIONS"),
AddDropSync::ADD => f.write_str("ADD PARTITIONS"),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum ShowCreateObject {
Event,
Function,
Procedure,
Table,
Trigger,
View,
}
impl fmt::Display for ShowCreateObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ShowCreateObject::Event => f.write_str("EVENT"),
ShowCreateObject::Function => f.write_str("FUNCTION"),
ShowCreateObject::Procedure => f.write_str("PROCEDURE"),
ShowCreateObject::Table => f.write_str("TABLE"),
ShowCreateObject::Trigger => f.write_str("TRIGGER"),
ShowCreateObject::View => f.write_str("VIEW"),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CommentObject {
Column,
Table,
}
impl fmt::Display for CommentObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CommentObject::Column => f.write_str("COLUMN"),
CommentObject::Table => f.write_str("TABLE"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum Password {
Password(Expr),
NullPassword,
}
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "visitor",
derive(Visit, VisitMut),
visit(with = "visit_statement")
)]
pub enum Statement {
Analyze {
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
partitions: Option<Vec<Expr>>,
for_columns: bool,
columns: Vec<Ident>,
cache_metadata: bool,
noscan: bool,
compute_statistics: bool,
},
Truncate {
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
partitions: Option<Vec<Expr>>,
},
Msck {
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
repair: bool,
partition_action: Option<AddDropSync>,
},
Query(Box<Query>),
Insert {
or: Option<SqliteOnConflict>,
into: bool,
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
columns: Vec<Ident>,
overwrite: bool,
source: Box<Query>,
partitioned: Option<Vec<Expr>>,
after_columns: Vec<Ident>,
table: bool,
on: Option<OnInsert>,
returning: Option<Vec<SelectItem>>,
},
Directory {
overwrite: bool,
local: bool,
path: String,
file_format: Option<FileFormat>,
source: Box<Query>,
},
Copy {
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
columns: Vec<Ident>,
to: bool,
target: CopyTarget,
options: Vec<CopyOption>,
legacy_options: Vec<CopyLegacyOption>,
values: Vec<Option<String>>,
},
Close {
cursor: CloseCursor,
},
Update {
table: TableWithJoins,
assignments: Vec<Assignment>,
from: Option<TableWithJoins>,
selection: Option<Expr>,
returning: Option<Vec<SelectItem>>,
},
Delete {
table_name: TableFactor,
using: Option<TableFactor>,
selection: Option<Expr>,
returning: Option<Vec<SelectItem>>,
},
CreateView {
or_replace: bool,
materialized: bool,
name: ObjectName,
columns: Vec<Ident>,
query: Box<Query>,
with_options: Vec<SqlOption>,
cluster_by: Vec<Ident>,
},
CreateTable {
or_replace: bool,
temporary: bool,
external: bool,
global: Option<bool>,
if_not_exists: bool,
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
name: ObjectName,
columns: Vec<ColumnDef>,
constraints: Vec<TableConstraint>,
hive_distribution: HiveDistributionStyle,
hive_formats: Option<HiveFormat>,
table_properties: Vec<SqlOption>,
with_options: Vec<SqlOption>,
file_format: Option<FileFormat>,
location: Option<String>,
query: Option<Box<Query>>,
without_rowid: bool,
like: Option<ObjectName>,
clone: Option<ObjectName>,
engine: Option<String>,
default_charset: Option<String>,
collation: Option<String>,
on_commit: Option<OnCommit>,
on_cluster: Option<String>,
},
CreateVirtualTable {
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
name: ObjectName,
if_not_exists: bool,
module_name: Ident,
module_args: Vec<Ident>,
},
CreateIndex {
name: ObjectName,
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
using: Option<Ident>,
columns: Vec<OrderByExpr>,
unique: bool,
if_not_exists: bool,
},
CreateRole {
names: Vec<ObjectName>,
if_not_exists: bool,
login: Option<bool>,
inherit: Option<bool>,
bypassrls: Option<bool>,
password: Option<Password>,
superuser: Option<bool>,
create_db: Option<bool>,
create_role: Option<bool>,
replication: Option<bool>,
connection_limit: Option<Expr>,
valid_until: Option<Expr>,
in_role: Vec<Ident>,
in_group: Vec<Ident>,
role: Vec<Ident>,
user: Vec<Ident>,
admin: Vec<Ident>,
authorization_owner: Option<ObjectName>,
},
AlterTable {
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
name: ObjectName,
operation: AlterTableOperation,
},
AlterIndex {
name: ObjectName,
operation: AlterIndexOperation,
},
Drop {
object_type: ObjectType,
if_exists: bool,
names: Vec<ObjectName>,
cascade: bool,
restrict: bool,
purge: bool,
},
DropFunction {
if_exists: bool,
func_desc: Vec<DropFunctionDesc>,
option: Option<ReferentialAction>,
},
Declare {
name: Ident,
binary: bool,
sensitive: Option<bool>,
scroll: Option<bool>,
hold: Option<bool>,
query: Box<Query>,
},
Fetch {
name: Ident,
direction: FetchDirection,
into: Option<ObjectName>,
},
Discard { object_type: DiscardObject },
SetRole {
context_modifier: ContextModifier,
role_name: Option<Ident>,
},
SetVariable {
local: bool,
hivevar: bool,
variable: ObjectName,
value: Vec<Expr>,
},
SetTimeZone { local: bool, value: Expr },
SetNames {
charset_name: String,
collation_name: Option<String>,
},
SetNamesDefault {},
ShowFunctions { filter: Option<ShowStatementFilter> },
ShowVariable { variable: Vec<Ident> },
ShowVariables { filter: Option<ShowStatementFilter> },
ShowCreate {
obj_type: ShowCreateObject,
obj_name: ObjectName,
},
ShowColumns {
extended: bool,
full: bool,
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
filter: Option<ShowStatementFilter>,
},
ShowTables {
extended: bool,
full: bool,
db_name: Option<Ident>,
filter: Option<ShowStatementFilter>,
},
ShowCollation { filter: Option<ShowStatementFilter> },
Use { db_name: Ident },
StartTransaction { modes: Vec<TransactionMode> },
SetTransaction {
modes: Vec<TransactionMode>,
snapshot: Option<Value>,
session: bool,
},
Comment {
object_type: CommentObject,
object_name: ObjectName,
comment: Option<String>,
},
Commit { chain: bool },
Rollback { chain: bool },
CreateSchema {
schema_name: SchemaName,
if_not_exists: bool,
},
CreateDatabase {
db_name: ObjectName,
if_not_exists: bool,
location: Option<String>,
managed_location: Option<String>,
},
CreateFunction {
or_replace: bool,
temporary: bool,
name: ObjectName,
args: Option<Vec<OperateFunctionArg>>,
return_type: Option<DataType>,
params: CreateFunctionBody,
},
Assert {
condition: Expr,
message: Option<Expr>,
},
Grant {
privileges: Privileges,
objects: GrantObjects,
grantees: Vec<Ident>,
with_grant_option: bool,
granted_by: Option<Ident>,
},
Revoke {
privileges: Privileges,
objects: GrantObjects,
grantees: Vec<Ident>,
granted_by: Option<Ident>,
cascade: bool,
},
Deallocate { name: Ident, prepare: bool },
Execute { name: Ident, parameters: Vec<Expr> },
Prepare {
name: Ident,
data_types: Vec<DataType>,
statement: Box<Statement>,
},
Kill {
modifier: Option<KillType>,
id: u64,
},
ExplainTable {
describe_alias: bool,
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
},
Explain {
describe_alias: bool,
analyze: bool,
verbose: bool,
statement: Box<Statement>,
format: Option<AnalyzeFormat>,
},
Savepoint { name: Ident },
Merge {
into: bool,
table: TableFactor,
source: TableFactor,
on: Box<Expr>,
clauses: Vec<MergeClause>,
},
Cache {
table_flag: Option<ObjectName>,
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
has_as: bool,
options: Vec<SqlOption>,
query: Option<Query>,
},
UNCache {
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
table_name: ObjectName,
if_exists: bool,
},
CreateSequence {
temporary: bool,
if_not_exists: bool,
name: ObjectName,
data_type: Option<DataType>,
sequence_options: Vec<SequenceOptions>,
owned_by: Option<ObjectName>,
},
}
impl fmt::Display for Statement {
#[allow(clippy::cognitive_complexity)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Statement::Kill { modifier, id } => {
write!(f, "KILL ")?;
if let Some(m) = modifier {
write!(f, "{} ", m)?;
}
write!(f, "{}", id)
}
Statement::ExplainTable {
describe_alias,
table_name,
} => {
if *describe_alias {
write!(f, "DESCRIBE ")?;
} else {
write!(f, "EXPLAIN ")?;
}
write!(f, "{}", table_name)
}
Statement::Explain {
describe_alias,
verbose,
analyze,
statement,
format,
} => {
if *describe_alias {
write!(f, "DESCRIBE ")?;
} else {
write!(f, "EXPLAIN ")?;
}
if *analyze {
write!(f, "ANALYZE ")?;
}
if *verbose {
write!(f, "VERBOSE ")?;
}
if let Some(format) = format {
write!(f, "FORMAT {} ", format)?;
}
write!(f, "{}", statement)
}
Statement::Query(s) => write!(f, "{}", s),
Statement::Declare {
name,
binary,
sensitive,
scroll,
hold,
query,
} => {
write!(f, "DECLARE {} ", name)?;
if *binary {
write!(f, "BINARY ")?;
}
if let Some(sensitive) = sensitive {
if *sensitive {
write!(f, "INSENSITIVE ")?;
} else {
write!(f, "ASENSITIVE ")?;
}
}
if let Some(scroll) = scroll {
if *scroll {
write!(f, "SCROLL ")?;
} else {
write!(f, "NO SCROLL ")?;
}
}
write!(f, "CURSOR ")?;
if let Some(hold) = hold {
if *hold {
write!(f, "WITH HOLD ")?;
} else {
write!(f, "WITHOUT HOLD ")?;
}
}
write!(f, "FOR {}", query)
}
Statement::Fetch {
name,
direction,
into,
} => {
write!(f, "FETCH {} ", direction)?;
write!(f, "IN {}", name)?;
if let Some(into) = into {
write!(f, " INTO {}", into)?;
}
Ok(())
}
Statement::Directory {
overwrite,
local,
path,
file_format,
source,
} => {
write!(
f,
"INSERT{overwrite}{local} DIRECTORY '{path}'",
overwrite = if *overwrite { " OVERWRITE" } else { "" },
local = if *local { " LOCAL" } else { "" },
path = path
)?;
if let Some(ref ff) = file_format {
write!(f, " STORED AS {}", ff)?
}
write!(f, " {}", source)
}
Statement::Msck {
table_name,
repair,
partition_action,
} => {
write!(
f,
"MSCK {repair}TABLE {table}",
repair = if *repair { "REPAIR " } else { "" },
table = table_name
)?;
if let Some(pa) = partition_action {
write!(f, " {}", pa)?;
}
Ok(())
}
Statement::Truncate {
table_name,
partitions,
} => {
write!(f, "TRUNCATE TABLE {}", table_name)?;
if let Some(ref parts) = partitions {
if !parts.is_empty() {
write!(f, " PARTITION ({})", display_comma_separated(parts))?;
}
}
Ok(())
}
Statement::Analyze {
table_name,
partitions,
for_columns,
columns,
cache_metadata,
noscan,
compute_statistics,
} => {
write!(f, "ANALYZE TABLE {}", table_name)?;
if let Some(ref parts) = partitions {
if !parts.is_empty() {
write!(f, " PARTITION ({})", display_comma_separated(parts))?;
}
}
if *compute_statistics {
write!(f, " COMPUTE STATISTICS")?;
}
if *noscan {
write!(f, " NOSCAN")?;
}
if *cache_metadata {
write!(f, " CACHE METADATA")?;
}
if *for_columns {
write!(f, " FOR COLUMNS")?;
if !columns.is_empty() {
write!(f, " {}", display_comma_separated(columns))?;
}
}
Ok(())
}
Statement::Insert {
or,
into,
table_name,
overwrite,
partitioned,
columns,
after_columns,
source,
table,
on,
returning,
} => {
if let Some(action) = or {
write!(f, "INSERT OR {} INTO {} ", action, table_name)?;
} else {
write!(
f,
"INSERT{over}{int}{tbl} {table_name} ",
table_name = table_name,
over = if *overwrite { " OVERWRITE" } else { "" },
int = if *into { " INTO" } else { "" },
tbl = if *table { " TABLE" } else { "" }
)?;
}
if !columns.is_empty() {
write!(f, "({}) ", display_comma_separated(columns))?;
}
if let Some(ref parts) = partitioned {
if !parts.is_empty() {
write!(f, "PARTITION ({}) ", display_comma_separated(parts))?;
}
}
if !after_columns.is_empty() {
write!(f, "({}) ", display_comma_separated(after_columns))?;
}
write!(f, "{}", source)?;
if let Some(on) = on {
write!(f, "{}", on)?;
}
if let Some(returning) = returning {
write!(f, " RETURNING {}", display_comma_separated(returning))?;
}
Ok(())
}
Statement::Copy {
table_name,
columns,
to,
target,
options,
legacy_options,
values,
} => {
write!(f, "COPY {}", table_name)?;
if !columns.is_empty() {
write!(f, " ({})", display_comma_separated(columns))?;
}
write!(f, " {} {}", if *to { "TO" } else { "FROM" }, target)?;
if !options.is_empty() {
write!(f, " ({})", display_comma_separated(options))?;
}
if !legacy_options.is_empty() {
write!(f, " {}", display_separated(legacy_options, " "))?;
}
if !values.is_empty() {
writeln!(f, ";")?;
let mut delim = "";
for v in values {
write!(f, "{}", delim)?;
delim = "\t";
if let Some(v) = v {
write!(f, "{}", v)?;
} else {
write!(f, "\\N")?;
}
}
write!(f, "\n\\.")?;
}
Ok(())
}
Statement::Update {
table,
assignments,
from,
selection,
returning,
} => {
write!(f, "UPDATE {}", table)?;
if !assignments.is_empty() {
write!(f, " SET {}", display_comma_separated(assignments))?;
}
if let Some(from) = from {
write!(f, " FROM {}", from)?;
}
if let Some(selection) = selection {
write!(f, " WHERE {}", selection)?;
}
if let Some(returning) = returning {
write!(f, " RETURNING {}", display_comma_separated(returning))?;
}
Ok(())
}
Statement::Delete {
table_name,
using,
selection,
returning,
} => {
write!(f, "DELETE FROM {}", table_name)?;
if let Some(using) = using {
write!(f, " USING {}", using)?;
}
if let Some(selection) = selection {
write!(f, " WHERE {}", selection)?;
}
if let Some(returning) = returning {
write!(f, " RETURNING {}", display_comma_separated(returning))?;
}
Ok(())
}
Statement::Close { cursor } => {
write!(f, "CLOSE {}", cursor)?;
Ok(())
}
Statement::CreateDatabase {
db_name,
if_not_exists,
location,
managed_location,
} => {
write!(f, "CREATE DATABASE")?;
if *if_not_exists {
write!(f, " IF NOT EXISTS")?;
}
write!(f, " {}", db_name)?;
if let Some(l) = location {
write!(f, " LOCATION '{}'", l)?;
}
if let Some(ml) = managed_location {
write!(f, " MANAGEDLOCATION '{}'", ml)?;
}
Ok(())
}
Statement::CreateFunction {
or_replace,
temporary,
name,
args,
return_type,
params,
} => {
write!(
f,
"CREATE {or_replace}{temp}FUNCTION {name}",
temp = if *temporary { "TEMPORARY " } else { "" },
or_replace = if *or_replace { "OR REPLACE " } else { "" },
)?;
if let Some(args) = args {
write!(f, "({})", display_comma_separated(args))?;
}
if let Some(return_type) = return_type {
write!(f, " RETURNS {}", return_type)?;
}
write!(f, "{params}")?;
Ok(())
}
Statement::CreateView {
name,
or_replace,
columns,
query,
materialized,
with_options,
cluster_by,
} => {
write!(
f,
"CREATE {or_replace}{materialized}VIEW {name}",
or_replace = if *or_replace { "OR REPLACE " } else { "" },
materialized = if *materialized { "MATERIALIZED " } else { "" },
name = name
)?;
if !with_options.is_empty() {
write!(f, " WITH ({})", display_comma_separated(with_options))?;
}
if !columns.is_empty() {
write!(f, " ({})", display_comma_separated(columns))?;
}
if !cluster_by.is_empty() {
write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
}
write!(f, " AS {}", query)
}
Statement::CreateTable {
name,
columns,
constraints,
table_properties,
with_options,
or_replace,
if_not_exists,
hive_distribution,
hive_formats,
external,
global,
temporary,
file_format,
location,
query,
without_rowid,
like,
clone,
default_charset,
engine,
collation,
on_commit,
on_cluster,
} => {
write!(
f,
"CREATE {or_replace}{external}{global}{temporary}TABLE {if_not_exists}{name}",
or_replace = if *or_replace { "OR REPLACE " } else { "" },
external = if *external { "EXTERNAL " } else { "" },
global = global
.map(|global| {
if global {
"GLOBAL "
} else {
"LOCAL "
}
})
.unwrap_or(""),
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
temporary = if *temporary { "TEMPORARY " } else { "" },
name = name,
)?;
if let Some(on_cluster) = on_cluster {
write!(
f,
" ON CLUSTER {}",
on_cluster.replace('{', "'{").replace('}', "}'")
)?;
}
if !columns.is_empty() || !constraints.is_empty() {
write!(f, " ({}", display_comma_separated(columns))?;
if !columns.is_empty() && !constraints.is_empty() {
write!(f, ", ")?;
}
write!(f, "{})", display_comma_separated(constraints))?;
} else if query.is_none() && like.is_none() && clone.is_none() {
write!(f, " ()")?;
}
if *without_rowid {
write!(f, " WITHOUT ROWID")?;
}
if let Some(l) = like {
write!(f, " LIKE {}", l)?;
}
if let Some(c) = clone {
write!(f, " CLONE {}", c)?;
}
match hive_distribution {
HiveDistributionStyle::PARTITIONED { columns } => {
write!(f, " PARTITIONED BY ({})", display_comma_separated(columns))?;
}
HiveDistributionStyle::CLUSTERED {
columns,
sorted_by,
num_buckets,
} => {
write!(f, " CLUSTERED BY ({})", display_comma_separated(columns))?;
if !sorted_by.is_empty() {
write!(f, " SORTED BY ({})", display_comma_separated(sorted_by))?;
}
if *num_buckets > 0 {
write!(f, " INTO {} BUCKETS", num_buckets)?;
}
}
HiveDistributionStyle::SKEWED {
columns,
on,
stored_as_directories,
} => {
write!(
f,
" SKEWED BY ({})) ON ({})",
display_comma_separated(columns),
display_comma_separated(on)
)?;
if *stored_as_directories {
write!(f, " STORED AS DIRECTORIES")?;
}
}
_ => (),
}
if let Some(HiveFormat {
row_format,
storage,
location,
}) = hive_formats
{
match row_format {
Some(HiveRowFormat::SERDE { class }) => {
write!(f, " ROW FORMAT SERDE '{}'", class)?
}
Some(HiveRowFormat::DELIMITED) => write!(f, " ROW FORMAT DELIMITED")?,
None => (),
}
match storage {
Some(HiveIOFormat::IOF {
input_format,
output_format,
}) => write!(
f,
" STORED AS INPUTFORMAT {} OUTPUTFORMAT {}",
input_format, output_format
)?,
Some(HiveIOFormat::FileFormat { format }) if !*external => {
write!(f, " STORED AS {}", format)?
}
_ => (),
}
if !*external {
if let Some(loc) = location {
write!(f, " LOCATION '{}'", loc)?;
}
}
}
if *external {
write!(
f,
" STORED AS {} LOCATION '{}'",
file_format.as_ref().unwrap(),
location.as_ref().unwrap()
)?;
}
if !table_properties.is_empty() {
write!(
f,
" TBLPROPERTIES ({})",
display_comma_separated(table_properties)
)?;
}
if !with_options.is_empty() {
write!(f, " WITH ({})", display_comma_separated(with_options))?;
}
if let Some(query) = query {
write!(f, " AS {}", query)?;
}
if let Some(engine) = engine {
write!(f, " ENGINE={}", engine)?;
}
if let Some(default_charset) = default_charset {
write!(f, " DEFAULT CHARSET={}", default_charset)?;
}
if let Some(collation) = collation {
write!(f, " COLLATE={}", collation)?;
}
if on_commit.is_some() {
let on_commit = match on_commit {
Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
Some(OnCommit::PreserveRows) => "ON COMMIT PRESERVE ROWS",
Some(OnCommit::Drop) => "ON COMMIT DROP",
None => "",
};
write!(f, " {}", on_commit)?;
}
Ok(())
}
Statement::CreateVirtualTable {
name,
if_not_exists,
module_name,
module_args,
} => {
write!(
f,
"CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
name = name,
module_name = module_name
)?;
if !module_args.is_empty() {
write!(f, " ({})", display_comma_separated(module_args))?;
}
Ok(())
}
Statement::CreateIndex {
name,
table_name,
using,
columns,
unique,
if_not_exists,
} => {
write!(
f,
"CREATE {unique}INDEX {if_not_exists}{name} ON {table_name}",
unique = if *unique { "UNIQUE " } else { "" },
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
name = name,
table_name = table_name
)?;
if let Some(value) = using {
write!(f, " USING {} ", value)?;
}
write!(f, "({})", display_separated(columns, ","))
}
Statement::CreateRole {
names,
if_not_exists,
inherit,
login,
bypassrls,
password,
create_db,
create_role,
superuser,
replication,
connection_limit,
valid_until,
in_role,
in_group,
role,
user,
admin,
authorization_owner,
} => {
write!(
f,
"CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
names = display_separated(names, ", "),
superuser = match *superuser {
Some(true) => " SUPERUSER",
Some(false) => " NOSUPERUSER",
None => ""
},
create_db = match *create_db {
Some(true) => " CREATEDB",
Some(false) => " NOCREATEDB",
None => ""
},
create_role = match *create_role {
Some(true) => " CREATEROLE",
Some(false) => " NOCREATEROLE",
None => ""
},
inherit = match *inherit {
Some(true) => " INHERIT",
Some(false) => " NOINHERIT",
None => ""
},
login = match *login {
Some(true) => " LOGIN",
Some(false) => " NOLOGIN",
None => ""
},
replication = match *replication {
Some(true) => " REPLICATION",
Some(false) => " NOREPLICATION",
None => ""
},
bypassrls = match *bypassrls {
Some(true) => " BYPASSRLS",
Some(false) => " NOBYPASSRLS",
None => ""
}
)?;
if let Some(limit) = connection_limit {
write!(f, " CONNECTION LIMIT {}", limit)?;
}
match password {
Some(Password::Password(pass)) => write!(f, " PASSWORD {}", pass),
Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
None => Ok(()),
}?;
if let Some(until) = valid_until {
write!(f, " VALID UNTIL {}", until)?;
}
if !in_role.is_empty() {
write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
}
if !in_group.is_empty() {
write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
}
if !role.is_empty() {
write!(f, " ROLE {}", display_comma_separated(role))?;
}
if !user.is_empty() {
write!(f, " USER {}", display_comma_separated(user))?;
}
if !admin.is_empty() {
write!(f, " ADMIN {}", display_comma_separated(admin))?;
}
if let Some(owner) = authorization_owner {
write!(f, " AUTHORIZATION {}", owner)?;
}
Ok(())
}
Statement::AlterTable { name, operation } => {
write!(f, "ALTER TABLE {} {}", name, operation)
}
Statement::AlterIndex { name, operation } => {
write!(f, "ALTER INDEX {} {}", name, operation)
}
Statement::Drop {
object_type,
if_exists,
names,
cascade,
restrict,
purge,
} => write!(
f,
"DROP {}{} {}{}{}{}",
object_type,
if *if_exists { " IF EXISTS" } else { "" },
display_comma_separated(names),
if *cascade { " CASCADE" } else { "" },
if *restrict { " RESTRICT" } else { "" },
if *purge { " PURGE" } else { "" }
),
Statement::DropFunction {
if_exists,
func_desc,
option,
} => {
write!(
f,
"DROP FUNCTION{} {}",
if *if_exists { " IF EXISTS" } else { "" },
display_comma_separated(func_desc),
)?;
if let Some(op) = option {
write!(f, " {}", op)?;
}
Ok(())
}
Statement::Discard { object_type } => {
write!(f, "DISCARD {object_type}", object_type = object_type)?;
Ok(())
}
Self::SetRole {
context_modifier,
role_name,
} => {
let role_name = role_name.clone().unwrap_or_else(|| Ident::new("NONE"));
write!(f, "SET{context_modifier} ROLE {role_name}")
}
Statement::SetVariable {
local,
variable,
hivevar,
value,
} => {
f.write_str("SET ")?;
if *local {
f.write_str("LOCAL ")?;
}
write!(
f,
"{hivevar}{name} = {value}",
hivevar = if *hivevar { "HIVEVAR:" } else { "" },
name = variable,
value = display_comma_separated(value)
)
}
Statement::SetTimeZone { local, value } => {
f.write_str("SET ")?;
if *local {
f.write_str("LOCAL ")?;
}
write!(f, "TIME ZONE {value}")
}
Statement::SetNames {
charset_name,
collation_name,
} => {
f.write_str("SET NAMES ")?;
f.write_str(charset_name)?;
if let Some(collation) = collation_name {
f.write_str(" COLLATE ")?;
f.write_str(collation)?;
};
Ok(())
}
Statement::SetNamesDefault {} => {
f.write_str("SET NAMES DEFAULT")?;
Ok(())
}
Statement::ShowVariable { variable } => {
write!(f, "SHOW")?;
if !variable.is_empty() {
write!(f, " {}", display_separated(variable, " "))?;
}
Ok(())
}
Statement::ShowVariables { filter } => {
write!(f, "SHOW VARIABLES")?;
if filter.is_some() {
write!(f, " {}", filter.as_ref().unwrap())?;
}
Ok(())
}
Statement::ShowCreate { obj_type, obj_name } => {
write!(
f,
"SHOW CREATE {obj_type} {obj_name}",
obj_type = obj_type,
obj_name = obj_name,
)?;
Ok(())
}
Statement::ShowColumns {
extended,
full,
table_name,
filter,
} => {
write!(
f,
"SHOW {extended}{full}COLUMNS FROM {table_name}",
extended = if *extended { "EXTENDED " } else { "" },
full = if *full { "FULL " } else { "" },
table_name = table_name,
)?;
if let Some(filter) = filter {
write!(f, " {}", filter)?;
}
Ok(())
}
Statement::ShowTables {
extended,
full,
db_name,
filter,
} => {
write!(
f,
"SHOW {extended}{full}TABLES",
extended = if *extended { "EXTENDED " } else { "" },
full = if *full { "FULL " } else { "" },
)?;
if let Some(db_name) = db_name {
write!(f, " FROM {}", db_name)?;
}
if let Some(filter) = filter {
write!(f, " {}", filter)?;
}
Ok(())
}
Statement::ShowFunctions { filter } => {
write!(f, "SHOW FUNCTIONS")?;
if let Some(filter) = filter {
write!(f, " {}", filter)?;
}
Ok(())
}
Statement::Use { db_name } => {
write!(f, "USE {}", db_name)?;
Ok(())
}
Statement::ShowCollation { filter } => {
write!(f, "SHOW COLLATION")?;
if let Some(filter) = filter {
write!(f, " {}", filter)?;
}
Ok(())
}
Statement::StartTransaction { modes } => {
write!(f, "START TRANSACTION")?;
if !modes.is_empty() {
write!(f, " {}", display_comma_separated(modes))?;
}
Ok(())
}
Statement::SetTransaction {
modes,
snapshot,
session,
} => {
if *session {
write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
} else {
write!(f, "SET TRANSACTION")?;
}
if !modes.is_empty() {
write!(f, " {}", display_comma_separated(modes))?;
}
if let Some(snapshot_id) = snapshot {
write!(f, " SNAPSHOT {}", snapshot_id)?;
}
Ok(())
}
Statement::Commit { chain } => {
write!(f, "COMMIT{}", if *chain { " AND CHAIN" } else { "" },)
}
Statement::Rollback { chain } => {
write!(f, "ROLLBACK{}", if *chain { " AND CHAIN" } else { "" },)
}
Statement::CreateSchema {
schema_name,
if_not_exists,
} => write!(
f,
"CREATE SCHEMA {if_not_exists}{name}",
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
name = schema_name
),
Statement::Assert { condition, message } => {
write!(f, "ASSERT {}", condition)?;
if let Some(m) = message {
write!(f, " AS {}", m)?;
}
Ok(())
}
Statement::Grant {
privileges,
objects,
grantees,
with_grant_option,
granted_by,
} => {
write!(f, "GRANT {} ", privileges)?;
write!(f, "ON {} ", objects)?;
write!(f, "TO {}", display_comma_separated(grantees))?;
if *with_grant_option {
write!(f, " WITH GRANT OPTION")?;
}
if let Some(grantor) = granted_by {
write!(f, " GRANTED BY {}", grantor)?;
}
Ok(())
}
Statement::Revoke {
privileges,
objects,
grantees,
granted_by,
cascade,
} => {
write!(f, "REVOKE {} ", privileges)?;
write!(f, "ON {} ", objects)?;
write!(f, "FROM {}", display_comma_separated(grantees))?;
if let Some(grantor) = granted_by {
write!(f, " GRANTED BY {}", grantor)?;
}
write!(f, " {}", if *cascade { "CASCADE" } else { "RESTRICT" })?;
Ok(())
}
Statement::Deallocate { name, prepare } => write!(
f,
"DEALLOCATE {prepare}{name}",
prepare = if *prepare { "PREPARE " } else { "" },
name = name,
),
Statement::Execute { name, parameters } => {
write!(f, "EXECUTE {}", name)?;
if !parameters.is_empty() {
write!(f, "({})", display_comma_separated(parameters))?;
}
Ok(())
}
Statement::Prepare {
name,
data_types,
statement,
} => {
write!(f, "PREPARE {} ", name)?;
if !data_types.is_empty() {
write!(f, "({}) ", display_comma_separated(data_types))?;
}
write!(f, "AS {}", statement)
}
Statement::Comment {
object_type,
object_name,
comment,
} => {
write!(f, "COMMENT ON {} {} IS ", object_type, object_name)?;
if let Some(c) = comment {
write!(f, "'{}'", c)
} else {
write!(f, "NULL")
}
}
Statement::Savepoint { name } => {
write!(f, "SAVEPOINT ")?;
write!(f, "{}", name)
}
Statement::Merge {
into,
table,
source,
on,
clauses,
} => {
write!(
f,
"MERGE{int} {table} USING {source} ",
int = if *into { " INTO" } else { "" }
)?;
write!(f, "ON {} ", on)?;
write!(f, "{}", display_separated(clauses, " "))
}
Statement::Cache {
table_name,
table_flag,
has_as,
options,
query,
} => {
if table_flag.is_some() {
write!(
f,
"CACHE {table_flag} TABLE {table_name}",
table_flag = table_flag.clone().unwrap(),
table_name = table_name,
)?;
} else {
write!(f, "CACHE TABLE {table_name}", table_name = table_name,)?;
}
if !options.is_empty() {
write!(f, " OPTIONS({})", display_comma_separated(options))?;
}
let has_query = query.is_some();
if *has_as && has_query {
write!(f, " AS {query}", query = query.clone().unwrap())
} else if !has_as && has_query {
write!(f, " {query}", query = query.clone().unwrap())
} else if *has_as && !has_query {
write!(f, " AS")
} else {
Ok(())
}
}
Statement::UNCache {
table_name,
if_exists,
} => {
if *if_exists {
write!(
f,
"UNCACHE TABLE IF EXISTS {table_name}",
table_name = table_name
)
} else {
write!(f, "UNCACHE TABLE {table_name}", table_name = table_name)
}
}
Statement::CreateSequence {
temporary,
if_not_exists,
name,
data_type,
sequence_options,
owned_by,
} => {
let as_type: String = if let Some(dt) = data_type.as_ref() {
[" AS ", &dt.to_string()].concat()
} else {
"".to_string()
};
write!(
f,
"CREATE {temporary}SEQUENCE {if_not_exists}{name}{as_type}",
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
temporary = if *temporary { "TEMPORARY " } else { "" },
name = name,
as_type = as_type
)?;
for sequence_option in sequence_options {
write!(f, "{}", sequence_option)?;
}
if let Some(ob) = owned_by.as_ref() {
write!(f, " OWNED BY {}", ob)?;
}
write!(f, "")
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum SequenceOptions {
IncrementBy(Expr, bool),
MinValue(MinMaxValue),
MaxValue(MinMaxValue),
StartWith(Expr, bool),
Cache(Expr),
Cycle(bool),
}
impl fmt::Display for SequenceOptions {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
SequenceOptions::IncrementBy(increment, by) => {
write!(
f,
" INCREMENT{by} {increment}",
by = if *by { " BY" } else { "" },
increment = increment
)
}
SequenceOptions::MinValue(value) => match value {
MinMaxValue::Empty => {
write!(f, "")
}
MinMaxValue::None => {
write!(f, " NO MINVALUE")
}
MinMaxValue::Some(minvalue) => {
write!(f, " MINVALUE {minvalue}", minvalue = minvalue)
}
},
SequenceOptions::MaxValue(value) => match value {
MinMaxValue::Empty => {
write!(f, "")
}
MinMaxValue::None => {
write!(f, " NO MAXVALUE")
}
MinMaxValue::Some(maxvalue) => {
write!(f, " MAXVALUE {maxvalue}", maxvalue = maxvalue)
}
},
SequenceOptions::StartWith(start, with) => {
write!(
f,
" START{with} {start}",
with = if *with { " WITH" } else { "" },
start = start
)
}
SequenceOptions::Cache(cache) => {
write!(f, " CACHE {}", *cache)
}
SequenceOptions::Cycle(no) => {
write!(f, " {}CYCLE", if *no { "NO " } else { "" })
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum MinMaxValue {
Empty,
None,
Some(Expr),
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
#[non_exhaustive]
pub enum OnInsert {
DuplicateKeyUpdate(Vec<Assignment>),
OnConflict(OnConflict),
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct OnConflict {
pub conflict_target: Option<ConflictTarget>,
pub action: OnConflictAction,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum ConflictTarget {
Columns(Vec<Ident>),
OnConstraint(ObjectName),
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum OnConflictAction {
DoNothing,
DoUpdate(DoUpdate),
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct DoUpdate {
pub assignments: Vec<Assignment>,
pub selection: Option<Expr>,
}
impl fmt::Display for OnInsert {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::DuplicateKeyUpdate(expr) => write!(
f,
" ON DUPLICATE KEY UPDATE {}",
display_comma_separated(expr)
),
Self::OnConflict(o) => write!(f, " {o}"),
}
}
}
impl fmt::Display for OnConflict {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, " ON CONFLICT")?;
if let Some(target) = &self.conflict_target {
write!(f, "{}", target)?;
}
write!(f, " {}", self.action)
}
}
impl fmt::Display for ConflictTarget {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ConflictTarget::Columns(cols) => write!(f, "({})", display_comma_separated(cols)),
ConflictTarget::OnConstraint(name) => write!(f, " ON CONSTRAINT {}", name),
}
}
}
impl fmt::Display for OnConflictAction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::DoNothing => write!(f, "DO NOTHING"),
Self::DoUpdate(do_update) => {
write!(f, "DO UPDATE")?;
if !do_update.assignments.is_empty() {
write!(
f,
" SET {}",
display_comma_separated(&do_update.assignments)
)?;
}
if let Some(selection) = &do_update.selection {
write!(f, " WHERE {}", selection)?;
}
Ok(())
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum Privileges {
All {
with_privileges_keyword: bool,
},
Actions(Vec<Action>),
}
impl fmt::Display for Privileges {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Privileges::All {
with_privileges_keyword,
} => {
write!(
f,
"ALL{}",
if *with_privileges_keyword {
" PRIVILEGES"
} else {
""
}
)
}
Privileges::Actions(actions) => {
write!(f, "{}", display_comma_separated(actions))
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum FetchDirection {
Count { limit: Value },
Next,
Prior,
First,
Last,
Absolute { limit: Value },
Relative { limit: Value },
All,
Forward { limit: Option<Value> },
ForwardAll,
Backward { limit: Option<Value> },
BackwardAll,
}
impl fmt::Display for FetchDirection {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FetchDirection::Count { limit } => f.write_str(&limit.to_string())?,
FetchDirection::Next => f.write_str("NEXT")?,
FetchDirection::Prior => f.write_str("PRIOR")?,
FetchDirection::First => f.write_str("FIRST")?,
FetchDirection::Last => f.write_str("LAST")?,
FetchDirection::Absolute { limit } => {
f.write_str("ABSOLUTE ")?;
f.write_str(&limit.to_string())?;
}
FetchDirection::Relative { limit } => {
f.write_str("RELATIVE ")?;
f.write_str(&limit.to_string())?;
}
FetchDirection::All => f.write_str("ALL")?,
FetchDirection::Forward { limit } => {
f.write_str("FORWARD")?;
if let Some(l) = limit {
f.write_str(" ")?;
f.write_str(&l.to_string())?;
}
}
FetchDirection::ForwardAll => f.write_str("FORWARD ALL")?,
FetchDirection::Backward { limit } => {
f.write_str("BACKWARD")?;
if let Some(l) = limit {
f.write_str(" ")?;
f.write_str(&l.to_string())?;
}
}
FetchDirection::BackwardAll => f.write_str("BACKWARD ALL")?,
};
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum Action {
Connect,
Create,
Delete,
Execute,
Insert { columns: Option<Vec<Ident>> },
References { columns: Option<Vec<Ident>> },
Select { columns: Option<Vec<Ident>> },
Temporary,
Trigger,
Truncate,
Update { columns: Option<Vec<Ident>> },
Usage,
}
impl fmt::Display for Action {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Action::Connect => f.write_str("CONNECT")?,
Action::Create => f.write_str("CREATE")?,
Action::Delete => f.write_str("DELETE")?,
Action::Execute => f.write_str("EXECUTE")?,
Action::Insert { .. } => f.write_str("INSERT")?,
Action::References { .. } => f.write_str("REFERENCES")?,
Action::Select { .. } => f.write_str("SELECT")?,
Action::Temporary => f.write_str("TEMPORARY")?,
Action::Trigger => f.write_str("TRIGGER")?,
Action::Truncate => f.write_str("TRUNCATE")?,
Action::Update { .. } => f.write_str("UPDATE")?,
Action::Usage => f.write_str("USAGE")?,
};
match self {
Action::Insert { columns }
| Action::References { columns }
| Action::Select { columns }
| Action::Update { columns } => {
if let Some(columns) = columns {
write!(f, " ({})", display_comma_separated(columns))?;
}
}
_ => (),
};
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum GrantObjects {
AllSequencesInSchema { schemas: Vec<ObjectName> },
AllTablesInSchema { schemas: Vec<ObjectName> },
Schemas(Vec<ObjectName>),
Sequences(Vec<ObjectName>),
Tables(Vec<ObjectName>),
}
impl fmt::Display for GrantObjects {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
GrantObjects::Sequences(sequences) => {
write!(f, "SEQUENCE {}", display_comma_separated(sequences))
}
GrantObjects::Schemas(schemas) => {
write!(f, "SCHEMA {}", display_comma_separated(schemas))
}
GrantObjects::Tables(tables) => {
write!(f, "{}", display_comma_separated(tables))
}
GrantObjects::AllSequencesInSchema { schemas } => {
write!(
f,
"ALL SEQUENCES IN SCHEMA {}",
display_comma_separated(schemas)
)
}
GrantObjects::AllTablesInSchema { schemas } => {
write!(
f,
"ALL TABLES IN SCHEMA {}",
display_comma_separated(schemas)
)
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct Assignment {
pub id: Vec<Ident>,
pub value: Expr,
}
impl fmt::Display for Assignment {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} = {}", display_separated(&self.id, "."), self.value)
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum FunctionArgExpr {
Expr(Expr),
QualifiedWildcard(ObjectName),
Wildcard,
}
impl fmt::Display for FunctionArgExpr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FunctionArgExpr::Expr(expr) => write!(f, "{}", expr),
FunctionArgExpr::QualifiedWildcard(prefix) => write!(f, "{}.*", prefix),
FunctionArgExpr::Wildcard => f.write_str("*"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum FunctionArg {
Named { name: Ident, arg: FunctionArgExpr },
Unnamed(FunctionArgExpr),
}
impl fmt::Display for FunctionArg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FunctionArg::Named { name, arg } => write!(f, "{} => {}", name, arg),
FunctionArg::Unnamed(unnamed_arg) => write!(f, "{}", unnamed_arg),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CloseCursor {
All,
Specific { name: Ident },
}
impl fmt::Display for CloseCursor {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
CloseCursor::All => write!(f, "ALL"),
CloseCursor::Specific { name } => write!(f, "{}", name),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct Function {
pub name: ObjectName,
pub args: Vec<FunctionArg>,
pub over: Option<WindowSpec>,
pub distinct: bool,
pub special: bool,
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum AnalyzeFormat {
TEXT,
GRAPHVIZ,
JSON,
}
impl fmt::Display for AnalyzeFormat {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(match self {
AnalyzeFormat::TEXT => "TEXT",
AnalyzeFormat::GRAPHVIZ => "GRAPHVIZ",
AnalyzeFormat::JSON => "JSON",
})
}
}
impl fmt::Display for Function {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.special {
write!(f, "{}", self.name)?;
} else {
write!(
f,
"{}({}{})",
self.name,
if self.distinct { "DISTINCT " } else { "" },
display_comma_separated(&self.args),
)?;
if let Some(o) = &self.over {
write!(f, " OVER ({})", o)?;
}
}
Ok(())
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum FileFormat {
TEXTFILE,
SEQUENCEFILE,
ORC,
PARQUET,
AVRO,
RCFILE,
JSONFILE,
}
impl fmt::Display for FileFormat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::FileFormat::*;
f.write_str(match self {
TEXTFILE => "TEXTFILE",
SEQUENCEFILE => "SEQUENCEFILE",
ORC => "ORC",
PARQUET => "PARQUET",
AVRO => "AVRO",
RCFILE => "RCFILE",
JSONFILE => "JSONFILE",
})
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct ListAgg {
pub distinct: bool,
pub expr: Box<Expr>,
pub separator: Option<Box<Expr>>,
pub on_overflow: Option<ListAggOnOverflow>,
pub within_group: Vec<OrderByExpr>,
}
impl fmt::Display for ListAgg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"LISTAGG({}{}",
if self.distinct { "DISTINCT " } else { "" },
self.expr
)?;
if let Some(separator) = &self.separator {
write!(f, ", {}", separator)?;
}
if let Some(on_overflow) = &self.on_overflow {
write!(f, "{}", on_overflow)?;
}
write!(f, ")")?;
if !self.within_group.is_empty() {
write!(
f,
" WITHIN GROUP (ORDER BY {})",
display_comma_separated(&self.within_group)
)?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum ListAggOnOverflow {
Error,
Truncate {
filler: Option<Box<Expr>>,
with_count: bool,
},
}
impl fmt::Display for ListAggOnOverflow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, " ON OVERFLOW")?;
match self {
ListAggOnOverflow::Error => write!(f, " ERROR"),
ListAggOnOverflow::Truncate { filler, with_count } => {
write!(f, " TRUNCATE")?;
if let Some(filler) = filler {
write!(f, " {}", filler)?;
}
if *with_count {
write!(f, " WITH")?;
} else {
write!(f, " WITHOUT")?;
}
write!(f, " COUNT")
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct ArrayAgg {
pub distinct: bool,
pub expr: Box<Expr>,
pub order_by: Option<Box<OrderByExpr>>,
pub limit: Option<Box<Expr>>,
pub within_group: bool, }
impl fmt::Display for ArrayAgg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"ARRAY_AGG({}{}",
if self.distinct { "DISTINCT " } else { "" },
self.expr
)?;
if !self.within_group {
if let Some(order_by) = &self.order_by {
write!(f, " ORDER BY {}", order_by)?;
}
if let Some(limit) = &self.limit {
write!(f, " LIMIT {}", limit)?;
}
}
write!(f, ")")?;
if self.within_group {
if let Some(order_by) = &self.order_by {
write!(f, " WITHIN GROUP (ORDER BY {})", order_by)?;
}
}
Ok(())
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum ObjectType {
Table,
View,
Index,
Schema,
Role,
Sequence,
}
impl fmt::Display for ObjectType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self {
ObjectType::Table => "TABLE",
ObjectType::View => "VIEW",
ObjectType::Index => "INDEX",
ObjectType::Schema => "SCHEMA",
ObjectType::Role => "ROLE",
ObjectType::Sequence => "SEQUENCE",
})
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum KillType {
Connection,
Query,
Mutation,
}
impl fmt::Display for KillType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match self {
KillType::Connection => "CONNECTION",
KillType::Query => "QUERY",
KillType::Mutation => "MUTATION",
})
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum HiveDistributionStyle {
PARTITIONED {
columns: Vec<ColumnDef>,
},
CLUSTERED {
columns: Vec<Ident>,
sorted_by: Vec<ColumnDef>,
num_buckets: i32,
},
SKEWED {
columns: Vec<ColumnDef>,
on: Vec<ColumnDef>,
stored_as_directories: bool,
},
NONE,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum HiveRowFormat {
SERDE { class: String },
DELIMITED,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
#[allow(clippy::large_enum_variant)]
pub enum HiveIOFormat {
IOF {
input_format: Expr,
output_format: Expr,
},
FileFormat {
format: FileFormat,
},
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct HiveFormat {
pub row_format: Option<HiveRowFormat>,
pub storage: Option<HiveIOFormat>,
pub location: Option<String>,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct SqlOption {
pub name: Ident,
pub value: Value,
}
impl fmt::Display for SqlOption {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} = {}", self.name, self.value)
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum TransactionMode {
AccessMode(TransactionAccessMode),
IsolationLevel(TransactionIsolationLevel),
}
impl fmt::Display for TransactionMode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use TransactionMode::*;
match self {
AccessMode(access_mode) => write!(f, "{}", access_mode),
IsolationLevel(iso_level) => write!(f, "ISOLATION LEVEL {}", iso_level),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum TransactionAccessMode {
ReadOnly,
ReadWrite,
}
impl fmt::Display for TransactionAccessMode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use TransactionAccessMode::*;
f.write_str(match self {
ReadOnly => "READ ONLY",
ReadWrite => "READ WRITE",
})
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum TransactionIsolationLevel {
ReadUncommitted,
ReadCommitted,
RepeatableRead,
Serializable,
}
impl fmt::Display for TransactionIsolationLevel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use TransactionIsolationLevel::*;
f.write_str(match self {
ReadUncommitted => "READ UNCOMMITTED",
ReadCommitted => "READ COMMITTED",
RepeatableRead => "REPEATABLE READ",
Serializable => "SERIALIZABLE",
})
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum ShowStatementFilter {
Like(String),
ILike(String),
Where(Expr),
}
impl fmt::Display for ShowStatementFilter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ShowStatementFilter::*;
match self {
Like(pattern) => write!(f, "LIKE '{}'", value::escape_single_quote_string(pattern)),
ILike(pattern) => write!(f, "ILIKE {}", value::escape_single_quote_string(pattern)),
Where(expr) => write!(f, "WHERE {}", expr),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum SqliteOnConflict {
Rollback,
Abort,
Fail,
Ignore,
Replace,
}
impl fmt::Display for SqliteOnConflict {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use SqliteOnConflict::*;
match self {
Rollback => write!(f, "ROLLBACK"),
Abort => write!(f, "ABORT"),
Fail => write!(f, "FAIL"),
Ignore => write!(f, "IGNORE"),
Replace => write!(f, "REPLACE"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CopyTarget {
Stdin,
Stdout,
File {
filename: String,
},
Program {
command: String,
},
}
impl fmt::Display for CopyTarget {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use CopyTarget::*;
match self {
Stdin { .. } => write!(f, "STDIN"),
Stdout => write!(f, "STDOUT"),
File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
Program { command } => write!(
f,
"PROGRAM '{}'",
value::escape_single_quote_string(command)
),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum OnCommit {
DeleteRows,
PreserveRows,
Drop,
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CopyOption {
Format(Ident),
Freeze(bool),
Delimiter(char),
Null(String),
Header(bool),
Quote(char),
Escape(char),
ForceQuote(Vec<Ident>),
ForceNotNull(Vec<Ident>),
ForceNull(Vec<Ident>),
Encoding(String),
}
impl fmt::Display for CopyOption {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use CopyOption::*;
match self {
Format(name) => write!(f, "FORMAT {}", name),
Freeze(true) => write!(f, "FREEZE"),
Freeze(false) => write!(f, "FREEZE FALSE"),
Delimiter(char) => write!(f, "DELIMITER '{}'", char),
Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
Header(true) => write!(f, "HEADER"),
Header(false) => write!(f, "HEADER FALSE"),
Quote(char) => write!(f, "QUOTE '{}'", char),
Escape(char) => write!(f, "ESCAPE '{}'", char),
ForceQuote(columns) => write!(f, "FORCE_QUOTE ({})", display_comma_separated(columns)),
ForceNotNull(columns) => {
write!(f, "FORCE_NOT_NULL ({})", display_comma_separated(columns))
}
ForceNull(columns) => write!(f, "FORCE_NULL ({})", display_comma_separated(columns)),
Encoding(name) => write!(f, "ENCODING '{}'", value::escape_single_quote_string(name)),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CopyLegacyOption {
Binary,
Delimiter(char),
Null(String),
Csv(Vec<CopyLegacyCsvOption>),
}
impl fmt::Display for CopyLegacyOption {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use CopyLegacyOption::*;
match self {
Binary => write!(f, "BINARY"),
Delimiter(char) => write!(f, "DELIMITER '{}'", char),
Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)),
Csv(opts) => write!(f, "CSV {}", display_separated(opts, " ")),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CopyLegacyCsvOption {
Header,
Quote(char),
Escape(char),
ForceQuote(Vec<Ident>),
ForceNotNull(Vec<Ident>),
}
impl fmt::Display for CopyLegacyCsvOption {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use CopyLegacyCsvOption::*;
match self {
Header => write!(f, "HEADER"),
Quote(char) => write!(f, "QUOTE '{}'", char),
Escape(char) => write!(f, "ESCAPE '{}'", char),
ForceQuote(columns) => write!(f, "FORCE QUOTE {}", display_comma_separated(columns)),
ForceNotNull(columns) => {
write!(f, "FORCE NOT NULL {}", display_comma_separated(columns))
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum MergeClause {
MatchedUpdate {
predicate: Option<Expr>,
assignments: Vec<Assignment>,
},
MatchedDelete(Option<Expr>),
NotMatched {
predicate: Option<Expr>,
columns: Vec<Ident>,
values: Values,
},
}
impl fmt::Display for MergeClause {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use MergeClause::*;
write!(f, "WHEN")?;
match self {
MatchedUpdate {
predicate,
assignments,
} => {
write!(f, " MATCHED")?;
if let Some(pred) = predicate {
write!(f, " AND {}", pred)?;
}
write!(
f,
" THEN UPDATE SET {}",
display_comma_separated(assignments)
)
}
MatchedDelete(predicate) => {
write!(f, " MATCHED")?;
if let Some(pred) = predicate {
write!(f, " AND {}", pred)?;
}
write!(f, " THEN DELETE")
}
NotMatched {
predicate,
columns,
values,
} => {
write!(f, " NOT MATCHED")?;
if let Some(pred) = predicate {
write!(f, " AND {}", pred)?;
}
write!(
f,
" THEN INSERT ({}) {}",
display_comma_separated(columns),
values
)
}
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum DiscardObject {
ALL,
PLANS,
SEQUENCES,
TEMP,
}
impl fmt::Display for DiscardObject {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DiscardObject::ALL => f.write_str("ALL"),
DiscardObject::PLANS => f.write_str("PLANS"),
DiscardObject::SEQUENCES => f.write_str("SEQUENCES"),
DiscardObject::TEMP => f.write_str("TEMP"),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum ContextModifier {
None,
Local,
Session,
}
impl fmt::Display for ContextModifier {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::None => {
write!(f, "")
}
Self::Local => {
write!(f, " LOCAL")
}
Self::Session => {
write!(f, " SESSION")
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum DropFunctionOption {
Restrict,
Cascade,
}
impl fmt::Display for DropFunctionOption {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DropFunctionOption::Restrict => write!(f, "RESTRICT "),
DropFunctionOption::Cascade => write!(f, "CASCADE "),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct DropFunctionDesc {
pub name: ObjectName,
pub args: Option<Vec<OperateFunctionArg>>,
}
impl fmt::Display for DropFunctionDesc {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)?;
if let Some(args) = &self.args {
write!(f, "({})", display_comma_separated(args))?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct OperateFunctionArg {
pub mode: Option<ArgMode>,
pub name: Option<Ident>,
pub data_type: DataType,
pub default_expr: Option<Expr>,
}
impl OperateFunctionArg {
pub fn unnamed(data_type: DataType) -> Self {
Self {
mode: None,
name: None,
data_type,
default_expr: None,
}
}
pub fn with_name(name: &str, data_type: DataType) -> Self {
Self {
mode: None,
name: Some(name.into()),
data_type,
default_expr: None,
}
}
}
impl fmt::Display for OperateFunctionArg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(mode) = &self.mode {
write!(f, "{} ", mode)?;
}
if let Some(name) = &self.name {
write!(f, "{} ", name)?;
}
write!(f, "{}", self.data_type)?;
if let Some(default_expr) = &self.default_expr {
write!(f, " = {}", default_expr)?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum ArgMode {
In,
Out,
InOut,
}
impl fmt::Display for ArgMode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ArgMode::In => write!(f, "IN"),
ArgMode::Out => write!(f, "OUT"),
ArgMode::InOut => write!(f, "INOUT"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum FunctionBehavior {
Immutable,
Stable,
Volatile,
}
impl fmt::Display for FunctionBehavior {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FunctionBehavior::Immutable => write!(f, "IMMUTABLE"),
FunctionBehavior::Stable => write!(f, "STABLE"),
FunctionBehavior::Volatile => write!(f, "VOLATILE"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum FunctionDefinition {
SingleQuotedDef(String),
DoubleDollarDef(String),
}
impl fmt::Display for FunctionDefinition {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
FunctionDefinition::SingleQuotedDef(s) => write!(f, "'{s}'")?,
FunctionDefinition::DoubleDollarDef(s) => write!(f, "$${s}$$")?,
}
Ok(())
}
}
#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct CreateFunctionBody {
pub language: Option<Ident>,
pub behavior: Option<FunctionBehavior>,
pub as_: Option<FunctionDefinition>,
pub return_: Option<Expr>,
pub using: Option<CreateFunctionUsing>,
}
impl fmt::Display for CreateFunctionBody {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(language) = &self.language {
write!(f, " LANGUAGE {language}")?;
}
if let Some(behavior) = &self.behavior {
write!(f, " {behavior}")?;
}
if let Some(definition) = &self.as_ {
write!(f, " AS {definition}")?;
}
if let Some(expr) = &self.return_ {
write!(f, " RETURN {expr}")?;
}
if let Some(using) = &self.using {
write!(f, " {using}")?;
}
Ok(())
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum CreateFunctionUsing {
Jar(String),
File(String),
Archive(String),
}
impl fmt::Display for CreateFunctionUsing {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "USING ")?;
match self {
CreateFunctionUsing::Jar(uri) => write!(f, "JAR '{uri}'"),
CreateFunctionUsing::File(uri) => write!(f, "FILE '{uri}'"),
CreateFunctionUsing::Archive(uri) => write!(f, "ARCHIVE '{uri}'"),
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum SchemaName {
Simple(ObjectName),
UnnamedAuthorization(Ident),
NamedAuthorization(ObjectName, Ident),
}
impl fmt::Display for SchemaName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
SchemaName::Simple(name) => {
write!(f, "{name}")
}
SchemaName::UnnamedAuthorization(authorization) => {
write!(f, "AUTHORIZATION {authorization}")
}
SchemaName::NamedAuthorization(name, authorization) => {
write!(f, "{name} AUTHORIZATION {authorization}")
}
}
}
}
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum SearchModifier {
InNaturalLanguageMode,
InNaturalLanguageModeWithQueryExpansion,
InBooleanMode,
WithQueryExpansion,
}
impl fmt::Display for SearchModifier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InNaturalLanguageMode => {
write!(f, "IN NATURAL LANGUAGE MODE")?;
}
Self::InNaturalLanguageModeWithQueryExpansion => {
write!(f, "IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION")?;
}
Self::InBooleanMode => {
write!(f, "IN BOOLEAN MODE")?;
}
Self::WithQueryExpansion => {
write!(f, "WITH QUERY EXPANSION")?;
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_window_frame_default() {
let window_frame = WindowFrame::default();
assert_eq!(WindowFrameBound::Preceding(None), window_frame.start_bound);
}
#[test]
fn test_grouping_sets_display() {
let grouping_sets = Expr::GroupingSets(vec![
vec![Expr::Identifier(Ident::new("a"))],
vec![Expr::Identifier(Ident::new("b"))],
]);
assert_eq!("GROUPING SETS ((a), (b))", format!("{}", grouping_sets));
let grouping_sets = Expr::GroupingSets(vec![vec![
Expr::Identifier(Ident::new("a")),
Expr::Identifier(Ident::new("b")),
]]);
assert_eq!("GROUPING SETS ((a, b))", format!("{}", grouping_sets));
let grouping_sets = Expr::GroupingSets(vec![
vec![
Expr::Identifier(Ident::new("a")),
Expr::Identifier(Ident::new("b")),
],
vec![
Expr::Identifier(Ident::new("c")),
Expr::Identifier(Ident::new("d")),
],
]);
assert_eq!(
"GROUPING SETS ((a, b), (c, d))",
format!("{}", grouping_sets)
);
}
#[test]
fn test_rollup_display() {
let rollup = Expr::Rollup(vec![vec![Expr::Identifier(Ident::new("a"))]]);
assert_eq!("ROLLUP (a)", format!("{}", rollup));
let rollup = Expr::Rollup(vec![vec![
Expr::Identifier(Ident::new("a")),
Expr::Identifier(Ident::new("b")),
]]);
assert_eq!("ROLLUP ((a, b))", format!("{}", rollup));
let rollup = Expr::Rollup(vec![
vec![Expr::Identifier(Ident::new("a"))],
vec![Expr::Identifier(Ident::new("b"))],
]);
assert_eq!("ROLLUP (a, b)", format!("{}", rollup));
let rollup = Expr::Rollup(vec![
vec![Expr::Identifier(Ident::new("a"))],
vec![
Expr::Identifier(Ident::new("b")),
Expr::Identifier(Ident::new("c")),
],
vec![Expr::Identifier(Ident::new("d"))],
]);
assert_eq!("ROLLUP (a, (b, c), d)", format!("{}", rollup));
}
#[test]
fn test_cube_display() {
let cube = Expr::Cube(vec![vec![Expr::Identifier(Ident::new("a"))]]);
assert_eq!("CUBE (a)", format!("{}", cube));
let cube = Expr::Cube(vec![vec![
Expr::Identifier(Ident::new("a")),
Expr::Identifier(Ident::new("b")),
]]);
assert_eq!("CUBE ((a, b))", format!("{}", cube));
let cube = Expr::Cube(vec![
vec![Expr::Identifier(Ident::new("a"))],
vec![Expr::Identifier(Ident::new("b"))],
]);
assert_eq!("CUBE (a, b)", format!("{}", cube));
let cube = Expr::Cube(vec![
vec![Expr::Identifier(Ident::new("a"))],
vec![
Expr::Identifier(Ident::new("b")),
Expr::Identifier(Ident::new("c")),
],
vec![Expr::Identifier(Ident::new("d"))],
]);
assert_eq!("CUBE (a, (b, c), d)", format!("{}", cube));
}
}