Skip to content

Commit

Permalink
Respect dotted quoted identifiers in parenthesis
Browse files Browse the repository at this point in the history
When a double-quoted value is found, it is unclear whether to treat
it as a string (MySQL) or as an identifier (standard SQL), so the
placeholder logic must treat it as a string. However, if it is
preceded or followed by a dot, then we know it must be an identifier,
and we should not replace it with a placeholder.
  • Loading branch information
unflxw committed Mar 2, 2023
1 parent a3379e0 commit 6ef3301
Showing 1 changed file with 43 additions and 16 deletions.
59 changes: 43 additions & 16 deletions src/sanitizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ impl SqlSanitizer {
state = State::KeywordScopeStarted
}
Token::Keyword(Keyword::Insert) | Token::Keyword(Keyword::Into) => (),
Token::Keyword(_) if state == State::KeywordScopeStarted => state = State::KeywordScopeStarted,
Token::Keyword(_) if state == State::KeywordScopeStarted => {
state = State::KeywordScopeStarted
}
Token::Keyword(_) => state = State::Keyword,
Token::LiteralValueTypeIndicator(_) => state = State::LiteralValueTypeIndicator,
Token::ParentheseOpen if state == State::ComparisonOperator => {
Expand Down Expand Up @@ -85,7 +87,19 @@ impl SqlSanitizer {
| State::KeywordScopeStarted
| State::Between
| State::LiteralValueTypeIndicator => {
self.placeholder(pos);
// Double quoted might (standard SQL) or might not (MySQL) be an identifier,
// but if it's a component in a dotted path, then we know it's part of an
// identifier and we should definitely not replace it with a placeholder.
match self.sql.tokens.get(pos).unwrap() {
Token::DoubleQuoted(_) => {
if !(self.sql.tokens.get(pos - 1) == Some(&Token::Dot)
|| self.sql.tokens.get(pos + 1) == Some(&Token::Dot))
{
self.placeholder(pos)
}
}
_ => self.placeholder(pos),
}
}
State::ComparisonScopeStarted | State::ArrayStarted => {
// We're in an IN () or ARRAY[] and it starts with content. Remove everything until
Expand Down Expand Up @@ -541,32 +555,23 @@ mod tests {
#[test]
fn test_remove_trailing_comments_multiline() {
assert_eq!(
sanitize_string(
"SELECT table.* FROM table; /* trace: a1b2c3d4e5f6 */"
.to_string()
),
sanitize_string("SELECT table.* FROM table; /* trace: a1b2c3d4e5f6 */".to_string()),
"SELECT table.* FROM table;"
);
}

#[test]
fn test_remove_trailing_comments_inline() {
assert_eq!(
sanitize_string(
"SELECT table.* FROM table; -- trace: a1b2c3d4e5f6"
.to_string()
),
sanitize_string("SELECT table.* FROM table; -- trace: a1b2c3d4e5f6".to_string()),
"SELECT table.* FROM table;"
);
}

#[test]
fn test_remove_trailing_comments_before_semicolon() {
assert_eq!(
sanitize_string(
"SELECT table.* FROM table /* trace: a1b2c3d4e5f6 */;"
.to_string()
),
sanitize_string("SELECT table.* FROM table /* trace: a1b2c3d4e5f6 */;".to_string()),
"SELECT table.* FROM table;"
);
}
Expand All @@ -581,13 +586,35 @@ mod tests {
);
}

#[test]
fn test_select_jsonb_extract_path_quoted_identifier() {
assert_eq!(
sanitize_string(
"SELECT jsonb_extract_path(\"table\".\"data\", 'foo', 22) FROM \"table\";"
.to_string()
),
"SELECT jsonb_extract_path(\"table\".\"data\", ?, ?) FROM \"table\";"
);
}

#[test]
fn test_where_jsonb_extract_path() {
assert_eq!(
sanitize_string(
"SELECT id FROM table WHERE jsonb_extract_path(table.data, 'foo', 22) == 'bar';".to_string()
"SELECT id FROM table WHERE jsonb_extract_path(table.data, 'foo', 22) = 'bar';"
.to_string()
),
"SELECT id FROM table WHERE jsonb_extract_path(table.data, ?, ?) = ?;"
);
}

#[test]
fn test_where_quoted_identifier_in_parenthesis() {
assert_eq!(
sanitize_string(
r#"SELECT "table"."id" FROM "table" WHERE ("table"."data" = 'foo');"#.to_string()
),
"SELECT id FROM table WHERE jsonb_extract_path(table.data, ?, ?) == ?;"
r#"SELECT "table"."id" FROM "table" WHERE ("table"."data" = ?);"#
);
}
}

0 comments on commit 6ef3301

Please sign in to comment.