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: + * + *
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