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 <17555551+jackie-ji...@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-unsubscr...@pinot.apache.org For additional commands, e-mail: commits-h...@pinot.apache.org