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
|
/// deleted along with the dropped table
|
||||||
purge: bool,
|
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
|
/// FETCH - retrieve rows from a query using a cursor
|
||||||
///
|
///
|
||||||
/// Note: this is a PostgreSQL-specific statement,
|
/// Note: this is a PostgreSQL-specific statement,
|
||||||
|
@ -1125,6 +1148,48 @@ impl fmt::Display for Statement {
|
||||||
write!(f, "{}", statement)
|
write!(f, "{}", statement)
|
||||||
}
|
}
|
||||||
Statement::Query(s) => write!(f, "{}", s),
|
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 {
|
Statement::Fetch {
|
||||||
name,
|
name,
|
||||||
direction,
|
direction,
|
||||||
|
|
|
@ -167,6 +167,7 @@ impl<'a> Parser<'a> {
|
||||||
Keyword::CREATE => Ok(self.parse_create()?),
|
Keyword::CREATE => Ok(self.parse_create()?),
|
||||||
Keyword::DROP => Ok(self.parse_drop()?),
|
Keyword::DROP => Ok(self.parse_drop()?),
|
||||||
Keyword::DISCARD => Ok(self.parse_discard()?),
|
Keyword::DISCARD => Ok(self.parse_discard()?),
|
||||||
|
Keyword::DECLARE => Ok(self.parse_declare()?),
|
||||||
Keyword::FETCH => Ok(self.parse_fetch_statement()?),
|
Keyword::FETCH => Ok(self.parse_fetch_statement()?),
|
||||||
Keyword::DELETE => Ok(self.parse_delete()?),
|
Keyword::DELETE => Ok(self.parse_delete()?),
|
||||||
Keyword::INSERT => Ok(self.parse_insert()?),
|
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;
|
// FETCH [ direction { FROM | IN } ] cursor INTO target;
|
||||||
pub fn parse_fetch_statement(&mut self) -> Result<Statement, ParserError> {
|
pub fn parse_fetch_statement(&mut self) -> Result<Statement, ParserError> {
|
||||||
let direction = if self.parse_keyword(Keyword::NEXT) {
|
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]
|
#[test]
|
||||||
fn parse_fetch() {
|
fn parse_fetch() {
|
||||||
pg_and_generic().verified_stmt("FETCH 2048 IN \"SQL_CUR0x7fa44801bc00\"");
|
pg_and_generic().verified_stmt("FETCH 2048 IN \"SQL_CUR0x7fa44801bc00\"");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue