Skip to content

Commit d6f7253

Browse files
Postgres: Apply ONLY keyword per table in TRUNCATE stmt
The `ONLY` keyword was previously applied to the entire stmt, the correct psql behaviour is to apply the keyword per table.
1 parent 394a534 commit d6f7253

File tree

5 files changed

+45
-15
lines changed

5 files changed

+45
-15
lines changed

src/ast/mod.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3014,9 +3014,6 @@ pub enum Statement {
30143014
/// TABLE - optional keyword;
30153015
table: bool,
30163016
/// Postgres-specific option
3017-
/// [ TRUNCATE TABLE ONLY ]
3018-
only: bool,
3019-
/// Postgres-specific option
30203017
/// [ RESTART IDENTITY | CONTINUE IDENTITY ]
30213018
identity: Option<TruncateIdentityOption>,
30223019
/// Postgres-specific option
@@ -3405,7 +3402,7 @@ pub enum Statement {
34053402
purge: bool,
34063403
/// MySQL-specific "TEMPORARY" keyword
34073404
temporary: bool,
3408-
/// MySQL-specific drop index syntax, which requires table specification
3405+
/// MySQL-specific drop index syntax, which requires table specification
34093406
/// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
34103407
table: Option<ObjectName>,
34113408
},
@@ -4422,17 +4419,15 @@ impl fmt::Display for Statement {
44224419
table_names,
44234420
partitions,
44244421
table,
4425-
only,
44264422
identity,
44274423
cascade,
44284424
on_cluster,
44294425
} => {
44304426
let table = if *table { "TABLE " } else { "" };
4431-
let only = if *only { "ONLY " } else { "" };
44324427

44334428
write!(
44344429
f,
4435-
"TRUNCATE {table}{only}{table_names}",
4430+
"TRUNCATE {table}{table_names}",
44364431
table_names = display_comma_separated(table_names)
44374432
)?;
44384433

@@ -6097,10 +6092,17 @@ pub struct TruncateTableTarget {
60976092
/// name of the table being truncated
60986093
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
60996094
pub name: ObjectName,
6095+
/// Postgres-specific option
6096+
/// [ TRUNCATE TABLE ONLY ]
6097+
/// <https://www.postgresql.org/docs/current/sql-truncate.html>
6098+
pub only: bool,
61006099
}
61016100

61026101
impl fmt::Display for TruncateTableTarget {
61036102
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6103+
if self.only {
6104+
write!(f, "ONLY ")?;
6105+
};
61046106
write!(f, "{}", self.name)
61056107
}
61066108
}

src/ast/spans.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,6 @@ impl Spanned for Statement {
311311
table_names,
312312
partitions,
313313
table: _,
314-
only: _,
315314
identity: _,
316315
cascade: _,
317316
on_cluster: _,

src/parser/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -960,12 +960,13 @@ impl<'a> Parser<'a> {
960960

961961
pub fn parse_truncate(&mut self) -> Result<Statement, ParserError> {
962962
let table = self.parse_keyword(Keyword::TABLE);
963-
let only = self.parse_keyword(Keyword::ONLY);
964963

965964
let table_names = self
966-
.parse_comma_separated(|p| p.parse_object_name(false))?
965+
.parse_comma_separated(|p| {
966+
Ok((p.parse_keyword(Keyword::ONLY), p.parse_object_name(false)?))
967+
})?
967968
.into_iter()
968-
.map(|n| TruncateTableTarget { name: n })
969+
.map(|(only, name)| TruncateTableTarget { name, only })
969970
.collect();
970971

971972
let mut partitions = None;
@@ -996,7 +997,6 @@ impl<'a> Parser<'a> {
996997
table_names,
997998
partitions,
998999
table,
999-
only,
10001000
identity,
10011001
cascade,
10021002
on_cluster,

tests/sqlparser_common.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15294,3 +15294,31 @@ fn test_open() {
1529415294
})
1529515295
);
1529615296
}
15297+
15298+
#[test]
15299+
fn parse_truncate_only() {
15300+
let truncate = all_dialects().verified_stmt("TRUNCATE TABLE employee, ONLY dept");
15301+
15302+
let table_names = vec![
15303+
TruncateTableTarget {
15304+
name: ObjectName::from(vec![Ident::new("employee")]),
15305+
only: false,
15306+
},
15307+
TruncateTableTarget {
15308+
name: ObjectName::from(vec![Ident::new("dept")]),
15309+
only: true,
15310+
},
15311+
];
15312+
15313+
assert_eq!(
15314+
Statement::Truncate {
15315+
table_names,
15316+
partitions: None,
15317+
table: true,
15318+
identity: None,
15319+
cascade: None,
15320+
on_cluster: None,
15321+
},
15322+
truncate
15323+
);
15324+
}

tests/sqlparser_postgres.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4790,13 +4790,13 @@ fn parse_truncate() {
47904790
let table_name = ObjectName::from(vec![Ident::new("db"), Ident::new("table_name")]);
47914791
let table_names = vec![TruncateTableTarget {
47924792
name: table_name.clone(),
4793+
only: false,
47934794
}];
47944795
assert_eq!(
47954796
Statement::Truncate {
47964797
table_names,
47974798
partitions: None,
47984799
table: false,
4799-
only: false,
48004800
identity: None,
48014801
cascade: None,
48024802
on_cluster: None,
@@ -4813,14 +4813,14 @@ fn parse_truncate_with_options() {
48134813
let table_name = ObjectName::from(vec![Ident::new("db"), Ident::new("table_name")]);
48144814
let table_names = vec![TruncateTableTarget {
48154815
name: table_name.clone(),
4816+
only: true,
48164817
}];
48174818

48184819
assert_eq!(
48194820
Statement::Truncate {
48204821
table_names,
48214822
partitions: None,
48224823
table: true,
4823-
only: true,
48244824
identity: Some(TruncateIdentityOption::Restart),
48254825
cascade: Some(CascadeOption::Cascade),
48264826
on_cluster: None,
@@ -4841,9 +4841,11 @@ fn parse_truncate_with_table_list() {
48414841
let table_names = vec![
48424842
TruncateTableTarget {
48434843
name: table_name_a.clone(),
4844+
only: false,
48444845
},
48454846
TruncateTableTarget {
48464847
name: table_name_b.clone(),
4848+
only: false,
48474849
},
48484850
];
48494851

@@ -4852,7 +4854,6 @@ fn parse_truncate_with_table_list() {
48524854
table_names,
48534855
partitions: None,
48544856
table: true,
4855-
only: false,
48564857
identity: Some(TruncateIdentityOption::Restart),
48574858
cascade: Some(CascadeOption::Cascade),
48584859
on_cluster: None,

0 commit comments

Comments
 (0)