Skip to content

Commit 4c121a9

Browse files
poonaialamb
andauthored
support for session transaction and transaction snapshot. (#379)
* add support for snapshot id in set transaction Signed-off-by: poonai <[email protected]> * add support for default session transaction characteristics Signed-off-by: poonai <[email protected]> * add additional assertion for parse_set_transaction test Signed-off-by: poonai <[email protected]> * Fix clippy Co-authored-by: Andrew Lamb <[email protected]>
1 parent a81805e commit 4c121a9

File tree

5 files changed

+77
-10
lines changed

5 files changed

+77
-10
lines changed

src/ast/mod.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -786,7 +786,11 @@ pub enum Statement {
786786
/// `{ BEGIN [ TRANSACTION | WORK ] | START TRANSACTION } ...`
787787
StartTransaction { modes: Vec<TransactionMode> },
788788
/// `SET TRANSACTION ...`
789-
SetTransaction { modes: Vec<TransactionMode> },
789+
SetTransaction {
790+
modes: Vec<TransactionMode>,
791+
snapshot: Option<Value>,
792+
session: bool,
793+
},
790794
/// `COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
791795
Commit { chain: bool },
792796
/// `ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]`
@@ -1369,11 +1373,22 @@ impl fmt::Display for Statement {
13691373
}
13701374
Ok(())
13711375
}
1372-
Statement::SetTransaction { modes } => {
1373-
write!(f, "SET TRANSACTION")?;
1376+
Statement::SetTransaction {
1377+
modes,
1378+
snapshot,
1379+
session,
1380+
} => {
1381+
if *session {
1382+
write!(f, "SET SESSION CHARACTERISTICS AS TRANSACTION")?;
1383+
} else {
1384+
write!(f, "SET TRANSACTION")?;
1385+
}
13741386
if !modes.is_empty() {
13751387
write!(f, " {}", display_comma_separated(modes))?;
13761388
}
1389+
if let Some(snapshot_id) = snapshot {
1390+
write!(f, " SNAPSHOT {}", snapshot_id)?;
1391+
}
13771392
Ok(())
13781393
}
13791394
Statement::Commit { chain } => {

src/keywords.rs

+1
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ define_keywords!(
412412
SHOW,
413413
SIMILAR,
414414
SMALLINT,
415+
SNAPSHOT,
415416
SOME,
416417
SORT,
417418
SPECIFIC,

src/parser.rs

+17
Original file line numberDiff line numberDiff line change
@@ -2670,9 +2670,26 @@ impl<'a> Parser<'a> {
26702670
value: values,
26712671
});
26722672
}
2673+
} else if variable.value == "CHARACTERISTICS" {
2674+
self.expect_keywords(&[Keyword::AS, Keyword::TRANSACTION])?;
2675+
Ok(Statement::SetTransaction {
2676+
modes: self.parse_transaction_modes()?,
2677+
snapshot: None,
2678+
session: true,
2679+
})
26732680
} else if variable.value == "TRANSACTION" && modifier.is_none() {
2681+
if self.parse_keyword(Keyword::SNAPSHOT) {
2682+
let snaphot_id = self.parse_value()?;
2683+
return Ok(Statement::SetTransaction {
2684+
modes: vec![],
2685+
snapshot: Some(snaphot_id),
2686+
session: false,
2687+
});
2688+
}
26742689
Ok(Statement::SetTransaction {
26752690
modes: self.parse_transaction_modes()?,
2691+
snapshot: None,
2692+
session: false,
26762693
})
26772694
} else {
26782695
self.expected("equals sign or TO", self.peek_token())

tests/sqlparser_common.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -3586,14 +3586,22 @@ fn parse_set_transaction() {
35863586
// TRANSACTION, so no need to duplicate the tests here. We just do a quick
35873587
// sanity check.
35883588
match verified_stmt("SET TRANSACTION READ ONLY, READ WRITE, ISOLATION LEVEL SERIALIZABLE") {
3589-
Statement::SetTransaction { modes } => assert_eq!(
3589+
Statement::SetTransaction {
35903590
modes,
3591-
vec![
3592-
TransactionMode::AccessMode(TransactionAccessMode::ReadOnly),
3593-
TransactionMode::AccessMode(TransactionAccessMode::ReadWrite),
3594-
TransactionMode::IsolationLevel(TransactionIsolationLevel::Serializable),
3595-
]
3596-
),
3591+
session,
3592+
snapshot,
3593+
} => {
3594+
assert_eq!(
3595+
modes,
3596+
vec![
3597+
TransactionMode::AccessMode(TransactionAccessMode::ReadOnly),
3598+
TransactionMode::AccessMode(TransactionAccessMode::ReadWrite),
3599+
TransactionMode::IsolationLevel(TransactionIsolationLevel::Serializable),
3600+
]
3601+
);
3602+
assert!(!session);
3603+
assert_eq!(snapshot, None);
3604+
}
35973605
_ => unreachable!(),
35983606
}
35993607
}

tests/sqlparser_postgres.rs

+26
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,32 @@ fn parse_map_access_expr() {
723723
);
724724
}
725725

726+
#[test]
727+
fn test_transaction_statement() {
728+
let statement = pg().verified_stmt("SET TRANSACTION SNAPSHOT '000003A1-1'");
729+
assert_eq!(
730+
statement,
731+
Statement::SetTransaction {
732+
modes: vec![],
733+
snapshot: Some(Value::SingleQuotedString(String::from("000003A1-1"))),
734+
session: false
735+
}
736+
);
737+
let statement = pg().verified_stmt("SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY, READ WRITE, ISOLATION LEVEL SERIALIZABLE");
738+
assert_eq!(
739+
statement,
740+
Statement::SetTransaction {
741+
modes: vec![
742+
TransactionMode::AccessMode(TransactionAccessMode::ReadOnly),
743+
TransactionMode::AccessMode(TransactionAccessMode::ReadWrite),
744+
TransactionMode::IsolationLevel(TransactionIsolationLevel::Serializable),
745+
],
746+
snapshot: None,
747+
session: true
748+
}
749+
);
750+
}
751+
726752
fn pg() -> TestedDialects {
727753
TestedDialects {
728754
dialects: vec![Box::new(PostgreSqlDialect {})],

0 commit comments

Comments
 (0)