You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by ja...@apache.org on 2021/01/08 19:39:45 UTC

[incubator-pinot] branch master updated: Fix escape character in transform function literals (#6416)

This is an automated email from the ASF dual-hosted git repository.

jackie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-pinot.git


The following commit(s) were added to refs/heads/master by this push:
     new e018695  Fix escape character in transform function literals (#6416)
e018695 is described below

commit e01869533f57857afa4807cca758c2a0a8dc6a04
Author: Xiaotian (Jackie) Jiang <17...@users.noreply.github.com>
AuthorDate: Fri Jan 8 11:39:31 2021 -0800

    Fix escape character in transform function literals (#6416)
    
    When serializing the function, put back the escape quotes in the literal
---
 .../request/transform/TransformExpressionTree.java   |  3 ++-
 .../org/apache/pinot/parsers/utils/ParserUtils.java  | 20 +++++++++++++-------
 .../transform/TransformExpressionTreeTest.java       | 11 ++++++++++-
 .../tests/BaseClusterIntegrationTestSet.java         |  5 +++++
 4 files changed, 30 insertions(+), 9 deletions(-)

diff --git a/pinot-common/src/main/java/org/apache/pinot/common/request/transform/TransformExpressionTree.java b/pinot-common/src/main/java/org/apache/pinot/common/request/transform/TransformExpressionTree.java
index 7de0be6..ab92972 100644
--- a/pinot-common/src/main/java/org/apache/pinot/common/request/transform/TransformExpressionTree.java
+++ b/pinot-common/src/main/java/org/apache/pinot/common/request/transform/TransformExpressionTree.java
@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Objects;
 import java.util.Set;
 import javax.annotation.Nullable;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.pinot.pql.parsers.Pql2Compiler;
 import org.apache.pinot.pql.parsers.pql2.ast.AstNode;
 import org.apache.pinot.pql.parsers.pql2.ast.FunctionCallAstNode;
@@ -224,7 +225,7 @@ public class TransformExpressionTree {
       case IDENTIFIER:
         return _value;
       case LITERAL:
-        return "\'" + _value + "\'";
+        return "'" + StringUtils.replace(_value, "'", "''") + "'";
       default:
         throw new IllegalStateException();
     }
diff --git a/pinot-common/src/main/java/org/apache/pinot/parsers/utils/ParserUtils.java b/pinot-common/src/main/java/org/apache/pinot/parsers/utils/ParserUtils.java
index c5e6d98..3c733aa 100644
--- a/pinot-common/src/main/java/org/apache/pinot/parsers/utils/ParserUtils.java
+++ b/pinot-common/src/main/java/org/apache/pinot/parsers/utils/ParserUtils.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.pinot.common.request.Expression;
 import org.apache.pinot.common.request.FilterOperator;
 import org.apache.pinot.common.request.Function;
@@ -188,14 +189,19 @@ public class ParserUtils {
     switch (expression.getType()) {
       case LITERAL:
         Literal literal = expression.getLiteral();
-        // Force single quote on non-string literal inside a function.
-        if (forceSingleQuoteOnNonStringLiteral && !literal.isSetStringValue()) {
-          return "'" + literal.getFieldValue() + "'";
-        }
-        if (treatLiteralAsIdentifier || !literal.isSetStringValue()) {
-          return literal.getFieldValue().toString();
+        String literalString = literal.getFieldValue().toString();
+        if (literal.isSetStringValue()) {
+          if (treatLiteralAsIdentifier) {
+            return literalString;
+          } else {
+            return "'" + StringUtils.replace(literalString, "'", "''") + "'";
+          }
         } else {
-          return "'" + literal.getFieldValue() + "'";
+          if (forceSingleQuoteOnNonStringLiteral) {
+            return "'" + literalString + "'";
+          } else {
+            return literalString;
+          }
         }
       case IDENTIFIER:
         return expression.getIdentifier().getName();
diff --git a/pinot-common/src/test/java/org/apache/pinot/common/request/transform/TransformExpressionTreeTest.java b/pinot-common/src/test/java/org/apache/pinot/common/request/transform/TransformExpressionTreeTest.java
index 0c3ba1f..f1d7511 100644
--- a/pinot-common/src/test/java/org/apache/pinot/common/request/transform/TransformExpressionTreeTest.java
+++ b/pinot-common/src/test/java/org/apache/pinot/common/request/transform/TransformExpressionTreeTest.java
@@ -94,6 +94,15 @@ public class TransformExpressionTreeTest {
   }
 
   @Test
+  public void testEscapeQuotes() {
+    String expression = "foo('a''b')";
+    TransformExpressionTree expressionTree = TransformExpressionTree.compileToExpressionTree(expression);
+    Assert.assertEquals(expressionTree.getChildren().get(0),
+        new TransformExpressionTree(TransformExpressionTree.ExpressionType.LITERAL, "a'b", null));
+    Assert.assertEquals(TransformExpressionTree.compileToExpressionTree(expressionTree.toString()), expressionTree);
+  }
+
+  @Test
   public void testUpperCase() {
     String expression = "foO(bAr('a',FOoBar(b,'c',123)),d)";
     Assert.assertTrue(equalsWithStandardExpressionTree(TransformExpressionTree.compileToExpressionTree(expression)));
@@ -103,7 +112,7 @@ public class TransformExpressionTreeTest {
   public void testNoArgFunction() {
     String expression = "now()";
     TransformExpressionTree expressionTree = TransformExpressionTree.compileToExpressionTree(expression);
-    Assert.assertEquals(expressionTree.isFunction(), true);
+    Assert.assertTrue(expressionTree.isFunction());
     Assert.assertEquals(expressionTree.getValue(), "now");
     Assert.assertEquals(expressionTree.getChildren().size(), 0);
   }
diff --git a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BaseClusterIntegrationTestSet.java b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BaseClusterIntegrationTestSet.java
index 37cec5a..7bf675d 100644
--- a/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BaseClusterIntegrationTestSet.java
+++ b/pinot-integration-tests/src/test/java/org/apache/pinot/integration/tests/BaseClusterIntegrationTestSet.java
@@ -284,6 +284,11 @@ public abstract class BaseClusterIntegrationTestSet extends BaseClusterIntegrati
           "SELECT COUNT(*) FROM mytable WHERE DestAirportID NOT IN (SELECT DestAirportID FROM mytable WHERE DaysSinceEpoch = 16430)";
       testSqlQuery(notInSubqueryQuery, Collections.singletonList(notInQuery));
     }
+
+    // Escape quotes
+    query = "SELECT DistanceGroup FROM mytable WHERE DATE_TIME_CONVERT(DaysSinceEpoch, '1:DAYS:EPOCH', '1:DAYS:SIMPLE_DATE_FORMAT:yyyy-MM-dd''T''HH:mm:ss.SSS''Z''', '1:DAYS') = '2014-09-05T00:00:00.000Z'";
+    h2queries = Collections.singletonList("SELECT DistanceGroup FROM mytable WHERE DaysSinceEpoch = 16318 LIMIT 10000");
+    testSqlQuery(query, h2queries);
   }
 
   /**


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org