Skip to main content

sqlparser/ast/helpers/
key_value_options.rs

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//! Key-value options for SQL statements.
19//! See [this page](https://docs.snowflake.com/en/sql-reference/commands-data-loading) for more details.
20
21#[cfg(not(feature = "std"))]
22use alloc::{boxed::Box, string::String, vec::Vec};
23use core::fmt;
24use core::fmt::Formatter;
25
26#[cfg(feature = "serde")]
27use serde::{Deserialize, Serialize};
28
29#[cfg(feature = "visitor")]
30use sqlparser_derive::{Visit, VisitMut};
31
32use crate::ast::{display_comma_separated, display_separated, Value};
33
34#[derive(#[automatically_derived]
impl ::core::fmt::Debug for KeyValueOptions {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "KeyValueOptions", "options", &self.options, "delimiter",
            &&self.delimiter)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for KeyValueOptions {
    #[inline]
    fn clone(&self) -> KeyValueOptions {
        KeyValueOptions {
            options: ::core::clone::Clone::clone(&self.options),
            delimiter: ::core::clone::Clone::clone(&self.delimiter),
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for KeyValueOptions {
    #[inline]
    fn eq(&self, other: &KeyValueOptions) -> bool {
        self.options == other.options && self.delimiter == other.delimiter
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for KeyValueOptions {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Vec<KeyValueOption>>;
        let _: ::core::cmp::AssertParamIsEq<KeyValueOptionsDelimiter>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for KeyValueOptions {
    #[inline]
    fn partial_cmp(&self, other: &KeyValueOptions)
        -> ::core::option::Option<::core::cmp::Ordering> {
        match ::core::cmp::PartialOrd::partial_cmp(&self.options,
                &other.options) {
            ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
                ::core::cmp::PartialOrd::partial_cmp(&self.delimiter,
                    &other.delimiter),
            cmp => cmp,
        }
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for KeyValueOptions {
    #[inline]
    fn cmp(&self, other: &KeyValueOptions) -> ::core::cmp::Ordering {
        match ::core::cmp::Ord::cmp(&self.options, &other.options) {
            ::core::cmp::Ordering::Equal =>
                ::core::cmp::Ord::cmp(&self.delimiter, &other.delimiter),
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for KeyValueOptions {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.options, state);
        ::core::hash::Hash::hash(&self.delimiter, state)
    }
}Hash)]
35#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
36#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for KeyValueOptions {
    fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
        -> ::std::ops::ControlFlow<V::Break> {
        ::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
            ::recursive::get_stack_allocation_size(),
            move || -> ::std::ops::ControlFlow<V::Break>
                {
                    {
                        sqlparser::ast::Visit::visit(&self.options, visitor)?;
                        sqlparser::ast::Visit::visit(&self.delimiter, visitor)?;
                        ::std::ops::ControlFlow::Continue(())
                    }
                })
    }
}Visit, impl sqlparser::ast::VisitMut for KeyValueOptions {
    fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
        -> ::std::ops::ControlFlow<V::Break> {
        ::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
            ::recursive::get_stack_allocation_size(),
            move || -> ::std::ops::ControlFlow<V::Break>
                {
                    {
                        sqlparser::ast::VisitMut::visit(&mut self.options,
                                visitor)?;
                        sqlparser::ast::VisitMut::visit(&mut self.delimiter,
                                visitor)?;
                        ::std::ops::ControlFlow::Continue(())
                    }
                })
    }
}VisitMut))]
37/// A collection of key-value options.
38pub struct KeyValueOptions {
39    /// The list of key-value options.
40    pub options: Vec<KeyValueOption>,
41    /// The delimiter used between options.
42    pub delimiter: KeyValueOptionsDelimiter,
43}
44
45#[derive(#[automatically_derived]
impl ::core::fmt::Debug for KeyValueOptionsDelimiter {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                KeyValueOptionsDelimiter::Space => "Space",
                KeyValueOptionsDelimiter::Comma => "Comma",
            })
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for KeyValueOptionsDelimiter {
    #[inline]
    fn clone(&self) -> KeyValueOptionsDelimiter {
        match self {
            KeyValueOptionsDelimiter::Space =>
                KeyValueOptionsDelimiter::Space,
            KeyValueOptionsDelimiter::Comma =>
                KeyValueOptionsDelimiter::Comma,
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for KeyValueOptionsDelimiter {
    #[inline]
    fn eq(&self, other: &KeyValueOptionsDelimiter) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for KeyValueOptionsDelimiter {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for KeyValueOptionsDelimiter {
    #[inline]
    fn partial_cmp(&self, other: &KeyValueOptionsDelimiter)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for KeyValueOptionsDelimiter {
    #[inline]
    fn cmp(&self, other: &KeyValueOptionsDelimiter) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for KeyValueOptionsDelimiter {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}Hash)]
46#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
47#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for KeyValueOptionsDelimiter {
    fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
        -> ::std::ops::ControlFlow<V::Break> {
        ::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
            ::recursive::get_stack_allocation_size(),
            move || -> ::std::ops::ControlFlow<V::Break>
                {
                    {
                        match self { Self::Space => {} Self::Comma => {} }
                        ::std::ops::ControlFlow::Continue(())
                    }
                })
    }
}Visit, impl sqlparser::ast::VisitMut for KeyValueOptionsDelimiter {
    fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
        -> ::std::ops::ControlFlow<V::Break> {
        ::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
            ::recursive::get_stack_allocation_size(),
            move || -> ::std::ops::ControlFlow<V::Break>
                {
                    {
                        match self { Self::Space => {} Self::Comma => {} }
                        ::std::ops::ControlFlow::Continue(())
                    }
                })
    }
}VisitMut))]
48/// The delimiter used between key-value options.
49pub enum KeyValueOptionsDelimiter {
50    /// Options are separated by spaces.
51    Space,
52    /// Options are separated by commas.
53    Comma,
54}
55
56#[derive(#[automatically_derived]
impl ::core::fmt::Debug for KeyValueOption {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f,
            "KeyValueOption", "option_name", &self.option_name,
            "option_value", &&self.option_value)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for KeyValueOption {
    #[inline]
    fn clone(&self) -> KeyValueOption {
        KeyValueOption {
            option_name: ::core::clone::Clone::clone(&self.option_name),
            option_value: ::core::clone::Clone::clone(&self.option_value),
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for KeyValueOption {
    #[inline]
    fn eq(&self, other: &KeyValueOption) -> bool {
        self.option_name == other.option_name &&
            self.option_value == other.option_value
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for KeyValueOption {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<String>;
        let _: ::core::cmp::AssertParamIsEq<KeyValueOptionKind>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for KeyValueOption {
    #[inline]
    fn partial_cmp(&self, other: &KeyValueOption)
        -> ::core::option::Option<::core::cmp::Ordering> {
        match ::core::cmp::PartialOrd::partial_cmp(&self.option_name,
                &other.option_name) {
            ::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
                ::core::cmp::PartialOrd::partial_cmp(&self.option_value,
                    &other.option_value),
            cmp => cmp,
        }
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for KeyValueOption {
    #[inline]
    fn cmp(&self, other: &KeyValueOption) -> ::core::cmp::Ordering {
        match ::core::cmp::Ord::cmp(&self.option_name, &other.option_name) {
            ::core::cmp::Ordering::Equal =>
                ::core::cmp::Ord::cmp(&self.option_value,
                    &other.option_value),
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for KeyValueOption {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        ::core::hash::Hash::hash(&self.option_name, state);
        ::core::hash::Hash::hash(&self.option_value, state)
    }
}Hash)]
57#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
58#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for KeyValueOption {
    fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
        -> ::std::ops::ControlFlow<V::Break> {
        ::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
            ::recursive::get_stack_allocation_size(),
            move || -> ::std::ops::ControlFlow<V::Break>
                {
                    {
                        sqlparser::ast::Visit::visit(&self.option_name, visitor)?;
                        sqlparser::ast::Visit::visit(&self.option_value, visitor)?;
                        ::std::ops::ControlFlow::Continue(())
                    }
                })
    }
}Visit, impl sqlparser::ast::VisitMut for KeyValueOption {
    fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
        -> ::std::ops::ControlFlow<V::Break> {
        ::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
            ::recursive::get_stack_allocation_size(),
            move || -> ::std::ops::ControlFlow<V::Break>
                {
                    {
                        sqlparser::ast::VisitMut::visit(&mut self.option_name,
                                visitor)?;
                        sqlparser::ast::VisitMut::visit(&mut self.option_value,
                                visitor)?;
                        ::std::ops::ControlFlow::Continue(())
                    }
                })
    }
}VisitMut))]
59/// A single key-value option.
60pub struct KeyValueOption {
61    /// The name of the option.
62    pub option_name: String,
63    /// The value of the option.
64    pub option_value: KeyValueOptionKind,
65}
66
67/// An option can have a single value, multiple values or a nested list of values.
68///
69/// A value can be numeric, boolean, etc. Enum-style values are represented
70/// as Value::Placeholder. For example: MFA_METHOD=SMS will be represented as
71/// `Value::Placeholder("SMS".to_string)`.
72#[derive(#[automatically_derived]
impl ::core::fmt::Debug for KeyValueOptionKind {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            KeyValueOptionKind::Single(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Single",
                    &__self_0),
            KeyValueOptionKind::Multi(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Multi",
                    &__self_0),
            KeyValueOptionKind::KeyValueOptions(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "KeyValueOptions", &__self_0),
        }
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for KeyValueOptionKind {
    #[inline]
    fn clone(&self) -> KeyValueOptionKind {
        match self {
            KeyValueOptionKind::Single(__self_0) =>
                KeyValueOptionKind::Single(::core::clone::Clone::clone(__self_0)),
            KeyValueOptionKind::Multi(__self_0) =>
                KeyValueOptionKind::Multi(::core::clone::Clone::clone(__self_0)),
            KeyValueOptionKind::KeyValueOptions(__self_0) =>
                KeyValueOptionKind::KeyValueOptions(::core::clone::Clone::clone(__self_0)),
        }
    }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for KeyValueOptionKind {
    #[inline]
    fn eq(&self, other: &KeyValueOptionKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (KeyValueOptionKind::Single(__self_0),
                    KeyValueOptionKind::Single(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (KeyValueOptionKind::Multi(__self_0),
                    KeyValueOptionKind::Multi(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (KeyValueOptionKind::KeyValueOptions(__self_0),
                    KeyValueOptionKind::KeyValueOptions(__arg1_0)) =>
                    __self_0 == __arg1_0,
                _ => unsafe { ::core::intrinsics::unreachable() }
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for KeyValueOptionKind {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<Value>;
        let _: ::core::cmp::AssertParamIsEq<Vec<Value>>;
        let _: ::core::cmp::AssertParamIsEq<Box<KeyValueOptions>>;
    }
}Eq, #[automatically_derived]
impl ::core::cmp::PartialOrd for KeyValueOptionKind {
    #[inline]
    fn partial_cmp(&self, other: &KeyValueOptionKind)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match (self, other) {
            (KeyValueOptionKind::Single(__self_0),
                KeyValueOptionKind::Single(__arg1_0)) =>
                ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            (KeyValueOptionKind::Multi(__self_0),
                KeyValueOptionKind::Multi(__arg1_0)) =>
                ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            (KeyValueOptionKind::KeyValueOptions(__self_0),
                KeyValueOptionKind::KeyValueOptions(__arg1_0)) =>
                ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
            _ =>
                ::core::cmp::PartialOrd::partial_cmp(&__self_discr,
                    &__arg1_discr),
        }
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for KeyValueOptionKind {
    #[inline]
    fn cmp(&self, other: &KeyValueOptionKind) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
            ::core::cmp::Ordering::Equal =>
                match (self, other) {
                    (KeyValueOptionKind::Single(__self_0),
                        KeyValueOptionKind::Single(__arg1_0)) =>
                        ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    (KeyValueOptionKind::Multi(__self_0),
                        KeyValueOptionKind::Multi(__arg1_0)) =>
                        ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    (KeyValueOptionKind::KeyValueOptions(__self_0),
                        KeyValueOptionKind::KeyValueOptions(__arg1_0)) =>
                        ::core::cmp::Ord::cmp(__self_0, __arg1_0),
                    _ => unsafe { ::core::intrinsics::unreachable() }
                },
            cmp => cmp,
        }
    }
}Ord, #[automatically_derived]
impl ::core::hash::Hash for KeyValueOptionKind {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state);
        match self {
            KeyValueOptionKind::Single(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            KeyValueOptionKind::Multi(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
            KeyValueOptionKind::KeyValueOptions(__self_0) =>
                ::core::hash::Hash::hash(__self_0, state),
        }
    }
}Hash)]
73#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
74#[cfg_attr(feature = "visitor", derive(impl sqlparser::ast::Visit for KeyValueOptionKind {
    fn visit<V: sqlparser::ast::Visitor>(&self, visitor: &mut V)
        -> ::std::ops::ControlFlow<V::Break> {
        ::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
            ::recursive::get_stack_allocation_size(),
            move || -> ::std::ops::ControlFlow<V::Break>
                {
                    {
                        match self {
                            Self::Single(_0) => {
                                sqlparser::ast::Visit::visit(_0, visitor)?;
                            }
                            Self::Multi(_0) => {
                                sqlparser::ast::Visit::visit(_0, visitor)?;
                            }
                            Self::KeyValueOptions(_0) => {
                                sqlparser::ast::Visit::visit(_0, visitor)?;
                            }
                        }
                        ::std::ops::ControlFlow::Continue(())
                    }
                })
    }
}Visit, impl sqlparser::ast::VisitMut for KeyValueOptionKind {
    fn visit<V: sqlparser::ast::VisitorMut>(&mut self, visitor: &mut V)
        -> ::std::ops::ControlFlow<V::Break> {
        ::recursive::__impl::stacker::maybe_grow(::recursive::get_minimum_stack_size(),
            ::recursive::get_stack_allocation_size(),
            move || -> ::std::ops::ControlFlow<V::Break>
                {
                    {
                        match self {
                            Self::Single(_0) => {
                                sqlparser::ast::VisitMut::visit(_0, visitor)?;
                            }
                            Self::Multi(_0) => {
                                sqlparser::ast::VisitMut::visit(_0, visitor)?;
                            }
                            Self::KeyValueOptions(_0) => {
                                sqlparser::ast::VisitMut::visit(_0, visitor)?;
                            }
                        }
                        ::std::ops::ControlFlow::Continue(())
                    }
                })
    }
}VisitMut))]
75/// The kind of value for a key-value option.
76pub enum KeyValueOptionKind {
77    /// A single value.
78    Single(Value),
79    /// Multiple values.
80    Multi(Vec<Value>),
81    /// A nested list of key-value options.
82    KeyValueOptions(Box<KeyValueOptions>),
83}
84
85impl fmt::Display for KeyValueOptions {
86    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
87        let sep = match self.delimiter {
88            KeyValueOptionsDelimiter::Space => " ",
89            KeyValueOptionsDelimiter::Comma => ", ",
90        };
91        f.write_fmt(format_args!("{0}", display_separated(&self.options, sep)))write!(f, "{}", display_separated(&self.options, sep))
92    }
93}
94
95impl fmt::Display for KeyValueOption {
96    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97        match &self.option_value {
98            KeyValueOptionKind::Single(value) => {
99                f.write_fmt(format_args!("{0}={1}", self.option_name, value))write!(f, "{}={value}", self.option_name)?;
100            }
101            KeyValueOptionKind::Multi(values) => {
102                f.write_fmt(format_args!("{0}=({1})", self.option_name,
        display_comma_separated(values)))write!(
103                    f,
104                    "{}=({})",
105                    self.option_name,
106                    display_comma_separated(values)
107                )?;
108            }
109            KeyValueOptionKind::KeyValueOptions(options) => {
110                f.write_fmt(format_args!("{0}=({1})", self.option_name, options))write!(f, "{}=({options})", self.option_name)?;
111            }
112        }
113        Ok(())
114    }
115}