This is an automated email from the ASF dual-hosted git repository. jackietien pushed a commit to branch ExtractBug in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit a08b5d8eec4ff3e016e8314a295a840e8dfccb40 Author: JackieTien97 <[email protected]> AuthorDate: Wed Aug 27 16:09:40 2025 +0800 Fix DateTimeUtils init order bug --- .../plan/planner/plan/node/PlanGraphPrinter.java | 7 +- .../scalar/DateBinFunctionColumnTransformer.java | 21 +++--- .../column/unary/scalar/ExtractTransformer.java | 12 ++-- .../java/org/apache/iotdb/db/service/DataNode.java | 4 ++ .../org/apache/iotdb/db/utils/DateTimeUtils.java | 75 ++++++++++++++-------- 5 files changed, 78 insertions(+), 41 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java index b07cc767910..a294448947f 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/planner/plan/node/PlanGraphPrinter.java @@ -20,6 +20,7 @@ package org.apache.iotdb.db.queryengine.plan.planner.plan.node; import org.apache.iotdb.common.rpc.thrift.TRegionReplicaSet; +import org.apache.iotdb.commons.conf.CommonDescriptor; import org.apache.iotdb.commons.partition.DataPartition; import org.apache.iotdb.commons.path.PartialPath; import org.apache.iotdb.db.queryengine.plan.analyze.TemplatedInfo; @@ -99,7 +100,6 @@ import java.util.Map.Entry; import java.util.Optional; import static com.google.common.base.Preconditions.checkArgument; -import static org.apache.iotdb.db.utils.DateTimeUtils.TIMESTAMP_PRECISION; public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter.GraphContext> { @@ -837,7 +837,10 @@ public class PlanGraphPrinter extends PlanVisitor<List<String>, PlanGraphPrinter if (node.getMonthDuration() != 0) { boxValue.add(String.format("Interval: %smo", node.getMonthDuration())); } else { - boxValue.add(String.format("Interval: %s" + TIMESTAMP_PRECISION, node.getNonMonthDuration())); + boxValue.add( + String.format( + "Interval: %s" + CommonDescriptor.getInstance().getConfig().getTimestampPrecision(), + node.getNonMonthDuration())); } boxValue.add(String.format("GapFillColumn: %s", node.getGapFillColumn())); if (!node.getGapFillGroupingKeys().isEmpty()) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/DateBinFunctionColumnTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/DateBinFunctionColumnTransformer.java index e0d51429ac6..93ef9dff3a2 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/DateBinFunctionColumnTransformer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/DateBinFunctionColumnTransformer.java @@ -19,6 +19,7 @@ package org.apache.iotdb.db.queryengine.transformation.dag.column.unary.scalar; +import org.apache.iotdb.commons.conf.CommonDescriptor; import org.apache.iotdb.db.queryengine.transformation.dag.column.ColumnTransformer; import org.apache.iotdb.db.queryengine.transformation.dag.column.unary.UnaryColumnTransformer; @@ -32,8 +33,6 @@ import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.concurrent.TimeUnit; -import static org.apache.iotdb.db.utils.DateTimeUtils.TIMESTAMP_PRECISION; - public class DateBinFunctionColumnTransformer extends UnaryColumnTransformer { private static final long NANOSECONDS_IN_MILLISECOND = 1_000_000; @@ -62,7 +61,7 @@ public class DateBinFunctionColumnTransformer extends UnaryColumnTransformer { private static LocalDateTime convertToLocalDateTime(long timestamp, ZoneId zoneId) { Instant instant; - switch (TIMESTAMP_PRECISION) { + switch (CommonDescriptor.getInstance().getConfig().getTimestampPrecision()) { case "ms": instant = Instant.ofEpochMilli(timestamp); break; @@ -77,7 +76,9 @@ public class DateBinFunctionColumnTransformer extends UnaryColumnTransformer { TimeUnit.NANOSECONDS.toSeconds(timestamp), timestamp % 1_000_000_000); break; default: - throw new IllegalArgumentException("Unsupported precision: " + TIMESTAMP_PRECISION); + throw new IllegalArgumentException( + "Unsupported precision: " + + CommonDescriptor.getInstance().getConfig().getTimestampPrecision()); } return LocalDateTime.ofInstant(instant, zoneId); @@ -89,7 +90,7 @@ public class DateBinFunctionColumnTransformer extends UnaryColumnTransformer { // Get the nanoseconds section long nanoAdjustment = dateTime.getNano(); - switch (TIMESTAMP_PRECISION) { + switch (CommonDescriptor.getInstance().getConfig().getTimestampPrecision()) { case "ms": return epochMilliSecond + nanoAdjustment / NANOSECONDS_IN_MILLISECOND; case "us": @@ -98,12 +99,14 @@ public class DateBinFunctionColumnTransformer extends UnaryColumnTransformer { case "ns": return TimeUnit.MILLISECONDS.toNanos(epochMilliSecond) + nanoAdjustment; default: - throw new IllegalArgumentException("Unknown precision: " + TIMESTAMP_PRECISION); + throw new IllegalArgumentException( + "Unknown precision: " + + CommonDescriptor.getInstance().getConfig().getTimestampPrecision()); } } private static long getNanoTimeStamp(long timestamp) { - switch (TIMESTAMP_PRECISION) { + switch (CommonDescriptor.getInstance().getConfig().getTimestampPrecision()) { case "ms": return TimeUnit.MILLISECONDS.toNanos(timestamp); case "us": @@ -111,7 +114,9 @@ public class DateBinFunctionColumnTransformer extends UnaryColumnTransformer { case "ns": return timestamp; default: - throw new IllegalArgumentException("Unknown precision: " + TIMESTAMP_PRECISION); + throw new IllegalArgumentException( + "Unknown precision: " + + CommonDescriptor.getInstance().getConfig().getTimestampPrecision()); } } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/ExtractTransformer.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/ExtractTransformer.java index 76d4c1c7e10..c8e11806f89 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/ExtractTransformer.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/transformation/dag/column/unary/scalar/ExtractTransformer.java @@ -31,10 +31,10 @@ import java.time.ZoneId; import java.util.function.Function; import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR; -import static org.apache.iotdb.db.utils.DateTimeUtils.EXTRACT_TIMESTAMP_MS_PART; -import static org.apache.iotdb.db.utils.DateTimeUtils.EXTRACT_TIMESTAMP_NS_PART; -import static org.apache.iotdb.db.utils.DateTimeUtils.EXTRACT_TIMESTAMP_US_PART; import static org.apache.iotdb.db.utils.DateTimeUtils.convertToZonedDateTime; +import static org.apache.iotdb.db.utils.DateTimeUtils.getExtractTimestampMsPartFunction; +import static org.apache.iotdb.db.utils.DateTimeUtils.getExtractTimestampNsPartFunction; +import static org.apache.iotdb.db.utils.DateTimeUtils.getExtractTimestampUsPartFunction; public class ExtractTransformer extends UnaryColumnTransformer { private final Function<Long, Long> evaluateFunction; @@ -72,11 +72,11 @@ public class ExtractTransformer extends UnaryColumnTransformer { case SECOND: return timestamp -> (long) convertToZonedDateTime(timestamp, zoneId).getSecond(); case MS: - return EXTRACT_TIMESTAMP_MS_PART; + return getExtractTimestampMsPartFunction(); case US: - return EXTRACT_TIMESTAMP_US_PART; + return getExtractTimestampUsPartFunction(); case NS: - return EXTRACT_TIMESTAMP_NS_PART; + return getExtractTimestampNsPartFunction(); default: throw new UnsupportedOperationException("Unexpected extract field: " + field); } diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java index 55268d72ab2..bad4d839eac 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/service/DataNode.java @@ -137,6 +137,7 @@ import java.util.stream.Collectors; import static org.apache.iotdb.commons.conf.IoTDBConstant.DEFAULT_CLUSTER_NAME; import static org.apache.iotdb.commons.utils.StatusUtils.retrieveExitStatusCode; import static org.apache.iotdb.db.conf.IoTDBStartCheck.PROPERTIES_FILE_NAME; +import static org.apache.iotdb.db.utils.DateTimeUtils.initTimestampPrecision; public class DataNode extends ServerCommandLine implements DataNodeMBean { @@ -392,6 +393,9 @@ public class DataNode extends ServerCommandLine implements DataNodeMBean { } catch (Exception e) { throw new StartupException(e.getMessage()); } + + // init + initTimestampPrecision(); long endTime = System.currentTimeMillis(); logger.info( "Successfully pull system configurations from ConfigNode-leader, which takes {} ms", diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DateTimeUtils.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DateTimeUtils.java index b413ae5ff37..63e577407cb 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DateTimeUtils.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/DateTimeUtils.java @@ -59,12 +59,11 @@ public class DateTimeUtils { // forbidding instantiation } - public static final String TIMESTAMP_PRECISION = - CommonDescriptor.getInstance().getConfig().getTimestampPrecision(); + private static String timestampPrecision; public static long correctPrecision(long millis) { try { - switch (TIMESTAMP_PRECISION) { + switch (timestampPrecision) { case "us": case "microsecond": return Math.multiplyExact(millis, 1_000L); @@ -80,44 +79,70 @@ public class DateTimeUtils { throw new IoTDBRuntimeException( String.format( "Timestamp overflow, Millisecond: %s , Timestamp precision: %s", - millis, TIMESTAMP_PRECISION), + millis, timestampPrecision), NUMERIC_VALUE_OUT_OF_RANGE.getStatusCode(), true); } } - public static final Function<Long, Long> CAST_TIMESTAMP_TO_MS; - public static final Function<Long, Long> EXTRACT_TIMESTAMP_MS_PART; - public static final Function<Long, Long> EXTRACT_TIMESTAMP_US_PART; - public static final Function<Long, Long> EXTRACT_TIMESTAMP_NS_PART; + private static Function<Long, Long> castTimestampToMs; + private static Function<Long, Long> extractTimestampMsPart; + private static Function<Long, Long> extractTimestampUsPart; + private static Function<Long, Long> extractTimestampNsPart; - static { - switch (CommonDescriptor.getInstance().getConfig().getTimestampPrecision()) { + private static void updateFunction() { + switch (timestampPrecision) { case "us": case "microsecond": - CAST_TIMESTAMP_TO_MS = timestamp -> timestamp / 1000; - EXTRACT_TIMESTAMP_MS_PART = timestamp -> Math.floorMod(timestamp, 1000_000L) / 1000; - EXTRACT_TIMESTAMP_US_PART = timestamp -> Math.floorMod(timestamp, 1000L); - EXTRACT_TIMESTAMP_NS_PART = timestamp -> 0L; + castTimestampToMs = timestamp -> timestamp / 1000; + extractTimestampMsPart = timestamp -> Math.floorMod(timestamp, 1000_000L) / 1000; + extractTimestampUsPart = timestamp -> Math.floorMod(timestamp, 1000L); + extractTimestampNsPart = timestamp -> 0L; break; case "ns": case "nanosecond": - CAST_TIMESTAMP_TO_MS = timestamp -> timestamp / 1000000; - EXTRACT_TIMESTAMP_MS_PART = timestamp -> Math.floorMod(timestamp, 1000_000_000L) / 1000_000; - EXTRACT_TIMESTAMP_US_PART = timestamp -> Math.floorMod(timestamp, 1000_000L) / 1000; - EXTRACT_TIMESTAMP_NS_PART = timestamp -> Math.floorMod(timestamp, 1000L); + castTimestampToMs = timestamp -> timestamp / 1000000; + extractTimestampMsPart = timestamp -> Math.floorMod(timestamp, 1000_000_000L) / 1000_000; + extractTimestampUsPart = timestamp -> Math.floorMod(timestamp, 1000_000L) / 1000; + extractTimestampNsPart = timestamp -> Math.floorMod(timestamp, 1000L); break; case "ms": case "millisecond": default: - CAST_TIMESTAMP_TO_MS = timestamp -> timestamp; - EXTRACT_TIMESTAMP_MS_PART = timestamp -> Math.floorMod(timestamp, 1000L); - EXTRACT_TIMESTAMP_US_PART = timestamp -> 0L; - EXTRACT_TIMESTAMP_NS_PART = timestamp -> 0L; + castTimestampToMs = timestamp -> timestamp; + extractTimestampMsPart = timestamp -> Math.floorMod(timestamp, 1000L); + extractTimestampUsPart = timestamp -> 0L; + extractTimestampNsPart = timestamp -> 0L; break; } } + public static Function<Long, Long> getExtractTimestampMsPartFunction() { + if (extractTimestampMsPart == null) { + throw new IllegalArgumentException("ExtractTimestampMsPart is null"); + } + return extractTimestampMsPart; + } + + public static Function<Long, Long> getExtractTimestampUsPartFunction() { + if (extractTimestampUsPart == null) { + throw new IllegalArgumentException("ExtractTimestampUsPart is null"); + } + return extractTimestampUsPart; + } + + public static Function<Long, Long> getExtractTimestampNsPartFunction() { + if (extractTimestampNsPart == null) { + throw new IllegalArgumentException("ExtractTimestampNsPart is null"); + } + return extractTimestampNsPart; + } + + public static void initTimestampPrecision() { + timestampPrecision = CommonDescriptor.getInstance().getConfig().getTimestampPrecision(); + updateFunction(); + } + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); public static final DateTimeFormatter ISO_LOCAL_DATE_WIDTH_1_2; @@ -787,12 +812,12 @@ public class DateTimeUtils { } public static LocalDate convertToLocalDate(long timestamp, ZoneId zoneId) { - timestamp = CAST_TIMESTAMP_TO_MS.apply(timestamp); + timestamp = castTimestampToMs.apply(timestamp); return Instant.ofEpochMilli(timestamp).atZone(zoneId).toLocalDate(); } public static ZonedDateTime convertToZonedDateTime(long timestamp, ZoneId zoneId) { - timestamp = CAST_TIMESTAMP_TO_MS.apply(timestamp); + timestamp = castTimestampToMs.apply(timestamp); return ZonedDateTime.ofInstant(Instant.ofEpochMilli(timestamp), zoneId); } @@ -924,7 +949,7 @@ public class DateTimeUtils { parser1.getInterpreter().setPredictionMode(PredictionMode.SLL); parser1.removeErrorListeners(); parser1.addErrorListener(SqlParseError.INSTANCE); - return astVisitor.parseDateExpression(parser1.dateExpression(), TIMESTAMP_PRECISION); + return astVisitor.parseDateExpression(parser1.dateExpression(), timestampPrecision); } public static Integer parseDateExpressionToInt(String dateExpression) {
