>From Hussain Towaileb <[email protected]>:
Hussain Towaileb has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21314?usp=email )
Change subject: [NO ISSUE][EXT]: fixes for timezone
......................................................................
[NO ISSUE][EXT]: fixes for timezone
Details:
- allow zone id values such as GMT+01:00
- when iceberg timezone is passed, only updated
the UTC adjusted timestamp, the wallclock timestap
should remain untouched.
- snapshots should not be impacted by provided timezone.
Ext-ref: MB-72261
Change-Id: I2887ab0d9a79bf555a38596fdf941ff88d2e7aab
---
M
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.010.ddl.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.050.query.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.060.query.sqlpp
M
asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.999.ddl.sqlpp
A
asterixdb/asterix-app/src/test/resources/runtimets/results/iceberg/all-data-types/result.050.adm
A
asterixdb/asterix-app/src/test/resources/runtimets/results/iceberg/all-data-types/result.060.adm
M
asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/iceberg/converter/IcebergConverterContext.java
M
asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/IcebergParquetDataParser.java
M
asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
M
asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/iceberg/IcebergSnapshotUtils.java
10 files changed, 207 insertions(+), 35 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/14/21314/1
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.010.ddl.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.010.ddl.sqlpp
index ba010cd..d2cd914 100644
---
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.010.ddl.sqlpp
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.010.ddl.sqlpp
@@ -72,4 +72,42 @@
("catalogName"="myNessieCatalog"),
("format"="parquet"),
("decimal-to-double"="true")
+);
+
+CREATE TYPE allTypesTimesNotConvertedZoneId AS open {};
+CREATE EXTERNAL COLLECTION
allTypesTimesNotConvertedZoneId(allTypesTimesNotConvertedZoneId)
+USING S3
+(
+ ("table-format"="iceberg"),
+ ("namespace"="my_namespace"),
+ ("tableName"="allTypes"),
+ ("region"="custom-region"),
+ ("serviceEndpoint"="%DOCKER_S3_CONTAINER%"),
+ ("pathStyleAddressing"="true"),
+ ("catalogName"="myNessieCatalog"),
+ ("format"="parquet"),
+ ("decimal-to-double"="true"),
+ ("date-to-int"="false"),
+ ("time-to-int"="false"),
+ ("timestamp-to-long"="false"),
+ ("timezone"="GMT+01:00")
+);
+
+CREATE TYPE allTypesTimesNotConvertedZoneIdByName AS open {};
+CREATE EXTERNAL COLLECTION
allTypesTimesNotConvertedZoneIdByName(allTypesTimesNotConvertedZoneIdByName)
+USING S3
+(
+ ("table-format"="iceberg"),
+ ("namespace"="my_namespace"),
+ ("tableName"="allTypes"),
+ ("region"="custom-region"),
+ ("serviceEndpoint"="%DOCKER_S3_CONTAINER%"),
+ ("pathStyleAddressing"="true"),
+ ("catalogName"="myNessieCatalog"),
+ ("format"="parquet"),
+ ("decimal-to-double"="true"),
+ ("date-to-int"="false"),
+ ("time-to-int"="false"),
+ ("timestamp-to-long"="false"),
+ ("timezone"="Africa/Lagos")
);
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.050.query.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.050.query.sqlpp
new file mode 100644
index 0000000..fd6e649
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.050.query.sqlpp
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+SELECT
+ bool_field,
+ byte_field,
+ short_field,
+ int_field,
+ long_field,
+ float_field,
+ double_field,
+ decimal_field,
+ string_field,
+ varchar_field,
+ char_field,
+ uuid_field,
+ print_binary(binary_field, "base64") as binary_field,
+ print_binary(fixed_field, "base64") as fixed_field,
+ date_field,
+ time_field,
+ timestamp_field,
+ timestamp_ntz_field,
+ timestamp_nano_field,
+ interval_ym_field,
+ interval_dt_field,
+ print_binary(geometry_field, "base64") as geometry_field,
+ print_binary(geography_field, "base64") as geography_field,
+ struct_field,
+ list_field,
+ map_field,
+ variant_field,
+ unknown_field
+FROM allTypesTimesNotConvertedZoneId;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.060.query.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.060.query.sqlpp
new file mode 100644
index 0000000..3c57332
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.060.query.sqlpp
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+SELECT
+ bool_field,
+ byte_field,
+ short_field,
+ int_field,
+ long_field,
+ float_field,
+ double_field,
+ decimal_field,
+ string_field,
+ varchar_field,
+ char_field,
+ uuid_field,
+ print_binary(binary_field, "base64") as binary_field,
+ print_binary(fixed_field, "base64") as fixed_field,
+ date_field,
+ time_field,
+ timestamp_field,
+ timestamp_ntz_field,
+ timestamp_nano_field,
+ interval_ym_field,
+ interval_dt_field,
+ print_binary(geometry_field, "base64") as geometry_field,
+ print_binary(geography_field, "base64") as geography_field,
+ struct_field,
+ list_field,
+ map_field,
+ variant_field,
+ unknown_field
+FROM allTypesTimesNotConvertedZoneIdByName;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.999.ddl.sqlpp
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.999.ddl.sqlpp
index 6fa5c73..d0468b9 100644
---
a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.999.ddl.sqlpp
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/iceberg/all-data-types/test.999.ddl.sqlpp
@@ -20,7 +20,11 @@
DROP COLLECTION allTypesTimesConverted;
DROP COLLECTION allTypesTimesNotConverted;
DROP COLLECTION allTypesTimesDefaultExpectingNotConverted;
+DROP COLLECTION allTypesTimesNotConvertedZoneId;
+DROP COLLECTION allTypesTimesNotConvertedZoneIdByName;
DROP TYPE allTypesTimesConverted;
DROP TYPE allTypesTimesNotConverted;
DROP TYPE allTypesTimesDefaultExpectingNotConverted;
+DROP TYPE allTypesTimesNotConvertedZoneId;
+DROP TYPE allTypesTimesNotConvertedZoneIdByName;
DROP CATALOG myNessieCatalog;
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/results/iceberg/all-data-types/result.050.adm
b/asterixdb/asterix-app/src/test/resources/runtimets/results/iceberg/all-data-types/result.050.adm
new file mode 100644
index 0000000..a6c1db5
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/results/iceberg/all-data-types/result.050.adm
@@ -0,0 +1 @@
+{ "binary_field": "AQIDBAUGBwg=", "fixed_field": "SGVsbG8gV29ybGQ=",
"geometry_field": "AQIDBAUGBwgJCg==", "geography_field": "AQIDBAUGBwgJCg0=",
"bool_field": true, "byte_field": 42, "short_field": 1000, "int_field": 42,
"long_field": 9223372036854775807, "float_field": 3.14, "double_field":
2.718281828459045, "decimal_field": 12345.6789, "string_field": "hello world",
"varchar_field": "varchar value one", "char_field": "Hi", "uuid_field":
uuid("550e8400-e29b-41d4-a716-446655440000"), "date_field": date("2024-01-01"),
"time_field": time("10:20:30.000"), "timestamp_field":
datetime("2024-02-03T23:40:00.000"), "timestamp_ntz_field":
datetime("2024-02-04T12:00:00.000"), "timestamp_nano_field":
datetime("2024-02-03T23:40:00.000"), "interval_ym_field": 14,
"interval_dt_field": 37230000000, "struct_field": { "name": "Alice", "age": 30,
"active": true }, "list_field": [ "a", "b", "c" ], "map_field": { "key1":
"value1", "key2": "100" }, "variant_field": "string value", "unknown_field":
null }
\ No newline at end of file
diff --git
a/asterixdb/asterix-app/src/test/resources/runtimets/results/iceberg/all-data-types/result.060.adm
b/asterixdb/asterix-app/src/test/resources/runtimets/results/iceberg/all-data-types/result.060.adm
new file mode 100644
index 0000000..a6c1db5
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/runtimets/results/iceberg/all-data-types/result.060.adm
@@ -0,0 +1 @@
+{ "binary_field": "AQIDBAUGBwg=", "fixed_field": "SGVsbG8gV29ybGQ=",
"geometry_field": "AQIDBAUGBwgJCg==", "geography_field": "AQIDBAUGBwgJCg0=",
"bool_field": true, "byte_field": 42, "short_field": 1000, "int_field": 42,
"long_field": 9223372036854775807, "float_field": 3.14, "double_field":
2.718281828459045, "decimal_field": 12345.6789, "string_field": "hello world",
"varchar_field": "varchar value one", "char_field": "Hi", "uuid_field":
uuid("550e8400-e29b-41d4-a716-446655440000"), "date_field": date("2024-01-01"),
"time_field": time("10:20:30.000"), "timestamp_field":
datetime("2024-02-03T23:40:00.000"), "timestamp_ntz_field":
datetime("2024-02-04T12:00:00.000"), "timestamp_nano_field":
datetime("2024-02-03T23:40:00.000"), "interval_ym_field": 14,
"interval_dt_field": 37230000000, "struct_field": { "name": "Alice", "age": 30,
"active": true }, "list_field": [ "a", "b", "c" ], "map_field": { "key1":
"value1", "key2": "100" }, "variant_field": "string value", "unknown_field":
null }
\ No newline at end of file
diff --git
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/iceberg/converter/IcebergConverterContext.java
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/iceberg/converter/IcebergConverterContext.java
index c7713ac..d7b57ca 100644
---
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/iceberg/converter/IcebergConverterContext.java
+++
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/input/record/reader/aws/iceberg/converter/IcebergConverterContext.java
@@ -25,7 +25,6 @@
import static
org.apache.asterix.external.util.ExternalDataConstants.IcebergOptions.TIME_AS_INT;
import java.time.ZoneId;
-import java.time.ZoneOffset;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
@@ -54,7 +53,7 @@
if (configuredTimeZoneId != null && !configuredTimeZoneId.isEmpty()) {
timeZoneId = TimeZone.getTimeZone(configuredTimeZoneId).toZoneId();
} else {
- timeZoneId = ZoneOffset.UTC;
+ timeZoneId = null;
}
}
diff --git
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/IcebergParquetDataParser.java
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/IcebergParquetDataParser.java
index 79840f2..8817b1a 100644
---
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/IcebergParquetDataParser.java
+++
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/parser/IcebergParquetDataParser.java
@@ -31,6 +31,7 @@
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
@@ -66,6 +67,7 @@
import org.apache.iceberg.types.Types.StructType;
public class IcebergParquetDataParser extends AbstractDataParser implements
IRecordDataParser<Record> {
+ private static final LocalDateTime LOCAL_EPOCH = LocalDateTime.of(1970, 1,
1, 0, 0);
private final IcebergConverterContext parserContext;
private final IExternalFilterValueEmbedder valueEmbedder;
private final Schema projectedSchema;
@@ -350,23 +352,47 @@
}
private void serializeTimestamp(Type type, Object value, DataOutput
output) throws HyracksDataException {
- Instant instant;
switch (value) {
- case OffsetDateTime offsetDateTime -> instant =
offsetDateTime.toInstant();
- case LocalDateTime localDateTime -> {
- ZoneId zoneId = parserContext.getTimeZoneId();
- instant = localDateTime.atZone(zoneId).toInstant();
- }
+ case LocalDateTime localDateTime ->
serializeWallClockTimestamp(type, localDateTime, output);
+ case OffsetDateTime offsetDateTime ->
serializeUtcAdjustedTimestamp(type, offsetDateTime, output);
case null, default -> throw
RuntimeDataException.create(ErrorCode.EXTERNAL_SOURCE_ERROR,
value == null ? "unexpected null value for field type (" +
type + ")"
: "unexpected value type (" + value.getClass() +
") for field type (" + type + ")");
}
+ }
+ private void serializeWallClockTimestamp(Type type, LocalDateTime
localDateTime, DataOutput output)
+ throws HyracksDataException {
if (parserContext.isTimestampAsLong()) {
- long timestampAsLong = type.typeId() == Type.TypeID.TIMESTAMP_NANO
- ? ChronoUnit.NANOS.between(Instant.EPOCH, instant)
+ long value =
+ type.typeId() == Type.TypeID.TIMESTAMP_NANO ?
ChronoUnit.NANOS.between(LOCAL_EPOCH, localDateTime)
+ : ChronoUnit.MICROS.between(LOCAL_EPOCH,
localDateTime);
+ serializeLong(value, output);
+ } else {
+ aDateTime.setValue(ChronoUnit.MILLIS.between(LOCAL_EPOCH,
localDateTime));
+ datetimeSerde.serialize(aDateTime, output);
+ }
+ }
+
+ private void serializeUtcAdjustedTimestamp(Type type, OffsetDateTime
offsetDateTime, DataOutput output)
+ throws HyracksDataException {
+ Instant instant = offsetDateTime.toInstant();
+ ZoneId zoneId = parserContext.getTimeZoneId();
+ if (zoneId != null) {
+ instant = projectToZoneWallClockAsUtcInstant(instant, zoneId);
+ }
+ serializeInstantTimestamp(type, instant, output);
+ }
+
+ private static Instant projectToZoneWallClockAsUtcInstant(Instant instant,
ZoneId zoneId) {
+ return
instant.atZone(zoneId).toLocalDateTime().toInstant(ZoneOffset.UTC);
+ }
+
+ private void serializeInstantTimestamp(Type type, Instant instant,
DataOutput output) throws HyracksDataException {
+ if (parserContext.isTimestampAsLong()) {
+ long value = type.typeId() == Type.TypeID.TIMESTAMP_NANO ?
ChronoUnit.NANOS.between(Instant.EPOCH, instant)
: ChronoUnit.MICROS.between(Instant.EPOCH, instant);
- serializeLong(timestampAsLong, output);
+ serializeLong(value, output);
} else {
aDateTime.setValue(instant.toEpochMilli());
datetimeSerde.serialize(aDateTime, output);
diff --git
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
index dba9bd7..7cd584f 100644
---
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
+++
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/ExternalDataUtils.java
@@ -18,6 +18,7 @@
*/
package org.apache.asterix.external.util;
+import static
org.apache.asterix.common.exceptions.ErrorCode.EXTERNAL_SOURCE_ERROR;
import static
org.apache.asterix.common.exceptions.ErrorCode.INVALID_PARAM_VALUE_ALLOWED_VALUE;
import static org.apache.asterix.common.exceptions.ErrorCode.PARSE_ERROR;
import static
org.apache.asterix.common.exceptions.ErrorCode.PROPERTY_INVALID_VALUE_TYPE;
@@ -52,6 +53,7 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
@@ -60,9 +62,9 @@
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Optional;
-import java.util.Set;
import java.util.TimeZone;
import java.util.function.BiPredicate;
import java.util.regex.Matcher;
@@ -144,7 +146,7 @@
public class ExternalDataUtils {
- private static final Set<String> validTimeZones =
Set.of(TimeZone.getAvailableIDs());
+ private static final Map<String, String> validTimeZonesMap = new
HashMap<>();
private static final Map<ATypeTag, IValueParserFactory>
valueParserFactoryMap = new EnumMap<>(ATypeTag.class);
private static final int DEFAULT_MAX_ARGUMENT_SZ = 1024 * 1024;
private static final int HEADER_FUDGE = 64;
@@ -158,6 +160,9 @@
valueParserFactoryMap.put(ATypeTag.BIGINT, LongParserFactory.INSTANCE);
valueParserFactoryMap.put(ATypeTag.STRING,
UTF8StringParserFactory.INSTANCE);
valueParserFactoryMap.put(ATypeTag.BOOLEAN,
BooleanParserFactory.INSTANCE);
+ for (String id : TimeZone.getAvailableIDs()) {
+ validTimeZonesMap.put(id.toLowerCase(Locale.ROOT), id);
+ }
}
private ExternalDataUtils() {
@@ -539,10 +544,9 @@
throw new
CompilationException(ErrorCode.INVALID_DELTA_TABLE_FORMAT,
configuration.get(ExternalDataConstants.KEY_FORMAT));
}
- if
(configuration.containsKey(ExternalDataConstants.DeltaOptions.TIMEZONE)
- &&
!validTimeZones.contains(configuration.get(ExternalDataConstants.DeltaOptions.TIMEZONE)))
{
- throw new CompilationException(ErrorCode.INVALID_TIMEZONE,
-
configuration.get(ExternalDataConstants.DeltaOptions.TIMEZONE));
+ if
(configuration.containsKey(ExternalDataConstants.DeltaOptions.TIMEZONE)) {
+ String resolved =
resolveTimeZone(configuration.get(ExternalDataConstants.DeltaOptions.TIMEZONE));
+ configuration.put(ExternalDataConstants.DeltaOptions.TIMEZONE,
resolved);
}
}
@@ -1011,21 +1015,26 @@
return isParquetFormat(properties) || isDeltaTable(properties) ||
isIcebergTable(properties);
}
- /**
- * Validate Parquet dataset's declared type and configuration
- *
- * @param properties external dataset configuration
- * @param datasetRecordType dataset declared type
- */
+ private static String resolveTimeZone(String timeZoneId) throws
CompilationException {
+ String canonical =
validTimeZonesMap.get(timeZoneId.toLowerCase(Locale.ROOT));
+ if (canonical != null) {
+ return canonical;
+ }
+ try {
+ return ZoneId.of(timeZoneId).getId();
+ } catch (Exception e) {
+ throw CompilationException.create(EXTERNAL_SOURCE_ERROR, e,
getMessageOrToString(e));
+ }
+ }
+
public static void validateParquetTypeAndConfiguration(Map<String, String>
properties,
ARecordType datasetRecordType) throws CompilationException {
if (isParquetFormat(properties)) {
if (datasetRecordType.getFieldTypes().length != 0) {
throw new
CompilationException(ErrorCode.UNSUPPORTED_TYPE_FOR_PARQUET,
datasetRecordType.getTypeName());
- } else if (properties.containsKey(ParquetOptions.TIMEZONE)
- &&
!validTimeZones.contains(properties.get(ParquetOptions.TIMEZONE))) {
- //Ensure the configured time zone id is correct
- throw new CompilationException(ErrorCode.INVALID_TIMEZONE,
properties.get(ParquetOptions.TIMEZONE));
+ } else if (properties.containsKey(ParquetOptions.TIMEZONE)) {
+ String resolved =
resolveTimeZone(properties.get(ParquetOptions.TIMEZONE));
+ properties.put(ParquetOptions.TIMEZONE, resolved);
}
}
}
diff --git
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/iceberg/IcebergSnapshotUtils.java
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/iceberg/IcebergSnapshotUtils.java
index ab2ffa9..b2a2cdf 100644
---
a/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/iceberg/IcebergSnapshotUtils.java
+++
b/asterixdb/asterix-external-data/src/main/java/org/apache/asterix/external/util/iceberg/IcebergSnapshotUtils.java
@@ -28,7 +28,6 @@
import java.time.LocalDate;
import java.time.LocalDateTime;
-import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeParseException;
import java.util.Map;
@@ -36,7 +35,6 @@
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
-import org.apache.asterix.external.util.ExternalDataConstants;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.iceberg.Table;
import org.apache.iceberg.catalog.Catalog;
@@ -49,8 +47,6 @@
public static Optional<Long> validateAndGetSnapshot(Map<String, String>
properties) throws CompilationException {
String snapshotId = properties.get(ICEBERG_SNAPSHOT_ID_PROPERTY_KEY);
String snapshotTimestamp =
properties.get(ICEBERG_SNAPSHOT_TIMESTAMP_PROPERTY_KEY);
- String timeZoneId =
properties.get(ExternalDataConstants.IcebergOptions.TIMEZONE);
- ZoneId zoneId = timeZoneId != null ? ZoneId.of(timeZoneId) :
ZoneOffset.UTC;
if (snapshotId != null && snapshotTimestamp != null) {
throw new
CompilationException(PARAM_NOT_ALLOWED_IF_PARAM_IS_PRESENT,
ICEBERG_SNAPSHOT_TIMESTAMP_PROPERTY_KEY,
ICEBERG_SNAPSHOT_ID_PROPERTY_KEY);
@@ -60,7 +56,7 @@
if (snapshotId != null) {
return Optional.of(Long.parseLong(snapshotId));
} else if (snapshotTimestamp != null) {
- return Optional.of(parseTimestamp(snapshotTimestamp, zoneId));
+ return Optional.of(parseTimestamp(snapshotTimestamp));
} else {
return Optional.empty();
}
@@ -70,7 +66,7 @@
}
}
- private static long parseTimestamp(String timestamp, ZoneId zoneId) throws
CompilationException {
+ private static long parseTimestamp(String timestamp) throws
CompilationException {
try {
// try parsing as a long first
return Long.parseLong(timestamp);
@@ -79,14 +75,14 @@
try {
// try parsing as ISO 8601 date, e.g., "yyyy-MM-dd"
- return LocalDate.parse(timestamp,
ISO_LOCAL_DATE).atStartOfDay(zoneId).toInstant().toEpochMilli();
+ return LocalDate.parse(timestamp,
ISO_LOCAL_DATE).atStartOfDay(ZoneOffset.UTC).toInstant().toEpochMilli();
} catch (DateTimeParseException ignored) {
}
try {
// try parsing as ISO 8601 timestamp, e.g., "yyyy-MM-dd'T'HH:mm:ss"
LocalDateTime localDateTime = LocalDateTime.parse(timestamp,
ISO_LOCAL_DATE_TIME);
- return localDateTime.atZone(zoneId).toInstant().toEpochMilli();
+ return
localDateTime.atZone(ZoneOffset.UTC).toInstant().toEpochMilli();
} catch (DateTimeParseException ignored) {
throw CompilationException.create(EXTERNAL_SOURCE_ERROR,
"unexpected TIMESTAMP snapshot format. Allow formats are:
(milliseconds, yyyy-MM-dd or "
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21314?usp=email
To unsubscribe, or for help writing mail filters, visit
https://asterix-gerrit.ics.uci.edu/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: lumina
Gerrit-Change-Id: I2887ab0d9a79bf555a38596fdf941ff88d2e7aab
Gerrit-Change-Number: 21314
Gerrit-PatchSet: 1
Gerrit-Owner: Hussain Towaileb <[email protected]>