Skip to content

Commit 1318e49

Browse files
author
Takahiro Ebato
committed
add support for BEGIN TRANSACTION modifiers in sqlite
Support the following syntaxes - BEGIN DEFERRED - BEGIN IMMEDIATE - BEGIN EXCLUSIVE
1 parent 8d97330 commit 1318e49

File tree

4 files changed

+81
-1
lines changed

4 files changed

+81
-1
lines changed

src/ast/mod.rs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1819,6 +1819,8 @@ pub enum Statement {
18191819
StartTransaction {
18201820
modes: Vec<TransactionMode>,
18211821
begin: bool,
1822+
// Only for sqlite
1823+
modifier: Option<TransactionModifier>,
18221824
},
18231825
/// `SET TRANSACTION ...`
18241826
SetTransaction {
@@ -3107,9 +3109,14 @@ impl fmt::Display for Statement {
31073109
Statement::StartTransaction {
31083110
modes,
31093111
begin: syntax_begin,
3112+
modifier,
31103113
} => {
31113114
if *syntax_begin {
3112-
write!(f, "BEGIN TRANSACTION")?;
3115+
if let Some(modifier) = *modifier {
3116+
write!(f, "BEGIN {} TRANSACTION", modifier)?;
3117+
} else {
3118+
write!(f, "BEGIN TRANSACTION")?;
3119+
}
31133120
} else {
31143121
write!(f, "START TRANSACTION")?;
31153122
}
@@ -4292,6 +4299,29 @@ impl fmt::Display for TransactionIsolationLevel {
42924299
}
42934300
}
42944301

4302+
/// Sqlite specific syntax
4303+
///
4304+
/// https://sqlite.org/lang_transaction.html
4305+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
4306+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
4307+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
4308+
pub enum TransactionModifier {
4309+
Deferred,
4310+
Immediate,
4311+
Exclusive,
4312+
}
4313+
4314+
impl fmt::Display for TransactionModifier {
4315+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
4316+
use TransactionModifier::*;
4317+
f.write_str(match self {
4318+
Deferred => "DEFERRED",
4319+
Immediate => "IMMEDIATE",
4320+
Exclusive => "EXCLUSIVE",
4321+
})
4322+
}
4323+
}
4324+
42954325
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
42964326
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
42974327
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]

src/keywords.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ define_keywords!(
209209
DECIMAL,
210210
DECLARE,
211211
DEFAULT,
212+
DEFERRED,
212213
DELETE,
213214
DELIMITED,
214215
DELIMITER,
@@ -254,6 +255,7 @@ define_keywords!(
254255
EVERY,
255256
EXCEPT,
256257
EXCLUDE,
258+
EXCLUSIVE,
257259
EXEC,
258260
EXECUTE,
259261
EXISTS,
@@ -321,6 +323,7 @@ define_keywords!(
321323
IF,
322324
IGNORE,
323325
ILIKE,
326+
IMMEDIATE,
324327
IMMUTABLE,
325328
IN,
326329
INCLUDE,

src/parser/mod.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7834,14 +7834,27 @@ impl<'a> Parser<'a> {
78347834
Ok(Statement::StartTransaction {
78357835
modes: self.parse_transaction_modes()?,
78367836
begin: false,
7837+
modifier: None,
78377838
})
78387839
}
78397840

78407841
pub fn parse_begin(&mut self) -> Result<Statement, ParserError> {
7842+
let modifier = if !dialect_of!(self is SQLiteDialect) {
7843+
None
7844+
} else if self.parse_keyword(Keyword::DEFERRED) {
7845+
Some(TransactionModifier::Deferred)
7846+
} else if self.parse_keyword(Keyword::IMMEDIATE) {
7847+
Some(TransactionModifier::Immediate)
7848+
} else if self.parse_keyword(Keyword::EXCLUSIVE) {
7849+
Some(TransactionModifier::Exclusive)
7850+
} else {
7851+
None
7852+
};
78417853
let _ = self.parse_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK]);
78427854
Ok(Statement::StartTransaction {
78437855
modes: self.parse_transaction_modes()?,
78447856
begin: true,
7857+
modifier,
78457858
})
78467859
}
78477860

tests/sqlparser_common.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6232,6 +6232,40 @@ fn parse_start_transaction() {
62326232
);
62336233
}
62346234

6235+
#[test]
6236+
fn parse_start_transaction_sqlite() {
6237+
let dialect = SQLiteDialect {};
6238+
6239+
let check = |sql: &str, expected_modifier: Option<TransactionModifier>| match Parser::parse_sql(
6240+
&dialect, &sql,
6241+
)
6242+
.unwrap()
6243+
.pop()
6244+
.unwrap()
6245+
{
6246+
Statement::StartTransaction { modifier, .. } => assert_eq!(modifier, expected_modifier),
6247+
_ => panic!("{}", sql),
6248+
};
6249+
6250+
let sql = "BEGIN DEFERRED";
6251+
check(sql, Some(TransactionModifier::Deferred));
6252+
6253+
let sql = "BEGIN DEFERRED TRANSACTION";
6254+
check(sql, Some(TransactionModifier::Deferred));
6255+
6256+
let sql = "BEGIN IMMEDIATE";
6257+
check(sql, Some(TransactionModifier::Immediate));
6258+
6259+
let sql = "BEGIN IMMEDIATE TRANSACTION";
6260+
check(sql, Some(TransactionModifier::Immediate));
6261+
6262+
let sql = "BEGIN EXCLUSIVE";
6263+
check(sql, Some(TransactionModifier::Exclusive));
6264+
6265+
let sql = "BEGIN EXCLUSIVE TRANSACTION";
6266+
check(sql, Some(TransactionModifier::Exclusive));
6267+
}
6268+
62356269
#[test]
62366270
fn parse_set_transaction() {
62376271
// SET TRANSACTION shares transaction mode parsing code with START

0 commit comments

Comments
 (0)