From 26c6f97e08698f91298186d9c545ea1fe3102552 Mon Sep 17 00:00:00 2001 From: Steven Phillips Date: Fri, 4 Mar 2016 20:29:26 -0800 Subject: [PATCH] DRILL-4486: Fix expression serialization escaping --- .../common/expression/ExpressionStringBuilder.java | 13 ++++++++++--- .../drill/common/expression/parser/TreeTest.java | 12 ++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java b/logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java index c29b9b02d1a..85547bc7cda 100644 --- a/logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java +++ b/logical/src/main/java/org/apache/drill/common/expression/ExpressionStringBuilder.java @@ -56,6 +56,13 @@ public static void toString(LogicalExpression expr, StringBuilder sb) { expr.accept(INSTANCE, sb); } + public static String escapeSingleQuote(String input) { + return input.replaceAll("(['\\\\])", "\\\\$1"); + } + + public static String escapeBackTick(String input) { + return input.replaceAll("([`\\\\])", "\\\\$1"); + } @Override public Void visitFunctionCall(FunctionCall call, StringBuilder sb) throws RuntimeException { @@ -119,14 +126,14 @@ public Void visitSchemaPath(SchemaPath path, StringBuilder sb) throws RuntimeExc throw new IllegalStateException("Drill doesn't currently support top level arrays"); } sb.append('`'); - sb.append(seg.getNameSegment().getPath()); + sb.append(escapeBackTick(seg.getNameSegment().getPath())); sb.append('`'); while ( (seg = seg.getChild()) != null) { if (seg.isNamed()) { sb.append('.'); sb.append('`'); - sb.append(seg.getNameSegment().getPath()); + sb.append(escapeBackTick(seg.getNameSegment().getPath())); sb.append('`'); } else { sb.append('['); @@ -224,7 +231,7 @@ public Void visitBooleanConstant(BooleanExpression e, StringBuilder sb) throws R @Override public Void visitQuotedStringConstant(QuotedString e, StringBuilder sb) throws RuntimeException { sb.append("'"); - sb.append(e.value); + sb.append(escapeSingleQuote(e.value)); sb.append("'"); return null; } diff --git a/logical/src/test/java/org/apache/drill/common/expression/parser/TreeTest.java b/logical/src/test/java/org/apache/drill/common/expression/parser/TreeTest.java index c8f6219dabb..fe135371da3 100644 --- a/logical/src/test/java/org/apache/drill/common/expression/parser/TreeTest.java +++ b/logical/src/test/java/org/apache/drill/common/expression/parser/TreeTest.java @@ -31,6 +31,18 @@ public class TreeTest extends DrillTest { private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(TreeTest.class); + @Test + public void escapeStringLiteral() throws Exception { + String expr = "func(`identifier`, '\\\\d+', 0, 'fjds')"; + testExpressionParsing(expr); + } + + @Test + public void escapeQuotedIdentifier() throws Exception { + String expr = "`a\\\\b` + `c'd`"; + testExpressionParsing(expr); + } + @Test public void testIfWithCase() throws Exception{ testExpressionParsing("if ($F1) then case when (_MAP.R_NAME = 'AFRICA') then 2 else 4 end else if(4==3) then 1 else if(x==3) then 7 else (if(2==1) then 6 else 4 end) end");