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

lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new cb136340a [core] Support TimestampToNumericPrimitiveCastRule in 
casting (#3854)
cb136340a is described below

commit cb136340af4b5037d44b3adb97d7ec825833761c
Author: xuzifu666 <[email protected]>
AuthorDate: Mon Aug 12 15:21:05 2024 +0800

    [core] Support TimestampToNumericPrimitiveCastRule in casting (#3854)
---
 .../org/apache/paimon/casting/CastExecutors.java   |  1 +
 .../TimestampToNumericPrimitiveCastRule.java       | 71 ++++++++++++++++++++++
 .../apache/paimon/casting/CastExecutorTest.java    | 53 ++++++++++++++++
 3 files changed, 125 insertions(+)

diff --git 
a/paimon-core/src/main/java/org/apache/paimon/casting/CastExecutors.java 
b/paimon-core/src/main/java/org/apache/paimon/casting/CastExecutors.java
index 054d6fca1..beb7aa0a5 100644
--- a/paimon-core/src/main/java/org/apache/paimon/casting/CastExecutors.java
+++ b/paimon-core/src/main/java/org/apache/paimon/casting/CastExecutors.java
@@ -70,6 +70,7 @@ public class CastExecutors {
                 .addRule(TimestampToTimeCastRule.INSTANCE)
                 .addRule(DateToTimestampCastRule.INSTANCE)
                 .addRule(TimeToTimestampCastRule.INSTANCE)
+                .addRule(TimestampToNumericPrimitiveCastRule.INSTANCE)
                 // To binary rules
                 .addRule(BinaryToBinaryCastRule.INSTANCE);
     }
diff --git 
a/paimon-core/src/main/java/org/apache/paimon/casting/TimestampToNumericPrimitiveCastRule.java
 
b/paimon-core/src/main/java/org/apache/paimon/casting/TimestampToNumericPrimitiveCastRule.java
new file mode 100644
index 000000000..f7cd21bab
--- /dev/null
+++ 
b/paimon-core/src/main/java/org/apache/paimon/casting/TimestampToNumericPrimitiveCastRule.java
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+package org.apache.paimon.casting;
+
+import org.apache.paimon.data.Timestamp;
+import org.apache.paimon.types.DataType;
+import org.apache.paimon.types.DataTypeFamily;
+import org.apache.paimon.types.DataTypeRoot;
+import org.apache.paimon.utils.DateTimeUtils;
+
+/**
+ * {@link DataTypeRoot#TIMESTAMP_WITHOUT_TIME_ZONE}/{@link
+ * DataTypeRoot#TIMESTAMP_WITH_LOCAL_TIME_ZONE} to {@link 
DataTypeFamily#NUMERIC} cast rule.
+ */
+public class TimestampToNumericPrimitiveCastRule extends 
AbstractCastRule<Timestamp, Number> {
+
+    static final TimestampToNumericPrimitiveCastRule INSTANCE =
+            new TimestampToNumericPrimitiveCastRule();
+
+    private TimestampToNumericPrimitiveCastRule() {
+        super(
+                CastRulePredicate.builder()
+                        .input(DataTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE)
+                        .input(DataTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+                        .target(DataTypeRoot.BIGINT)
+                        .target(DataTypeRoot.INTEGER)
+                        .build());
+    }
+
+    @Override
+    public CastExecutor<Timestamp, Number> create(DataType inputType, DataType 
targetType) {
+        if (inputType.is(DataTypeRoot.TIMESTAMP_WITHOUT_TIME_ZONE)) {
+            if (targetType.is(DataTypeRoot.BIGINT)) {
+                return value -> 
DateTimeUtils.unixTimestamp(value.getMillisecond());
+            } else if (targetType.is(DataTypeRoot.INTEGER)) {
+                return value -> (int) 
DateTimeUtils.unixTimestamp(value.getMillisecond());
+            }
+        } else if (inputType.is(DataTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE)) {
+            if (targetType.is(DataTypeRoot.BIGINT)) {
+                return value ->
+                        DateTimeUtils.unixTimestamp(
+                                
Timestamp.fromLocalDateTime(value.toLocalDateTime())
+                                        .getMillisecond());
+            } else if (targetType.is(DataTypeRoot.INTEGER)) {
+                return value ->
+                        (int)
+                                DateTimeUtils.unixTimestamp(
+                                        
Timestamp.fromLocalDateTime(value.toLocalDateTime())
+                                                .getMillisecond());
+            }
+        }
+
+        return null;
+    }
+}
diff --git 
a/paimon-core/src/test/java/org/apache/paimon/casting/CastExecutorTest.java 
b/paimon-core/src/test/java/org/apache/paimon/casting/CastExecutorTest.java
index ff805993c..5c41f2b5f 100644
--- a/paimon-core/src/test/java/org/apache/paimon/casting/CastExecutorTest.java
+++ b/paimon-core/src/test/java/org/apache/paimon/casting/CastExecutorTest.java
@@ -286,6 +286,59 @@ public class CastExecutorTest {
                         DateTimeUtils.formatTimestamp(timestamp, 
TimeZone.getDefault(), 5)));
     }
 
+    @Test
+    public void testTimestampToNumeric() {
+        long mills = System.currentTimeMillis() / 1000 * 1000;
+        Timestamp timestamp1 = Timestamp.fromEpochMillis(mills);
+        long millisecond = timestamp1.getMillisecond();
+        Timestamp timestamp2 =
+                Timestamp.fromLocalDateTime(
+                        DateTimeUtils.toLocalDateTime(mills, 
TimeZone.getDefault().toZoneId()));
+        long millisecond1 = timestamp2.getMillisecond();
+
+        // cast from TimestampType to BigIntType or IntType
+        compareCastResult(
+                CastExecutors.resolve(new TimestampType(3), new 
BigIntType(false)),
+                timestamp1,
+                DateTimeUtils.unixTimestamp(millisecond));
+
+        compareCastResult(
+                CastExecutors.resolve(new LocalZonedTimestampType(3), new 
BigIntType(false)),
+                timestamp2,
+                DateTimeUtils.unixTimestamp(millisecond1));
+
+        compareCastResult(
+                CastExecutors.resolve(new TimestampType(3), new 
IntType(false)),
+                timestamp1,
+                (int) DateTimeUtils.unixTimestamp(millisecond));
+
+        compareCastResult(
+                CastExecutors.resolve(new LocalZonedTimestampType(3), new 
IntType(false)),
+                timestamp2,
+                (int) DateTimeUtils.unixTimestamp(millisecond1));
+
+        // cast from BigIntType or IntType to TimestampType
+        compareCastResult(
+                CastExecutors.resolve(new BigIntType(false), new 
TimestampType(3)),
+                DateTimeUtils.unixTimestamp(millisecond),
+                timestamp1);
+
+        compareCastResult(
+                CastExecutors.resolve(new BigIntType(false), new 
LocalZonedTimestampType(3)),
+                DateTimeUtils.unixTimestamp(millisecond),
+                timestamp2);
+
+        compareCastResult(
+                CastExecutors.resolve(new IntType(false), new 
TimestampType(3)),
+                (int) DateTimeUtils.unixTimestamp(millisecond),
+                timestamp1);
+
+        compareCastResult(
+                CastExecutors.resolve(new IntType(false), new 
LocalZonedTimestampType(3)),
+                (int) DateTimeUtils.unixTimestamp(millisecond),
+                timestamp2);
+    }
+
     @Test
     public void testTimeToString() {
         compareCastResult(

Reply via email to