mirror of
https://github.com/apache/datafusion-sqlparser-rs.git
synced 2025-09-11 00:16:21 +00:00
Support hexadecimal string literals
This commit is contained in:
parent
2308c1c6f7
commit
eba3983268
4 changed files with 36 additions and 3 deletions
|
@ -9,6 +9,8 @@ pub enum Value {
|
||||||
SingleQuotedString(String),
|
SingleQuotedString(String),
|
||||||
/// N'string value'
|
/// N'string value'
|
||||||
NationalStringLiteral(String),
|
NationalStringLiteral(String),
|
||||||
|
/// X'hex value'
|
||||||
|
HexStringLiteral(String),
|
||||||
/// Boolean value true or false
|
/// Boolean value true or false
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
/// NULL value in insert statements,
|
/// NULL value in insert statements,
|
||||||
|
@ -22,6 +24,7 @@ impl ToString for Value {
|
||||||
Value::Double(v) => v.to_string(),
|
Value::Double(v) => v.to_string(),
|
||||||
Value::SingleQuotedString(v) => format!("'{}'", escape_single_quote_string(v)),
|
Value::SingleQuotedString(v) => format!("'{}'", escape_single_quote_string(v)),
|
||||||
Value::NationalStringLiteral(v) => format!("N'{}'", v),
|
Value::NationalStringLiteral(v) => format!("N'{}'", v),
|
||||||
|
Value::HexStringLiteral(v) => format!("X'{}'", v),
|
||||||
Value::Boolean(v) => v.to_string(),
|
Value::Boolean(v) => v.to_string(),
|
||||||
Value::Null => "NULL".to_string(),
|
Value::Null => "NULL".to_string(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -238,7 +238,10 @@ impl Parser {
|
||||||
expr: Box::new(self.parse_subexpr(Self::PLUS_MINUS_PREC)?),
|
expr: Box::new(self.parse_subexpr(Self::PLUS_MINUS_PREC)?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Token::Number(_) | Token::SingleQuotedString(_) | Token::NationalStringLiteral(_) => {
|
Token::Number(_)
|
||||||
|
| Token::SingleQuotedString(_)
|
||||||
|
| Token::NationalStringLiteral(_)
|
||||||
|
| Token::HexStringLiteral(_) => {
|
||||||
self.prev_token();
|
self.prev_token();
|
||||||
self.parse_sql_value()
|
self.parse_sql_value()
|
||||||
}
|
}
|
||||||
|
@ -1037,6 +1040,7 @@ impl Parser {
|
||||||
Token::NationalStringLiteral(ref s) => {
|
Token::NationalStringLiteral(ref s) => {
|
||||||
Ok(Value::NationalStringLiteral(s.to_string()))
|
Ok(Value::NationalStringLiteral(s.to_string()))
|
||||||
}
|
}
|
||||||
|
Token::HexStringLiteral(ref s) => Ok(Value::HexStringLiteral(s.to_string())),
|
||||||
_ => parser_err!(format!("Unsupported value: {:?}", t)),
|
_ => parser_err!(format!("Unsupported value: {:?}", t)),
|
||||||
},
|
},
|
||||||
None => parser_err!("Expecting a value, but found EOF"),
|
None => parser_err!("Expecting a value, but found EOF"),
|
||||||
|
|
|
@ -37,6 +37,8 @@ pub enum Token {
|
||||||
SingleQuotedString(String),
|
SingleQuotedString(String),
|
||||||
/// "National" string literal: i.e: N'string'
|
/// "National" string literal: i.e: N'string'
|
||||||
NationalStringLiteral(String),
|
NationalStringLiteral(String),
|
||||||
|
/// Hexadecimal string literal: i.e.: X'deadbeef'
|
||||||
|
HexStringLiteral(String),
|
||||||
/// Comma
|
/// Comma
|
||||||
Comma,
|
Comma,
|
||||||
/// Whitespace (space, tab, etc)
|
/// Whitespace (space, tab, etc)
|
||||||
|
@ -97,6 +99,7 @@ impl ToString for Token {
|
||||||
Token::Char(ref c) => c.to_string(),
|
Token::Char(ref c) => c.to_string(),
|
||||||
Token::SingleQuotedString(ref s) => format!("'{}'", s),
|
Token::SingleQuotedString(ref s) => format!("'{}'", s),
|
||||||
Token::NationalStringLiteral(ref s) => format!("N'{}'", s),
|
Token::NationalStringLiteral(ref s) => format!("N'{}'", s),
|
||||||
|
Token::HexStringLiteral(ref s) => format!("X'{}'", s),
|
||||||
Token::Comma => ",".to_string(),
|
Token::Comma => ",".to_string(),
|
||||||
Token::Whitespace(ws) => ws.to_string(),
|
Token::Whitespace(ws) => ws.to_string(),
|
||||||
Token::Eq => "=".to_string(),
|
Token::Eq => "=".to_string(),
|
||||||
|
@ -286,6 +289,23 @@ impl<'a> Tokenizer<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// The spec only allows an uppercase 'X' to introduce a hex
|
||||||
|
// string, but PostgreSQL, at least, allows a lowercase 'x' too.
|
||||||
|
x @ 'x' | x @ 'X' => {
|
||||||
|
chars.next(); // consume, to check the next char
|
||||||
|
match chars.peek() {
|
||||||
|
Some('\'') => {
|
||||||
|
// X'...' - a <binary string literal>
|
||||||
|
let s = self.tokenize_single_quoted_string(chars);
|
||||||
|
Ok(Some(Token::HexStringLiteral(s)))
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// regular identifier starting with an "X"
|
||||||
|
let s = self.tokenize_word(x, chars);
|
||||||
|
Ok(Some(Token::make_word(&s, None)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// identifier or keyword
|
// identifier or keyword
|
||||||
ch if self.dialect.is_identifier_start(ch) => {
|
ch if self.dialect.is_identifier_start(ch) => {
|
||||||
chars.next(); // consume the first char
|
chars.next(); // consume the first char
|
||||||
|
|
|
@ -923,9 +923,9 @@ fn parse_aggregate_with_group_by() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_literal_string() {
|
fn parse_literal_string() {
|
||||||
let sql = "SELECT 'one', N'national string'";
|
let sql = "SELECT 'one', N'national string', X'deadBEEF'";
|
||||||
let select = verified_only_select(sql);
|
let select = verified_only_select(sql);
|
||||||
assert_eq!(2, select.projection.len());
|
assert_eq!(3, select.projection.len());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
&ASTNode::SQLValue(Value::SingleQuotedString("one".to_string())),
|
&ASTNode::SQLValue(Value::SingleQuotedString("one".to_string())),
|
||||||
expr_from_projection(&select.projection[0])
|
expr_from_projection(&select.projection[0])
|
||||||
|
@ -934,6 +934,12 @@ fn parse_literal_string() {
|
||||||
&ASTNode::SQLValue(Value::NationalStringLiteral("national string".to_string())),
|
&ASTNode::SQLValue(Value::NationalStringLiteral("national string".to_string())),
|
||||||
expr_from_projection(&select.projection[1])
|
expr_from_projection(&select.projection[1])
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
&ASTNode::SQLValue(Value::HexStringLiteral("deadBEEF".to_string())),
|
||||||
|
expr_from_projection(&select.projection[2])
|
||||||
|
);
|
||||||
|
|
||||||
|
one_statement_parses_to("SELECT x'deadBEEF'", "SELECT X'deadBEEF'");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue