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);
     }
 }

Reply via email to