Get persistence of DomainBase actually working (#438)

* Get persistence of DomainBase actually working

Fix all of the existing problems with DomainBase persistence:
- Remove "final" keywords on getters that cause errors during startup.
- Remove Transient from creationTime (since there's a converter for
  CreateAutoTimestamp)
- Fix DesignatedContext persistence so that it only creates a single table.
  This is a lot more efficient given that these are many-to-one with their
  domains.
- Add a flyway script, update the golden schema.
- Create a unit test, add it to the integration test suite.

* Changes request in review

* Regenerated generated schema file.

* Changes for review

* Persist status value enum set

* Changes in response to review

* Changes requested in review

* Fixes for #456

* Rename Domain "status" column to "statuses"
This commit is contained in:
Michael Muller 2020-01-28 11:32:26 -05:00 committed by GitHub
parent 1912453f4e
commit e386bf5bd8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 295 additions and 159 deletions

View file

@ -50,8 +50,10 @@ import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import org.hibernate.annotations.Type;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@ -87,7 +89,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
// Map the method to XML, not the field, because if we map the field (with an adaptor class) it
// will never be omitted from the xml even if the timestamp inside creationTime is null and we
// return null from the adaptor. (Instead it gets written as an empty tag.)
@Index @Transient CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
@Index CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
/**
* The time when this resource was or will be deleted.
@ -105,7 +107,6 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
@Index
DateTime deletionTime;
/**
* The time that this resource was last updated.
*
@ -116,7 +117,10 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
DateTime lastEppUpdateTime;
/** Status values associated with this resource. */
@Transient Set<StatusValue> status;
@Type(type = "google.registry.model.eppcommon.StatusValue$StatusValueSetType")
@Column(name = "statuses")
// TODO(mmuller): rename to "statuses" once we're off datastore.
Set<StatusValue> status;
/**
* Sorted map of {@link DateTime} keys (modified time) to {@link CommitLogManifest} entries.
@ -126,6 +130,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
*
* @see google.registry.model.translators.CommitLogRevisionsTranslatorFactory
*/
@Transient
ImmutableSortedMap<DateTime, Key<CommitLogManifest>> revisions = ImmutableSortedMap.of();
public final String getRepoId() {
@ -136,15 +141,15 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
return creationTime.getTimestamp();
}
public final String getCreationClientId() {
public String getCreationClientId() {
return creationClientId;
}
public final DateTime getLastEppUpdateTime() {
public DateTime getLastEppUpdateTime() {
return lastEppUpdateTime;
}
public final String getLastEppUpdateClientId() {
public String getLastEppUpdateClientId() {
return lastEppUpdateClientId;
}
@ -162,7 +167,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
return nullToEmptyImmutableCopy(status);
}
public final DateTime getDeletionTime() {
public DateTime getDeletionTime() {
return deletionTime;
}

View file

@ -21,7 +21,7 @@ import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Index;
import google.registry.model.ImmutableObject;
import google.registry.model.contact.ContactResource;
import javax.persistence.Id;
import javax.persistence.Embeddable;
import javax.xml.bind.annotation.XmlEnumValue;
/**
@ -40,7 +40,7 @@ import javax.xml.bind.annotation.XmlEnumValue;
* - Contact and Client Identifiers</a>
*/
@Embed
@javax.persistence.Entity
@Embeddable
public class DesignatedContact extends ImmutableObject {
/**
@ -67,7 +67,7 @@ public class DesignatedContact extends ImmutableObject {
Type type;
@Index @Id Key<ContactResource> contact;
@Index Key<ContactResource> contact;
public Type getType() {
return type;

View file

@ -75,6 +75,7 @@ import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Transient;
import org.joda.time.DateTime;
import org.joda.time.Interval;
@ -89,8 +90,16 @@ import org.joda.time.Interval;
*/
@ReportedOn
@Entity
@javax.persistence.Entity
@javax.persistence.Table(name = "Domain")
@javax.persistence.Entity(name = "Domain")
@javax.persistence.Table(
name = "Domain",
indexes = {
@javax.persistence.Index(columnList = "creationTime"),
@javax.persistence.Index(columnList = "currentSponsorClientId"),
@javax.persistence.Index(columnList = "deletionTime"),
@javax.persistence.Index(columnList = "fullyQualifiedDomainName"),
@javax.persistence.Index(columnList = "tld")
})
@ExternalMessagingName("domain")
public class DomainBase extends EppResource
implements ForeignKeyedEppResource, ResourceWithTransferData {
@ -115,22 +124,21 @@ public class DomainBase extends EppResource
*
* @invariant fullyQualifiedDomainName == fullyQualifiedDomainName.toLowerCase(Locale.ENGLISH)
*/
@Index
String fullyQualifiedDomainName;
@Index String fullyQualifiedDomainName;
/** The top level domain this is under, dernormalized from {@link #fullyQualifiedDomainName}. */
@Index
String tld;
/** References to hosts that are the nameservers for the domain. */
@Index @ElementCollection Set<Key<HostResource>> nsHosts;
@Index @ElementCollection @Transient Set<Key<HostResource>> nsHosts;
/**
* The union of the contacts visible via {@link #getContacts} and {@link #getRegistrant}.
*
* <p>These are stored in one field so that we can query across all contacts at once.
*/
@ElementCollection Set<DesignatedContact> allContacts;
@Transient Set<DesignatedContact> allContacts;
/** Authorization info (aka transfer secret) of the domain. */
@Embedded
@ -146,7 +154,7 @@ public class DomainBase extends EppResource
* <p>This is {@literal @}XmlTransient because it needs to be returned under the "extension" tag
* of an info response rather than inside the "infData" tag.
*/
@ElementCollection Set<DelegationSignerData> dsData;
@Transient Set<DelegationSignerData> dsData;
/**
* The claims notice supplied when this application or domain was created, if there was one. It's
@ -177,7 +185,8 @@ public class DomainBase extends EppResource
String idnTableName;
/** Fully qualified host names of this domain's active subordinate hosts. */
@ElementCollection Set<String> subordinateHosts;
@org.hibernate.annotations.Type(type = "google.registry.persistence.StringSetUserType")
Set<String> subordinateHosts;
/** When this domain's registration will expire. */
DateTime registrationExpirationTime;
@ -189,7 +198,7 @@ public class DomainBase extends EppResource
* refer to a {@link PollMessage} timed to when the domain is fully deleted. If the domain is
* restored, the message should be deleted.
*/
Key<PollMessage.OneTime> deletePollMessage;
@Transient Key<PollMessage.OneTime> deletePollMessage;
/**
* The recurring billing event associated with this domain's autorenewals.
@ -199,7 +208,7 @@ public class DomainBase extends EppResource
* {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one
* should be created, and this field should be updated to point to the new one.
*/
Key<BillingEvent.Recurring> autorenewBillingEvent;
@Transient Key<BillingEvent.Recurring> autorenewBillingEvent;
/**
* The recurring poll message associated with this domain's autorenewals.
@ -209,10 +218,10 @@ public class DomainBase extends EppResource
* {@link #registrationExpirationTime} is changed the recurrence should be closed, a new one
* should be created, and this field should be updated to point to the new one.
*/
Key<PollMessage.Autorenew> autorenewPollMessage;
@Transient Key<PollMessage.Autorenew> autorenewPollMessage;
/** The unexpired grace periods for this domain (some of which may not be active yet). */
@ElementCollection Set<GracePeriod> gracePeriods;
@Transient @ElementCollection Set<GracePeriod> gracePeriods;
/**
* The id of the signed mark that was used to create this domain in sunrise.
@ -223,31 +232,7 @@ public class DomainBase extends EppResource
String smdId;
/** Data about any pending or past transfers on this domain. */
@Embedded
@AttributeOverrides({
@AttributeOverride(
name = "transferRequestTrid",
column = @Column(name = "transfer_data_request_trid")),
@AttributeOverride(
name = "transferPeriod",
column = @Column(name = "transfer_data_transfer_period")),
@AttributeOverride(
name = "transferredRegistrationExpirationTime",
column = @Column(name = "transfer_data_registration_expiration_time")),
@AttributeOverride(
name = "serverApproveEntities",
column = @Column(name = "transfer_data_server_approve_entities")),
@AttributeOverride(
name = "serverApproveBillingEvent",
column = @Column(name = "transfer_data_server_approve_billing_event")),
@AttributeOverride(
name = "serverApproveAutorenewEvent",
column = @Column(name = "transfer_data_server_approve_autorenrew_event")),
@AttributeOverride(
name = "serverApproveAutorenewPollMessage",
column = @Column(name = "transfer_data_server_approve_autorenrew_poll_message")),
})
TransferData transferData;
@Transient TransferData transferData;
/**
* The time that this resource was last transferred.
@ -285,7 +270,7 @@ public class DomainBase extends EppResource
}
@Override
public final TransferData getTransferData() {
public TransferData getTransferData() {
return Optional.ofNullable(transferData).orElse(TransferData.EMPTY);
}

View file

@ -25,6 +25,7 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.host.HostResource;
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
import google.registry.model.translators.StatusValueAdapter;
import google.registry.persistence.EnumSetUserType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
@ -164,4 +165,12 @@ public enum StatusValue implements EppEnum {
public static StatusValue fromXmlName(String xmlName) {
return StatusValue.valueOf(LOWER_CAMEL.to(UPPER_UNDERSCORE, nullToEmpty(xmlName)));
}
/** Hibernate type for sets of {@link StatusValue}. */
public static class StatusValueSetType extends EnumSetUserType<StatusValue> {
@Override
protected Object convertToElem(Object value) {
return StatusValue.valueOf((String) value);
}
}
}

View file

@ -0,0 +1,121 @@
// Copyright 2017 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.domain;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.EntityTestCase;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DesignatedContact.Type;
import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.domain.secdns.DelegationSignerData;
import google.registry.model.eppcommon.AuthInfo.PasswordAuth;
import google.registry.model.eppcommon.StatusValue;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageRule;
import javax.persistence.EntityManager;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Verify that we can store/retrieve DomainBase objects from a SQL database. */
@RunWith(JUnit4.class)
public class DomainBaseSqlTest extends EntityTestCase {
@Rule
public final JpaIntegrationWithCoverageRule jpaRule =
new JpaTestRules.Builder().buildIntegrationWithCoverageRule();
DomainBase domain;
Key<ContactResource> contactKey;
Key<ContactResource> contact2Key;
@Before
public void setUp() {
contactKey = Key.create(ContactResource.class, "contact_id1");
contact2Key = Key.create(ContactResource.class, "contact_id2");
domain =
new DomainBase.Builder()
.setFullyQualifiedDomainName("example.com")
.setRepoId("4-COM")
.setCreationClientId("a registrar")
.setLastEppUpdateTime(clock.nowUtc())
.setLastEppUpdateClientId("AnotherRegistrar")
.setLastTransferTime(clock.nowUtc())
.setStatusValues(
ImmutableSet.of(
StatusValue.CLIENT_DELETE_PROHIBITED,
StatusValue.SERVER_DELETE_PROHIBITED,
StatusValue.SERVER_TRANSFER_PROHIBITED,
StatusValue.SERVER_UPDATE_PROHIBITED,
StatusValue.SERVER_RENEW_PROHIBITED,
StatusValue.SERVER_HOLD))
.setRegistrant(contactKey)
.setContacts(ImmutableSet.of(DesignatedContact.create(Type.ADMIN, contact2Key)))
.setSubordinateHosts(ImmutableSet.of("ns1.example.com"))
.setPersistedCurrentSponsorClientId("losing")
.setRegistrationExpirationTime(clock.nowUtc().plusYears(1))
.setAuthInfo(DomainAuthInfo.create(PasswordAuth.create("password")))
.setDsData(ImmutableSet.of(DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
.setLaunchNotice(
LaunchNotice.create("tcnid", "validatorId", START_OF_TIME, START_OF_TIME))
.setSmdId("smdid")
.build();
}
@Test
public void testDomainBasePersistence() {
jpaTm()
.transact(
() -> {
// Persist the domain.
EntityManager em = jpaTm().getEntityManager();
em.persist(domain);
});
jpaTm()
.transact(
() -> {
// Load the domain in its entirety.
EntityManager em = jpaTm().getEntityManager();
DomainBase result = em.find(DomainBase.class, "4-COM");
// Fix contacts, grace period and DS data, since we can't persist them yet.
result =
result
.asBuilder()
.setRegistrant(contactKey)
.setContacts(
ImmutableSet.of(DesignatedContact.create(Type.ADMIN, contact2Key)))
.setDsData(
ImmutableSet.of(
DelegationSignerData.create(1, 2, 3, new byte[] {0, 1, 2})))
.build();
// Fix the original creation timestamp (this gets initialized on first write)
DomainBase org = domain.asBuilder().setCreationTime(result.getCreationTime()).build();
// Note that the equality comparison forces a lazy load of all fields.
assertThat(result).isEqualTo(org);
});
}
}

View file

@ -15,6 +15,7 @@
package google.registry.schema.integration;
import com.google.common.truth.Expect;
import google.registry.model.domain.DomainBaseSqlTest;
import google.registry.model.registry.RegistryLockDaoTest;
import google.registry.persistence.transaction.JpaEntityCoverage;
import google.registry.schema.cursor.CursorDaoTest;
@ -55,6 +56,7 @@ import org.junit.runners.Suite.SuiteClasses;
CursorDaoTest.class,
DomainLockUtilsTest.class,
LockDomainCommandTest.class,
DomainBaseSqlTest.class,
PremiumListDaoTest.class,
RegistryLockDaoTest.class,
RegistryLockGetActionTest.class,

View file

@ -0,0 +1,44 @@
-- Copyright 2020 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.
create table "Domain" (
repo_id text not null,
creation_client_id text,
creation_time timestamptz,
current_sponsor_client_id text,
deletion_time timestamptz,
last_epp_update_client_id text,
last_epp_update_time timestamptz,
statuses text[],
auth_info_repo_id text,
auth_info_value text,
fully_qualified_domain_name text,
idn_table_name text,
last_transfer_time timestamptz,
launch_notice_accepted_time timestamptz,
launch_notice_expiration_time timestamptz,
launch_notice_tcn_id text,
launch_notice_validator_id text,
registration_expiration_time timestamptz,
smd_id text,
subordinate_hosts text[],
tld text,
primary key (repo_id)
);
create index IDX8nr0ke9mrrx4ewj6pd2ag4rmr on "Domain" (creation_time);
create index IDX8ffrqm27qtj20jac056j7yq07 on "Domain" (current_sponsor_client_id);
create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
create index IDX1rcgkdd777bpvj0r94sltwd5y on "Domain" (fully_qualified_domain_name);
create index IDXrwl38wwkli1j7gkvtywi9jokq on "Domain" (tld);

View file

@ -42,25 +42,17 @@
primary key (key_tag)
);
create table "DesignatedContact" (
contact bytea not null,
type int4,
primary key (contact)
);
create table "Domain" (
repo_id text not null,
creation_client_id text,
creation_time timestamptz,
current_sponsor_client_id text,
deletion_time timestamptz,
last_epp_update_client_id text,
last_epp_update_time timestamptz,
revisions bytea,
statuses text[],
auth_info_repo_id text,
auth_info_value text,
autorenew_billing_event bytea,
autorenew_poll_message bytea,
delete_poll_message bytea,
fully_qualified_domain_name text,
idn_table_name text,
last_transfer_time timestamptz,
@ -70,56 +62,11 @@
launch_notice_validator_id text,
registration_expiration_time timestamptz,
smd_id text,
subordinate_hosts text[],
tld text,
transfer_data_server_approve_autorenrew_event bytea,
transfer_data_server_approve_autorenrew_poll_message bytea,
transfer_data_server_approve_billing_event bytea,
unit int4,
value int4,
client_transaction_id text,
server_transaction_id text,
transfer_data_registration_expiration_time timestamptz,
gaining_client_id text,
losing_client_id text,
pending_transfer_expiration_time timestamptz,
transfer_request_time timestamptz,
transfer_status int4,
primary key (repo_id)
);
create table "Domain_DelegationSignerData" (
domain_base_repo_id text not null,
ds_data_key_tag int4 not null,
primary key (domain_base_repo_id, ds_data_key_tag)
);
create table "Domain_DesignatedContact" (
domain_base_repo_id text not null,
all_contacts_contact bytea not null,
primary key (domain_base_repo_id, all_contacts_contact)
);
create table "Domain_GracePeriod" (
domain_base_repo_id text not null,
grace_periods_id int8 not null,
primary key (domain_base_repo_id, grace_periods_id)
);
create table "DomainBase_nsHosts" (
domain_base_repo_id text not null,
ns_hosts bytea
);
create table "DomainBase_serverApproveEntities" (
domain_base_repo_id text not null,
transfer_data_server_approve_entities bytea
);
create table "DomainBase_subordinateHosts" (
domain_base_repo_id text not null,
subordinate_hosts text
);
create table "GracePeriod" (
id bigserial not null,
billing_event_one_time bytea,
@ -177,15 +124,11 @@
should_publish boolean not null,
primary key (revision_id)
);
alter table if exists "Domain_DelegationSignerData"
add constraint UK_2yp55erx1i51pa7gnb8bu7tjn unique (ds_data_key_tag);
alter table if exists "Domain_DesignatedContact"
add constraint UK_4ys6wdxcmndimlr6af3tsl0ow unique (all_contacts_contact);
alter table if exists "Domain_GracePeriod"
add constraint UK_4ps2u4y8i5r91wu2n1x2xea28 unique (grace_periods_id);
create index IDX8nr0ke9mrrx4ewj6pd2ag4rmr on "Domain" (creation_time);
create index IDX8ffrqm27qtj20jac056j7yq07 on "Domain" (current_sponsor_client_id);
create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
create index IDX1rcgkdd777bpvj0r94sltwd5y on "Domain" (fully_qualified_domain_name);
create index IDXrwl38wwkli1j7gkvtywi9jokq on "Domain" (tld);
create index premiumlist_name_idx on "PremiumList" (name);
create index idx_registry_lock_verification_code on "RegistryLock" (verification_code);
create index idx_registry_lock_registrar_id on "RegistryLock" (registrar_id);
@ -199,51 +142,6 @@ create index reservedlist_name_idx on "ReservedList" (name);
foreign key (revision_id)
references "ClaimsList";
alter table if exists "Domain_DelegationSignerData"
add constraint FKho8wxowo3f4e688ehdl4wpni5
foreign key (ds_data_key_tag)
references "DelegationSignerData";
alter table if exists "Domain_DelegationSignerData"
add constraint FK2nvqbovvy5wasa8arhyhy8mge
foreign key (domain_base_repo_id)
references "Domain";
alter table if exists "Domain_DesignatedContact"
add constraint FKqnnsrj0vi9eqhoth305cd4bi7
foreign key (all_contacts_contact)
references "DesignatedContact";
alter table if exists "Domain_DesignatedContact"
add constraint FK169lte99hlt3otom9di13ubfn
foreign key (domain_base_repo_id)
references "Domain";
alter table if exists "Domain_GracePeriod"
add constraint FKny62h7k1nd3910rp56gdo5pfi
foreign key (grace_periods_id)
references "GracePeriod";
alter table if exists "Domain_GracePeriod"
add constraint FKkpor7amcdp7gwe0hp3obng6do
foreign key (domain_base_repo_id)
references "Domain";
alter table if exists "DomainBase_nsHosts"
add constraint FKow28763fcl1ilx8unxrfjtbja
foreign key (domain_base_repo_id)
references "Domain";
alter table if exists "DomainBase_serverApproveEntities"
add constraint FK7vuyqcsmcfvpv5648femoxien
foreign key (domain_base_repo_id)
references "Domain";
alter table if exists "DomainBase_subordinateHosts"
add constraint FKkva2lb57ri8qf39hthcej538k
foreign key (domain_base_repo_id)
references "Domain";
alter table if exists "PremiumEntry"
add constraint FKo0gw90lpo1tuee56l0nb6y6g5
foreign key (revision_id)

View file

@ -87,6 +87,35 @@ CREATE TABLE public."Cursor" (
);
--
-- Name: Domain; Type: TABLE; Schema: public; Owner: -
--
CREATE TABLE public."Domain" (
repo_id text NOT NULL,
creation_client_id text,
creation_time timestamp with time zone,
current_sponsor_client_id text,
deletion_time timestamp with time zone,
last_epp_update_client_id text,
last_epp_update_time timestamp with time zone,
statuses text[],
auth_info_repo_id text,
auth_info_value text,
fully_qualified_domain_name text,
idn_table_name text,
last_transfer_time timestamp with time zone,
launch_notice_accepted_time timestamp with time zone,
launch_notice_expiration_time timestamp with time zone,
launch_notice_tcn_id text,
launch_notice_validator_id text,
registration_expiration_time timestamp with time zone,
smd_id text,
subordinate_hosts text[],
tld text
);
--
-- Name: PremiumEntry; Type: TABLE; Schema: public; Owner: -
--
@ -264,6 +293,14 @@ ALTER TABLE ONLY public."Cursor"
ADD CONSTRAINT "Cursor_pkey" PRIMARY KEY (scope, type);
--
-- Name: Domain Domain_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."Domain"
ADD CONSTRAINT "Domain_pkey" PRIMARY KEY (repo_id);
--
-- Name: PremiumEntry PremiumEntry_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
@ -312,6 +349,34 @@ ALTER TABLE ONLY public."RegistryLock"
ADD CONSTRAINT idx_registry_lock_repo_id_revision_id UNIQUE (repo_id, revision_id);
--
-- Name: idx1rcgkdd777bpvj0r94sltwd5y; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX idx1rcgkdd777bpvj0r94sltwd5y ON public."Domain" USING btree (fully_qualified_domain_name);
--
-- Name: idx5mnf0wn20tno4b9do88j61klr; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX idx5mnf0wn20tno4b9do88j61klr ON public."Domain" USING btree (deletion_time);
--
-- Name: idx8ffrqm27qtj20jac056j7yq07; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX idx8ffrqm27qtj20jac056j7yq07 ON public."Domain" USING btree (current_sponsor_client_id);
--
-- Name: idx8nr0ke9mrrx4ewj6pd2ag4rmr; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX idx8nr0ke9mrrx4ewj6pd2ag4rmr ON public."Domain" USING btree (creation_time);
--
-- Name: idx_registry_lock_registrar_id; Type: INDEX; Schema: public; Owner: -
--
@ -326,6 +391,13 @@ CREATE INDEX idx_registry_lock_registrar_id ON public."RegistryLock" USING btree
CREATE INDEX idx_registry_lock_verification_code ON public."RegistryLock" USING btree (verification_code);
--
-- Name: idxrwl38wwkli1j7gkvtywi9jokq; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX idxrwl38wwkli1j7gkvtywi9jokq ON public."Domain" USING btree (tld);
--
-- Name: premiumlist_name_idx; Type: INDEX; Schema: public; Owner: -
--