You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by xi...@apache.org on 2021/05/07 08:20:47 UTC

[iotdb] branch to0.12groupbymonthbug created (now 6f9ead2)

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

xiangweiwei pushed a change to branch to0.12groupbymonthbug
in repository https://gitbox.apache.org/repos/asf/iotdb.git.


      at 6f9ead2  Fix issue-3116

This branch includes the following new commits:

     new 6f9ead2  Fix issue-3116

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[iotdb] 01/01: Fix issue-3116

Posted by xi...@apache.org.
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 <wx...@gmail.com>
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");