fix: iterate arrays in reverse when removing elements in SearchClient (#23215)

* fix: iterate arrays in reverse when removing elements in SearchClient

Changed loops in SearchClient.java to iterate backwards over tags, dataProducts,
lineage, entityRelationship, and testSuites arrays before removing elements.

This prevents skipping elements or index errors due to forward iteration while removing items.

* Refactor Painless scripts to use removeIf and Java multiline strings

* Fix failed Java checkstyle

---------

Co-authored-by: Mohit Yadav <105265192+mohityadav766@users.noreply.github.com>
(cherry picked from commit c336257cf4d6ed7ae7cc47c08cdb9a438dd19796)
This commit is contained in:
Bhanuagr 2025-09-11 06:05:43 +01:00 committed by OpenMetadata Release Bot
parent 75e7b832d5
commit b08f980892

View File

@ -81,11 +81,10 @@ public interface SearchClient<T> {
+ "ctx._source.put('%s', newObject); "
+ "}";
String SOFT_DELETE_RESTORE_SCRIPT = "ctx._source.put('deleted', '%s')";
String REMOVE_TAGS_CHILDREN_SCRIPT =
"for (int i = 0; i < ctx._source.tags.length; i++) { if (ctx._source.tags[i].tagFQN == params.fqn) { ctx._source.tags.remove(i) }}";
String REMOVE_TAGS_CHILDREN_SCRIPT = "ctx._source.tags.removeIf(tag -> tag.tagFQN == params.fqn)";
String REMOVE_DATA_PRODUCTS_CHILDREN_SCRIPT =
"for (int i = 0; i < ctx._source.dataProducts.length; i++) { if (ctx._source.dataProducts[i].fullyQualifiedName == params.fqn) { ctx._source.dataProducts.remove(i) }}";
"ctx._source.dataProducts.removeIf(product -> product.fullyQualifiedName == params.fqn)";
String UPDATE_CERTIFICATION_SCRIPT =
"if (ctx._source.certification != null && ctx._source.certification.tagLabel != null) {ctx._source.certification.tagLabel.style = params.style; ctx._source.certification.tagLabel.description = params.description; ctx._source.certification.tagLabel.tagFQN = params.tagFQN; ctx._source.certification.tagLabel.name = params.name; }";
@ -102,10 +101,10 @@ public interface SearchClient<T> {
+ "}";
String REMOVE_LINEAGE_SCRIPT =
"for (int i = 0; i < ctx._source.upstreamLineage.length; i++) { if (ctx._source.upstreamLineage[i].docUniqueId == '%s') { ctx._source.upstreamLineage.remove(i) }}";
"ctx._source.upstreamLineage.removeIf(lineage -> lineage.docUniqueId == '%s')";
String REMOVE_ENTITY_RELATIONSHIP =
"for (int i = 0; i < ctx._source.upstreamEntityRelationship.length; i++) { if (ctx._source.upstreamEntityRelationship[i].docId == '%s') { ctx._source.upstreamEntityRelationship.remove(i) }}";
"ctx._source.upstreamEntityRelationship.removeIf(relationship -> relationship.docId == '%s')";
String ADD_UPDATE_LINEAGE =
"boolean docIdExists = false; for (int i = 0; i < ctx._source.upstreamLineage.size(); i++) { if (ctx._source.upstreamLineage[i].docUniqueId.equalsIgnoreCase(params.lineageData.docUniqueId)) { ctx._source.upstreamLineage[i] = params.lineageData; docIdExists = true; break;}}if (!docIdExists) {ctx._source.upstreamLineage.add(params.lineageData);}";
@ -120,9 +119,43 @@ public interface SearchClient<T> {
+ " ctx._source.upstreamEntityRelationship[i] = params.entityRelationshipData; docIdExists = true; break;}}"
+ "if (!docIdExists) {ctx._source.upstreamEntityRelationship.add(params.entityRelationshipData);}";
String UPDATE_ADDED_DELETE_GLOSSARY_TAGS =
"if (ctx._source.tags != null) { for (int i = ctx._source.tags.size() - 1; i >= 0; i--) { if (params.tagDeleted != null) { for (int j = 0; j < params.tagDeleted.size(); j++) { if (ctx._source.tags[i].tagFQN.equalsIgnoreCase(params.tagDeleted[j].tagFQN)) { ctx._source.tags.remove(i); } } } } } if (ctx._source.tags == null) { ctx._source.tags = []; } if (params.tagAdded != null) { ctx._source.tags.addAll(params.tagAdded); } ctx._source.tags = ctx._source.tags .stream() .distinct() .sorted((o1, o2) -> o1.tagFQN.compareTo(o2.tagFQN)) .collect(Collectors.toList());";
"""
if (ctx._source.tags != null) {
for (int i = ctx._source.tags.size() - 1; i >= 0; i--) {
if (params.tagDeleted != null) {
for (int j = 0; j < params.tagDeleted.size(); j++) {
if (ctx._source.tags[i].tagFQN.equalsIgnoreCase(params.tagDeleted[j].tagFQN)) {
ctx._source.tags.remove(i);
break;
}
}
}
}
}
if (ctx._source.tags == null) {
ctx._source.tags = [];
}
if (params.tagAdded != null) {
ctx._source.tags.addAll(params.tagAdded);
}
Set seen = new HashSet();
List uniqueTags = [];
for (def tag : ctx._source.tags) {
if (!seen.contains(tag.tagFQN)) {
seen.add(tag.tagFQN);
uniqueTags.add(tag);
}
}
Collections.sort(uniqueTags, (o1, o2) -> o1.tagFQN.compareTo(o2.tagFQN));
ctx._source.tags = uniqueTags;
""";
String REMOVE_TEST_SUITE_CHILDREN_SCRIPT =
"for (int i = 0; i < ctx._source.testSuites.length; i++) { if (ctx._source.testSuites[i].id == '%s') { ctx._source.testSuites.remove(i) }}";
"ctx._source.testSuites.removeIf(suite -> suite.id == '%s')";
String ADD_OWNERS_SCRIPT =
"if (ctx._source.owners == null || ctx._source.owners.isEmpty() || "