You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kylin.apache.org by xx...@apache.org on 2021/06/03 02:01:38 UTC
[kylin] branch master updated: KYLIN-4995 fix query exception when
the query statement contains a single left parenthesis
This is an automated email from the ASF dual-hosted git repository.
xxyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kylin.git
The following commit(s) were added to refs/heads/master by this push:
new 4e63c34 KYLIN-4995 fix query exception when the query statement contains a single left parenthesis
4e63c34 is described below
commit 4e63c34b11496a1b79cb7ad4a1ce7b29c99a492d
Author: 7mming7 <7m...@gmail.com>
AuthorDate: Wed May 26 19:13:27 2021 +0800
KYLIN-4995 fix query exception when the query statement contains a single left parenthesis
---
.../kylin/metadata/model/tool/CalciteParser.java | 7 ++
.../source/adhocquery/HivePushDownConverter.java | 12 +-
.../apache/kylin/model/tool/CalciteParserTest.java | 126 +++++++++++++++++++++
.../adhocquery/HivePushDownConverterTest.java | 7 ++
4 files changed, 148 insertions(+), 4 deletions(-)
diff --git a/core-metadata/src/main/java/org/apache/kylin/metadata/model/tool/CalciteParser.java b/core-metadata/src/main/java/org/apache/kylin/metadata/model/tool/CalciteParser.java
index fe602c7..d31800c 100644
--- a/core-metadata/src/main/java/org/apache/kylin/metadata/model/tool/CalciteParser.java
+++ b/core-metadata/src/main/java/org/apache/kylin/metadata/model/tool/CalciteParser.java
@@ -160,9 +160,16 @@ public class CalciteParser {
private static Pair<Integer, Integer> getPosWithBracketsCompletion(String inputSql, int left, int right) {
int leftBracketNum = 0;
int rightBracketNum = 0;
+ boolean constantFlag = false;
String substring = inputSql.substring(left, right);
for (int i = 0; i < substring.length(); i++) {
char temp = substring.charAt(i);
+ if (temp == '\'') {
+ constantFlag = !constantFlag;
+ }
+ if (constantFlag) {
+ continue;
+ }
if (temp == '(') {
leftBracketNum++;
}
diff --git a/core-metadata/src/main/java/org/apache/kylin/source/adhocquery/HivePushDownConverter.java b/core-metadata/src/main/java/org/apache/kylin/source/adhocquery/HivePushDownConverter.java
index 9db5a99..fcbf80a 100644
--- a/core-metadata/src/main/java/org/apache/kylin/source/adhocquery/HivePushDownConverter.java
+++ b/core-metadata/src/main/java/org/apache/kylin/source/adhocquery/HivePushDownConverter.java
@@ -6,9 +6,9 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -228,15 +228,19 @@ public class HivePushDownConverter implements IPushDownConverter {
if (sql.length() > 1) {
Stack<Integer> lStack = new Stack<>();
boolean inStrVal = false;
+ boolean constantFlag = false;
for (int i = 0; i < sql.length(); i++) {
switch (sql.charAt(i)) {
+ case '\'':
+ constantFlag = !constantFlag;
+ break;
case '(':
- if (!inStrVal) {
+ if (!inStrVal && !constantFlag) {
lStack.push(i);
}
break;
case ')':
- if (!inStrVal && !lStack.empty()) {
+ if (!inStrVal && !lStack.empty() && !constantFlag) {
result.put(lStack.pop(), i);
}
break;
diff --git a/core-metadata/src/test/java/org/apache/kylin/model/tool/CalciteParserTest.java b/core-metadata/src/test/java/org/apache/kylin/model/tool/CalciteParserTest.java
new file mode 100644
index 0000000..a775606
--- /dev/null
+++ b/core-metadata/src/test/java/org/apache/kylin/model/tool/CalciteParserTest.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.kylin.model.tool;
+
+import com.google.common.base.Preconditions;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlSelect;
+import org.apache.calcite.sql.parser.SqlParseException;
+import org.apache.kylin.common.util.Pair;
+import org.apache.kylin.metadata.model.tool.CalciteParser;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class CalciteParserTest {
+
+ @Rule
+ public final ExpectedException exception = ExpectedException.none();
+
+ @Test
+ public void testNoTableNameExists() throws SqlParseException {
+ String expr1 = "a + b";
+ assertEquals("x.a + x.b", CalciteParser.insertAliasInExpr(expr1, "x"));
+
+ String expr2 = "a + year(b)";
+ assertEquals("x.a + year(x.b)", CalciteParser.insertAliasInExpr(expr2, "x"));
+
+ String expr3 = "a + hiveudf(b)";
+ assertEquals("x.a + hiveudf(x.b)", CalciteParser.insertAliasInExpr(expr3, "x"));
+ }
+
+ @Test
+ public void testTableNameExists1() throws SqlParseException {
+ String expr1 = "a + x.b";
+
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage("SqlIdentifier X.B contains DB/Table name");
+ CalciteParser.insertAliasInExpr(expr1, "x");
+ }
+
+ @Test
+ public void testTableNameExists2() throws SqlParseException {
+ String expr1 = "a + year(x.b)";
+
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage("SqlIdentifier X.B contains DB/Table name");
+ CalciteParser.insertAliasInExpr(expr1, "x");
+ }
+
+ @Test
+ public void testTableNameExists3() throws SqlParseException {
+ String expr1 = "a + hiveudf(x.b)";
+
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage("SqlIdentifier X.B contains DB/Table name");
+ CalciteParser.insertAliasInExpr(expr1, "x");
+ }
+
+ @Test
+ public void testCaseWhen() {
+ String expr = "(CASE LSTG_FORMAT_NAME WHEN 'Auction' THEN 'x' WHEN 'y' THEN '222' ELSE 'z' END)";
+ String alias = "TEST_KYLIN_FACT";
+ String s = CalciteParser.insertAliasInExpr(expr, alias);
+ System.out.println(s);
+ assertEquals(
+ "(CASE TEST_KYLIN_FACT.LSTG_FORMAT_NAME WHEN 'Auction' THEN 'x' WHEN 'y' THEN '222' ELSE 'z' END)",
+ s);
+ }
+
+ @Test
+ public void testPos() throws SqlParseException {
+ String[] sqls = new String[]{"select \n a \n + \n b \n from t", //
+ "select\na\n+\nb\nfrom t", //
+ "select \r\n a \r\n + \r\n b \r\n from t", //
+ "select\r\na\r\n+\r\nb\r\nfrom t"};
+
+ for (String sql : sqls) {
+ SqlNode parse = ((SqlSelect) CalciteParser.parse(sql)).getSelectList().get(0);
+ Pair<Integer, Integer> replacePos = CalciteParser.getReplacePos(parse, sql);
+ String substring = sql.substring(replacePos.getFirst(), replacePos.getSecond());
+ Preconditions.checkArgument(substring.startsWith("a"));
+ Preconditions.checkArgument(substring.endsWith("b"));
+ }
+
+ }
+
+ @Test
+ public void testPosWithBracketsInConstant() throws SqlParseException {
+ String[] sqls = new String[]{"select '( a + b) * (c+ d ' from t", };
+ for (String sql : sqls) {
+ SqlNode parse = ((SqlSelect) CalciteParser.parse(sql)).getSelectList().get(0);
+ Pair<Integer, Integer> replacePos = CalciteParser.getReplacePos(parse, sql);
+ String substring = sql.substring(replacePos.getFirst(), replacePos.getSecond());
+ Preconditions.checkArgument(substring.startsWith("'"));
+ }
+ }
+
+ @Test
+ public void testRowExpression() {
+ String sql = "SELECT 'LO_LINENUMBER', 'LO_SUPPKEY' FROM \"SSB\".\"P_LINEORDER\" WHERE ROW('LO_ORDERKEY', 'LO_CUSTKEY') IN (ROW(123, 234), ROW(321, 432)) GROUP BY 'LO_LINENUMBER', 'LO_SUPPKEY'";
+ try {
+ CalciteParser.parse(sql);
+ } catch (SqlParseException e) {
+ fail("can't parse row construction");
+ }
+ }
+}
\ No newline at end of file
diff --git a/core-metadata/src/test/java/org/apache/kylin/source/adhocquery/HivePushDownConverterTest.java b/core-metadata/src/test/java/org/apache/kylin/source/adhocquery/HivePushDownConverterTest.java
index b374a60..63faf33 100644
--- a/core-metadata/src/test/java/org/apache/kylin/source/adhocquery/HivePushDownConverterTest.java
+++ b/core-metadata/src/test/java/org/apache/kylin/source/adhocquery/HivePushDownConverterTest.java
@@ -31,6 +31,13 @@ public class HivePushDownConverterTest extends TestCase {
}
@Test
+ public void testStringReplace1() {
+ String originString = "select * from (select '(aaaa' from P_LINEORDER) ";
+ String replacedString = HivePushDownConverter.subqueryReplace(originString);
+ assertEquals("select * from (select '(aaaa' from P_LINEORDER) ", replacedString);
+ }
+
+ @Test
public void testExtractReplace() {
String originString = "ignore EXTRACT(YEAR FROM KYLIN_CAL_DT.CAL_DT) ignore";
String replacedString = HivePushDownConverter.extractReplace(originString);