diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index eb8830bb1..11bc37613 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -577,7 +577,7 @@ pub enum Expr {
///
/// Syntax:
/// ```sql
- /// MARCH (
, , ...) AGAINST ( [])
+ /// MATCH (, , ...) AGAINST ( [])
///
/// = CompoundIdentifier
/// = String literal
@@ -1312,6 +1312,7 @@ pub enum Statement {
query: Box,
with_options: Vec,
cluster_by: Vec,
+ late_binding: bool,
},
/// CREATE TABLE
CreateTable {
@@ -2241,6 +2242,7 @@ impl fmt::Display for Statement {
materialized,
with_options,
cluster_by,
+ late_binding,
} => {
write!(
f,
@@ -2258,7 +2260,11 @@ impl fmt::Display for Statement {
if !cluster_by.is_empty() {
write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
}
- write!(f, " AS {query}")
+ write!(f, " AS {query}")?;
+ if *late_binding {
+ write!(f, " WITH NO SCHEMA BINDING")?;
+ }
+ Ok(())
}
Statement::CreateTable {
name,
diff --git a/src/keywords.rs b/src/keywords.rs
index ad0526ccd..16aa36a72 100644
--- a/src/keywords.rs
+++ b/src/keywords.rs
@@ -109,6 +109,7 @@ define_keywords!(
BIGINT,
BIGNUMERIC,
BINARY,
+ BINDING,
BLOB,
BLOOMFILTER,
BOOL,
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index ba8f5784f..fefe185a0 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -2957,6 +2957,15 @@ impl<'a> Parser<'a> {
self.expect_keyword(Keyword::AS)?;
let query = Box::new(self.parse_query()?);
// Optional `WITH [ CASCADED | LOCAL ] CHECK OPTION` is widely supported here.
+
+ let late_binding = dialect_of!(self is RedshiftSqlDialect)
+ && self.parse_keywords(&[
+ Keyword::WITH,
+ Keyword::NO,
+ Keyword::SCHEMA,
+ Keyword::BINDING,
+ ]);
+
Ok(Statement::CreateView {
name,
columns,
@@ -2965,6 +2974,7 @@ impl<'a> Parser<'a> {
or_replace,
with_options,
cluster_by,
+ late_binding,
})
}
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 6f780de9e..a7e778e59 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -5310,6 +5310,7 @@ fn parse_create_view() {
materialized,
with_options,
cluster_by,
+ late_binding,
} => {
assert_eq!("myschema.myview", name.to_string());
assert_eq!(Vec::::new(), columns);
@@ -5318,6 +5319,7 @@ fn parse_create_view() {
assert!(!or_replace);
assert_eq!(with_options, vec![]);
assert_eq!(cluster_by, vec![]);
+ assert_eq!(late_binding, false);
}
_ => unreachable!(),
}
@@ -5358,6 +5360,7 @@ fn parse_create_view_with_columns() {
query,
materialized,
cluster_by,
+ late_binding,
} => {
assert_eq!("v", name.to_string());
assert_eq!(columns, vec![Ident::new("has"), Ident::new("cols")]);
@@ -5366,6 +5369,7 @@ fn parse_create_view_with_columns() {
assert!(!materialized);
assert!(!or_replace);
assert_eq!(cluster_by, vec![]);
+ assert_eq!(late_binding, false);
}
_ => unreachable!(),
}
@@ -5383,6 +5387,7 @@ fn parse_create_or_replace_view() {
query,
materialized,
cluster_by,
+ late_binding,
} => {
assert_eq!("v", name.to_string());
assert_eq!(columns, vec![]);
@@ -5391,6 +5396,7 @@ fn parse_create_or_replace_view() {
assert!(!materialized);
assert!(or_replace);
assert_eq!(cluster_by, vec![]);
+ assert_eq!(late_binding, false);
}
_ => unreachable!(),
}
@@ -5412,6 +5418,7 @@ fn parse_create_or_replace_materialized_view() {
query,
materialized,
cluster_by,
+ late_binding,
} => {
assert_eq!("v", name.to_string());
assert_eq!(columns, vec![]);
@@ -5420,6 +5427,7 @@ fn parse_create_or_replace_materialized_view() {
assert!(materialized);
assert!(or_replace);
assert_eq!(cluster_by, vec![]);
+ assert_eq!(late_binding, false);
}
_ => unreachable!(),
}
@@ -5437,6 +5445,7 @@ fn parse_create_materialized_view() {
materialized,
with_options,
cluster_by,
+ late_binding,
} => {
assert_eq!("myschema.myview", name.to_string());
assert_eq!(Vec::::new(), columns);
@@ -5445,6 +5454,7 @@ fn parse_create_materialized_view() {
assert_eq!(with_options, vec![]);
assert!(!or_replace);
assert_eq!(cluster_by, vec![]);
+ assert_eq!(late_binding, false);
}
_ => unreachable!(),
}
@@ -5462,6 +5472,7 @@ fn parse_create_materialized_view_with_cluster_by() {
materialized,
with_options,
cluster_by,
+ late_binding,
} => {
assert_eq!("myschema.myview", name.to_string());
assert_eq!(Vec::::new(), columns);
@@ -5470,6 +5481,7 @@ fn parse_create_materialized_view_with_cluster_by() {
assert_eq!(with_options, vec![]);
assert!(!or_replace);
assert_eq!(cluster_by, vec![Ident::new("foo")]);
+ assert_eq!(late_binding, false);
}
_ => unreachable!(),
}
diff --git a/tests/sqlparser_redshift.rs b/tests/sqlparser_redshift.rs
index f17ca5841..5ac1e262f 100644
--- a/tests/sqlparser_redshift.rs
+++ b/tests/sqlparser_redshift.rs
@@ -281,3 +281,9 @@ fn test_sharp() {
select.projection[0]
);
}
+
+#[test]
+fn test_create_view_late_binding() {
+ redshift()
+ .verified_stmt("CREATE VIEW myevent AS SELECT eventname FROM event WITH NO SCHEMA BINDING");
+}