From 48d5faa8e37f12f7779b33dcbb8f537bbbd03fd1 Mon Sep 17 00:00:00 2001 From: Ilya Date: Sun, 17 Sep 2023 14:34:56 +0300 Subject: [PATCH 1/3] parse SQLite pragma statement --- src/ast/mod.rs | 23 ++++++++++++++++ src/keywords.rs | 1 + src/parser/mod.rs | 28 +++++++++++++++++++ tests/sqlparser_sqlite.rs | 57 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index eb8830bb1..d779a8096 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1806,6 +1806,13 @@ pub enum Statement { name: ObjectName, representation: UserDefinedTypeRepresentation, }, + // PRAGMA . = + Pragma { + name: ObjectName, + value: Option, + is_eq: bool + } + } impl fmt::Display for Statement { @@ -3143,6 +3150,22 @@ 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(()) + } } } } diff --git a/src/keywords.rs b/src/keywords.rs index ad0526ccd..9452f07e2 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -467,6 +467,7 @@ define_keywords!( POSITION, POSITION_REGEX, POWER, + PRAGMA, PRECEDES, PRECEDING, PRECISION, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index ba8f5784f..6ed5475dc 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -490,6 +490,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 => { @@ -7297,6 +7299,32 @@ impl<'a> Parser<'a> { }) } + // PRAGMA [schema-name '.'] pragma-name [('=' pragma-value) | '(' pragma-value ')'] + pub fn parse_pragma(&mut self) -> Result { + 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 ] /// ``` diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index 8f6cc7572..775a782ac 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -24,6 +24,63 @@ use sqlparser::ast::*; use sqlparser::dialect::{GenericDialect, SQLiteDialect}; use sqlparser::tokenizer::Token; +#[test] +fn bool_equality() { + let sql = "SELECT a==b FROM t"; + sqlite_and_generic().verified_stmt(sql); +} + +#[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 column_witout_type_affinity() { + let sql = "CREATE TABLE t1(x)"; + sqlite_and_generic().verified_stmt(sql); +} + #[test] fn parse_create_table_without_rowid() { let sql = "CREATE TABLE t (a INT) WITHOUT ROWID"; From 4e3617554e06149b05f192bc1a8bb989d22233c5 Mon Sep 17 00:00:00 2001 From: Ilya Date: Sun, 17 Sep 2023 14:41:59 +0300 Subject: [PATCH 2/3] remove tests meant for another PR --- tests/sqlparser_sqlite.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs index 775a782ac..7f356b879 100644 --- a/tests/sqlparser_sqlite.rs +++ b/tests/sqlparser_sqlite.rs @@ -24,12 +24,6 @@ use sqlparser::ast::*; use sqlparser::dialect::{GenericDialect, SQLiteDialect}; use sqlparser::tokenizer::Token; -#[test] -fn bool_equality() { - let sql = "SELECT a==b FROM t"; - sqlite_and_generic().verified_stmt(sql); -} - #[test] fn pragma_no_value() { let sql = "PRAGMA cache_size"; @@ -75,12 +69,6 @@ fn pragma_funciton_style() { } } -#[test] -fn column_witout_type_affinity() { - let sql = "CREATE TABLE t1(x)"; - sqlite_and_generic().verified_stmt(sql); -} - #[test] fn parse_create_table_without_rowid() { let sql = "CREATE TABLE t (a INT) WITHOUT ROWID"; From 12573870376757fc86142737d7df70a59e1eefec Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Thu, 5 Oct 2023 15:29:36 -0400 Subject: [PATCH 3/3] Check in `cargo fmt` --- src/ast/mod.rs | 11 +++-------- src/parser/mod.rs | 2 +- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/ast/mod.rs b/src/ast/mod.rs index da80ff368..06841efa9 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1826,9 +1826,8 @@ pub enum Statement { Pragma { name: ObjectName, value: Option, - is_eq: bool - } - + is_eq: bool, + }, } impl fmt::Display for Statement { @@ -3187,11 +3186,7 @@ impl fmt::Display for Statement { } => { write!(f, "CREATE TYPE {name} AS {representation}") } - Statement::Pragma { - name, - value, - is_eq - } => { + Statement::Pragma { name, value, is_eq } => { write!(f, "PRAGMA {name}")?; if value.is_some() { let val = value.as_ref().unwrap(); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 065212343..75e47afac 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -7418,7 +7418,7 @@ impl<'a> Parser<'a> { Ok(Statement::Pragma { name, value: None, - is_eq: false + is_eq: false, }) } }