Redshift: more copy options (#2072)

This commit is contained in:
Yoav Cohen 2025-10-22 11:11:19 +02:00 committed by GitHub
parent 9cc9f9ab38
commit 6b352eaffd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 95 additions and 2 deletions

View file

@ -8210,6 +8210,8 @@ pub enum CopyLegacyOption {
Bzip2,
/// CLEANPATH
CleanPath,
/// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ]
CompUpdate { preset: bool, enabled: Option<bool> },
/// CSV ...
Csv(Vec<CopyLegacyCsvOption>),
/// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' }
@ -8250,8 +8252,12 @@ pub enum CopyLegacyOption {
PartitionBy(UnloadPartitionBy),
/// REGION \[ AS \] 'aws-region' }
Region(String),
/// REMOVEQUOTES
RemoveQuotes,
/// ROWGROUPSIZE \[ AS \] size \[ MB | GB \]
RowGroupSize(FileSize),
/// STATUPDATE [ { ON | TRUE } | { OFF | FALSE } ]
StatUpdate(Option<bool>),
/// TIMEFORMAT \[ AS \] {'timeformat_string' | 'auto' | 'epochsecs' | 'epochmillisecs' }
TimeFormat(Option<String>),
/// TRUNCATECOLUMNS
@ -8278,6 +8284,22 @@ impl fmt::Display for CopyLegacyOption {
BlankAsNull => write!(f, "BLANKSASNULL"),
Bzip2 => write!(f, "BZIP2"),
CleanPath => write!(f, "CLEANPATH"),
CompUpdate { preset, enabled } => {
write!(f, "COMPUPDATE")?;
if *preset {
write!(f, " PRESET")?;
} else if let Some(enabled) = enabled {
write!(
f,
"{}",
match enabled {
true => " TRUE",
false => " FALSE",
}
)?;
}
Ok(())
}
Csv(opts) => {
write!(f, "CSV")?;
if !opts.is_empty() {
@ -8324,7 +8346,19 @@ impl fmt::Display for CopyLegacyOption {
Parquet => write!(f, "PARQUET"),
PartitionBy(p) => write!(f, "{p}"),
Region(region) => write!(f, "REGION '{}'", value::escape_single_quote_string(region)),
RemoveQuotes => write!(f, "REMOVEQUOTES"),
RowGroupSize(file_size) => write!(f, "ROWGROUPSIZE {file_size}"),
StatUpdate(enabled) => {
write!(
f,
"STATUPDATE{}",
match enabled {
Some(true) => " TRUE",
Some(false) => " FALSE",
_ => "",
}
)
}
TimeFormat(fmt) => {
write!(f, "TIMEFORMAT")?;
if let Some(fmt) = fmt {

View file

@ -215,6 +215,7 @@ define_keywords!(
COMMITTED,
COMPATIBLE,
COMPRESSION,
COMPUPDATE,
COMPUTE,
CONCURRENTLY,
CONDITION,
@ -749,6 +750,7 @@ define_keywords!(
PRECISION,
PREPARE,
PRESERVE,
PRESET,
PREWHERE,
PRIMARY,
PRINT,
@ -801,6 +803,7 @@ define_keywords!(
RELEASES,
REMOTE,
REMOVE,
REMOVEQUOTES,
RENAME,
REORG,
REPAIR,
@ -915,6 +918,7 @@ define_keywords!(
STATS_AUTO_RECALC,
STATS_PERSISTENT,
STATS_SAMPLE_PAGES,
STATUPDATE,
STATUS,
STDDEV_POP,
STDDEV_SAMP,

View file

@ -9741,6 +9741,7 @@ impl<'a> Parser<'a> {
Keyword::BLANKSASNULL,
Keyword::BZIP2,
Keyword::CLEANPATH,
Keyword::COMPUPDATE,
Keyword::CSV,
Keyword::DATEFORMAT,
Keyword::DELIMITER,
@ -9761,7 +9762,9 @@ impl<'a> Parser<'a> {
Keyword::PARQUET,
Keyword::PARTITION,
Keyword::REGION,
Keyword::REMOVEQUOTES,
Keyword::ROWGROUPSIZE,
Keyword::STATUPDATE,
Keyword::TIMEFORMAT,
Keyword::TRUNCATECOLUMNS,
Keyword::ZSTD,
@ -9782,6 +9785,20 @@ impl<'a> Parser<'a> {
Some(Keyword::BLANKSASNULL) => CopyLegacyOption::BlankAsNull,
Some(Keyword::BZIP2) => CopyLegacyOption::Bzip2,
Some(Keyword::CLEANPATH) => CopyLegacyOption::CleanPath,
Some(Keyword::COMPUPDATE) => {
let preset = self.parse_keyword(Keyword::PRESET);
let enabled = match self.parse_one_of_keywords(&[
Keyword::TRUE,
Keyword::FALSE,
Keyword::ON,
Keyword::OFF,
]) {
Some(Keyword::TRUE) | Some(Keyword::ON) => Some(true),
Some(Keyword::FALSE) | Some(Keyword::OFF) => Some(false),
_ => None,
};
CopyLegacyOption::CompUpdate { preset, enabled }
}
Some(Keyword::CSV) => CopyLegacyOption::Csv({
let mut opts = vec![];
while let Some(opt) =
@ -9870,11 +9887,25 @@ impl<'a> Parser<'a> {
let region = self.parse_literal_string()?;
CopyLegacyOption::Region(region)
}
Some(Keyword::REMOVEQUOTES) => CopyLegacyOption::RemoveQuotes,
Some(Keyword::ROWGROUPSIZE) => {
let _ = self.parse_keyword(Keyword::AS);
let file_size = self.parse_file_size()?;
CopyLegacyOption::RowGroupSize(file_size)
}
Some(Keyword::STATUPDATE) => {
let enabled = match self.parse_one_of_keywords(&[
Keyword::TRUE,
Keyword::FALSE,
Keyword::ON,
Keyword::OFF,
]) {
Some(Keyword::TRUE) | Some(Keyword::ON) => Some(true),
Some(Keyword::FALSE) | Some(Keyword::OFF) => Some(false),
_ => None,
};
CopyLegacyOption::StatUpdate(enabled)
}
Some(Keyword::TIMEFORMAT) => {
let _ = self.parse_keyword(Keyword::AS);
let fmt = if matches!(self.peek_token().token, Token::SingleQuotedString(_)) {