Skip to content

Commit 8b2a248

Browse files
marhoilyalamb
andauthored
parse SQLite pragma statement (apache#969)
Co-authored-by: Andrew Lamb <[email protected]>
1 parent 2798b65 commit 8b2a248

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

src/ast/mod.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1914,6 +1914,12 @@ pub enum Statement {
19141914
name: ObjectName,
19151915
representation: UserDefinedTypeRepresentation,
19161916
},
1917+
// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
1918+
Pragma {
1919+
name: ObjectName,
1920+
value: Option<Value>,
1921+
is_eq: bool,
1922+
},
19171923
}
19181924

19191925
impl fmt::Display for Statement {
@@ -3276,6 +3282,18 @@ impl fmt::Display for Statement {
32763282
} => {
32773283
write!(f, "CREATE TYPE {name} AS {representation}")
32783284
}
3285+
Statement::Pragma { name, value, is_eq } => {
3286+
write!(f, "PRAGMA {name}")?;
3287+
if value.is_some() {
3288+
let val = value.as_ref().unwrap();
3289+
if *is_eq {
3290+
write!(f, " = {val}")?;
3291+
} else {
3292+
write!(f, "({val})")?;
3293+
}
3294+
}
3295+
Ok(())
3296+
}
32793297
}
32803298
}
32813299
}

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ define_keywords!(
472472
POSITION,
473473
POSITION_REGEX,
474474
POWER,
475+
PRAGMA,
475476
PRECEDES,
476477
PRECEDING,
477478
PRECISION,

src/parser/mod.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,8 @@ impl<'a> Parser<'a> {
491491
Keyword::EXECUTE => Ok(self.parse_execute()?),
492492
Keyword::PREPARE => Ok(self.parse_prepare()?),
493493
Keyword::MERGE => Ok(self.parse_merge()?),
494+
// `PRAGMA` is sqlite specific https://www.sqlite.org/pragma.html
495+
Keyword::PRAGMA => Ok(self.parse_pragma()?),
494496
_ => self.expected("an SQL statement", next_token),
495497
},
496498
Token::LParen => {
@@ -7502,6 +7504,32 @@ impl<'a> Parser<'a> {
75027504
})
75037505
}
75047506

7507+
// PRAGMA [schema-name '.'] pragma-name [('=' pragma-value) | '(' pragma-value ')']
7508+
pub fn parse_pragma(&mut self) -> Result<Statement, ParserError> {
7509+
let name = self.parse_object_name()?;
7510+
if self.consume_token(&Token::LParen) {
7511+
let value = self.parse_number_value()?;
7512+
self.expect_token(&Token::RParen)?;
7513+
Ok(Statement::Pragma {
7514+
name,
7515+
value: Some(value),
7516+
is_eq: false,
7517+
})
7518+
} else if self.consume_token(&Token::Eq) {
7519+
Ok(Statement::Pragma {
7520+
name,
7521+
value: Some(self.parse_number_value()?),
7522+
is_eq: true,
7523+
})
7524+
} else {
7525+
Ok(Statement::Pragma {
7526+
name,
7527+
value: None,
7528+
is_eq: false,
7529+
})
7530+
}
7531+
}
7532+
75057533
/// ```sql
75067534
/// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
75077535
/// ```

tests/sqlparser_sqlite.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,51 @@ use sqlparser::ast::*;
2424
use sqlparser::dialect::{GenericDialect, SQLiteDialect};
2525
use sqlparser::tokenizer::Token;
2626

27+
#[test]
28+
fn pragma_no_value() {
29+
let sql = "PRAGMA cache_size";
30+
match sqlite_and_generic().verified_stmt(sql) {
31+
Statement::Pragma {
32+
name,
33+
value: None,
34+
is_eq: false,
35+
} => {
36+
assert_eq!("cache_size", name.to_string());
37+
}
38+
_ => unreachable!(),
39+
}
40+
}
41+
#[test]
42+
fn pragma_eq_style() {
43+
let sql = "PRAGMA cache_size = 10";
44+
match sqlite_and_generic().verified_stmt(sql) {
45+
Statement::Pragma {
46+
name,
47+
value: Some(val),
48+
is_eq: true,
49+
} => {
50+
assert_eq!("cache_size", name.to_string());
51+
assert_eq!("10", val.to_string());
52+
}
53+
_ => unreachable!(),
54+
}
55+
}
56+
#[test]
57+
fn pragma_funciton_style() {
58+
let sql = "PRAGMA cache_size(10)";
59+
match sqlite_and_generic().verified_stmt(sql) {
60+
Statement::Pragma {
61+
name,
62+
value: Some(val),
63+
is_eq: false,
64+
} => {
65+
assert_eq!("cache_size", name.to_string());
66+
assert_eq!("10", val.to_string());
67+
}
68+
_ => unreachable!(),
69+
}
70+
}
71+
2772
#[test]
2873
fn parse_create_table_without_rowid() {
2974
let sql = "CREATE TABLE t (a INT) WITHOUT ROWID";

0 commit comments

Comments
 (0)