mz_sql_parser/ast/
metadata.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License in the LICENSE file at the
6// root of this repository, or online at
7//
8//     http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use std::fmt::{self, Debug};
17use std::hash::Hash;
18
19use crate::ast::display::{self, AstDisplay, AstFormatter};
20use crate::ast::fold::{Fold, FoldNode};
21use crate::ast::{
22    Ident, Statement, UnresolvedDatabaseName, UnresolvedItemName, UnresolvedObjectName,
23    UnresolvedSchemaName, Version,
24};
25
26/// This represents the metadata that lives next to an AST, as we take it through
27/// various stages in the planning process.
28///
29/// Conceptually, when we first receive an AST from the parsing process, it only
30/// represents the syntax that the user input, and has no semantic information
31/// embedded in it. Later in this process, we want to be able to walk the tree
32/// and add additional information to it piecemeal, perhaps without going down
33/// the full planning pipeline. AstInfo represents various bits of information
34/// that get stored in the tree: for instance, at first, table names are only
35/// represented by the names the user input (in the `Raw` implementor of this
36/// trait), but later on, we replace them with both the name along with the ID
37/// that it gets resolved to.
38///
39/// Currently this process brings an `Ast<Raw>` to `Ast<Aug>`, and lives in
40/// sql/src/names.rs:resolve.
41pub trait AstInfo: Clone {
42    /// The type used for nested statements.
43    type NestedStatement: AstDisplay + Clone + Hash + Debug + Eq;
44    /// The type used for item references. Items are the subset of objects that are namespaced by a
45    /// database and schema.
46    type ItemName: AstDisplay + Clone + Hash + Debug + Eq + Ord;
47    /// The type used to specify a column.
48    ///
49    /// n.b. when implementing visitors, you likely want to build the visitor to
50    /// visit [`crate::ast::ColumnName`] instead of visiting this struct
51    /// directly. The visitor on this should usually just return an error.
52    type ColumnReference: AstDisplay + Clone + Hash + Debug + Eq + Ord;
53    /// The type used for schema names.
54    type SchemaName: AstDisplay + Clone + Hash + Debug + Eq + Ord;
55    /// The type used for database names.
56    type DatabaseName: AstDisplay + Clone + Hash + Debug + Eq + Ord;
57    /// The type used for cluster names.
58    type ClusterName: AstDisplay + Clone + Hash + Debug + Eq + Ord;
59    /// The type used for data types.
60    type DataType: AstDisplay + Clone + Hash + Debug + Eq + Ord;
61    /// The type stored next to CTEs for their assigned ID.
62    type CteId: Clone + Hash + Debug + Eq + Ord;
63    /// The type used for role references.
64    type RoleName: AstDisplay + Clone + Hash + Debug + Eq + Ord;
65    /// The type used for network policy references.
66    type NetworkPolicyName: AstDisplay + Clone + Hash + Debug + Eq + Ord;
67    /// They type used for any object names. Objects are the superset of all objects in Materialize.
68    type ObjectName: AstDisplay + Clone + Hash + Debug + Eq + Ord;
69}
70
71#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone, Default)]
72pub struct Raw;
73
74impl AstInfo for Raw {
75    type NestedStatement = Statement<Raw>;
76    type ItemName = RawItemName;
77    type ColumnReference = Ident;
78    type SchemaName = UnresolvedSchemaName;
79    type DatabaseName = UnresolvedDatabaseName;
80    type ClusterName = RawClusterName;
81    type DataType = RawDataType;
82    type CteId = ();
83    type RoleName = Ident;
84    type NetworkPolicyName = RawNetworkPolicyName;
85    type ObjectName = UnresolvedObjectName;
86}
87
88#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
89pub enum RawItemName {
90    Name(UnresolvedItemName),
91    Id(String, UnresolvedItemName, Option<Version>),
92}
93
94impl RawItemName {
95    pub fn name(&self) -> &UnresolvedItemName {
96        match self {
97            RawItemName::Name(name) => name,
98            RawItemName::Id(_, name, _) => name,
99        }
100    }
101
102    pub fn name_mut(&mut self) -> &mut UnresolvedItemName {
103        match self {
104            RawItemName::Name(name) => name,
105            RawItemName::Id(_, name, _) => name,
106        }
107    }
108}
109
110impl AstDisplay for RawItemName {
111    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
112        match self {
113            RawItemName::Name(o) => f.write_node(o),
114            RawItemName::Id(id, o, v) => {
115                f.write_str(format!("[{} AS ", id));
116                f.write_node(o);
117                if let Some(v) = v {
118                    f.write_str(" VERSION ");
119                    f.write_node(v);
120                }
121                f.write_str("]");
122            }
123        }
124    }
125}
126impl_display!(RawItemName);
127
128impl<T> FoldNode<Raw, T> for RawItemName
129where
130    T: AstInfo,
131{
132    type Folded = T::ItemName;
133
134    fn fold<F>(self, f: &mut F) -> Self::Folded
135    where
136        F: Fold<Raw, T>,
137    {
138        f.fold_item_name(self)
139    }
140}
141
142#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
143pub enum RawClusterName {
144    Unresolved(Ident),
145    Resolved(String),
146}
147
148impl AstDisplay for RawClusterName {
149    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
150        match self {
151            RawClusterName::Unresolved(id) => f.write_node(id),
152            RawClusterName::Resolved(id) => {
153                f.write_str(format!("[{}]", id));
154            }
155        }
156    }
157}
158impl_display!(RawClusterName);
159
160impl<T> FoldNode<Raw, T> for RawClusterName
161where
162    T: AstInfo,
163{
164    type Folded = T::ClusterName;
165
166    fn fold<F>(self, f: &mut F) -> Self::Folded
167    where
168        F: Fold<Raw, T>,
169    {
170        f.fold_cluster_name(self)
171    }
172}
173
174#[derive(Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
175pub enum RawNetworkPolicyName {
176    Unresolved(Ident),
177    Resolved(String),
178}
179
180impl AstDisplay for RawNetworkPolicyName {
181    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
182        match self {
183            RawNetworkPolicyName::Unresolved(id) => f.write_node(id),
184            RawNetworkPolicyName::Resolved(id) => {
185                f.write_str(format!("[{}]", id));
186            }
187        }
188    }
189}
190impl_display!(RawNetworkPolicyName);
191
192impl<T> FoldNode<Raw, T> for RawNetworkPolicyName
193where
194    T: AstInfo,
195{
196    type Folded = T::NetworkPolicyName;
197
198    fn fold<F>(self, f: &mut F) -> Self::Folded
199    where
200        F: Fold<Raw, T>,
201    {
202        f.fold_network_policy_name(self)
203    }
204}
205
206/// SQL data types
207#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
208pub enum RawDataType {
209    /// Array
210    Array(Box<RawDataType>),
211    /// List
212    List(Box<RawDataType>),
213    /// Map
214    Map {
215        key_type: Box<RawDataType>,
216        value_type: Box<RawDataType>,
217    },
218    /// Types who don't embed other types, e.g. INT
219    Other {
220        name: RawItemName,
221        /// Typ modifiers appended to the type name, e.g. `numeric(38,0)`.
222        typ_mod: Vec<i64>,
223    },
224}
225
226impl AstDisplay for RawDataType {
227    fn fmt<W: fmt::Write>(&self, f: &mut AstFormatter<W>) {
228        match self {
229            RawDataType::Array(ty) => {
230                f.write_node(&ty);
231                f.write_str("[]");
232            }
233            RawDataType::List(ty) => {
234                f.write_node(&ty);
235                f.write_str(" list");
236            }
237            RawDataType::Map {
238                key_type,
239                value_type,
240            } => {
241                f.write_str("map[");
242                f.write_node(&key_type);
243                f.write_str("=>");
244                f.write_node(&value_type);
245                f.write_str("]");
246            }
247            RawDataType::Other { name, typ_mod } => {
248                f.write_node(name);
249                if typ_mod.len() > 0 {
250                    f.write_str("(");
251                    f.write_node(&display::comma_separated(typ_mod));
252                    f.write_str(")");
253                }
254            }
255        }
256    }
257}
258impl_display!(RawDataType);
259
260impl<T> FoldNode<Raw, T> for RawDataType
261where
262    T: AstInfo,
263{
264    type Folded = T::DataType;
265
266    fn fold<F>(self, f: &mut F) -> Self::Folded
267    where
268        F: Fold<Raw, T>,
269    {
270        f.fold_data_type(self)
271    }
272}