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

Caideyipi pushed a commit to branch time-partition-boundary-overflow-fix
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit 375f1a65a0959d5daca35d721903abc08db64db1
Author: Caideyipi <[email protected]>
AuthorDate: Tue Jun 9 19:20:18 2026 +0800

    Fix time partition boundary overflow handling
---
 .../realtime/PipeRealtimeDataRegionSource.java     |   4 +-
 .../queryengine/plan/analyze/AnalyzeVisitor.java   |  16 ++--
 .../iotdb/db/storageengine/StorageEngine.java      |   2 +
 .../plan/analyze/QueryTimePartitionTest.java       |  27 ++++++
 .../commons/partition/SeriesPartitionTable.java    |  22 ++++-
 .../iotdb/commons/utils/TimePartitionUtils.java    | 101 ++++++++++++---------
 .../partition/SeriesPartitionTableTest.java        |  22 +++++
 .../commons/utils/TimePartitionUtilsTest.java      |  89 ++++++++++++++++++
 8 files changed, 229 insertions(+), 54 deletions(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/realtime/PipeRealtimeDataRegionSource.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/realtime/PipeRealtimeDataRegionSource.java
index b13b2040016..2038766ded2 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/realtime/PipeRealtimeDataRegionSource.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/realtime/PipeRealtimeDataRegionSource.java
@@ -251,11 +251,11 @@ public abstract class PipeRealtimeDataRegionSource 
implements PipeExtractor {
     }
 
     startTimePartitionIdLowerBound =
-        (realtimeDataExtractionStartTime % 
TimePartitionUtils.getTimePartitionInterval() == 0)
+        
TimePartitionUtils.isTimePartitionStartTime(realtimeDataExtractionStartTime)
             ? 
TimePartitionUtils.getTimePartitionId(realtimeDataExtractionStartTime)
             : 
TimePartitionUtils.getTimePartitionId(realtimeDataExtractionStartTime) + 1;
     endTimePartitionIdUpperBound =
-        (realtimeDataExtractionEndTime % 
TimePartitionUtils.getTimePartitionInterval() == 0)
+        
TimePartitionUtils.isTimePartitionStartTime(realtimeDataExtractionEndTime)
             ? 
TimePartitionUtils.getTimePartitionId(realtimeDataExtractionEndTime)
             : 
TimePartitionUtils.getTimePartitionId(realtimeDataExtractionEndTime) - 1;
 
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
index 22d5b0518ac..d62ef26a3bc 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/AnalyzeVisitor.java
@@ -2234,11 +2234,7 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
         result.add(timePartitionSlot);
         // next init
         timePartitionSlot = new TTimePartitionSlot(endTime);
-        // beware of overflow
-        endTime =
-            endTime + TimePartitionUtils.getTimePartitionInterval() > endTime
-                ? endTime + TimePartitionUtils.getTimePartitionInterval()
-                : Long.MAX_VALUE;
+        endTime = TimePartitionUtils.getTimePartitionUpperBound(endTime);
       } else {
         index++;
         if (index < size) {
@@ -2267,8 +2263,14 @@ public class AnalyzeVisitor extends 
StatementVisitor<Analysis, MPPQueryContext>
       return;
     }
     long size = TimePartitionUtils.getEstimateTimePartitionSize(minTime, 
maxTime);
-    context.reserveMemoryForFrontEnd(
-        RamUsageEstimator.shallowSizeOfInstance(TTimePartitionSlot.class) * 
size);
+    context.reserveMemoryForFrontEnd(estimateTimePartitionSlotMemory(size));
+  }
+
+  static long estimateTimePartitionSlotMemory(long timePartitionSlotCount) {
+    long timePartitionSlotSize = 
RamUsageEstimator.shallowSizeOfInstance(TTimePartitionSlot.class);
+    return timePartitionSlotCount > Long.MAX_VALUE / timePartitionSlotSize
+        ? Long.MAX_VALUE
+        : timePartitionSlotSize * timePartitionSlotCount;
   }
 
   private void analyzeInto(
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java
index db51775281d..17717780307 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/StorageEngine.java
@@ -178,6 +178,8 @@ public class StorageEngine implements IService {
   }
 
   private static void initTimePartition() {
+    TimePartitionUtils.setTimePartitionOrigin(
+        CommonDescriptor.getInstance().getConfig().getTimePartitionOrigin());
     TimePartitionUtils.setTimePartitionInterval(
         CommonDescriptor.getInstance().getConfig().getTimePartitionInterval());
   }
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/QueryTimePartitionTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/QueryTimePartitionTest.java
index 1e85a1461ee..aa31e0ed376 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/QueryTimePartitionTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/QueryTimePartitionTest.java
@@ -20,6 +20,7 @@ package org.apache.iotdb.db.queryengine.plan.analyze;
 
 import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
 import org.apache.iotdb.commons.conf.CommonDescriptor;
+import org.apache.iotdb.commons.utils.TimePartitionUtils;
 import org.apache.iotdb.db.queryengine.common.MPPQueryContext;
 import org.apache.iotdb.db.queryengine.common.QueryId;
 
@@ -575,4 +576,30 @@ public class QueryTimePartitionTest {
     assertFalse(res.right.left);
     assertFalse(res.right.right);
   }
+
+  @Test
+  public void testEstimateTimePartitionSlotMemoryWithOverflow() {
+    assertEquals(Long.MAX_VALUE, 
AnalyzeVisitor.estimateTimePartitionSlotMemory(Long.MAX_VALUE));
+  }
+
+  @Test
+  public void testTimePartitionSlotListWithUpperOverflowPartition() {
+    MPPQueryContext context = new MPPQueryContext(new QueryId("test_query"));
+    long partitionStartTime = 
TimePartitionUtils.getTimePartitionSlot(Long.MAX_VALUE).startTime;
+
+    Pair<List<TTimePartitionSlot>, Pair<Boolean, Boolean>> res =
+        getTimePartitionSlotList(
+            TimeFilterApi.between(partitionStartTime - 1, Long.MAX_VALUE - 1), 
context);
+    List<TTimePartitionSlot> expected =
+        Arrays.asList(
+            TimePartitionUtils.getTimePartitionSlot(partitionStartTime - 1),
+            new TTimePartitionSlot(partitionStartTime));
+
+    assertEquals(expected.size(), res.left.size());
+    for (int i = 0; i < expected.size(); i++) {
+      assertEquals(expected.get(i), res.left.get(i));
+    }
+    assertFalse(res.right.left);
+    assertFalse(res.right.right);
+  }
 }
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/partition/SeriesPartitionTable.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/partition/SeriesPartitionTable.java
index b388121fcd0..28ec68baf8c 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/partition/SeriesPartitionTable.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/partition/SeriesPartitionTable.java
@@ -265,8 +265,7 @@ public class SeriesPartitionTable {
     while (iterator.hasNext()) {
       Map.Entry<TTimePartitionSlot, List<TConsensusGroupId>> entry = 
iterator.next();
       TTimePartitionSlot timePartitionSlot = entry.getKey();
-      if (timePartitionSlot.getStartTime() + timePartitionInterval + TTL
-          <= currentTimeSlot.getStartTime()) {
+      if (isTimePartitionExpired(timePartitionSlot, timePartitionInterval, 
TTL, currentTimeSlot)) {
         removedTimePartitions.add(timePartitionSlot);
         iterator.remove();
       }
@@ -274,6 +273,25 @@ public class SeriesPartitionTable {
     return removedTimePartitions;
   }
 
+  private static boolean isTimePartitionExpired(
+      TTimePartitionSlot timePartitionSlot,
+      long timePartitionInterval,
+      long TTL,
+      TTimePartitionSlot currentTimeSlot) {
+    long partitionEndTime =
+        saturatingAdd(timePartitionSlot.getStartTime(), timePartitionInterval);
+    long expireTime = saturatingAdd(partitionEndTime, TTL);
+    return expireTime <= currentTimeSlot.getStartTime();
+  }
+
+  private static long saturatingAdd(long left, long right) {
+    long result = left + right;
+    if (((left ^ result) & (right ^ result)) < 0) {
+      return left < 0 ? Long.MIN_VALUE : Long.MAX_VALUE;
+    }
+    return result;
+  }
+
   public void merge(SeriesPartitionTable sourceMap) {
     if (sourceMap == null) return;
     sourceMap.seriesPartitionMap.forEach(
diff --git 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/TimePartitionUtils.java
 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/TimePartitionUtils.java
index 250a347d149..06a28bd0cd0 100644
--- 
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/TimePartitionUtils.java
+++ 
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/TimePartitionUtils.java
@@ -31,44 +31,46 @@ public class TimePartitionUtils {
    * Time partition origin for dividing database, the time unit is the same 
with IoTDB's
    * TimestampPrecision
    */
-  private static long timePartitionOrigin =
+  private static volatile long timePartitionOrigin =
       CommonDescriptor.getInstance().getConfig().getTimePartitionOrigin();
 
   /** Time range for dividing database, the time unit is the same with IoTDB's 
TimestampPrecision */
-  private static long timePartitionInterval =
+  private static volatile long timePartitionInterval =
       CommonDescriptor.getInstance().getConfig().getTimePartitionInterval();
 
-  private static final BigInteger bigTimePartitionOrigin = 
BigInteger.valueOf(timePartitionOrigin);
-  private static final BigInteger bigTimePartitionInterval =
-      BigInteger.valueOf(timePartitionInterval);
-  private static final boolean originMayCauseOverflow = (timePartitionOrigin 
!= 0);
-  private static final long timePartitionLowerBoundWithoutOverflow;
-  private static final long timePartitionUpperBoundWithoutOverflow;
+  private static volatile boolean originMayCauseOverflow;
+  private static volatile long timePartitionLowerBoundWithoutOverflow;
+  private static volatile long timePartitionUpperBoundWithoutOverflow;
 
   static {
+    updateTimePartitionBound();
+  }
+
+  private static void updateTimePartitionBound() {
     long minPartition = getTimePartitionIdWithoutOverflow(Long.MIN_VALUE);
     long maxPartition = getTimePartitionIdWithoutOverflow(Long.MAX_VALUE);
     BigInteger minPartitionStartTime =
         BigInteger.valueOf(minPartition)
-            .multiply(bigTimePartitionInterval)
-            .add(bigTimePartitionOrigin);
+            .multiply(BigInteger.valueOf(timePartitionInterval))
+            .add(BigInteger.valueOf(timePartitionOrigin));
     BigInteger maxPartitionEndTime =
         BigInteger.valueOf(maxPartition)
-            .multiply(bigTimePartitionInterval)
-            .add(bigTimePartitionInterval)
-            .add(bigTimePartitionOrigin);
+            .multiply(BigInteger.valueOf(timePartitionInterval))
+            .add(BigInteger.valueOf(timePartitionInterval))
+            .add(BigInteger.valueOf(timePartitionOrigin));
     if (minPartitionStartTime.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 
0) {
       timePartitionLowerBoundWithoutOverflow =
-          minPartitionStartTime.add(bigTimePartitionInterval).longValue();
+          
minPartitionStartTime.add(BigInteger.valueOf(timePartitionInterval)).longValue();
     } else {
       timePartitionLowerBoundWithoutOverflow = 
minPartitionStartTime.longValue();
     }
     if (maxPartitionEndTime.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) 
{
       timePartitionUpperBoundWithoutOverflow =
-          maxPartitionEndTime.subtract(bigTimePartitionInterval).longValue();
+          
maxPartitionEndTime.subtract(BigInteger.valueOf(timePartitionInterval)).longValue();
     } else {
       timePartitionUpperBoundWithoutOverflow = maxPartitionEndTime.longValue();
     }
+    originMayCauseOverflow = (timePartitionOrigin != 0);
   }
 
   public static TTimePartitionSlot getTimePartitionSlot(long time) {
@@ -86,10 +88,7 @@ public class TimePartitionUtils {
       return Long.MIN_VALUE;
     }
     if (originMayCauseOverflow) {
-      return BigInteger.valueOf(getTimePartitionIdWithoutOverflow(time))
-          .multiply(bigTimePartitionInterval)
-          .add(bigTimePartitionOrigin)
-          .longValue();
+      return 
getTimePartitionStartTime(getTimePartitionIdWithoutOverflow(time));
     } else {
       return getTimePartitionId(time) * timePartitionInterval + 
timePartitionOrigin;
     }
@@ -105,7 +104,14 @@ public class TimePartitionUtils {
         : lowerBound + timePartitionInterval;
   }
 
+  public static boolean isTimePartitionStartTime(long time) {
+    return getTimePartitionLowerBound(time) == time;
+  }
+
   public static long getTimePartitionId(long time) {
+    if (originMayCauseOverflow) {
+      return getTimePartitionIdWithoutOverflow(time);
+    }
     time -= timePartitionOrigin;
     return time > 0 || time % timePartitionInterval == 0
         ? time / timePartitionInterval
@@ -113,7 +119,8 @@ public class TimePartitionUtils {
   }
 
   public static long getTimePartitionIdWithoutOverflow(long time) {
-    BigInteger bigTime = 
BigInteger.valueOf(time).subtract(bigTimePartitionOrigin);
+    BigInteger bigTime = 
BigInteger.valueOf(time).subtract(BigInteger.valueOf(timePartitionOrigin));
+    BigInteger bigTimePartitionInterval = 
BigInteger.valueOf(timePartitionInterval);
     BigInteger partitionId =
         bigTime.compareTo(BigInteger.ZERO) > 0
                 || 
bigTime.remainder(bigTimePartitionInterval).equals(BigInteger.ZERO)
@@ -123,7 +130,7 @@ public class TimePartitionUtils {
   }
 
   public static long getStartTimeByPartitionId(long partitionId) {
-    return (partitionId * timePartitionInterval) + timePartitionOrigin;
+    return getTimePartitionStartTime(partitionId);
   }
 
   public static boolean satisfyPartitionId(long startTime, long endTime, long 
partitionId) {
@@ -142,40 +149,48 @@ public class TimePartitionUtils {
     if (timeFilter == null) {
       return true;
     }
-
-    long partitionEndTime =
-        partitionStartTime >= timePartitionLowerBoundWithoutOverflow
-            ? Long.MAX_VALUE
-            : (partitionStartTime + timePartitionInterval - 1);
+    long partitionEndTime = getTimePartitionUpperBound(partitionStartTime);
+    partitionEndTime = partitionEndTime == Long.MAX_VALUE ? Long.MAX_VALUE : 
partitionEndTime - 1;
     return timeFilter.satisfyStartEndTime(partitionStartTime, 
partitionEndTime);
   }
 
   public static boolean satisfyTimePartition(Filter timeFilter, long 
partitionId) {
-    long partitionStartTime;
-    if (originMayCauseOverflow) {
-      partitionStartTime =
-          BigInteger.valueOf(partitionId)
-              .multiply(bigTimePartitionInterval)
-              .add(bigTimePartitionOrigin)
-              .longValue();
-    } else {
-      partitionStartTime = partitionId * timePartitionInterval + 
timePartitionOrigin;
+    return satisfyPartitionStartTime(timeFilter, 
getTimePartitionStartTime(partitionId));
+  }
+
+  private static long getTimePartitionStartTime(long partitionId) {
+    BigInteger partitionStartTime =
+        BigInteger.valueOf(partitionId)
+            .multiply(BigInteger.valueOf(timePartitionInterval))
+            .add(BigInteger.valueOf(timePartitionOrigin));
+    if (partitionStartTime.compareTo(BigInteger.valueOf(Long.MIN_VALUE)) < 0) {
+      return Long.MIN_VALUE;
+    }
+    if (partitionStartTime.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
+      return Long.MAX_VALUE;
     }
-    return satisfyPartitionStartTime(timeFilter, partitionStartTime);
+    return partitionStartTime.longValue();
   }
 
   public static void setTimePartitionInterval(long timePartitionInterval) {
     TimePartitionUtils.timePartitionInterval = timePartitionInterval;
+    updateTimePartitionBound();
+  }
+
+  public static void setTimePartitionOrigin(long timePartitionOrigin) {
+    TimePartitionUtils.timePartitionOrigin = timePartitionOrigin;
+    updateTimePartitionBound();
   }
 
   public static long getEstimateTimePartitionSize(long startTime, long 
endTime) {
-    if (endTime > 0 && startTime < 0) {
-      return BigInteger.valueOf(endTime)
-              .subtract(BigInteger.valueOf(startTime))
-              .divide(bigTimePartitionInterval)
-              .longValue()
-          + 1;
+    BigInteger estimateSize =
+        BigInteger.valueOf(endTime)
+            .subtract(BigInteger.valueOf(startTime))
+            .divide(BigInteger.valueOf(timePartitionInterval))
+            .add(BigInteger.ONE);
+    if (estimateSize.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) > 0) {
+      return Long.MAX_VALUE;
     }
-    return (endTime - startTime) / timePartitionInterval + 1;
+    return estimateSize.longValue();
   }
 }
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/partition/SeriesPartitionTableTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/partition/SeriesPartitionTableTest.java
index ab63deb3c68..4ef40a3b4df 100644
--- 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/partition/SeriesPartitionTableTest.java
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/partition/SeriesPartitionTableTest.java
@@ -108,4 +108,26 @@ public class SeriesPartitionTableTest {
     table1.deserialize(inputStream, protocol);
     Assert.assertEquals(table0, table1);
   }
+
+  @Test
+  public void autoCleanPartitionTableShouldNotExpireOnOverflow() {
+    TConsensusGroupId consensusGroupId = new 
TConsensusGroupId(TConsensusGroupType.DataRegion, 0);
+
+    SeriesPartitionTable table = new SeriesPartitionTable();
+    TTimePartitionSlot nearMaxSlot = new TTimePartitionSlot(Long.MAX_VALUE - 
1);
+    table.putDataPartition(nearMaxSlot, consensusGroupId);
+    Assert.assertTrue(
+        table.autoCleanPartitionTable(0, new TTimePartitionSlot(Long.MAX_VALUE 
- 1)).isEmpty());
+    Assert.assertTrue(table.getSeriesPartitionMap().containsKey(nearMaxSlot));
+
+    table = new SeriesPartitionTable();
+    TTimePartitionSlot normalSlot = new TTimePartitionSlot(0);
+    table.putDataPartition(normalSlot, consensusGroupId);
+    Assert.assertTrue(
+        table
+            .autoCleanPartitionTable(
+                Long.MAX_VALUE - 1, new TTimePartitionSlot(Long.MAX_VALUE - 1))
+            .isEmpty());
+    Assert.assertTrue(table.getSeriesPartitionMap().containsKey(normalSlot));
+  }
 }
diff --git 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/TimePartitionUtilsTest.java
 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/TimePartitionUtilsTest.java
index ea0eeda45d2..f6e37f949c6 100644
--- 
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/TimePartitionUtilsTest.java
+++ 
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/TimePartitionUtilsTest.java
@@ -22,6 +22,8 @@ package org.apache.iotdb.commons.utils;
 import org.apache.iotdb.common.rpc.thrift.TTimePartitionSlot;
 import org.apache.iotdb.commons.conf.CommonDescriptor;
 
+import org.apache.tsfile.read.filter.factory.TimeFilterApi;
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -33,12 +35,31 @@ public class TimePartitionUtilsTest {
   private static final long TEST_TIME_PARTITION_ORIGIN = 1000L;
   private static final long TEST_TIME_PARTITION_INTERVAL = 3600000L;
 
+  private long previousTimePartitionOrigin;
+  private long previousTimePartitionInterval;
+
   @Before
   public void setUp() {
+    previousTimePartitionOrigin =
+        CommonDescriptor.getInstance().getConfig().getTimePartitionOrigin();
+    previousTimePartitionInterval =
+        CommonDescriptor.getInstance().getConfig().getTimePartitionInterval();
     
CommonDescriptor.getInstance().getConfig().setTimePartitionOrigin(TEST_TIME_PARTITION_ORIGIN);
     CommonDescriptor.getInstance()
         .getConfig()
         .setTimePartitionInterval(TEST_TIME_PARTITION_INTERVAL);
+    TimePartitionUtils.setTimePartitionOrigin(TEST_TIME_PARTITION_ORIGIN);
+    TimePartitionUtils.setTimePartitionInterval(TEST_TIME_PARTITION_INTERVAL);
+  }
+
+  @After
+  public void tearDown() {
+    
CommonDescriptor.getInstance().getConfig().setTimePartitionOrigin(previousTimePartitionOrigin);
+    CommonDescriptor.getInstance()
+        .getConfig()
+        .setTimePartitionInterval(previousTimePartitionInterval);
+    TimePartitionUtils.setTimePartitionOrigin(previousTimePartitionOrigin);
+    TimePartitionUtils.setTimePartitionInterval(previousTimePartitionInterval);
   }
 
   @Test
@@ -105,4 +126,72 @@ public class TimePartitionUtilsTest {
     long upperBound = TimePartitionUtils.getTimePartitionUpperBound(testTime);
     assertEquals(Long.MAX_VALUE, upperBound);
   }
+
+  @Test
+  public void testIsTimePartitionStartTimeWithOrigin() {
+    
Assert.assertTrue(TimePartitionUtils.isTimePartitionStartTime(TEST_TIME_PARTITION_ORIGIN));
+    
Assert.assertFalse(TimePartitionUtils.isTimePartitionStartTime(TEST_TIME_PARTITION_ORIGIN
 + 1));
+    Assert.assertTrue(
+        TimePartitionUtils.isTimePartitionStartTime(
+            TEST_TIME_PARTITION_ORIGIN + TEST_TIME_PARTITION_INTERVAL));
+  }
+
+  @Test
+  public void testSatisfyPartitionStartTimeWithNormalPartitionEnd() {
+    Assert.assertFalse(
+        TimePartitionUtils.satisfyPartitionStartTime(
+            TimeFilterApi.gtEq(TEST_TIME_PARTITION_ORIGIN + 
TEST_TIME_PARTITION_INTERVAL),
+            TEST_TIME_PARTITION_ORIGIN));
+    Assert.assertFalse(
+        TimePartitionUtils.satisfyTimePartition(
+            TimeFilterApi.gtEq(TEST_TIME_PARTITION_ORIGIN + 
TEST_TIME_PARTITION_INTERVAL), 0));
+    Assert.assertTrue(
+        TimePartitionUtils.satisfyPartitionStartTime(
+            TimeFilterApi.gtEq(TEST_TIME_PARTITION_ORIGIN + 
TEST_TIME_PARTITION_INTERVAL - 1),
+            TEST_TIME_PARTITION_ORIGIN));
+  }
+
+  @Test
+  public void testSatisfyPartitionStartTimeWithOverflowPartitionEnd() {
+    long partitionStartTime = 
TimePartitionUtils.getTimePartitionSlot(Long.MAX_VALUE).startTime;
+
+    Assert.assertTrue(
+        TimePartitionUtils.satisfyPartitionStartTime(
+            TimeFilterApi.eq(Long.MAX_VALUE), partitionStartTime));
+  }
+
+  @Test
+  public void testSatisfyTimePartitionWithOverflowPartitionStart() {
+    long partitionId = 
TimePartitionUtils.getTimePartitionIdWithoutOverflow(Long.MIN_VALUE);
+    long nextPartitionStartTime = 
TimePartitionUtils.getTimePartitionUpperBound(Long.MIN_VALUE);
+
+    Assert.assertTrue(
+        
TimePartitionUtils.satisfyTimePartition(TimeFilterApi.eq(Long.MIN_VALUE), 
partitionId));
+    Assert.assertFalse(
+        TimePartitionUtils.satisfyTimePartition(
+            TimeFilterApi.eq(nextPartitionStartTime), partitionId));
+  }
+
+  @Test
+  public void testGetTimePartitionIdWithOverflowOrigin() {
+    assertEquals(
+        TimePartitionUtils.getTimePartitionIdWithoutOverflow(Long.MIN_VALUE),
+        TimePartitionUtils.getTimePartitionId(Long.MIN_VALUE));
+    assertEquals(
+        TimePartitionUtils.getTimePartitionIdWithoutOverflow(Long.MAX_VALUE),
+        TimePartitionUtils.getTimePartitionId(Long.MAX_VALUE));
+  }
+
+  @Test
+  public void testGetEstimateTimePartitionSizeWithOverflow() {
+    long previousTimePartitionInterval = 
TimePartitionUtils.getTimePartitionInterval();
+    try {
+      TimePartitionUtils.setTimePartitionInterval(1);
+      assertEquals(
+          Long.MAX_VALUE,
+          TimePartitionUtils.getEstimateTimePartitionSize(Long.MIN_VALUE, 
Long.MAX_VALUE));
+    } finally {
+      
TimePartitionUtils.setTimePartitionInterval(previousTimePartitionInterval);
+    }
+  }
 }

Reply via email to