Skip to content

Commit 91599e8

Browse files
authored
Merge pull request #15 from cube-js/create-temporary-table
Support `global`,`local`, `on commit` for `create temporary table`
2 parents d26e026 + 97793cd commit 91599e8

File tree

5 files changed

+93
-10
lines changed

5 files changed

+93
-10
lines changed

src/ast/mod.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ pub enum Statement {
794794
or_replace: bool,
795795
temporary: bool,
796796
external: bool,
797+
global: Option<bool>,
797798
if_not_exists: bool,
798799
/// Table name
799800
name: ObjectName,
@@ -812,6 +813,7 @@ pub enum Statement {
812813
engine: Option<String>,
813814
default_charset: Option<String>,
814815
collation: Option<String>,
816+
on_commit: Option<OnCommit>,
815817
},
816818
/// SQLite's `CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
817819
CreateVirtualTable {
@@ -1308,6 +1310,7 @@ impl fmt::Display for Statement {
13081310
hive_distribution,
13091311
hive_formats,
13101312
external,
1313+
global,
13111314
temporary,
13121315
file_format,
13131316
location,
@@ -1317,6 +1320,7 @@ impl fmt::Display for Statement {
13171320
default_charset,
13181321
engine,
13191322
collation,
1323+
on_commit,
13201324
} => {
13211325
// We want to allow the following options
13221326
// Empty column list, allowed by PostgreSQL:
@@ -1327,9 +1331,18 @@ impl fmt::Display for Statement {
13271331
// `CREATE TABLE t (a INT) AS SELECT a from t2`
13281332
write!(
13291333
f,
1330-
"CREATE {or_replace}{external}{temporary}TABLE {if_not_exists}{name}",
1334+
"CREATE {or_replace}{external}{global}{temporary}TABLE {if_not_exists}{name}",
13311335
or_replace = if *or_replace { "OR REPLACE " } else { "" },
13321336
external = if *external { "EXTERNAL " } else { "" },
1337+
global = global
1338+
.map(|global| {
1339+
if global {
1340+
"GLOBAL "
1341+
} else {
1342+
"LOCAL "
1343+
}
1344+
})
1345+
.unwrap_or(""),
13331346
if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
13341347
temporary = if *temporary { "TEMPORARY " } else { "" },
13351348
name = name,
@@ -1451,6 +1464,17 @@ impl fmt::Display for Statement {
14511464
if let Some(collation) = collation {
14521465
write!(f, " COLLATE={}", collation)?;
14531466
}
1467+
1468+
if on_commit.is_some() {
1469+
let on_commit = match on_commit {
1470+
Some(OnCommit::DeleteRows) => "ON COMMIT DELETE ROWS",
1471+
Some(OnCommit::PreserveRows) => "ON COMMIT PRESERVE ROWS",
1472+
Some(OnCommit::Drop) => "ON COMMIT DROP",
1473+
None => "",
1474+
};
1475+
write!(f, " {}", on_commit)?;
1476+
}
1477+
14541478
Ok(())
14551479
}
14561480
Statement::CreateVirtualTable {
@@ -2351,6 +2375,14 @@ impl fmt::Display for CopyTarget {
23512375
}
23522376
}
23532377

2378+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2379+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2380+
pub enum OnCommit {
2381+
DeleteRows,
2382+
PreserveRows,
2383+
Drop,
2384+
}
2385+
23542386
/// An option in `COPY` statement.
23552387
///
23562388
/// <https://www.postgresql.org/docs/14/sql-copy.html>

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ define_keywords!(
380380
PRECEDING,
381381
PRECISION,
382382
PREPARE,
383+
PRESERVE,
383384
PRIMARY,
384385
PRIVILEGES,
385386
PROCEDURE,

src/parser.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1510,11 +1510,20 @@ impl<'a> Parser<'a> {
15101510
/// Parse a SQL CREATE statement
15111511
pub fn parse_create(&mut self) -> Result<Statement, ParserError> {
15121512
let or_replace = self.parse_keywords(&[Keyword::OR, Keyword::REPLACE]);
1513+
let local = self.parse_one_of_keywords(&[Keyword::LOCAL]).is_some();
1514+
let global = self.parse_one_of_keywords(&[Keyword::GLOBAL]).is_some();
1515+
let global: Option<bool> = if global {
1516+
Some(true)
1517+
} else if local {
1518+
Some(false)
1519+
} else {
1520+
None
1521+
};
15131522
let temporary = self
15141523
.parse_one_of_keywords(&[Keyword::TEMP, Keyword::TEMPORARY])
15151524
.is_some();
15161525
if self.parse_keyword(Keyword::TABLE) {
1517-
self.parse_create_table(or_replace, temporary)
1526+
self.parse_create_table(or_replace, temporary, global)
15181527
} else if self.parse_keyword(Keyword::MATERIALIZED) || self.parse_keyword(Keyword::VIEW) {
15191528
self.prev_token();
15201529
self.parse_create_view(or_replace)
@@ -1624,6 +1633,7 @@ impl<'a> Parser<'a> {
16241633
or_replace,
16251634
if_not_exists,
16261635
external: true,
1636+
global: None,
16271637
temporary: false,
16281638
file_format,
16291639
location,
@@ -1633,6 +1643,7 @@ impl<'a> Parser<'a> {
16331643
default_charset: None,
16341644
engine: None,
16351645
collation: None,
1646+
on_commit: None,
16361647
})
16371648
}
16381649

@@ -1781,6 +1792,7 @@ impl<'a> Parser<'a> {
17811792
&mut self,
17821793
or_replace: bool,
17831794
temporary: bool,
1795+
global: Option<bool>,
17841796
) -> Result<Statement, ParserError> {
17851797
let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]);
17861798
let table_name = self.parse_object_name()?;
@@ -1837,6 +1849,23 @@ impl<'a> Parser<'a> {
18371849
None
18381850
};
18391851

1852+
let on_commit: Option<OnCommit> =
1853+
if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT, Keyword::DELETE, Keyword::ROWS])
1854+
{
1855+
Some(OnCommit::DeleteRows)
1856+
} else if self.parse_keywords(&[
1857+
Keyword::ON,
1858+
Keyword::COMMIT,
1859+
Keyword::PRESERVE,
1860+
Keyword::ROWS,
1861+
]) {
1862+
Some(OnCommit::PreserveRows)
1863+
} else if self.parse_keywords(&[Keyword::ON, Keyword::COMMIT, Keyword::DROP]) {
1864+
Some(OnCommit::Drop)
1865+
} else {
1866+
None
1867+
};
1868+
18401869
Ok(Statement::CreateTable {
18411870
name: table_name,
18421871
temporary,
@@ -1849,6 +1878,7 @@ impl<'a> Parser<'a> {
18491878
hive_distribution,
18501879
hive_formats: Some(hive_formats),
18511880
external: false,
1881+
global,
18521882
file_format: None,
18531883
location: None,
18541884
query,
@@ -1857,6 +1887,7 @@ impl<'a> Parser<'a> {
18571887
engine,
18581888
default_charset,
18591889
collation,
1890+
on_commit,
18601891
})
18611892
}
18621893

tests/sqlparser_common.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,10 +2499,12 @@ fn parse_expr_interval() {
24992499
value: "HOUR".to_string(),
25002500
quote_style: None,
25012501
}]),
2502-
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident {
2503-
value: "order_date".to_string(),
2504-
quote_style: None,
2505-
})))],
2502+
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
2503+
Expr::Identifier(Ident {
2504+
value: "order_date".to_string(),
2505+
quote_style: None,
2506+
}),
2507+
))],
25062508
over: None,
25072509
distinct: false,
25082510
});
@@ -2528,10 +2530,12 @@ fn parse_expr_interval() {
25282530
value: "QUARTER".to_string(),
25292531
quote_style: None,
25302532
}]),
2531-
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(Expr::Identifier(Ident {
2532-
value: "order_date".to_string(),
2533-
quote_style: None,
2534-
})))],
2533+
args: vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
2534+
Expr::Identifier(Ident {
2535+
value: "order_date".to_string(),
2536+
quote_style: None,
2537+
}),
2538+
))],
25352539
over: None,
25362540
distinct: false,
25372541
});

tests/sqlparser_postgres.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,21 @@ fn parse_quoted_identifier() {
12641264
pg_and_generic().verified_stmt(r#"SELECT "quoted "" ident""#);
12651265
}
12661266

1267+
#[test]
1268+
fn parse_local_and_global() {
1269+
pg_and_generic().verified_stmt("CREATE LOCAL TEMPORARY TABLE table (COL INT)");
1270+
}
1271+
1272+
#[test]
1273+
fn parse_on_commit() {
1274+
pg_and_generic()
1275+
.verified_stmt("CREATE TEMPORARY TABLE table (COL INT) ON COMMIT PRESERVE ROWS");
1276+
1277+
pg_and_generic().verified_stmt("CREATE TEMPORARY TABLE table (COL INT) ON COMMIT DELETE ROWS");
1278+
1279+
pg_and_generic().verified_stmt("CREATE TEMPORARY TABLE table (COL INT) ON COMMIT DROP");
1280+
}
1281+
12671282
fn pg() -> TestedDialects {
12681283
TestedDialects {
12691284
dialects: vec![Box::new(PostgreSqlDialect {})],

0 commit comments

Comments
 (0)