in polaris-synchronizer/api/src/main/java/org/apache/polaris/tools/sync/polaris/planning/BaseStrategyPlanner.java [84:151]
private <T> SynchronizationPlan<T> sortOnIdentifier(
Collection<T> entitiesOnSource,
Collection<T> entitiesOnTarget,
boolean requiresOverwrites,
Function<T, Object> entityIdentifierSupplier
) {
Set<Object> sourceEntityIdentifiers = entitiesOnSource.stream().map(entityIdentifierSupplier).collect(Collectors.toSet());
Set<Object> targetEntityIdentifiers = entitiesOnTarget.stream().map(entityIdentifierSupplier).collect(Collectors.toSet());
SynchronizationPlan<T> plan = new SynchronizationPlan<>();
for (T entityOnSource : entitiesOnSource) {
Object sourceEntityId = entityIdentifierSupplier.apply(entityOnSource);
if (targetEntityIdentifiers.contains(sourceEntityId)) {
// If an entity with this identifier exists on both the source and the target
if (strategy == Strategy.CREATE_ONLY) {
// if the same entity identifier is on the source and target,
// but we only permit creates, skip it
plan.skipEntity(entityOnSource);
} else {
// if the same entity identifier is on the source and the target,
// overwrite the one on the target with the one on the source
if (requiresOverwrites) {
// If the entity requires a drop-and-recreate to perform an overwrite.
// some grant records can be "created" indefinitely even if they already exists, for example,
// catalog roles can be assigned the same principal role many times
plan.overwriteEntity(entityOnSource);
} else {
// if the entity is not a type that requires "overwriting" in the sense of
// dropping and recreating, then just create it again
plan.createEntity(entityOnSource);
}
}
} else {
// if the entity identifier only exists on the source, that means
// we need to create it for the first time on the target
plan.createEntity(entityOnSource);
}
}
for (T entityOnTarget : entitiesOnTarget) {
Object targetEntityId = entityIdentifierSupplier.apply(entityOnTarget);
if (!sourceEntityIdentifiers.contains(targetEntityId)) {
// if the entity exists on the target but doesn't exist on the source,
// clean it up from the target
// this is especially important for access control entities, as, for example,
// we could have a scenario where a grant was revoked from a catalog role,
// or a catalog role was revoked from a principal role, in which case the target
// should reflect this change when the tool is run multiple times, because we don't
// want to take chances with over-extending privileges
if (strategy == Strategy.REPLICATE) {
plan.removeEntity(entityOnTarget);
} else {
// skip children here because if we want to remove the entity
// and then that means it does not exist on the source, so there are no child
// entities to sync
plan.skipEntityAndSkipChildren(entityOnTarget);
}
}
}
return plan;
}