This is an automated email from the ASF dual-hosted git repository. amashenkov pushed a commit to branch ignite-22393 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
commit fa378ea4fb1380de60d083e6ddc6537482c62fdd Author: amashenkov <[email protected]> AuthorDate: Fri Jun 7 14:06:49 2024 +0300 wip --- .../ignite/internal/marshaller/FieldAccessor.java | 10 +- .../apache/ignite/internal/table/ItMapperTest.java | 138 +++++++++++++++++++++ 2 files changed, 143 insertions(+), 5 deletions(-) diff --git a/modules/marshaller-common/src/main/java/org/apache/ignite/internal/marshaller/FieldAccessor.java b/modules/marshaller-common/src/main/java/org/apache/ignite/internal/marshaller/FieldAccessor.java index 8340ac4be1..75aee3f679 100644 --- a/modules/marshaller-common/src/main/java/org/apache/ignite/internal/marshaller/FieldAccessor.java +++ b/modules/marshaller-common/src/main/java/org/apache/ignite/internal/marshaller/FieldAccessor.java @@ -76,14 +76,14 @@ abstract class FieldAccessor { validateColumnType(col, field.getType()); } - BinaryMode mode = BinaryMode.forClass(field.getType()); + BinaryMode fieldAccessMode = BinaryMode.forClass(field.getType()); MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(type, MethodHandles.lookup()); VarHandle varHandle = lookup.unreflectVarHandle(field); - assert mode != null : "Invalid mode for type: " + field.getType(); + assert fieldAccessMode != null : "Invalid fieldAccessMode for type: " + field.getType(); - switch (mode) { + switch (fieldAccessMode) { case P_BOOLEAN: return new BooleanPrimitiveAccessor(varHandle, colIdx); @@ -123,10 +123,10 @@ abstract class FieldAccessor { case DATETIME: case TIMESTAMP: case POJO: - return new ReferenceFieldAccessor(varHandle, colIdx, mode, col.scale(), typeConverter); + return new ReferenceFieldAccessor(varHandle, colIdx, col.type(), col.scale(), typeConverter); default: - assert false : "Invalid mode " + mode; + assert false : "Invalid field access mode " + fieldAccessMode; } throw new IllegalArgumentException("Failed to create accessor for field [name=" + field.getName() + ']'); diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItMapperTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItMapperTest.java new file mode 100644 index 0000000000..42e0caf6de --- /dev/null +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/table/ItMapperTest.java @@ -0,0 +1,138 @@ +/* + * 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.ignite.internal.table; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneOffset; +import java.util.Date; +import java.util.Objects; +import org.apache.ignite.catalog.ColumnType; +import org.apache.ignite.catalog.definitions.ColumnDefinition; +import org.apache.ignite.catalog.definitions.TableDefinition; +import org.apache.ignite.internal.ClusterPerClassIntegrationTest; +import org.apache.ignite.internal.app.IgniteImpl; +import org.apache.ignite.table.mapper.Mapper; +import org.apache.ignite.table.mapper.TypeConverter; +import org.junit.jupiter.api.Test; + +/** + * POJO mappers test. + */ +public class ItMapperTest extends ClusterPerClassIntegrationTest { + @Test + void valueWithTypeConverter() throws Exception { + IgniteImpl node = CLUSTER.node(0); + + var tableDef = TableDefinition.builder("PrimTestTable") + .columns( + ColumnDefinition.column("ID", ColumnType.INT32), + ColumnDefinition.column("VAL", ColumnType.DATE) + ) + .primaryKey("ID") + .build(); + + node.catalog().createTableAsync(tableDef).get(); + + var keyMapper = Mapper.of(Integer.class); + var valMapper = Mapper.of(Date.class, "VAL", new DateTypeConverter()); + var table = node.tables().table("PrimTestTable").keyValueView(keyMapper, valMapper); + + var expected = Date.from(LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC)); + table.put(null, 1, expected); + var actual = table.get(null, 1); + + assertEquals(expected, actual); + } + + @Test + void pojoWithTypeConverter() throws Exception { + IgniteImpl node = CLUSTER.node(0); + + var tableDef = TableDefinition.builder("PojoTestTable") + .key(Integer.class) + .value(MyPojoWithDate.class) + .build(); + + node.catalog().createTableAsync(tableDef).get(); + + var keyMapper = Mapper.of(Integer.class); + var valMapper = Mapper.builder(MyPojoWithDate.class) + .map("name", "NAME") + .map("birthday", "BIRTHDAY", new DateTypeConverter()) + .build(); + + var table = node.tables().table("PojoTestTable").keyValueView(keyMapper, valMapper); + + var expectedDate = Date.from(LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC)); + var expected = new MyPojoWithDate("someName", expectedDate); + + table.put(null, 1, expected); + var actual = table.get(null, 1); + + assertEquals(expected, actual); + } + + private static class DateTypeConverter implements TypeConverter<Date, LocalDate> { + @Override + public LocalDate toColumnType(Date obj) { + var timestamp = obj.toInstant(); + return LocalDate.ofInstant(timestamp, ZoneOffset.UTC); + } + + @Override + public Date toObjectType(LocalDate data) { + Instant instant = data.atStartOfDay().toInstant(ZoneOffset.UTC); + return Date.from(instant); + } + } + + static class MyPojoWithDate { + private String name; + + private Date birthday; + + public MyPojoWithDate() { + // No-op. + } + + public MyPojoWithDate(String name, Date birthday) { + this.name = name; + this.birthday = birthday; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + MyPojoWithDate that = (MyPojoWithDate) o; + return Objects.equals(name, that.name) && Objects.equals(birthday, that.birthday); + } + + @Override + public int hashCode() { + return Objects.hash(name, birthday); + } + } +}
