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 <[email protected]>
AuthorDate: Tue Oct 27 15:52:57 2026 +0530
ATLAS-5425:Implement getEntitiesWithTagChanges for RDBMS audit repository
(#791)
Co-authored-by: sanket.bhor <[email protected]>
(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 < :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);