From 77a8b2335d197b09c3167c083e8ee26ddcb2bd6e Mon Sep 17 00:00:00 2001 From: sonika-shah <58761340+sonika-shah@users.noreply.github.com> Date: Sat, 27 Sep 2025 20:19:28 +0530 Subject: [PATCH] Fix batchFetchClassification for tags (#23581) --- .../service/jdbi3/TagRepository.java | 5 +- .../resources/tags/TagResourceTest.java | 104 ++++++++++++++++++ 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TagRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TagRepository.java index 3c5cee00527..0f084c0e6cc 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TagRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/TagRepository.java @@ -379,7 +379,8 @@ public class TagRepository extends EntityRepository { var records = daoCollection .relationshipDAO() - .findToBatch(entityIds, Relationship.CONTAINS.ordinal(), Entity.CLASSIFICATION); + .findFromBatch( + entityIds, Relationship.CONTAINS.ordinal(), Entity.CLASSIFICATION, NON_DELETED); if (records.isEmpty()) { return Map.of(); @@ -422,7 +423,7 @@ public class TagRepository extends EntityRepository { var records = daoCollection .relationshipDAO() - .findToBatch(entityIds, Relationship.CONTAINS.ordinal(), TAG); + .findFromBatch(entityIds, Relationship.CONTAINS.ordinal(), TAG, NON_DELETED); if (records.isEmpty()) { return Map.of(); diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/resources/tags/TagResourceTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/resources/tags/TagResourceTest.java index 05482531e8e..5b52e1af436 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/resources/tags/TagResourceTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/resources/tags/TagResourceTest.java @@ -793,4 +793,108 @@ public class TagResourceTest extends EntityResourceTest { return classificationResourceTest.getEntityByName( name, classificationResourceTest.getAllowedFields(), ADMIN_AUTH_HEADERS); } + + @Test + @Order(100) // Run this test later to ensure environment is ready + void test_bulkSetFieldsForTags(TestInfo test) throws IOException { + // This test verifies that bulk operations (like those used during reindexing) + // correctly set classification and parent relationships for tags + + // Create a classification + String classificationName = + "BulkTestClassification_" + UUID.randomUUID().toString().substring(0, 8); + Classification classification = createClassification(classificationName); + + // Create a parent tag + String parentTagName = "BulkParentTag_" + UUID.randomUUID().toString().substring(0, 8); + CreateTag createParent = + createRequest(parentTagName).withClassification(classification.getFullyQualifiedName()); + Tag parentTag = createEntity(createParent, ADMIN_AUTH_HEADERS); + + // Create multiple child tags + List childTags = new ArrayList<>(); + for (int i = 0; i < 5; i++) { + String childTagName = + "BulkChildTag_" + i + "_" + UUID.randomUUID().toString().substring(0, 8); + CreateTag createChild = + createRequest(childTagName) + .withClassification(classification.getFullyQualifiedName()) + .withParent(parentTag.getFullyQualifiedName()); + Tag childTag = createEntity(createChild, ADMIN_AUTH_HEADERS); + childTags.add(childTag); + } + + // Get TagRepository to test bulk operations + org.openmetadata.service.jdbi3.TagRepository tagRepository = + (org.openmetadata.service.jdbi3.TagRepository) Entity.getEntityRepository(Entity.TAG); + + // Fetch tags without fields (simulating initial reindexing fetch) + // During reindexing, tags are fetched without relationships populated + List tagsWithoutFields = new ArrayList<>(); + for (Tag childTag : childTags) { + // Create a minimal tag object to simulate what happens during reindexing + // when tags are fetched in bulk without relationship fields + Tag tagWithoutFields = new Tag(); + tagWithoutFields.setId(childTag.getId()); + tagWithoutFields.setName(childTag.getName()); + tagWithoutFields.setFullyQualifiedName(childTag.getFullyQualifiedName()); + tagWithoutFields.setDescription(childTag.getDescription()); + // Classification and parent are intentionally not set - simulating bulk fetch without + // relationships + tagsWithoutFields.add(tagWithoutFields); + } + + // Test setFieldsInBulk method + org.openmetadata.service.util.EntityUtil.Fields fields = + new org.openmetadata.service.util.EntityUtil.Fields( + java.util.Set.of("classification", "parent", "usageCount")); + tagRepository.setFieldsInBulk(fields, tagsWithoutFields); + + // Verify all tags now have their classification and parent set correctly + for (Tag tag : tagsWithoutFields) { + assertNotNull(tag.getClassification(), "Classification should be set after bulk operation"); + assertEquals( + classification.getId(), + tag.getClassification().getId(), + "Classification ID should match"); + assertEquals( + classification.getFullyQualifiedName(), + tag.getClassification().getFullyQualifiedName(), + "Classification FQN should match"); + + assertNotNull(tag.getParent(), "Parent should be set after bulk operation"); + assertEquals(parentTag.getId(), tag.getParent().getId(), "Parent ID should match"); + assertEquals( + parentTag.getFullyQualifiedName(), + tag.getParent().getFullyQualifiedName(), + "Parent FQN should match"); + + assertNotNull(tag.getUsageCount(), "Usage count should be set"); + assertTrue(tag.getUsageCount() >= 0, "Usage count should be non-negative"); + } + + // Test edge case: empty list + List emptyList = new ArrayList<>(); + tagRepository.setFieldsInBulk(fields, emptyList); + assertTrue(emptyList.isEmpty(), "Empty list should remain empty"); + + // Test with parent tag (which has no parent) + List parentTagList = new ArrayList<>(); + Tag parentWithoutFields = new Tag(); + parentWithoutFields.setId(parentTag.getId()); + parentWithoutFields.setName(parentTag.getName()); + parentWithoutFields.setFullyQualifiedName(parentTag.getFullyQualifiedName()); + parentWithoutFields.setDescription(parentTag.getDescription()); + parentTagList.add(parentWithoutFields); + + tagRepository.setFieldsInBulk(fields, parentTagList); + + assertNotNull( + parentWithoutFields.getClassification(), "Parent tag should have classification set"); + assertEquals( + classification.getId(), + parentWithoutFields.getClassification().getId(), + "Parent tag classification should match"); + assertNull(parentWithoutFields.getParent(), "Parent tag should not have a parent"); + } }