datafusion_common/
spans.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
18use std::cmp::{self, Ordering};
19use std::fmt;
20use std::hash::{Hash, Hasher};
21
22/// Represents a location, determined by a line and a column number, in the
23/// original SQL query.
24#[derive(Eq, PartialEq, Hash, Clone, Copy, Ord, PartialOrd)]
25pub struct Location {
26    /// Line number, starting from 1.
27    ///
28    /// Note: Line 0 is used for empty spans
29    pub line: u64,
30    /// Line column, starting from 1.
31    ///
32    /// Note: Column 0 is used for empty spans
33    pub column: u64,
34}
35
36impl fmt::Debug for Location {
37    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
38        write!(f, "Location({},{})", self.line, self.column)
39    }
40}
41
42impl From<sqlparser::tokenizer::Location> for Location {
43    fn from(value: sqlparser::tokenizer::Location) -> Self {
44        Self {
45            line: value.line,
46            column: value.column,
47        }
48    }
49}
50
51/// Represents an interval of characters in the original SQL query.
52#[derive(Eq, PartialEq, Hash, Clone, PartialOrd, Ord, Copy)]
53pub struct Span {
54    pub start: Location,
55    pub end: Location,
56}
57
58impl fmt::Debug for Span {
59    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60        write!(f, "Span({:?}..{:?})", self.start, self.end)
61    }
62}
63
64impl Span {
65    /// Creates a new [`Span`] from a start and an end [`Location`].
66    pub fn new(start: Location, end: Location) -> Self {
67        Self { start, end }
68    }
69
70    /// Convert a [`Span`](sqlparser::tokenizer::Span) from the parser, into a
71    /// DataFusion [`Span`]. If the input span is empty (line 0 column 0, to
72    /// line 0 column 0), then [`None`] is returned.
73    pub fn try_from_sqlparser_span(span: sqlparser::tokenizer::Span) -> Option<Span> {
74        if span == sqlparser::tokenizer::Span::empty() {
75            None
76        } else {
77            Some(Span {
78                start: span.start.into(),
79                end: span.end.into(),
80            })
81        }
82    }
83
84    /// Returns the smallest Span that contains both `self` and `other`
85    ///
86    /// # Examples
87    /// ```
88    /// # use sqlparser::tokenizer::{Span, Location};
89    /// // line 1, column1 -> line 2, column 5
90    /// let span1 = Span::new(Location::new(1, 1), Location::new(2, 5));
91    /// // line 2, column 3 -> line 3, column 7
92    /// let span2 = Span::new(Location::new(2, 3), Location::new(3, 7));
93    /// // Union of the two is the min/max of the two spans
94    /// // line 1, column 1 -> line 3, column 7
95    /// let union = span1.union(&span2);
96    /// assert_eq!(union, Span::new(Location::new(1, 1), Location::new(3, 7)));
97    /// ```
98    pub fn union(&self, other: &Span) -> Span {
99        Span {
100            start: cmp::min(self.start, other.start),
101            end: cmp::max(self.end, other.end),
102        }
103    }
104
105    /// Same as [Span::union] for `Option<Span>`.
106    ///
107    /// If `other` is `None`, `self` is returned.
108    pub fn union_opt(&self, other: &Option<Span>) -> Span {
109        match other {
110            Some(other) => self.union(other),
111            None => *self,
112        }
113    }
114
115    /// Return the [Span::union] of all spans in the iterator.
116    ///
117    /// If the iterator is empty, [`None`] is returned.
118    ///
119    /// # Example
120    /// ```
121    /// # use sqlparser::tokenizer::{Span, Location};
122    /// let spans = vec![
123    ///     Span::new(Location::new(1, 1), Location::new(2, 5)),
124    ///     Span::new(Location::new(2, 3), Location::new(3, 7)),
125    ///     Span::new(Location::new(3, 1), Location::new(4, 2)),
126    /// ];
127    /// // line 1, column 1 -> line 4, column 2
128    /// assert_eq!(
129    ///   Span::union_iter(spans),
130    ///   Span::new(Location::new(1, 1), Location::new(4, 2))
131    /// );
132    pub fn union_iter<I: IntoIterator<Item = Span>>(iter: I) -> Option<Span> {
133        iter.into_iter().reduce(|acc, item| acc.union(&item))
134    }
135}
136
137/// A collection of [`Span`], meant to be used as a field of entities whose
138/// location in the original SQL query is desired to be tracked. Sometimes an
139/// entity can have multiple spans. e.g. if you want to track the position of
140/// the column a that comes from SELECT 1 AS a UNION ALL SELECT 2 AS a you'll
141/// need two spans.
142#[derive(Debug, Clone)]
143// Store the first [`Span`] on the stack because that is by far the most common
144// case. More will spill onto the heap.
145pub struct Spans(pub Vec<Span>);
146
147impl Spans {
148    /// Creates a new empty [`Spans`] with no [`Span`].
149    pub fn new() -> Self {
150        Spans(Vec::new())
151    }
152
153    /// Returns the first [`Span`], if any. This is useful when you know that
154    /// there's gonna be only one [`Span`] at most.
155    pub fn first(&self) -> Option<Span> {
156        self.0.first().copied()
157    }
158
159    /// Returns a slice of the [`Span`]s.
160    pub fn get_spans(&self) -> &[Span] {
161        &self.0
162    }
163
164    /// Adds a [`Span`] to the collection.
165    pub fn add_span(&mut self, span: Span) {
166        self.0.push(span);
167    }
168
169    /// Iterates over the [`Span`]s.
170    pub fn iter(&self) -> impl Iterator<Item = &Span> {
171        self.0.iter()
172    }
173}
174
175impl Default for Spans {
176    fn default() -> Self {
177        Self::new()
178    }
179}
180
181// Since [`Spans`] will be used as a field in other structs, we don't want it to
182// interfere with the equality and ordering of the entities themselves, since
183// this is just diagnostics information for the end user.
184impl PartialEq for Spans {
185    fn eq(&self, _other: &Self) -> bool {
186        true
187    }
188}
189
190// Since [`Spans`] will be used as a field in other structs, we don't want it to
191// interfere with the equality and ordering of the entities themselves, since
192// this is just diagnostics information for the end user.
193impl Eq for Spans {}
194
195// Since [`Spans`] will be used as a field in other structs, we don't want it to
196// interfere with the equality and ordering of the entities themselves, since
197// this is just diagnostics information for the end user.
198impl PartialOrd for Spans {
199    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
200        Some(self.cmp(other))
201    }
202}
203
204// Since [`Spans`] will be used as a field in other structs, we don't want it to
205// interfere with the equality and ordering of the entities themselves, since
206// this is just diagnostics information for the end user.
207impl Ord for Spans {
208    fn cmp(&self, _other: &Self) -> Ordering {
209        Ordering::Equal
210    }
211}
212
213// Since [`Spans`] will be used as a field in other structs, we don't want it to
214// interfere with the equality and ordering of the entities themselves, since
215// this is just diagnostics information for the end user.
216impl Hash for Spans {
217    fn hash<H: Hasher>(&self, _state: &mut H) {}
218}