diff --git a/core/src/main/java/google/registry/model/reporting/Spec11ThreatMatchDao.java b/core/src/main/java/google/registry/model/reporting/Spec11ThreatMatchDao.java index 29f2c2498..e48285cb6 100644 --- a/core/src/main/java/google/registry/model/reporting/Spec11ThreatMatchDao.java +++ b/core/src/main/java/google/registry/model/reporting/Spec11ThreatMatchDao.java @@ -21,10 +21,10 @@ import javax.persistence.TemporalType; import org.joda.time.LocalDate; /** - * Data access object for {@link google.registry.model.reporting.Spec11ThreatMatch}. + * Data access object for {@link Spec11ThreatMatch}. * - *

A JpaTransactionManager is passed into each static method because they are called from a BEAM - * pipeline and we don't know where it's coming from. + *

The transaction manager is passed as a parameter because this could be called either from a + * BEAM pipeline or standard non-BEAM code. */ public class Spec11ThreatMatchDao { diff --git a/core/src/main/java/google/registry/reporting/spec11/Spec11RegistrarThreatMatchesParser.java b/core/src/main/java/google/registry/reporting/spec11/Spec11RegistrarThreatMatchesParser.java index b99de5bcb..474f1a7b2 100644 --- a/core/src/main/java/google/registry/reporting/spec11/Spec11RegistrarThreatMatchesParser.java +++ b/core/src/main/java/google/registry/reporting/spec11/Spec11RegistrarThreatMatchesParser.java @@ -14,9 +14,11 @@ package google.registry.reporting.spec11; +import static com.google.common.collect.ImmutableSet.toImmutableSet; import static java.nio.charset.StandardCharsets.UTF_8; import com.google.appengine.tools.cloudstorage.GcsFilename; +import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.flogger.FluentLogger; @@ -59,6 +61,25 @@ public class Spec11RegistrarThreatMatchesParser { return getFromFile(getGcsFilename(date)); } + /** Returns registrar:set-of-threat-match pairings from the file, or empty if it doesn't exist. */ + public ImmutableSet getFromFile(GcsFilename spec11ReportFilename) + throws IOException { + if (!gcsUtils.existsAndNotEmpty(spec11ReportFilename)) { + return ImmutableSet.of(); + } + ImmutableSet.Builder builder = ImmutableSet.builder(); + try (InputStream in = gcsUtils.openInputStream(spec11ReportFilename); + InputStreamReader isr = new InputStreamReader(in, UTF_8)) { + // Skip the header at line 0 + return Splitter.on("\n") + .omitEmptyStrings() + .splitToStream(CharStreams.toString(isr)) + .skip(1) + .map(this::parseRegistrarThreatMatch) + .collect(toImmutableSet()); + } + } + public Optional getPreviousDateWithMatches(LocalDate date) { LocalDate yesterday = date.minusDays(1); GcsFilename gcsFilename = getGcsFilename(yesterday); @@ -82,20 +103,6 @@ public class Spec11RegistrarThreatMatchesParser { return new GcsFilename(reportingBucket, Spec11Pipeline.getSpec11ReportFilePath(localDate)); } - private ImmutableSet getFromFile(GcsFilename spec11ReportFilename) - throws IOException, JSONException { - ImmutableSet.Builder builder = ImmutableSet.builder(); - try (InputStream in = gcsUtils.openInputStream(spec11ReportFilename)) { - ImmutableList reportLines = - ImmutableList.copyOf(CharStreams.toString(new InputStreamReader(in, UTF_8)).split("\n")); - // Iterate from 1 to size() to skip the header at line 0. - for (int i = 1; i < reportLines.size(); i++) { - builder.add(parseRegistrarThreatMatch(reportLines.get(i))); - } - return builder.build(); - } - } - private RegistrarThreatMatches parseRegistrarThreatMatch(String line) throws JSONException { JSONObject reportJSON = new JSONObject(line); String clientId = reportJSON.getString(Spec11Pipeline.REGISTRAR_CLIENT_ID_FIELD); diff --git a/core/src/main/java/google/registry/tools/RegistryTool.java b/core/src/main/java/google/registry/tools/RegistryTool.java index 08000e671..a96cc5205 100644 --- a/core/src/main/java/google/registry/tools/RegistryTool.java +++ b/core/src/main/java/google/registry/tools/RegistryTool.java @@ -16,6 +16,7 @@ package google.registry.tools; import com.google.common.collect.ImmutableMap; import google.registry.tools.javascrap.BackfillRegistryLocksCommand; +import google.registry.tools.javascrap.BackfillSpec11ThreatMatchesCommand; import google.registry.tools.javascrap.PopulateNullRegistrarFieldsCommand; import google.registry.tools.javascrap.RemoveIpAddressCommand; @@ -32,6 +33,7 @@ public final class RegistryTool { new ImmutableMap.Builder>() .put("ack_poll_messages", AckPollMessagesCommand.class) .put("backfill_registry_locks", BackfillRegistryLocksCommand.class) + .put("backfill_spec11_threat_matches", BackfillSpec11ThreatMatchesCommand.class) .put("canonicalize_labels", CanonicalizeLabelsCommand.class) .put("check_domain", CheckDomainCommand.class) .put("check_domain_claims", CheckDomainClaimsCommand.class) diff --git a/core/src/main/java/google/registry/tools/javascrap/BackfillSpec11ThreatMatchesCommand.java b/core/src/main/java/google/registry/tools/javascrap/BackfillSpec11ThreatMatchesCommand.java new file mode 100644 index 000000000..0b2d8b8d0 --- /dev/null +++ b/core/src/main/java/google/registry/tools/javascrap/BackfillSpec11ThreatMatchesCommand.java @@ -0,0 +1,216 @@ +// 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.tools.javascrap; + +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.ImmutableListMultimap.flatteningToImmutableListMultimap; +import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableSet; +import google.registry.beam.spec11.ThreatMatch; +import google.registry.model.domain.DomainBase; +import google.registry.model.reporting.Spec11ThreatMatch; +import google.registry.model.reporting.Spec11ThreatMatch.ThreatType; +import google.registry.model.reporting.Spec11ThreatMatchDao; +import google.registry.reporting.spec11.RegistrarThreatMatches; +import google.registry.reporting.spec11.Spec11RegistrarThreatMatchesParser; +import google.registry.tools.CommandWithRemoteApi; +import google.registry.tools.ConfirmingCommand; +import google.registry.util.Clock; +import java.io.IOException; +import java.util.Comparator; +import java.util.List; +import java.util.function.Function; +import javax.inject.Inject; +import org.joda.time.LocalDate; + +/** + * Scrap tool to backfill {@link Spec11ThreatMatch} objects from prior days. + * + *

This will load the previously-existing Spec11 files from GCS (looking back to 2019-01-01 (a + * rough estimate of when we started using this format) and convert those RegistrarThreatMatches + * objects into the new Spec11ThreatMatch format. It will then insert these entries into SQL. + * + *

Note that the script will attempt to find the corresponding {@link DomainBase} object for each + * domain name on the day of the scan. It will fail if it cannot find a corresponding domain object, + * or if the domain objects were not active at the time of the scan. + */ +@Parameters( + commandDescription = + "Backfills Spec11 threat match entries from the old and deprecated GCS JSON files to the " + + "Cloud SQL database.") +public class BackfillSpec11ThreatMatchesCommand extends ConfirmingCommand + implements CommandWithRemoteApi { + + private static final LocalDate START_DATE = new LocalDate(2019, 1, 1); + + @Parameter( + names = {"-o", "--overwrite_existing_dates"}, + description = + "Whether the command will overwrite data that already exists for dates that exist in the " + + "GCS bucket. Defaults to false.") + private boolean overrideExistingDates; + + @Inject Spec11RegistrarThreatMatchesParser threatMatchesParser; + // Inject the clock for testing purposes + @Inject Clock clock; + + @Override + protected String prompt() { + return String.format("Backfill Spec11 results from %d files?", getDatesToBackfill().size()); + } + + @Override + protected String execute() { + ImmutableList dates = getDatesToBackfill(); + ImmutableListMultimap.Builder threatMatchesBuilder = + new ImmutableListMultimap.Builder<>(); + for (LocalDate date : dates) { + try { + // It's OK if the file doesn't exist for a particular date; the result will be empty. + threatMatchesBuilder.putAll(date, threatMatchesParser.getRegistrarThreatMatches(date)); + } catch (IOException e) { + throw new RuntimeException( + String.format("Error parsing through file with date %s.", date), e); + } + } + ImmutableListMultimap threatMatches = + threatMatchesBuilder.build(); + // Look up all possible DomainBases for these domain names, any of which can be in the past + ImmutableListMultimap domainsByDomainName = + getDomainsByDomainName(threatMatches); + + // For each date, convert all threat matches with the proper domain repo ID + int totalNumThreats = 0; + for (LocalDate date : threatMatches.keySet()) { + ImmutableList.Builder spec11ThreatsBuilder = new ImmutableList.Builder<>(); + for (RegistrarThreatMatches rtm : threatMatches.get(date)) { + rtm.threatMatches().stream() + .map( + threatMatch -> + threatMatchToCloudSqlObject( + threatMatch, date, rtm.clientId(), domainsByDomainName)) + .forEach(spec11ThreatsBuilder::add); + } + ImmutableList spec11Threats = spec11ThreatsBuilder.build(); + jpaTm() + .transact( + () -> { + Spec11ThreatMatchDao.deleteEntriesByDate(jpaTm(), date); + jpaTm().putAll(spec11Threats); + }); + totalNumThreats += spec11Threats.size(); + } + return String.format( + "Successfully parsed through %d files with %d threats.", dates.size(), totalNumThreats); + } + + /** Returns a per-domain list of possible DomainBase objects, starting with the most recent. */ + private ImmutableListMultimap getDomainsByDomainName( + ImmutableListMultimap threatMatchesByDate) { + return threatMatchesByDate.values().stream() + .map(RegistrarThreatMatches::threatMatches) + .flatMap(ImmutableList::stream) + .map(ThreatMatch::fullyQualifiedDomainName) + .distinct() + .collect( + flatteningToImmutableListMultimap( + Function.identity(), + (domainName) -> { + List domains = + ofy() + .load() + .type(DomainBase.class) + .filter("fullyQualifiedDomainName", domainName) + .list(); + domains.sort(Comparator.comparing(DomainBase::getCreationTime).reversed()); + checkState( + !domains.isEmpty(), + "Domain name %s had no associated DomainBase objects.", + domainName); + return domains.stream(); + })); + } + + /** Converts the previous {@link ThreatMatch} object to {@link Spec11ThreatMatch}. */ + private Spec11ThreatMatch threatMatchToCloudSqlObject( + ThreatMatch threatMatch, + LocalDate date, + String registrarId, + ImmutableListMultimap domainsByDomainName) { + DomainBase domain = + findDomainAsOfDateOrThrow( + threatMatch.fullyQualifiedDomainName(), date, domainsByDomainName); + return new Spec11ThreatMatch.Builder() + .setThreatTypes(ImmutableSet.of(ThreatType.valueOf(threatMatch.threatType()))) + .setCheckDate(date) + .setRegistrarId(registrarId) + .setDomainName(threatMatch.fullyQualifiedDomainName()) + .setDomainRepoId(domain.getRepoId()) + .build(); + } + + /** Returns the DomainBase object as of the particular date, which is likely in the past. */ + private DomainBase findDomainAsOfDateOrThrow( + String domainName, + LocalDate date, + ImmutableListMultimap domainsByDomainName) { + ImmutableList domains = domainsByDomainName.get(domainName); + for (DomainBase domain : domains) { + // We only know the date (not datetime) of the threat scan, so we approximate + LocalDate creationDate = domain.getCreationTime().toLocalDate(); + LocalDate deletionDate = domain.getDeletionTime().toLocalDate(); + if (!date.isBefore(creationDate) && !date.isAfter(deletionDate)) { + return domain; + } + } + throw new IllegalStateException( + String.format("Could not find a DomainBase valid for %s on day %s.", domainName, date)); + } + + /** Returns the list of dates between {@link #START_DATE} and now (UTC), inclusive. */ + private ImmutableList getDatesToBackfill() { + ImmutableSet datesToSkip = + overrideExistingDates ? ImmutableSet.of() : getExistingDates(); + ImmutableList.Builder result = new ImmutableList.Builder<>(); + LocalDate endDate = clock.nowUtc().toLocalDate(); + for (LocalDate currentDate = START_DATE; + !currentDate.isAfter(endDate); + currentDate = currentDate.plusDays(1)) { + if (!datesToSkip.contains(currentDate)) { + result.add(currentDate); + } + } + return result.build(); + } + + private ImmutableSet getExistingDates() { + return jpaTm() + .transact( + () -> + jpaTm() + .getEntityManager() + .createQuery( + "SELECT DISTINCT stm.checkDate FROM Spec11ThreatMatch stm", LocalDate.class) + .getResultStream() + .collect(toImmutableSet())); + } +} diff --git a/core/src/test/java/google/registry/reporting/spec11/Spec11RegistrarThreatMatchesParserTest.java b/core/src/test/java/google/registry/reporting/spec11/Spec11RegistrarThreatMatchesParserTest.java index 9f68ba30b..4d7136646 100644 --- a/core/src/test/java/google/registry/reporting/spec11/Spec11RegistrarThreatMatchesParserTest.java +++ b/core/src/test/java/google/registry/reporting/spec11/Spec11RegistrarThreatMatchesParserTest.java @@ -34,7 +34,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; /** Unit tests for {@link Spec11RegistrarThreatMatchesParser}. */ -class Spec11RegistrarThreatMatchesParserTest { +public class Spec11RegistrarThreatMatchesParserTest { private static final String TODAY = "2018-07-21"; private static final String YESTERDAY = "2018-07-20"; @@ -66,6 +66,12 @@ class Spec11RegistrarThreatMatchesParserTest { assertThat(parser.getPreviousDateWithMatches(LocalDate.parse(TODAY))).isEmpty(); } + @Test + void testNonexistent_returnsEmpty() throws Exception { + assertThat(parser.getRegistrarThreatMatches(LocalDate.parse(YESTERDAY).minusYears(1))) + .isEmpty(); + } + @Test void testFindPrevious_olderThanYesterdayFound() throws Exception { setupFile("spec11_fake_report_previous_day", "2018-07-14"); @@ -95,7 +101,7 @@ class Spec11RegistrarThreatMatchesParserTest { } /** The expected contents of the sample spec11 report file */ - static ImmutableSet sampleThreatMatches() throws Exception { + public static ImmutableSet sampleThreatMatches() throws Exception { return ImmutableSet.of(getMatchA(), getMatchB()); } diff --git a/core/src/test/java/google/registry/tools/javascrap/BackfillSpec11ThreatMatchesCommandTest.java b/core/src/test/java/google/registry/tools/javascrap/BackfillSpec11ThreatMatchesCommandTest.java new file mode 100644 index 000000000..e0b0a4052 --- /dev/null +++ b/core/src/test/java/google/registry/tools/javascrap/BackfillSpec11ThreatMatchesCommandTest.java @@ -0,0 +1,271 @@ +// 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.tools.javascrap; + +import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; +import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence; +import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; +import static google.registry.reporting.spec11.Spec11RegistrarThreatMatchesParserTest.sampleThreatMatches; +import static google.registry.testing.DatabaseHelper.createTld; +import static google.registry.testing.DatabaseHelper.deleteResource; +import static google.registry.testing.DatabaseHelper.newDomainBase; +import static google.registry.testing.DatabaseHelper.persistActiveDomain; +import static google.registry.testing.DatabaseHelper.persistResource; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Iterables; +import google.registry.model.domain.DomainBase; +import google.registry.model.reporting.Spec11ThreatMatch; +import google.registry.model.reporting.Spec11ThreatMatch.ThreatType; +import google.registry.reporting.spec11.Spec11RegistrarThreatMatchesParser; +import google.registry.tools.CommandTestCase; +import java.io.IOException; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +/** Tests for {@link BackfillSpec11ThreatMatchesCommand}. */ +public class BackfillSpec11ThreatMatchesCommandTest + extends CommandTestCase { + + private static final LocalDate CURRENT_DATE = DateTime.parse("2020-11-22").toLocalDate(); + private final Spec11RegistrarThreatMatchesParser threatMatchesParser = + mock(Spec11RegistrarThreatMatchesParser.class); + + private DomainBase domainA; + + @BeforeEach + void beforeEach() throws Exception { + createTld("com"); + domainA = persistActiveDomain("a.com"); + persistActiveDomain("b.com"); + persistActiveDomain("c.com"); + fakeClock.setTo(CURRENT_DATE.toDateTimeAtStartOfDay()); + command.threatMatchesParser = threatMatchesParser; + command.clock = fakeClock; + when(threatMatchesParser.getRegistrarThreatMatches(any(LocalDate.class))) + .thenReturn(ImmutableSet.of()); + } + + @Test + void testSuccess_singleFile() throws Exception { + when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) + .thenReturn(sampleThreatMatches()); + runCommandForced(); + assertInStdout("Backfill Spec11 results from 692 files?"); + assertInStdout("Successfully parsed through 692 files with 3 threats."); + verifyExactlyThreeEntriesInDbFromLastDay(); + } + + @Test + void testSuccess_sameDomain_multipleDays() throws Exception { + // If the same domains show up on multiple days, there should be multiple entries for them + when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) + .thenReturn(sampleThreatMatches()); + when(threatMatchesParser.getRegistrarThreatMatches(LocalDate.parse("2019-01-01"))) + .thenReturn(sampleThreatMatches()); + runCommandForced(); + assertInStdout("Backfill Spec11 results from 692 files?"); + assertInStdout("Successfully parsed through 692 files with 6 threats."); + jpaTm() + .transact( + () -> { + ImmutableList threatMatches = + jpaTm().loadAll(Spec11ThreatMatch.class); + assertThat(threatMatches).hasSize(6); + assertThat( + threatMatches.stream() + .map(Spec11ThreatMatch::getDomainName) + .collect(toImmutableSet())) + .containsExactly("a.com", "b.com", "c.com"); + assertThat( + threatMatches.stream() + .map(Spec11ThreatMatch::getCheckDate) + .collect(toImmutableSet())) + .containsExactly(CURRENT_DATE, LocalDate.parse("2019-01-01")); + }); + } + + @Test + void testSuccess_empty() throws Exception { + runCommandForced(); + assertInStdout("Backfill Spec11 results from 692 files?"); + assertInStdout("Successfully parsed through 692 files with 0 threats."); + } + + @Test + void testSuccess_sameDayTwice() throws Exception { + when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) + .thenReturn(sampleThreatMatches()); + runCommandForced(); + runCommandForced(); + verifyExactlyThreeEntriesInDbFromLastDay(); + } + + @Test + void testSuccess_threeDomainsForDomainName() throws Exception { + // We should use the repo ID from the proper DomainBase object at the scan's point in time. + // First, domain was created at START_OF_TIME and deleted one year ago + DateTime now = fakeClock.nowUtc(); + domainA = persistResource(domainA.asBuilder().setDeletionTime(now.minusYears(1)).build()); + + // Next, domain was created six months ago and deleted two months ago + DomainBase secondSave = + persistResource( + newDomainBase("a.com") + .asBuilder() + .setCreationTimeForTest(now.minusMonths(6)) + .setDeletionTime(now.minusMonths(2)) + .build()); + + // Lastly, domain was created one month ago and is still valid + DomainBase thirdSave = + persistResource( + newDomainBase("a.com").asBuilder().setCreationTimeForTest(now.minusMonths(1)).build()); + + // If the scan result was from three months ago, we should use the second save + when(threatMatchesParser.getRegistrarThreatMatches(now.toLocalDate().minusMonths(3))) + .thenReturn(sampleThreatMatches()); + runCommandForced(); + String threatMatchRepoId = + jpaTm() + .transact( + () -> + jpaTm().loadAll(Spec11ThreatMatch.class).stream() + .filter((match) -> match.getDomainName().equals("a.com")) + .findFirst() + .get() + .getDomainRepoId()); + assertThat(threatMatchRepoId).isNotEqualTo(domainA.getRepoId()); + assertThat(threatMatchRepoId).isEqualTo(secondSave.getRepoId()); + assertThat(threatMatchRepoId).isNotEqualTo(thirdSave.getRepoId()); + } + + @Test + void testSuccess_skipsExistingDatesWithoutOverwrite() throws Exception { + when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) + .thenReturn(sampleThreatMatches()); + Spec11ThreatMatch previous = + new Spec11ThreatMatch.Builder() + .setCheckDate(CURRENT_DATE) + .setDomainName("previous.tld") + .setDomainRepoId("1-DOMAIN") + .setRegistrarId("TheRegistrar") + .setThreatTypes(ImmutableSet.of(ThreatType.MALWARE)) + .build(); + jpaTm().transact(() -> jpaTm().put(previous)); + + runCommandForced(); + ImmutableList threatMatches = + jpaTm().transact(() -> jpaTm().loadAll(Spec11ThreatMatch.class)); + assertAboutImmutableObjects() + .that(Iterables.getOnlyElement(threatMatches)) + .isEqualExceptFields(previous, "id"); + } + + @Test + void testSuccess_overwritesExistingDatesWhenSpecified() throws Exception { + when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) + .thenReturn(sampleThreatMatches()); + Spec11ThreatMatch previous = + new Spec11ThreatMatch.Builder() + .setCheckDate(CURRENT_DATE) + .setDomainName("previous.tld") + .setDomainRepoId("1-DOMAIN") + .setRegistrarId("TheRegistrar") + .setThreatTypes(ImmutableSet.of(ThreatType.MALWARE)) + .build(); + jpaTm().transact(() -> jpaTm().put(previous)); + + runCommandForced("--overwrite_existing_dates"); + verifyExactlyThreeEntriesInDbFromLastDay(); + } + + @Test + void testFailure_oneFileFails() throws Exception { + // If there are any exceptions, we should fail loud and fast + when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) + .thenReturn(sampleThreatMatches()); + when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE.minusDays(1))) + .thenThrow(new IOException("hi")); + RuntimeException runtimeException = + assertThrows(RuntimeException.class, this::runCommandForced); + assertThat(runtimeException.getCause().getClass()).isEqualTo(IOException.class); + assertThat(runtimeException).hasCauseThat().hasMessageThat().isEqualTo("hi"); + jpaTm().transact(() -> assertThat(jpaTm().loadAll(Spec11ThreatMatch.class)).isEmpty()); + } + + @Test + void testFailure_noDomainForDomainName() throws Exception { + deleteResource(domainA); + when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) + .thenReturn(sampleThreatMatches()); + assertThat(assertThrows(IllegalStateException.class, this::runCommandForced)) + .hasMessageThat() + .isEqualTo("Domain name a.com had no associated DomainBase objects."); + } + + @Test + void testFailure_noDomainAtTimeOfScan() throws Exception { + // If the domain existed at some point(s) in time but not the time of the scan, fail. + // First, domain was created at START_OF_TIME and deleted one year ago + DateTime now = fakeClock.nowUtc(); + domainA = persistResource(domainA.asBuilder().setDeletionTime(now.minusYears(1)).build()); + + // Second, domain was created one month ago and is still valid + persistResource( + newDomainBase("a.com").asBuilder().setCreationTimeForTest(now.minusMonths(1)).build()); + + // If we have a result for this domain from 3 months ago when it didn't exist, fail. + when(threatMatchesParser.getRegistrarThreatMatches(now.toLocalDate().minusMonths(3))) + .thenReturn(sampleThreatMatches()); + assertThat(assertThrows(IllegalStateException.class, this::runCommandForced)) + .hasMessageThat() + .isEqualTo("Could not find a DomainBase valid for a.com on day 2020-08-22."); + } + + private void verifyExactlyThreeEntriesInDbFromLastDay() { + jpaTm() + .transact( + () -> { + ImmutableList threatMatches = + jpaTm().loadAll(Spec11ThreatMatch.class); + assertThat(threatMatches) + .comparingElementsUsing(immutableObjectCorrespondence("id", "domainRepoId")) + .containsExactly( + expectedThreatMatch("TheRegistrar", "a.com"), + expectedThreatMatch("NewRegistrar", "b.com"), + expectedThreatMatch("NewRegistrar", "c.com")); + }); + } + + private Spec11ThreatMatch expectedThreatMatch(String registrarId, String domainName) { + return new Spec11ThreatMatch.Builder() + .setDomainRepoId("ignored") + .setDomainName(domainName) + .setRegistrarId(registrarId) + .setCheckDate(CURRENT_DATE) + .setThreatTypes(ImmutableSet.of(ThreatType.MALWARE)) + .build(); + } +} diff --git a/db/src/main/resources/sql/er_diagram/brief_er_diagram.html b/db/src/main/resources/sql/er_diagram/brief_er_diagram.html index a17aa9e29..52dd59ba8 100644 --- a/db/src/main/resources/sql/er_diagram/brief_er_diagram.html +++ b/db/src/main/resources/sql/er_diagram/brief_er_diagram.html @@ -261,19 +261,19 @@ td.section { generated on - 2020-11-30 21:59:21.319302 + 2020-12-05 00:29:03.934355 last flyway file - V80__defer_bill_event_key.sql + V81__drop_spec11_fkeys.sql

 

 

- + SchemaCrawler_Diagram - + generated by @@ -284,2823 +284,2776 @@ td.section { generated on - 2020-11-30 21:59:21.319302 + 2020-12-05 00:29:03.934355 allocationtoken_a08ccbef - - + + public.AllocationToken - - + + [table] - + token - + - + text not null - + domain_name - + - + text - + billingevent_a57d1815 - - + + public.BillingEvent - - + + [table] - + billing_event_id - + - + int8 not null - + registrar_id - + - + text not null - + domain_history_revision_id - + - + int8 not null - + domain_repo_id - + - + text not null - + event_time - + - + timestamptz not null - + allocation_token - + - + text - + billing_time - + - + timestamptz - + cancellation_matching_billing_recurrence_id - + - + int8 - + synthetic_creation_time - + - + timestamptz - + billingevent_a57d1815:w->allocationtoken_a08ccbef:e - - - - - - - - + + + + + + + + fk_billing_event_allocation_token billingrecurrence_5fa2cb01 - - + + public.BillingRecurrence - - + + [table] - + billing_recurrence_id - + - + int8 not null - + registrar_id - + - + text not null - + domain_history_revision_id - + - + int8 not null - + domain_repo_id - + - + text not null - + event_time - + - + timestamptz not null - + recurrence_end_time - + - + timestamptz - + recurrence_time_of_year - + - + text - + billingevent_a57d1815:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_billing_event_cancellation_matching_billing_recurrence_id domainhistory_a54cc226 - - + + public.DomainHistory - - + + [table] - + history_revision_id - + - + int8 not null - + history_registrar_id - + - + text - + history_modification_time - + - + timestamptz not null - + history_type - + - + text not null - + creation_time - + - + timestamptz - + domain_repo_id - + - + text not null - + + + + billingevent_a57d1815:w->domainhistory_a54cc226:e + + + + + + + + + fk_billing_event_domain_history + billingevent_a57d1815:w->domainhistory_a54cc226:e - - - - - - - - - fk_billing_event_domain_history - - - - billingevent_a57d1815:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk_billing_event_domain_history - + registrar_6e1503e3 - - + + public.Registrar - - + + [table] - + registrar_id - + - + text not null - + iana_identifier - + - + int8 - + registrar_name - + - + text not null - + - + billingevent_a57d1815:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_billing_event_registrar_id billingcancellation_6eedf614 - - + + public.BillingCancellation - - + + [table] - + billing_cancellation_id - + - + int8 not null - + registrar_id - + - + text not null - + domain_history_revision_id - + - + int8 not null - + domain_repo_id - + - + text not null - + event_time - + - + timestamptz not null - + billing_time - + - + timestamptz - + billing_event_id - + - + int8 - + billing_recurrence_id - + - + int8 - + billingcancellation_6eedf614:w->billingevent_a57d1815:e - - - - - - - - + + + + + + + + fk_billing_cancellation_billing_event_id billingcancellation_6eedf614:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_billing_cancellation_billing_recurrence_id + + billingcancellation_6eedf614:w->domainhistory_a54cc226:e + + + + + + + + + fk_billing_cancellation_domain_history + + billingcancellation_6eedf614:w->domainhistory_a54cc226:e - - - - - - - - - fk_billing_cancellation_domain_history - - - - billingcancellation_6eedf614:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk_billing_cancellation_domain_history - + billingcancellation_6eedf614:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_billing_cancellation_registrar_id domain_6c51cffa - - + + public.Domain - - + + [table] - + repo_id - + - + text not null - + 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 - + domain_name - + - + text - + tld - + - + text - + admin_contact - + - + text - + billing_contact - + - + text - + registrant_contact - + - + text - + tech_contact - + - + text - + transfer_billing_cancellation_id - + - + int8 - + transfer_billing_event_id - + - + int8 - + transfer_billing_recurrence_id - + - + int8 - + transfer_gaining_registrar_id - + - + text - + transfer_losing_registrar_id - + - + text - + billing_recurrence_id - + - + int8 - + autorenew_end_time - + - + timestamptz - + domain_6c51cffa:w->billingevent_a57d1815:e - - - - - - - - + + + + + + + + fk_domain_transfer_billing_event_id domain_6c51cffa:w->billingcancellation_6eedf614:e - - - - - - - - + + + + + + + + fk_domain_transfer_billing_cancellation_id domain_6c51cffa:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_domain_billing_recurrence_id domain_6c51cffa:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_domain_transfer_billing_recurrence_id contact_8de8cb16 - - + + public.Contact - - + + [table] - + repo_id - + - + text not null - + 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 - + contact_id - + - + text - + search_name - + - + text - + transfer_gaining_registrar_id - + - + text - + transfer_losing_registrar_id - + - + text - + domain_6c51cffa:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_domain_admin_contact domain_6c51cffa:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_domain_billing_contact domain_6c51cffa:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_domain_registrant_contact domain_6c51cffa:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_domain_tech_contact + + domain_6c51cffa:w->registrar_6e1503e3:e + + + + + + + + + fk2jc69qyg2tv9hhnmif6oa1cx1 + + domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - - fk2jc69qyg2tv9hhnmif6oa1cx1 + + + + + + + + + fk2u3srsfbei272093m3b3xwj23 domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - - fk2u3srsfbei272093m3b3xwj23 + + + + + + + + + fkjc0r9r5y1lfbt4gpbqw4wsuvq domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - - fkjc0r9r5y1lfbt4gpbqw4wsuvq + + + + + + + + + fk_domain_transfer_gaining_registrar_id domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - - fk_domain_transfer_gaining_registrar_id - - - - domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_domain_transfer_losing_registrar_id tld_f1fa57e2 - - + + public.Tld - - + + [table] - + tld_name - + - + text not null - + - + domain_6c51cffa:w->tld_f1fa57e2:e - - - - - - - - + + + + + + + + fk_domain_tld graceperiod_cd3b2e8f - - + + public.GracePeriod - - + + [table] - + grace_period_id - + - + int8 not null - + billing_event_id - + - + int8 - + billing_recurrence_id - + - + int8 - + registrar_id - + - + text not null - + domain_repo_id - + - + text not null - + graceperiod_cd3b2e8f:w->billingevent_a57d1815:e - - - - - - - - + + + + + + + + fk_grace_period_billing_event_id graceperiod_cd3b2e8f:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fk_grace_period_domain_repo_id graceperiod_cd3b2e8f:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_grace_period_billing_recurrence_id - + graceperiod_cd3b2e8f:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_grace_period_registrar_id + + billingrecurrence_5fa2cb01:w->domainhistory_a54cc226:e + + + + + + + + + fk_billing_recurrence_domain_history + + billingrecurrence_5fa2cb01:w->domainhistory_a54cc226:e - - - - - - - - - fk_billing_recurrence_domain_history - - - - billingrecurrence_5fa2cb01:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk_billing_recurrence_domain_history - + billingrecurrence_5fa2cb01:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_billing_recurrence_registrar_id claimsentry_105da9f1 - - + + public.ClaimsEntry - - + + [table] - + revision_id - + - + int8 not null - + domain_label - + - + text not null - + claimslist_3d49bc2b - - + + public.ClaimsList - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + claimsentry_105da9f1:w->claimslist_3d49bc2b:e - - - - - - - - + + + + + + + + fk6sc6at5hedffc0nhdcab6ivuq + + contact_8de8cb16:w->registrar_6e1503e3:e + + + + + + + + + fk1sfyj7o7954prbn1exk7lpnoe + + contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - - fk1sfyj7o7954prbn1exk7lpnoe + + + + + + + + + fk93c185fx7chn68uv7nl6uv2s0 contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - - fk93c185fx7chn68uv7nl6uv2s0 + + + + + + + + + fkmb7tdiv85863134w1wogtxrb2 contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - - fkmb7tdiv85863134w1wogtxrb2 + + + + + + + + + fk_contact_transfer_gaining_registrar_id contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - - fk_contact_transfer_gaining_registrar_id - - - - contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_contact_transfer_losing_registrar_id contacthistory_d2964f8a - - + + public.ContactHistory - - + + [table] - + history_revision_id - + - + int8 not null - + history_registrar_id - + - + text - + history_modification_time - + - + timestamptz not null - + history_type - + - + text not null - + creation_time - + - + timestamptz - + contact_repo_id - + - + text not null - + contacthistory_d2964f8a:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_contact_history_contact_repo_id - + contacthistory_d2964f8a:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_contact_history_registrar_id pollmessage_614a523e - - + + public.PollMessage - - + + [table] - + poll_message_id - + - + int8 not null - + registrar_id - + - + text not null - + contact_repo_id - + - + text - + contact_history_revision_id - + - + int8 - + domain_repo_id - + - + text - + domain_history_revision_id - + - + int8 - + event_time - + - + timestamptz not null - + host_repo_id - + - + text - + host_history_revision_id - + - + int8 - + transfer_response_gaining_registrar_id - + - + text - + transfer_response_losing_registrar_id - + - + text - + pollmessage_614a523e:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fk_poll_message_domain_repo_id pollmessage_614a523e:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_poll_message_contact_repo_id pollmessage_614a523e:w->contacthistory_d2964f8a:e - - - - - - - - + + + + + + + + fk_poll_message_contact_history pollmessage_614a523e:w->contacthistory_d2964f8a:e - - - - - - - - + + + + + + + + fk_poll_message_contact_history + + pollmessage_614a523e:w->domainhistory_a54cc226:e + + + + + + + + + fk_poll_message_domain_history + + pollmessage_614a523e:w->domainhistory_a54cc226:e - - - - - - - - - fk_poll_message_domain_history - - - - pollmessage_614a523e:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk_poll_message_domain_history host_f21b78de - - + + public.Host - - + + [table] - + repo_id - + - + text not null - + creation_registrar_id - + - + text - + current_sponsor_registrar_id - + - + text - + last_epp_update_registrar_id - + - + text - + superordinate_domain - + - + text - + - + pollmessage_614a523e:w->host_f21b78de:e - - - - - - - - + + + + + + + + fk_poll_message_host_repo_id - + hosthistory_56210c2 - - + + public.HostHistory - - + + [table] - + history_revision_id - + - + int8 not null - + history_registrar_id - + - + text not null - + history_modification_time - + - + timestamptz not null - + history_type - + - + text not null - + host_name - + - + text - + creation_time - + - + timestamptz - + host_repo_id - + - + text not null - + + + + pollmessage_614a523e:w->hosthistory_56210c2:e + + + + + + + + + fk_poll_message_host_history + pollmessage_614a523e:w->hosthistory_56210c2:e - - - - - - - - + + + + + + + + fk_poll_message_host_history - - - pollmessage_614a523e:w->hosthistory_56210c2:e - - - - - - - - - fk_poll_message_host_history + + + pollmessage_614a523e:w->registrar_6e1503e3:e + + + + + + + + + fk_poll_message_registrar_id pollmessage_614a523e:w->registrar_6e1503e3:e - - - - - - - - - fk_poll_message_registrar_id + + + + + + + + + fk_poll_message_transfer_response_gaining_registrar_id pollmessage_614a523e:w->registrar_6e1503e3:e - - - - - - - - - fk_poll_message_transfer_response_gaining_registrar_id - - - - pollmessage_614a523e:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_poll_message_transfer_response_losing_registrar_id cursor_6af40e8c - - + + public."Cursor" - - + + [table] - + "scope" - + - + text not null - + type - + - + text not null - + delegationsignerdata_e542a872 - - + + public.DelegationSignerData - - + + [table] - + domain_repo_id - + - + text not null - + key_tag - + - + int4 not null - + algorithm - + - + int4 not null - + digest - + - + bytea not null - + digest_type - + - + int4 not null - + delegationsignerdata_e542a872:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fktr24j9v14ph2mfuw2gsmt12kq domainhistory_a54cc226:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fk_domain_history_domain_repo_id - + domainhistory_a54cc226:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_domain_history_registrar_id domainhost_1ea127c2 - - + + public.DomainHost - - + + [table] - + domain_repo_id - + - + text not null - + host_repo_id - + - + text - + domainhost_1ea127c2:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fkfmi7bdink53swivs390m2btxg - + domainhost_1ea127c2:w->host_f21b78de:e - - - - - - - - + + + + + + + + fk_domainhost_host_valid host_f21b78de:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fk_host_superordinate_domain + + host_f21b78de:w->registrar_6e1503e3:e + + + + + + + + + fk_host_creation_registrar_id + + host_f21b78de:w->registrar_6e1503e3:e - - - - - - - - - fk_host_creation_registrar_id + + + + + + + + + fk_host_current_sponsor_registrar_id host_f21b78de:w->registrar_6e1503e3:e - - - - - - - - - fk_host_current_sponsor_registrar_id - - - - host_f21b78de:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_host_last_epp_update_registrar_id - - - spec11threatmatch_a61228a6 - - - public.Spec11ThreatMatch - - - - [table] - - - id - - - - - bigserial not null - - - - - auto-incremented - - - check_date - - - - - date not null - - - domain_repo_id - - - - - text not null - - - registrar_id - - - - - text not null - - - tld - - - - - text not null - - - - - spec11threatmatch_a61228a6:w->domain_6c51cffa:e - - - - - - - - - fk_spec11_threat_match_domain_repo_id - - - - spec11threatmatch_a61228a6:w->registrar_6e1503e3:e - - - - - - - - - fk_spec11_threat_match_registrar_id - - - - spec11threatmatch_a61228a6:w->tld_f1fa57e2:e - - - - - - - - - fk_spec11_threat_match_tld - - + domaindsdatahistory_995b060d - - + + public.DomainDsDataHistory - - + + [table] - + ds_data_history_revision_id - + - + int8 not null - + domain_history_revision_id - + - + int8 not null - + domain_repo_id - + - + text - + + + + domaindsdatahistory_995b060d:w->domainhistory_a54cc226:e + + + + + + + + + fko4ilgyyfnvppbpuivus565i0j + domaindsdatahistory_995b060d:w->domainhistory_a54cc226:e - - - - - - - - - fko4ilgyyfnvppbpuivus565i0j - - - - domaindsdatahistory_995b060d:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fko4ilgyyfnvppbpuivus565i0j - + domainhistoryhost_9f3f23ee - - + + public.DomainHistoryHost - - + + [table] - + domain_history_history_revision_id - + - + int8 not null - + domain_history_domain_repo_id - + - + text not null - + + + + domainhistoryhost_9f3f23ee:w->domainhistory_a54cc226:e + + + + + + + + + fka9woh3hu8gx5x0vly6bai327n + domainhistoryhost_9f3f23ee:w->domainhistory_a54cc226:e - - - - - - - - - fka9woh3hu8gx5x0vly6bai327n - - - - domainhistoryhost_9f3f23ee:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fka9woh3hu8gx5x0vly6bai327n - + domaintransactionrecord_6e77ff61 - - + + public.DomainTransactionRecord - - + + [table] - + id - + - + bigserial not null - + - + auto-incremented - + tld - + - + text not null - + domain_repo_id - + - + text - + history_revision_id - + - + int8 - + + + + domaintransactionrecord_6e77ff61:w->domainhistory_a54cc226:e + + + + + + + + + fkcjqe54u72kha71vkibvxhjye7 + domaintransactionrecord_6e77ff61:w->domainhistory_a54cc226:e - - - - - - - - - fkcjqe54u72kha71vkibvxhjye7 - - - - domaintransactionrecord_6e77ff61:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fkcjqe54u72kha71vkibvxhjye7 - + domaintransactionrecord_6e77ff61:w->tld_f1fa57e2:e - - - - - - - - + + + + + + + + fk_domain_transaction_record_tld - + graceperiodhistory_40ccc1f1 - - + + public.GracePeriodHistory - - + + [table] - + grace_period_history_revision_id - + - + int8 not null - + domain_repo_id - + - + text not null - + domain_history_revision_id - + - + int8 - + + + + graceperiodhistory_40ccc1f1:w->domainhistory_a54cc226:e + + + + + + + + + fk7w3cx8d55q8bln80e716tr7b8 + graceperiodhistory_40ccc1f1:w->domainhistory_a54cc226:e - - - - - - - - - fk7w3cx8d55q8bln80e716tr7b8 - - - - graceperiodhistory_40ccc1f1:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk7w3cx8d55q8bln80e716tr7b8 - + hosthistory_56210c2:w->host_f21b78de:e - - - - - - - - + + + + + + + + fk_hosthistory_host - + hosthistory_56210c2:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk3d09knnmxrt6iniwnp8j2ykga - + kmssecret_f3b28857 - - + + public.KmsSecret - - + + [table] - + revision_id - + - + int8 not null - + secret_name - + - + text not null - + - + lock_f21d4861 - - + + public.Lock - - + + [table] - + resource_name - + - + text not null - + tld - + - + text not null - + - + premiumentry_b0060b91 - - + + public.PremiumEntry - - + + [table] - + revision_id - + - + int8 not null - + domain_label - + - + text not null - + - + premiumlist_7c3ea68b - - + + public.PremiumList - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + name - + - + text not null - + - + premiumentry_b0060b91:w->premiumlist_7c3ea68b:e - - - - - - - - + + + + + + + + fko0gw90lpo1tuee56l0nb6y6g5 - + rderevision_83396864 - - + + public.RdeRevision - - + + [table] - + tld - + - + text not null - + mode - + - + text not null - + "date" - + - + date not null - + - + registrarpoc_ab47054d - - + + public.RegistrarPoc - - + + [table] - + email_address - + - + text not null - + gae_user_id - + - + text - + registrar_id - + - + text not null - + - + registrarpoc_ab47054d:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_registrar_poc_registrar_id - + registrylock_ac88663e - - + + public.RegistryLock - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + registrar_id - + - + text not null - + repo_id - + - + text not null - + verification_code - + - + text not null - + relock_revision_id - + - + int8 - + - + registrylock_ac88663e:w->registrylock_ac88663e:e - - - - - - - - + + + + + + + + fk2lhcwpxlnqijr96irylrh1707 - + reservedentry_1a7b8520 - - + + public.ReservedEntry - - + + [table] - + revision_id - + - + int8 not null - + domain_label - + - + text not null - + - + reservedlist_b97c3f1c - - + + public.ReservedList - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + name - + - + text not null - + - + reservedentry_1a7b8520:w->reservedlist_b97c3f1c:e - - - - - - - - + + + + + + + + fkgq03rk0bt1hb915dnyvd3vnfc - + serversecret_6cc90f09 - - + + public.ServerSecret - - + + [table] - + secret - + - + uuid not null - + - + signedmarkrevocationentry_99c39721 - - + + public.SignedMarkRevocationEntry - - + + [table] - + revision_id - + - + int8 not null - + smd_id - + - + text not null - + - + signedmarkrevocationlist_c5d968fb - - + + public.SignedMarkRevocationList - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + - + signedmarkrevocationentry_99c39721:w->signedmarkrevocationlist_c5d968fb:e - - - - - - - - + + + + + + + + fk5ivlhvs3121yx2li5tqh54u4 + + + spec11threatmatch_a61228a6 + + + public.Spec11ThreatMatch + + + + [table] + + + id + + + + + bigserial not null + + + + + auto-incremented + + + check_date + + + + + date not null + + + registrar_id + + + + + text not null + + + tld + + + + + text not null + + sqlreplaycheckpoint_342081b3 - - + + public.SqlReplayCheckpoint - - + + [table] - + revision_id - + - + int8 not null - + tmchcrl_d282355 - - + + public.TmchCrl - - + + [table] - + certificate_revocations - + - + text not null - + update_timestamp - + - + timestamptz not null - + url - + - + text not null - + transaction_d50389d4 - - + + public.Transaction - - + + [table] - + id - + - + bigserial not null - + - + auto-incremented - + @@ -4467,18 +4420,6 @@ td.section {
-
- fk_spec11_threat_match_domain_repo_id - [foreign key, with no action] -
-
- - repo_id ←(0..many) public.Spec11ThreatMatch.domain_repo_id - -
-
- -
fk2jc69qyg2tv9hhnmif6oa1cx1 [foreign key, with no action] @@ -6212,18 +6153,6 @@ td.section { registrar_id ←(0..many) public.RegistrarPoc.registrar_id
-
- -
-
- fk_spec11_threat_match_registrar_id - [foreign key, with no action] -
-
- - registrar_id ←(0..many) public.Spec11ThreatMatch.registrar_id - -

 

@@ -6639,11 +6568,6 @@ td.section { check_date date not null - - - domain_repo_id - text not null - registrar_id @@ -6672,48 +6596,6 @@ td.section { id - - - - - Foreign Keys - - - - - - fk_spec11_threat_match_domain_repo_id - [foreign key, with no action] - - - - domain_repo_id (0..many)→ public.Domain.repo_id - - - - - - - fk_spec11_threat_match_registrar_id - [foreign key, with no action] - - - - registrar_id (0..many)→ public.Registrar.registrar_id - - - - - - - fk_spec11_threat_match_tld - [foreign key, with no action] - - - - tld (0..many)→ public.Tld.tld_name - -

 

@@ -6804,18 +6686,6 @@ td.section { tld_name ←(0..many) public.DomainTransactionRecord.tld - - - - - fk_spec11_threat_match_tld - [foreign key, with no action] - - - - tld_name ←(0..many) public.Spec11ThreatMatch.tld - -

 

diff --git a/db/src/main/resources/sql/er_diagram/full_er_diagram.html b/db/src/main/resources/sql/er_diagram/full_er_diagram.html index 235e4219d..11d616f0d 100644 --- a/db/src/main/resources/sql/er_diagram/full_er_diagram.html +++ b/db/src/main/resources/sql/er_diagram/full_er_diagram.html @@ -261,19 +261,19 @@ td.section { generated on - 2020-11-30 21:59:18.813825 + 2020-12-05 00:29:01.929048 last flyway file - V80__defer_bill_event_key.sql + V81__drop_spec11_fkeys.sql

 

 

- + SchemaCrawler_Diagram - + generated by @@ -284,6071 +284,6032 @@ td.section { generated on - 2020-11-30 21:59:18.813825 + 2020-12-05 00:29:01.929048 allocationtoken_a08ccbef - - + + public.AllocationToken - - + + [table] - + token - + - + text not null - + update_timestamp - + - + timestamptz - + allowed_registrar_ids - + - + _text - + allowed_tlds - + - + _text - + creation_time - + - + timestamptz not null - + discount_fraction - + - + float8(17, 17) not null - + discount_premiums - + - + bool not null - + discount_years - + - + int4 not null - + domain_name - + - + text - + redemption_domain_repo_id - + - + text - + token_status_transitions - + - + "hstore" - + token_type - + - + text - + redemption_domain_history_id - + - + int8 - + billingevent_a57d1815 - - + + public.BillingEvent - - + + [table] - + billing_event_id - + - + int8 not null - + registrar_id - + - + text not null - + domain_history_revision_id - + - + int8 not null - + domain_repo_id - + - + text not null - + event_time - + - + timestamptz not null - + flags - + - + _text - + reason - + - + text not null - + domain_name - + - + text not null - + allocation_token - + - + text - + billing_time - + - + timestamptz - + cancellation_matching_billing_recurrence_id - + - + int8 - + cost_amount - + - + numeric(19, 2) - + cost_currency - + - + text - + period_years - + - + int4 - + synthetic_creation_time - + - + timestamptz - + billingevent_a57d1815:w->allocationtoken_a08ccbef:e - - - - - - - - + + + + + + + + fk_billing_event_allocation_token billingrecurrence_5fa2cb01 - - + + public.BillingRecurrence - - + + [table] - + billing_recurrence_id - + - + int8 not null - + registrar_id - + - + text not null - + domain_history_revision_id - + - + int8 not null - + domain_repo_id - + - + text not null - + event_time - + - + timestamptz not null - + flags - + - + _text - + reason - + - + text not null - + domain_name - + - + text not null - + recurrence_end_time - + - + timestamptz - + recurrence_time_of_year - + - + text - + billingevent_a57d1815:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_billing_event_cancellation_matching_billing_recurrence_id domainhistory_a54cc226 - - + + public.DomainHistory - - + + [table] - + history_revision_id - + - + int8 not null - + history_by_superuser - + - + bool not null - + history_registrar_id - + - + text - + history_modification_time - + - + timestamptz not null - + history_reason - + - + text - + history_requested_by_registrar - + - + bool - + history_client_transaction_id - + - + text - + history_server_transaction_id - + - + text - + history_type - + - + text not null - + history_xml_bytes - + - + bytea - + admin_contact - + - + text - + auth_info_repo_id - + - + text - + auth_info_value - + - + text - + billing_recurrence_id - + - + int8 - + autorenew_poll_message_id - + - + int8 - + billing_contact - + - + text - + deletion_poll_message_id - + - + int8 - + domain_name - + - + text - + idn_table_name - + - + text - + last_transfer_time - + - + timestamptz - + launch_notice_accepted_time - + - + timestamptz - + launch_notice_expiration_time - + - + timestamptz - + launch_notice_tcn_id - + - + text - + launch_notice_validator_id - + - + text - + registrant_contact - + - + text - + registration_expiration_time - + - + timestamptz - + smd_id - + - + text - + subordinate_hosts - + - + _text - + tech_contact - + - + text - + tld - + - + text - + transfer_billing_cancellation_id - + - + int8 - + transfer_billing_recurrence_id - + - + int8 - + transfer_autorenew_poll_message_id - + - + int8 - + transfer_billing_event_id - + - + int8 - + transfer_renew_period_unit - + - + text - + transfer_renew_period_value - + - + int4 - + transfer_registration_expiration_time - + - + timestamptz - + transfer_gaining_poll_message_id - + - + int8 - + transfer_losing_poll_message_id - + - + int8 - + transfer_client_txn_id - + - + text - + transfer_server_txn_id - + - + text - + transfer_gaining_registrar_id - + - + text - + transfer_losing_registrar_id - + - + text - + transfer_pending_expiration_time - + - + timestamptz - + transfer_request_time - + - + timestamptz - + transfer_status - + - + text - + creation_registrar_id - + - + text - + creation_time - + - + timestamptz - + current_sponsor_registrar_id - + - + text - + deletion_time - + - + timestamptz - + last_epp_update_registrar_id - + - + text - + last_epp_update_time - + - + timestamptz - + statuses - + - + _text - + update_timestamp - + - + timestamptz - + domain_repo_id - + - + text not null - + autorenew_end_time - + - + timestamptz - + history_other_registrar_id - + - + text - + history_period_unit - + - + text - + history_period_value - + - + int4 - + billing_recurrence_history_id - + - + int8 - + autorenew_poll_message_history_id - + - + int8 - + deletion_poll_message_history_id - + - + int8 - + transfer_billing_recurrence_history_id - + - + int8 - + transfer_autorenew_poll_message_history_id - + - + int8 - + transfer_billing_event_history_id - + - + int8 - + + + + billingevent_a57d1815:w->domainhistory_a54cc226:e + + + + + + + + + fk_billing_event_domain_history + billingevent_a57d1815:w->domainhistory_a54cc226:e - - - - - - - - - fk_billing_event_domain_history - - - - billingevent_a57d1815:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk_billing_event_domain_history - + registrar_6e1503e3 - - + + public.Registrar - - + + [table] - + registrar_id - + - + text not null - + allowed_tlds - + - + _text - + billing_account_map - + - + "hstore" - + billing_identifier - + - + int8 - + block_premium_names - + - + bool not null - + client_certificate - + - + text - + client_certificate_hash - + - + text - + contacts_require_syncing - + - + bool not null - + creation_time - + - + timestamptz - + drive_folder_id - + - + text - + email_address - + - + text - + failover_client_certificate - + - + text - + failover_client_certificate_hash - + - + text - + fax_number - + - + text - + iana_identifier - + - + int8 - + icann_referral_email - + - + text - + i18n_address_city - + - + text - + i18n_address_country_code - + - + text - + i18n_address_state - + - + text - + i18n_address_street_line1 - + - + text - + i18n_address_street_line2 - + - + text - + i18n_address_street_line3 - + - + text - + i18n_address_zip - + - + text - + ip_address_allow_list - + - + _text - + last_certificate_update_time - + - + timestamptz - + last_update_time - + - + timestamptz - + localized_address_city - + - + text - + localized_address_country_code - + - + text - + localized_address_state - + - + text - + localized_address_street_line1 - + - + text - + localized_address_street_line2 - + - + text - + localized_address_street_line3 - + - + text - + localized_address_zip - + - + text - + password_hash - + - + text - + phone_number - + - + text - + phone_passcode - + - + text - + po_number - + - + text - + rdap_base_urls - + - + _text - + registrar_name - + - + text not null - + registry_lock_allowed - + - + bool not null - + password_salt - + - + text - + state - + - + text - + type - + - + text not null - + url - + - + text - + whois_server - + - + text - + - + billingevent_a57d1815:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_billing_event_registrar_id billingcancellation_6eedf614 - - + + public.BillingCancellation - - + + [table] - + billing_cancellation_id - + - + int8 not null - + registrar_id - + - + text not null - + domain_history_revision_id - + - + int8 not null - + domain_repo_id - + - + text not null - + event_time - + - + timestamptz not null - + flags - + - + _text - + reason - + - + text not null - + domain_name - + - + text not null - + billing_time - + - + timestamptz - + billing_event_id - + - + int8 - + billing_recurrence_id - + - + int8 - + billingcancellation_6eedf614:w->billingevent_a57d1815:e - - - - - - - - + + + + + + + + fk_billing_cancellation_billing_event_id billingcancellation_6eedf614:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_billing_cancellation_billing_recurrence_id + + billingcancellation_6eedf614:w->domainhistory_a54cc226:e + + + + + + + + + fk_billing_cancellation_domain_history + + billingcancellation_6eedf614:w->domainhistory_a54cc226:e - - - - - - - - - fk_billing_cancellation_domain_history - - - - billingcancellation_6eedf614:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk_billing_cancellation_domain_history - + billingcancellation_6eedf614:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_billing_cancellation_registrar_id domain_6c51cffa - - + + public.Domain - - + + [table] - + repo_id - + - + text not null - + 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 - + auth_info_repo_id - + - + text - + auth_info_value - + - + text - + domain_name - + - + text - + idn_table_name - + - + text - + last_transfer_time - + - + timestamptz - + launch_notice_accepted_time - + - + timestamptz - + launch_notice_expiration_time - + - + timestamptz - + launch_notice_tcn_id - + - + text - + launch_notice_validator_id - + - + text - + registration_expiration_time - + - + timestamptz - + smd_id - + - + text - + subordinate_hosts - + - + _text - + tld - + - + text - + admin_contact - + - + text - + billing_contact - + - + text - + registrant_contact - + - + text - + tech_contact - + - + text - + transfer_gaining_poll_message_id - + - + int8 - + transfer_losing_poll_message_id - + - + int8 - + transfer_billing_cancellation_id - + - + int8 - + transfer_billing_event_id - + - + int8 - + transfer_billing_recurrence_id - + - + int8 - + transfer_autorenew_poll_message_id - + - + int8 - + transfer_renew_period_unit - + - + text - + transfer_renew_period_value - + - + int4 - + transfer_client_txn_id - + - + text - + transfer_server_txn_id - + - + text - + transfer_registration_expiration_time - + - + timestamptz - + transfer_gaining_registrar_id - + - + text - + transfer_losing_registrar_id - + - + text - + transfer_pending_expiration_time - + - + timestamptz - + transfer_request_time - + - + timestamptz - + transfer_status - + - + text - + update_timestamp - + - + timestamptz - + billing_recurrence_id - + - + int8 - + autorenew_poll_message_id - + - + int8 - + deletion_poll_message_id - + - + int8 - + autorenew_end_time - + - + timestamptz - + billing_recurrence_history_id - + - + int8 - + autorenew_poll_message_history_id - + - + int8 - + deletion_poll_message_history_id - + - + int8 - + transfer_billing_recurrence_history_id - + - + int8 - + transfer_autorenew_poll_message_history_id - + - + int8 - + transfer_billing_event_history_id - + - + int8 - + domain_6c51cffa:w->billingevent_a57d1815:e - - - - - - - - + + + + + + + + fk_domain_transfer_billing_event_id domain_6c51cffa:w->billingcancellation_6eedf614:e - - - - - - - - + + + + + + + + fk_domain_transfer_billing_cancellation_id domain_6c51cffa:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_domain_billing_recurrence_id domain_6c51cffa:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_domain_transfer_billing_recurrence_id contact_8de8cb16 - - + + public.Contact - - + + [table] - + repo_id - + - + text not null - + 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 - + auth_info_repo_id - + - + text - + auth_info_value - + - + text - + contact_id - + - + text - + disclose_types_addr - + - + _text - + disclose_show_email - + - + bool - + disclose_show_fax - + - + bool - + disclose_mode_flag - + - + bool - + disclose_types_name - + - + _text - + disclose_types_org - + - + _text - + disclose_show_voice - + - + bool - + email - + - + text - + fax_phone_extension - + - + text - + fax_phone_number - + - + text - + addr_i18n_city - + - + text - + addr_i18n_country_code - + - + text - + addr_i18n_state - + - + text - + addr_i18n_street_line1 - + - + text - + addr_i18n_street_line2 - + - + text - + addr_i18n_street_line3 - + - + text - + addr_i18n_zip - + - + text - + addr_i18n_name - + - + text - + addr_i18n_org - + - + text - + addr_i18n_type - + - + text - + last_transfer_time - + - + timestamptz - + addr_local_city - + - + text - + addr_local_country_code - + - + text - + addr_local_state - + - + text - + addr_local_street_line1 - + - + text - + addr_local_street_line2 - + - + text - + addr_local_street_line3 - + - + text - + addr_local_zip - + - + text - + addr_local_name - + - + text - + addr_local_org - + - + text - + addr_local_type - + - + text - + search_name - + - + text - + voice_phone_extension - + - + text - + voice_phone_number - + - + text - + transfer_gaining_poll_message_id - + - + int8 - + transfer_losing_poll_message_id - + - + int8 - + transfer_client_txn_id - + - + text - + transfer_server_txn_id - + - + text - + transfer_gaining_registrar_id - + - + text - + transfer_losing_registrar_id - + - + text - + transfer_pending_expiration_time - + - + timestamptz - + transfer_request_time - + - + timestamptz - + transfer_status - + - + text - + update_timestamp - + - + timestamptz - + domain_6c51cffa:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_domain_admin_contact domain_6c51cffa:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_domain_billing_contact domain_6c51cffa:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_domain_registrant_contact domain_6c51cffa:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_domain_tech_contact + + domain_6c51cffa:w->registrar_6e1503e3:e + + + + + + + + + fk2jc69qyg2tv9hhnmif6oa1cx1 + + domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - - fk2jc69qyg2tv9hhnmif6oa1cx1 + + + + + + + + + fk2u3srsfbei272093m3b3xwj23 domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - - fk2u3srsfbei272093m3b3xwj23 + + + + + + + + + fkjc0r9r5y1lfbt4gpbqw4wsuvq domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - - fkjc0r9r5y1lfbt4gpbqw4wsuvq + + + + + + + + + fk_domain_transfer_gaining_registrar_id domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - - fk_domain_transfer_gaining_registrar_id - - - - domain_6c51cffa:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_domain_transfer_losing_registrar_id tld_f1fa57e2 - - + + public.Tld - - + + [table] - + tld_name - + - + text not null - + add_grace_period_length - + - + interval not null - + allowed_fully_qualified_host_names - + - + _text - + allowed_registrant_contact_ids - + - + _text - + anchor_tenant_add_grace_period_length - + - + interval not null - + auto_renew_grace_period_length - + - + interval not null - + automatic_transfer_length - + - + interval not null - + claims_period_end - + - + timestamptz not null - + create_billing_cost_amount - + - + numeric(19, 2) - + create_billing_cost_currency - + - + text - + creation_time - + - + timestamptz not null - + currency - + - + text not null - + dns_paused - + - + bool not null - + dns_writers - + - + _text not null - + drive_folder_id - + - + text - + eap_fee_schedule - + - + "hstore" not null - + escrow_enabled - + - + bool not null - + invoicing_enabled - + - + bool not null - + lordn_username - + - + text - + num_dns_publish_locks - + - + int4 not null - + pending_delete_length - + - + interval not null - + premium_list_name - + - + text - + pricing_engine_class_name - + - + text - + redemption_grace_period_length - + - + interval not null - + registry_lock_or_unlock_cost_amount - + - + numeric(19, 2) - + registry_lock_or_unlock_cost_currency - + - + text - + renew_billing_cost_transitions - + - + "hstore" not null - + renew_grace_period_length - + - + interval not null - + reserved_list_names - + - + _text - + restore_billing_cost_amount - + - + numeric(19, 2) - + restore_billing_cost_currency - + - + text - + roid_suffix - + - + text - + server_status_change_billing_cost_amount - + - + numeric(19, 2) - + server_status_change_billing_cost_currency - + - + text - + tld_state_transitions - + - + "hstore" not null - + tld_type - + - + text not null - + tld_unicode - + - + text not null - + transfer_grace_period_length - + - + interval not null - + - + domain_6c51cffa:w->tld_f1fa57e2:e - - - - - - - - + + + + + + + + fk_domain_tld graceperiod_cd3b2e8f - - + + public.GracePeriod - - + + [table] - + grace_period_id - + - + int8 not null - + billing_event_id - + - + int8 - + billing_recurrence_id - + - + int8 - + registrar_id - + - + text not null - + domain_repo_id - + - + text not null - + expiration_time - + - + timestamptz not null - + type - + - + text not null - + billing_event_history_id - + - + int8 - + billing_recurrence_history_id - + - + int8 - + graceperiod_cd3b2e8f:w->billingevent_a57d1815:e - - - - - - - - + + + + + + + + fk_grace_period_billing_event_id graceperiod_cd3b2e8f:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fk_grace_period_domain_repo_id graceperiod_cd3b2e8f:w->billingrecurrence_5fa2cb01:e - - - - - - - - + + + + + + + + fk_grace_period_billing_recurrence_id - + graceperiod_cd3b2e8f:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_grace_period_registrar_id + + billingrecurrence_5fa2cb01:w->domainhistory_a54cc226:e + + + + + + + + + fk_billing_recurrence_domain_history + + billingrecurrence_5fa2cb01:w->domainhistory_a54cc226:e - - - - - - - - - fk_billing_recurrence_domain_history - - - - billingrecurrence_5fa2cb01:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk_billing_recurrence_domain_history - + billingrecurrence_5fa2cb01:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_billing_recurrence_registrar_id claimsentry_105da9f1 - - + + public.ClaimsEntry - - + + [table] - + revision_id - + - + int8 not null - + claim_key - + - + text not null - + domain_label - + - + text not null - + claimslist_3d49bc2b - - + + public.ClaimsList - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + creation_timestamp - + - + timestamptz not null - + tmdb_generation_time - + - + timestamptz not null - + claimsentry_105da9f1:w->claimslist_3d49bc2b:e - - - - - - - - + + + + + + + + fk6sc6at5hedffc0nhdcab6ivuq + + contact_8de8cb16:w->registrar_6e1503e3:e + + + + + + + + + fk1sfyj7o7954prbn1exk7lpnoe + + contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - - fk1sfyj7o7954prbn1exk7lpnoe + + + + + + + + + fk93c185fx7chn68uv7nl6uv2s0 contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - - fk93c185fx7chn68uv7nl6uv2s0 + + + + + + + + + fkmb7tdiv85863134w1wogtxrb2 contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - - fkmb7tdiv85863134w1wogtxrb2 + + + + + + + + + fk_contact_transfer_gaining_registrar_id contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - - fk_contact_transfer_gaining_registrar_id - - - - contact_8de8cb16:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_contact_transfer_losing_registrar_id contacthistory_d2964f8a - - + + public.ContactHistory - - + + [table] - + history_revision_id - + - + int8 not null - + history_by_superuser - + - + bool not null - + history_registrar_id - + - + text - + history_modification_time - + - + timestamptz not null - + history_reason - + - + text - + history_requested_by_registrar - + - + bool - + history_client_transaction_id - + - + text - + history_server_transaction_id - + - + text - + history_type - + - + text not null - + history_xml_bytes - + - + bytea - + auth_info_repo_id - + - + text - + auth_info_value - + - + text - + contact_id - + - + text - + disclose_types_addr - + - + _text - + disclose_show_email - + - + bool - + disclose_show_fax - + - + bool - + disclose_mode_flag - + - + bool - + disclose_types_name - + - + _text - + disclose_types_org - + - + _text - + disclose_show_voice - + - + bool - + email - + - + text - + fax_phone_extension - + - + text - + fax_phone_number - + - + text - + addr_i18n_city - + - + text - + addr_i18n_country_code - + - + text - + addr_i18n_state - + - + text - + addr_i18n_street_line1 - + - + text - + addr_i18n_street_line2 - + - + text - + addr_i18n_street_line3 - + - + text - + addr_i18n_zip - + - + text - + addr_i18n_name - + - + text - + addr_i18n_org - + - + text - + addr_i18n_type - + - + text - + last_transfer_time - + - + timestamptz - + addr_local_city - + - + text - + addr_local_country_code - + - + text - + addr_local_state - + - + text - + addr_local_street_line1 - + - + text - + addr_local_street_line2 - + - + text - + addr_local_street_line3 - + - + text - + addr_local_zip - + - + text - + addr_local_name - + - + text - + addr_local_org - + - + text - + addr_local_type - + - + text - + search_name - + - + text - + transfer_gaining_poll_message_id - + - + int8 - + transfer_losing_poll_message_id - + - + int8 - + transfer_client_txn_id - + - + text - + transfer_server_txn_id - + - + text - + transfer_gaining_registrar_id - + - + text - + transfer_losing_registrar_id - + - + text - + transfer_pending_expiration_time - + - + timestamptz - + transfer_request_time - + - + timestamptz - + transfer_status - + - + text - + voice_phone_extension - + - + text - + voice_phone_number - + - + text - + creation_registrar_id - + - + text - + creation_time - + - + timestamptz - + current_sponsor_registrar_id - + - + text - + deletion_time - + - + timestamptz - + last_epp_update_registrar_id - + - + text - + last_epp_update_time - + - + timestamptz - + statuses - + - + _text - + contact_repo_id - + - + text not null - + update_timestamp - + - + timestamptz - + contacthistory_d2964f8a:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_contact_history_contact_repo_id - + contacthistory_d2964f8a:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_contact_history_registrar_id pollmessage_614a523e - - + + public.PollMessage - - + + [table] - + type - + - + text not null - + poll_message_id - + - + int8 not null - + registrar_id - + - + text not null - + contact_repo_id - + - + text - + contact_history_revision_id - + - + int8 - + domain_repo_id - + - + text - + domain_history_revision_id - + - + int8 - + event_time - + - + timestamptz not null - + host_repo_id - + - + text - + host_history_revision_id - + - + int8 - + message - + - + text - + transfer_response_contact_id - + - + text - + transfer_response_domain_expiration_time - + - + timestamptz - + transfer_response_domain_name - + - + text - + pending_action_response_action_result - + - + bool - + pending_action_response_name_or_id - + - + text - + pending_action_response_processed_date - + - + timestamptz - + pending_action_response_client_txn_id - + - + text - + pending_action_response_server_txn_id - + - + text - + transfer_response_gaining_registrar_id - + - + text - + transfer_response_losing_registrar_id - + - + text - + transfer_response_pending_transfer_expiration_time - + - + timestamptz - + transfer_response_transfer_request_time - + - + timestamptz - + transfer_response_transfer_status - + - + text - + autorenew_end_time - + - + timestamptz - + autorenew_domain_name - + - + text - + pollmessage_614a523e:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fk_poll_message_domain_repo_id pollmessage_614a523e:w->contact_8de8cb16:e - - - - - - - - + + + + + + + + fk_poll_message_contact_repo_id pollmessage_614a523e:w->contacthistory_d2964f8a:e - - - - - - - - + + + + + + + + fk_poll_message_contact_history pollmessage_614a523e:w->contacthistory_d2964f8a:e - - - - - - - - + + + + + + + + fk_poll_message_contact_history + + pollmessage_614a523e:w->domainhistory_a54cc226:e + + + + + + + + + fk_poll_message_domain_history + + pollmessage_614a523e:w->domainhistory_a54cc226:e - - - - - - - - - fk_poll_message_domain_history - - - - pollmessage_614a523e:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk_poll_message_domain_history host_f21b78de - - + + public.Host - - + + [table] - + repo_id - + - + text not null - + creation_registrar_id - + - + text - + creation_time - + - + timestamptz - + current_sponsor_registrar_id - + - + text - + deletion_time - + - + timestamptz - + last_epp_update_registrar_id - + - + text - + last_epp_update_time - + - + timestamptz - + statuses - + - + _text - + host_name - + - + text - + last_superordinate_change - + - + timestamptz - + last_transfer_time - + - + timestamptz - + superordinate_domain - + - + text - + inet_addresses - + - + _text - + update_timestamp - + - + timestamptz - + - + pollmessage_614a523e:w->host_f21b78de:e - - - - - - - - + + + + + + + + fk_poll_message_host_repo_id - + hosthistory_56210c2 - - + + public.HostHistory - - + + [table] - + history_revision_id - + - + int8 not null - + history_by_superuser - + - + bool not null - + history_registrar_id - + - + text not null - + history_modification_time - + - + timestamptz not null - + history_reason - + - + text - + history_requested_by_registrar - + - + bool - + history_client_transaction_id - + - + text - + history_server_transaction_id - + - + text - + history_type - + - + text not null - + history_xml_bytes - + - + bytea - + host_name - + - + text - + inet_addresses - + - + _text - + last_superordinate_change - + - + timestamptz - + last_transfer_time - + - + timestamptz - + superordinate_domain - + - + text - + creation_registrar_id - + - + text - + creation_time - + - + timestamptz - + current_sponsor_registrar_id - + - + text - + deletion_time - + - + timestamptz - + last_epp_update_registrar_id - + - + text - + last_epp_update_time - + - + timestamptz - + statuses - + - + _text - + host_repo_id - + - + text not null - + update_timestamp - + - + timestamptz - + + + + pollmessage_614a523e:w->hosthistory_56210c2:e + + + + + + + + + fk_poll_message_host_history + pollmessage_614a523e:w->hosthistory_56210c2:e - - - - - - - - + + + + + + + + fk_poll_message_host_history - - - pollmessage_614a523e:w->hosthistory_56210c2:e - - - - - - - - - fk_poll_message_host_history + + + pollmessage_614a523e:w->registrar_6e1503e3:e + + + + + + + + + fk_poll_message_registrar_id pollmessage_614a523e:w->registrar_6e1503e3:e - - - - - - - - - fk_poll_message_registrar_id + + + + + + + + + fk_poll_message_transfer_response_gaining_registrar_id pollmessage_614a523e:w->registrar_6e1503e3:e - - - - - - - - - fk_poll_message_transfer_response_gaining_registrar_id - - - - pollmessage_614a523e:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_poll_message_transfer_response_losing_registrar_id cursor_6af40e8c - - + + public."Cursor" - - + + [table] - + "scope" - + - + text not null - + type - + - + text not null - + cursor_time - + - + timestamptz not null - + last_update_time - + - + timestamptz not null - + delegationsignerdata_e542a872 - - + + public.DelegationSignerData - - + + [table] - + domain_repo_id - + - + text not null - + key_tag - + - + int4 not null - + algorithm - + - + int4 not null - + digest - + - + bytea not null - + digest_type - + - + int4 not null - + delegationsignerdata_e542a872:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fktr24j9v14ph2mfuw2gsmt12kq domainhistory_a54cc226:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fk_domain_history_domain_repo_id - + domainhistory_a54cc226:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_domain_history_registrar_id domainhost_1ea127c2 - - + + public.DomainHost - - + + [table] - + domain_repo_id - + - + text not null - + host_repo_id - + - + text - + domainhost_1ea127c2:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fkfmi7bdink53swivs390m2btxg - + domainhost_1ea127c2:w->host_f21b78de:e - - - - - - - - + + + + + + + + fk_domainhost_host_valid host_f21b78de:w->domain_6c51cffa:e - - - - - - - - + + + + + + + + fk_host_superordinate_domain + + host_f21b78de:w->registrar_6e1503e3:e + + + + + + + + + fk_host_creation_registrar_id + + host_f21b78de:w->registrar_6e1503e3:e - - - - - - - - - fk_host_creation_registrar_id + + + + + + + + + fk_host_current_sponsor_registrar_id host_f21b78de:w->registrar_6e1503e3:e - - - - - - - - - fk_host_current_sponsor_registrar_id - - - - host_f21b78de:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_host_last_epp_update_registrar_id - - - spec11threatmatch_a61228a6 - - - public.Spec11ThreatMatch - - - - [table] - - - id - - - - - bigserial not null - - - - - auto-incremented - - - check_date - - - - - date not null - - - domain_name - - - - - text not null - - - domain_repo_id - - - - - text not null - - - registrar_id - - - - - text not null - - - threat_types - - - - - _text not null - - - tld - - - - - text not null - - - - - spec11threatmatch_a61228a6:w->domain_6c51cffa:e - - - - - - - - - fk_spec11_threat_match_domain_repo_id - - - - spec11threatmatch_a61228a6:w->registrar_6e1503e3:e - - - - - - - - - fk_spec11_threat_match_registrar_id - - - - spec11threatmatch_a61228a6:w->tld_f1fa57e2:e - - - - - - - - - fk_spec11_threat_match_tld - - + domaindsdatahistory_995b060d - - + + public.DomainDsDataHistory - - + + [table] - + ds_data_history_revision_id - + - + int8 not null - + algorithm - + - + int4 not null - + digest - + - + bytea not null - + digest_type - + - + int4 not null - + domain_history_revision_id - + - + int8 not null - + key_tag - + - + int4 not null - + domain_repo_id - + - + text - + + + + domaindsdatahistory_995b060d:w->domainhistory_a54cc226:e + + + + + + + + + fko4ilgyyfnvppbpuivus565i0j + domaindsdatahistory_995b060d:w->domainhistory_a54cc226:e - - - - - - - - - fko4ilgyyfnvppbpuivus565i0j - - - - domaindsdatahistory_995b060d:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fko4ilgyyfnvppbpuivus565i0j - + domainhistoryhost_9f3f23ee - - + + public.DomainHistoryHost - - + + [table] - + domain_history_history_revision_id - + - + int8 not null - + host_repo_id - + - + text - + domain_history_domain_repo_id - + - + text not null - + + + + domainhistoryhost_9f3f23ee:w->domainhistory_a54cc226:e + + + + + + + + + fka9woh3hu8gx5x0vly6bai327n + domainhistoryhost_9f3f23ee:w->domainhistory_a54cc226:e - - - - - - - - - fka9woh3hu8gx5x0vly6bai327n - - - - domainhistoryhost_9f3f23ee:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fka9woh3hu8gx5x0vly6bai327n - + domaintransactionrecord_6e77ff61 - - + + public.DomainTransactionRecord - - + + [table] - + id - + - + bigserial not null - + - + auto-incremented - + report_amount - + - + int4 not null - + report_field - + - + text not null - + reporting_time - + - + timestamptz not null - + tld - + - + text not null - + domain_repo_id - + - + text - + history_revision_id - + - + int8 - + + + + domaintransactionrecord_6e77ff61:w->domainhistory_a54cc226:e + + + + + + + + + fkcjqe54u72kha71vkibvxhjye7 + domaintransactionrecord_6e77ff61:w->domainhistory_a54cc226:e - - - - - - - - - fkcjqe54u72kha71vkibvxhjye7 - - - - domaintransactionrecord_6e77ff61:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fkcjqe54u72kha71vkibvxhjye7 - + domaintransactionrecord_6e77ff61:w->tld_f1fa57e2:e - - - - - - - - + + + + + + + + fk_domain_transaction_record_tld - + graceperiodhistory_40ccc1f1 - - + + public.GracePeriodHistory - - + + [table] - + grace_period_history_revision_id - + - + int8 not null - + billing_event_id - + - + int8 - + billing_event_history_id - + - + int8 - + billing_recurrence_id - + - + int8 - + billing_recurrence_history_id - + - + int8 - + registrar_id - + - + text not null - + domain_repo_id - + - + text not null - + expiration_time - + - + timestamptz not null - + type - + - + text not null - + domain_history_revision_id - + - + int8 - + grace_period_id - + - + int8 not null - + + + + graceperiodhistory_40ccc1f1:w->domainhistory_a54cc226:e + + + + + + + + + fk7w3cx8d55q8bln80e716tr7b8 + graceperiodhistory_40ccc1f1:w->domainhistory_a54cc226:e - - - - - - - - - fk7w3cx8d55q8bln80e716tr7b8 - - - - graceperiodhistory_40ccc1f1:w->domainhistory_a54cc226:e - - - - - - - - + + + + + + + + fk7w3cx8d55q8bln80e716tr7b8 - + hosthistory_56210c2:w->host_f21b78de:e - - - - - - - - + + + + + + + + fk_hosthistory_host - + hosthistory_56210c2:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk3d09knnmxrt6iniwnp8j2ykga - + kmssecret_f3b28857 - - + + public.KmsSecret - - + + [table] - + revision_id - + - + int8 not null - + creation_time - + - + timestamptz not null - + encrypted_value - + - + text not null - + crypto_key_version_name - + - + text not null - + secret_name - + - + text not null - + - + lock_f21d4861 - - + + public.Lock - - + + [table] - + resource_name - + - + text not null - + tld - + - + text not null - + acquired_time - + - + timestamptz not null - + expiration_time - + - + timestamptz not null - + request_log_id - + - + text not null - + - + premiumentry_b0060b91 - - + + public.PremiumEntry - - + + [table] - + revision_id - + - + int8 not null - + price - + - + numeric(19, 2) not null - + domain_label - + - + text not null - + - + premiumlist_7c3ea68b - - + + public.PremiumList - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + creation_timestamp - + - + timestamptz - + name - + - + text not null - + bloom_filter - + - + bytea not null - + currency - + - + text not null - + - + premiumentry_b0060b91:w->premiumlist_7c3ea68b:e - - - - - - - - + + + + + + + + fko0gw90lpo1tuee56l0nb6y6g5 - + rderevision_83396864 - - + + public.RdeRevision - - + + [table] - + tld - + - + text not null - + mode - + - + text not null - + "date" - + - + date not null - + update_timestamp - + - + timestamptz - + revision - + - + int4 not null - + - + registrarpoc_ab47054d - - + + public.RegistrarPoc - - + + [table] - + email_address - + - + text not null - + allowed_to_set_registry_lock_password - + - + bool not null - + fax_number - + - + text - + gae_user_id - + - + text - + name - + - + text - + phone_number - + - + text - + registry_lock_password_hash - + - + text - + registry_lock_password_salt - + - + text - + types - + - + _text - + visible_in_domain_whois_as_abuse - + - + bool not null - + visible_in_whois_as_admin - + - + bool not null - + visible_in_whois_as_tech - + - + bool not null - + registry_lock_email_address - + - + text - + registrar_id - + - + text not null - + - + registrarpoc_ab47054d:w->registrar_6e1503e3:e - - - - - - - - + + + + + + + + fk_registrar_poc_registrar_id - + registrylock_ac88663e - - + + public.RegistryLock - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + lock_completion_timestamp - + - + timestamptz - + lock_request_timestamp - + - + timestamptz not null - + domain_name - + - + text not null - + is_superuser - + - + bool not null - + registrar_id - + - + text not null - + registrar_poc_id - + - + text - + repo_id - + - + text not null - + verification_code - + - + text not null - + unlock_request_timestamp - + - + timestamptz - + unlock_completion_timestamp - + - + timestamptz - + last_update_timestamp - + - + timestamptz - + relock_revision_id - + - + int8 - + relock_duration - + - + interval - + - + registrylock_ac88663e:w->registrylock_ac88663e:e - - - - - - - - + + + + + + + + fk2lhcwpxlnqijr96irylrh1707 - + reservedentry_1a7b8520 - - + + public.ReservedEntry - - + + [table] - + revision_id - + - + int8 not null - + comment - + - + text - + reservation_type - + - + int4 not null - + domain_label - + - + text not null - + - + reservedlist_b97c3f1c - - + + public.ReservedList - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + creation_timestamp - + - + timestamptz not null - + name - + - + text not null - + should_publish - + - + bool not null - + - + reservedentry_1a7b8520:w->reservedlist_b97c3f1c:e - - - - - - - - + + + + + + + + fkgq03rk0bt1hb915dnyvd3vnfc - + serversecret_6cc90f09 - - + + public.ServerSecret - - + + [table] - + secret - + - + uuid not null - + - + signedmarkrevocationentry_99c39721 - - + + public.SignedMarkRevocationEntry - - + + [table] - + revision_id - + - + int8 not null - + revocation_time - + - + timestamptz not null - + smd_id - + - + text not null - + - + signedmarkrevocationlist_c5d968fb - - + + public.SignedMarkRevocationList - - + + [table] - + revision_id - + - + bigserial not null - + - + auto-incremented - + creation_time - + - + timestamptz - + - + signedmarkrevocationentry_99c39721:w->signedmarkrevocationlist_c5d968fb:e - - - - - - - - + + + + + + + + fk5ivlhvs3121yx2li5tqh54u4 + + + spec11threatmatch_a61228a6 + + + public.Spec11ThreatMatch + + + + [table] + + + id + + + + + bigserial not null + + + + + auto-incremented + + + check_date + + + + + date not null + + + domain_name + + + + + text not null + + + domain_repo_id + + + + + text not null + + + registrar_id + + + + + text not null + + + threat_types + + + + + _text not null + + + tld + + + + + text not null + + sqlreplaycheckpoint_342081b3 - - + + public.SqlReplayCheckpoint - - + + [table] - + revision_id - + - + int8 not null - + last_replay_time - + - + timestamptz not null - + tmchcrl_d282355 - - + + public.TmchCrl - - + + [table] - + certificate_revocations - + - + text not null - + update_timestamp - + - + timestamptz not null - + url - + - + text not null - + transaction_d50389d4 - - + + public.Transaction - - + + [table] - + id - + - + bigserial not null - + - + auto-incremented - + contents - + - + bytea - + @@ -9031,18 +8992,6 @@ td.section {
-
- fk_spec11_threat_match_domain_repo_id - [foreign key, with no action] -
-
- - repo_id ←(0..many) public.Spec11ThreatMatch.domain_repo_id - -
-
- -
fk2jc69qyg2tv9hhnmif6oa1cx1 [foreign key, with no action] @@ -12183,18 +12132,6 @@ td.section {
-
- fk_spec11_threat_match_registrar_id - [foreign key, with no action] -
-
- - registrar_id ←(0..many) public.Spec11ThreatMatch.registrar_id - -
-
- -
Indexes
@@ -13031,48 +12968,6 @@ td.section {
-
- Foreign Keys -
-
- -
-
- fk_spec11_threat_match_domain_repo_id - [foreign key, with no action] -
-
- - domain_repo_id (0..many)→ public.Domain.repo_id - -
-
- -
-
- fk_spec11_threat_match_registrar_id - [foreign key, with no action] -
-
- - registrar_id (0..many)→ public.Registrar.registrar_id - -
-
- -
-
- fk_spec11_threat_match_tld - [foreign key, with no action] -
-
- - tld (0..many)→ public.Tld.tld_name - -
-
- -
Indexes
@@ -13425,18 +13320,6 @@ td.section {
-
- fk_spec11_threat_match_tld - [foreign key, with no action] -
-
- - tld_name ←(0..many) public.Spec11ThreatMatch.tld - -
-
- -
Indexes
diff --git a/db/src/main/resources/sql/flyway.txt b/db/src/main/resources/sql/flyway.txt index 806e9fc6e..5cda2afd2 100644 --- a/db/src/main/resources/sql/flyway.txt +++ b/db/src/main/resources/sql/flyway.txt @@ -78,3 +78,4 @@ V77__fixes_for_replay.sql V78__add_history_id_for_redemption_history_entry.sql V79__drop_foreign_keys_on_pollmessage.sql V80__defer_bill_event_key.sql +V81__drop_spec11_fkeys.sql diff --git a/db/src/main/resources/sql/flyway/V81__drop_spec11_fkeys.sql b/db/src/main/resources/sql/flyway/V81__drop_spec11_fkeys.sql new file mode 100644 index 000000000..b12762b12 --- /dev/null +++ b/db/src/main/resources/sql/flyway/V81__drop_spec11_fkeys.sql @@ -0,0 +1,18 @@ +-- 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. + +-- Some objects haven't been fully populated in SQL yet, so don't depend on them. +ALTER TABLE "Spec11ThreatMatch" DROP CONSTRAINT "fk_spec11_threat_match_domain_repo_id"; +ALTER TABLE "Spec11ThreatMatch" DROP CONSTRAINT "fk_spec11_threat_match_registrar_id"; +ALTER TABLE "Spec11ThreatMatch" DROP CONSTRAINT "fk_spec11_threat_match_tld"; diff --git a/db/src/main/resources/sql/schema/nomulus.golden.sql b/db/src/main/resources/sql/schema/nomulus.golden.sql index 40da09be6..c1e9039d0 100644 --- a/db/src/main/resources/sql/schema/nomulus.golden.sql +++ b/db/src/main/resources/sql/schema/nomulus.golden.sql @@ -2251,30 +2251,6 @@ ALTER TABLE ONLY public."RegistrarPoc" ADD CONSTRAINT fk_registrar_poc_registrar_id FOREIGN KEY (registrar_id) REFERENCES public."Registrar"(registrar_id); --- --- Name: Spec11ThreatMatch fk_spec11_threat_match_domain_repo_id; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public."Spec11ThreatMatch" - ADD CONSTRAINT fk_spec11_threat_match_domain_repo_id FOREIGN KEY (domain_repo_id) REFERENCES public."Domain"(repo_id); - - --- --- Name: Spec11ThreatMatch fk_spec11_threat_match_registrar_id; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public."Spec11ThreatMatch" - ADD CONSTRAINT fk_spec11_threat_match_registrar_id FOREIGN KEY (registrar_id) REFERENCES public."Registrar"(registrar_id); - - --- --- Name: Spec11ThreatMatch fk_spec11_threat_match_tld; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public."Spec11ThreatMatch" - ADD CONSTRAINT fk_spec11_threat_match_tld FOREIGN KEY (tld) REFERENCES public."Tld"(tld_name); - - -- -- Name: DomainHistoryHost fka9woh3hu8gx5x0vly6bai327n; Type: FK CONSTRAINT; Schema: public; Owner: - --