bugfix#1553 Computed column éå¼è½¬æ¢ä¸¤ç«¯æ¬å·è¢«æªæ
Project: http://git-wip-us.apache.org/repos/asf/kylin/repo Commit: http://git-wip-us.apache.org/repos/asf/kylin/commit/a2cb5335 Tree: http://git-wip-us.apache.org/repos/asf/kylin/tree/a2cb5335 Diff: http://git-wip-us.apache.org/repos/asf/kylin/diff/a2cb5335 Branch: refs/heads/2.1.x Commit: a2cb53358e05af9093f9762157f84686569460fc Parents: 11aa9ff Author: Aron.tao <245915...@qq.com> Authored: Thu Jul 13 10:42:28 2017 +0800 Committer: Jiatao Tao <jiatao.tao@Kyligences-MacBook-Pro.local> Committed: Fri Jul 21 14:11:16 2017 +0800 ---------------------------------------------------------------------- .../metadata/model/tool/CalciteParser.java | 42 ++++++++++++++++++-- .../kylin/model/tool/CalciteParserTest.java | 19 ++++++++- .../query/util/ConvertToComputedColumn.java | 3 +- .../query/util/ConvertToComputedColumnTest.java | 11 +++++ 4 files changed, 68 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kylin/blob/a2cb5335/core-metadata/src/main/java/org/apache/kylin/metadata/model/tool/CalciteParser.java ---------------------------------------------------------------------- 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 9b80969..5352708 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 @@ -24,7 +24,6 @@ import java.util.List; import java.util.Objects; import java.util.Set; -import com.google.common.collect.Lists; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlLiteral; @@ -39,6 +38,7 @@ import org.apache.calcite.sql.util.SqlVisitor; import org.apache.commons.lang3.tuple.Pair; import com.google.common.base.Preconditions; +import com.google.common.collect.Lists; import com.google.common.collect.Sets; public class CalciteParser { @@ -188,7 +188,11 @@ public class CalciteParser { return sql.substring(prefix.length(), sql.length() - suffix.length()); } - public static Pair<Integer, Integer> getReplacePos(SqlNode node, String... lines) { + public static Pair<Integer, Integer> getReplacePos(SqlNode node, String inputSql) { + if (inputSql == null) { + return Pair.of(0, 0); + } + String[] lines = inputSql.split("\n"); SqlParserPos pos = node.getParserPosition(); int lineStart = pos.getLineNum(); int lineEnd = pos.getEndLineNum(); @@ -201,6 +205,38 @@ public class CalciteParser { for (int i = 0; i < lineEnd - 1; i++) { columnEnd += lines[i].length() + 1; } - return Pair.of(columnStart, columnEnd); + //for calcite's bug CALCITE-1875 + Pair<Integer, Integer> startEndPos = getPosWithBracketsCompletion(inputSql, columnStart, columnEnd); + return startEndPos; + } + + private static Pair<Integer, Integer> getPosWithBracketsCompletion(String inputSql, int left, int right) { + int leftBracketNum = 0; + int rightBracketNum = 0; + String substring = inputSql.substring(left, right); + for (int i = 0; i < substring.length(); i++) { + char temp = substring.charAt(i); + if (temp == '(') { + leftBracketNum++; + } + if (temp == ')') { + rightBracketNum++; + if (leftBracketNum < rightBracketNum) { + while ('(' != inputSql.charAt(left - 1)) { + left--; + } + left--; + leftBracketNum++; + } + } + } + while (rightBracketNum < leftBracketNum) { + while (')' != inputSql.charAt(right)) { + right++; + } + right++; + rightBracketNum++; + } + return Pair.of(left, right); } } http://git-wip-us.apache.org/repos/asf/kylin/blob/a2cb5335/core-metadata/src/test/java/org/apache/kylin/model/tool/CalciteParserTest.java ---------------------------------------------------------------------- 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 index 81c1c97..2da6c9e 100644 --- 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 @@ -95,8 +95,7 @@ public class CalciteParserTest { for (String sql : sqls) { SqlNode parse = ((SqlSelect) CalciteParser.parse(sql)).getSelectList().get(0); - String[] lines = sql.split("\n"); - Pair<Integer, Integer> replacePos = CalciteParser.getReplacePos(parse, lines); + Pair<Integer, Integer> replacePos = CalciteParser.getReplacePos(parse, sql); String substring = sql.substring(replacePos.getLeft(), replacePos.getRight()); Preconditions.checkArgument(substring.startsWith("a")); Preconditions.checkArgument(substring.endsWith("b")); @@ -120,4 +119,20 @@ public class CalciteParserTest { assertEquals(true, CalciteParser.isNodeEqual(sn0, sn2)); assertEquals(false, CalciteParser.isNodeEqual(sn0, sn3)); } + + @Test + public void testPosWithBrackets() throws SqlParseException { + String[] sqls = new String[] { + "select ( a + b) * (c+ d ) from t", "select (a+b) * (c+d) from t", + "select (a + b) * (c+ d) from t", "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.getLeft(), replacePos.getRight()); + Preconditions.checkArgument(substring.startsWith("(")); + Preconditions.checkArgument(substring.endsWith(")")); + } + } } http://git-wip-us.apache.org/repos/asf/kylin/blob/a2cb5335/query/src/main/java/org/apache/kylin/query/util/ConvertToComputedColumn.java ---------------------------------------------------------------------- diff --git a/query/src/main/java/org/apache/kylin/query/util/ConvertToComputedColumn.java b/query/src/main/java/org/apache/kylin/query/util/ConvertToComputedColumn.java index c9feaab..ad42b96 100644 --- a/query/src/main/java/org/apache/kylin/query/util/ConvertToComputedColumn.java +++ b/query/src/main/java/org/apache/kylin/query/util/ConvertToComputedColumn.java @@ -74,7 +74,6 @@ public class ConvertToComputedColumn implements QueryUtil.IQueryTransformer { return inputSql; } String result = inputSql; - String[] lines = inputSql.split("\n"); List<Pair<String, String>> toBeReplacedExp = new ArrayList<>(); //{"alias":"expression"}, like {"t1":"t1.a+t1.b+t1.c"} for (String ccExp : computedColumn.keySet()) { @@ -86,7 +85,7 @@ public class ConvertToComputedColumn implements QueryUtil.IQueryTransformer { return inputSql; } for (SqlNode node : matchedNodes) { - Pair<Integer, Integer> startEndPos = CalciteParser.getReplacePos(node, lines); + Pair<Integer, Integer> startEndPos = CalciteParser.getReplacePos(node, inputSql); int start = startEndPos.getLeft(); int end = startEndPos.getRight(); //add table alias like t1.column,if exists alias http://git-wip-us.apache.org/repos/asf/kylin/blob/a2cb5335/query/src/test/java/org/apache/kylin/query/util/ConvertToComputedColumnTest.java ---------------------------------------------------------------------- diff --git a/query/src/test/java/org/apache/kylin/query/util/ConvertToComputedColumnTest.java b/query/src/test/java/org/apache/kylin/query/util/ConvertToComputedColumnTest.java index f9b8d8b..d9910fe 100644 --- a/query/src/test/java/org/apache/kylin/query/util/ConvertToComputedColumnTest.java +++ b/query/src/test/java/org/apache/kylin/query/util/ConvertToComputedColumnTest.java @@ -110,4 +110,15 @@ public class ConvertToComputedColumnTest { } + @Test + public void testCCWithBrackets() { + String sql0 = "select ( a + b) + (c+d \t\n) from t"; + String expr1 = "a + b + (c + d)"; + + Map<String, String> map = new HashMap<>(); + map.put("cc0", expr1); + ImmutableSortedMap<String, String> computedColumns = ConvertToComputedColumn.getMapSortedByValue(map); + Assert.assertEquals("select cc0 from t", + ConvertToComputedColumn.replaceComputedColumn(sql0, computedColumns)); + } }