You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ra...@apache.org on 2026/06/12 21:12:25 UTC

(atlas) branch atlas-2.6 updated: ATLAS-5310: Export/Import API : When tag attributes types get modified between th… (#662)

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

asf-gitbox-commits pushed a commit to branch atlas-2.6
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/atlas-2.6 by this push:
     new 9db78b95e ATLAS-5310: Export/Import API : When tag attributes types get modified between th… (#662)
9db78b95e is described below

commit 9db78b95e1b6a750bb7b77fd87b4b4ef0a1787dc
Author: saksenasonali <37...@users.noreply.github.com>
AuthorDate: Sat Jun 13 02:41:00 2026 +0530

    ATLAS-5310: Export/Import API : When tag attributes types get modified between th… (#662)
    
    Co-authored-by: ssaksena <ss...@cloudera.com>
    (cherry picked from commit ac00c0f983b64cddace745e806750c7057abd867)
---
 .../repository/graphdb/AtlasGraphManagement.java   |  7 ++++++
 .../graphdb/janus/AtlasJanusGraphManagement.java   |  9 ++++++++
 .../repository/graph/GraphBackedSearchIndexer.java |  9 ++++++++
 .../repository/impexp/TypeAttributeDifference.java | 10 ++++----
 .../store/graph/v2/AtlasStructDefStoreV2.java      | 27 ++++++++++++++++++----
 .../atlas/repository/impexp/ImportServiceTest.java | 17 ++++++--------
 .../impexp/TypeAttributeDifferenceTest.java        | 15 ++++++++++++
 7 files changed, 74 insertions(+), 20 deletions(-)

diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java
index 7a3ca74c2..55f2d7629 100644
--- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java
+++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java
@@ -47,6 +47,13 @@ public interface AtlasGraphManagement extends AutoCloseable {
      */
     AtlasEdgeLabel makeEdgeLabel(String label);
 
+    /**
+     * @param propertyName
+     * @param dataType
+     * @return true if the property key exists and has the given data type
+     */
+    boolean propertyKeyHasDataType(String propertyName, Class<?> dataType);
+
     /**
      *  @param propertyKey
      *
diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphManagement.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphManagement.java
index bc3b25cdb..824733e01 100644
--- a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphManagement.java
+++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusGraphManagement.java
@@ -210,6 +210,15 @@ public class AtlasJanusGraphManagement implements AtlasGraphManagement {
         return GraphDbObjectFactory.createEdgeLabel(edgeLabel);
     }
 
+    @Override
+    public boolean propertyKeyHasDataType(String propertyName, Class<?> dataType) {
+        checkName(propertyName);
+
+        PropertyKey janusPropertyKey = management.getPropertyKey(propertyName);
+
+        return janusPropertyKey != null && janusPropertyKey.dataType().equals(dataType);
+    }
+
     @Override
     public void deletePropertyKey(String propertyKey) {
         PropertyKey janusPropertyKey = management.getPropertyKey(propertyKey);
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedSearchIndexer.java b/repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedSearchIndexer.java
index addeb3d0c..03bb953af 100755
--- a/repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedSearchIndexer.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/GraphBackedSearchIndexer.java
@@ -21,6 +21,7 @@ package org.apache.atlas.repository.graph;
 import com.google.common.annotations.VisibleForTesting;
 import org.apache.atlas.ApplicationProperties;
 import org.apache.atlas.AtlasException;
+import org.apache.atlas.RequestContext;
 import org.apache.atlas.discovery.SearchIndexer;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.ha.HAConfiguration;
@@ -439,6 +440,14 @@ public class GraphBackedSearchIndexer implements SearchIndexer, ActiveStateChang
         if (propertyName != null) {
             AtlasPropertyKey propertyKey = management.getPropertyKey(propertyName);
 
+            if (propertyKey != null && RequestContext.get().isImportInProgress()
+                    && !management.propertyKeyHasDataType(propertyName, propertyClass)) {
+                LOG.info("Recreating property key {} during import; data type changed to {}", propertyName, propertyClass.getName());
+
+                management.deletePropertyKey(propertyName);
+                propertyKey = null;
+            }
+
             if (propertyKey == null) {
                 propertyKey = management.makePropertyKey(propertyName, propertyClass, cardinality);
 
diff --git a/repository/src/main/java/org/apache/atlas/repository/impexp/TypeAttributeDifference.java b/repository/src/main/java/org/apache/atlas/repository/impexp/TypeAttributeDifference.java
index a3885810f..070932d5a 100644
--- a/repository/src/main/java/org/apache/atlas/repository/impexp/TypeAttributeDifference.java
+++ b/repository/src/main/java/org/apache/atlas/repository/impexp/TypeAttributeDifference.java
@@ -18,7 +18,6 @@
 package org.apache.atlas.repository.impexp;
 
 import com.google.common.annotations.VisibleForTesting;
-import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.impexp.AtlasImportResult;
 import org.apache.atlas.model.typedef.AtlasBusinessMetadataDef;
@@ -170,12 +169,11 @@ public class TypeAttributeDifference {
             if (relationshipType == null) {
                 difference.add(incoming);
             }
-        } else {
-            if (!existingAttribute.getTypeName().equals(incoming.getTypeName())) {
-                LOG.error("Attribute definition difference found: {}, {}", existingAttribute, incoming);
+        } else if (!existingAttribute.getTypeName().equals(incoming.getTypeName())) {
+            LOG.info("Attribute type changed for {}.{}: {} -> {}; updating typedef during import",
+                    existing.getName(), existingAttribute.getName(), existingAttribute.getTypeName(), incoming.getTypeName());
 
-                throw new AtlasBaseException(AtlasErrorCode.INVALID_IMPORT_ATTRIBUTE_TYPE_CHANGED, existing.getName(), existingAttribute.getName(), existingAttribute.getTypeName(), incoming.getTypeName());
-            }
+            difference.add(incoming);
         }
     }
 
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasStructDefStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasStructDefStoreV2.java
index c26d1c347..e187b0f26 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasStructDefStoreV2.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasStructDefStoreV2.java
@@ -177,7 +177,18 @@ public class AtlasStructDefStoreV2 extends AtlasAbstractDefStoreV2<AtlasStructDe
                 AtlasAttributeDef existingAttribute = currentStructDef.getAttribute(attributeDef.getName());
 
                 if (null != existingAttribute && !attributeDef.getTypeName().equals(existingAttribute.getTypeName())) {
-                    throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Data type update for attribute is not supported");
+                    if (!RequestContext.get().isImportInProgress()) {
+                        throw new AtlasBaseException(AtlasErrorCode.BAD_REQUEST, "Data type update for attribute is not supported");
+                    }
+
+                    LOG.info("Updating attribute type during import: {}.{} from {} to {}",
+                            structDef.getName(), attributeDef.getName(), existingAttribute.getTypeName(), attributeDef.getTypeName());
+
+                    String propertyKey = AtlasGraphUtilsV2.getTypeDefPropertyKey(structDef, attributeDef.getName());
+
+                    AtlasGraphUtilsV2.setProperty(vertex, propertyKey, toJsonFromAttributeDef(attributeDef));
+
+                    continue;
                 }
 
                 String propertyKey = AtlasGraphUtilsV2.getTypeDefPropertyKey(structDef, attributeDef.getName());
@@ -237,7 +248,15 @@ public class AtlasStructDefStoreV2 extends AtlasAbstractDefStoreV2<AtlasStructDe
 
     @VisibleForTesting
     public static String toJsonFromAttribute(AtlasAttribute attribute) {
-        AtlasAttributeDef   attributeDef = attribute.getAttributeDef();
+        return toJsonFromAttributeDef(attribute.getAttributeDef(), attribute.isOwnedRef(), attribute.getInverseRefAttributeName());
+    }
+
+    @VisibleForTesting
+    public static String toJsonFromAttributeDef(AtlasAttributeDef attributeDef) {
+        return toJsonFromAttributeDef(attributeDef, false, null);
+    }
+
+    private static String toJsonFromAttributeDef(AtlasAttributeDef attributeDef, boolean isComposite, String reverseAttributeName) {
         Map<String, Object> attribInfo   = new HashMap<>();
 
         attribInfo.put("name", attributeDef.getName());
@@ -245,8 +264,8 @@ public class AtlasStructDefStoreV2 extends AtlasAbstractDefStoreV2<AtlasStructDe
         attribInfo.put("isUnique", attributeDef.getIsUnique());
         attribInfo.put("isIndexable", attributeDef.getIsIndexable());
         attribInfo.put("includeInNotification", attributeDef.getIncludeInNotification());
-        attribInfo.put("isComposite", attribute.isOwnedRef());
-        attribInfo.put("reverseAttributeName", attribute.getInverseRefAttributeName());
+        attribInfo.put("isComposite", isComposite);
+        attribInfo.put("reverseAttributeName", reverseAttributeName);
         attribInfo.put("defaultValue", attributeDef.getDefaultValue());
         attribInfo.put("description", attributeDef.getDescription());
         attribInfo.put("searchWeight", attributeDef.getSearchWeight());
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
index 6f461cf2c..bef2de68f 100644
--- a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
@@ -364,21 +364,18 @@ public class ImportServiceTest extends AtlasTestBase {
         assertEntityCount("AtlasGlossaryTerm", "105533b6-c125-4a87-bed5-cdf67fb68c39", 1);
     }
 
-    @Test(dataProvider = "hdfs_path1", expectedExceptions = AtlasBaseException.class)
+    @Test(dataProvider = "hdfs_path1")
     public void importHdfs_path1(InputStream inputStream) throws IOException, AtlasBaseException {
         loadBaseModel();
         loadFsModel();
         loadModelFromResourcesJson("tag1.json", typeDefStore, typeRegistry);
 
-        try {
-            runImportWithNoParameters(importService, inputStream);
-        } catch (AtlasBaseException e) {
-            assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.INVALID_IMPORT_ATTRIBUTE_TYPE_CHANGED);
-            AtlasClassificationType tag1 = typeRegistry.getClassificationTypeByName("tag1");
-            assertNotNull(tag1);
-            assertEquals(tag1.getAllAttributes().size(), 2);
-            throw e;
-        }
+        runImportWithNoParameters(importService, inputStream);
+
+        AtlasClassificationType tag1 = typeRegistry.getClassificationTypeByName("tag1");
+        assertNotNull(tag1);
+        assertEquals(tag1.getAttribute("attrib1").getAttributeDef().getTypeName(), "string");
+        assertNotNull(tag1.getAttribute("attrib2"));
     }
 
     @Test(dataProvider = "zip-direct-3", expectedExceptions = AtlasBaseException.class)
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/TypeAttributeDifferenceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/TypeAttributeDifferenceTest.java
index 85ba6bd10..53164a9a8 100644
--- a/repository/src/test/java/org/apache/atlas/repository/impexp/TypeAttributeDifferenceTest.java
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/TypeAttributeDifferenceTest.java
@@ -88,6 +88,21 @@ public class TypeAttributeDifferenceTest {
         assertEquals(actualAttributes, expectedAttributes);
     }
 
+    @Test
+    public void attributeTypeChanged_ReturnsUpdatedAttribute() throws Exception {
+        AtlasEntityDef                         existing           = getAtlasEntityDefWithAttributes("name");
+        AtlasEntityDef                         incoming           = new AtlasEntityDef();
+        AtlasStructDef.AtlasAttributeDef       nameAttr           = new AtlasStructDef.AtlasAttributeDef("name", AtlasBaseTypeDef.ATLAS_TYPE_DOUBLE);
+        List<AtlasStructDef.AtlasAttributeDef> expectedAttributes = new ArrayList<>();
+
+        incoming.addAttribute(nameAttr);
+        expectedAttributes.add(nameAttr);
+
+        List<AtlasStructDef.AtlasAttributeDef> actualAttributes = invokeGetAttributesAbsentInExisting(existing, incoming);
+
+        assertEquals(actualAttributes, expectedAttributes);
+    }
+
     @Test
     public void differentSubset_ReturnsDifference() throws Exception {
         AtlasEntityDef                         existing         = getAtlasEntityDefWithAttributes("name", "qualifiedName");