Merge pull request #36 from nickolay/strings

Clean up string-related variants in Token and Value
This commit is contained in:
Andy Grove 2019-03-08 06:14:59 -07:00 committed by GitHub
commit 73f55fe1bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 11 additions and 29 deletions

View file

@ -103,7 +103,7 @@ pub enum ASTNode {
/// COLUMNS /// COLUMNS
columns: Vec<String>, columns: Vec<String>,
/// VALUES a vector of values to be copied /// VALUES a vector of values to be copied
values: Vec<Value>, values: Vec<Option<String>>,
}, },
/// UPDATE /// UPDATE
SQLUpdate { SQLUpdate {
@ -290,7 +290,7 @@ impl ToString for ASTNode {
"\n{}", "\n{}",
values values
.iter() .iter()
.map(|v| v.to_string()) .map(|v| v.clone().unwrap_or("\\N".to_string()))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("\t") .join("\t")
); );

View file

@ -2,21 +2,17 @@ use chrono::{offset::FixedOffset, DateTime, NaiveDate, NaiveDateTime, NaiveTime}
use uuid::Uuid; use uuid::Uuid;
/// SQL values such as int, double, string timestamp /// SQL values such as int, double, string, timestamp
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Value { pub enum Value {
/// Literal signed long /// Literal signed long
Long(i64), Long(i64),
/// Literal floating point value /// Literal floating point value
Double(f64), Double(f64),
/// Unquoted string
String(String),
/// Uuid value /// Uuid value
Uuid(Uuid), Uuid(Uuid),
/// 'string value' /// 'string value'
SingleQuotedString(String), SingleQuotedString(String),
/// "string value"
DoubleQuotedString(String),
/// Boolean value true or false, /// Boolean value true or false,
Boolean(bool), Boolean(bool),
/// Date value /// Date value
@ -36,10 +32,8 @@ impl ToString for Value {
match self { match self {
Value::Long(v) => v.to_string(), Value::Long(v) => v.to_string(),
Value::Double(v) => v.to_string(), Value::Double(v) => v.to_string(),
Value::String(v) => v.to_string(),
Value::Uuid(v) => v.to_string(), Value::Uuid(v) => v.to_string(),
Value::SingleQuotedString(v) => format!("'{}'", v), Value::SingleQuotedString(v) => format!("'{}'", v),
Value::DoubleQuotedString(v) => format!("\"{}\"", v),
Value::Boolean(v) => v.to_string(), Value::Boolean(v) => v.to_string(),
Value::Date(v) => v.to_string(), Value::Date(v) => v.to_string(),
Value::Time(v) => v.to_string(), Value::Time(v) => v.to_string(),

View file

@ -157,10 +157,7 @@ impl Parser {
} }
} }
} }
Token::Number(_) Token::Number(_) | Token::SingleQuotedString(_) => {
| Token::String(_)
| Token::SingleQuotedString(_)
| Token::DoubleQuotedString(_) => {
self.prev_token(); self.prev_token();
self.parse_sql_value() self.parse_sql_value()
} }
@ -693,7 +690,7 @@ impl Parser {
/// Parse a tab separated values in /// Parse a tab separated values in
/// COPY payload /// COPY payload
fn parse_tsv(&mut self) -> Result<Vec<Value>, ParserError> { fn parse_tsv(&mut self) -> Result<Vec<Option<String>>, ParserError> {
let values = self.parse_tab_value()?; let values = self.parse_tab_value()?;
Ok(values) Ok(values)
} }
@ -702,17 +699,17 @@ impl Parser {
Ok(ASTNode::SQLValue(self.parse_value()?)) Ok(ASTNode::SQLValue(self.parse_value()?))
} }
fn parse_tab_value(&mut self) -> Result<Vec<Value>, ParserError> { fn parse_tab_value(&mut self) -> Result<Vec<Option<String>>, ParserError> {
let mut values = vec![]; let mut values = vec![];
let mut content = String::from(""); let mut content = String::from("");
while let Some(t) = self.next_token_no_skip() { while let Some(t) = self.next_token_no_skip() {
match t { match t {
Token::Whitespace(Whitespace::Tab) => { Token::Whitespace(Whitespace::Tab) => {
values.push(Value::String(content.to_string())); values.push(Some(content.to_string()));
content.clear(); content.clear();
} }
Token::Whitespace(Whitespace::Newline) => { Token::Whitespace(Whitespace::Newline) => {
values.push(Value::String(content.to_string())); values.push(Some(content.to_string()));
content.clear(); content.clear();
} }
Token::Backslash => { Token::Backslash => {
@ -721,7 +718,7 @@ impl Parser {
} }
if let Some(token) = self.next_token() { if let Some(token) = self.next_token() {
if token == Token::Identifier("N".to_string()) { if token == Token::Identifier("N".to_string()) {
values.push(Value::Null); values.push(None);
} }
} else { } else {
continue; continue;
@ -735,6 +732,7 @@ impl Parser {
Ok(values) Ok(values)
} }
/// Parse a literal value (numbers, strings, date/time, booleans)
fn parse_value(&mut self) -> Result<Value, ParserError> { fn parse_value(&mut self) -> Result<Value, ParserError> {
match self.next_token() { match self.next_token() {
Some(t) => { Some(t) => {
@ -754,14 +752,9 @@ impl Parser {
Ok(n) => Ok(Value::Long(n)), Ok(n) => Ok(Value::Long(n)),
Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)), Err(e) => parser_err!(format!("Could not parse '{}' as i64: {}", n, e)),
}, },
Token::Identifier(id) => Ok(Value::String(id.to_string())),
Token::String(ref s) => Ok(Value::String(s.to_string())),
Token::SingleQuotedString(ref s) => { Token::SingleQuotedString(ref s) => {
Ok(Value::SingleQuotedString(s.to_string())) Ok(Value::SingleQuotedString(s.to_string()))
} }
Token::DoubleQuotedString(ref s) => {
Ok(Value::DoubleQuotedString(s.to_string()))
}
_ => parser_err!(format!("Unsupported value: {:?}", self.peek_token())), _ => parser_err!(format!("Unsupported value: {:?}", self.peek_token())),
} }
} }
@ -792,9 +785,7 @@ impl Parser {
/// Parse a literal string /// Parse a literal string
pub fn parse_literal_string(&mut self) -> Result<String, ParserError> { pub fn parse_literal_string(&mut self) -> Result<String, ParserError> {
match self.next_token() { match self.next_token() {
Some(Token::String(ref s)) => Ok(s.clone()),
Some(Token::SingleQuotedString(ref s)) => Ok(s.clone()), Some(Token::SingleQuotedString(ref s)) => Ok(s.clone()),
Some(Token::DoubleQuotedString(ref s)) => Ok(s.clone()),
other => parser_err!(format!("Expected literal string, found {:?}", other)), other => parser_err!(format!("Expected literal string, found {:?}", other)),
} }
} }

View file

@ -32,8 +32,7 @@ pub enum Token {
Keyword(String), Keyword(String),
/// Numeric literal /// Numeric literal
Number(String), Number(String),
/// String literal /// A character that could not be tokenized
String(String),
Char(char), Char(char),
/// Single quoted string: i.e: 'string' /// Single quoted string: i.e: 'string'
SingleQuotedString(String), SingleQuotedString(String),
@ -97,7 +96,6 @@ impl ToString for Token {
Token::Identifier(ref id) => id.to_string(), Token::Identifier(ref id) => id.to_string(),
Token::Keyword(ref k) => k.to_string(), Token::Keyword(ref k) => k.to_string(),
Token::Number(ref n) => n.to_string(), Token::Number(ref n) => n.to_string(),
Token::String(ref s) => s.to_string(),
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::DoubleQuotedString(ref s) => format!("\"{}\"", s), Token::DoubleQuotedString(ref s) => format!("\"{}\"", s),
@ -194,7 +192,6 @@ impl<'a> Tokenizer<'a> {
Token::Identifier(s) => self.col += s.len() as u64, Token::Identifier(s) => self.col += s.len() as u64,
Token::Keyword(s) => self.col += s.len() as u64, Token::Keyword(s) => self.col += s.len() as u64,
Token::Number(s) => self.col += s.len() as u64, Token::Number(s) => self.col += s.len() as u64,
Token::String(s) => self.col += s.len() as u64,
Token::SingleQuotedString(s) => self.col += s.len() as u64, Token::SingleQuotedString(s) => self.col += s.len() as u64,
Token::DoubleQuotedString(s) => self.col += s.len() as u64, Token::DoubleQuotedString(s) => self.col += s.len() as u64,
_ => self.col += 1, _ => self.col += 1,