orql 0.1.0

A toy SQL parser for a subset of the Oracle dialect.
Documentation
use super::{Expr, Ident, Node, OrderBy, PartitionBy};

#[derive(Debug)]
pub enum WindowSpec<'s, ID> {
    /// Represents an empty window spec, treating the entire set of query rows
    /// as a single partition.
    ///
    /// The contained node can be used to access comments within the empty
    /// parens.
    Empty(Node<(), ID>),

    /// Represents a non-empty window spec describing the shape of the window
    /// in more details.
    Details(WindowSpecDetails<'s, ID>),
}

/// The details Specification details of a (analytical) window as part of a
/// [function call](crate::ast::FunctionParams::over) or
/// [query WINDOW definitions](crate::ast::QuerySelect::windows)
///
/// Note: ... a window specifiction part of a query's `WINDOW` clause
/// [underlies certain rules](https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-1B520407-DD06-4568-8E64-25F90F4C0B59) that are
/// _not_ checked by the parser!
#[derive(Debug)]
pub struct WindowSpecDetails<'s, ID> {
    /// Reference by name to a defined window whose definitions to use as a base
    ///
    /// Note: the name is exclusive with the partition clause
    pub window_name: Option<Node<Ident<'s>, ID>>,

    /// the partition definition of the window; e.g. `PARTITION BY <expr>, <expr>`
    ///
    /// Note: the `PARTITION BY` is mutually exlusive with `window_name` when the spec is part of a analytical function call
    pub partition_by: Option<PartitionBy<'s, ID>>,

    /// e.g. `ORDER BY <expr>, <expr>`
    pub order_by: Option<OrderBy<'s, ID>>,

    /// Window frame definition; e.g. ROWS BETWEEN ...
    ///
    /// Note: a frame definition, when part of a function call, cannot be
    /// present without a preceding `order_by` definition
    pub frame: Option<WindowFrame<'s, ID>>,
}

#[derive(Debug)]
pub struct WindowFrame<'s, ID> {
    /// the unit of the frame's bounds, e.g. `ROWS | RANGE | GROUPS`
    pub unit_token: Node<WindowFrameUnit, ID>,

    /// the bounds of the frame, e.g. `... BETWEEN ... AND ...`
    pub bounds: WindowFrameBounds<'s, ID>,

    /// exclusions within the frame, e.g. `... EXCLUDE TIES`
    pub exclude: Option<WindowFrameExclude<ID>>,
}

#[derive(Debug, Clone, Copy)]
pub enum WindowFrameUnit {
    /// `ROWS`
    Rows,

    /// `RANGE`
    Range,

    /// `GROUPS`
    Groups,
}

#[derive(Debug)]
pub enum WindowFrameBounds<'s, ID> {
    /// e.g. `ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING`
    Between {
        /// the `BETWEEN` keyword
        between_token: Node<(), ID>,
        /// the start of the "between" range
        start: WindowFrameBoundType<'s, ID>,
        /// the `AND` keyword
        and_token: Node<(), ID>,
        /// the endo of the "end" range
        end: WindowFrameBoundType<'s, ID>,
    },

    /// e.g. `ROWS UNBOUNDED PRECEEDING`
    ///
    /// Note: the direction is always [WindowFrameBoundDirection::Preceding]
    Start(WindowFrameBoundType<'s, ID>),
}

#[derive(Debug)]
pub enum WindowFrameBoundType<'s, ID> {
    /// e.g. `UNBOUNDED PRECEDING` or `UNBOUNDED FOLLOWING`
    Unbounded {
        /// the `UNBOUNDED` keyword
        unbounded_token: Node<(), ID>,
        /// the direction `PRECEDING` or `FOLLOWING` keyword
        direction_token: Node<WindowFrameBoundDirection, ID>,
    },

    /// e.g. `CURRENT ROW`
    CurrentRow {
        /// the `CURRENT` keyword
        current_token: Node<(), ID>,
        /// the `ROW` keyword
        row_token: Node<(), ID>,
    },

    /// e.g. `<value_expr> PRECEDING` or `<value_expr> FOLLOWING`
    Value {
        /// the value (expression) by which to limit frame bound
        expr: Expr<'s, ID>,
        /// the direction `PRECEDING` or `FOLLOWING` keyword
        direction_token: Node<WindowFrameBoundDirection, ID>,
    },
}

/// Defines the direction (relative to the current row) in which to start or
/// end a frame.
#[derive(Debug, Clone, Copy)]
pub enum WindowFrameBoundDirection {
    /// e.g. `... UNBOUNDED PRECEEDING`
    Preceding,

    /// e.g. `... AND <expr> FOLLOWING`
    Following,
}

/// Specifies exclusions from a [window frame](WindowFrame).
#[derive(Debug)]
pub struct WindowFrameExclude<ID> {
    /// the `EXCLUDE` token
    pub exclude_token: Node<(), ID>,

    /// the "what" to be excluded
    pub subject: WindowFrameExcludeSubject<ID>,
}

/// the `EXCLUDE` clause of a [WindowFrame]
#[derive(Debug)]
pub enum WindowFrameExcludeSubject<ID> {
    /// e.g. `EXCLUDE CURRENT ROW`
    CurrentRow {
        current_token: Node<(), ID>,
        row_token: Node<(), ID>,
    },

    /// e.g. `EXCLUDE GROUP`
    Group { group_token: Node<(), ID> },

    /// e.g. `EXCLUDE TIES`
    Ties { ties_token: Node<(), ID> },

    /// e.g. `EXCLUDE NO OTHERS`
    NoOthers {
        no_token: Node<(), ID>,
        others_token: Node<(), ID>,
    },
}