Skip to content

Commit 56b63be

Browse files
author
Roman Borschel
committed
Merge branch 'main' into mssql-if-else
2 parents 535793d + 3ed4ad9 commit 56b63be

File tree

9 files changed

+157
-42
lines changed

9 files changed

+157
-42
lines changed

src/ast/ddl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ impl fmt::Display for AlterColumnOperation {
868868
AlterColumnOperation::SetDefault { value } => {
869869
write!(f, "SET DEFAULT {value}")
870870
}
871-
AlterColumnOperation::DropDefault {} => {
871+
AlterColumnOperation::DropDefault => {
872872
write!(f, "DROP DEFAULT")
873873
}
874874
AlterColumnOperation::SetDataType { data_type, using } => {

src/ast/mod.rs

Lines changed: 56 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -663,17 +663,17 @@ pub enum Expr {
663663
/// such as maps, arrays, and lists:
664664
/// - Array
665665
/// - A 1-dim array `a[1]` will be represented like:
666-
/// `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
666+
/// `CompoundFieldAccess(Ident('a'), vec![Subscript(1)]`
667667
/// - A 2-dim array `a[1][2]` will be represented like:
668-
/// `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
668+
/// `CompoundFieldAccess(Ident('a'), vec![Subscript(1), Subscript(2)]`
669669
/// - Map or Struct (Bracket-style)
670670
/// - A map `a['field1']` will be represented like:
671-
/// `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
671+
/// `CompoundFieldAccess(Ident('a'), vec![Subscript('field')]`
672672
/// - A 2-dim map `a['field1']['field2']` will be represented like:
673-
/// `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
673+
/// `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Subscript('field2')]`
674674
/// - Struct (Dot-style) (only effect when the chain contains both subscript and expr)
675675
/// - A struct access `a[field1].field2` will be represented like:
676-
/// `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
676+
/// `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]`
677677
/// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2])
678678
CompoundFieldAccess {
679679
root: Box<Expr>,
@@ -6137,10 +6137,10 @@ pub enum Action {
61376137
ManageReleases,
61386138
ManageVersions,
61396139
Modify {
6140-
modify_type: ActionModifyType,
6140+
modify_type: Option<ActionModifyType>,
61416141
},
61426142
Monitor {
6143-
monitor_type: ActionMonitorType,
6143+
monitor_type: Option<ActionMonitorType>,
61446144
},
61456145
Operate,
61466146
OverrideShareRestrictions,
@@ -6173,7 +6173,7 @@ impl fmt::Display for Action {
61736173
match self {
61746174
Action::AddSearchOptimization => f.write_str("ADD SEARCH OPTIMIZATION")?,
61756175
Action::Apply { apply_type } => write!(f, "APPLY {apply_type}")?,
6176-
Action::ApplyBudget => f.write_str("APPLY BUDGET")?,
6176+
Action::ApplyBudget => f.write_str("APPLYBUDGET")?,
61776177
Action::AttachListing => f.write_str("ATTACH LISTING")?,
61786178
Action::AttachPolicy => f.write_str("ATTACH POLICY")?,
61796179
Action::Audit => f.write_str("AUDIT")?,
@@ -6201,8 +6201,18 @@ impl fmt::Display for Action {
62016201
Action::Manage { manage_type } => write!(f, "MANAGE {manage_type}")?,
62026202
Action::ManageReleases => f.write_str("MANAGE RELEASES")?,
62036203
Action::ManageVersions => f.write_str("MANAGE VERSIONS")?,
6204-
Action::Modify { modify_type } => write!(f, "MODIFY {modify_type}")?,
6205-
Action::Monitor { monitor_type } => write!(f, "MONITOR {monitor_type}")?,
6204+
Action::Modify { modify_type } => {
6205+
write!(f, "MODIFY")?;
6206+
if let Some(modify_type) = modify_type {
6207+
write!(f, " {modify_type}")?;
6208+
}
6209+
}
6210+
Action::Monitor { monitor_type } => {
6211+
write!(f, "MONITOR")?;
6212+
if let Some(monitor_type) = monitor_type {
6213+
write!(f, " {monitor_type}")?
6214+
}
6215+
}
62066216
Action::Operate => f.write_str("OPERATE")?,
62076217
Action::OverrideShareRestrictions => f.write_str("OVERRIDE SHARE RESTRICTIONS")?,
62086218
Action::Ownership => f.write_str("OWNERSHIP")?,
@@ -6520,6 +6530,20 @@ pub enum GrantObjects {
65206530
Warehouses(Vec<ObjectName>),
65216531
/// Grant privileges on specific integrations
65226532
Integrations(Vec<ObjectName>),
6533+
/// Grant privileges on resource monitors
6534+
ResourceMonitors(Vec<ObjectName>),
6535+
/// Grant privileges on users
6536+
Users(Vec<ObjectName>),
6537+
/// Grant privileges on compute pools
6538+
ComputePools(Vec<ObjectName>),
6539+
/// Grant privileges on connections
6540+
Connections(Vec<ObjectName>),
6541+
/// Grant privileges on failover groups
6542+
FailoverGroup(Vec<ObjectName>),
6543+
/// Grant privileges on replication group
6544+
ReplicationGroup(Vec<ObjectName>),
6545+
/// Grant privileges on external volumes
6546+
ExternalVolumes(Vec<ObjectName>),
65236547
}
65246548

65256549
impl fmt::Display for GrantObjects {
@@ -6560,6 +6584,27 @@ impl fmt::Display for GrantObjects {
65606584
display_comma_separated(schemas)
65616585
)
65626586
}
6587+
GrantObjects::ResourceMonitors(objects) => {
6588+
write!(f, "RESOURCE MONITOR {}", display_comma_separated(objects))
6589+
}
6590+
GrantObjects::Users(objects) => {
6591+
write!(f, "USER {}", display_comma_separated(objects))
6592+
}
6593+
GrantObjects::ComputePools(objects) => {
6594+
write!(f, "COMPUTE POOL {}", display_comma_separated(objects))
6595+
}
6596+
GrantObjects::Connections(objects) => {
6597+
write!(f, "CONNECTION {}", display_comma_separated(objects))
6598+
}
6599+
GrantObjects::FailoverGroup(objects) => {
6600+
write!(f, "FAILOVER GROUP {}", display_comma_separated(objects))
6601+
}
6602+
GrantObjects::ReplicationGroup(objects) => {
6603+
write!(f, "REPLICATION GROUP {}", display_comma_separated(objects))
6604+
}
6605+
GrantObjects::ExternalVolumes(objects) => {
6606+
write!(f, "EXTERNAL VOLUME {}", display_comma_separated(objects))
6607+
}
65636608
}
65646609
}
65656610
}
@@ -7630,7 +7675,7 @@ impl fmt::Display for CopyTarget {
76307675
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
76317676
use CopyTarget::*;
76327677
match self {
7633-
Stdin { .. } => write!(f, "STDIN"),
7678+
Stdin => write!(f, "STDIN"),
76347679
Stdout => write!(f, "STDOUT"),
76357680
File { filename } => write!(f, "'{}'", value::escape_single_quote_string(filename)),
76367681
Program { command } => write!(

src/dialect/redshift.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,8 @@ impl Dialect for RedshiftSqlDialect {
121121
fn supports_array_typedef_with_brackets(&self) -> bool {
122122
true
123123
}
124+
125+
fn allow_extract_single_quotes(&self) -> bool {
126+
true
127+
}
124128
}

src/dialect/snowflake.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,14 +1038,13 @@ fn parse_session_options(
10381038
}
10391039
}
10401040
}
1041-
options
1042-
.is_empty()
1043-
.then(|| {
1044-
Err(ParserError::ParserError(
1045-
"expected at least one option".to_string(),
1046-
))
1047-
})
1048-
.unwrap_or(Ok(options))
1041+
if options.is_empty() {
1042+
Err(ParserError::ParserError(
1043+
"expected at least one option".to_string(),
1044+
))
1045+
} else {
1046+
Ok(options)
1047+
}
10491048
}
10501049

10511050
/// Parses options provided within parentheses like:

src/keywords.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
//! This module defines
1919
//! 1) a list of constants for every keyword
2020
//! 2) an `ALL_KEYWORDS` array with every keyword in it
21-
//! This is not a list of *reserved* keywords: some of these can be
22-
//! parsed as identifiers if the parser decides so. This means that
23-
//! new keywords can be added here without affecting the parse result.
21+
//! This is not a list of *reserved* keywords: some of these can be
22+
//! parsed as identifiers if the parser decides so. This means that
23+
//! new keywords can be added here without affecting the parse result.
2424
//!
25-
//! As a matter of fact, most of these keywords are not used at all
26-
//! and could be removed.
25+
//! As a matter of fact, most of these keywords are not used at all
26+
//! and could be removed.
2727
//! 3) a `RESERVED_FOR_TABLE_ALIAS` array with keywords reserved in a
28-
//! "table alias" context.
28+
//! "table alias" context.
2929
3030
#[cfg(feature = "serde")]
3131
use serde::{Deserialize, Serialize};
@@ -738,6 +738,7 @@ define_keywords!(
738738
REPLICATION,
739739
RESET,
740740
RESOLVE,
741+
RESOURCE,
741742
RESPECT,
742743
RESTART,
743744
RESTRICT,

src/parser/mod.rs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12889,6 +12889,26 @@ impl<'a> Parser<'a> {
1288912889
Some(GrantObjects::AllSequencesInSchema {
1289012890
schemas: self.parse_comma_separated(|p| p.parse_object_name(false))?,
1289112891
})
12892+
} else if self.parse_keywords(&[Keyword::RESOURCE, Keyword::MONITOR]) {
12893+
Some(GrantObjects::ResourceMonitors(self.parse_comma_separated(
12894+
|p| p.parse_object_name_with_wildcards(false, true),
12895+
)?))
12896+
} else if self.parse_keywords(&[Keyword::COMPUTE, Keyword::POOL]) {
12897+
Some(GrantObjects::ComputePools(self.parse_comma_separated(
12898+
|p| p.parse_object_name_with_wildcards(false, true),
12899+
)?))
12900+
} else if self.parse_keywords(&[Keyword::FAILOVER, Keyword::GROUP]) {
12901+
Some(GrantObjects::FailoverGroup(self.parse_comma_separated(
12902+
|p| p.parse_object_name_with_wildcards(false, true),
12903+
)?))
12904+
} else if self.parse_keywords(&[Keyword::REPLICATION, Keyword::GROUP]) {
12905+
Some(GrantObjects::ReplicationGroup(self.parse_comma_separated(
12906+
|p| p.parse_object_name_with_wildcards(false, true),
12907+
)?))
12908+
} else if self.parse_keywords(&[Keyword::EXTERNAL, Keyword::VOLUME]) {
12909+
Some(GrantObjects::ExternalVolumes(self.parse_comma_separated(
12910+
|p| p.parse_object_name_with_wildcards(false, true),
12911+
)?))
1289212912
} else {
1289312913
let object_type = self.parse_one_of_keywords(&[
1289412914
Keyword::SEQUENCE,
@@ -12902,6 +12922,8 @@ impl<'a> Parser<'a> {
1290212922
Keyword::VIEW,
1290312923
Keyword::WAREHOUSE,
1290412924
Keyword::INTEGRATION,
12925+
Keyword::USER,
12926+
Keyword::CONNECTION,
1290512927
]);
1290612928
let objects =
1290712929
self.parse_comma_separated(|p| p.parse_object_name_with_wildcards(false, true));
@@ -12912,6 +12934,8 @@ impl<'a> Parser<'a> {
1291212934
Some(Keyword::WAREHOUSE) => Some(GrantObjects::Warehouses(objects?)),
1291312935
Some(Keyword::INTEGRATION) => Some(GrantObjects::Integrations(objects?)),
1291412936
Some(Keyword::VIEW) => Some(GrantObjects::Views(objects?)),
12937+
Some(Keyword::USER) => Some(GrantObjects::Users(objects?)),
12938+
Some(Keyword::CONNECTION) => Some(GrantObjects::Connections(objects?)),
1291512939
Some(Keyword::TABLE) | None => Some(GrantObjects::Tables(objects?)),
1291612940
_ => unreachable!(),
1291712941
}
@@ -12997,10 +13021,10 @@ impl<'a> Parser<'a> {
1299713021
let manage_type = self.parse_action_manage_type()?;
1299813022
Ok(Action::Manage { manage_type })
1299913023
} else if self.parse_keyword(Keyword::MODIFY) {
13000-
let modify_type = self.parse_action_modify_type()?;
13024+
let modify_type = self.parse_action_modify_type();
1300113025
Ok(Action::Modify { modify_type })
1300213026
} else if self.parse_keyword(Keyword::MONITOR) {
13003-
let monitor_type = self.parse_action_monitor_type()?;
13027+
let monitor_type = self.parse_action_monitor_type();
1300413028
Ok(Action::Monitor { monitor_type })
1300513029
} else if self.parse_keyword(Keyword::OPERATE) {
1300613030
Ok(Action::Operate)
@@ -13141,29 +13165,29 @@ impl<'a> Parser<'a> {
1314113165
}
1314213166
}
1314313167

13144-
fn parse_action_modify_type(&mut self) -> Result<ActionModifyType, ParserError> {
13168+
fn parse_action_modify_type(&mut self) -> Option<ActionModifyType> {
1314513169
if self.parse_keywords(&[Keyword::LOG, Keyword::LEVEL]) {
13146-
Ok(ActionModifyType::LogLevel)
13170+
Some(ActionModifyType::LogLevel)
1314713171
} else if self.parse_keywords(&[Keyword::TRACE, Keyword::LEVEL]) {
13148-
Ok(ActionModifyType::TraceLevel)
13172+
Some(ActionModifyType::TraceLevel)
1314913173
} else if self.parse_keywords(&[Keyword::SESSION, Keyword::LOG, Keyword::LEVEL]) {
13150-
Ok(ActionModifyType::SessionLogLevel)
13174+
Some(ActionModifyType::SessionLogLevel)
1315113175
} else if self.parse_keywords(&[Keyword::SESSION, Keyword::TRACE, Keyword::LEVEL]) {
13152-
Ok(ActionModifyType::SessionTraceLevel)
13176+
Some(ActionModifyType::SessionTraceLevel)
1315313177
} else {
13154-
self.expected("GRANT MODIFY type", self.peek_token())
13178+
None
1315513179
}
1315613180
}
1315713181

13158-
fn parse_action_monitor_type(&mut self) -> Result<ActionMonitorType, ParserError> {
13182+
fn parse_action_monitor_type(&mut self) -> Option<ActionMonitorType> {
1315913183
if self.parse_keyword(Keyword::EXECUTION) {
13160-
Ok(ActionMonitorType::Execution)
13184+
Some(ActionMonitorType::Execution)
1316113185
} else if self.parse_keyword(Keyword::SECURITY) {
13162-
Ok(ActionMonitorType::Security)
13186+
Some(ActionMonitorType::Security)
1316313187
} else if self.parse_keyword(Keyword::USAGE) {
13164-
Ok(ActionMonitorType::Usage)
13188+
Some(ActionMonitorType::Usage)
1316513189
} else {
13166-
self.expected("GRANT MONITOR type", self.peek_token())
13190+
None
1316713191
}
1316813192
}
1316913193

tests/sqlparser_common.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14091,8 +14091,7 @@ fn test_table_sample() {
1409114091

1409214092
#[test]
1409314093
fn overflow() {
14094-
let expr = std::iter::repeat("1")
14095-
.take(1000)
14094+
let expr = std::iter::repeat_n("1", 1000)
1409614095
.collect::<Vec<_>>()
1409714096
.join(" + ");
1409814097
let sql = format!("SELECT {}", expr);

tests/sqlparser_redshift.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,3 +391,9 @@ fn test_parse_nested_quoted_identifier() {
391391
.parse_sql_statements(r#"SELECT 1 AS ["1]"#)
392392
.is_err());
393393
}
394+
395+
#[test]
396+
fn parse_extract_single_quotes() {
397+
let sql = "SELECT EXTRACT('month' FROM my_timestamp) FROM my_table";
398+
redshift().verified_stmt(&sql);
399+
}

tests/sqlparser_snowflake.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3357,7 +3357,7 @@ fn test_timetravel_at_before() {
33573357
}
33583358

33593359
#[test]
3360-
fn test_grant_account_privileges() {
3360+
fn test_grant_account_global_privileges() {
33613361
let privileges = vec![
33623362
"ALL",
33633363
"ALL PRIVILEGES",
@@ -3462,6 +3462,43 @@ fn test_grant_account_privileges() {
34623462
}
34633463
}
34643464

3465+
#[test]
3466+
fn test_grant_account_object_privileges() {
3467+
let privileges = vec![
3468+
"ALL",
3469+
"ALL PRIVILEGES",
3470+
"APPLYBUDGET",
3471+
"MODIFY",
3472+
"MONITOR",
3473+
"USAGE",
3474+
"OPERATE",
3475+
];
3476+
3477+
let objects_types = vec![
3478+
"USER",
3479+
"RESOURCE MONITOR",
3480+
"WAREHOUSE",
3481+
"COMPUTE POOL",
3482+
"DATABASE",
3483+
"INTEGRATION",
3484+
"CONNECTION",
3485+
"FAILOVER GROUP",
3486+
"REPLICATION GROUP",
3487+
"EXTERNAL VOLUME",
3488+
];
3489+
3490+
let with_grant_options = vec!["", " WITH GRANT OPTION"];
3491+
3492+
for t in &objects_types {
3493+
for p in &privileges {
3494+
for wgo in &with_grant_options {
3495+
let sql = format!("GRANT {p} ON {t} obj1 TO ROLE role1{wgo}");
3496+
snowflake_and_generic().verified_stmt(&sql);
3497+
}
3498+
}
3499+
}
3500+
}
3501+
34653502
#[test]
34663503
fn test_grant_role_to() {
34673504
snowflake_and_generic().verified_stmt("GRANT ROLE r1 TO ROLE r2");

0 commit comments

Comments
 (0)