sqlparser-queryscript 0.32.0

Extensible SQL Lexer and Parser with support for ANSI SQL:2011
use std::fmt;

use super::{display_comma_separated, Expr, Ident, Located, SelectItem};

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct LoopRange {
    pub item: Located<Ident>,
    pub range: Box<Expr>,
}

impl fmt::Display for LoopRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} in {}", self.item, self.range)
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct ForEach<T> {
    pub ranges: Vec<LoopRange>,
    pub body: Vec<T>,
}

impl<T: fmt::Display> fmt::Display for ForEach<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "FOR EACH ")?;
        if self.ranges.len() == 1 {
            write!(f, "{}", self.ranges[0])?;
        } else {
            write!(f, "({})", display_comma_separated(&self.ranges))?;
        }
        writeln!(f, "{{")?;
        for stmt in self.body.iter() {
            write!(f, "  {},", stmt)?;
        }
        write!(f, "\n}}")
    }
}

impl ForEach<ForEachOr<Vec<Expr>>> {
    pub fn vec_display(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "FOR EACH ")?;
        if self.ranges.len() == 1 {
            write!(f, "{}", self.ranges[0])?;
        } else {
            write!(f, "({})", display_comma_separated(&self.ranges))?;
        }
        writeln!(f, "{{")?;
        for stmt in self.body.iter() {
            match stmt {
                ForEachOr::ForEach(fe) => {
                    write!(f, "  ")?;
                    fe.vec_display(f)?;
                }
                ForEachOr::Item(item) => write!(f, "  {},", display_comma_separated(item))?,
            };
        }
        write!(f, "\n}}")
    }
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum ForEachOr<T> {
    ForEach(ForEach<ForEachOr<T>>),
    Item(T),
}

impl<T> From<T> for ForEachOr<T> {
    fn from(item: T) -> Self {
        Self::Item(item)
    }
}

pub trait ToForEach {
    type Target;
    fn for_each(self) -> Self::Target;
}

impl<T> ToForEach for Vec<T> {
    type Target = Vec<ForEachOr<T>>;
    fn for_each(self) -> Self::Target {
        self.into_iter().map(|i| ForEachOr::Item(i)).collect()
    }
}

impl<T: fmt::Display> fmt::Display for ForEachOr<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::ForEach(fe) => fe.fmt(f),
            Self::Item(item) => item.fmt(f),
        }
    }
}

pub trait ConstructForEach: Sized {
    fn construct_for_each(foreach: ForEach<Self>) -> Self;
}

impl ConstructForEach for SelectItem {
    fn construct_for_each(foreach: ForEach<Self>) -> Self {
        SelectItem::ForEach(foreach)
    }
}

impl<T> ConstructForEach for ForEachOr<T> {
    fn construct_for_each(foreach: ForEach<Self>) -> Self {
        ForEachOr::ForEach(foreach)
    }
}