From 5e8726b92b0eaef87c3ad7a9ecb6ca0c2ff35ae0 Mon Sep 17 00:00:00 2001 From: Michael Muller Date: Tue, 25 May 2021 11:28:30 -0400 Subject: [PATCH] Safely lazy load claims and reserved lists (#1177) * Safely lazy load claims and reserved lists This moves the entries of all of these lists into "insignificant" fields and manages them explicitly. * Additional fixes Fix a few problems that came up in the merge or weren't caught in earlier local test runs. * Changes for review - removed debug code - added comments - improved some methods that were loading the entire claims list unnecessarily. * Fixed javadoc links * Reformatted * Minor fix for review --- .../registry/label/BaseDomainLabelList.java | 5 +- .../registry/label/DomainLabelEntry.java | 3 +- .../model/registry/label/ReservedList.java | 83 ++++++++++--- .../model/registry/label/ReservedListDao.java | 5 +- .../registry/model/tmch/ClaimsEntry.java | 56 +++++++++ .../registry/model/tmch/ClaimsList.java | 114 ++++++++++++++---- .../registry/model/tmch/ClaimsListDao.java | 11 +- .../tools/CreateReservedListCommand.java | 25 ++++ .../main/resources/META-INF/persistence.xml | 2 + .../registry/label/ReservedListTest.java | 24 ++-- ...teOrUpdateReservedListCommandTestCase.java | 5 +- .../google/registry/model/schema.txt | 3 +- .../sql/schema/db-schema.sql.generated | 16 +-- 13 files changed, 276 insertions(+), 76 deletions(-) create mode 100644 core/src/main/java/google/registry/model/tmch/ClaimsEntry.java diff --git a/core/src/main/java/google/registry/model/registry/label/BaseDomainLabelList.java b/core/src/main/java/google/registry/model/registry/label/BaseDomainLabelList.java index b5454e4c2..a64532240 100644 --- a/core/src/main/java/google/registry/model/registry/label/BaseDomainLabelList.java +++ b/core/src/main/java/google/registry/model/registry/label/BaseDomainLabelList.java @@ -38,7 +38,6 @@ import google.registry.model.ImmutableObject; import google.registry.model.annotations.InCrossTld; import google.registry.model.common.EntityGroupRoot; import google.registry.model.registry.Registry; -import google.registry.model.registry.label.ReservedList.ReservedListEntry; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -56,8 +55,8 @@ import org.joda.time.DateTime; * Base class for {@link ReservedList} and {@link PremiumList} objects stored in Datastore. * * @param The type of the root value being listed, e.g. {@link ReservationType}. - * @param The type of domain label entry being listed, e.g. {@link ReservedListEntry} (note, - * must subclass {@link DomainLabelEntry}. + * @param The type of domain label entry being listed, e.g. {@link + * ReservedList.ReservedListEntry} (note, must subclass {@link DomainLabelEntry}. */ @MappedSuperclass @InCrossTld diff --git a/core/src/main/java/google/registry/model/registry/label/DomainLabelEntry.java b/core/src/main/java/google/registry/model/registry/label/DomainLabelEntry.java index 435c6b5b8..3c857b8a3 100644 --- a/core/src/main/java/google/registry/model/registry/label/DomainLabelEntry.java +++ b/core/src/main/java/google/registry/model/registry/label/DomainLabelEntry.java @@ -36,7 +36,8 @@ public abstract class DomainLabelEntry, D extends Domain extends ImmutableObject implements Comparable { @Id - @Column(name = "domain_label", insertable = false, updatable = false) + @javax.persistence.Id + @Column(name = "domain_label", nullable = false) String label; String comment; diff --git a/core/src/main/java/google/registry/model/registry/label/ReservedList.java b/core/src/main/java/google/registry/model/registry/label/ReservedList.java index 0698f256d..dd2f18e8d 100644 --- a/core/src/main/java/google/registry/model/registry/label/ReservedList.java +++ b/core/src/main/java/google/registry/model/registry/label/ReservedList.java @@ -17,9 +17,13 @@ package google.registry.model.registry.label; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.isNullOrEmpty; +import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration; +import static google.registry.model.ImmutableObject.Insignificant; import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED; +import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ; +import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import static google.registry.util.CollectionUtils.nullToEmpty; import static org.joda.time.DateTimeZone.UTC; @@ -40,19 +44,19 @@ import google.registry.model.annotations.ReportedOn; import google.registry.model.registry.Registry; import google.registry.model.registry.label.DomainLabelMetrics.MetricsReservedListMatch; import google.registry.schema.replay.NonReplicatedEntity; +import java.io.Serializable; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ExecutionException; import javax.annotation.Nullable; -import javax.persistence.CollectionTable; import javax.persistence.Column; -import javax.persistence.ElementCollection; -import javax.persistence.Embeddable; +import javax.persistence.Id; import javax.persistence.Index; -import javax.persistence.JoinColumn; -import javax.persistence.MapKeyColumn; +import javax.persistence.PostPersist; +import javax.persistence.PreRemove; import javax.persistence.Table; +import javax.persistence.Transient; import org.joda.time.DateTime; /** @@ -71,25 +75,60 @@ public final class ReservedList extends BaseDomainLabelList implements NonReplicatedEntity { + /** + * Mapping from domain name to its reserved list info. + * + *

This field requires special treatment since we want to lazy load it. We have to remove it + * from the immutability contract so we can modify it after construction and we have to handle the + * database processing on our own so we can detach it after load. + */ @Mapify(ReservedListEntry.LabelMapper.class) - @ElementCollection - @CollectionTable( - name = "ReservedEntry", - joinColumns = @JoinColumn(name = "revisionId", referencedColumnName = "revisionId")) - @MapKeyColumn(name = "domain_label") + @Insignificant + @Transient Map reservedListMap; @Column(nullable = false) boolean shouldPublish = true; + @PreRemove + void preRemove() { + jpaTm() + .query("DELETE FROM ReservedEntry WHERE revision_id = :revisionId") + .setParameter("revisionId", revisionId) + .executeUpdate(); + } + + /** + * Hibernate hook called on the insert of a new ReservedList. Stores the associated {@link + * ReservedEntry}'s. + * + *

We need to persist the list entries, but only on the initial insert (not on update) since + * the entries themselves never get changed, so we only annotate it with {@link PostPersist}, not + * {@link PostUpdate}. + */ + @PostPersist + void postPersist() { + if (reservedListMap != null) { + reservedListMap.values().stream() + .forEach( + entry -> { + // We can safely change the revision id since it's "Insignificant". + entry.revisionId = revisionId; + jpaTm().insert(entry); + }); + } + } + /** * A reserved list entry entity, persisted to Datastore, that represents a single label and its * reservation type. */ @Embed - @Embeddable + @javax.persistence.Entity(name = "ReservedEntry") public static class ReservedListEntry extends DomainLabelEntry - implements Buildable { + implements Buildable, NonReplicatedEntity, Serializable { + + @Insignificant @Id Long revisionId; @Column(nullable = false) ReservationType reservationType; @@ -164,8 +203,24 @@ public final class ReservedList return shouldPublish; } - /** Returns a {@link Map} of domain labels to {@link ReservedListEntry}. */ - public ImmutableMap getReservedListEntries() { + /** + * Returns a {@link Map} of domain labels to {@link ReservedListEntry}. + * + *

Note that this involves a database fetch of a potentially large number of elements and + * should be avoided unless necessary. + */ + public synchronized ImmutableMap getReservedListEntries() { + if (reservedListMap == null) { + reservedListMap = + jpaTm() + .transact( + () -> + jpaTm() + .createQueryComposer(ReservedListEntry.class) + .where("revisionId", EQ, revisionId) + .stream() + .collect(toImmutableMap(ReservedListEntry::getLabel, e -> e))); + } return ImmutableMap.copyOf(nullToEmpty(reservedListMap)); } diff --git a/core/src/main/java/google/registry/model/registry/label/ReservedListDao.java b/core/src/main/java/google/registry/model/registry/label/ReservedListDao.java index 14c1360e9..7183636a7 100644 --- a/core/src/main/java/google/registry/model/registry/label/ReservedListDao.java +++ b/core/src/main/java/google/registry/model/registry/label/ReservedListDao.java @@ -52,9 +52,8 @@ public class ReservedListDao { () -> jpaTm() .query( - "FROM ReservedList rl LEFT JOIN FETCH rl.reservedListMap WHERE" - + " rl.revisionId IN (SELECT MAX(revisionId) FROM ReservedList subrl" - + " WHERE subrl.name = :name)", + "FROM ReservedList WHERE revisionId IN " + + "(SELECT MAX(revisionId) FROM ReservedList WHERE name = :name)", ReservedList.class) .setParameter("name", reservedListName) .getResultStream() diff --git a/core/src/main/java/google/registry/model/tmch/ClaimsEntry.java b/core/src/main/java/google/registry/model/tmch/ClaimsEntry.java new file mode 100644 index 000000000..864936d93 --- /dev/null +++ b/core/src/main/java/google/registry/model/tmch/ClaimsEntry.java @@ -0,0 +1,56 @@ +// Copyright 2021 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.model.tmch; + +import google.registry.model.ImmutableObject; +import google.registry.schema.replay.NonReplicatedEntity; +import java.io.Serializable; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +/** + * Claims entry record, used by ClaimsList for persistence. + * + *

It would be preferable to have this nested in {@link ClaimsList}, but for some reason + * hibernate won't generate this into the schema in this case. We may not care, as we only use the + * generated schema for informational purposes and persistence against the actual schema seems to + * work. + */ +@Entity(name = "ClaimsEntry") +class ClaimsEntry extends ImmutableObject implements NonReplicatedEntity, Serializable { + @Id private Long revisionId; + @Id private String domainLabel; + + @Column(nullable = false) + private String claimKey; + + /** Default constructor for Hibernate. */ + ClaimsEntry() {} + + ClaimsEntry(Long revisionId, String domainLabel, String claimKey) { + this.revisionId = revisionId; + this.domainLabel = domainLabel; + this.claimKey = claimKey; + } + + String getDomainLabel() { + return domainLabel; + } + + String getClaimKey() { + return claimKey; + } +} diff --git a/core/src/main/java/google/registry/model/tmch/ClaimsList.java b/core/src/main/java/google/registry/model/tmch/ClaimsList.java index 03d8fa55b..c9a16a800 100644 --- a/core/src/main/java/google/registry/model/tmch/ClaimsList.java +++ b/core/src/main/java/google/registry/model/tmch/ClaimsList.java @@ -16,13 +16,15 @@ package google.registry.model.tmch; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.ImmutableMap.toImmutableMap; import static google.registry.model.ofy.ObjectifyService.allocateId; import static google.registry.model.ofy.ObjectifyService.auditedOfy; +import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ; +import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableMap; import com.googlecode.objectify.Key; -import com.googlecode.objectify.annotation.EmbedMap; import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Ignore; @@ -39,13 +41,11 @@ import google.registry.schema.replay.NonReplicatedEntity; import java.util.Map; import java.util.Optional; import javax.annotation.Nullable; -import javax.persistence.CollectionTable; import javax.persistence.Column; -import javax.persistence.ElementCollection; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; -import javax.persistence.JoinColumn; -import javax.persistence.MapKeyColumn; +import javax.persistence.PostPersist; +import javax.persistence.PreRemove; import javax.persistence.Table; import javax.persistence.Transient; import org.joda.time.DateTime; @@ -94,15 +94,40 @@ public class ClaimsList extends ImmutableObject implements NonReplicatedEntity { @Column(name = "tmdb_generation_time", nullable = false) DateTime creationTime; - /** A map from labels to claims keys. */ - @EmbedMap - @ElementCollection - @CollectionTable( - name = "ClaimsEntry", - joinColumns = @JoinColumn(name = "revisionId", referencedColumnName = "revisionId")) - @MapKeyColumn(name = "domainLabel", nullable = false) - @Column(name = "claimKey", nullable = false) - Map labelsToKeys; + /** + * A map from labels to claims keys. + * + *

This field requires special treatment since we want to lazy load it. We have to remove it + * from the immutability contract so we can modify it after construction and we have to handle the + * database processing on our own so we can detach it after load. + */ + @Insignificant @Transient ImmutableMap labelsToKeys; + + @PreRemove + void preRemove() { + jpaTm() + .query("DELETE FROM ClaimsEntry WHERE revision_id = :revisionId") + .setParameter("revisionId", revisionId) + .executeUpdate(); + } + + /** + * Hibernate hook called on the insert of a new ReservedList. Stores the associated {@link + * ReservedListEntry}'s. + * + *

We need to persist the list entries, but only on the initial insert (not on update) since + * the entries themselves never get changed, so we only annotate it with {@link PostPersist}, not + * {@link PostUpdate}. + */ + @PostPersist + void postPersist() { + if (labelsToKeys != null) { + labelsToKeys.entrySet().stream() + .forEach( + entry -> + jpaTm().insert(new ClaimsEntry(revisionId, entry.getKey(), entry.getValue()))); + } + } /** Returns the revision id of this claims list, or throws exception if it is null. */ public Long getRevisionId() { @@ -126,22 +151,69 @@ public class ClaimsList extends ImmutableObject implements NonReplicatedEntity { return creationTimestamp.getTimestamp(); } - /** Returns the claim key for a given domain if there is one, empty otherwise. */ + /** + * Returns the claim key for a given domain if there is one, empty otherwise. + * + *

Note that this may do a database query. For checking multiple keys against the claims list + * it may be more efficient to use {@link #getLabelsToKeys()} first, as this will prefetch all + * entries and cache them locally. + */ public Optional getClaimKey(String label) { - return Optional.ofNullable(labelsToKeys.get(label)); + if (labelsToKeys != null) { + return Optional.ofNullable(labelsToKeys.get(label)); + } + return jpaTm() + .transact( + () -> + jpaTm() + .createQueryComposer(ClaimsEntry.class) + .where("revisionId", EQ, revisionId) + .where("domainLabel", EQ, label) + .first() + .map(ClaimsEntry::getClaimKey)); } - /** Returns an {@link Map} mapping domain label to its lookup key. */ + /** + * Returns an {@link Map} mapping domain label to its lookup key. + * + *

Note that this involves a database fetch of a potentially large number of elements and + * should be avoided unless necessary. + */ public ImmutableMap getLabelsToKeys() { - return ImmutableMap.copyOf(labelsToKeys); + if (labelsToKeys == null) { + labelsToKeys = + jpaTm() + .transact( + () -> + jpaTm() + .createQueryComposer(ClaimsEntry.class) + .where("revisionId", EQ, revisionId) + .stream() + .collect( + toImmutableMap( + ClaimsEntry::getDomainLabel, ClaimsEntry::getClaimKey))); + } + return labelsToKeys; } - /** Returns the number of claims. */ - public int size() { + /** + * Returns the number of claims. + * + *

Note that this will perform a database "count" query if the label to key map has not been + * previously cached by calling {@link #getLabelsToKeys()}. + */ + public long size() { + if (labelsToKeys == null) { + return jpaTm() + .createQueryComposer(ClaimsEntry.class) + .where("revisionId", EQ, revisionId) + .count(); + } return labelsToKeys.size(); } - public static ClaimsList create(DateTime tmdbGenerationTime, Map labelsToKeys) { + public static ClaimsList create( + DateTime tmdbGenerationTime, ImmutableMap labelsToKeys) { ClaimsList instance = new ClaimsList(); instance.id = allocateId(); instance.creationTime = checkNotNull(tmdbGenerationTime); diff --git a/core/src/main/java/google/registry/model/tmch/ClaimsListDao.java b/core/src/main/java/google/registry/model/tmch/ClaimsListDao.java index a0c23d1c5..ff7df8671 100644 --- a/core/src/main/java/google/registry/model/tmch/ClaimsListDao.java +++ b/core/src/main/java/google/registry/model/tmch/ClaimsListDao.java @@ -14,6 +14,7 @@ package google.registry.model.tmch; +import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ; import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import static google.registry.util.DateTimeUtils.START_OF_TIME; @@ -40,13 +41,9 @@ public class ClaimsListDao { .query("SELECT MAX(revisionId) FROM ClaimsList", Long.class) .getSingleResult(); return jpaTm() - .query( - "FROM ClaimsList cl LEFT JOIN FETCH cl.labelsToKeys WHERE cl.revisionId =" - + " :revisionId", - ClaimsList.class) - .setParameter("revisionId", revisionId) - .getResultStream() - .findFirst(); + .createQueryComposer(ClaimsList.class) + .where("revisionId", EQ, revisionId) + .first(); }) .orElse(ClaimsList.create(START_OF_TIME, ImmutableMap.of())); } diff --git a/core/src/main/java/google/registry/tools/CreateReservedListCommand.java b/core/src/main/java/google/registry/tools/CreateReservedListCommand.java index 5921e30da..b8c554130 100644 --- a/core/src/main/java/google/registry/tools/CreateReservedListCommand.java +++ b/core/src/main/java/google/registry/tools/CreateReservedListCommand.java @@ -30,6 +30,7 @@ import google.registry.model.registry.label.ReservedList; import google.registry.persistence.VKey; import java.nio.file.Files; import java.util.List; +import java.util.stream.Collectors; import org.joda.time.DateTime; /** Command to create a {@link ReservedList}. */ @@ -73,6 +74,30 @@ final class CreateReservedListCommand extends CreateOrUpdateReservedListCommand null, reservedList, VKey.createOfy(ReservedList.class, Key.create(reservedList))); } + @Override + protected String prompt() { + return getChangedEntities().isEmpty() + ? "No entity changes to apply." + : getChangedEntities().stream() + .map( + entity -> { + if (entity instanceof ReservedList) { + // Format the entries of the reserved list as well. + String entries = + ((ReservedList) entity) + .getReservedListEntries().entrySet().stream() + .map( + entry -> + String.format("%s=%s", entry.getKey(), entry.getValue())) + .collect(Collectors.joining(", ")); + return String.format("%s\nreservedListMap={%s}\n", entity, entries); + } else { + return entity.toString(); + } + }) + .collect(Collectors.joining("\n")); + } + private static void validateListName(String name) { List nameParts = Splitter.on('_').splitToList(name); checkArgument(nameParts.size() == 2, INVALID_FORMAT_ERROR_MESSAGE); diff --git a/core/src/main/resources/META-INF/persistence.xml b/core/src/main/resources/META-INF/persistence.xml index e653ebb89..f19138f9b 100644 --- a/core/src/main/resources/META-INF/persistence.xml +++ b/core/src/main/resources/META-INF/persistence.xml @@ -61,6 +61,7 @@ google.registry.model.registrar.RegistrarContact google.registry.model.registry.label.PremiumList google.registry.model.registry.label.ReservedList + google.registry.model.registry.label.ReservedList$ReservedListEntry google.registry.model.registry.Registry google.registry.model.reporting.DomainTransactionRecord google.registry.model.reporting.Spec11ThreatMatch @@ -69,6 +70,7 @@ google.registry.model.server.ServerSecret google.registry.model.smd.SignedMarkRevocationList google.registry.model.tmch.ClaimsList + google.registry.model.tmch.ClaimsEntry google.registry.model.tmch.TmchCrl google.registry.persistence.transaction.TransactionEntity google.registry.schema.domain.RegistryLock diff --git a/core/src/test/java/google/registry/model/registry/label/ReservedListTest.java b/core/src/test/java/google/registry/model/registry/label/ReservedListTest.java index 0d8bee73b..d92315550 100644 --- a/core/src/test/java/google/registry/model/registry/label/ReservedListTest.java +++ b/core/src/test/java/google/registry/model/registry/label/ReservedListTest.java @@ -24,6 +24,7 @@ import static google.registry.model.registry.label.DomainLabelMetrics.reservedLi import static google.registry.model.registry.label.ReservationType.ALLOWED_IN_SUNRISE; import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED; import static google.registry.model.registry.label.ReservationType.NAME_COLLISION; +import static google.registry.model.registry.label.ReservedList.ReservedListEntry; import static google.registry.model.registry.label.ReservedList.getReservationTypes; import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.persistReservedList; @@ -34,32 +35,37 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import google.registry.model.ofy.Ofy; import google.registry.model.registry.Registry; -import google.registry.model.registry.label.ReservedList.ReservedListEntry; +import google.registry.schema.tld.PremiumEntry; import google.registry.testing.AppEngineExtension; -import google.registry.testing.DatabaseHelper; import google.registry.testing.FakeClock; import google.registry.testing.InjectExtension; import org.joda.time.DateTime; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; /** Unit tests for {@link ReservedList}. */ class ReservedListTest { - @RegisterExtension final InjectExtension inject = new InjectExtension(); + private FakeClock clock = new FakeClock(DateTime.parse("2010-01-01T10:00:00Z")); + + @Order(value = Order.DEFAULT - 1) + @RegisterExtension + final InjectExtension inject = + new InjectExtension().withStaticFieldOverride(Ofy.class, "clock", clock); @RegisterExtension final AppEngineExtension appEngine = - AppEngineExtension.builder().withDatastoreAndCloudSql().build(); - - private FakeClock clock = new FakeClock(DateTime.parse("2010-01-01T10:00:00Z")); + AppEngineExtension.builder() + .withClock(clock) + .withJpaUnitTestEntities( + PremiumList.class, PremiumEntry.class, ReservedList.class, ReservedListEntry.class) + .withDatastoreAndCloudSql() + .build(); @BeforeEach void beforeEach() { - inject.setStaticField(Ofy.class, "clock", clock); - // Auto-increment clock in DatabaseHelper. - inject.setStaticField(DatabaseHelper.class, "clock", clock); createTld("tld"); reservedListChecks.reset(); reservedListProcessingTime.reset(); diff --git a/core/src/test/java/google/registry/tools/CreateOrUpdateReservedListCommandTestCase.java b/core/src/test/java/google/registry/tools/CreateOrUpdateReservedListCommandTestCase.java index c156d82a4..b155dcb83 100644 --- a/core/src/test/java/google/registry/tools/CreateOrUpdateReservedListCommandTestCase.java +++ b/core/src/test/java/google/registry/tools/CreateOrUpdateReservedListCommandTestCase.java @@ -125,10 +125,7 @@ abstract class CreateOrUpdateReservedListCommandTestCase< .setParameter("name", name) .getSingleResult(); return jpaTm() - .query( - "FROM ReservedList rl LEFT JOIN FETCH rl.reservedListMap WHERE" - + " rl.revisionId = :revisionId", - ReservedList.class) + .query("FROM ReservedList WHERE revisionId = :revisionId", ReservedList.class) .setParameter("revisionId", revisionId) .getSingleResult(); }); diff --git a/core/src/test/resources/google/registry/model/schema.txt b/core/src/test/resources/google/registry/model/schema.txt index 003d7863d..bdf4ff2dd 100644 --- a/core/src/test/resources/google/registry/model/schema.txt +++ b/core/src/test/resources/google/registry/model/schema.txt @@ -754,6 +754,7 @@ class google.registry.model.registry.label.ReservedList { class google.registry.model.registry.label.ReservedList$ReservedListEntry { @Id java.lang.String label; google.registry.model.registry.label.ReservationType reservationType; + java.lang.Long revisionId; java.lang.String comment; } class google.registry.model.reporting.DomainTransactionRecord { @@ -862,7 +863,7 @@ class google.registry.model.server.ServerSecret { class google.registry.model.tmch.ClaimsList { @Id long id; @Parent com.googlecode.objectify.Key parent; - java.util.Map labelsToKeys; + com.google.common.collect.ImmutableMap labelsToKeys; org.joda.time.DateTime creationTime; } class google.registry.model.tmch.ClaimsList$ClaimsListRevision { diff --git a/db/src/main/resources/sql/schema/db-schema.sql.generated b/db/src/main/resources/sql/schema/db-schema.sql.generated index 319729525..c2d87aaa6 100644 --- a/db/src/main/resources/sql/schema/db-schema.sql.generated +++ b/db/src/main/resources/sql/schema/db-schema.sql.generated @@ -83,8 +83,8 @@ create table "ClaimsEntry" ( revision_id int8 not null, - claim_key text not null, domain_label text not null, + claim_key text not null, primary key (revision_id, domain_label) ); @@ -650,9 +650,9 @@ create table "ReservedEntry" ( revision_id int8 not null, - reservation_type int4 not null, - comment text, domain_label text not null, + comment text, + reservation_type int4 not null, primary key (revision_id, domain_label) ); @@ -822,11 +822,6 @@ create index spec11threatmatch_registrar_id_idx on "Spec11ThreatMatch" (registra create index spec11threatmatch_tld_idx on "Spec11ThreatMatch" (tld); create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date); - alter table if exists "ClaimsEntry" - add constraint FK6sc6at5hedffc0nhdcab6ivuq - foreign key (revision_id) - references "ClaimsList"; - alter table if exists "DelegationSignerData" add constraint FKtr24j9v14ph2mfuw2gsmt12kq foreign key (domain_repo_id) @@ -867,11 +862,6 @@ create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date foreign key (relock_revision_id) references "RegistryLock"; - alter table if exists "ReservedEntry" - add constraint FKgq03rk0bt1hb915dnyvd3vnfc - foreign key (revision_id) - references "ReservedList"; - alter table if exists "SignedMarkRevocationEntry" add constraint FK5ivlhvs3121yx2li5tqh54u4 foreign key (revision_id)