Skip to content

Commit

Permalink
#30894 second try eith the multi data base unique fields validation
Browse files Browse the repository at this point in the history
  • Loading branch information
freddyDOTCMS committed Jan 14, 2025
1 parent 9882aa2 commit cd28d52
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.dotcms.content.elasticsearch.business.ESContentletAPIImpl.UNIQUE_PER_SITE_FIELD_VARIABLE_NAME;
Expand Down Expand Up @@ -218,7 +217,6 @@ private static boolean isLive(Contentlet contentlet) {
*
* @throws UniqueFieldValueDuplicatedException The unique value already exists.
*/
@WrapInTransaction
private void insertUniqueValue(final UniqueFieldCriteria uniqueFieldCriteria, final String contentletId) throws UniqueFieldValueDuplicatedException {
final boolean uniquePerSite = uniqueFieldCriteria.field().fieldVariableValue(UNIQUE_PER_SITE_FIELD_VARIABLE_NAME)
.map(Boolean::valueOf).orElse(false);
Expand All @@ -230,39 +228,25 @@ private void insertUniqueValue(final UniqueFieldCriteria uniqueFieldCriteria, fi
try {
Logger.debug(DBUniqueFieldValidationStrategy.class, String.format("Including value of field '%s' in Contentlet " +
"'%s' in the unique_fields table", uniqueFieldCriteria.field().variable(), contentletId));
uniqueFieldDataBaseUtil.insert(uniqueFieldCriteria.criteria(), supportingValues);
} catch (final DotDataException e) {
if (isDuplicatedKeyError(e)) {
final boolean isUnique = uniqueFieldDataBaseUtil.validateDuplicated(uniqueFieldCriteria.criteria(), supportingValues);

if (!isUnique) {
final String duplicatedValueMessage = String.format("The unique value '%s' for the field '%s'" +
" in the Content Type '%s' already exists",
uniqueFieldCriteria.value(), uniqueFieldCriteria.field().variable(),
uniqueFieldCriteria.contentType().variable());

Logger.error(DBUniqueFieldValidationStrategy.class, duplicatedValueMessage);
throw new UniqueFieldValueDuplicatedException(duplicatedValueMessage);
} else {
final String errorMsg = String.format("Failed to insert unique value for Field '%s' in Contentlet " +
"'%s': %s", uniqueFieldCriteria.field().variable(), contentletId, ExceptionUtil.getErrorMessage(e));
Logger.error(this, errorMsg, e);
throw new DotRuntimeException(errorMsg);
}
} catch (final DotDataException e) {
final String errorMsg = String.format("Failed to insert unique value for Field '%s' in Contentlet " +
"'%s': %s", uniqueFieldCriteria.field().variable(), contentletId, ExceptionUtil.getErrorMessage(e));
Logger.error(this, errorMsg, e);
throw new DotRuntimeException(errorMsg);
}
}

/**
* Utility method to check if the exception's message belongs to a situation in which the
* unique key has been violated. In this case, it means that a unique value already exists.
*
* @param exception The exception to check.
*
* @return If the exception is related to a duplicated key error, returns {@code true}.
*/
private static boolean isDuplicatedKeyError(final Exception exception) {
final String originalMessage = exception.getMessage();
return originalMessage != null && originalMessage.startsWith(
"ERROR: duplicate key value violates unique constraint \"unique_fields_pkey\"");
}

@WrapInTransaction
@Override
public void recalculate(final Field field, final boolean uniquePerSite) throws UniqueFieldValueDuplicatedException {
Expand All @@ -284,6 +268,20 @@ public void recalculate(final Field field, final boolean uniquePerSite) throws U
}
}

/**
* Utility method to check if the exception's message belongs to a situation in which the
* unique key has been violated. In this case, it means that a unique value already exists.
*
* @param exception The exception to check.
*
* @return If the exception is related to a duplicated key error, returns {@code true}.
*/
private static boolean isDuplicatedKeyError(final Exception exception) {
final String originalMessage = exception.getMessage();
return originalMessage != null && originalMessage.startsWith(
"ERROR: duplicate key value violates unique constraint \"unique_fields_pkey\"");
}

@Override
public void cleanUp(final Contentlet contentlet, final boolean deleteAllVariant) throws DotDataException {
if (deleteAllVariant) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
import com.dotmarketing.common.db.DotConnect;
import com.dotmarketing.db.HibernateUtil;
import com.dotmarketing.exception.DotDataException;
import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.exception.DotSecurityException;
import com.dotmarketing.portlets.contentlet.model.Contentlet;
import com.dotmarketing.util.Logger;
import com.liferay.util.StringPool;
Expand Down Expand Up @@ -148,12 +146,38 @@ public void insertWithHash(final String key, final Map<String, Object> supportin
new DotConnect().setSQL(INSERT_SQL_WIT_HASH).addParam(key).addJSONParam(supportingValues).loadObjectResults();
}

public void insert(final String key, final Map<String, Object> supportingValues) throws DotDataException {
new DotConnect()
.setSQL(INSERT_SQL)
.addParam(key)
.addJSONParam(supportingValues)
.loadObjectResults();
public boolean validateDuplicated(final String key, final Map<String, Object> supportingValues) throws DotDataException {
try {
new DotConnect()
.setSQL(INSERT_SQL)
.addParam(key)
.addJSONParam(supportingValues)
.loadObjectResults();

return true;
} catch (final DotDataException e) {
if (isDuplicatedKeyError(e)) {
return false;
} else {
throw e;
}
}finally {
HibernateUtil.closeAndCommitTransaction();
}
}

/**
* Utility method to check if the exception's message belongs to a situation in which the
* unique key has been violated. In this case, it means that a unique value already exists.
*
* @param exception The exception to check.
*
* @return If the exception is related to a duplicated key error, returns {@code true}.
*/
private static boolean isDuplicatedKeyError(final Exception exception) {
final String originalMessage = exception.getMessage();
return originalMessage != null && originalMessage.startsWith(
"ERROR: duplicate key value violates unique constraint \"unique_fields_pkey\"");
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4599,7 +4599,7 @@ public void saveSiteIDRightInSupportingValues() throws DotDataException, DotSecu
* @throws DotSecurityException
*/
@Test
public void multiUniqueFieldsCIntentType() throws DotDataException, DotSecurityException {
public void multiUniqueFieldsContentType() throws DotDataException, DotSecurityException {

final boolean oldEnabledDataBaseValidation = ESContentletAPIImpl.getFeatureFlagDbUniqueFieldValidation();

Expand Down Expand Up @@ -4746,7 +4746,7 @@ public void multiUniqueFieldsCIntentTypeKeepExtableUnTouch() throws DotDataExcep

} catch (Exception e){
final String expectedMessage = String.format("Contentlet with ID 'Unknown/New' [''] has invalid/missing field(s)."
+ " - Fields: [UNIQUE]: %s (%s)", uniqueTextField_1.name(), uniqueTextField_1.variable());
+ " - Fields: [UNIQUE]: %s (%s)", uniqueTextField_2.name(), uniqueTextField_2.variable());

assertEquals(expectedMessage, e.getMessage());
}
Expand Down

0 comments on commit cd28d52

Please sign in to comment.