## Coverage Report

#### Created: 2025-11-22 06:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)

    /Users/andrewlamb/Software/datafusion/datafusion/expr/src/logical_plan/statement.rs

    Line
    Count
    Source
    1
    // Licensed to the Apache Software Foundation (ASF) under one
    2
    // or more contributor license agreements.  See the NOTICE file
    3
    // distributed with this work for additional information
    4
    // regarding copyright ownership.  The ASF licenses this file
    5
    // to you under the Apache License, Version 2.0 (the
    6
    // "License"); you may not use this file except in compliance
    7
    // with the License.  You may obtain a copy of the License at
    8
    //
    9
    //   http://www.apache.org/licenses/LICENSE-2.0
    10
    //
    11
    // Unless required by applicable law or agreed to in writing,
    12
    // software distributed under the License is distributed on an
    13
    // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14
    // KIND, either express or implied.  See the License for the
    15
    // specific language governing permissions and limitations
    16
    // under the License.
    17
    18
    use arrow::datatypes::FieldRef;
    19
    use datafusion_common::metadata::format_type_and_metadata;
    20
    use datafusion_common::{DFSchema, DFSchemaRef};
    21
    use itertools::Itertools as _;
    22
    use std::fmt::{self, Display};
    23
    use std::sync::{Arc, LazyLock};
    24
    25
    use crate::{expr_vec_fmt, Expr, LogicalPlan};
    26
    27
    /// Various types of Statements.
    28
    ///
    29
    /// # Transactions:
    30
    ///
    31
    /// While DataFusion does not offer support transactions, it provides
    32
    /// [`LogicalPlan`] support to assist building database systems
    33
    /// using DataFusion
    34
    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
    35
    pub enum Statement {
    36
        // Begin a transaction
    37
        TransactionStart(TransactionStart),
    38
        // Commit or rollback a transaction
    39
        TransactionEnd(TransactionEnd),
    40
        /// Set a Variable
    41
        SetVariable(SetVariable),
    42
        /// Reset a Variable
    43
        ResetVariable(ResetVariable),
    44
        /// Prepare a statement and find any bind parameters
    45
        /// (e.g. `?`). This is used to implement SQL-prepared statements.
    46
        Prepare(Prepare),
    47
        /// Execute a prepared statement. This is used to implement SQL 'EXECUTE'.
    48
        Execute(Execute),
    49
        /// Deallocate a prepared statement.
    50
        /// This is used to implement SQL 'DEALLOCATE'.
    51
        Deallocate(Deallocate),
    52
    }
    53
    54
    impl Statement {
    55
        /// Get a reference to the logical plan's schema
    56
    0
        pub fn schema(&self) -> &DFSchemaRef {
    57
            // Statements have an unchanging empty schema.
    58
            static STATEMENT_EMPTY_SCHEMA: LazyLock<DFSchemaRef> =
    59
    0
                LazyLock::new(|| Arc::new(DFSchema::empty()));
    60
    61
    0
            &STATEMENT_EMPTY_SCHEMA
    62
    0
        }
    63
    64
        /// Return a descriptive string describing the type of this
    65
        /// [`Statement`]
    66
    0
        pub fn name(&self) -> &str {
    67
    0
            match self {
    68
    0
                Statement::TransactionStart(_) => "TransactionStart",
    69
    0
                Statement::TransactionEnd(_) => "TransactionEnd",
    70
    0
                Statement::SetVariable(_) => "SetVariable",
    71
    0
                Statement::ResetVariable(_) => "ResetVariable",
    72
    0
                Statement::Prepare(_) => "Prepare",
    73
    0
                Statement::Execute(_) => "Execute",
    74
    0
                Statement::Deallocate(_) => "Deallocate",
    75
            }
    76
    0
        }
    77
    78
        /// Returns input LogicalPlans in the current `Statement`.
    79
    0
        pub(super) fn inputs(&self) -> Vec<&LogicalPlan> {
    80
    0
            match self {
    81
    0
                Statement::Prepare(Prepare { input, .. }) => vec![input.as_ref()],
    82
    0
                _ => vec![],
    83
            }
    84
    0
        }
    85
    86
        /// Return a `format`able structure with the a human readable
    87
        /// description of this LogicalPlan node per node, not including
    88
        /// children.
    89
        ///
    90
        /// See [crate::LogicalPlan::display] for an example
    91
    0
        pub fn display(&self) -> impl Display + '_ {
    92
            struct Wrapper<'a>(&'a Statement);
    93
            impl Display for Wrapper<'_> {
    94
    0
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    95
    0
                    match self.0 {
    96
                        Statement::TransactionStart(TransactionStart {
    97
    0
                            access_mode,
    98
    0
                            isolation_level,
    99
                            ..
    100
                        }) => {
    101
    0
                            write!(f, "TransactionStart: {access_mode:?} {isolation_level:?}")
    102
                        }
    103
                        Statement::TransactionEnd(TransactionEnd {
    104
    0
                            conclusion,
    105
    0
                            chain,
    106
                            ..
    107
                        }) => {
    108
    0
                            write!(f, "TransactionEnd: {conclusion:?} chain:={chain}")
    109
                        }
    110
                        Statement::SetVariable(SetVariable {
    111
    0
                            variable, value, ..
    112
                        }) => {
    113
    0
                            write!(f, "SetVariable: set {variable:?} to {value:?}")
    114
                        }
    115
    0
                        Statement::ResetVariable(ResetVariable { variable }) => {
    116
    0
                            write!(f, "ResetVariable: reset {variable:?}")
    117
                        }
    118
    0
                        Statement::Prepare(Prepare { name, fields, .. }) => {
    119
    0
                            write!(
    120
    0
                                f,
    121
    0
                                "Prepare: {name:?} [{}]",
    122
    0
                                fields
    123
    0
                                    .iter()
    124
    0
                                    .map(|f| format_type_and_metadata(
    125
    0
                                        f.data_type(),
    126
    0
                                        Some(f.metadata())
    127
                                    ))
    128
    0
                                    .join(", ")
    129
                            )
    130
                        }
    131
                        Statement::Execute(Execute {
    132
    0
                            name, parameters, ..
    133
                        }) => {
    134
    0
                            write!(
    135
    0
                                f,
    136
    0
                                "Execute: {} params=[{}]",
    137
                                name,
    138
    0
                                expr_vec_fmt!(parameters)
    139
                            )
    140
                        }
    141
    0
                        Statement::Deallocate(Deallocate { name }) => {
    142
    0
                            write!(f, "Deallocate: {name}")
    143
                        }
    144
                    }
    145
    0
                }
    146
            }
    147
    0
            Wrapper(self)
    148
    0
        }
    149
    }
    150
    151
    /// Indicates if a transaction was committed or aborted
    152
    #[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
    153
    pub enum TransactionConclusion {
    154
        Commit,
    155
        Rollback,
    156
    }
    157
    158
    /// Indicates if this transaction is allowed to write
    159
    #[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
    160
    pub enum TransactionAccessMode {
    161
        ReadOnly,
    162
        ReadWrite,
    163
    }
    164
    165
    /// Indicates ANSI transaction isolation level
    166
    #[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
    167
    pub enum TransactionIsolationLevel {
    168
        ReadUncommitted,
    169
        ReadCommitted,
    170
        RepeatableRead,
    171
        Serializable,
    172
        Snapshot,
    173
    }
    174
    175
    /// Indicator that the following statements should be committed or rolled back atomically
    176
    #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
    177
    pub struct TransactionStart {
    178
        /// indicates if transaction is allowed to write
    179
        pub access_mode: TransactionAccessMode,
    180
        // indicates ANSI isolation level
    181
        pub isolation_level: TransactionIsolationLevel,
    182
    }
    183
    184
    /// Indicator that any current transaction should be terminated
    185
    #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
    186
    pub struct TransactionEnd {
    187
        /// whether the transaction committed or aborted
    188
        pub conclusion: TransactionConclusion,
    189
        /// if specified a new transaction is immediately started with same characteristics
    190
        pub chain: bool,
    191
    }
    192
    193
    /// Set a Variable's value -- value in
    194
    /// [`ConfigOptions`](datafusion_common::config::ConfigOptions)
    195
    #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
    196
    pub struct SetVariable {
    197
        /// The variable name
    198
        pub variable: String,
    199
        /// The value to set
    200
        pub value: String,
    201
    }
    202
    203
    /// Reset a configuration variable to its default
    204
    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
    205
    pub struct ResetVariable {
    206
        /// The variable name
    207
        pub variable: String,
    208
    }
    209
    /// Prepare a statement but do not execute it. Prepare statements can have 0 or more
    210
    /// `Expr::Placeholder` expressions that are filled in during execution
    211
    #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
    212
    pub struct Prepare {
    213
        /// The name of the statement
    214
        pub name: String,
    215
        /// Data types of the parameters ([`Expr::Placeholder`])
    216
        pub fields: Vec<FieldRef>,
    217
        /// The logical plan of the statements
    218
        pub input: Arc<LogicalPlan>,
    219
    }
    220
    221
    /// Execute a prepared statement.
    222
    #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
    223
    pub struct Execute {
    224
        /// The name of the prepared statement to execute
    225
        pub name: String,
    226
        /// The execute parameters
    227
        pub parameters: Vec<Expr>,
    228
    }
    229
    230
    /// Deallocate a prepared statement.
    231
    #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Hash)]
    232
    pub struct Deallocate {
    233
        /// The name of the prepared statement to deallocate
    234
        pub name: String,
    235
    }