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

amashenkov pushed a commit to branch ignite-24979
in repository https://gitbox.apache.org/repos/asf/ignite-3.git

commit c7d54dfd68c7e3c16ef06728690358f48a9e2f95
Author: amashenkov <[email protected]>
AuthorDate: Tue Apr 1 13:37:26 2025 +0300

    Optimize TypeUtils.fromInternal and toInternal methods.
---
 .../internal/sql/engine/exec/ExecutionContext.java |   2 +-
 .../internal/sql/engine/exec/SqlRowHandler.java    |   6 +-
 .../sql/engine/exec/exp/IgniteSqlFunctions.java    |   3 +-
 .../prepare/ddl/DdlSqlToCommandConverter.java      |  12 +-
 .../prepare/pruning/PartitionPruningPredicate.java |   3 +-
 .../ignite/internal/sql/engine/util/TypeUtils.java | 133 ++++++++++++++++++++-
 .../sql/engine/exec/row/SqlRowHandlerTest.java     |   3 +-
 .../prepare/ddl/DdlSqlToCommandConverterTest.java  |   3 +-
 .../internal/sql/engine/util/TypeUtilsTest.java    |  10 ++
 9 files changed, 151 insertions(+), 24 deletions(-)

diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionContext.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionContext.java
index ee5abe01aa8..32b064f1c35 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionContext.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ExecutionContext.java
@@ -298,7 +298,7 @@ public class ExecutionContext<RowT> implements DataContext {
             return null;
         }
 
-        return TypeUtils.toInternal(param, storageType == null ? 
param.getClass() : storageType);
+        return storageType == null ? TypeUtils.toInternal(param, 
param.getClass()) : TypeUtils.toInternal(param, storageType);
     }
 
     /**
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/SqlRowHandler.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/SqlRowHandler.java
index e31442dfdcb..4fcff1628c4 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/SqlRowHandler.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/SqlRowHandler.java
@@ -35,11 +35,9 @@ import 
org.apache.ignite.internal.sql.engine.exec.SqlRowHandler.RowWrapper;
 import org.apache.ignite.internal.sql.engine.exec.row.RowSchema;
 import org.apache.ignite.internal.sql.engine.exec.row.RowSchemaTypes;
 import org.apache.ignite.internal.sql.engine.exec.row.TypeSpec;
-import org.apache.ignite.internal.sql.engine.util.Commons;
 import org.apache.ignite.internal.sql.engine.util.TypeUtils;
 import org.apache.ignite.internal.type.DecimalNativeType;
 import org.apache.ignite.internal.type.NativeType;
-import org.apache.ignite.internal.type.NativeTypeSpec;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -262,7 +260,7 @@ public class SqlRowHandler implements 
RowHandler<RowWrapper> {
 
             NativeType nativeType = RowSchemaTypes.toNativeType(schemaType);
 
-            value = TypeUtils.fromInternal(value, 
NativeTypeSpec.toClass(nativeType.spec(), schemaType.isNullable()));
+            value = TypeUtils.fromInternal(value, nativeType.spec());
 
             assert value != null : nativeType;
 
@@ -365,7 +363,7 @@ public class SqlRowHandler implements 
RowHandler<RowWrapper> {
                 return null;
             }
 
-            return TypeUtils.toInternal(value, 
Commons.nativeTypeToClass(nativeType));
+            return TypeUtils.toInternal(value, nativeType.spec());
         }
 
         @Override
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteSqlFunctions.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteSqlFunctions.java
index e469dd76672..375f3bf5a49 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteSqlFunctions.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/IgniteSqlFunctions.java
@@ -37,6 +37,7 @@ import org.apache.ignite.internal.lang.IgniteStringBuilder;
 import org.apache.ignite.internal.sql.engine.util.Commons;
 import org.apache.ignite.internal.sql.engine.util.IgniteMath;
 import org.apache.ignite.internal.sql.engine.util.TypeUtils;
+import org.apache.ignite.internal.type.NativeTypeSpec;
 import org.apache.ignite.sql.SqlException;
 import org.jetbrains.annotations.Nullable;
 
@@ -451,7 +452,7 @@ public class IgniteSqlFunctions {
     }
 
     public static int currentTime(DataContext ctx) {
-        return (int) TypeUtils.toInternal(LocalTime.now(), LocalTime.class);
+        return (int) TypeUtils.toInternal(LocalTime.now(), 
NativeTypeSpec.TIME);
     }
 
     /** LEAST2. */
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
index b6be840005f..e6f6645063f 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverter.java
@@ -42,9 +42,6 @@ import static 
org.apache.ignite.lang.ErrorGroups.Sql.STMT_VALIDATION_ERR;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.Duration;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
 import java.time.Period;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -140,6 +137,7 @@ import 
org.apache.ignite.internal.sql.engine.sql.IgniteSqlZoneOption;
 import org.apache.ignite.internal.sql.engine.sql.IgniteSqlZoneOptionMode;
 import org.apache.ignite.internal.sql.engine.type.UuidType;
 import org.apache.ignite.internal.sql.engine.util.Commons;
+import org.apache.ignite.internal.type.NativeTypeSpec;
 import org.apache.ignite.lang.IgniteException;
 import org.apache.ignite.sql.ColumnType;
 import org.apache.ignite.sql.SqlException;
@@ -993,12 +991,12 @@ public class DdlSqlToCommandConverter {
                     try {
                         literal = 
SqlParserUtil.parseDateLiteral(literal.getValueAs(String.class), 
literal.getParserPosition());
                         int val = 
literal.getValueAs(DateString.class).getDaysSinceEpoch();
-                        return fromInternal(val, LocalDate.class);
+                        return fromInternal(val, NativeTypeSpec.DATE);
                     } catch (CalciteContextException e) {
                         literal = 
SqlParserUtil.parseTimestampLiteral(literal.getValueAs(String.class), 
literal.getParserPosition());
                         TimestampString tsString = 
literal.getValueAs(TimestampString.class);
                         int val = 
convertToIntExact(TimeUnit.MILLISECONDS.toDays(tsString.getMillisSinceEpoch()));
-                        return fromInternal(val, LocalDate.class);
+                        return fromInternal(val, NativeTypeSpec.DATE);
                     }
                 }
                 case TIME: {
@@ -1009,13 +1007,13 @@ public class DdlSqlToCommandConverter {
                     }
                     literal = SqlParserUtil.parseTimeLiteral(strLiteral, 
literal.getParserPosition());
                     int val = 
literal.getValueAs(TimeString.class).getMillisOfDay();
-                    return fromInternal(val, LocalTime.class);
+                    return fromInternal(val, NativeTypeSpec.TIME);
                 }
                 case DATETIME: {
                     literal = 
SqlParserUtil.parseTimestampLiteral(literal.getValueAs(String.class), 
literal.getParserPosition());
                     var tsString = literal.getValueAs(TimestampString.class);
 
-                    return fromInternal(tsString.getMillisSinceEpoch(), 
LocalDateTime.class);
+                    return fromInternal(tsString.getMillisSinceEpoch(), 
NativeTypeSpec.DATETIME);
                 }
                 case TIMESTAMP:
                     // TODO: IGNITE-17376
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningPredicate.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningPredicate.java
index 8879501c4ac..6627300e88c 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningPredicate.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/pruning/PartitionPruningPredicate.java
@@ -159,8 +159,7 @@ public final class PartitionPruningPredicate {
                 NativeType physicalType = descriptor.physicalType();
 
                 Object valueInInternalForm = 
expressionFactory.scalar(node).get(context);
-                Class<?> storageType = 
NativeTypeSpec.toClass(physicalType.spec(), descriptor.nullable());
-                Object value = TypeUtils.fromInternal(valueInInternalForm, 
storageType);
+                Object value = TypeUtils.fromInternal(valueInInternalForm, 
physicalType.spec());
 
                 partitionCalculator.append(value);
             }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
index 32b321816cf..546fdf12f26 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
@@ -272,14 +272,73 @@ public class TypeUtils {
             var nativeTypeSpec = NativeTypeSpec.fromClass((Class<?>) 
storageType);
             assert nativeTypeSpec != null : "No native type spec for type: " + 
storageType;
 
-            var customType = 
SafeCustomTypeInternalConversion.INSTANCE.tryConvertToInternal(val, 
nativeTypeSpec);
-            return customType != null ? customType : val;
+            return 
SafeCustomTypeInternalConversion.INSTANCE.tryConvertToInternal(val, 
nativeTypeSpec);
         }
     }
 
     /**
-     * FromInternal.
-     * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859
+     * Converts the given value to its presentation used by the execution 
engine.
+     */
+    public static Object toInternal(Object val, NativeTypeSpec spec) {
+        switch (spec) {
+            case INT8:
+                return SqlFunctions.toByte(val);
+            case INT16:
+                return SqlFunctions.toShort(val);
+            case INT32:
+                return SqlFunctions.toInt(val);
+            case INT64:
+                return SqlFunctions.toLong(val);
+            case FLOAT:
+                return SqlFunctions.toFloat(val);
+            case DOUBLE:
+                return SqlFunctions.toDouble(val);
+            case DECIMAL:
+                return SqlFunctions.toBigDecimal(val);
+            case STRING:
+                return val;
+            case BYTES: {
+                if (val instanceof String) {
+                    return new ByteString(((String) 
val).getBytes(StandardCharsets.UTF_8));
+                } else if (val instanceof byte[]) {
+                    return new ByteString((byte[]) val);
+                } else {
+                    assert val instanceof ByteString : "Expected ByteString 
but got " + val + ", type=" + val.getClass().getTypeName();
+                    return val;
+                }
+            }
+            case DATE:
+                return (int) ((LocalDate) val).toEpochDay();
+            case TIME:
+                return (int) (TimeUnit.NANOSECONDS.toMillis(((LocalTime) 
val).toNanoOfDay()));
+            case DATETIME: {
+                var dt = (LocalDateTime) val;
+
+                return 
TimeUnit.SECONDS.toMillis(dt.toEpochSecond(ZoneOffset.UTC)) + 
TimeUnit.NANOSECONDS.toMillis(dt.getNano());
+            }
+            case TIMESTAMP: {
+                var timeStamp = (Instant) val;
+
+                return timeStamp.toEpochMilli();
+            }
+            case BOOLEAN:
+                return SqlFunctions.toBoolean(val);
+            // case DURATION:
+            //     return TimeUnit.SECONDS.toMillis(((Duration) 
val).getSeconds())
+            //             + TimeUnit.NANOSECONDS.toMillis(((Duration) 
val).getNano());
+            // case PREIOD:
+            //     return (int) ((Period) val).toTotalMonths();
+            case UUID:
+                // Fallthrough. UUID is a custom type.
+            default: {
+                var customType = 
SafeCustomTypeInternalConversion.INSTANCE.tryConvertToInternal(val, spec);
+                return customType != null ? customType : val;
+            }
+        }
+    }
+
+    /**
+     * Converts the value from its presentation used by the execution engine.
      */
     public static @Nullable Object fromInternal(@Nullable Object val, Type 
storageType) {
         if (val == null) {
@@ -302,8 +361,70 @@ public class TypeUtils {
             var nativeTypeSpec = NativeTypeSpec.fromClass((Class<?>) 
storageType);
             assert nativeTypeSpec != null : "No native type spec for type: " + 
storageType;
 
-            var customType = 
SafeCustomTypeInternalConversion.INSTANCE.tryConvertFromInternal(val, 
nativeTypeSpec);
-            return customType != null ? customType : val;
+            return 
SafeCustomTypeInternalConversion.INSTANCE.tryConvertFromInternal(val, 
nativeTypeSpec);
+        }
+    }
+
+    /**
+     * Converts the value from its presentation used by the execution engine.
+     */
+    public static @Nullable Object fromInternal(@Nullable Object val, 
NativeTypeSpec spec) {
+        if (val == null) {
+            return null;
+        }
+        switch (spec) {
+            case INT8:
+            case INT16:
+            case INT32:
+            case INT64:
+            case FLOAT:
+            case DOUBLE: {
+                assert val instanceof Number;
+                return val;
+            }
+            case DECIMAL: {
+                assert val instanceof BigDecimal;
+                return val;
+            }
+            case STRING: {
+                assert val instanceof String;
+                return val;
+            }
+            case BYTES:
+                return ((ByteString) val).getBytes();
+            case DATE: {
+                assert val instanceof Integer;
+                return LocalDate.ofEpochDay((Integer) val);
+            }
+            case TIME: {
+                assert val instanceof Integer;
+                return 
LocalTime.ofNanoOfDay(TimeUnit.MILLISECONDS.toNanos(Long.valueOf((Integer) 
val)));
+            }
+            case DATETIME: {
+                assert val instanceof Long;
+                return LocalDateTime.ofInstant(Instant.ofEpochMilli((Long) 
val), ZoneOffset.UTC);
+            }
+            case TIMESTAMP: {
+                assert val instanceof Long;
+                return Instant.ofEpochMilli((Long) val);
+            }
+            case BOOLEAN: {
+                assert val instanceof Boolean;
+                return val;
+            }
+            // case DURATION: {
+            //     assert val instanceof Long;
+            //    return Duration.ofMillis((Long) val);
+            // }
+            // case PREIOD: {
+            //     assert val instanceof Integer;
+            //     return Period.of((Integer) val / 12, (Integer) val % 12, 0);
+            //     }
+            case UUID:
+                // Fallthrough. UUID is a custom type.
+            default: {
+                return 
SafeCustomTypeInternalConversion.INSTANCE.tryConvertFromInternal(val, spec);
+            }
         }
     }
 
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/row/SqlRowHandlerTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/row/SqlRowHandlerTest.java
index bcaaa445cea..1b800ded7eb 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/row/SqlRowHandlerTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/exec/row/SqlRowHandlerTest.java
@@ -372,8 +372,7 @@ public class SqlRowHandlerTest extends IgniteAbstractTest {
         } else {
             BaseTypeSpec baseTypeSpec = (BaseTypeSpec) typeSpec;
             NativeType nativeType = baseTypeSpec.nativeType();
-            Class<?> type = Commons.nativeTypeToClass(nativeType);
-            return TypeUtils.toInternal(value, type);
+            return TypeUtils.toInternal(value, nativeType.spec());
         }
     }
 }
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
index d56c893f5ca..d4517da6058 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
@@ -86,6 +86,7 @@ import 
org.apache.ignite.internal.sql.engine.prepare.PlanningContext;
 import org.apache.ignite.internal.sql.engine.util.Commons;
 import org.apache.ignite.internal.sql.engine.util.SqlTestUtils;
 import org.apache.ignite.internal.testframework.WithSystemProperty;
+import org.apache.ignite.internal.type.NativeTypeSpec;
 import org.apache.ignite.sql.ColumnType;
 import org.hamcrest.CustomMatcher;
 import org.hamcrest.Matcher;
@@ -618,7 +619,7 @@ public class DdlSqlToCommandConverterTest extends 
AbstractDdlSqlToCommandConvert
         List<DynamicTest> testItems = new ArrayList<>();
         PlanningContext ctx = createContext();
 
-        fillTestCase("VARBINARY", "x'0102'", testItems, true, ctx, 
fromInternal(new byte[]{(byte) 1, (byte) 2}, byte[].class));
+        fillTestCase("VARBINARY", "x'0102'", testItems, true, ctx, 
fromInternal(new byte[]{(byte) 1, (byte) 2}, NativeTypeSpec.BYTES));
         fillTestCase("VARBINARY", "'0102'", testItems, false, ctx);
         fillTestCase("VARBINARY", "1", testItems, false, ctx);
 
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/TypeUtilsTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/TypeUtilsTest.java
index 60b832effe1..20bf8be5e93 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/TypeUtilsTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/TypeUtilsTest.java
@@ -55,6 +55,7 @@ import 
org.apache.ignite.internal.sql.engine.type.IgniteCustomTypeSpec;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
 import org.apache.ignite.internal.sql.engine.type.UuidType;
 import org.apache.ignite.internal.testframework.BaseIgniteAbstractTest;
+import org.apache.ignite.internal.type.NativeTypeSpec;
 import org.apache.ignite.internal.type.NativeTypes;
 import org.apache.ignite.lang.ErrorGroups.Sql;
 import org.apache.ignite.sql.ColumnType;
@@ -262,12 +263,21 @@ public class TypeUtilsTest extends BaseIgniteAbstractTest 
{
     @ParameterizedTest
     @MethodSource("valueAndType")
     public void testToFromInternalMatch(Object value, Class<?> type) {
+        var nativeTypeSpec = NativeTypeSpec.fromClass(type);
+
         Object internal = TypeUtils.toInternal(value, type);
         assertNotNull(internal, "Conversion to internal has produced null");
 
+        internal = TypeUtils.toInternal(value, nativeTypeSpec);
+        assertNotNull(internal, "Conversion to internal has produced null");
+
         Object original = TypeUtils.fromInternal(internal, type);
         assertEquals(value, original, "toInternal -> fromInternal");
         assertNotNull(original, "Conversion from internal has produced null");
+
+        original = TypeUtils.fromInternal(internal, nativeTypeSpec);
+        assertEquals(value, original, "toInternal -> fromInternal");
+        assertNotNull(original, "Conversion from internal has produced null");
     }
 
     private static Stream<Arguments> valueAndType() {

Reply via email to