This is an automated email from the ASF dual-hosted git repository.
isapego pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new 2344d8c1d9d IGNITE-27910 Migration Tools: Add support for fields from
inherited classes (#7661)
2344d8c1d9d is described below
commit 2344d8c1d9df7ff981371c205ab66825d2f35708
Author: Tiago Marques Godinho <[email protected]>
AuthorDate: Thu Feb 26 09:59:28 2026 +0000
IGNITE-27910 Migration Tools: Add support for fields from inherited classes
(#7661)
---
.../tests/models/IdentifiedEntity.java | 52 ++++++++++++++
.../tests/models/IdentifiedPojo.java | 83 ++++++++++++++++++++++
.../ignite/migrationtools/types/TypeInspector.java | 58 ++++++++-------
.../sql/sql/SqlDdlGeneratorTest.java | 30 ++++++++
.../migrationtools/types/TypeInspectorTest.java | 22 +++++-
5 files changed, 216 insertions(+), 29 deletions(-)
diff --git
a/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/IdentifiedEntity.java
b/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/IdentifiedEntity.java
new file mode 100644
index 00000000000..770e24c8252
--- /dev/null
+++
b/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/IdentifiedEntity.java
@@ -0,0 +1,52 @@
+/*
+ * 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.migrationtools.tests.models;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/** IdentifiedEntity. */
+public class IdentifiedEntity {
+ private UUID id;
+
+ public IdentifiedEntity() {
+ id = UUID.randomUUID();
+ }
+
+ public UUID getId() {
+ return id;
+ }
+
+ public void setId(UUID id) {
+ this.id = id;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof IdentifiedEntity)) {
+ return false;
+ }
+ IdentifiedEntity that = (IdentifiedEntity) o;
+ return Objects.equals(id, that.id);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(id);
+ }
+}
diff --git
a/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/IdentifiedPojo.java
b/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/IdentifiedPojo.java
new file mode 100644
index 00000000000..daab55d1c11
--- /dev/null
+++
b/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/IdentifiedPojo.java
@@ -0,0 +1,83 @@
+/*
+ * 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.migrationtools.tests.models;
+
+import java.util.Objects;
+
+/** IdentifiedPojo. */
+public class IdentifiedPojo extends IdentifiedEntity {
+ private String name;
+
+ private int amount;
+
+ private Double decimalAmount;
+
+ private IdentifiedPojo() {
+ // Default constructor
+ // Intentionally left blank.
+ }
+
+ /** Constructor. */
+ public IdentifiedPojo(String name, int amount, Double decimalAmount) {
+ this.name = name;
+ this.amount = amount;
+ this.decimalAmount = decimalAmount;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public int getAmount() {
+ return amount;
+ }
+
+ public void setAmount(int amount) {
+ this.amount = amount;
+ }
+
+ public Double getDecimalAmount() {
+ return decimalAmount;
+ }
+
+ public void setDecimalAmount(Double decimalAmount) {
+ this.decimalAmount = decimalAmount;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof IdentifiedPojo)) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ IdentifiedPojo that = (IdentifiedPojo) o;
+ return amount == that.amount && Objects.equals(name, that.name) &&
Objects.equals(decimalAmount,
+ that.decimalAmount);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), name, amount, decimalAmount);
+ }
+}
diff --git
a/migration-tools/modules/migration-tools-commons/src/main/java/org/apache/ignite/migrationtools/types/TypeInspector.java
b/migration-tools/modules/migration-tools-commons/src/main/java/org/apache/ignite/migrationtools/types/TypeInspector.java
index 770ab7cd867..9dc4630c5a8 100644
---
a/migration-tools/modules/migration-tools-commons/src/main/java/org/apache/ignite/migrationtools/types/TypeInspector.java
+++
b/migration-tools/modules/migration-tools-commons/src/main/java/org/apache/ignite/migrationtools/types/TypeInspector.java
@@ -95,33 +95,39 @@ public class TypeInspector {
} else if (isPrimitiveType(rootType)) {
return
Collections.singletonList(InspectedField.forUnnamed(rootTypeName,
InspectedFieldType.PRIMITIVE));
} else {
- Field[] fields = rootType.getDeclaredFields();
- List<InspectedField> ret = new ArrayList<>(fields.length);
- for (Field field : fields) {
- if (shouldPersistField(field)) {
- @Nullable QuerySqlField annotation =
field.getAnnotation(QuerySqlField.class);
- boolean hasAnnotation = annotation != null;
-
- Class<?> origFieldType = field.getType();
- Class<?> wrappedFieldType =
ClassUtils.primitiveToWrapper(origFieldType);
-
- boolean nullable = !origFieldType.isPrimitive();
-
- InspectedFieldType inspectedFieldType =
isPrimitiveType(wrappedFieldType)
- ? InspectedFieldType.POJO_ATTRIBUTE
- : InspectedFieldType.NESTED_POJO_ATTRIBUTE;
-
- InspectedField inspectedField = InspectedField.forNamed(
- field.getName(),
- wrappedFieldType.getName(),
- inspectedFieldType,
- nullable,
- hasAnnotation
- );
-
- ret.add(inspectedField);
+ Class<?> currentType = type;
+ ArrayList<InspectedField> ret = new ArrayList<>();
+ do {
+ Field[] fields = currentType.getDeclaredFields();
+ ret.ensureCapacity(ret.size() + fields.length);
+ for (Field field : fields) {
+ if (shouldPersistField(field)) {
+ @Nullable QuerySqlField annotation =
field.getAnnotation(QuerySqlField.class);
+ boolean hasAnnotation = annotation != null;
+
+ Class<?> origFieldType = field.getType();
+ Class<?> wrappedFieldType =
ClassUtils.primitiveToWrapper(origFieldType);
+
+ boolean nullable = !origFieldType.isPrimitive();
+
+ InspectedFieldType inspectedFieldType =
isPrimitiveType(wrappedFieldType)
+ ? InspectedFieldType.POJO_ATTRIBUTE
+ : InspectedFieldType.NESTED_POJO_ATTRIBUTE;
+
+ InspectedField inspectedField =
InspectedField.forNamed(
+ field.getName(),
+ wrappedFieldType.getName(),
+ inspectedFieldType,
+ nullable,
+ hasAnnotation
+ );
+
+ ret.add(inspectedField);
+ }
}
- }
+
+ currentType = currentType.getSuperclass();
+ } while (currentType != Object.class && currentType != null);
return ret;
}
diff --git
a/migration-tools/modules/migration-tools-commons/src/test/java/org/apache/ignite/migrationtools/sql/sql/SqlDdlGeneratorTest.java
b/migration-tools/modules/migration-tools-commons/src/test/java/org/apache/ignite/migrationtools/sql/sql/SqlDdlGeneratorTest.java
index e54e3b86add..00395e0b014 100644
---
a/migration-tools/modules/migration-tools-commons/src/test/java/org/apache/ignite/migrationtools/sql/sql/SqlDdlGeneratorTest.java
+++
b/migration-tools/modules/migration-tools-commons/src/test/java/org/apache/ignite/migrationtools/sql/sql/SqlDdlGeneratorTest.java
@@ -62,6 +62,7 @@ import
org.apache.ignite.migrationtools.sql.SqlDdlGenerator.GenerateTableResult;
import org.apache.ignite.migrationtools.tablemanagement.TableTypeDescriptor;
import
org.apache.ignite.migrationtools.tablemanagement.TableTypeRegistryMapImpl;
import org.apache.ignite.migrationtools.tests.models.ComplexKeyIntStr;
+import org.apache.ignite.migrationtools.tests.models.IdentifiedPojo;
import org.apache.ignite.migrationtools.tests.models.InterceptingFieldsModel;
import org.apache.ignite.migrationtools.tests.models.SimplePojo;
import org.apache.ignite3.catalog.ColumnSorted;
@@ -498,6 +499,35 @@ class SqlDdlGeneratorTest {
);
}
+ @ParameterizedTest
+ @MethodSource("provideCacheConfigSupplier")
+ void testTableDefWithFieldsFromSuperClass(
+ BiFunction<Class<?>, Class<?>, CacheConfiguration<?, ?>>
cacheConfigSupplier,
+ boolean allowExtraFields
+ ) {
+ var cacheCfg = cacheConfigSupplier.apply(UUID.class,
IdentifiedPojo.class);
+
+ testCacheConfig(
+ cacheCfg,
+ allowExtraFields,
+ List.of(
+ primaryKey("KEY", "UUID"),
+ nonKey("name", "VARCHAR", true),
+ nonKey("amount", "INT", false),
+ nonKey("decimalAmount", "DOUBLE", true),
+ nonKey("id", "UUID", true)
+ ),
+ entry(UUID.class.getName(), IdentifiedPojo.class.getName()),
+ Map.ofEntries(),
+ Map.ofEntries(
+ entry("name", "name"),
+ entry("amount", "amount"),
+ entry("decimalAmount", "decimalAmount"),
+ entry("id", "id")
+ )
+ );
+ }
+
@ParameterizedTest
@FieldSource("EXTRA_FIELDS_ENABLED_ARG")
void testTableDefWithPojoWithPrimitiveFieldsDefined(boolean
allowExtraFields) {
diff --git
a/migration-tools/modules/migration-tools-commons/src/test/java/org/apache/ignite/migrationtools/types/TypeInspectorTest.java
b/migration-tools/modules/migration-tools-commons/src/test/java/org/apache/ignite/migrationtools/types/TypeInspectorTest.java
index b2eadc0ec87..a0283a47006 100644
---
a/migration-tools/modules/migration-tools-commons/src/test/java/org/apache/ignite/migrationtools/types/TypeInspectorTest.java
+++
b/migration-tools/modules/migration-tools-commons/src/test/java/org/apache/ignite/migrationtools/types/TypeInspectorTest.java
@@ -24,10 +24,12 @@ import static
org.junit.jupiter.params.provider.Arguments.arguments;
import java.sql.Timestamp;
import java.util.List;
+import java.util.UUID;
import java.util.stream.Stream;
import org.apache.ignite.examples.model.Address;
import org.apache.ignite.examples.model.Organization;
import org.apache.ignite.examples.model.OrganizationType;
+import org.apache.ignite.migrationtools.tests.models.IdentifiedPojo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -40,7 +42,7 @@ class TypeInspectorTest {
List<InspectedField> inspectedTypes = inspectType(primitiveKlass);
var expected = InspectedField.forUnnamed(typeName,
InspectedFieldType.PRIMITIVE);
- assertThat(inspectedTypes).containsExactly(expected);
+ assertThat(inspectedTypes).containsExactlyInAnyOrder(expected);
}
private static Stream<Arguments> primitiveTypes() {
@@ -71,7 +73,7 @@ class TypeInspectorTest {
List<InspectedField> inspectedTypes = inspectType(primitiveKlass);
var expected = InspectedField.forUnnamed(primitiveKlass.getName(),
InspectedFieldType.ARRAY);
- assertThat(inspectedTypes).containsExactly(expected);
+ assertThat(inspectedTypes).containsExactlyInAnyOrder(expected);
}
private static Stream<Arguments> arrayTypes() {
@@ -109,6 +111,20 @@ class TypeInspectorTest {
forNamed("lastUpdated", Timestamp.class.getName(),
InspectedFieldType.POJO_ATTRIBUTE, true, false)
};
- assertThat(inspectedTypes).containsExactly(expected);
+ assertThat(inspectedTypes).containsExactlyInAnyOrder(expected);
+ }
+
+ @Test
+ void testSuperClass() {
+ List<InspectedField> inspectedTypes =
inspectType(IdentifiedPojo.class);
+
+ InspectedField[] expected = new InspectedField[] {
+ forNamed("name", String.class.getName(),
InspectedFieldType.POJO_ATTRIBUTE, true, false),
+ forNamed("amount", Integer.class.getName(),
InspectedFieldType.POJO_ATTRIBUTE, false, false),
+ forNamed("decimalAmount", Double.class.getName(),
InspectedFieldType.POJO_ATTRIBUTE, true, false),
+ forNamed("id", UUID.class.getName(),
InspectedFieldType.POJO_ATTRIBUTE, true, false)
+ };
+
+ assertThat(inspectedTypes).containsExactlyInAnyOrder(expected);
}
}