mirror of
https://github.com/datahub-project/datahub.git
synced 2025-09-25 09:00:50 +00:00
fix(mysql): modifies hashing and equals behavior for primary keys to match mysql behavior (#13984)
This commit is contained in:
parent
1228f9b1de
commit
c2928a1a6d
@ -303,14 +303,15 @@ public class EbeanAspectDao implements AspectDao, AspectMigrationsDao {
|
||||
|
||||
int position = 0;
|
||||
|
||||
List<EbeanAspectV2.PrimaryKey> keyList = new ArrayList<>(keys);
|
||||
final int totalPageCount = QueryUtils.getTotalPageCount(keys.size(), keysCount);
|
||||
final List<EbeanAspectV2> finalResult =
|
||||
batchGetSelectString(new ArrayList<>(keys), keysCount, position, forUpdate);
|
||||
batchGetSelectString(keyList, keysCount, position, forUpdate);
|
||||
|
||||
while (QueryUtils.hasMore(position, keysCount, totalPageCount)) {
|
||||
position += keysCount;
|
||||
final List<EbeanAspectV2> oneStatementResult =
|
||||
batchGetSelectString(new ArrayList<>(keys), keysCount, position, forUpdate);
|
||||
batchGetSelectString(keyList, keysCount, position, forUpdate);
|
||||
finalResult.addAll(oneStatementResult);
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,9 @@ import jakarta.persistence.Lob;
|
||||
import jakarta.persistence.Table;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Objects;
|
||||
import javax.annotation.Nonnull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
@ -43,13 +43,17 @@ public class EbeanAspectV2 extends Model {
|
||||
/** Key for an aspect in the table. */
|
||||
@Embeddable
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@EqualsAndHashCode
|
||||
public static class PrimaryKey implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public PrimaryKey(@Nonnull String urn, @Nonnull String aspect, long version) {
|
||||
this.urn = urn.stripTrailing();
|
||||
this.aspect = aspect.stripTrailing();
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Index
|
||||
@Column(name = URN_COLUMN, length = 500, nullable = false)
|
||||
@ -71,6 +75,27 @@ public class EbeanAspectV2 extends Model {
|
||||
public EntityAspectIdentifier toAspectIdentifier() {
|
||||
return new EntityAspectIdentifier(getUrn(), getAspect(), getVersion());
|
||||
}
|
||||
|
||||
// Custom Equals and Hash code that trims to handle MySQL PAD SPACE:
|
||||
// https://dev.mysql.com/doc/refman/8.4/en/charset-binary-collations.html#charset-binary-collations-trailing-space-comparisons
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
PrimaryKey that = (PrimaryKey) o;
|
||||
return version == that.version
|
||||
&& Objects.equals(urn.stripTrailing(), that.urn.stripTrailing())
|
||||
&& Objects.equals(aspect.stripTrailing(), that.aspect.stripTrailing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(urn.stripTrailing(), aspect.stripTrailing(), version);
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull @EmbeddedId @Index protected PrimaryKey key;
|
||||
|
@ -70,6 +70,7 @@ import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
import org.apache.commons.lang3.tuple.Triple;
|
||||
import org.testcontainers.shaded.com.google.common.collect.ImmutableSet;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
@ -482,6 +483,40 @@ public class EbeanEntityServiceTest
|
||||
"Expected version 0 with systemMeta version 3 accounting for the the collision");
|
||||
}
|
||||
|
||||
// NOTE: This is not currently super useful because H2 always treats spaces as significant
|
||||
@Test
|
||||
public void testSystemMetadataDuplicateKeyWhitespace() throws Exception {
|
||||
Urn entityUrn = UrnUtils.getUrn("urn:li:corpuser:duplicateKeyTest");
|
||||
SystemMetadata systemMetadata = AspectGenerationUtils.createSystemMetadata();
|
||||
ChangeItemImpl item =
|
||||
ChangeItemImpl.builder()
|
||||
.urn(entityUrn)
|
||||
.aspectName(STATUS_ASPECT_NAME)
|
||||
.recordTemplate(new Status().setRemoved(true))
|
||||
.systemMetadata(systemMetadata)
|
||||
.auditStamp(TEST_AUDIT_STAMP)
|
||||
.build(TestOperationContexts.emptyActiveUsersAspectRetriever(null));
|
||||
_entityServiceImpl.ingestAspects(
|
||||
opContext,
|
||||
AspectsBatchImpl.builder()
|
||||
.retrieverContext(opContext.getRetrieverContext())
|
||||
.items(List.of(item))
|
||||
.build(opContext),
|
||||
false,
|
||||
true);
|
||||
|
||||
Urn entityUrnWhitespace = UrnUtils.getUrn(entityUrn + " ");
|
||||
Map<Urn, List<EnvelopedAspect>> envelopedAspects =
|
||||
_entityServiceImpl.getLatestEnvelopedAspects(
|
||||
opContext,
|
||||
ImmutableSet.of(entityUrn, entityUrnWhitespace),
|
||||
ImmutableSet.of(STATUS_ASPECT_NAME),
|
||||
false);
|
||||
|
||||
assertEquals(envelopedAspects.get(entityUrn).size(), 1);
|
||||
assertEquals(envelopedAspects.get(entityUrnWhitespace).size(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dataGeneratorThreadingTest() {
|
||||
DataGenerator dataGenerator = new DataGenerator(opContext, _entityServiceImpl);
|
||||
|
Loading…
x
Reference in New Issue
Block a user