Skip to content

Commit 5898668

Browse files
authored
Fix group by nature month when timezone is not default
1 parent 21652cc commit 5898668

28 files changed

+220
-96
lines changed

integration-test/src/main/java/org/apache/iotdb/it/env/cluster/env/AbstractEnv.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import java.sql.Connection;
7070
import java.sql.DriverManager;
7171
import java.sql.SQLException;
72+
import java.time.ZoneId;
7273
import java.util.*;
7374
import java.util.concurrent.TimeUnit;
7475
import java.util.function.Predicate;
@@ -489,6 +490,20 @@ public ISession getSessionConnection() throws IoTDBConnectionException {
489490
return session;
490491
}
491492

493+
@Override
494+
public ISession getSessionConnection(ZoneId zoneId) throws IoTDBConnectionException {
495+
final DataNodeWrapper dataNode =
496+
this.dataNodeWrapperList.get(rand.nextInt(this.dataNodeWrapperList.size()));
497+
final Session session =
498+
new Session.Builder()
499+
.host(dataNode.getIp())
500+
.port(dataNode.getPort())
501+
.zoneId(zoneId)
502+
.build();
503+
session.open();
504+
return session;
505+
}
506+
492507
@Override
493508
public ISession getSessionConnection(final String userName, final String password)
494509
throws IoTDBConnectionException {

integration-test/src/main/java/org/apache/iotdb/it/env/remote/env/RemoteServerEnv.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import java.sql.DriverManager;
5252
import java.sql.SQLException;
5353
import java.sql.Statement;
54+
import java.time.ZoneId;
5455
import java.util.ArrayList;
5556
import java.util.Collections;
5657
import java.util.List;
@@ -273,6 +274,14 @@ public ISession getSessionConnection() throws IoTDBConnectionException {
273274
return session;
274275
}
275276

277+
@Override
278+
public ISession getSessionConnection(ZoneId zoneId) throws IoTDBConnectionException {
279+
Session session =
280+
new Session.Builder().host(ip_addr).port(Integer.parseInt(port)).zoneId(zoneId).build();
281+
session.open();
282+
return session;
283+
}
284+
276285
@Override
277286
public ITableSession getTableSessionConnection() throws IoTDBConnectionException {
278287
return new TableSessionBuilder()

integration-test/src/main/java/org/apache/iotdb/itbase/env/BaseEnv.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import java.net.URL;
4343
import java.sql.Connection;
4444
import java.sql.SQLException;
45+
import java.time.ZoneId;
4546
import java.util.List;
4647
import java.util.Optional;
4748
import java.util.Properties;
@@ -193,6 +194,8 @@ IConfigNodeRPCService.Iface getLeaderConfigNodeConnection()
193194

194195
ISession getSessionConnection() throws IoTDBConnectionException;
195196

197+
ISession getSessionConnection(ZoneId zoneId) throws IoTDBConnectionException;
198+
196199
ISession getSessionConnection(String userName, String password) throws IoTDBConnectionException;
197200

198201
ISession getSessionConnection(List<String> nodeUrls) throws IoTDBConnectionException;

integration-test/src/test/java/org/apache/iotdb/db/it/groupby/IoTDBGroupByNaturalMonthIT.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package org.apache.iotdb.db.it.groupby;
2020

21+
import org.apache.iotdb.isession.ISession;
22+
import org.apache.iotdb.isession.SessionDataSet;
2123
import org.apache.iotdb.it.env.EnvFactory;
2224
import org.apache.iotdb.it.framework.IoTDBTestRunner;
2325
import org.apache.iotdb.itbase.category.ClusterIT;
@@ -49,6 +51,7 @@
4951
import static org.apache.iotdb.db.utils.constant.TestConstant.sum;
5052
import static org.apache.iotdb.itbase.constant.TestConstant.TIMESTAMP_STR;
5153
import static org.apache.iotdb.itbase.constant.TestConstant.count;
54+
import static org.junit.Assert.assertEquals;
5255
import static org.junit.Assert.fail;
5356

5457
@RunWith(IoTDBTestRunner.class)
@@ -75,6 +78,8 @@ public class IoTDBGroupByNaturalMonthIT {
7578
calendar.add(Calendar.MONTH, 1), i = calendar.getTimeInMillis()) {
7679
dataSet.add("insert into root.test.d1(timestamp, s1) values (" + i + ", 1)");
7780
}
81+
82+
dataSet.add("insert into root.testTimeZone.d1(timestamp, s1) values (1, 1)");
7883
}
7984

8085
protected static final DateFormat df = new SimpleDateFormat("MM/dd/yyyy:HH:mm:ss");
@@ -413,4 +418,27 @@ public void groupByNaturalMonthWithMixedUnit2() {
413418
null,
414419
currPrecision);
415420
}
421+
422+
@Test
423+
public void groupByNaturalMonthWithNonSystemDefaultTimeZone() {
424+
try (ISession session =
425+
EnvFactory.getEnv().getSessionConnection(TimeZone.getTimeZone("UTC+09:00").toZoneId())) {
426+
427+
SessionDataSet sessionDataSet =
428+
session.executeQueryStatement(
429+
"select count(s1) from root.testTimeZone.d1 group by([2024-07-01, 2024-08-01), 1mo)");
430+
431+
int count = 0;
432+
while (sessionDataSet.hasNext()) {
433+
sessionDataSet.next();
434+
count++;
435+
}
436+
assertEquals(1, count);
437+
438+
sessionDataSet.closeOperationHandle();
439+
} catch (Exception e) {
440+
e.printStackTrace();
441+
fail(e.getMessage());
442+
}
443+
}
416444
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/protocol/thrift/impl/ClientRPCServiceImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ private List<TsBlock> executeGroupByQueryInternal(
789789
scanOptionsBuilder.build(),
790790
driverContext.getOperatorContexts().get(0),
791791
Collections.singletonList(aggregator),
792-
initTimeRangeIterator(groupByTimeParameter, true, true),
792+
initTimeRangeIterator(groupByTimeParameter, true, true, sessionInfo.getZoneId()),
793793
groupByTimeParameter,
794794
DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES,
795795
!TSDataType.BLOB.equals(dataType)
@@ -805,7 +805,7 @@ private List<TsBlock> executeGroupByQueryInternal(
805805
scanOptionsBuilder.build(),
806806
driverContext.getOperatorContexts().get(0),
807807
Collections.singletonList(aggregator),
808-
initTimeRangeIterator(groupByTimeParameter, true, true),
808+
initTimeRangeIterator(groupByTimeParameter, true, true, sessionInfo.getZoneId()),
809809
groupByTimeParameter,
810810
DEFAULT_MAX_TSBLOCK_SIZE_IN_BYTES,
811811
!TSDataType.BLOB.equals(dataType)

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/aggregation/timerangeiterator/AggrWindowIterator.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
import org.apache.tsfile.read.common.TimeRange;
2626
import org.apache.tsfile.utils.TimeDuration;
2727

28+
import java.time.ZoneId;
29+
2830
/**
2931
* This class iteratively generates aggregated time windows.
3032
*
@@ -46,21 +48,25 @@ public class AggrWindowIterator implements ITimeRangeIterator {
4648
// The number of current timeRange, it's used to calculate the cpu when there contains month
4749
private int timeRangeCount;
4850

51+
private final ZoneId zoneId;
52+
4953
@SuppressWarnings("squid:S107")
5054
public AggrWindowIterator(
5155
long startTime,
5256
long endTime,
5357
TimeDuration interval,
5458
TimeDuration slidingStep,
5559
boolean isAscending,
56-
boolean leftCRightO) {
60+
boolean leftCRightO,
61+
ZoneId zoneId) {
5762
this.startTime = startTime;
5863
this.endTime = endTime;
5964
this.interval = interval;
6065
this.slidingStep = slidingStep;
6166
this.isAscending = isAscending;
6267
this.leftCRightO = leftCRightO;
6368
this.timeRangeCount = 0;
69+
this.zoneId = zoneId;
6470
}
6571

6672
@Override
@@ -78,7 +84,7 @@ private TimeRange getLeftmostTimeRange() {
7884
// calculate interval length by natural month based on startTime
7985
// ie. startTIme = 1/31, interval = 1mo, curEndTime will be set to 2/29
8086
retEndTime =
81-
Math.min(DateTimeUtils.calcPositiveIntervalByMonth(startTime, interval), endTime);
87+
Math.min(DateTimeUtils.calcPositiveIntervalByMonth(startTime, interval, zoneId), endTime);
8288
} else {
8389
retEndTime = Math.min(startTime + interval.nonMonthDuration, endTime);
8490
}
@@ -99,14 +105,14 @@ private TimeRange getRightmostTimeRange() {
99105
/ (slidingStep.getMaxTotalDuration(TimestampPrecisionUtils.currPrecision)));
100106
long tempRetStartTime =
101107
DateTimeUtils.calcPositiveIntervalByMonth(
102-
startTime, slidingStep.multiple(intervalNum - 1));
108+
startTime, slidingStep.multiple(intervalNum - 1), zoneId);
103109
retStartTime = tempRetStartTime;
104110
while (tempRetStartTime < endTime) {
105111
intervalNum++;
106112
retStartTime = tempRetStartTime;
107113
tempRetStartTime =
108114
DateTimeUtils.calcPositiveIntervalByMonth(
109-
retStartTime, slidingStep.multiple(intervalNum - 1));
115+
retStartTime, slidingStep.multiple(intervalNum - 1), zoneId);
110116
}
111117
intervalNum -= 1;
112118
} else {
@@ -120,7 +126,7 @@ private TimeRange getRightmostTimeRange() {
120126
retEndTime =
121127
Math.min(
122128
DateTimeUtils.calcPositiveIntervalByMonth(
123-
startTime, interval.merge(slidingStep.multiple(intervalNum - 1))),
129+
startTime, interval.merge(slidingStep.multiple(intervalNum - 1)), zoneId),
124130
endTime);
125131
} else {
126132
retEndTime = Math.min(retStartTime + interval.nonMonthDuration, endTime);
@@ -147,7 +153,7 @@ public boolean hasNextTimeRange() {
147153
if (slidingStep.containsMonth()) {
148154
retStartTime =
149155
DateTimeUtils.calcPositiveIntervalByMonth(
150-
startTime, slidingStep.multiple(timeRangeCount));
156+
startTime, slidingStep.multiple(timeRangeCount), zoneId);
151157
} else {
152158
retStartTime = curStartTime + slidingStep.nonMonthDuration;
153159
}
@@ -171,7 +177,7 @@ public boolean hasNextTimeRange() {
171177
if (interval.containsMonth()) {
172178
retEndTime =
173179
DateTimeUtils.calcPositiveIntervalByMonth(
174-
startTime, slidingStep.multiple(timeRangeCount).merge(interval));
180+
startTime, slidingStep.multiple(timeRangeCount).merge(interval), zoneId);
175181
} else {
176182
retEndTime = retStartTime + interval.nonMonthDuration;
177183
}
@@ -213,11 +219,13 @@ public long getTotalIntervalNum() {
213219
(double) queryRange
214220
/ (slidingStep.getMaxTotalDuration(TimestampPrecisionUtils.currPrecision)));
215221
long retStartTime =
216-
DateTimeUtils.calcPositiveIntervalByMonth(startTime, slidingStep.multiple(intervalNum));
222+
DateTimeUtils.calcPositiveIntervalByMonth(
223+
startTime, slidingStep.multiple(intervalNum), zoneId);
217224
while (retStartTime < endTime) {
218225
intervalNum++;
219226
retStartTime =
220-
DateTimeUtils.calcPositiveIntervalByMonth(startTime, slidingStep.multiple(intervalNum));
227+
DateTimeUtils.calcPositiveIntervalByMonth(
228+
startTime, slidingStep.multiple(intervalNum), zoneId);
221229
}
222230
} else {
223231
intervalNum = (long) Math.ceil(queryRange / (double) slidingStep.nonMonthDuration);

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/aggregation/timerangeiterator/PreAggrWindowWithNaturalMonthIterator.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import org.apache.tsfile.read.common.TimeRange;
2525
import org.apache.tsfile.utils.TimeDuration;
2626

27+
import java.time.ZoneId;
28+
2729
public class PreAggrWindowWithNaturalMonthIterator implements ITimeRangeIterator {
2830

2931
private static final int HEAP_MAX_SIZE = 100;
@@ -46,11 +48,13 @@ public PreAggrWindowWithNaturalMonthIterator(
4648
TimeDuration interval,
4749
TimeDuration slidingStep,
4850
boolean isAscending,
49-
boolean leftCRightO) {
51+
boolean leftCRightO,
52+
ZoneId zoneId) {
5053
this.isAscending = isAscending;
5154
this.timeBoundaryHeap = new TimeSelector(HEAP_MAX_SIZE, isAscending);
5255
this.aggrWindowIterator =
53-
new AggrWindowIterator(startTime, endTime, interval, slidingStep, isAscending, leftCRightO);
56+
new AggrWindowIterator(
57+
startTime, endTime, interval, slidingStep, isAscending, leftCRightO, zoneId);
5458
this.leftCRightO = leftCRightO;
5559
initHeap();
5660
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/aggregation/timerangeiterator/TimeRangeIteratorFactory.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323

2424
import org.apache.tsfile.utils.TimeDuration;
2525

26+
import java.time.ZoneId;
27+
2628
public class TimeRangeIteratorFactory {
2729

2830
private TimeRangeIteratorFactory() {}
@@ -40,7 +42,8 @@ public static ITimeRangeIterator getTimeRangeIterator(
4042
TimeDuration slidingStep,
4143
boolean isAscending,
4244
boolean leftCRightO,
43-
boolean outputPartialTimeWindow) {
45+
boolean outputPartialTimeWindow,
46+
ZoneId zoneId) {
4447
if (outputPartialTimeWindow
4548
&& interval.getTotalDuration(TimestampPrecisionUtils.currPrecision)
4649
> slidingStep.getTotalDuration(TimestampPrecisionUtils.currPrecision)) {
@@ -54,11 +57,11 @@ public static ITimeRangeIterator getTimeRangeIterator(
5457
leftCRightO);
5558
} else {
5659
return new PreAggrWindowWithNaturalMonthIterator(
57-
startTime, endTime, interval, slidingStep, isAscending, leftCRightO);
60+
startTime, endTime, interval, slidingStep, isAscending, leftCRightO, zoneId);
5861
}
5962
} else {
6063
return new AggrWindowIterator(
61-
startTime, endTime, interval, slidingStep, isAscending, leftCRightO);
64+
startTime, endTime, interval, slidingStep, isAscending, leftCRightO, zoneId);
6265
}
6366
}
6467
}

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/AggregationUtil.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import org.apache.tsfile.read.common.block.column.TimeColumnBuilder;
4848
import org.apache.tsfile.utils.Pair;
4949

50+
import java.time.ZoneId;
5051
import java.util.Arrays;
5152
import java.util.List;
5253
import java.util.stream.Collectors;
@@ -73,7 +74,8 @@ private AggregationUtil() {
7374
public static ITimeRangeIterator initTimeRangeIterator(
7475
GroupByTimeParameter groupByTimeParameter,
7576
boolean ascending,
76-
boolean outputPartialTimeWindow) {
77+
boolean outputPartialTimeWindow,
78+
ZoneId zoneId) {
7779
if (groupByTimeParameter == null) {
7880
return new SingleTimeWindowIterator(Long.MIN_VALUE, Long.MAX_VALUE);
7981
} else {
@@ -84,7 +86,8 @@ public static ITimeRangeIterator initTimeRangeIterator(
8486
groupByTimeParameter.getSlidingStep(),
8587
ascending,
8688
groupByTimeParameter.isLeftCRightO(),
87-
outputPartialTimeWindow);
89+
outputPartialTimeWindow,
90+
zoneId);
8891
}
8992
}
9093

iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/operator/process/SlidingWindowAggregationOperator.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import org.apache.tsfile.read.common.block.TsBlockBuilder;
3333
import org.apache.tsfile.utils.RamUsageEstimator;
3434

35+
import java.time.ZoneId;
3536
import java.util.ArrayList;
3637
import java.util.Arrays;
3738
import java.util.List;
@@ -61,7 +62,8 @@ public SlidingWindowAggregationOperator(
6162
boolean ascending,
6263
boolean outputEndTime,
6364
GroupByTimeParameter groupByTimeParameter,
64-
long maxReturnSize) {
65+
long maxReturnSize,
66+
ZoneId zoneId) {
6567
super(operatorContext, aggregators, child, ascending, maxReturnSize);
6668
checkArgument(
6769
groupByTimeParameter != null,
@@ -78,7 +80,8 @@ public SlidingWindowAggregationOperator(
7880

7981
this.timeRangeIterator = timeRangeIterator;
8082
this.outputEndTime = outputEndTime;
81-
this.subTimeRangeIterator = initTimeRangeIterator(groupByTimeParameter, ascending, true);
83+
this.subTimeRangeIterator =
84+
initTimeRangeIterator(groupByTimeParameter, ascending, true, zoneId);
8285
}
8386

8487
@Override

0 commit comments

Comments
 (0)