This is an automated email from the ASF dual-hosted git repository. xiangweiwei pushed a commit to branch to0.12groupbymonthbug in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 6f9ead2e08cdaba13bc351229c2fbf23e2f66237 Author: Alima777 <[email protected]> AuthorDate: Fri May 7 16:20:01 2021 +0800 Fix issue-3116 --- .../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java | 60 ++++++++++++++++------ .../iotdb/db/integration/IoTDBGroupByMonthIT.java | 28 ++++++++++ 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java index 4a8373b..acb84fb 100644 --- a/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java +++ b/server/src/main/java/org/apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java @@ -252,7 +252,6 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { + "time > XXX, time <= XXX, or two atomic expressions connected by 'AND'"; private ZoneId zoneId; QueryOperator queryOp; - private boolean isParsingSlidingStep; public void setZoneId(ZoneId zoneId) { this.zoneId = zoneId; @@ -1437,17 +1436,17 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { queryOp.setGroupByTime(true); queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null); // parse timeUnit - queryOp.setUnit(parseDuration(ctx.DURATION(0).getText())); - queryOp.setSlidingStep(queryOp.getUnit()); + queryOp.setUnit(parseTimeUnitOrSlidingStep(queryOp, ctx.DURATION(0).getText(), true)); // parse sliding step if (ctx.DURATION().size() == 2) { - isParsingSlidingStep = true; - queryOp.setSlidingStep(parseDuration(ctx.DURATION(1).getText())); - isParsingSlidingStep = false; + queryOp.setSlidingStep(parseTimeUnitOrSlidingStep(queryOp, ctx.DURATION(1).getText(), false)); if (queryOp.getSlidingStep() < queryOp.getUnit()) { throw new SQLParserException( "The third parameter sliding step shouldn't be smaller than the second parameter time interval."); } + } else { + queryOp.setSlidingStep(queryOp.getUnit()); + queryOp.setSlidingStepByMonth(queryOp.isIntervalByMonth()); } parseTimeInterval(ctx.timeInterval(), queryOp); @@ -1853,16 +1852,6 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { i++; unit += durationStr.charAt(i); } - if (unit.equalsIgnoreCase("mo")) { - // interval is by month, sliding step by default equals to interval - if (!isParsingSlidingStep) { - queryOp.setIntervalByMonth(true); - } - queryOp.setSlidingStepByMonth(true); - } else if (isParsingSlidingStep) { - // parsing sliding step value, and unit is not by month - queryOp.setSlidingStepByMonth(false); - } total += DatetimeUtils.convertDurationStrToLong(tmp, unit.toLowerCase(), timestampPrecision); tmp = 0; @@ -1874,6 +1863,45 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> { return total; } + /** + * parse time unit or sliding step in group by query. If 'mo' is used, then other units can not be + * used together, like '1mo1d'. + * + * @param durationStr represent duration string like: 12d8m9ns, 1y1mo, etc. + * @return time in milliseconds, microseconds, or nanoseconds depending on the profile + */ + private long parseTimeUnitOrSlidingStep( + QueryOperator queryOp, String durationStr, boolean isParsingTimeUnit) { + boolean hasMonthUnit = false; + boolean hasOtherUnits = false; + for (int i = 0; i < durationStr.length(); i++) { + char ch = durationStr.charAt(i); + if (!Character.isDigit(ch)) { + String unit = durationStr.charAt(i) + ""; + // This is to identify units with two letters. + if (i + 1 < durationStr.length() && !Character.isDigit(durationStr.charAt(i + 1))) { + i++; + unit += durationStr.charAt(i); + } + if (unit.equalsIgnoreCase("mo")) { + if (isParsingTimeUnit) { + queryOp.setIntervalByMonth(true); + } else { + queryOp.setSlidingStepByMonth(true); + } + hasMonthUnit = true; + } else { + hasOtherUnits = true; + } + } + } + if (hasMonthUnit && hasOtherUnits) { + throw new SQLParserException( + "Natural month unit can not be used with other time units together now."); + } + return parseDuration(durationStr); + } + private PartialPath parseSuffixPath(SuffixPathContext ctx) { List<NodeNameContext> nodeNames = ctx.nodeName(); String[] path = new String[nodeNames.size()]; diff --git a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByMonthIT.java b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByMonthIT.java index 5ff2236..fdfb216 100644 --- a/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByMonthIT.java +++ b/server/src/test/java/org/apache/iotdb/db/integration/IoTDBGroupByMonthIT.java @@ -224,6 +224,34 @@ public class IoTDBGroupByMonthIT { } } + /** StartTime: now() - 1mo, EndTime: now(). */ + @Test + public void groupByNaturalMonth6() { + try (Connection connection = + DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root"); + Statement statement = connection.createStatement()) { + + boolean hasResultSet = + statement.execute( + "select sum(temperature) from root.sg1.d1 GROUP BY ([now() - 1mo, now()), 1d)"); + + Assert.assertTrue(hasResultSet); + int cnt = 0; + try (ResultSet resultSet = statement.getResultSet()) { + while (resultSet.next()) { + String ans = resultSet.getString(sum("root.sg1.d1.temperature")); + if (ans.equals("0.0")) { + cnt++; + } + } + Assert.assertEquals(30, cnt); + } + } catch (Exception e) { + e.printStackTrace(); + fail(e.getMessage()); + } + } + private void prepareData() { try (Connection connection = DriverManager.getConnection("jdbc:iotdb://127.0.0.1:6667/", "root", "root");
