Use composite primary key for DomainHistory (#767)

* Use composite primary key for DomainHistory

* Move History table's SequenceGenerator to orm.xml

* Rebase on HEAD and remove default value for key in History tables

* Use primitive type for id.

* Revert the cache change
This commit is contained in:
Shicong Huang 2020-09-03 10:21:23 -04:00 committed by GitHub
parent b177532d58
commit b34da92f42
10 changed files with 219 additions and 78 deletions

View file

@ -19,8 +19,13 @@ import com.googlecode.objectify.annotation.EntitySubclass;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/** /**
* A persisted history entry representing an EPP modification to a contact. * A persisted history entry representing an EPP modification to a contact.
@ -38,6 +43,7 @@ import javax.persistence.Entity;
@javax.persistence.Index(columnList = "historyModificationTime") @javax.persistence.Index(columnList = "historyModificationTime")
}) })
@EntitySubclass @EntitySubclass
@Access(AccessType.FIELD)
public class ContactHistory extends HistoryEntry { public class ContactHistory extends HistoryEntry {
// Store ContactBase instead of ContactResource so we don't pick up its @Id // Store ContactBase instead of ContactResource so we don't pick up its @Id
ContactBase contactBase; ContactBase contactBase;
@ -45,6 +51,15 @@ public class ContactHistory extends HistoryEntry {
@Column(nullable = false) @Column(nullable = false)
VKey<ContactResource> contactRepoId; VKey<ContactResource> contactRepoId;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HistorySequenceGenerator")
@Column(name = "historyRevisionId")
@Access(AccessType.PROPERTY)
@Override
public long getId() {
return super.getId();
}
/** The state of the {@link ContactBase} object at this point in time. */ /** The state of the {@link ContactBase} object at this point in time. */
public ContactBase getContactBase() { public ContactBase getContactBase() {
return contactBase; return contactBase;

View file

@ -14,20 +14,32 @@
package google.registry.model.domain; package google.registry.model.domain;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import com.googlecode.objectify.Key; import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.EntitySubclass; import com.googlecode.objectify.annotation.EntitySubclass;
import com.googlecode.objectify.annotation.Ignore;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.contact.ContactResource; import google.registry.model.ImmutableObject;
import google.registry.model.domain.DomainHistory.DomainHistoryId;
import google.registry.model.host.HostResource; import google.registry.model.host.HostResource;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import java.io.Serializable;
import java.util.Set; import java.util.Set;
import javax.persistence.Access; import javax.persistence.Access;
import javax.persistence.AccessType; import javax.persistence.AccessType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.ElementCollection; import javax.persistence.ElementCollection;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Index;
import javax.persistence.JoinTable; import javax.persistence.JoinTable;
import javax.persistence.PostLoad;
import javax.persistence.Table;
/** /**
* A persisted history entry representing an EPP modification to a domain. * A persisted history entry representing an EPP modification to a domain.
@ -37,27 +49,43 @@ import javax.persistence.JoinTable;
* the foreign-keyed fields in that class can refer to this object. * the foreign-keyed fields in that class can refer to this object.
*/ */
@Entity @Entity
@javax.persistence.Table( @Table(
indexes = { indexes = {
@javax.persistence.Index(columnList = "creationTime"), @Index(columnList = "creationTime"),
@javax.persistence.Index(columnList = "historyRegistrarId"), @Index(columnList = "historyRegistrarId"),
@javax.persistence.Index(columnList = "historyType"), @Index(columnList = "historyType"),
@javax.persistence.Index(columnList = "historyModificationTime") @Index(columnList = "historyModificationTime")
}) })
@EntitySubclass @EntitySubclass
@Access(AccessType.FIELD)
@IdClass(DomainHistoryId.class)
public class DomainHistory extends HistoryEntry { public class DomainHistory extends HistoryEntry {
// Store DomainContent instead of DomainBase so we don't pick up its @Id // Store DomainContent instead of DomainBase so we don't pick up its @Id
DomainContent domainContent; DomainContent domainContent;
@Column(nullable = false) @Id String domainRepoId;
VKey<DomainBase> domainRepoId;
// We could have reused domainContent.nsHosts here, but Hibernate throws a weird exception after
// we change to use a composite primary key.
// TODO(b/166776754): Investigate if we can reuse domainContent.nsHosts for storing host keys.
@Ignore
@ElementCollection @ElementCollection
@JoinTable(name = "DomainHistoryHost") @JoinTable(name = "DomainHistoryHost")
@Access(AccessType.PROPERTY)
@Column(name = "host_repo_id") @Column(name = "host_repo_id")
Set<VKey<HostResource>> nsHosts;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HistorySequenceGenerator")
@Column(name = "historyRevisionId")
@Access(AccessType.PROPERTY)
@Override
public long getId() {
return super.getId();
}
/** Returns keys to the {@link HostResource} that are the nameservers for the domain. */
public Set<VKey<HostResource>> getNsHosts() { public Set<VKey<HostResource>> getNsHosts() {
return domainContent.nsHosts; return nsHosts;
} }
/** The state of the {@link DomainContent} object at this point in time. */ /** The state of the {@link DomainContent} object at this point in time. */
@ -65,16 +93,51 @@ public class DomainHistory extends HistoryEntry {
return domainContent; return domainContent;
} }
/** The key to the {@link ContactResource} this is based off of. */ /** The key to the {@link DomainBase} this is based off of. */
public VKey<DomainBase> getDomainRepoId() { public VKey<DomainBase> getDomainRepoId() {
return domainRepoId; return VKey.create(DomainBase.class, domainRepoId, Key.create(DomainBase.class, domainRepoId));
} }
// Hibernate needs this in order to populate nsHosts but no one else should ever use it public VKey<DomainHistory> createVKey() {
@SuppressWarnings("UnusedMethod") return VKey.createSql(DomainHistory.class, new DomainHistoryId(domainRepoId, getId()));
private void setNsHosts(Set<VKey<HostResource>> nsHosts) { }
@PostLoad
void postLoad() {
if (domainContent != null) { if (domainContent != null) {
domainContent.nsHosts = nsHosts; domainContent.nsHosts = nullToEmptyImmutableCopy(nsHosts);
}
}
/** Class to represent the composite primary key of {@link DomainHistory} entity. */
static class DomainHistoryId extends ImmutableObject implements Serializable {
private String domainRepoId;
private Long id;
/** Hibernate requires this default constructor. */
private DomainHistoryId() {}
DomainHistoryId(String domainRepoId, long id) {
this.domainRepoId = domainRepoId;
this.id = id;
}
String getDomainRepoId() {
return domainRepoId;
}
void setDomainRepoId(String domainRepoId) {
this.domainRepoId = domainRepoId;
}
long getId() {
return id;
}
void setId(long id) {
this.id = id;
} }
} }
@ -93,12 +156,15 @@ public class DomainHistory extends HistoryEntry {
public Builder setDomainContent(DomainContent domainContent) { public Builder setDomainContent(DomainContent domainContent) {
getInstance().domainContent = domainContent; getInstance().domainContent = domainContent;
if (domainContent != null) {
getInstance().nsHosts = nullToEmptyImmutableCopy(domainContent.nsHosts);
}
return this; return this;
} }
public Builder setDomainRepoId(VKey<DomainBase> domainRepoId) { public Builder setDomainRepoId(String domainRepoId) {
getInstance().domainRepoId = domainRepoId; getInstance().domainRepoId = domainRepoId;
domainRepoId.maybeGetOfyKey().ifPresent(parent -> getInstance().parent = parent); getInstance().parent = Key.create(DomainBase.class, domainRepoId);
return this; return this;
} }
@ -106,8 +172,7 @@ public class DomainHistory extends HistoryEntry {
@Override @Override
public Builder setParent(Key<? extends EppResource> parent) { public Builder setParent(Key<? extends EppResource> parent) {
super.setParent(parent); super.setParent(parent);
getInstance().domainRepoId = getInstance().domainRepoId = parent.getName();
VKey.create(DomainBase.class, parent.getName(), (Key<DomainBase>) parent);
return this; return this;
} }
} }

View file

@ -19,8 +19,13 @@ import com.googlecode.objectify.annotation.EntitySubclass;
import google.registry.model.EppResource; import google.registry.model.EppResource;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey; import google.registry.persistence.VKey;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
/** /**
* A persisted history entry representing an EPP modification to a host. * A persisted history entry representing an EPP modification to a host.
@ -39,6 +44,7 @@ import javax.persistence.Entity;
@javax.persistence.Index(columnList = "historyModificationTime") @javax.persistence.Index(columnList = "historyModificationTime")
}) })
@EntitySubclass @EntitySubclass
@Access(AccessType.FIELD)
public class HostHistory extends HistoryEntry { public class HostHistory extends HistoryEntry {
// Store HostBase instead of HostResource so we don't pick up its @Id // Store HostBase instead of HostResource so we don't pick up its @Id
@ -47,6 +53,15 @@ public class HostHistory extends HistoryEntry {
@Column(nullable = false) @Column(nullable = false)
VKey<HostResource> hostRepoId; VKey<HostResource> hostRepoId;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HistorySequenceGenerator")
@Column(name = "historyRevisionId")
@Access(AccessType.PROPERTY)
@Override
public long getId() {
return super.getId();
}
/** The state of the {@link HostBase} object at this point in time. */ /** The state of the {@link HostBase} object at this point in time. */
public HostBase getHostBase() { public HostBase getHostBase() {
return hostBase; return hostBase;

View file

@ -42,15 +42,14 @@ import google.registry.persistence.VKey;
import google.registry.persistence.WithStringVKey; import google.registry.persistence.WithStringVKey;
import java.util.Set; import java.util.Set;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.AttributeOverride; import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides; import javax.persistence.AttributeOverrides;
import javax.persistence.Column; import javax.persistence.Column;
import javax.persistence.EnumType; import javax.persistence.EnumType;
import javax.persistence.Enumerated; import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.MappedSuperclass; import javax.persistence.MappedSuperclass;
import javax.persistence.SequenceGenerator;
import javax.persistence.Transient; import javax.persistence.Transient;
import org.joda.time.DateTime; import org.joda.time.DateTime;
@ -59,6 +58,7 @@ import org.joda.time.DateTime;
@Entity @Entity
@MappedSuperclass @MappedSuperclass
@WithStringVKey // TODO(b/162229294): This should be resolved during the course of that bug @WithStringVKey // TODO(b/162229294): This should be resolved during the course of that bug
@Access(AccessType.FIELD)
public class HistoryEntry extends ImmutableObject implements Buildable { public class HistoryEntry extends ImmutableObject implements Buildable {
/** Represents the type of history entry. */ /** Represents the type of history entry. */
@ -110,17 +110,13 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
SYNTHETIC SYNTHETIC
} }
/** The autogenerated id of this event. */ /**
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HistorySequenceGenerator") * The autogenerated id of this event. Note that, this field is marked as {@link Transient} in the
@SequenceGenerator( * SQL schema, this is because the child class of {@link HistoryEntry}, e.g. {@link
name = "HistorySequenceGenerator", * DomainHistory}, uses a composite primary key which the id is part of, and Hibernate requires
sequenceName = "history_id_sequence", * that all the {@link javax.persistence.Id} fields must be put in the exact same class.
allocationSize = 1) */
@Id @Id @Transient @VisibleForTesting public Long id;
@javax.persistence.Id
@Column(name = "historyRevisionId")
@VisibleForTesting
public Long id;
/** The resource this event mutated. */ /** The resource this event mutated. */
@Parent @Transient protected Key<? extends EppResource> parent; @Parent @Transient protected Key<? extends EppResource> parent;
@ -196,8 +192,17 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
@Transient // domain-specific @Transient // domain-specific
Set<DomainTransactionRecord> domainTransactionRecords; Set<DomainTransactionRecord> domainTransactionRecords;
public Long getId() { public long getId() {
return id; // For some reason, Hibernate throws NPE during some initialization phase if we don't deal with
// the null case. Setting the id to 0L when it is null should be fine because 0L for primitive
// type is considered as null for wrapper class in the Hibernate context.
return id == null ? 0L : id;
}
// This method is required by Hibernate.
@SuppressWarnings("UnusedMethod")
private void setId(long id) {
this.id = id;
} }
public Key<? extends EppResource> getParent() { public Key<? extends EppResource> getParent() {
@ -279,11 +284,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
// can't use a switch statement since we're calling getKind() // can't use a switch statement since we're calling getKind()
if (parentKind.equals(getKind(DomainBase.class))) { if (parentKind.equals(getKind(DomainBase.class))) {
resultEntity = resultEntity =
new DomainHistory.Builder() new DomainHistory.Builder().copyFrom(this).setDomainRepoId(parent.getName()).build();
.copyFrom(this)
.setDomainRepoId(
VKey.create(DomainBase.class, parent.getName(), (Key<DomainBase>) parent))
.build();
} else if (parentKind.equals(getKind(HostResource.class))) { } else if (parentKind.equals(getKind(HostResource.class))) {
resultEntity = resultEntity =
new HostHistory.Builder() new HostHistory.Builder()
@ -349,6 +350,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
return thisCastToDerived(); return thisCastToDerived();
} }
// Until we move completely to SQL, override this in subclasses (e.g. HostHistory) to set VKeys
public B setParent(Key<? extends EppResource> parent) { public B setParent(Key<? extends EppResource> parent) {
getInstance().parent = parent; getInstance().parent = parent;
return thisCastToDerived(); return thisCastToDerived();

View file

@ -10,6 +10,9 @@
<basic name="amount" access="FIELD"/> <basic name="amount" access="FIELD"/>
</attributes> </attributes>
</embeddable> </embeddable>
<sequence-generator name="HistorySequenceGenerator" sequence-name="history_id_sequence" />
<persistence-unit-metadata> <persistence-unit-metadata>
<persistence-unit-defaults> <persistence-unit-defaults>
<entity-listeners> <entity-listeners>

View file

@ -14,6 +14,7 @@
package google.registry.model.history; package google.registry.model.history;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
@ -71,11 +72,15 @@ public class DomainHistoryTest extends EntityTestCase {
jpaTm() jpaTm()
.transact( .transact(
() -> { () -> {
DomainHistory fromDatabase = DomainHistory fromDatabase = jpaTm().load(domainHistory.createVKey());
jpaTm().load(VKey.createSql(DomainHistory.class, domainHistory.getId()));
assertDomainHistoriesEqual(fromDatabase, domainHistory); assertDomainHistoriesEqual(fromDatabase, domainHistory);
assertThat(fromDatabase.getDomainRepoId().getSqlKey()) assertThat(fromDatabase.getDomainRepoId().getSqlKey())
.isEqualTo(domainHistory.getDomainRepoId().getSqlKey()); .isEqualTo(domainHistory.getDomainRepoId().getSqlKey());
assertThat(fromDatabase.getNsHosts())
.containsExactlyElementsIn(
domainHistory.getNsHosts().stream()
.map(key -> VKey.createSql(HostResource.class, key.getSqlKey()))
.collect(toImmutableSet()));
}); });
} }
@ -120,7 +125,7 @@ public class DomainHistoryTest extends EntityTestCase {
static void assertDomainHistoriesEqual(DomainHistory one, DomainHistory two) { static void assertDomainHistoriesEqual(DomainHistory one, DomainHistory two) {
assertAboutImmutableObjects() assertAboutImmutableObjects()
.that(one) .that(one)
.isEqualExceptFields(two, "domainContent", "domainRepoId", "parent"); .isEqualExceptFields(two, "domainContent", "domainRepoId", "parent", "nsHosts");
} }
private DomainHistory createDomainHistory(DomainContent domain) { private DomainHistory createDomainHistory(DomainContent domain) {
@ -134,7 +139,7 @@ public class DomainHistoryTest extends EntityTestCase {
.setReason("reason") .setReason("reason")
.setRequestedByRegistrar(true) .setRequestedByRegistrar(true)
.setDomainContent(domain) .setDomainContent(domain)
.setDomainRepoId(domain.createVKey()) .setDomainRepoId(domain.getRepoId())
.build(); .build();
} }
} }

View file

@ -270,9 +270,9 @@ class google.registry.model.domain.DomainHistory {
google.registry.model.domain.Period period; google.registry.model.domain.Period period;
google.registry.model.eppcommon.Trid trid; google.registry.model.eppcommon.Trid trid;
google.registry.model.reporting.HistoryEntry$Type type; google.registry.model.reporting.HistoryEntry$Type type;
google.registry.persistence.VKey<google.registry.model.domain.DomainBase> domainRepoId;
java.lang.Boolean requestedByRegistrar; java.lang.Boolean requestedByRegistrar;
java.lang.String clientId; java.lang.String clientId;
java.lang.String domainRepoId;
java.lang.String otherClientId; java.lang.String otherClientId;
java.lang.String reason; java.lang.String reason;
java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords; java.util.Set<google.registry.model.reporting.DomainTransactionRecord> domainTransactionRecords;

View file

@ -0,0 +1,34 @@
-- 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.
alter sequence "history_id_sequence" increment 50;
alter table "DomainHistory" alter column history_revision_id drop default;
alter table "ContactHistory" alter column history_revision_id drop default;
alter table "HostHistory" alter column history_revision_id drop default;
alter table if exists "DomainHistoryHost"
drop constraint fk6b8eqdxwe3guc56tgpm89atx;
alter table "DomainHistory" drop constraint "DomainHistory_pkey";
alter table "DomainHistory"
add constraint "DomainHistory_pkey" primary key (domain_repo_id, history_revision_id);
alter table "DomainHistoryHost" add column domain_history_domain_repo_id text not null;
alter table if exists "DomainHistoryHost"
add constraint FKa9woh3hu8gx5x0vly6bai327n
foreign key (domain_history_domain_repo_id, domain_history_history_revision_id)
references "DomainHistory";

View file

@ -11,7 +11,7 @@
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and -- See the License for the specific language governing permissions and
-- limitations under the License. -- limitations under the License.
create sequence history_id_sequence start 1 increment 1; create sequence history_id_sequence start 1 increment 50;
create table "AllocationToken" ( create table "AllocationToken" (
token text not null, token text not null,
@ -286,7 +286,8 @@ create sequence history_id_sequence start 1 increment 1;
); );
create table "DomainHistory" ( create table "DomainHistory" (
history_revision_id int8 not null, domain_repo_id text not null,
history_revision_id int8 not null,
history_by_superuser boolean not null, history_by_superuser boolean not null,
history_registrar_id text, history_registrar_id text,
history_modification_time timestamptz not null, history_modification_time timestamptz not null,
@ -341,12 +342,12 @@ create sequence history_id_sequence start 1 increment 1;
last_epp_update_time timestamptz, last_epp_update_time timestamptz,
statuses text[], statuses text[],
update_timestamp timestamptz, update_timestamp timestamptz,
domain_repo_id text not null, primary key (domain_repo_id, history_revision_id)
primary key (history_revision_id)
); );
create table "DomainHistoryHost" ( create table "DomainHistoryHost" (
domain_history_history_revision_id int8 not null, domain_history_domain_repo_id text not null,
domain_history_history_revision_id int8 not null,
host_repo_id text host_repo_id text
); );
@ -644,8 +645,8 @@ create index spec11threatmatch_check_date_idx on "Spec11ThreatMatch" (check_date
references "ClaimsList"; references "ClaimsList";
alter table if exists "DomainHistoryHost" alter table if exists "DomainHistoryHost"
add constraint FK378h8v3j8qd8xtjn2e0bcmrtj add constraint FKa9woh3hu8gx5x0vly6bai327n
foreign key (domain_history_history_revision_id) foreign key (domain_history_domain_repo_id, domain_history_history_revision_id)
references "DomainHistory"; references "DomainHistory";
alter table if exists "DomainHost" alter table if exists "DomainHost"

View file

@ -275,24 +275,12 @@ CREATE TABLE public."Contact" (
); );
--
-- Name: history_id_sequence; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.history_id_sequence
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
-- --
-- Name: ContactHistory; Type: TABLE; Schema: public; Owner: - -- Name: ContactHistory; Type: TABLE; Schema: public; Owner: -
-- --
CREATE TABLE public."ContactHistory" ( CREATE TABLE public."ContactHistory" (
history_revision_id bigint DEFAULT nextval('public.history_id_sequence'::regclass) NOT NULL, history_revision_id bigint NOT NULL,
history_by_superuser boolean NOT NULL, history_by_superuser boolean NOT NULL,
history_registrar_id text, history_registrar_id text,
history_modification_time timestamp with time zone NOT NULL, history_modification_time timestamp with time zone NOT NULL,
@ -431,7 +419,7 @@ CREATE TABLE public."Domain" (
-- --
CREATE TABLE public."DomainHistory" ( CREATE TABLE public."DomainHistory" (
history_revision_id bigint DEFAULT nextval('public.history_id_sequence'::regclass) NOT NULL, history_revision_id bigint NOT NULL,
history_by_superuser boolean NOT NULL, history_by_superuser boolean NOT NULL,
history_registrar_id text, history_registrar_id text,
history_modification_time timestamp with time zone NOT NULL, history_modification_time timestamp with time zone NOT NULL,
@ -496,7 +484,8 @@ CREATE TABLE public."DomainHistory" (
CREATE TABLE public."DomainHistoryHost" ( CREATE TABLE public."DomainHistoryHost" (
domain_history_history_revision_id bigint NOT NULL, domain_history_history_revision_id bigint NOT NULL,
host_repo_id text host_repo_id text,
domain_history_domain_repo_id text NOT NULL
); );
@ -549,7 +538,7 @@ ALTER SEQUENCE public."GracePeriod_id_seq" OWNED BY public."GracePeriod".id;
-- --
CREATE TABLE public."HostHistory" ( CREATE TABLE public."HostHistory" (
history_revision_id bigint DEFAULT nextval('public.history_id_sequence'::regclass) NOT NULL, history_revision_id bigint NOT NULL,
history_by_superuser boolean NOT NULL, history_by_superuser boolean NOT NULL,
history_registrar_id text NOT NULL, history_registrar_id text NOT NULL,
history_modification_time timestamp with time zone NOT NULL, history_modification_time timestamp with time zone NOT NULL,
@ -929,6 +918,18 @@ CREATE SEQUENCE public."Transaction_id_seq"
ALTER SEQUENCE public."Transaction_id_seq" OWNED BY public."Transaction".id; ALTER SEQUENCE public."Transaction_id_seq" OWNED BY public."Transaction".id;
--
-- Name: history_id_sequence; Type: SEQUENCE; Schema: public; Owner: -
--
CREATE SEQUENCE public.history_id_sequence
START WITH 1
INCREMENT BY 50
NO MINVALUE
NO MAXVALUE
CACHE 1;
-- --
-- Name: BillingCancellation billing_cancellation_id; Type: DEFAULT; Schema: public; Owner: - -- Name: BillingCancellation billing_cancellation_id; Type: DEFAULT; Schema: public; Owner: -
-- --
@ -1083,7 +1084,7 @@ ALTER TABLE ONLY public."Cursor"
-- --
ALTER TABLE ONLY public."DomainHistory" ALTER TABLE ONLY public."DomainHistory"
ADD CONSTRAINT "DomainHistory_pkey" PRIMARY KEY (history_revision_id); ADD CONSTRAINT "DomainHistory_pkey" PRIMARY KEY (domain_repo_id, history_revision_id);
-- --
@ -1612,14 +1613,6 @@ ALTER TABLE ONLY public."HostHistory"
ADD CONSTRAINT fk3d09knnmxrt6iniwnp8j2ykga FOREIGN KEY (history_registrar_id) REFERENCES public."Registrar"(registrar_id); ADD CONSTRAINT fk3d09knnmxrt6iniwnp8j2ykga FOREIGN KEY (history_registrar_id) REFERENCES public."Registrar"(registrar_id);
--
-- Name: DomainHistoryHost fk6b8eqdxwe3guc56tgpm89atx; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."DomainHistoryHost"
ADD CONSTRAINT fk6b8eqdxwe3guc56tgpm89atx FOREIGN KEY (domain_history_history_revision_id) REFERENCES public."DomainHistory"(history_revision_id);
-- --
-- Name: ClaimsEntry fk6sc6at5hedffc0nhdcab6ivuq; Type: FK CONSTRAINT; Schema: public; Owner: - -- Name: ClaimsEntry fk6sc6at5hedffc0nhdcab6ivuq; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --
@ -1916,6 +1909,14 @@ ALTER TABLE ONLY public."PollMessage"
ADD CONSTRAINT fk_poll_message_transfer_response_losing_registrar_id FOREIGN KEY (transfer_response_losing_registrar_id) REFERENCES public."Registrar"(registrar_id); ADD CONSTRAINT fk_poll_message_transfer_response_losing_registrar_id FOREIGN KEY (transfer_response_losing_registrar_id) REFERENCES public."Registrar"(registrar_id);
--
-- Name: DomainHistoryHost fka9woh3hu8gx5x0vly6bai327n; Type: FK CONSTRAINT; Schema: public; Owner: -
--
ALTER TABLE ONLY public."DomainHistoryHost"
ADD CONSTRAINT fka9woh3hu8gx5x0vly6bai327n FOREIGN KEY (domain_history_domain_repo_id, domain_history_history_revision_id) REFERENCES public."DomainHistory"(domain_repo_id, history_revision_id);
-- --
-- Name: DomainHost fkfmi7bdink53swivs390m2btxg; Type: FK CONSTRAINT; Schema: public; Owner: - -- Name: DomainHost fkfmi7bdink53swivs390m2btxg; Type: FK CONSTRAINT; Schema: public; Owner: -
-- --