mirror of
https://github.com/google/nomulus.git
synced 2025-05-22 04:09:46 +02:00
Add HostBase and HostHistory classes (#587)
* Add proof of concept for HostBase and HostHistory classes * Use a PROPERTY accessor for @Ids * Add an unused setter method for Hibernate's sake * Refactor HostHistory * Some responses to CR * Fix relationship and test * Manually manage the foreign keys for HostHistory * Protect HostBase's builder and use text for the enum type * Add responses to CR - Add javadocs - Create an ID sequence for host history objects * Don't try to set the ID * Use a Long and remove the setter * Add some comments and rename a couple fields * Don't change Datastore schema * Use Long in the Datastore schema * Add new createVKey method * Add comments and rename fields * Rename v27->v31 and regenerate the golden * Fix superordinateDomain and inetAddresses in HostHistory * V31 -> V32 * Fix SQL files that got messed up in the merge * Configure and use a manually-created history ID sequence * Add three more indices to HostHistory
This commit is contained in:
parent
56c9e81bcd
commit
58c557d715
15 changed files with 742 additions and 203 deletions
|
@ -48,6 +48,8 @@ import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.stream.StreamSupport;
|
import java.util.stream.StreamSupport;
|
||||||
|
import javax.persistence.Access;
|
||||||
|
import javax.persistence.AccessType;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.MappedSuperclass;
|
import javax.persistence.MappedSuperclass;
|
||||||
import javax.persistence.Transient;
|
import javax.persistence.Transient;
|
||||||
|
@ -56,15 +58,21 @@ import org.joda.time.Duration;
|
||||||
|
|
||||||
/** An EPP entity object (i.e. a domain, contact, or host). */
|
/** An EPP entity object (i.e. a domain, contact, or host). */
|
||||||
@MappedSuperclass
|
@MappedSuperclass
|
||||||
|
@Access(AccessType.FIELD) // otherwise it'll use the default if the repoId (property)
|
||||||
public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unique identifier in the registry for this resource.
|
* Unique identifier in the registry for this resource.
|
||||||
*
|
*
|
||||||
* <p>This is in the (\w|_){1,80}-\w{1,8} format specified by RFC 5730 for roidType.
|
* <p>This is in the (\w|_){1,80}-\w{1,8} format specified by RFC 5730 for roidType.
|
||||||
|
*
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc5730">RFC 5730</a>
|
* @see <a href="https://tools.ietf.org/html/rfc5730">RFC 5730</a>
|
||||||
*/
|
*/
|
||||||
@Id @javax.persistence.Id String repoId;
|
@Id
|
||||||
|
// not persisted so that we can store these in references to other objects. Subclasses that wish
|
||||||
|
// to use this as the primary key should create a getter method annotated with @Id
|
||||||
|
@Transient
|
||||||
|
String repoId;
|
||||||
|
|
||||||
/** The ID of the registrar that is currently sponsoring this resource. */
|
/** The ID of the registrar that is currently sponsoring this resource. */
|
||||||
@Index
|
@Index
|
||||||
|
@ -138,6 +146,12 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||||
return repoId;
|
return repoId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hibernate needs this to populate the repo ID, but no one else should ever use it
|
||||||
|
@SuppressWarnings("UnusedMethod")
|
||||||
|
private void setRepoId(String repoId) {
|
||||||
|
this.repoId = repoId;
|
||||||
|
}
|
||||||
|
|
||||||
public final DateTime getCreationTime() {
|
public final DateTime getCreationTime() {
|
||||||
return creationTime.getTimestamp();
|
return creationTime.getTimestamp();
|
||||||
}
|
}
|
||||||
|
@ -214,7 +228,7 @@ public abstract class EppResource extends BackupGroupRoot implements Buildable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Abstract builder for {@link EppResource} types. */
|
/** Abstract builder for {@link EppResource} types. */
|
||||||
public abstract static class Builder<T extends EppResource, B extends Builder<?, ?>>
|
public abstract static class Builder<T extends EppResource, B extends Builder<T, B>>
|
||||||
extends GenericBuilder<T, B> {
|
extends GenericBuilder<T, B> {
|
||||||
|
|
||||||
/** Create a {@link Builder} wrapping a new instance. */
|
/** Create a {@link Builder} wrapping a new instance. */
|
||||||
|
|
|
@ -37,6 +37,8 @@ import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
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;
|
||||||
|
@ -63,6 +65,7 @@ import org.joda.time.DateTime;
|
||||||
})
|
})
|
||||||
@ExternalMessagingName("contact")
|
@ExternalMessagingName("contact")
|
||||||
@WithStringVKey
|
@WithStringVKey
|
||||||
|
@Access(AccessType.FIELD)
|
||||||
public class ContactResource extends EppResource
|
public class ContactResource extends EppResource
|
||||||
implements DatastoreAndSqlEntity, ForeignKeyedEppResource, ResourceWithTransferData {
|
implements DatastoreAndSqlEntity, ForeignKeyedEppResource, ResourceWithTransferData {
|
||||||
|
|
||||||
|
@ -201,6 +204,13 @@ public class ContactResource extends EppResource
|
||||||
return VKey.createOfy(ContactResource.class, Key.create(this));
|
return VKey.createOfy(ContactResource.class, Key.create(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@javax.persistence.Id
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
|
public String getRepoId() {
|
||||||
|
return super.getRepoId();
|
||||||
|
}
|
||||||
|
|
||||||
public String getContactId() {
|
public String getContactId() {
|
||||||
return contactId;
|
return contactId;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,6 +75,8 @@ import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
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;
|
||||||
|
@ -109,6 +111,7 @@ import org.joda.time.Interval;
|
||||||
})
|
})
|
||||||
@WithStringVKey
|
@WithStringVKey
|
||||||
@ExternalMessagingName("domain")
|
@ExternalMessagingName("domain")
|
||||||
|
@Access(AccessType.FIELD)
|
||||||
public class DomainBase extends EppResource
|
public class DomainBase extends EppResource
|
||||||
implements DatastoreAndSqlEntity,
|
implements DatastoreAndSqlEntity,
|
||||||
ForeignKeyedEppResource,
|
ForeignKeyedEppResource,
|
||||||
|
@ -295,6 +298,13 @@ public class DomainBase extends EppResource
|
||||||
allContacts = contactsBuilder.build();
|
allContacts = contactsBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@javax.persistence.Id
|
||||||
|
@Access(AccessType.PROPERTY)
|
||||||
|
public String getRepoId() {
|
||||||
|
return super.getRepoId();
|
||||||
|
}
|
||||||
|
|
||||||
public ImmutableSet<String> getSubordinateHosts() {
|
public ImmutableSet<String> getSubordinateHosts() {
|
||||||
return nullToEmptyImmutableCopy(subordinateHosts);
|
return nullToEmptyImmutableCopy(subordinateHosts);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableSet;
|
||||||
import google.registry.model.EppResource;
|
import google.registry.model.EppResource;
|
||||||
import google.registry.model.contact.ContactResource;
|
import google.registry.model.contact.ContactResource;
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
|
import google.registry.model.host.HostBase;
|
||||||
import google.registry.model.host.HostResource;
|
import google.registry.model.host.HostResource;
|
||||||
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
|
import google.registry.model.translators.EnumToAttributeAdapter.EppEnum;
|
||||||
import google.registry.model.translators.StatusValueAdapter;
|
import google.registry.model.translators.StatusValueAdapter;
|
||||||
|
@ -127,7 +128,7 @@ public enum StatusValue implements EppEnum {
|
||||||
|
|
||||||
/** Enum to help clearly list which resource types a status value is allowed to be present on. */
|
/** Enum to help clearly list which resource types a status value is allowed to be present on. */
|
||||||
private enum AllowedOn {
|
private enum AllowedOn {
|
||||||
ALL(ContactResource.class, DomainBase.class, HostResource.class),
|
ALL(ContactResource.class, DomainBase.class, HostBase.class, HostResource.class),
|
||||||
NONE,
|
NONE,
|
||||||
DOMAINS(DomainBase.class);
|
DOMAINS(DomainBase.class);
|
||||||
|
|
||||||
|
|
229
core/src/main/java/google/registry/model/host/HostBase.java
Normal file
229
core/src/main/java/google/registry/model/host/HostBase.java
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package google.registry.model.host;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static com.google.common.collect.Sets.difference;
|
||||||
|
import static com.google.common.collect.Sets.union;
|
||||||
|
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
||||||
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
|
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import com.googlecode.objectify.annotation.IgnoreSave;
|
||||||
|
import com.googlecode.objectify.annotation.Index;
|
||||||
|
import com.googlecode.objectify.condition.IfNull;
|
||||||
|
import google.registry.model.EppResource;
|
||||||
|
import google.registry.model.domain.DomainBase;
|
||||||
|
import google.registry.model.transfer.TransferData;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.persistence.Access;
|
||||||
|
import javax.persistence.AccessType;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A persistable Host resource including mutable and non-mutable fields.
|
||||||
|
*
|
||||||
|
* <p>A host's {@link TransferData} is stored on the superordinate domain. Non-subordinate hosts
|
||||||
|
* don't carry a full set of TransferData; all they have is lastTransferTime.
|
||||||
|
*
|
||||||
|
* <p>This class deliberately does not include an {@link javax.persistence.Id} so that any
|
||||||
|
* foreign-keyed fields can refer to the proper parent entity's ID, whether we're storing this in
|
||||||
|
* the DB itself or as part of another entity
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc5732">RFC 5732</a>
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
@Embeddable
|
||||||
|
@Access(AccessType.FIELD)
|
||||||
|
public class HostBase extends EppResource {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fully qualified hostname, which is a unique identifier for this host.
|
||||||
|
*
|
||||||
|
* <p>This is only unique in the sense that for any given lifetime specified as the time range
|
||||||
|
* from (creationTime, deletionTime) there can only be one host in Datastore with this name.
|
||||||
|
* However, there can be many hosts with the same name and non-overlapping lifetimes.
|
||||||
|
*/
|
||||||
|
@Index String fullyQualifiedHostName;
|
||||||
|
|
||||||
|
/** IP Addresses for this host. Can be null if this is an external host. */
|
||||||
|
@Index Set<InetAddress> inetAddresses;
|
||||||
|
|
||||||
|
/** The superordinate domain of this host, or null if this is an external host. */
|
||||||
|
@Index
|
||||||
|
@IgnoreSave(IfNull.class)
|
||||||
|
@DoNotHydrate
|
||||||
|
VKey<DomainBase> superordinateDomain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time that this resource was last transferred.
|
||||||
|
*
|
||||||
|
* <p>Can be null if the resource has never been transferred.
|
||||||
|
*/
|
||||||
|
DateTime lastTransferTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The most recent time that the {@link #superordinateDomain} field was changed.
|
||||||
|
*
|
||||||
|
* <p>This should be updated whenever the superordinate domain changes, including when it is set
|
||||||
|
* to null. This field will be null for new hosts that have never experienced a change of
|
||||||
|
* superordinate domain.
|
||||||
|
*/
|
||||||
|
DateTime lastSuperordinateChange;
|
||||||
|
|
||||||
|
public String getFullyQualifiedHostName() {
|
||||||
|
return fullyQualifiedHostName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public VKey<DomainBase> getSuperordinateDomain() {
|
||||||
|
return superordinateDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSubordinate() {
|
||||||
|
return superordinateDomain != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableSet<InetAddress> getInetAddresses() {
|
||||||
|
return nullToEmptyImmutableCopy(inetAddresses);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime getLastTransferTime() {
|
||||||
|
return lastTransferTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime getLastSuperordinateChange() {
|
||||||
|
return lastSuperordinateChange;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getForeignKey() {
|
||||||
|
return fullyQualifiedHostName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VKey<? extends EppResource> createVKey() {
|
||||||
|
return VKey.createOfy(HostBase.class, Key.create(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
@Override
|
||||||
|
public HostBase cloneProjectedAtTime(DateTime now) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder asBuilder() {
|
||||||
|
return new Builder<>(clone(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the correct last transfer time for this host given its loaded superordinate domain.
|
||||||
|
*
|
||||||
|
* <p>Hosts can move between superordinate domains, so to know which lastTransferTime is correct
|
||||||
|
* we need to know if the host was attached to this superordinate the last time that the
|
||||||
|
* superordinate was transferred. If the last superordinate change was before this time, then the
|
||||||
|
* host was attached to this superordinate domain during that transfer.
|
||||||
|
*
|
||||||
|
* <p>If the host is not subordinate the domain can be null and we just return last transfer time.
|
||||||
|
*
|
||||||
|
* @param superordinateDomain the loaded superordinate domain, which must match the key in the
|
||||||
|
* {@link #superordinateDomain} field. Passing it as a parameter allows the caller to control
|
||||||
|
* the degree of consistency used to load it.
|
||||||
|
*/
|
||||||
|
public DateTime computeLastTransferTime(@Nullable DomainBase superordinateDomain) {
|
||||||
|
if (!isSubordinate()) {
|
||||||
|
checkArgument(superordinateDomain == null);
|
||||||
|
return getLastTransferTime();
|
||||||
|
}
|
||||||
|
checkArgument(
|
||||||
|
superordinateDomain != null
|
||||||
|
&& superordinateDomain.createVKey().equals(getSuperordinateDomain()));
|
||||||
|
DateTime lastSuperordinateChange =
|
||||||
|
Optional.ofNullable(getLastSuperordinateChange()).orElse(getCreationTime());
|
||||||
|
DateTime lastTransferOfCurrentSuperordinate =
|
||||||
|
Optional.ofNullable(superordinateDomain.getLastTransferTime()).orElse(START_OF_TIME);
|
||||||
|
return lastSuperordinateChange.isBefore(lastTransferOfCurrentSuperordinate)
|
||||||
|
? superordinateDomain.getLastTransferTime()
|
||||||
|
: getLastTransferTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A builder for constructing {@link HostBase}, since it is immutable. */
|
||||||
|
protected static class Builder<T extends HostBase, B extends Builder<T, B>>
|
||||||
|
extends EppResource.Builder<T, B> {
|
||||||
|
public Builder() {}
|
||||||
|
|
||||||
|
protected Builder(T instance) {
|
||||||
|
super(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strangely, if we don't add these @Overrides the methods return an EppResource.Builder
|
||||||
|
// even though we parameterize it with B in both cases anyway.
|
||||||
|
@Override
|
||||||
|
public B setRepoId(String repoId) {
|
||||||
|
return super.setRepoId(repoId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T build() {
|
||||||
|
return super.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setFullyQualifiedHostName(String fullyQualifiedHostName) {
|
||||||
|
checkArgument(
|
||||||
|
fullyQualifiedHostName.equals(canonicalizeDomainName(fullyQualifiedHostName)),
|
||||||
|
"Host name must be in puny-coded, lower-case form");
|
||||||
|
getInstance().fullyQualifiedHostName = fullyQualifiedHostName;
|
||||||
|
return thisCastToDerived();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setInetAddresses(ImmutableSet<InetAddress> inetAddresses) {
|
||||||
|
getInstance().inetAddresses = inetAddresses;
|
||||||
|
return thisCastToDerived();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setLastSuperordinateChange(DateTime lastSuperordinateChange) {
|
||||||
|
getInstance().lastSuperordinateChange = lastSuperordinateChange;
|
||||||
|
return thisCastToDerived();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B addInetAddresses(ImmutableSet<InetAddress> inetAddresses) {
|
||||||
|
return setInetAddresses(
|
||||||
|
ImmutableSet.copyOf(union(getInstance().getInetAddresses(), inetAddresses)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public B removeInetAddresses(ImmutableSet<InetAddress> inetAddresses) {
|
||||||
|
return setInetAddresses(
|
||||||
|
ImmutableSet.copyOf(difference(getInstance().getInetAddresses(), inetAddresses)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setSuperordinateDomain(VKey<DomainBase> superordinateDomain) {
|
||||||
|
getInstance().superordinateDomain = superordinateDomain;
|
||||||
|
return thisCastToDerived();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setLastTransferTime(DateTime lastTransferTime) {
|
||||||
|
getInstance().lastTransferTime = lastTransferTime;
|
||||||
|
return thisCastToDerived();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package google.registry.model.host;
|
||||||
|
|
||||||
|
import com.googlecode.objectify.Key;
|
||||||
|
import google.registry.model.EppResource;
|
||||||
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A persisted history entry representing an EPP modification to a host.
|
||||||
|
*
|
||||||
|
* <p>In addition to the general history fields (e.g. action time, registrar ID) we also persist a
|
||||||
|
* copy of the host entity at this point in time. We persist a raw {@link HostBase} so that the
|
||||||
|
* foreign-keyed fields in that class can refer to this object.
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@javax.persistence.Table(
|
||||||
|
indexes = {
|
||||||
|
@javax.persistence.Index(columnList = "creationTime"),
|
||||||
|
@javax.persistence.Index(columnList = "historyRegistrarId"),
|
||||||
|
@javax.persistence.Index(columnList = "fullyQualifiedHostName"),
|
||||||
|
@javax.persistence.Index(columnList = "historyType"),
|
||||||
|
@javax.persistence.Index(columnList = "historyModificationTime")
|
||||||
|
})
|
||||||
|
public class HostHistory extends HistoryEntry {
|
||||||
|
|
||||||
|
// Store HostBase instead of HostResource so we don't pick up its @Id
|
||||||
|
HostBase hostBase;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
VKey<HostResource> hostRepoId;
|
||||||
|
|
||||||
|
/** The state of the {@link HostBase} object at this point in time. */
|
||||||
|
public HostBase getHostBase() {
|
||||||
|
return hostBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The key to the {@link google.registry.model.host.HostResource} this is based off of. */
|
||||||
|
public VKey<HostResource> getHostRepoId() {
|
||||||
|
return hostRepoId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder asBuilder() {
|
||||||
|
return new Builder(clone(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder extends HistoryEntry.Builder<HostHistory, Builder> {
|
||||||
|
|
||||||
|
public Builder() {}
|
||||||
|
|
||||||
|
public Builder(HostHistory instance) {
|
||||||
|
super(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setHostBase(HostBase hostBase) {
|
||||||
|
getInstance().hostBase = hostBase;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setHostResourceId(VKey<HostResource> hostRepoId) {
|
||||||
|
getInstance().hostRepoId = hostRepoId;
|
||||||
|
hostRepoId.maybeGetOfyKey().ifPresent(parent -> getInstance().parent = parent);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can remove this once all HistoryEntries are converted to History objects
|
||||||
|
@Override
|
||||||
|
public Builder setParent(Key<? extends EppResource> parent) {
|
||||||
|
super.setParent(parent);
|
||||||
|
getInstance().hostRepoId = VKey.createOfy(HostResource.class, (Key<HostResource>) parent);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,112 +14,36 @@
|
||||||
|
|
||||||
package google.registry.model.host;
|
package google.registry.model.host;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
|
||||||
import static com.google.common.collect.Sets.difference;
|
|
||||||
import static com.google.common.collect.Sets.union;
|
|
||||||
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
|
|
||||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
|
||||||
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.googlecode.objectify.Key;
|
import com.googlecode.objectify.Key;
|
||||||
import com.googlecode.objectify.annotation.Entity;
|
import com.googlecode.objectify.annotation.Entity;
|
||||||
import com.googlecode.objectify.annotation.IgnoreSave;
|
|
||||||
import com.googlecode.objectify.annotation.Index;
|
|
||||||
import com.googlecode.objectify.condition.IfNull;
|
|
||||||
import google.registry.model.EppResource;
|
|
||||||
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
import google.registry.model.EppResource.ForeignKeyedEppResource;
|
||||||
import google.registry.model.annotations.ExternalMessagingName;
|
import google.registry.model.annotations.ExternalMessagingName;
|
||||||
import google.registry.model.annotations.ReportedOn;
|
import google.registry.model.annotations.ReportedOn;
|
||||||
import google.registry.model.domain.DomainBase;
|
|
||||||
import google.registry.model.transfer.TransferData;
|
|
||||||
import google.registry.persistence.VKey;
|
import google.registry.persistence.VKey;
|
||||||
import google.registry.persistence.WithStringVKey;
|
import google.registry.persistence.WithStringVKey;
|
||||||
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
import google.registry.schema.replay.DatastoreAndSqlEntity;
|
||||||
import java.net.InetAddress;
|
import javax.persistence.Access;
|
||||||
import java.util.Optional;
|
import javax.persistence.AccessType;
|
||||||
import java.util.Set;
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import org.joda.time.DateTime;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A persistable Host resource including mutable and non-mutable fields.
|
* A persistable Host resource including mutable and non-mutable fields.
|
||||||
*
|
*
|
||||||
* <p>A host's {@link TransferData} is stored on the superordinate domain. Non-subordinate hosts
|
* <p>The {@link javax.persistence.Id} of the HostResource is the repoId.
|
||||||
* don't carry a full set of TransferData; all they have is lastTransferTime.
|
|
||||||
*
|
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc5732">RFC 5732</a>
|
|
||||||
*/
|
*/
|
||||||
@ReportedOn
|
@ReportedOn
|
||||||
@Entity
|
@Entity
|
||||||
@javax.persistence.Entity
|
@javax.persistence.Entity
|
||||||
@ExternalMessagingName("host")
|
@ExternalMessagingName("host")
|
||||||
@WithStringVKey
|
@WithStringVKey
|
||||||
public class HostResource extends EppResource
|
@Access(AccessType.FIELD) // otherwise it'll use the default if the repoId (property)
|
||||||
|
public class HostResource extends HostBase
|
||||||
implements DatastoreAndSqlEntity, ForeignKeyedEppResource {
|
implements DatastoreAndSqlEntity, ForeignKeyedEppResource {
|
||||||
|
|
||||||
/**
|
|
||||||
* Fully qualified hostname, which is a unique identifier for this host.
|
|
||||||
*
|
|
||||||
* <p>This is only unique in the sense that for any given lifetime specified as the time range
|
|
||||||
* from (creationTime, deletionTime) there can only be one host in Datastore with this name.
|
|
||||||
* However, there can be many hosts with the same name and non-overlapping lifetimes.
|
|
||||||
*/
|
|
||||||
@Index
|
|
||||||
String fullyQualifiedHostName;
|
|
||||||
|
|
||||||
/** IP Addresses for this host. Can be null if this is an external host. */
|
|
||||||
@Index Set<InetAddress> inetAddresses;
|
|
||||||
|
|
||||||
/** The superordinate domain of this host, or null if this is an external host. */
|
|
||||||
@Index
|
|
||||||
@IgnoreSave(IfNull.class)
|
|
||||||
@DoNotHydrate
|
|
||||||
VKey<DomainBase> superordinateDomain;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The time that this resource was last transferred.
|
|
||||||
*
|
|
||||||
* <p>Can be null if the resource has never been transferred.
|
|
||||||
*/
|
|
||||||
DateTime lastTransferTime;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The most recent time that the {@link #superordinateDomain} field was changed.
|
|
||||||
*
|
|
||||||
* <p>This should be updated whenever the superordinate domain changes, including when it is set
|
|
||||||
* to null. This field will be null for new hosts that have never experienced a change of
|
|
||||||
* superordinate domain.
|
|
||||||
*/
|
|
||||||
DateTime lastSuperordinateChange;
|
|
||||||
|
|
||||||
public String getFullyQualifiedHostName() {
|
|
||||||
return fullyQualifiedHostName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public VKey<DomainBase> getSuperordinateDomain() {
|
|
||||||
return superordinateDomain;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSubordinate() {
|
|
||||||
return superordinateDomain != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImmutableSet<InetAddress> getInetAddresses() {
|
|
||||||
return nullToEmptyImmutableCopy(inetAddresses);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DateTime getLastTransferTime() {
|
|
||||||
return lastTransferTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DateTime getLastSuperordinateChange() {
|
|
||||||
return lastSuperordinateChange;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getForeignKey() {
|
@javax.persistence.Id
|
||||||
return fullyQualifiedHostName;
|
@Access(AccessType.PROPERTY) // to tell it to use the non-default property-as-ID
|
||||||
|
public String getRepoId() {
|
||||||
|
return super.getRepoId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -128,92 +52,17 @@ public class HostResource extends EppResource
|
||||||
return VKey.createOfy(HostResource.class, Key.create(this));
|
return VKey.createOfy(HostResource.class, Key.create(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public HostResource cloneProjectedAtTime(DateTime now) {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compute the correct last transfer time for this host given its loaded superordinate domain.
|
|
||||||
*
|
|
||||||
* <p>Hosts can move between superordinate domains, so to know which lastTransferTime is correct
|
|
||||||
* we need to know if the host was attached to this superordinate the last time that the
|
|
||||||
* superordinate was transferred. If the last superordinate change was before this time, then the
|
|
||||||
* host was attached to this superordinate domain during that transfer.
|
|
||||||
*
|
|
||||||
* <p>If the host is not subordinate the domain can be null and we just return last transfer time.
|
|
||||||
*
|
|
||||||
* @param superordinateDomain the loaded superordinate domain, which must match the key in the
|
|
||||||
* {@link #superordinateDomain} field. Passing it as a parameter allows the caller to control
|
|
||||||
* the degree of consistency used to load it.
|
|
||||||
*/
|
|
||||||
public DateTime computeLastTransferTime(@Nullable DomainBase superordinateDomain) {
|
|
||||||
if (!isSubordinate()) {
|
|
||||||
checkArgument(superordinateDomain == null);
|
|
||||||
return getLastTransferTime();
|
|
||||||
}
|
|
||||||
checkArgument(
|
|
||||||
superordinateDomain != null
|
|
||||||
&& superordinateDomain.createVKey().equals(getSuperordinateDomain()));
|
|
||||||
DateTime lastSuperordinateChange =
|
|
||||||
Optional.ofNullable(getLastSuperordinateChange()).orElse(getCreationTime());
|
|
||||||
DateTime lastTransferOfCurrentSuperordinate =
|
|
||||||
Optional.ofNullable(superordinateDomain.getLastTransferTime()).orElse(START_OF_TIME);
|
|
||||||
return lastSuperordinateChange.isBefore(lastTransferOfCurrentSuperordinate)
|
|
||||||
? superordinateDomain.getLastTransferTime()
|
|
||||||
: getLastTransferTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Builder asBuilder() {
|
public Builder asBuilder() {
|
||||||
return new Builder(clone(this));
|
return new Builder(clone(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A builder for constructing {@link HostResource}, since it is immutable. */
|
/** A builder for constructing {@link HostResource}, since it is immutable. */
|
||||||
public static class Builder extends EppResource.Builder<HostResource, Builder> {
|
public static class Builder extends HostBase.Builder<HostResource, Builder> {
|
||||||
public Builder() {}
|
public Builder() {}
|
||||||
|
|
||||||
private Builder(HostResource instance) {
|
private Builder(HostResource instance) {
|
||||||
super(instance);
|
super(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setFullyQualifiedHostName(String fullyQualifiedHostName) {
|
|
||||||
checkArgument(
|
|
||||||
fullyQualifiedHostName.equals(canonicalizeDomainName(fullyQualifiedHostName)),
|
|
||||||
"Host name must be in puny-coded, lower-case form");
|
|
||||||
getInstance().fullyQualifiedHostName = fullyQualifiedHostName;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setInetAddresses(ImmutableSet<InetAddress> inetAddresses) {
|
|
||||||
getInstance().inetAddresses = inetAddresses;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setLastSuperordinateChange(DateTime lastSuperordinateChange) {
|
|
||||||
getInstance().lastSuperordinateChange = lastSuperordinateChange;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder addInetAddresses(ImmutableSet<InetAddress> inetAddresses) {
|
|
||||||
return setInetAddresses(ImmutableSet.copyOf(
|
|
||||||
union(getInstance().getInetAddresses(), inetAddresses)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder removeInetAddresses(ImmutableSet<InetAddress> inetAddresses) {
|
|
||||||
return setInetAddresses(ImmutableSet.copyOf(
|
|
||||||
difference(getInstance().getInetAddresses(), inetAddresses)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setSuperordinateDomain(VKey<DomainBase> superordinateDomain) {
|
|
||||||
getInstance().superordinateDomain = superordinateDomain;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setLastTransferTime(DateTime lastTransferTime) {
|
|
||||||
getInstance().lastTransferTime = lastTransferTime;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,22 @@ import google.registry.model.domain.Period;
|
||||||
import google.registry.model.eppcommon.Trid;
|
import google.registry.model.eppcommon.Trid;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.persistence.AttributeOverride;
|
||||||
|
import javax.persistence.AttributeOverrides;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import javax.persistence.SequenceGenerator;
|
||||||
|
import javax.persistence.Transient;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/** A record of an EPP command that mutated a resource. */
|
/** A record of an EPP command that mutated a resource. */
|
||||||
@ReportedOn
|
@ReportedOn
|
||||||
@Entity
|
@Entity
|
||||||
|
@MappedSuperclass
|
||||||
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. */
|
||||||
|
@ -60,8 +71,8 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||||
@Deprecated
|
@Deprecated
|
||||||
DOMAIN_ALLOCATE,
|
DOMAIN_ALLOCATE,
|
||||||
/**
|
/**
|
||||||
* Used for domain registration autorenews explicitly logged by
|
* Used for domain registration autorenews explicitly logged by {@link
|
||||||
* {@link google.registry.batch.ExpandRecurringBillingEventsAction}.
|
* google.registry.batch.ExpandRecurringBillingEventsAction}.
|
||||||
*/
|
*/
|
||||||
DOMAIN_AUTORENEW,
|
DOMAIN_AUTORENEW,
|
||||||
DOMAIN_CREATE,
|
DOMAIN_CREATE,
|
||||||
|
@ -89,14 +100,22 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The autogenerated id of this event. */
|
/** The autogenerated id of this event. */
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "HistorySequenceGenerator")
|
||||||
|
@SequenceGenerator(
|
||||||
|
name = "HistorySequenceGenerator",
|
||||||
|
sequenceName = "history_id_sequence",
|
||||||
|
allocationSize = 1)
|
||||||
@Id
|
@Id
|
||||||
long id;
|
@javax.persistence.Id
|
||||||
|
@Column(name = "historyRevisionId")
|
||||||
|
Long id;
|
||||||
|
|
||||||
/** The resource this event mutated. */
|
/** The resource this event mutated. */
|
||||||
@Parent
|
@Parent @Transient protected Key<? extends EppResource> parent;
|
||||||
Key<? extends EppResource> parent;
|
|
||||||
|
|
||||||
/** The type of history entry. */
|
/** The type of history entry. */
|
||||||
|
@Column(nullable = false, name = "historyType")
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
Type type;
|
Type type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,17 +123,21 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||||
* be null for all other types.
|
* be null for all other types.
|
||||||
*/
|
*/
|
||||||
@IgnoreSave(IfNull.class)
|
@IgnoreSave(IfNull.class)
|
||||||
|
@Transient // domain-specific
|
||||||
Period period;
|
Period period;
|
||||||
|
|
||||||
/** The actual EPP xml of the command, stored as bytes to be agnostic of encoding. */
|
/** The actual EPP xml of the command, stored as bytes to be agnostic of encoding. */
|
||||||
|
@Column(nullable = false, name = "historyXmlBytes")
|
||||||
byte[] xmlBytes;
|
byte[] xmlBytes;
|
||||||
|
|
||||||
/** The time the command occurred, represented by the ofy transaction time.*/
|
/** The time the command occurred, represented by the ofy transaction time. */
|
||||||
@Index
|
@Index
|
||||||
|
@Column(nullable = false, name = "historyModificationTime")
|
||||||
DateTime modificationTime;
|
DateTime modificationTime;
|
||||||
|
|
||||||
/** The id of the registrar that sent the command. */
|
/** The id of the registrar that sent the command. */
|
||||||
@Index
|
@Index
|
||||||
|
@Column(name = "historyRegistrarId")
|
||||||
String clientId;
|
String clientId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,18 +147,31 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||||
* sending the EPP transfer command is the gaining party). For approves and rejects, the other
|
* sending the EPP transfer command is the gaining party). For approves and rejects, the other
|
||||||
* registrar is the gaining party.
|
* registrar is the gaining party.
|
||||||
*/
|
*/
|
||||||
|
@Transient // domain-specific
|
||||||
String otherClientId;
|
String otherClientId;
|
||||||
|
|
||||||
/** Transaction id that made this change, or null if the entry was not created by a flow. */
|
/** Transaction id that made this change, or null if the entry was not created by a flow. */
|
||||||
@Nullable Trid trid;
|
@Nullable
|
||||||
|
@AttributeOverrides({
|
||||||
|
@AttributeOverride(
|
||||||
|
name = "clientTransactionId",
|
||||||
|
column = @Column(name = "historyClientTransactionId")),
|
||||||
|
@AttributeOverride(
|
||||||
|
name = "serverTransactionId",
|
||||||
|
column = @Column(name = "historyServerTransactionId"))
|
||||||
|
})
|
||||||
|
Trid trid;
|
||||||
|
|
||||||
/** Whether this change was created by a superuser. */
|
/** Whether this change was created by a superuser. */
|
||||||
|
@Column(nullable = false, name = "historyBySuperuser")
|
||||||
boolean bySuperuser;
|
boolean bySuperuser;
|
||||||
|
|
||||||
/** Reason for the change. */
|
/** Reason for the change. */
|
||||||
|
@Column(nullable = false, name = "historyReason")
|
||||||
String reason;
|
String reason;
|
||||||
|
|
||||||
/** Whether this change was requested by a registrar. */
|
/** Whether this change was requested by a registrar. */
|
||||||
|
@Column(nullable = false, name = "historyRequestedByRegistrar")
|
||||||
Boolean requestedByRegistrar;
|
Boolean requestedByRegistrar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,6 +181,7 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||||
* also be empty if the HistoryEntry refers to an EPP mutation that does not affect domain
|
* also be empty if the HistoryEntry refers to an EPP mutation that does not affect domain
|
||||||
* transaction counts (such as contact or host mutations).
|
* transaction counts (such as contact or host mutations).
|
||||||
*/
|
*/
|
||||||
|
@Transient // domain-specific
|
||||||
Set<DomainTransactionRecord> domainTransactionRecords;
|
Set<DomainTransactionRecord> domainTransactionRecords;
|
||||||
|
|
||||||
public Key<? extends EppResource> getParent() {
|
public Key<? extends EppResource> getParent() {
|
||||||
|
@ -176,7 +213,8 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns the TRID, which may be null if the entry was not created by a normal flow. */
|
/** Returns the TRID, which may be null if the entry was not created by a normal flow. */
|
||||||
@Nullable public Trid getTrid() {
|
@Nullable
|
||||||
|
public Trid getTrid() {
|
||||||
return trid;
|
return trid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,77 +240,84 @@ public class HistoryEntry extends ImmutableObject implements Buildable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A builder for {@link HistoryEntry} since it is immutable */
|
/** A builder for {@link HistoryEntry} since it is immutable */
|
||||||
public static class Builder extends Buildable.Builder<HistoryEntry> {
|
public static class Builder<T extends HistoryEntry, B extends Builder<?, ?>>
|
||||||
|
extends GenericBuilder<T, B> {
|
||||||
public Builder() {}
|
public Builder() {}
|
||||||
|
|
||||||
public Builder(HistoryEntry instance) {
|
public Builder(T instance) {
|
||||||
super(instance);
|
super(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setParent(EppResource parent) {
|
@Override
|
||||||
|
public T build() {
|
||||||
|
return super.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B setParent(EppResource parent) {
|
||||||
getInstance().parent = Key.create(parent);
|
getInstance().parent = Key.create(parent);
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setParent(Key<? extends EppResource> parentKey) {
|
// Until we move completely to SQL, override this in subclasses (e.g. HostHistory) to set VKeys
|
||||||
getInstance().parent = parentKey;
|
public B setParent(Key<? extends EppResource> parent) {
|
||||||
return this;
|
getInstance().parent = parent;
|
||||||
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setType(Type type) {
|
public B setType(Type type) {
|
||||||
getInstance().type = type;
|
getInstance().type = type;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setPeriod(Period period) {
|
public B setPeriod(Period period) {
|
||||||
getInstance().period = period;
|
getInstance().period = period;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setXmlBytes(byte[] xmlBytes) {
|
public B setXmlBytes(byte[] xmlBytes) {
|
||||||
getInstance().xmlBytes = xmlBytes;
|
getInstance().xmlBytes = xmlBytes;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setModificationTime(DateTime modificationTime) {
|
public B setModificationTime(DateTime modificationTime) {
|
||||||
getInstance().modificationTime = modificationTime;
|
getInstance().modificationTime = modificationTime;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setClientId(String clientId) {
|
public B setClientId(String clientId) {
|
||||||
getInstance().clientId = clientId;
|
getInstance().clientId = clientId;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setOtherClientId(String otherClientId) {
|
public B setOtherClientId(String otherClientId) {
|
||||||
getInstance().otherClientId = otherClientId;
|
getInstance().otherClientId = otherClientId;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setTrid(Trid trid) {
|
public B setTrid(Trid trid) {
|
||||||
getInstance().trid = trid;
|
getInstance().trid = trid;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setBySuperuser(boolean bySuperuser) {
|
public B setBySuperuser(boolean bySuperuser) {
|
||||||
getInstance().bySuperuser = bySuperuser;
|
getInstance().bySuperuser = bySuperuser;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setReason(String reason) {
|
public B setReason(String reason) {
|
||||||
getInstance().reason = reason;
|
getInstance().reason = reason;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setRequestedByRegistrar(Boolean requestedByRegistrar) {
|
public B setRequestedByRegistrar(Boolean requestedByRegistrar) {
|
||||||
getInstance().requestedByRegistrar = requestedByRegistrar;
|
getInstance().requestedByRegistrar = requestedByRegistrar;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder setDomainTransactionRecords(
|
public B setDomainTransactionRecords(
|
||||||
ImmutableSet<DomainTransactionRecord> domainTransactionRecords) {
|
ImmutableSet<DomainTransactionRecord> domainTransactionRecords) {
|
||||||
getInstance().domainTransactionRecords = domainTransactionRecords;
|
getInstance().domainTransactionRecords = domainTransactionRecords;
|
||||||
return this;
|
return thisCastToDerived();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
<class>google.registry.model.billing.BillingEvent$Recurring</class>
|
<class>google.registry.model.billing.BillingEvent$Recurring</class>
|
||||||
<class>google.registry.model.contact.ContactResource</class>
|
<class>google.registry.model.contact.ContactResource</class>
|
||||||
<class>google.registry.model.domain.DomainBase</class>
|
<class>google.registry.model.domain.DomainBase</class>
|
||||||
|
<class>google.registry.model.host.HostHistory</class>
|
||||||
<class>google.registry.model.host.HostResource</class>
|
<class>google.registry.model.host.HostResource</class>
|
||||||
<class>google.registry.model.registrar.Registrar</class>
|
<class>google.registry.model.registrar.Registrar</class>
|
||||||
<class>google.registry.model.registrar.RegistrarContact</class>
|
<class>google.registry.model.registrar.RegistrarContact</class>
|
||||||
|
@ -63,8 +64,8 @@
|
||||||
|
|
||||||
<!-- Generated converters for VKey -->
|
<!-- Generated converters for VKey -->
|
||||||
<class>google.registry.model.billing.VKeyConverter_BillingEvent</class>
|
<class>google.registry.model.billing.VKeyConverter_BillingEvent</class>
|
||||||
<class>google.registry.model.domain.VKeyConverter_DomainBase</class>
|
|
||||||
<class>google.registry.model.contact.VKeyConverter_ContactResource</class>
|
<class>google.registry.model.contact.VKeyConverter_ContactResource</class>
|
||||||
|
<class>google.registry.model.domain.VKeyConverter_DomainBase</class>
|
||||||
<class>google.registry.model.domain.token.VKeyConverter_AllocationToken</class>
|
<class>google.registry.model.domain.token.VKeyConverter_AllocationToken</class>
|
||||||
<class>google.registry.model.host.VKeyConverter_HostResource</class>
|
<class>google.registry.model.host.VKeyConverter_HostResource</class>
|
||||||
<class>google.registry.model.poll.VKeyConverter_Autorenew</class>
|
<class>google.registry.model.poll.VKeyConverter_Autorenew</class>
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
// 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.history;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||||
|
import static google.registry.testing.SqlHelper.saveRegistrar;
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import google.registry.model.EntityTestCase;
|
||||||
|
import google.registry.model.eppcommon.Trid;
|
||||||
|
import google.registry.model.host.HostHistory;
|
||||||
|
import google.registry.model.host.HostResource;
|
||||||
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import google.registry.persistence.VKey;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/** Tests for {@link HostHistory}. */
|
||||||
|
public class HostHistoryTest extends EntityTestCase {
|
||||||
|
|
||||||
|
public HostHistoryTest() {
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPersistence() {
|
||||||
|
saveRegistrar("registrar1");
|
||||||
|
|
||||||
|
HostResource host =
|
||||||
|
new HostResource.Builder()
|
||||||
|
.setRepoId("host1")
|
||||||
|
.setFullyQualifiedHostName("ns1.example.com")
|
||||||
|
.setCreationClientId("TheRegistrar")
|
||||||
|
.setPersistedCurrentSponsorClientId("TheRegistrar")
|
||||||
|
.setInetAddresses(ImmutableSet.of())
|
||||||
|
.build();
|
||||||
|
jpaTm().transact(() -> jpaTm().saveNew(host));
|
||||||
|
VKey<HostResource> hostVKey = VKey.createSql(HostResource.class, "host1");
|
||||||
|
HostResource hostFromDb = jpaTm().transact(() -> jpaTm().load(hostVKey));
|
||||||
|
HostHistory hostHistory =
|
||||||
|
new HostHistory.Builder()
|
||||||
|
.setType(HistoryEntry.Type.HOST_CREATE)
|
||||||
|
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||||
|
.setModificationTime(fakeClock.nowUtc())
|
||||||
|
.setClientId("registrar1")
|
||||||
|
.setTrid(Trid.create("ABC-123", "server-trid"))
|
||||||
|
.setBySuperuser(false)
|
||||||
|
.setReason("reason")
|
||||||
|
.setRequestedByRegistrar(true)
|
||||||
|
.setHostBase(hostFromDb)
|
||||||
|
.setHostResourceId(hostVKey)
|
||||||
|
.build();
|
||||||
|
jpaTm().transact(() -> jpaTm().saveNew(hostHistory));
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> {
|
||||||
|
HostHistory fromDatabase = jpaTm().load(VKey.createSql(HostHistory.class, 1L));
|
||||||
|
assertHostHistoriesEqual(fromDatabase, hostHistory);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertHostHistoriesEqual(HostHistory one, HostHistory two) {
|
||||||
|
// enough of the fields get changed during serialization that we can't depend on .equals()
|
||||||
|
assertThat(one.getClientId()).isEqualTo(two.getClientId());
|
||||||
|
assertThat(one.getHostRepoId()).isEqualTo(two.getHostRepoId());
|
||||||
|
assertThat(one.getBySuperuser()).isEqualTo(two.getBySuperuser());
|
||||||
|
assertThat(one.getRequestedByRegistrar()).isEqualTo(two.getRequestedByRegistrar());
|
||||||
|
assertThat(one.getReason()).isEqualTo(two.getReason());
|
||||||
|
assertThat(one.getTrid()).isEqualTo(two.getTrid());
|
||||||
|
assertThat(one.getType()).isEqualTo(two.getType());
|
||||||
|
assertThat(one.getHostBase().getFullyQualifiedHostName())
|
||||||
|
.isEqualTo(two.getHostBase().getFullyQualifiedHostName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import static com.google.common.truth.Truth.assert_;
|
||||||
import google.registry.model.billing.BillingEventTest;
|
import google.registry.model.billing.BillingEventTest;
|
||||||
import google.registry.model.contact.ContactResourceTest;
|
import google.registry.model.contact.ContactResourceTest;
|
||||||
import google.registry.model.domain.DomainBaseSqlTest;
|
import google.registry.model.domain.DomainBaseSqlTest;
|
||||||
|
import google.registry.model.history.HostHistoryTest;
|
||||||
import google.registry.model.poll.PollMessageTest;
|
import google.registry.model.poll.PollMessageTest;
|
||||||
import google.registry.model.registry.RegistryLockDaoTest;
|
import google.registry.model.registry.RegistryLockDaoTest;
|
||||||
import google.registry.persistence.transaction.JpaEntityCoverage;
|
import google.registry.persistence.transaction.JpaEntityCoverage;
|
||||||
|
@ -75,6 +76,7 @@ import org.junit.runner.RunWith;
|
||||||
ContactResourceTest.class,
|
ContactResourceTest.class,
|
||||||
CursorDaoTest.class,
|
CursorDaoTest.class,
|
||||||
DomainBaseSqlTest.class,
|
DomainBaseSqlTest.class,
|
||||||
|
HostHistoryTest.class,
|
||||||
LockDaoTest.class,
|
LockDaoTest.class,
|
||||||
PollMessageTest.class,
|
PollMessageTest.class,
|
||||||
PremiumListDaoTest.class,
|
PremiumListDaoTest.class,
|
||||||
|
|
|
@ -618,7 +618,7 @@ enum google.registry.model.reporting.DomainTransactionRecord$TransactionReportFi
|
||||||
TRANSFER_SUCCESSFUL;
|
TRANSFER_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
class google.registry.model.reporting.HistoryEntry {
|
class google.registry.model.reporting.HistoryEntry {
|
||||||
@Id long id;
|
@Id java.lang.Long id;
|
||||||
@Parent com.googlecode.objectify.Key<? extends google.registry.model.EppResource> parent;
|
@Parent com.googlecode.objectify.Key<? extends google.registry.model.EppResource> parent;
|
||||||
boolean bySuperuser;
|
boolean bySuperuser;
|
||||||
byte[] xmlBytes;
|
byte[] xmlBytes;
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
-- 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 "HostHistory" (
|
||||||
|
history_revision_id int8 NOT NULL,
|
||||||
|
history_by_superuser boolean NOT NULL,
|
||||||
|
history_registrar_id text NOT NULL,
|
||||||
|
history_modification_time timestamptz NOT NULL,
|
||||||
|
history_reason text NOT NULL,
|
||||||
|
history_requested_by_registrar boolean NOT NULL,
|
||||||
|
history_client_transaction_id text,
|
||||||
|
history_server_transaction_id text,
|
||||||
|
history_type text NOT NULL,
|
||||||
|
history_xml_bytes bytea NOT NULL,
|
||||||
|
fully_qualified_host_name text,
|
||||||
|
inet_addresses text[],
|
||||||
|
last_superordinate_change timestamptz,
|
||||||
|
last_transfer_time timestamptz,
|
||||||
|
superordinate_domain text,
|
||||||
|
creation_registrar_id text NOT NULL,
|
||||||
|
creation_time timestamptz NOT NULL,
|
||||||
|
current_sponsor_registrar_id text NOT NULL,
|
||||||
|
deletion_time timestamptz,
|
||||||
|
last_epp_update_registrar_id text,
|
||||||
|
last_epp_update_time timestamptz,
|
||||||
|
statuses text[],
|
||||||
|
host_repo_id text NOT NULL,
|
||||||
|
primary key (history_revision_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX IDXfg2nnjlujxo6cb9fha971bq2n ON "HostHistory" (creation_time);
|
||||||
|
CREATE INDEX IDX1iy7njgb7wjmj9piml4l2g0qi ON "HostHistory" (history_registrar_id);
|
||||||
|
CREATE INDEX IDXj77pfwhui9f0i7wjq6lmibovj ON "HostHistory" (fully_qualified_host_name);
|
||||||
|
CREATE INDEX IDXknk8gmj7s47q56cwpa6rmpt5l ON "HostHistory" (history_type);
|
||||||
|
CREATE INDEX IDX67qwkjtlq5q8dv6egtrtnhqi7 ON "HostHistory" (history_modification_time);
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS "HostHistory"
|
||||||
|
ADD CONSTRAINT FK3d09knnmxrt6iniwnp8j2ykga
|
||||||
|
FOREIGN KEY (history_registrar_id)
|
||||||
|
REFERENCES "Registrar";
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS "HostHistory"
|
||||||
|
ADD CONSTRAINT FK_HostHistory_HostResource
|
||||||
|
FOREIGN KEY (host_repo_id)
|
||||||
|
REFERENCES "HostResource";
|
||||||
|
|
||||||
|
CREATE SEQUENCE public."history_id_sequence"
|
||||||
|
START WITH 1
|
||||||
|
INCREMENT BY 1
|
||||||
|
NO MINVALUE
|
||||||
|
NO MAXVALUE
|
||||||
|
CACHE 1;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."HostHistory" ALTER COLUMN history_revision_id
|
||||||
|
SET DEFAULT nextval('public."history_id_sequence"'::regclass);
|
|
@ -11,6 +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 table "BillingCancellation" (
|
create table "BillingCancellation" (
|
||||||
billing_cancellation_id bigserial not null,
|
billing_cancellation_id bigserial not null,
|
||||||
|
@ -208,6 +209,33 @@
|
||||||
primary key (id)
|
primary key (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create table "HostHistory" (
|
||||||
|
history_revision_id int8 not null,
|
||||||
|
history_by_superuser boolean not null,
|
||||||
|
history_registrar_id text,
|
||||||
|
history_modification_time timestamptz not null,
|
||||||
|
history_reason text not null,
|
||||||
|
history_requested_by_registrar boolean not null,
|
||||||
|
history_client_transaction_id text,
|
||||||
|
history_server_transaction_id text,
|
||||||
|
history_type text not null,
|
||||||
|
history_xml_bytes bytea not null,
|
||||||
|
fully_qualified_host_name text,
|
||||||
|
inet_addresses text[],
|
||||||
|
last_superordinate_change timestamptz,
|
||||||
|
last_transfer_time timestamptz,
|
||||||
|
superordinate_domain text,
|
||||||
|
creation_registrar_id text not null,
|
||||||
|
creation_time timestamptz not null,
|
||||||
|
current_sponsor_registrar_id text not null,
|
||||||
|
deletion_time timestamptz,
|
||||||
|
last_epp_update_registrar_id text,
|
||||||
|
last_epp_update_time timestamptz,
|
||||||
|
statuses text[],
|
||||||
|
host_repo_id text not null,
|
||||||
|
primary key (history_revision_id)
|
||||||
|
);
|
||||||
|
|
||||||
create table "HostResource" (
|
create table "HostResource" (
|
||||||
repo_id text not null,
|
repo_id text not null,
|
||||||
creation_registrar_id text not null,
|
creation_registrar_id text not null,
|
||||||
|
@ -403,6 +431,11 @@ create index IDXhsjqiy2lyobfymplb28nm74lm on "Domain" (current_sponsor_registrar
|
||||||
create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
|
create index IDX5mnf0wn20tno4b9do88j61klr on "Domain" (deletion_time);
|
||||||
create index IDX1rcgkdd777bpvj0r94sltwd5y on "Domain" (fully_qualified_domain_name);
|
create index IDX1rcgkdd777bpvj0r94sltwd5y on "Domain" (fully_qualified_domain_name);
|
||||||
create index IDXrwl38wwkli1j7gkvtywi9jokq on "Domain" (tld);
|
create index IDXrwl38wwkli1j7gkvtywi9jokq on "Domain" (tld);
|
||||||
|
create index IDXfg2nnjlujxo6cb9fha971bq2n on "HostHistory" (creation_time);
|
||||||
|
create index IDX1iy7njgb7wjmj9piml4l2g0qi on "HostHistory" (history_registrar_id);
|
||||||
|
create index IDXj77pfwhui9f0i7wjq6lmibovj on "HostHistory" (fully_qualified_host_name);
|
||||||
|
create index IDXknk8gmj7s47q56cwpa6rmpt5l on "HostHistory" (history_type);
|
||||||
|
create index IDX67qwkjtlq5q8dv6egtrtnhqi7 on "HostHistory" (history_modification_time);
|
||||||
create index IDXe7wu46c7wpvfmfnj4565abibp on "PollMessage" (registrar_id);
|
create index IDXe7wu46c7wpvfmfnj4565abibp on "PollMessage" (registrar_id);
|
||||||
create index IDXaydgox62uno9qx8cjlj5lauye on "PollMessage" (event_time);
|
create index IDXaydgox62uno9qx8cjlj5lauye on "PollMessage" (event_time);
|
||||||
create index premiumlist_name_idx on "PremiumList" (name);
|
create index premiumlist_name_idx on "PremiumList" (name);
|
||||||
|
|
|
@ -325,6 +325,49 @@ CREATE TABLE public."DomainHost" (
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- 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: HostHistory; Type: TABLE; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE TABLE public."HostHistory" (
|
||||||
|
history_revision_id bigint DEFAULT nextval('public.history_id_sequence'::regclass) NOT NULL,
|
||||||
|
history_by_superuser boolean NOT NULL,
|
||||||
|
history_registrar_id text NOT NULL,
|
||||||
|
history_modification_time timestamp with time zone NOT NULL,
|
||||||
|
history_reason text NOT NULL,
|
||||||
|
history_requested_by_registrar boolean NOT NULL,
|
||||||
|
history_client_transaction_id text,
|
||||||
|
history_server_transaction_id text,
|
||||||
|
history_type text NOT NULL,
|
||||||
|
history_xml_bytes bytea NOT NULL,
|
||||||
|
fully_qualified_host_name text,
|
||||||
|
inet_addresses text[],
|
||||||
|
last_superordinate_change timestamp with time zone,
|
||||||
|
last_transfer_time timestamp with time zone,
|
||||||
|
superordinate_domain text,
|
||||||
|
creation_registrar_id text NOT NULL,
|
||||||
|
creation_time timestamp with time zone NOT NULL,
|
||||||
|
current_sponsor_registrar_id text NOT NULL,
|
||||||
|
deletion_time timestamp with time zone,
|
||||||
|
last_epp_update_registrar_id text,
|
||||||
|
last_epp_update_time timestamp with time zone,
|
||||||
|
statuses text[],
|
||||||
|
host_repo_id text NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: HostResource; Type: TABLE; Schema: public; Owner: -
|
-- Name: HostResource; Type: TABLE; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -733,6 +776,14 @@ ALTER TABLE ONLY public."Domain"
|
||||||
ADD CONSTRAINT "Domain_pkey" PRIMARY KEY (repo_id);
|
ADD CONSTRAINT "Domain_pkey" PRIMARY KEY (repo_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: HostHistory HostHistory_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."HostHistory"
|
||||||
|
ADD CONSTRAINT "HostHistory_pkey" PRIMARY KEY (history_revision_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: HostResource HostResource_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
-- Name: HostResource HostResource_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -829,6 +880,13 @@ ALTER TABLE ONLY public."Contact"
|
||||||
ADD CONSTRAINT ukoqd7n4hbx86hvlgkilq75olas UNIQUE (contact_id);
|
ADD CONSTRAINT ukoqd7n4hbx86hvlgkilq75olas UNIQUE (contact_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idx1iy7njgb7wjmj9piml4l2g0qi; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idx1iy7njgb7wjmj9piml4l2g0qi ON public."HostHistory" USING btree (history_registrar_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idx1p3esngcwwu6hstyua6itn6ff; Type: INDEX; Schema: public; Owner: -
|
-- Name: idx1p3esngcwwu6hstyua6itn6ff; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -871,6 +929,13 @@ CREATE INDEX idx5mnf0wn20tno4b9do88j61klr ON public."Domain" USING btree (deleti
|
||||||
CREATE INDEX idx5yfbr88439pxw0v3j86c74fp8 ON public."BillingEvent" USING btree (event_time);
|
CREATE INDEX idx5yfbr88439pxw0v3j86c74fp8 ON public."BillingEvent" USING btree (event_time);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idx67qwkjtlq5q8dv6egtrtnhqi7; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idx67qwkjtlq5q8dv6egtrtnhqi7 ON public."HostHistory" USING btree (history_modification_time);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idx6py6ocrab0ivr76srcd2okpnq; Type: INDEX; Schema: public; Owner: -
|
-- Name: idx6py6ocrab0ivr76srcd2okpnq; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -941,6 +1006,13 @@ CREATE INDEX idxe7wu46c7wpvfmfnj4565abibp ON public."PollMessage" USING btree (r
|
||||||
CREATE INDEX idxeokttmxtpq2hohcioe5t2242b ON public."BillingCancellation" USING btree (registrar_id);
|
CREATE INDEX idxeokttmxtpq2hohcioe5t2242b ON public."BillingCancellation" USING btree (registrar_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxfg2nnjlujxo6cb9fha971bq2n; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxfg2nnjlujxo6cb9fha971bq2n ON public."HostHistory" USING btree (creation_time);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idxhmv411mdqo5ibn4vy7ykxpmlv; Type: INDEX; Schema: public; Owner: -
|
-- Name: idxhmv411mdqo5ibn4vy7ykxpmlv; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -948,6 +1020,13 @@ CREATE INDEX idxeokttmxtpq2hohcioe5t2242b ON public."BillingCancellation" USING
|
||||||
CREATE INDEX idxhmv411mdqo5ibn4vy7ykxpmlv ON public."BillingEvent" USING btree (allocation_token_id);
|
CREATE INDEX idxhmv411mdqo5ibn4vy7ykxpmlv ON public."BillingEvent" USING btree (allocation_token_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxj77pfwhui9f0i7wjq6lmibovj; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxj77pfwhui9f0i7wjq6lmibovj ON public."HostHistory" USING btree (fully_qualified_host_name);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idxjny8wuot75b5e6p38r47wdawu; Type: INDEX; Schema: public; Owner: -
|
-- Name: idxjny8wuot75b5e6p38r47wdawu; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -962,6 +1041,13 @@ CREATE INDEX idxjny8wuot75b5e6p38r47wdawu ON public."BillingRecurrence" USING bt
|
||||||
CREATE INDEX idxkjt9yaq92876dstimd93hwckh ON public."Domain" USING btree (current_sponsor_registrar_id);
|
CREATE INDEX idxkjt9yaq92876dstimd93hwckh ON public."Domain" USING btree (current_sponsor_registrar_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: idxknk8gmj7s47q56cwpa6rmpt5l; Type: INDEX; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
CREATE INDEX idxknk8gmj7s47q56cwpa6rmpt5l ON public."HostHistory" USING btree (history_type);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: idxn1f711wicdnooa2mqb7g1m55o; Type: INDEX; Schema: public; Owner: -
|
-- Name: idxn1f711wicdnooa2mqb7g1m55o; Type: INDEX; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -1071,6 +1157,14 @@ ALTER TABLE ONLY public."Domain"
|
||||||
ADD CONSTRAINT fk2u3srsfbei272093m3b3xwj23 FOREIGN KEY (current_sponsor_registrar_id) REFERENCES public."Registrar"(registrar_id);
|
ADD CONSTRAINT fk2u3srsfbei272093m3b3xwj23 FOREIGN KEY (current_sponsor_registrar_id) REFERENCES public."Registrar"(registrar_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: HostHistory fk3d09knnmxrt6iniwnp8j2ykga; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."HostHistory"
|
||||||
|
ADD CONSTRAINT fk3d09knnmxrt6iniwnp8j2ykga FOREIGN KEY (history_registrar_id) REFERENCES public."Registrar"(registrar_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: ClaimsEntry fk6sc6at5hedffc0nhdcab6ivuq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
-- Name: ClaimsEntry fk6sc6at5hedffc0nhdcab6ivuq; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
@ -1239,6 +1333,14 @@ ALTER TABLE ONLY public."HostResource"
|
||||||
ADD CONSTRAINT fk_host_resource_superordinate_domain FOREIGN KEY (superordinate_domain) REFERENCES public."Domain"(repo_id);
|
ADD CONSTRAINT fk_host_resource_superordinate_domain FOREIGN KEY (superordinate_domain) REFERENCES public."Domain"(repo_id);
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Name: HostHistory fk_hosthistory_hostresource; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
|
--
|
||||||
|
|
||||||
|
ALTER TABLE ONLY public."HostHistory"
|
||||||
|
ADD CONSTRAINT fk_hosthistory_hostresource FOREIGN KEY (host_repo_id) REFERENCES public."HostResource"(repo_id);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Name: PollMessage fk_poll_message_contact_repo_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
-- Name: PollMessage fk_poll_message_contact_repo_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||||
--
|
--
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue