Skip to content

Commit

Permalink
parse SQLite pragma statement (apache#969)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrew Lamb <[email protected]>
  • Loading branch information
2 people authored and serprex committed Nov 6, 2023
1 parent 3f3b6f4 commit 9b3fc13
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 0 deletions.
18 changes: 18 additions & 0 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2037,6 +2037,12 @@ pub enum Statement {
name: ObjectName,
representation: UserDefinedTypeRepresentation,
},
// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
Pragma {
name: ObjectName,
value: Option<Value>,
is_eq: bool,
},

//////////////////////////////////
/// PeerDB Specific Statements ///
Expand Down Expand Up @@ -3464,6 +3470,18 @@ impl fmt::Display for Statement {
} => {
write!(f, "CREATE TYPE {name} AS {representation}")
}
Statement::Pragma { name, value, is_eq } => {
write!(f, "PRAGMA {name}")?;
if value.is_some() {
let val = value.as_ref().unwrap();
if *is_eq {
write!(f, " = {val}")?;
} else {
write!(f, "({val})")?;
}
}
Ok(())
}

//////////////////////////////////////////
// PeerDB Specific Statements
Expand Down
1 change: 1 addition & 0 deletions src/keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@ define_keywords!(
POSITION_REGEX,
POSTGRES,
POWER,
PRAGMA,
PRECEDES,
PRECEDING,
PRECISION,
Expand Down
28 changes: 28 additions & 0 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@ impl<'a> Parser<'a> {
Keyword::EXECUTE => Ok(self.parse_execute()?),
Keyword::PREPARE => Ok(self.parse_prepare()?),
Keyword::MERGE => Ok(self.parse_merge()?),
// `PRAGMA` is sqlite specific https://www.sqlite.org/pragma.html
Keyword::PRAGMA => Ok(self.parse_pragma()?),
_ => self.expected("an SQL statement", next_token),
},
Token::LParen => {
Expand Down Expand Up @@ -7550,6 +7552,32 @@ impl<'a> Parser<'a> {
})
}

// PRAGMA [schema-name '.'] pragma-name [('=' pragma-value) | '(' pragma-value ')']
pub fn parse_pragma(&mut self) -> Result<Statement, ParserError> {
let name = self.parse_object_name()?;
if self.consume_token(&Token::LParen) {
let value = self.parse_number_value()?;
self.expect_token(&Token::RParen)?;
Ok(Statement::Pragma {
name,
value: Some(value),
is_eq: false,
})
} else if self.consume_token(&Token::Eq) {
Ok(Statement::Pragma {
name,
value: Some(self.parse_number_value()?),
is_eq: true,
})
} else {
Ok(Statement::Pragma {
name,
value: None,
is_eq: false,
})
}
}

/// ```sql
/// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
/// ```
Expand Down
45 changes: 45 additions & 0 deletions tests/sqlparser_sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,51 @@ use sqlparser::ast::*;
use sqlparser::dialect::{GenericDialect, SQLiteDialect};
use sqlparser::tokenizer::Token;

#[test]
fn pragma_no_value() {
let sql = "PRAGMA cache_size";
match sqlite_and_generic().verified_stmt(sql) {
Statement::Pragma {
name,
value: None,
is_eq: false,
} => {
assert_eq!("cache_size", name.to_string());
}
_ => unreachable!(),
}
}
#[test]
fn pragma_eq_style() {
let sql = "PRAGMA cache_size = 10";
match sqlite_and_generic().verified_stmt(sql) {
Statement::Pragma {
name,
value: Some(val),
is_eq: true,
} => {
assert_eq!("cache_size", name.to_string());
assert_eq!("10", val.to_string());
}
_ => unreachable!(),
}
}
#[test]
fn pragma_funciton_style() {
let sql = "PRAGMA cache_size(10)";
match sqlite_and_generic().verified_stmt(sql) {
Statement::Pragma {
name,
value: Some(val),
is_eq: false,
} => {
assert_eq!("cache_size", name.to_string());
assert_eq!("10", val.to_string());
}
_ => unreachable!(),
}
}

#[test]
fn parse_create_table_without_rowid() {
let sql = "CREATE TABLE t (a INT) WITHOUT ROWID";
Expand Down

0 comments on commit 9b3fc13

Please sign in to comment.