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/06/21 02:17:05 UTC

[iotdb] branch updateGroupby created (now 299731c)

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

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


      at 299731c  Sync 0.12 with master

This branch includes the following new commits:

     new 299731c  Sync 0.12 with master

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: Sync 0.12 with master

Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

xiangweiwei pushed a commit to branch updateGroupby
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 299731c3aa64c39ccb24a998f99138506cca992e
Author: Alima777 <wx...@gmail.com>
AuthorDate: Mon Jun 21 10:16:01 2021 +0800

    Sync 0.12 with master
---
 .../apache/iotdb/db/qp/sql/IoTDBSqlVisitor.java    | 95 ++++++----------------
 .../apache/iotdb/db/qp/utils/DatetimeUtils.java    | 33 ++++++--
 .../iotdb/db/integration/IoTDBGroupByMonthIT.java  |  3 +-
 .../db/qp/utils/DatetimeQueryDataSetUtilsTest.java | 28 +++++++
 4 files changed, 81 insertions(+), 78 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 4684111..ae7f473 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
@@ -1479,7 +1479,7 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> {
     queryOp.setLeftCRightO(ctx.timeInterval().LS_BRACKET() != null);
 
     // parse timeUnit
-    queryOp.setUnit(parseDuration(ctx.DURATION().getText()));
+    queryOp.setUnit(DatetimeUtils.convertDurationStrToLong(ctx.DURATION().getText()));
     queryOp.setSlidingStep(queryOp.getUnit());
 
     parseTimeInterval(ctx.timeInterval(), queryOp);
@@ -1497,7 +1497,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> {
         if (typeClause.previousUntilLastClause() != null) {
           long preRange;
           if (typeClause.previousUntilLastClause().DURATION() != null) {
-            preRange = parseDuration(typeClause.previousUntilLastClause().DURATION().getText());
+            preRange =
+                DatetimeUtils.convertDurationStrToLong(
+                    typeClause.previousUntilLastClause().DURATION().getText());
           } else {
             preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
           }
@@ -1505,7 +1507,9 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> {
         } else {
           long preRange;
           if (typeClause.previousClause().DURATION() != null) {
-            preRange = parseDuration(typeClause.previousClause().DURATION().getText());
+            preRange =
+                DatetimeUtils.convertDurationStrToLong(
+                    typeClause.previousClause().DURATION().getText());
           } else {
             preRange = IoTDBDescriptor.getInstance().getConfig().getDefaultFillInterval();
           }
@@ -1536,22 +1540,27 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> {
 
     if (ctx.linearClause() != null) { // linear
       if (ctx.linearClause().DURATION(0) != null) {
-        long beforeRange = parseDuration(ctx.linearClause().DURATION(0).getText());
-        long afterRange = parseDuration(ctx.linearClause().DURATION(1).getText());
+        long beforeRange =
+            DatetimeUtils.convertDurationStrToLong(ctx.linearClause().DURATION(0).getText());
+        long afterRange =
+            DatetimeUtils.convertDurationStrToLong(ctx.linearClause().DURATION(1).getText());
         fillTypes.put(dataType, new LinearFill(beforeRange, afterRange));
       } else {
         fillTypes.put(dataType, new LinearFill(defaultFillInterval, defaultFillInterval));
       }
     } else if (ctx.previousClause() != null) { // previous
       if (ctx.previousClause().DURATION() != null) {
-        long preRange = parseDuration(ctx.previousClause().DURATION().getText());
+        long preRange =
+            DatetimeUtils.convertDurationStrToLong(ctx.previousClause().DURATION().getText());
         fillTypes.put(dataType, new PreviousFill(preRange));
       } else {
         fillTypes.put(dataType, new PreviousFill(defaultFillInterval));
       }
     } else { // previous until last
       if (ctx.previousUntilLastClause().DURATION() != null) {
-        long preRange = parseDuration(ctx.previousUntilLastClause().DURATION().getText());
+        long preRange =
+            DatetimeUtils.convertDurationStrToLong(
+                ctx.previousUntilLastClause().DURATION().getText());
         fillTypes.put(dataType, new PreviousFill(preRange, true));
       } else {
         fillTypes.put(dataType, new PreviousFill(defaultFillInterval, true));
@@ -1834,85 +1843,31 @@ public class IoTDBSqlVisitor extends SqlBaseBaseVisitor<Operator> {
     time = parseTimeFormat(ctx.getChild(0).getText());
     for (int i = 1; i < ctx.getChildCount(); i = i + 2) {
       if (ctx.getChild(i).getText().equals("+")) {
-        time += parseDuration(ctx.getChild(i + 1).getText());
+        time += DatetimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
       } else {
-        time -= parseDuration(ctx.getChild(i + 1).getText());
+        time -= DatetimeUtils.convertDurationStrToLong(time, ctx.getChild(i + 1).getText());
       }
     }
     return time;
   }
 
   /**
-   * parse duration to time value.
-   *
-   * @param durationStr represent duration string like: 12d8m9ns, 1y1mo, etc.
-   * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
-   */
-  private Long parseDuration(String durationStr) {
-    String timestampPrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision();
-
-    long total = 0;
-    long tmp = 0;
-    for (int i = 0; i < durationStr.length(); i++) {
-      char ch = durationStr.charAt(i);
-      if (Character.isDigit(ch)) {
-        tmp *= 10;
-        tmp += (ch - '0');
-      } else {
-        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);
-        }
-        total +=
-            DatetimeUtils.convertDurationStrToLong(tmp, unit.toLowerCase(), timestampPrecision);
-        tmp = 0;
-      }
-    }
-    if (total <= 0) {
-      throw new SQLParserException("Interval must more than 0.");
-    }
-    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.
+   * @param durationStr represent duration string like: 12d8m9ns, 1y1d, 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 (durationStr.toLowerCase().contains("mo")) {
+      if (isParsingTimeUnit) {
+        queryOp.setIntervalByMonth(true);
+      } else {
+        queryOp.setSlidingStepByMonth(true);
       }
     }
-    if (hasMonthUnit && hasOtherUnits) {
-      throw new SQLParserException(
-          "Natural month unit can not be used with other time units together now.");
-    }
-    return parseDuration(durationStr);
+    return DatetimeUtils.convertDurationStrToLong(durationStr);
   }
 
   private PartialPath parseSuffixPath(SuffixPathContext ctx) {
diff --git a/server/src/main/java/org/apache/iotdb/db/qp/utils/DatetimeUtils.java b/server/src/main/java/org/apache/iotdb/db/qp/utils/DatetimeUtils.java
index 80035d36..264fe6b 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/utils/DatetimeUtils.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/utils/DatetimeUtils.java
@@ -31,6 +31,7 @@ import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.DateTimeParseException;
 import java.time.format.SignStyle;
 import java.time.temporal.ChronoField;
+import java.util.Calendar;
 
 public class DatetimeUtils {
 
@@ -506,14 +507,15 @@ public class DatetimeUtils {
   }
 
   /**
-   * convert duration string to time value.
+   * convert duration string to time value. CurrentTime is used to calculate the days of natural *
+   * month. If it's set as -1, which means a context free situation, then '1mo' will be thought as *
+   * 30 days.
    *
    * @param duration represent duration string like: 12d8m9ns, 1y1mo, etc.
    * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
    */
   public static long convertDurationStrToLong(String duration) {
-    String timestampPrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision();
-    return convertDurationStrToLong(duration, timestampPrecision);
+    return convertDurationStrToLong(-1, duration);
   }
 
   /**
@@ -522,7 +524,8 @@ public class DatetimeUtils {
    * @param duration represent duration string like: 12d8m9ns, 1y1mo, etc.
    * @return time in milliseconds, microseconds, or nanoseconds depending on the profile
    */
-  public static long convertDurationStrToLong(String duration, String timestampPrecision) {
+  public static long convertDurationStrToLong(long currentTime, String duration) {
+    String timestampPrecision = IoTDBDescriptor.getInstance().getConfig().getTimestampPrecision();
     long total = 0;
     long temp = 0;
     for (int i = 0; i < duration.length(); i++) {
@@ -538,15 +541,24 @@ public class DatetimeUtils {
           unit += duration.charAt(i);
         }
         total +=
-            DatetimeUtils.convertDurationStrToLong(temp, unit.toLowerCase(), timestampPrecision);
+            DatetimeUtils.convertDurationStrToLong(
+                currentTime == -1 ? -1 : currentTime + total,
+                temp,
+                unit.toLowerCase(),
+                timestampPrecision);
         temp = 0;
       }
     }
     return total;
   }
 
-  /** convert duration string to millisecond, microsecond or nanosecond. */
   public static long convertDurationStrToLong(long value, String unit, String timestampPrecision) {
+    return convertDurationStrToLong(-1, value, unit, timestampPrecision);
+  }
+
+  /** convert duration string to millisecond, microsecond or nanosecond. */
+  public static long convertDurationStrToLong(
+      long currentTime, long value, String unit, String timestampPrecision) {
     DurationUnit durationUnit = DurationUnit.valueOf(unit);
     long res = value;
     switch (durationUnit) {
@@ -554,7 +566,14 @@ public class DatetimeUtils {
         res *= 365 * 86_400_000L;
         break;
       case mo:
-        res *= 30 * 86_400_000L;
+        if (currentTime == -1) {
+          res *= 30 * 86_400_000L;
+        } else {
+          Calendar calendar = Calendar.getInstance();
+          calendar.setTimeInMillis(currentTime);
+          calendar.add(Calendar.MONTH, (int) (value));
+          res = calendar.getTimeInMillis() - currentTime;
+        }
         break;
       case w:
         res *= 7 * 86_400_000L;
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 fdfb216..76e0dba 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
@@ -244,7 +244,8 @@ public class IoTDBGroupByMonthIT {
             cnt++;
           }
         }
-        Assert.assertEquals(30, cnt);
+        Assert.assertTrue(cnt >= 28);
+        Assert.assertTrue(cnt <= 31);
       }
     } catch (Exception e) {
       e.printStackTrace();
diff --git a/server/src/test/java/org/apache/iotdb/db/qp/utils/DatetimeQueryDataSetUtilsTest.java b/server/src/test/java/org/apache/iotdb/db/qp/utils/DatetimeQueryDataSetUtilsTest.java
index 8987830..999a590 100644
--- a/server/src/test/java/org/apache/iotdb/db/qp/utils/DatetimeQueryDataSetUtilsTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/qp/utils/DatetimeQueryDataSetUtilsTest.java
@@ -130,6 +130,34 @@ public class DatetimeQueryDataSetUtilsTest {
     Assert.assertEquals(7L, DatetimeUtils.convertDurationStrToLong(7, "ns", "ns"));
   }
 
+  /** Test convert duration including natural month unit. Time includes: 1970-01-01 ~ 1970-12-01 */
+  @Test
+  public void getConvertDurationIncludingMonthUnit() {
+    Assert.assertEquals(31 * 86400000L, DatetimeUtils.convertDurationStrToLong(0, 1, "mo", "ms"));
+    Assert.assertEquals(
+        28 * 86400000L, DatetimeUtils.convertDurationStrToLong(2678400000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        31 * 86400000L, DatetimeUtils.convertDurationStrToLong(5097600000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        30 * 86400000L, DatetimeUtils.convertDurationStrToLong(7776000000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        31 * 86400000L, DatetimeUtils.convertDurationStrToLong(10368000000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        30 * 86400000L, DatetimeUtils.convertDurationStrToLong(13046400000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        31 * 86400000L, DatetimeUtils.convertDurationStrToLong(15638400000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        31 * 86400000L, DatetimeUtils.convertDurationStrToLong(18316800000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        30 * 86400000L, DatetimeUtils.convertDurationStrToLong(20995200000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        31 * 86400000L, DatetimeUtils.convertDurationStrToLong(23587200000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        30 * 86400000L, DatetimeUtils.convertDurationStrToLong(26265600000L, 1, "mo", "ms"));
+    Assert.assertEquals(
+        31 * 86400000L, DatetimeUtils.convertDurationStrToLong(28857600000L, 1, "mo", "ms"));
+  }
+
   public void testConvertDatetimeStrToLongWithoutMS(ZoneOffset zoneOffset, ZoneId zoneId, long res)
       throws LogicalOperatorException {
     String[] timeFormatWithoutMs =