Skip to content
This repository was archived by the owner on Dec 25, 2019. It is now read-only.

Commit ec438f2

Browse files
author
JLDLaughlin
committed
WIP: Parse positional parameters
1 parent 2b70cac commit ec438f2

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

src/parser.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@ impl Parser {
256256
expr: Box::new(self.parse_subexpr(Self::PLUS_MINUS_PREC)?),
257257
})
258258
}
259-
Token::Number(_)
259+
Token::Parameter(_)
260+
| Token::Number(_)
260261
| Token::SingleQuotedString(_)
261262
| Token::NationalStringLiteral(_)
262263
| Token::HexStringLiteral(_) => {

src/tokenizer.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ pub enum Token {
3838
NationalStringLiteral(String),
3939
/// Hexadecimal string literal: i.e.: X'deadbeef'
4040
HexStringLiteral(String),
41+
/// An unsigned numeric literal representing positional
42+
/// parameters like $1, $2, etc. in prepared statements and
43+
/// function definitions
44+
Parameter(String),
4145
/// Comma
4246
Comma,
4347
/// Whitespace (space, tab, etc)
@@ -99,6 +103,7 @@ impl fmt::Display for Token {
99103
Token::SingleQuotedString(ref s) => write!(f, "'{}'", s),
100104
Token::NationalStringLiteral(ref s) => write!(f, "N'{}'", s),
101105
Token::HexStringLiteral(ref s) => write!(f, "X'{}'", s),
106+
Token::Parameter(ref s) => write!(f, "$'{}'", s),
102107
Token::Comma => f.write_str(","),
103108
Token::Whitespace(ws) => write!(f, "{}", ws),
104109
Token::Eq => f.write_str("="),
@@ -249,6 +254,7 @@ impl<'a> Tokenizer<'a> {
249254
Token::Word(w) if w.quote_style != None => self.col += w.value.len() as u64 + 2,
250255
Token::Number(s) => self.col += s.len() as u64,
251256
Token::SingleQuotedString(s) => self.col += s.len() as u64,
257+
Token::Parameter(s) => self.col += s.len() as u64,
252258
_ => self.col += 1,
253259
}
254260

@@ -259,7 +265,7 @@ impl<'a> Tokenizer<'a> {
259265

260266
/// Get the next token or return None
261267
fn next_token(&self, chars: &mut Peekable<Chars<'_>>) -> Result<Option<Token>, TokenizerError> {
262-
//println!("next_token: {:?}", chars.peek());
268+
// println!("next_token: {:?}", chars.peek());
263269
match chars.peek() {
264270
Some(&ch) => match ch {
265271
' ' => self.consume_and_return(chars, Token::Whitespace(Whitespace::Space)),
@@ -415,6 +421,7 @@ impl<'a> Tokenizer<'a> {
415421
'&' => self.consume_and_return(chars, Token::Ampersand),
416422
'{' => self.consume_and_return(chars, Token::LBrace),
417423
'}' => self.consume_and_return(chars, Token::RBrace),
424+
'$' => self.tokenize_positional_parameter(chars),
418425
other => self.consume_and_return(chars, Token::Char(other)),
419426
},
420427
None => Ok(None),
@@ -490,6 +497,27 @@ impl<'a> Tokenizer<'a> {
490497
}
491498
}
492499

500+
/// PostgreSQL supports positional parameters (like $1, $2, etc.) for prepared statements
501+
/// and function definitions.
502+
/// Grab the positional argument following a $ to parse it.
503+
fn tokenize_positional_parameter(&self, chars: &mut Peekable<Chars<'_>>) -> Result<Option<Token>, TokenizerError> {
504+
assert_eq!(Some(&'$'), chars.peek());
505+
chars.next(); // throw away $
506+
507+
// Right now, following block copied from number parsing above...
508+
// TODO: https://jakewheat.github.io/sql-overview/sql-2011-foundation-grammar.html#unsigned-numeric-literal
509+
let position = peeking_take_while(chars, |ch| match ch {
510+
'0'..='9' | '$' => true,
511+
_ => false,
512+
});
513+
// End copied block
514+
515+
let new_token = Token::Parameter(position);
516+
println!("new token: {:#?}", new_token);
517+
518+
Ok(Some(new_token))
519+
}
520+
493521
fn consume_and_return(
494522
&self,
495523
chars: &mut Peekable<Chars<'_>>,

0 commit comments

Comments
 (0)