pgmold-sqlparser 0.63.0

Fork of sqlparser with additional PostgreSQL features (PARTITION OF, SECURITY DEFINER/INVOKER, SET params, EXCLUDE, TEXT SEARCH, AGGREGATE, FOREIGN TABLE/FDW, PUBLICATION, SUBSCRIPTION, ALTER DOMAIN/TRIGGER/EXTENSION, CAST, CONVERSION, LANGUAGE, RULE, STATISTICS, ACCESS METHOD, EVENT TRIGGER, TRANSFORM, SECURITY LABEL, USER MAPPING, TABLESPACE, GRANT ON TYPE/DOMAIN, COMMENT ON TRIGGER/AGGREGATE/POLICY/CONSTRAINT/OPERATOR/RULE, ALTER TYPE OWNER/SCHEMA/ATTRIBUTE, ALTER DEFAULT PRIVILEGES)
Documentation
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! SQL Abstract Syntax Tree (AST) for triggers.
use super::*;

/// This specifies whether the trigger function should be fired once for every row affected by the trigger event, or just once per SQL statement.
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum TriggerObject {
    /// The trigger fires once for each row affected by the triggering event
    Row,
    /// The trigger fires once for the triggering SQL statement
    Statement,
}

impl fmt::Display for TriggerObject {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TriggerObject::Row => write!(f, "ROW"),
            TriggerObject::Statement => write!(f, "STATEMENT"),
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
/// This clause indicates whether the following relation name is for the before-image transition relation or the after-image transition relation
pub enum TriggerReferencingType {
    /// The transition relation containing the old rows affected by the triggering statement
    OldTable,
    /// The transition relation containing the new rows affected by the triggering statement
    NewTable,
}

impl fmt::Display for TriggerReferencingType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TriggerReferencingType::OldTable => write!(f, "OLD TABLE"),
            TriggerReferencingType::NewTable => write!(f, "NEW TABLE"),
        }
    }
}

/// This keyword immediately precedes the declaration of one or two relation names that provide access to the transition relations of the triggering statement
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct TriggerReferencing {
    /// The referencing type (`OLD TABLE` or `NEW TABLE`).
    pub refer_type: TriggerReferencingType,
    /// True if the `AS` keyword is present in the referencing clause.
    pub is_as: bool,
    /// The transition relation name provided by the referencing clause.
    pub transition_relation_name: ObjectName,
}

impl fmt::Display for TriggerReferencing {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{refer_type}{is_as} {relation_name}",
            refer_type = self.refer_type,
            is_as = if self.is_as { " AS" } else { "" },
            relation_name = self.transition_relation_name
        )
    }
}

/// Used to describe trigger events
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum TriggerEvent {
    /// Trigger on INSERT event
    Insert,
    /// Trigger on UPDATE event, with optional list of columns
    Update(Vec<Ident>),
    /// Trigger on DELETE event
    Delete,
    /// Trigger on TRUNCATE event
    Truncate,
}

impl fmt::Display for TriggerEvent {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TriggerEvent::Insert => write!(f, "INSERT"),
            TriggerEvent::Update(columns) => {
                write!(f, "UPDATE")?;
                if !columns.is_empty() {
                    write!(f, " OF")?;
                    write!(f, " {}", display_comma_separated(columns))?;
                }
                Ok(())
            }
            TriggerEvent::Delete => write!(f, "DELETE"),
            TriggerEvent::Truncate => write!(f, "TRUNCATE"),
        }
    }
}

/// Trigger period
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum TriggerPeriod {
    /// The trigger fires once for each row affected by the triggering event
    For,
    /// The trigger fires once for the triggering SQL statement
    After,
    /// The trigger fires before the triggering event
    Before,
    /// The trigger fires instead of the triggering event
    InsteadOf,
}

impl fmt::Display for TriggerPeriod {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TriggerPeriod::For => write!(f, "FOR"),
            TriggerPeriod::After => write!(f, "AFTER"),
            TriggerPeriod::Before => write!(f, "BEFORE"),
            TriggerPeriod::InsteadOf => write!(f, "INSTEAD OF"),
        }
    }
}

/// Types of trigger body execution body.
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum TriggerExecBodyType {
    /// Execute a function
    Function,
    /// Execute a procedure
    Procedure,
}

impl fmt::Display for TriggerExecBodyType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TriggerExecBodyType::Function => write!(f, "FUNCTION"),
            TriggerExecBodyType::Procedure => write!(f, "PROCEDURE"),
        }
    }
}
/// The EXECUTE clause of a CREATE TRIGGER statement.
///
/// Holds call-site information: the function/procedure name and optional
/// positional argument expressions (e.g. string literals passed to
/// `tsvector_update_trigger`).  This is deliberately distinct from
/// `FunctionDesc`, which carries CREATE-FUNCTION-style parameter
/// *declarations* (`argname argtype DEFAULT expr`).
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct TriggerExecBody {
    /// Whether the body is a `FUNCTION` or `PROCEDURE` invocation.
    pub exec_type: TriggerExecBodyType,
    /// The name of the function or procedure to invoke.
    pub func_name: ObjectName,
    /// Call-site arguments (expressions).  `None` means no parentheses were
    /// written; `Some(vec![])` means empty parentheses `()`.
    pub args: Option<Vec<Expr>>,
}

impl fmt::Display for TriggerExecBody {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.exec_type, self.func_name)?;
        if let Some(args) = &self.args {
            write!(f, "({})", display_comma_separated(args))?;
        }
        Ok(())
    }
}