From b35026b30d26c86ec4095db04eb898958d65068b Mon Sep 17 00:00:00 2001 From: gbrodman Date: Mon, 9 Sep 2019 14:27:52 -0400 Subject: [PATCH] Add naming strategy (#256) * Add naming strategy * Add test for formatting in GenerateSqlSchemaCommandTest * "domain" -> "Domain" * Call site literals * checkstyle * varchar -> text * Fix external messaging capitalization typo --- .../registry/model/domain/DomainBase.java | 2 +- .../EntityManagerFactoryProvider.java | 3 + .../persistence/NomulusNamingStrategy.java | 77 +++++++++++++++++++ .../tools/GenerateSqlSchemaCommand.java | 4 + .../tools/GenerateSqlSchemaCommandTest.java | 15 ++-- 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 core/src/main/java/google/registry/persistence/NomulusNamingStrategy.java diff --git a/core/src/main/java/google/registry/model/domain/DomainBase.java b/core/src/main/java/google/registry/model/domain/DomainBase.java index 77473e399..b29f239ac 100644 --- a/core/src/main/java/google/registry/model/domain/DomainBase.java +++ b/core/src/main/java/google/registry/model/domain/DomainBase.java @@ -89,7 +89,7 @@ import org.joda.time.Interval; @ReportedOn @Entity @javax.persistence.Entity -@javax.persistence.Table(name = "domain") +@javax.persistence.Table(name = "Domain") @ExternalMessagingName("domain") public class DomainBase extends EppResource implements ForeignKeyedEppResource, ResourceWithTransferData { diff --git a/core/src/main/java/google/registry/persistence/EntityManagerFactoryProvider.java b/core/src/main/java/google/registry/persistence/EntityManagerFactoryProvider.java index 3ba3fe4c5..ecff1d2b3 100644 --- a/core/src/main/java/google/registry/persistence/EntityManagerFactoryProvider.java +++ b/core/src/main/java/google/registry/persistence/EntityManagerFactoryProvider.java @@ -47,6 +47,9 @@ public class EntityManagerFactoryProvider { // SessionFactory is created. Setting it to 'none' to turn off the feature. properties.put(Environment.HBM2DDL_AUTO, "none"); + properties.put( + Environment.PHYSICAL_NAMING_STRATEGY, NomulusNamingStrategy.class.getCanonicalName()); + properties.put(Environment.ISOLATION, getHibernateConnectionIsolation()); properties.put(Environment.SHOW_SQL, getHibernateLogSqlQueries()); properties.put(HIKARI_CONNECTION_TIMEOUT, getHibernateHikariConnectionTimeout()); diff --git a/core/src/main/java/google/registry/persistence/NomulusNamingStrategy.java b/core/src/main/java/google/registry/persistence/NomulusNamingStrategy.java new file mode 100644 index 000000000..cb22f8924 --- /dev/null +++ b/core/src/main/java/google/registry/persistence/NomulusNamingStrategy.java @@ -0,0 +1,77 @@ +// Copyright 2019 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.persistence; + +import com.google.common.base.CaseFormat; +import org.hibernate.boot.model.naming.Identifier; +import org.hibernate.boot.model.naming.PhysicalNamingStrategy; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; + +/** + * Nomulus naming strategy for Hibernate ORM. + * + *

This class applies the following naming strategies to protect readability of SQL statements: + * + *

+ * + * These strategies ensure that both types of names are readable on case-insensitive platforms, and + * are easily distinguishable from each other. + * + *

The use of quoted names may introduce portability problems with hand-crafted SQL queries, + * e.g., between postgresql (which only accepts double-quotes) and MySQL(which only accepts + * back-quotes). This gives us incentives for adopting SQL query builders such as JOOQ for reporting + * etc. + */ +public class NomulusNamingStrategy implements PhysicalNamingStrategy { + + @Override + public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment jdbcEnvironment) { + return name; + } + + @Override + public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) { + return name; + } + + @Override + public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) { + if (name.isQuoted()) { + return name; + } + return jdbcEnvironment.getIdentifierHelper().toIdentifier(name.getText(), /* quoted= */ true); + } + + @Override + public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment jdbcEnvironment) { + return name; + } + + @Override + public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) { + if (name.isQuoted()) { + return name; + } + // Convert the lowerCamelCase field name into the snake_case column name + return jdbcEnvironment + .getIdentifierHelper() + .toIdentifier( + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, name.getText()), + /* quoted= */ false); + } +} diff --git a/core/src/main/java/google/registry/tools/GenerateSqlSchemaCommand.java b/core/src/main/java/google/registry/tools/GenerateSqlSchemaCommand.java index 2aa6bfdaf..b861cbe98 100644 --- a/core/src/main/java/google/registry/tools/GenerateSqlSchemaCommand.java +++ b/core/src/main/java/google/registry/tools/GenerateSqlSchemaCommand.java @@ -27,6 +27,7 @@ import google.registry.model.domain.secdns.DelegationSignerData; import google.registry.model.eppcommon.Trid; import google.registry.model.transfer.BaseTransferObject; import google.registry.model.transfer.TransferData; +import google.registry.persistence.NomulusNamingStrategy; import google.registry.schema.tld.PremiumList; import google.registry.schema.tmch.ClaimsList; import java.io.IOException; @@ -38,6 +39,7 @@ import java.util.HashMap; import java.util.Map; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Environment; import org.hibernate.dialect.PostgreSQL95Dialect; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.hibernate.tool.schema.TargetType; @@ -150,6 +152,8 @@ public class GenerateSqlSchemaCommand implements Command { settings.put("hibernate.connection.password", "domain-registry"); settings.put("hibernate.hbm2ddl.auto", "none"); settings.put("show_sql", "true"); + settings.put( + Environment.PHYSICAL_NAMING_STRATEGY, NomulusNamingStrategy.class.getCanonicalName()); MetadataSources metadata = new MetadataSources(new StandardServiceRegistryBuilder().applySettings(settings).build()); diff --git a/core/src/test/java/google/registry/tools/GenerateSqlSchemaCommandTest.java b/core/src/test/java/google/registry/tools/GenerateSqlSchemaCommandTest.java index f9f0fb909..b9f63fc02 100644 --- a/core/src/test/java/google/registry/tools/GenerateSqlSchemaCommandTest.java +++ b/core/src/test/java/google/registry/tools/GenerateSqlSchemaCommandTest.java @@ -11,12 +11,13 @@ // 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; -// import static org.mockito.Mockito.mock; - import static com.google.common.truth.Truth.assertThat; +import static java.nio.charset.StandardCharsets.UTF_8; +import com.google.common.io.Files; import java.io.File; import org.junit.Before; import org.junit.ClassRule; @@ -57,10 +58,14 @@ public class GenerateSqlSchemaCommandTest extends CommandTestCase