This is an automated email from the ASF dual-hosted git repository. github-bot pushed a commit to branch gh-readonly-queue/main/pr-2141-3af9988c432e3dae1a2343d60e64394f3ad9fa42 in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
commit d80c0b9b6c8bcbfe880e60daa1957674f0fcaa09 Author: Yoav Cohen <[email protected]> AuthorDate: Fri Jan 9 10:20:21 2026 +0100 Redshift: Add support for optional JSON format in copy option (#2141) --- src/ast/mod.rs | 12 +++++++++--- src/parser/mod.rs | 10 +++++++++- tests/sqlparser_common.rs | 6 ++++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index c8d9c6be..114dee11 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -8296,8 +8296,8 @@ pub enum CopyLegacyOption { IamRole(IamRoleKind), /// IGNOREHEADER \[ AS \] number_rows IgnoreHeader(u64), - /// JSON - Json, + /// JSON \[ AS \] 'json_option' + Json(Option<String>), /// MANIFEST \[ VERBOSE \] Manifest { verbose: bool }, /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \] @@ -8388,7 +8388,13 @@ impl fmt::Display for CopyLegacyOption { Header => write!(f, "HEADER"), IamRole(role) => write!(f, "IAM_ROLE {role}"), IgnoreHeader(num_rows) => write!(f, "IGNOREHEADER {num_rows}"), - Json => write!(f, "JSON"), + Json(opt) => { + write!(f, "JSON")?; + if let Some(opt) = opt { + write!(f, " AS '{}'", value::escape_single_quote_string(opt))?; + } + Ok(()) + } Manifest { verbose } => write!(f, "MANIFEST{}", if *verbose { " VERBOSE" } else { "" }), MaxFileSize(file_size) => write!(f, "MAXFILESIZE {file_size}"), Null(string) => write!(f, "NULL '{}'", value::escape_single_quote_string(string)), diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 3294acf6..3a31d925 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -10747,7 +10747,15 @@ impl<'a> Parser<'a> { let num_rows = self.parse_literal_uint()?; CopyLegacyOption::IgnoreHeader(num_rows) } - Some(Keyword::JSON) => CopyLegacyOption::Json, + Some(Keyword::JSON) => { + let _ = self.parse_keyword(Keyword::AS); + let fmt = if matches!(self.peek_token().token, Token::SingleQuotedString(_)) { + Some(self.parse_literal_string()?) + } else { + None + }; + CopyLegacyOption::Json(fmt) + } Some(Keyword::MANIFEST) => { let verbose = self.parse_keyword(Keyword::VERBOSE); CopyLegacyOption::Manifest { verbose } diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs index 365bddb0..9ed59eac 100644 --- a/tests/sqlparser_common.rs +++ b/tests/sqlparser_common.rs @@ -17421,6 +17421,9 @@ fn parse_copy_options() { "EMPTYASNULL ", "IAM_ROLE DEFAULT ", "IGNOREHEADER AS 1 ", + "JSON ", + "JSON 'auto' ", + "JSON AS 'auto' ", "TIMEFORMAT AS 'auto' ", "TRUNCATECOLUMNS ", "REMOVEQUOTES ", @@ -17446,6 +17449,9 @@ fn parse_copy_options() { "EMPTYASNULL ", "IAM_ROLE DEFAULT ", "IGNOREHEADER 1 ", + "JSON ", + "JSON AS 'auto' ", + "JSON AS 'auto' ", "TIMEFORMAT 'auto' ", "TRUNCATECOLUMNS ", "REMOVEQUOTES ", --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
