You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by pi...@apache.org on 2026/10/27 10:26:35 UTC

(atlas) branch atlas-2.6 updated: ATLAS-5425:Implement getEntitiesWithTagChanges for RDBMS audit repository (#791)

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

pinal-shah 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 cdc880b57b ATLAS-5425:Implement getEntitiesWithTagChanges for RDBMS audit repository (#791)
cdc880b57b is described below

commit cdc880b57b6cbf8ed06378b45753790bc3369dc4
Author: bhor-sanket <sa...@gmail.com>
AuthorDate: Tue Oct 27 15:52:57 2026 +0530

    ATLAS-5425:Implement getEntitiesWithTagChanges for RDBMS audit repository (#791)
    
    Co-authored-by: sanket.bhor <sa...@cloudera.com>
    (cherry picked from commit e56cd028949ce05c6c76895957ea951fac896e41)
---
 .../audit/rdbms/dao/DbEntityAuditDao.java          | 14 ++++++
 .../resources/META-INF/janus-jpa_named_queries.xml |  8 +++
 .../audit/rdbms/RdbmsBasedAuditRepository.java     | 15 +++++-
 .../repository/audit/AuditRepositoryTestBase.java  | 58 ++++++++++++++++++++++
 4 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/graphdb/janusgraph-rdbms/src/main/java/org/apache/atlas/repository/audit/rdbms/dao/DbEntityAuditDao.java b/graphdb/janusgraph-rdbms/src/main/java/org/apache/atlas/repository/audit/rdbms/dao/DbEntityAuditDao.java
index e6880344df..694abec732 100644
--- a/graphdb/janusgraph-rdbms/src/main/java/org/apache/atlas/repository/audit/rdbms/dao/DbEntityAuditDao.java
+++ b/graphdb/janusgraph-rdbms/src/main/java/org/apache/atlas/repository/audit/rdbms/dao/DbEntityAuditDao.java
@@ -100,6 +100,20 @@ public class DbEntityAuditDao extends BaseDao<DbEntityAudit> {
         return orderByQuery.toString();
     }
 
+    public List<String> getDistinctEntityIdsByActionPrefixAndTimeRange(String actionPrefix, long fromTimestamp, long toTimestamp) {
+        try {
+            return em.createNamedQuery("DbEntityAudit.getDistinctEntityIdsByActionPrefixAndTimeRange", String.class)
+                    .setParameter("actionPrefix", actionPrefix)
+                    .setParameter("fromTimestamp", fromTimestamp)
+                    .setParameter("toTimestamp", toTimestamp)
+                    .getResultList();
+        } catch (NoResultException excp) {
+            // ignore
+        }
+
+        return Collections.emptyList();
+    }
+
     public List<DbEntityAudit> getLatestAuditsByEntityIdAction(String entityId, String action, List<String> filterActions) {
         try {
             StringBuilder query = new StringBuilder("SELECT e FROM DbEntityAudit e WHERE e.entityId = :entityId");
diff --git a/graphdb/janusgraph-rdbms/src/main/resources/META-INF/janus-jpa_named_queries.xml b/graphdb/janusgraph-rdbms/src/main/resources/META-INF/janus-jpa_named_queries.xml
index a0258f5ba3..caacaff14b 100644
--- a/graphdb/janusgraph-rdbms/src/main/resources/META-INF/janus-jpa_named_queries.xml
+++ b/graphdb/janusgraph-rdbms/src/main/resources/META-INF/janus-jpa_named_queries.xml
@@ -32,6 +32,14 @@
         </query>
     </named-query>
 
+    <named-query name="DbEntityAudit.getDistinctEntityIdsByActionPrefixAndTimeRange">
+        <query>SELECT DISTINCT obj.entityId FROM DbEntityAudit obj
+            WHERE obj.action LIKE :actionPrefix
+            AND obj.eventTime >= :fromTimestamp
+            AND obj.eventTime &lt; :toTimestamp
+        </query>
+    </named-query>
+
     <named-query name="JanusStore.getIdByName">
         <query>SELECT s.id FROM JanusStore s WHERE s.name = :name</query>
     </named-query>
diff --git a/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java b/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java
index 7012a99798..e620485986 100644
--- a/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java
+++ b/repository/src/main/java/org/apache/atlas/repository/audit/rdbms/RdbmsBasedAuditRepository.java
@@ -45,6 +45,7 @@ import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -120,8 +121,18 @@ public class RdbmsBasedAuditRepository extends AbstractStorageBasedAuditReposito
 
     @Override
     public Set<String> getEntitiesWithTagChanges(long fromTimestamp, long toTimestamp) throws AtlasBaseException {
-        // TODO:
-        return Collections.emptySet();
+        LOG.debug("Listing entities with tag changes for fromTimestamp {}, toTimestamp {}", fromTimestamp, toTimestamp);
+
+        try (RdbmsTransaction trx = new RdbmsTransaction()) {
+            DbEntityAuditDao dao = new DbEntityAuditDao(trx.getEntityManager());
+
+            List<String> entityIds = dao.getDistinctEntityIdsByActionPrefixAndTimeRange(
+                    "CLASSIFICATION_%", fromTimestamp, toTimestamp);
+
+            return new HashSet<>(entityIds);
+        } catch (Exception excp) {
+            throw new AtlasBaseException("Error while retrieving entities with tag changes", excp);
+        }
     }
 
     @Override
diff --git a/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java b/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
index 82f5862cc4..3604e906df 100644
--- a/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
+++ b/repository/src/test/java/org/apache/atlas/repository/audit/AuditRepositoryTestBase.java
@@ -32,6 +32,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 import static org.testng.Assert.assertEquals;
@@ -245,6 +246,63 @@ public class AuditRepositoryTestBase {
         assertEquals(latestEvent, remainingEventsByTTL.get(0));
     }
 
+    @Test
+    public void testGetEntitiesWithTagChanges() throws Exception {
+        String      entityId1 = "tagChangeEntity1-" + rand();
+        String      entityId2 = "tagChangeEntity2-" + rand();
+        String      entityId3 = "tagChangeEntity3-" + rand();
+        AtlasEntity entity    = new AtlasEntity(rand());
+        long        ts        = System.currentTimeMillis();
+
+        eventRepository.putEventsV2(new EntityAuditEventV2(entityId1, ts + 1, "user1",
+                EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_ADD, "added PII", entity));
+        eventRepository.putEventsV2(new EntityAuditEventV2(entityId2, ts + 2, "user1",
+                EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_DELETE, "deleted PII", entity));
+        eventRepository.putEventsV2(new EntityAuditEventV2(entityId3, ts + 3, "user1",
+                EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_UPDATE, "updated PII", entity));
+
+        Set<String> result = eventRepository.getEntitiesWithTagChanges(ts, ts + 10);
+
+        assertNotNull(result);
+        assertTrue(result.contains(entityId1), "Expected CLASSIFICATION_ADD entity in result");
+        assertTrue(result.contains(entityId2), "Expected CLASSIFICATION_DELETE entity in result");
+        assertTrue(result.contains(entityId3), "Expected CLASSIFICATION_UPDATE entity in result");
+    }
+
+    @Test
+    public void testGetEntitiesWithTagChanges_emptyForNoMatchingTimeRange() throws Exception {
+        String      entityId = "tagChangeNoMatch-" + rand();
+        AtlasEntity entity   = new AtlasEntity(rand());
+        long        ts       = System.currentTimeMillis();
+
+        eventRepository.putEventsV2(new EntityAuditEventV2(entityId, ts + 100, "user1",
+                EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_ADD, "added PII", entity));
+
+        Set<String> result = eventRepository.getEntitiesWithTagChanges(ts, ts + 10);
+
+        assertNotNull(result);
+        assertFalse(result.contains(entityId), "Entity outside time range should not be in result");
+    }
+
+    @Test
+    public void testGetEntitiesWithTagChanges_deduplicatesEntities() throws Exception {
+        String      entityId = "tagChangeDuplicate-" + rand();
+        AtlasEntity entity   = new AtlasEntity(rand());
+        long        ts       = System.currentTimeMillis();
+
+        eventRepository.putEventsV2(new EntityAuditEventV2(entityId, ts + 1, "user1",
+                EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_ADD, "added PII", entity));
+        eventRepository.putEventsV2(new EntityAuditEventV2(entityId, ts + 2, "user1",
+                EntityAuditEventV2.EntityAuditActionV2.CLASSIFICATION_UPDATE, "updated PII", entity));
+
+        Set<String> result = eventRepository.getEntitiesWithTagChanges(ts, ts + 10);
+
+        assertNotNull(result);
+        assertTrue(result.contains(entityId));
+        long count = result.stream().filter(id -> id.equals(entityId)).count();
+        assertEquals(count, 1, "Entity should appear only once in the result set");
+    }
+
     protected void assertEventV1Equals(EntityAuditEvent actual, EntityAuditEvent expected) {
         if (expected != null) {
             assertNotNull(actual);