jdaugherty commented on code in PR #16572:
URL: https://github.com/apache/grails-core/pull/16572#discussion_r4361364345
##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/HibernateSession.groovy:
##########
@@ -76,8 +67,10 @@
* @author Graeme Rocher
* @since 1.0
*/
-@SuppressWarnings({"rawtypes", "PMD.DataflowAnomalyAnalysis",
"PMD.AvoidDuplicateLiterals"})
-public class HibernateSession extends AbstractAttributeStoringSession
implements QueryAliasAwareSession {
+// TODO(groovyism-cleanup): semicolons + double-quoted strings kept to
preserve rename-similarity against the original .java (see matrei's review on
#16576). Removed by the stacked groovyism-cleanup PR.
Review Comment:
This comment, and the `@SuppressWarnings('UnnecessarySemicolon')` on the
package statement above, are in 93 files, and the reason they give is gone: the
move commit preserves the history now, not the similarity of this diff. What is
left is two styles across the 324 converted files, chosen by a git heuristic:
136 files keep 5,431 lines ending in a semicolon (1,423 imports and 119 package
statements among them), 47 class-level suppressions hide `UnnecessaryGString`
over 607 double-quoted strings without interpolation, and 188 files are already
clean. Please strip the semicolons and the plain double quotes in the convert
commit and delete the suppressions and these comments, so CodeNarc enforces it
from here. The semicolons are a `sed -E 's/;[[:space:]]*$//'` over the
converted files (or the semicolon step of the `codenarcFix` task; its GString
step also rewrites quotes inside comments and the license headers, so that
output can't be taken as is). `codenarcTest` is skipped in this b
uild, so the 43 test and fixture files in `dbmigration-core` that have
semicolons and no suppression need the same pass by hand.
##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/domainbinding/util/OrderByClauseBuilder.groovy:
##########
@@ -16,110 +16,120 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.grails.orm.hibernate.cfg.domainbinding.util;
+package org.grails.orm.hibernate.cfg.domainbinding.util
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Locale;
-import java.util.stream.Collectors;
+import groovy.transform.CompileStatic
+import groovy.transform.PackageScope
+import org.hibernate.boot.model.internal.BinderHelper
+import org.hibernate.mapping.PersistentClass
+import org.hibernate.mapping.Property
+import org.hibernate.mapping.SingleTableSubclass
+import org.hibernate.mapping.Selectable
-import org.hibernate.boot.model.internal.BinderHelper;
-import org.hibernate.mapping.PersistentClass;
-import org.hibernate.mapping.Property;
-import org.hibernate.mapping.SingleTableSubclass;
-
-import org.grails.datastore.mapping.model.DatastoreConfigurationException;
+import org.grails.datastore.mapping.model.DatastoreConfigurationException
/** Utility class to build SQL order by clauses from HQL-style order by
strings. */
-@SuppressWarnings("PMD.DataflowAnomalyAnalysis")
-public class OrderByClauseBuilder {
+@CompileStatic
+@SuppressWarnings('PMD.DataflowAnomalyAnalysis')
+class OrderByClauseBuilder {
- public String buildOrderByClause(
+ String buildOrderByClause(
String hqlOrderBy, PersistentClass associatedClass, String role,
String defaultOrder) {
if (hqlOrderBy == null) {
- return null;
+ return null
}
if (hqlOrderBy.isEmpty()) {
- return associatedClass.getIdentifier().getSelectables().stream()
- .map(selectable -> selectable.getText() + " asc")
- .collect(Collectors.joining(", "));
+ List<String> parts = []
+ for (Selectable selectable :
associatedClass.identifier.selectables) {
+ parts.add(selectable.text + ' asc')
+ }
+ return parts.join(', ')
}
- List<SortEntry> entries = parseSortEntries(hqlOrderBy, role,
defaultOrder);
+ List<SortEntry> entries = parseSortEntries(hqlOrderBy, role,
defaultOrder)
- return entries.stream()
- .map(entry -> buildPropertyOrderBy(entry, associatedClass))
- .collect(Collectors.joining(", "));
+ List<String> parts = []
+ for (SortEntry entry : entries) {
+ parts.add(buildPropertyOrderBy(entry, associatedClass))
+ }
+ return parts.join(', ')
}
private List<SortEntry> parseSortEntries(String hqlOrderBy, String role,
String defaultOrder) {
- String[] tokens = hqlOrderBy.split("[ ,]+");
- List<SortEntry> entries = new ArrayList<>();
- SortEntry currentEntry = null;
+ String[] tokens = hqlOrderBy.split('[ ,]+')
+ List<SortEntry> entries = new ArrayList<>()
+ SortEntry currentEntry = null
for (String token : tokens) {
- if (token.isEmpty()) continue;
+ if (token.isEmpty()) {
+ continue
+ }
if (isDirectionToken(token)) {
if (currentEntry == null || currentEntry.direction != null) {
throw new DatastoreConfigurationException(
- "Error while parsing sort clause: " + hqlOrderBy +
" (" + role + ")");
+ "Error while parsing sort clause: ${hqlOrderBy}
(${role})".toString())
}
- currentEntry.direction = token.toLowerCase(Locale.ROOT);
- } else {
+ currentEntry.direction = token.toLowerCase(Locale.ROOT)
Review Comment:
`javap` shows this write, and the two below it, compile to
`ScriptBytecodeAdapter.setGroovyObjectProperty`: `direction` is a
`@PackageScope` field of a private nested class, written from the outer class.
It isn't in the description's list of remaining dynamic sites.
`currentEntry.@direction = …` (or a setter on `SortEntry`) makes it a field
write.
##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/cfg/PersistentEntityNamingStrategy.groovy:
##########
@@ -16,26 +16,27 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.grails.orm.hibernate.cfg;
+package org.grails.orm.hibernate.cfg
-import
org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity;
-import
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty;
+import
org.grails.orm.hibernate.cfg.domainbinding.hibernate.GrailsHibernatePersistentEntity
+import
org.grails.orm.hibernate.cfg.domainbinding.hibernate.HibernatePersistentProperty
/**
* Allows plugging into to custom naming strategies
*
* @author Graeme Rocher
* @since 5.0
*/
-public interface PersistentEntityNamingStrategy {
+interface PersistentEntityNamingStrategy {
Review Comment:
Default methods are code, so this interface needs `@CompileStatic` like
every other converted type; without it their bodies compile dynamically. `grep
-L '@CompileStatic'` over the moved files finds this one plus 14 converted
tests and fixtures in `dbmigration-core` that have none either:
`ColumnRemarksIntegrationTest`, `HibernateIndexDifferenceSuppressionTest`,
`CustomIdGeneratorTest`, `IdentifierGeneratorSnapshotTest`,
`NativeGeneratorAutoIncrementTest`, `NativeGeneratorSequenceTest`,
`SequenceGeneratorTest`, `columnremarks/Item`, `CustomIdEntity`,
`NativeGenEntity`, `SnowflakeId`, `SnowflakeIdGenerator`, `ForcedTableEntity`,
`QualifiedSequenceEntity` (the batch #16497 added; the older fixtures have it).
The remaining hits are pure interfaces and `ManagedEntity`, which need nothing.
##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/HqlQueryContext.groovy:
##########
@@ -52,83 +43,102 @@
*
* <p>Use {@link #prepare} to build an instance from raw inputs.
*/
-@SuppressWarnings({
+// TODO(groovyism-cleanup): semicolons + double-quoted strings kept to
preserve rename-similarity against the original .java (see matrei's review on
#16576). Removed by the stacked groovyism-cleanup PR.
+@CompileStatic
+@SuppressWarnings([
"PMD.AvoidDuplicateLiterals",
"PMD.DataflowAnomalyAnalysis",
"PMD.AvoidLiteralsInIfCondition",
- "PMD.UseLocaleWithCaseConversions"
-})
-public record HqlQueryContext(
+ 'PMD.UseLocaleWithCaseConversions',
+ 'ClassStartsWithBlankLine',
+ 'Indentation',
+ 'UnnecessarySemicolon',
+ 'UnnecessaryGString'
+])
+@RecordOptions(getAt = false, toList = false, toMap = false, size = false)
+@TupleConstructor(defaults = false)
Review Comment:
The public `Map` constructor is still generated: `javap` shows
`HqlQueryContext(java.util.Map)`, and those constructors are the only place in
the converted classes where `InvokerHelper.createAssertError` appears (9 sites
here, 10 in `HibernateQueryExecutor`, 4 each in `HibernateAlias` and
`PropertyArithmetic`). `@TupleConstructor(defaults = false, namedVariant =
false)` removes it.
##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.groovy:
##########
@@ -134,111 +127,113 @@ public class GrailsHibernateTemplate implements
IHibernateTemplate {
*
* @see #setFlushMode
*/
- public static final int FLUSH_ALWAYS = 4;
-
- private static final Logger LOG =
LoggerFactory.getLogger(GrailsHibernateTemplate.class);
- protected boolean exposeNativeSession = true;
- protected boolean cacheQueries = false;
- protected SessionFactory sessionFactory;
- protected DataSource dataSource = null;
- protected SQLExceptionTranslator jdbcExceptionTranslator;
- protected int flushMode = FLUSH_AUTO;
- private boolean osivReadOnly;
- private boolean passReadOnlyToHibernate = false;
- private boolean applyFlushModeOnlyToNonExistingTransactions = false;
- protected TransactionResources txResources = new
DefaultTransactionResources();
+ public static final int FLUSH_ALWAYS = 4
+
+ private static final Logger LOG =
LoggerFactory.getLogger(GrailsHibernateTemplate)
+ protected boolean exposeNativeSession = true
+ protected boolean cacheQueries = false
+ protected SessionFactory sessionFactory
+ protected DataSource dataSource = null
+ protected SQLExceptionTranslator jdbcExceptionTranslator
+ protected int flushMode = FLUSH_AUTO
+ private boolean osivReadOnly
+ private boolean passReadOnlyToHibernate = false
+ private boolean applyFlushModeOnlyToNonExistingTransactions = false
+ protected TransactionResources txResources = new
DefaultTransactionResources()
protected GrailsHibernateTemplate() {
// for testing
}
- public GrailsHibernateTemplate(SessionFactory sessionFactory) {
- Assert.notNull(sessionFactory, "Property 'sessionFactory' is
required");
- this.sessionFactory = sessionFactory;
+ GrailsHibernateTemplate(SessionFactory sessionFactory) {
+ Assert.notNull(sessionFactory, "Property 'sessionFactory' is required")
+ this.sessionFactory = sessionFactory
ConnectionProvider connectionProvider = ((SessionFactoryImplementor)
sessionFactory)
- .getServiceRegistry()
- .getService(ConnectionProvider.class);
- this.dataSource = connectionProvider != null ?
connectionProvider.unwrap(DataSource.class) : null;
+ .serviceRegistry
+ .getService(ConnectionProvider)
+ this.dataSource = connectionProvider != null ?
connectionProvider.unwrap(DataSource) : null
if (this.dataSource != null) {
if (this.dataSource instanceof TransactionAwareDataSourceProxy) {
- DataSource target = ((TransactionAwareDataSourceProxy)
this.dataSource).getTargetDataSource();
+ DataSource target = ((TransactionAwareDataSourceProxy)
this.dataSource).targetDataSource
if (target != null) {
- this.dataSource = target;
+ this.dataSource = target
}
}
- jdbcExceptionTranslator = new
SQLErrorCodeSQLExceptionTranslator(this.dataSource);
+ jdbcExceptionTranslator = new
SQLErrorCodeSQLExceptionTranslator(this.dataSource)
} else {
// must be in unit test mode, setup default translator
SQLErrorCodeSQLExceptionTranslator
sqlErrorCodeSQLExceptionTranslator =
- new SQLErrorCodeSQLExceptionTranslator();
- sqlErrorCodeSQLExceptionTranslator.setDatabaseProductName("H2");
- jdbcExceptionTranslator = sqlErrorCodeSQLExceptionTranslator;
+ new SQLErrorCodeSQLExceptionTranslator()
+ sqlErrorCodeSQLExceptionTranslator.databaseProductName = 'H2'
+ jdbcExceptionTranslator = sqlErrorCodeSQLExceptionTranslator
}
}
- public GrailsHibernateTemplate(SessionFactory sessionFactory,
HibernateDatastore datastore) {
- this(sessionFactory);
+ GrailsHibernateTemplate(SessionFactory sessionFactory, HibernateDatastore
datastore) {
+ this(sessionFactory)
if (datastore != null) {
- cacheQueries = datastore.isCacheQueries();
- this.osivReadOnly = datastore.isOsivReadOnly();
- this.passReadOnlyToHibernate =
datastore.isPassReadOnlyToHibernate();
- this.flushMode =
hibernateFlushModeToConstant(datastore.getDefaultFlushMode());
+ cacheQueries = datastore.isCacheQueries()
+ this.osivReadOnly = datastore.isOsivReadOnly()
+ this.passReadOnlyToHibernate =
datastore.isPassReadOnlyToHibernate()
+ this.flushMode =
hibernateFlushModeToConstant(datastore.defaultFlushMode)
}
}
- public GrailsHibernateTemplate(SessionFactory sessionFactory,
HibernateDatastore datastore, int defaultFlushMode) {
- this(sessionFactory);
+ GrailsHibernateTemplate(SessionFactory sessionFactory, HibernateDatastore
datastore, int defaultFlushMode) {
+ this(sessionFactory)
if (datastore != null) {
- cacheQueries = datastore.isCacheQueries();
- this.osivReadOnly = datastore.isOsivReadOnly();
- this.passReadOnlyToHibernate =
datastore.isPassReadOnlyToHibernate();
+ cacheQueries = datastore.isCacheQueries()
+ this.osivReadOnly = datastore.isOsivReadOnly()
+ this.passReadOnlyToHibernate =
datastore.isPassReadOnlyToHibernate()
}
- this.flushMode = defaultFlushMode;
+ this.flushMode = defaultFlushMode
}
/** Maps a Hibernate {@link FlushMode} to one of the {@code FLUSH_*}
constants of this class. */
- static int hibernateFlushModeToConstant(FlushMode mode) {
- return switch (mode) {
- case MANUAL -> FLUSH_NEVER;
- case COMMIT -> FLUSH_COMMIT;
- case ALWAYS -> FLUSH_ALWAYS;
- default -> FLUSH_AUTO;
- };
+ private static int hibernateFlushModeToConstant(FlushMode mode) {
Review Comment:
`private` here, package-private in Java, and `GrailsHibernateTemplateSpec`
still calls it; that only works because the spec is dynamic Groovy.
`@PackageScope` keeps the Java visibility and keeps the spec on a real API.
##########
grails-data-hibernate7/core/src/main/groovy/grails/orm/HibernateCriteriaBuilder.groovy:
##########
@@ -1219,37 +1215,37 @@ public ProjectionList sqlGroupProjection(String sql,
String groupBy, List<String
*/
private <T> T closingSessionOnError(Supplier<T> projections) {
try {
- return projections.get();
+ return projections.get()
} catch (IllegalArgumentException e) {
- closeSessionFollowingException();
- throw e;
+ closeSessionFollowingException()
+ throw e
}
}
/**
* Restricts the results with a native SQL condition. {@code {alias}} in
the SQL stands for the table alias of
* the queried entity.
*
- * @param sqlRestriction the SQL condition
+ * @param sql the SQL condition
* @return this criteria
*/
- public org.grails.datastore.mapping.query.api.Criteria
sqlRestriction(String sqlRestriction) {
- return sqlRestriction(sqlRestriction, Collections.emptyList());
+ org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sql)
{
Review Comment:
The parameter was `sqlRestriction` in Java (here, in the two-argument
overload and in `HibernateDetachedCriteriaExtension`), and the Javadoc `@param`
moved with it. Callers don't notice, but the conversion shouldn't rename public
parameters; please keep the Java names.
##########
grails-data-hibernate7/dbmigration-core/src/test/groovy/liquibase/ext/hibernate/database/HibernateDatabasePojoTest.groovy:
##########
@@ -0,0 +1,22 @@
+package liquibase.ext.hibernate.database
+
+import org.junit.Test
+
+import static org.junit.Assert.assertFalse
+
+/**
+ * {@link HibernateDatabase} has a public {@code getProperty(String)} that
returns a connection property.
+ * A Groovy class would take it for the {@code GroovyObject} hook behind every
dynamic property access,
+ * so the whole family is compiled without {@code GroovyObject}.
+ */
+class HibernateDatabasePojoTest {
Review Comment:
New Grails test, not fork code, so it needs the ASF header. RAT doesn't see
it because `database/**` is excluded wholesale.
##########
grails-data-hibernate7/dbmigration-core/src/test/groovy/liquibase/ext/hibernate/HibernateIntegrationTest.groovy:
##########
@@ -1,81 +1,79 @@
-package liquibase.ext.hibernate;
+package liquibase.ext.hibernate
-import liquibase.Liquibase;
-import liquibase.Scope;
-import liquibase.database.Database;
-import liquibase.database.core.H2Database;
-import liquibase.database.jvm.JdbcConnection;
-import liquibase.diff.DiffResult;
-import liquibase.diff.Difference;
-import liquibase.diff.ObjectDifferences;
-import liquibase.diff.compare.CompareControl;
-import liquibase.diff.output.DiffOutputControl;
-import liquibase.diff.output.changelog.DiffToChangeLog;
-import liquibase.diff.output.report.DiffToReport;
-import liquibase.ext.hibernate.database.HibernateClassicDatabase;
-import liquibase.ext.hibernate.database.connection.HibernateConnection;
-import liquibase.resource.ClassLoaderResourceAccessor;
-import liquibase.resource.DirectoryResourceAccessor;
-import liquibase.structure.DatabaseObject;
-import liquibase.structure.core.*;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
+import java.io.*
Review Comment:
Wildcard imports, here and in `SpringPackageScanningIntegrationTest`; the
repository rule is explicit imports, fork test or not.
##########
grails-doc/src/en/guide/upgrading/upgrading80x.adoc:
##########
@@ -1449,6 +1449,12 @@ class SportsCar extends Car {
}
----
+===== 26.11 Custom User Types
Review Comment:
This section is #16695's (see the comment on `CompositeUserTypeBinder`); it
goes with the rest of that PR.
##########
grails-data-hibernate7/core/src/main/groovy/org/grails/orm/hibernate/query/SqlRestriction.groovy:
##########
@@ -34,100 +33,106 @@
* @param values the values of the {@code ?} placeholders, in order
* @since 8.0.0
*/
-public record SqlRestriction(String sql, List<?> values) implements
Query.Criterion {
+@CompileStatic
+record SqlRestriction(String sql, List<?> values) implements Query.Criterion {
Review Comment:
Public API (`@since 8.0.0`) and still without the record options the other
records got: `SqlRestriction()`, `SqlRestriction(String)`,
`SqlRestriction(Map)`, `getAt`, `toList`, `toMap` and `size` are all generated.
Same for `GroovyProxyInterceptorLogic.InterceptorState`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]