mirror of
				https://github.com/apache/datafusion-sqlparser-rs.git
				synced 2025-11-04 00:43:40 +00:00 
			
		
		
		
	Fix parse error on some prepared statement placeholders (#604)
sqlparser can now parse all the prepared statement placeholders supported by SQLite: - ? - ?NNN - @VVV - :VVV - $VVV See: https://www.sqlite.org/lang_expr.html#varparam This does not break existing support for postgresql's '@' operator Fixes #603
This commit is contained in:
		
							parent
							
								
									3ac1bb5b80
								
							
						
					
					
						commit
						604f755a59
					
				
					 4 changed files with 45 additions and 12 deletions
				
			
		| 
						 | 
				
			
			@ -570,7 +570,7 @@ impl<'a> Parser<'a> {
 | 
			
		|||
                    })
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            Token::Placeholder(_) => {
 | 
			
		||||
            Token::Placeholder(_) | Token::Colon | Token::AtSign => {
 | 
			
		||||
                self.prev_token();
 | 
			
		||||
                Ok(Expr::Value(self.parse_value()?))
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1774,7 +1774,7 @@ impl<'a> Parser<'a> {
 | 
			
		|||
                            .iter()
 | 
			
		||||
                            .any(|d| kw.keyword == *d) =>
 | 
			
		||||
                    {
 | 
			
		||||
                        break
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                    Token::RParen | Token::EOF => break,
 | 
			
		||||
                    _ => continue,
 | 
			
		||||
| 
						 | 
				
			
			@ -3038,6 +3038,11 @@ impl<'a> Parser<'a> {
 | 
			
		|||
            Token::EscapedStringLiteral(ref s) => Ok(Value::EscapedStringLiteral(s.to_string())),
 | 
			
		||||
            Token::HexStringLiteral(ref s) => Ok(Value::HexStringLiteral(s.to_string())),
 | 
			
		||||
            Token::Placeholder(ref s) => Ok(Value::Placeholder(s.to_string())),
 | 
			
		||||
            tok @ Token::Colon | tok @ Token::AtSign => {
 | 
			
		||||
                let ident = self.parse_identifier()?;
 | 
			
		||||
                let placeholder = tok.to_string() + &ident.value;
 | 
			
		||||
                Ok(Value::Placeholder(placeholder))
 | 
			
		||||
            }
 | 
			
		||||
            unexpected => self.expected("a value", unexpected),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -4892,12 +4897,12 @@ impl<'a> Parser<'a> {
 | 
			
		|||
                    Some(_) => {
 | 
			
		||||
                        return Err(ParserError::ParserError(
 | 
			
		||||
                            "expected UPDATE, DELETE or INSERT in merge clause".to_string(),
 | 
			
		||||
                        ))
 | 
			
		||||
                        ));
 | 
			
		||||
                    }
 | 
			
		||||
                    None => {
 | 
			
		||||
                        return Err(ParserError::ParserError(
 | 
			
		||||
                            "expected UPDATE, DELETE or INSERT in merge clause".to_string(),
 | 
			
		||||
                        ))
 | 
			
		||||
                        ));
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
            );
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -678,13 +678,14 @@ impl<'a> Tokenizer<'a> {
 | 
			
		|||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                '@' => self.consume_and_return(chars, Token::AtSign),
 | 
			
		||||
                '?' => self.consume_and_return(chars, Token::Placeholder(String::from("?"))),
 | 
			
		||||
                '?' => {
 | 
			
		||||
                    chars.next();
 | 
			
		||||
                    let s = peeking_take_while(chars, |ch| ch.is_numeric());
 | 
			
		||||
                    Ok(Some(Token::Placeholder(String::from("?") + &s)))
 | 
			
		||||
                }
 | 
			
		||||
                '$' => {
 | 
			
		||||
                    chars.next();
 | 
			
		||||
                    let s = peeking_take_while(
 | 
			
		||||
                        chars,
 | 
			
		||||
                        |ch| matches!(ch, '0'..='9' | 'A'..='Z' | 'a'..='z'),
 | 
			
		||||
                    );
 | 
			
		||||
                    let s = peeking_take_while(chars, |ch| ch.is_alphanumeric() || ch == '_');
 | 
			
		||||
                    Ok(Some(Token::Placeholder(String::from("$") + &s)))
 | 
			
		||||
                }
 | 
			
		||||
                //whitespace check (including unicode chars) should be last as it covers some of the chars above
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue