Skip to content

Commit 9c62ffc

Browse files
committed
Add support for PostgreSQL/Redshift geometric operators
1 parent a5bbb5e commit 9c62ffc

11 files changed

+807
-26
lines changed

src/ast/data_type.rs

+35
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,10 @@ pub enum DataType {
386386
///
387387
/// [bigquery]: https://cloud.google.com/bigquery/docs/user-defined-functions#templated-sql-udf-parameters
388388
AnyType,
389+
/// geometric type
390+
///
391+
/// [Postgres]: https://www.postgresql.org/docs/9.5/functions-geometry.html
392+
GeometricType(GeometricTypeKind),
389393
}
390394

391395
impl fmt::Display for DataType {
@@ -639,6 +643,7 @@ impl fmt::Display for DataType {
639643
DataType::Trigger => write!(f, "TRIGGER"),
640644
DataType::AnyType => write!(f, "ANY TYPE"),
641645
DataType::Table(fields) => write!(f, "TABLE({})", display_comma_separated(fields)),
646+
DataType::GeometricType(kind) => write!(f, "{}", kind),
642647
}
643648
}
644649
}
@@ -915,3 +920,33 @@ pub enum ArrayElemTypeDef {
915920
/// `Array(Int64)`
916921
Parenthesis(Box<DataType>),
917922
}
923+
924+
/// Represents different types of geometric shapes which are commonly used in
925+
/// PostgreSQL/Redshift for spatial operations and geometry-related computations.
926+
///
927+
/// [Postgres]: https://www.postgresql.org/docs/9.5/functions-geometry.html
928+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
929+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
930+
pub enum GeometricTypeKind {
931+
Point,
932+
Line,
933+
LineSegment,
934+
GeometricBox,
935+
GeometricPath,
936+
Polygon,
937+
Circle,
938+
}
939+
940+
impl fmt::Display for GeometricTypeKind {
941+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
942+
match self {
943+
GeometricTypeKind::Point => write!(f, "point"),
944+
GeometricTypeKind::Line => write!(f, "line"),
945+
GeometricTypeKind::LineSegment => write!(f, "lseg"),
946+
GeometricTypeKind::GeometricBox => write!(f, "box"),
947+
GeometricTypeKind::GeometricPath => write!(f, "path"),
948+
GeometricTypeKind::Polygon => write!(f, "polygon"),
949+
GeometricTypeKind::Circle => write!(f, "circle"),
950+
}
951+
}
952+
}

src/ast/mod.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ use crate::ast::helpers::stmt_data_loading::{
9393
#[cfg(feature = "visitor")]
9494
pub use visitor::*;
9595

96+
pub use self::data_type::GeometricTypeKind;
97+
9698
mod data_type;
9799
mod dcl;
98100
mod ddl;
@@ -1533,7 +1535,15 @@ impl fmt::Display for Expr {
15331535
Expr::UnaryOp { op, expr } => {
15341536
if op == &UnaryOperator::PGPostfixFactorial {
15351537
write!(f, "{expr}{op}")
1536-
} else if op == &UnaryOperator::Not {
1538+
} else if matches!(
1539+
op,
1540+
UnaryOperator::Not
1541+
| UnaryOperator::Hash
1542+
| UnaryOperator::AtDashAt
1543+
| UnaryOperator::DoubleAt
1544+
| UnaryOperator::QuestionDash
1545+
| UnaryOperator::QuestionPipe
1546+
) {
15371547
write!(f, "{op} {expr}")
15381548
} else {
15391549
write!(f, "{op}{expr}")

src/ast/operator.rs

+84
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,21 @@ pub enum UnaryOperator {
5353
PGAbs,
5454
/// Unary logical not operator: e.g. `! false` (Hive-specific)
5555
BangNot,
56+
/// `#` Number of points in path or polygon (PostgreSQL/Redshift geometric operator)
57+
/// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
58+
Hash,
59+
/// `@-@` Length or circumference (PostgreSQL/Redshift geometric operator)
60+
/// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
61+
AtDashAt,
62+
/// `@@` Center (PostgreSQL/Redshift geometric operator)
63+
/// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
64+
DoubleAt,
65+
/// `?-` Is horizontal? (PostgreSQL/Redshift geometric operator)
66+
/// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
67+
QuestionDash,
68+
/// `?|` Is vertical? (PostgreSQL/Redshift geometric operator)
69+
/// see <https://www.postgresql.org/docs/9.5/functions-geometry.html>
70+
QuestionPipe,
5671
}
5772

5873
impl fmt::Display for UnaryOperator {
@@ -68,6 +83,11 @@ impl fmt::Display for UnaryOperator {
6883
UnaryOperator::PGPrefixFactorial => "!!",
6984
UnaryOperator::PGAbs => "@",
7085
UnaryOperator::BangNot => "!",
86+
UnaryOperator::Hash => "#",
87+
UnaryOperator::AtDashAt => "@-@",
88+
UnaryOperator::DoubleAt => "@@",
89+
UnaryOperator::QuestionDash => "?-",
90+
UnaryOperator::QuestionPipe => "?|",
7191
})
7292
}
7393
}
@@ -253,6 +273,54 @@ pub enum BinaryOperator {
253273
/// Specifies a test for an overlap between two datetime periods:
254274
/// <https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#overlaps-predicate>
255275
Overlaps,
276+
/// `##` Point of closest proximity (PostgreSQL/Redshift geometric operator)
277+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
278+
DoubleHash,
279+
/// `<->` Distance between (PostgreSQL/Redshift geometric operator)
280+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
281+
LtDashGt,
282+
/// `&<` Overlaps to left? (PostgreSQL/Redshift geometric operator)
283+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
284+
AndLt,
285+
/// `&>` Overlaps to right? (PostgreSQL/Redshift geometric operator)
286+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
287+
AndGt,
288+
/// `<<|` Is strictly below? (PostgreSQL/Redshift geometric operator)
289+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
290+
LtLtPipe,
291+
/// `|>>` Is strictly above? (PostgreSQL/Redshift geometric operator)
292+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
293+
PipeGtGt,
294+
/// `&<|` Does not extend above? (PostgreSQL/Redshift geometric operator)
295+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
296+
AndLtPipe,
297+
/// `|&>` Does not extend below? (PostgreSQL/Redshift geometric operator)
298+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
299+
PipeAndGt,
300+
/// `<^` Is below? (PostgreSQL/Redshift geometric operator)
301+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
302+
LtCaret,
303+
/// `>^` Is above? (PostgreSQL/Redshift geometric operator)
304+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
305+
GtCaret,
306+
/// `?#` Intersects? (PostgreSQL/Redshift geometric operator)
307+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
308+
QuestionHash,
309+
/// `?-` Is horizontal? (PostgreSQL/Redshift geometric operator)
310+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
311+
QuestionDash,
312+
/// `?-|` Is perpendicular? (PostgreSQL/Redshift geometric operator)
313+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
314+
QuestionDashPipe,
315+
/// `?||` Are Parallel? (PostgreSQL/Redshift geometric operator)
316+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
317+
QuestionDoublePipe,
318+
/// `@` Contained or on? (PostgreSQL/Redshift geometric operator)
319+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
320+
At,
321+
/// `~=` Same as? (PostgreSQL/Redshift geometric operator)
322+
/// See <https://www.postgresql.org/docs/9.5/functions-geometry.html>
323+
TildeEq,
256324
}
257325

258326
impl fmt::Display for BinaryOperator {
@@ -310,6 +378,22 @@ impl fmt::Display for BinaryOperator {
310378
write!(f, "OPERATOR({})", display_separated(idents, "."))
311379
}
312380
BinaryOperator::Overlaps => f.write_str("OVERLAPS"),
381+
BinaryOperator::DoubleHash => f.write_str("##"),
382+
BinaryOperator::LtDashGt => f.write_str("<->"),
383+
BinaryOperator::AndLt => f.write_str("&<"),
384+
BinaryOperator::AndGt => f.write_str("&>"),
385+
BinaryOperator::LtLtPipe => f.write_str("<<|"),
386+
BinaryOperator::PipeGtGt => f.write_str("|>>"),
387+
BinaryOperator::AndLtPipe => f.write_str("&<|"),
388+
BinaryOperator::PipeAndGt => f.write_str("|&>"),
389+
BinaryOperator::LtCaret => f.write_str("<^"),
390+
BinaryOperator::GtCaret => f.write_str(">^"),
391+
BinaryOperator::QuestionHash => f.write_str("?#"),
392+
BinaryOperator::QuestionDash => f.write_str("?-"),
393+
BinaryOperator::QuestionDashPipe => f.write_str("?-|"),
394+
BinaryOperator::QuestionDoublePipe => f.write_str("?||"),
395+
BinaryOperator::At => f.write_str("@"),
396+
BinaryOperator::TildeEq => f.write_str("~="),
313397
}
314398
}
315399
}

src/dialect/mod.rs

+29-7
Original file line numberDiff line numberDiff line change
@@ -591,18 +591,34 @@ pub trait Dialect: Debug + Any {
591591
| Token::ExclamationMarkDoubleTilde
592592
| Token::ExclamationMarkDoubleTildeAsterisk
593593
| Token::Spaceship => Ok(p!(Eq)),
594-
Token::Pipe => Ok(p!(Pipe)),
594+
Token::Pipe
595+
| Token::QuestionMarkDash
596+
| Token::DoubleSharp
597+
| Token::Overlap
598+
| Token::AmpersandLeftAngleBracket
599+
| Token::AmpersandRightAngleBracket
600+
| Token::QuestionMarkDashVerticalBar
601+
| Token::AmpersandLeftAngleBracketVerticalBar
602+
| Token::VerticalBarAmpersandRightAngleBracket
603+
| Token::TwoWayArrow
604+
| Token::LeftAngleBracketCaret
605+
| Token::RightAngleBracketCaret
606+
| Token::QuestionMarkSharp
607+
| Token::QuestionMarkDoubleVerticalBar
608+
| Token::QuestionPipe
609+
| Token::TildeEqual
610+
| Token::AtSign
611+
| Token::ShiftLeftVerticalBar
612+
| Token::VerticalBarShiftRight => Ok(p!(Pipe)),
595613
Token::Caret | Token::Sharp | Token::ShiftRight | Token::ShiftLeft => Ok(p!(Caret)),
596614
Token::Ampersand => Ok(p!(Ampersand)),
597615
Token::Plus | Token::Minus => Ok(p!(PlusMinus)),
598616
Token::Mul | Token::Div | Token::DuckIntDiv | Token::Mod | Token::StringConcat => {
599617
Ok(p!(MulDivModOp))
600618
}
601-
Token::DoubleColon
602-
| Token::ExclamationMark
603-
| Token::LBracket
604-
| Token::Overlap
605-
| Token::CaretAt => Ok(p!(DoubleColon)),
619+
Token::DoubleColon | Token::ExclamationMark | Token::LBracket | Token::CaretAt => {
620+
Ok(p!(DoubleColon))
621+
}
606622
Token::Arrow
607623
| Token::LongArrow
608624
| Token::HashArrow
@@ -614,7 +630,6 @@ pub trait Dialect: Debug + Any {
614630
| Token::AtAt
615631
| Token::Question
616632
| Token::QuestionAnd
617-
| Token::QuestionPipe
618633
| Token::CustomBinaryOperator(_) => Ok(p!(PgOther)),
619634
_ => Ok(self.prec_unknown()),
620635
}
@@ -912,6 +927,13 @@ pub trait Dialect: Debug + Any {
912927
fn supports_array_typedef_size(&self) -> bool {
913928
false
914929
}
930+
/// Returns true if the dialect supports geometric types.
931+
///
932+
/// Postgres: <https://www.postgresql.org/docs/9.5/functions-geometry.html>
933+
/// e.g. @@ circle '((0,0),10)'
934+
fn supports_geometric_types(&self) -> bool {
935+
false
936+
}
915937
}
916938

917939
/// This represents the operators for which precedence must be defined

src/dialect/postgresql.rs

+4
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ impl Dialect for PostgreSqlDialect {
258258
fn supports_array_typedef_size(&self) -> bool {
259259
true
260260
}
261+
262+
fn supports_geometric_types(&self) -> bool {
263+
true
264+
}
261265
}
262266

263267
pub fn parse_create(parser: &mut Parser) -> Option<Result<Statement, ParserError>> {

src/dialect/redshift.rs

+4
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,8 @@ impl Dialect for RedshiftSqlDialect {
113113
fn supports_string_escape_constant(&self) -> bool {
114114
true
115115
}
116+
117+
fn supports_geometric_types(&self) -> bool {
118+
true
119+
}
116120
}

src/keywords.rs

+6
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ define_keywords!(
141141
BOOL,
142142
BOOLEAN,
143143
BOTH,
144+
BOX,
144145
BROWSE,
145146
BTREE,
146147
BUCKET,
@@ -175,6 +176,7 @@ define_keywords!(
175176
CHARSET,
176177
CHAR_LENGTH,
177178
CHECK,
179+
CIRCLE,
178180
CLEAR,
179181
CLOB,
180182
CLONE,
@@ -478,6 +480,7 @@ define_keywords!(
478480
LIKE,
479481
LIKE_REGEX,
480482
LIMIT,
483+
LINE,
481484
LINES,
482485
LIST,
483486
LISTEN,
@@ -499,6 +502,7 @@ define_keywords!(
499502
LOWER,
500503
LOW_PRIORITY,
501504
LS,
505+
LSEG,
502506
MACRO,
503507
MANAGE,
504508
MANAGED,
@@ -653,7 +657,9 @@ define_keywords!(
653657
PLACING,
654658
PLAN,
655659
PLANS,
660+
POINT,
656661
POLICY,
662+
POLYGON,
657663
POOL,
658664
PORTION,
659665
POSITION,

0 commit comments

Comments
 (0)