mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-08-22 15:04:04 +00:00
feat: Initial support for DECLARE (cursors) (#509)
This commit is contained in:
parent
66a3082cb6
commit
3f1c6426f0
3 changed files with 133 additions and 0 deletions
|
@ -895,6 +895,29 @@ pub enum Statement {
|
|||
/// deleted along with the dropped table
|
||||
purge: bool,
|
||||
},
|
||||
/// DECLARE - Declaring Cursor Variables
|
||||
///
|
||||
/// Note: this is a PostgreSQL-specific statement,
|
||||
/// but may also compatible with other SQL.
|
||||
Declare {
|
||||
/// Cursor name
|
||||
name: Ident,
|
||||
/// Causes the cursor to return data in binary rather than in text format.
|
||||
binary: bool,
|
||||
/// None = Not specified
|
||||
/// Some(true) = INSENSITIVE
|
||||
/// Some(false) = ASENSITIVE
|
||||
sensitive: Option<bool>,
|
||||
/// None = Not specified
|
||||
/// Some(true) = SCROLL
|
||||
/// Some(false) = NO SCROLL
|
||||
scroll: Option<bool>,
|
||||
/// None = Not specified
|
||||
/// Some(true) = WITH HOLD, specifies that the cursor can continue to be used after the transaction that created it successfully commits
|
||||
/// Some(false) = WITHOUT HOLD, specifies that the cursor cannot be used outside of the transaction that created it
|
||||
hold: Option<bool>,
|
||||
query: Box<Query>,
|
||||
},
|
||||
/// FETCH - retrieve rows from a query using a cursor
|
||||
///
|
||||
/// Note: this is a PostgreSQL-specific statement,
|
||||
|
@ -1125,6 +1148,48 @@ impl fmt::Display for Statement {
|
|||
write!(f, "{}", statement)
|
||||
}
|
||||
Statement::Query(s) => write!(f, "{}", s),
|
||||
Statement::Declare {
|
||||
name,
|
||||
binary,
|
||||
sensitive,
|
||||
scroll,
|
||||
hold,
|
||||
query,
|
||||
} => {
|
||||
write!(f, "DECLARE {} ", name)?;
|
||||
|
||||
if *binary {
|
||||
write!(f, "BINARY ")?;
|
||||
}
|
||||
|
||||
if let Some(sensitive) = sensitive {
|
||||
if *sensitive {
|
||||
write!(f, "INSENSITIVE ")?;
|
||||
} else {
|
||||
write!(f, "ASENSITIVE ")?;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(scroll) = scroll {
|
||||
if *scroll {
|
||||
write!(f, "SCROLL ")?;
|
||||
} else {
|
||||
write!(f, "NO SCROLL ")?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "CURSOR ")?;
|
||||
|
||||
if let Some(hold) = hold {
|
||||
if *hold {
|
||||
write!(f, "WITH HOLD ")?;
|
||||
} else {
|
||||
write!(f, "WITHOUT HOLD ")?;
|
||||
}
|
||||
}
|
||||
|
||||
write!(f, "FOR {}", query)
|
||||
}
|
||||
Statement::Fetch {
|
||||
name,
|
||||
direction,
|
||||
|
|
|
@ -167,6 +167,7 @@ impl<'a> Parser<'a> {
|
|||
Keyword::CREATE => Ok(self.parse_create()?),
|
||||
Keyword::DROP => Ok(self.parse_drop()?),
|
||||
Keyword::DISCARD => Ok(self.parse_discard()?),
|
||||
Keyword::DECLARE => Ok(self.parse_declare()?),
|
||||
Keyword::FETCH => Ok(self.parse_fetch_statement()?),
|
||||
Keyword::DELETE => Ok(self.parse_delete()?),
|
||||
Keyword::INSERT => Ok(self.parse_insert()?),
|
||||
|
@ -1825,6 +1826,56 @@ impl<'a> Parser<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// DECLARE name [ BINARY ] [ ASENSITIVE | INSENSITIVE ] [ [ NO ] SCROLL ]
|
||||
// CURSOR [ { WITH | WITHOUT } HOLD ] FOR query
|
||||
pub fn parse_declare(&mut self) -> Result<Statement, ParserError> {
|
||||
let name = self.parse_identifier()?;
|
||||
|
||||
let binary = self.parse_keyword(Keyword::BINARY);
|
||||
let sensitive = if self.parse_keyword(Keyword::INSENSITIVE) {
|
||||
Some(true)
|
||||
} else if self.parse_keyword(Keyword::ASENSITIVE) {
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let scroll = if self.parse_keyword(Keyword::SCROLL) {
|
||||
Some(true)
|
||||
} else if self.parse_keywords(&[Keyword::NO, Keyword::SCROLL]) {
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.expect_keyword(Keyword::CURSOR)?;
|
||||
|
||||
let hold = match self.parse_one_of_keywords(&[Keyword::WITH, Keyword::WITHOUT]) {
|
||||
Some(keyword) => {
|
||||
self.expect_keyword(Keyword::HOLD)?;
|
||||
|
||||
match keyword {
|
||||
Keyword::WITH => Some(true),
|
||||
Keyword::WITHOUT => Some(false),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
|
||||
self.expect_keyword(Keyword::FOR)?;
|
||||
|
||||
let query = self.parse_query()?;
|
||||
|
||||
Ok(Statement::Declare {
|
||||
name,
|
||||
binary,
|
||||
sensitive,
|
||||
scroll,
|
||||
hold,
|
||||
query: Box::new(query),
|
||||
})
|
||||
}
|
||||
|
||||
// FETCH [ direction { FROM | IN } ] cursor INTO target;
|
||||
pub fn parse_fetch_statement(&mut self) -> Result<Statement, ParserError> {
|
||||
let direction = if self.parse_keyword(Keyword::NEXT) {
|
||||
|
|
|
@ -1514,6 +1514,23 @@ fn parse_escaped_literal_string() {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_declare() {
|
||||
pg_and_generic()
|
||||
.verified_stmt("DECLARE \"SQL_CUR0x7fa44801bc00\" CURSOR WITH HOLD FOR SELECT 1");
|
||||
pg_and_generic()
|
||||
.verified_stmt("DECLARE \"SQL_CUR0x7fa44801bc00\" CURSOR WITHOUT HOLD FOR SELECT 1");
|
||||
pg_and_generic().verified_stmt("DECLARE \"SQL_CUR0x7fa44801bc00\" BINARY CURSOR FOR SELECT 1");
|
||||
pg_and_generic()
|
||||
.verified_stmt("DECLARE \"SQL_CUR0x7fa44801bc00\" ASENSITIVE CURSOR FOR SELECT 1");
|
||||
pg_and_generic()
|
||||
.verified_stmt("DECLARE \"SQL_CUR0x7fa44801bc00\" INSENSITIVE CURSOR FOR SELECT 1");
|
||||
pg_and_generic().verified_stmt("DECLARE \"SQL_CUR0x7fa44801bc00\" SCROLL CURSOR FOR SELECT 1");
|
||||
pg_and_generic()
|
||||
.verified_stmt("DECLARE \"SQL_CUR0x7fa44801bc00\" NO SCROLL CURSOR FOR SELECT 1");
|
||||
pg_and_generic().verified_stmt("DECLARE \"SQL_CUR0x7fa44801bc00\" BINARY INSENSITIVE SCROLL CURSOR WITH HOLD FOR SELECT * FROM table_name LIMIT 2222");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_fetch() {
|
||||
pg_and_generic().verified_stmt("FETCH 2048 IN \"SQL_CUR0x7fa44801bc00\"");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue