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 02e70008bae IGNITE-28426 Migration Tools: Fix SqlDdlGenerator nested 
POJOs bug (#7912)
02e70008bae is described below

commit 02e70008baea8a0273c12efe44f36e326b7f4983
Author: Tiago Marques Godinho <[email protected]>
AuthorDate: Mon Apr 13 13:48:22 2026 +0100

    IGNITE-28426 Migration Tools: Fix SqlDdlGenerator nested POJOs bug (#7912)
---
 .../tests/models/NestedPojoWithAnnotations.java    | 61 ++++++++++++++++++++++
 .../ignite/migrationtools/sql/SqlDdlGenerator.java | 31 ++++++++++-
 .../ignite/migrationtools/types/TypeInspector.java |  8 ++-
 .../sql/sql/SqlDdlGeneratorTest.java               | 23 ++++++++
 4 files changed, 120 insertions(+), 3 deletions(-)

diff --git 
a/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/NestedPojoWithAnnotations.java
 
b/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/NestedPojoWithAnnotations.java
new file mode 100644
index 00000000000..beb074b2d17
--- /dev/null
+++ 
b/migration-tools/modules/migration-tools-commons-tests/src/main/java/org/apache/ignite/migrationtools/tests/models/NestedPojoWithAnnotations.java
@@ -0,0 +1,61 @@
+/*
+ * 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 org.apache.ignite.cache.query.annotations.QuerySqlField;
+
+/** NestedPojoWithAnnotations. */
+public class NestedPojoWithAnnotations {
+    @QuerySqlField
+    private long id;
+
+    @QuerySqlField
+    private SimplePojo nestedPojo;
+
+    public NestedPojoWithAnnotations() {
+        // Intentionally left blank.
+    }
+
+    public NestedPojoWithAnnotations(long id, SimplePojo nestedObj) {
+        this.id = id;
+        this.nestedPojo = nestedObj;
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public SimplePojo getNestedPojo() {
+        return nestedPojo;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof NestedPojoWithAnnotations)) {
+            return false;
+        }
+        NestedPojoWithAnnotations that = (NestedPojoWithAnnotations) o;
+        return id == that.id && Objects.equals(nestedPojo, that.nestedPojo);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, nestedPojo);
+    }
+}
diff --git 
a/migration-tools/modules/migration-tools-commons/src/main/java/org/apache/ignite/migrationtools/sql/SqlDdlGenerator.java
 
b/migration-tools/modules/migration-tools-commons/src/main/java/org/apache/ignite/migrationtools/sql/SqlDdlGenerator.java
index 821b0d57b5b..d942d8911f1 100644
--- 
a/migration-tools/modules/migration-tools-commons/src/main/java/org/apache/ignite/migrationtools/sql/SqlDdlGenerator.java
+++ 
b/migration-tools/modules/migration-tools-commons/src/main/java/org/apache/ignite/migrationtools/sql/SqlDdlGenerator.java
@@ -26,6 +26,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.Function;
@@ -388,6 +389,9 @@ public class SqlDdlGenerator {
             }
         }
 
+        // Tracks whether this QE maps a POJO on either Key/Value.
+        boolean mapsPojo = false;
+
         // Go over existing fields in the QE to they are correct and there are 
not silly nulls.
         {
             // AI2 may define primitive field types, however, they still mark 
them as nullable somehow.
@@ -430,6 +434,29 @@ public class SqlDdlGenerator {
 
             // Mark keyFields as not nullable.
             qe.getNotNullFields().addAll(qe.getKeyFields());
+
+            // We also want to remove fields non-compliant with AI3 so that 
they are handled in the extra fields.
+            for (Iterator<Entry<String, String>> it = 
qe.getFields().entrySet().iterator(); it.hasNext(); ) {
+                Entry<String, String> e = it.next();
+                String fieldType = ClassnameUtils.ensureWrapper(e.getValue());
+
+                boolean isNativelySupportedType;
+                try {
+                    Class<?> type = 
ClassUtils.getClass(this.clientClassLoader, fieldType);
+                    isNativelySupportedType = 
TypeInspector.isPrimitiveType(type);
+                } catch (ClassNotFoundException ignored) {
+                    // All natively supported types should be in the classpath.
+                    // Some enums might still slip through.
+                    isNativelySupportedType = false;
+                }
+
+                // Remove from the field list, we will need to map it in the 
extra fields.
+                if (!isNativelySupportedType) {
+                    mapsPojo = true;
+                    it.remove();
+                    qe.getKeyFields().remove(e.getKey());
+                }
+            }
         }
 
         @Nullable Map<InspectedField, String> keyFieldToColumnMap;
@@ -558,7 +585,7 @@ public class SqlDdlGenerator {
         }
 
         // Empty field lists means that the class for the type is not 
available on the classpath so it must be a pojo.
-        boolean mapsPojo = keyFields.isEmpty() || valFields.isEmpty();
+        mapsPojo = mapsPojo || keyFields.isEmpty() || valFields.isEmpty();
 
         // Process key fields
         {
@@ -583,7 +610,7 @@ public class SqlDdlGenerator {
 
         // Process value fields
         {
-            if (valFields.size() == 1) {
+            if (valFields.size() == 1 && !mapsPojo) {
                 InspectedField inspectedField = valFields.get(0);
                 String columnName = valFieldToColumnMap.get(inspectedField);
 
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 9dc4630c5a8..66e381c1411 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
@@ -133,7 +133,13 @@ public class TypeInspector {
         }
     }
 
-    private static boolean isPrimitiveType(Class<?> type) {
+    /**
+     * Whether the provided class, or its derivatives, is natively supported.
+     *
+     * @param type Type.
+     * @return True or false.
+     */
+    public static boolean isPrimitiveType(Class<?> type) {
         return type.isEnum() || Mapper.nativelySupported(type) || 
COL_TYPE_REF.containsKey(type);
     }
 
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 588fbbaef6e..440c250baa5 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
@@ -64,6 +64,7 @@ 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.NestedPojoWithAnnotations;
 import org.apache.ignite.migrationtools.tests.models.SimplePojo;
 import org.apache.ignite3.catalog.ColumnSorted;
 import org.apache.ignite3.catalog.definitions.ColumnDefinition;
@@ -347,6 +348,28 @@ class SqlDdlGeneratorTest {
         );
     }
 
+    @ParameterizedTest
+    @MethodSource("provideCacheConfigSupplier")
+    void testTableDefWithNestedPojoWithAnnotations(
+            BiFunction<Class<?>, Class<?>, CacheConfiguration<?, ?>> 
cacheConfigSupplier,
+            boolean allowExtraFields
+    ) {
+        var cacheCfg = cacheConfigSupplier.apply(String.class, 
NestedPojoWithAnnotations.class);
+        testCacheConfig(
+                cacheCfg,
+                allowExtraFields,
+                List.of(
+                        primaryKey("KEY", "VARCHAR"),
+                        nonKey("id", "BIGINT", false)
+                ),
+                entry(String.class.getName(), 
NestedPojoWithAnnotations.class.getName()),
+                emptyMap(),
+                Map.ofEntries(
+                        entry("id", "id")
+                )
+        );
+    }
+
     @ParameterizedTest
     @MethodSource("provideCacheConfigSupplier")
     void testTableDefWithOrganizationPojo(

Reply via email to