Merge pull request #53 from thomas-jeepe/master

Fix qualified wildcard stringifying
This commit is contained in:
Andy Grove 2019-04-27 08:53:08 -06:00 committed by GitHub
commit 07d66a93ef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 47 additions and 3 deletions

View file

@ -111,7 +111,7 @@ impl ToString for ASTNode {
match self { match self {
ASTNode::SQLIdentifier(s) => s.to_string(), ASTNode::SQLIdentifier(s) => s.to_string(),
ASTNode::SQLWildcard => "*".to_string(), ASTNode::SQLWildcard => "*".to_string(),
ASTNode::SQLQualifiedWildcard(q) => q.join(".") + "*", ASTNode::SQLQualifiedWildcard(q) => q.join(".") + ".*",
ASTNode::SQLCompoundIdentifier(s) => s.join("."), ASTNode::SQLCompoundIdentifier(s) => s.join("."),
ASTNode::SQLIsNull(ast) => format!("{} IS NULL", ast.as_ref().to_string()), ASTNode::SQLIsNull(ast) => format!("{} IS NULL", ast.as_ref().to_string()),
ASTNode::SQLIsNotNull(ast) => format!("{} IS NOT NULL", ast.as_ref().to_string()), ASTNode::SQLIsNotNull(ast) => format!("{} IS NOT NULL", ast.as_ref().to_string()),

View file

@ -35,7 +35,7 @@ impl ToString for Value {
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::Uuid(v) => v.to_string(), Value::Uuid(v) => v.to_string(),
Value::SingleQuotedString(v) => format!("'{}'", v), Value::SingleQuotedString(v) => format!("'{}'", escape_single_quote_string(v)),
Value::NationalStringLiteral(v) => format!("N'{}'", v), Value::NationalStringLiteral(v) => format!("N'{}'", 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(),
@ -46,3 +46,15 @@ impl ToString for Value {
} }
} }
} }
fn escape_single_quote_string(s: &str) -> String {
let mut escaped = String::new();
for c in s.chars() {
if c == '\'' {
escaped.push_str("\'\'");
} else {
escaped.push(c);
}
}
escaped
}

View file

@ -462,8 +462,14 @@ impl<'a> Tokenizer<'a> {
match ch { match ch {
'\'' => { '\'' => {
chars.next(); // consume chars.next(); // consume
let escaped_quote = chars.peek().map(|c| *c == '\'').unwrap_or(false);
if escaped_quote {
s.push('\'');
chars.next();
} else {
break; break;
} }
}
_ => { _ => {
chars.next(); // consume chars.next(); // consume
s.push(ch); s.push(ch);

View file

@ -90,6 +90,13 @@ fn parse_select_wildcard() {
); );
} }
#[test]
fn parse_count_wildcard() {
verified_only_select(
"SELECT COUNT(Employee.*) FROM Order JOIN Employee ON Order.employee = Employee.id",
);
}
#[test] #[test]
fn parse_column_aliases() { fn parse_column_aliases() {
let sql = "SELECT a.col + 1 AS newname FROM foo AS a"; let sql = "SELECT a.col + 1 AS newname FROM foo AS a";
@ -147,6 +154,25 @@ fn parse_projection_nested_type() {
//TODO: add assertions //TODO: add assertions
} }
#[test]
fn parse_escaped_single_quote_string_predicate() {
use self::ASTNode::*;
use self::SQLOperator::*;
let sql = "SELECT id, fname, lname FROM customer \
WHERE salary != 'Jim''s salary'";
let ast = verified_only_select(sql);
assert_eq!(
Some(SQLBinaryExpr {
left: Box::new(SQLIdentifier("salary".to_string())),
op: NotEq,
right: Box::new(SQLValue(Value::SingleQuotedString(
"Jim's salary".to_string()
)))
}),
ast.selection,
);
}
#[test] #[test]
fn parse_compound_expr_1() { fn parse_compound_expr_1() {
use self::ASTNode::*; use self::ASTNode::*;