From c0db2c7e5e244e0554bb6e41347fd2a125350569 Mon Sep 17 00:00:00 2001 From: estradaw Date: Tue, 14 Jan 2025 17:18:25 -0600 Subject: [PATCH 0001/1008] project compiles with multitenancy turned off --- .../build.gradle | 5 +- gradle.properties | 3 +- grails-datastore-gorm-hibernate/build.gradle | 18 +- .../grails/orm/HibernateCriteriaBuilder.java | 196 +-- .../groovy/grails/orm/PagedResultList.java | 94 -- .../groovy/grails/orm/RlikeExpression.java | 86 -- .../AbstractHibernateGormInstanceApi.groovy | 16 +- .../AbstractHibernateGormStaticApi.groovy | 188 ++- .../hibernate/AbstractHibernateSession.java | 15 +- .../hibernate/EventListenerIntegrator.java | 2 +- .../hibernate/GrailsHibernateTemplate.java | 35 +- .../hibernate/HibernateGormStaticApi.groovy | 17 +- .../orm/hibernate/HibernateSession.java | 9 +- .../orm/hibernate/IHibernateTemplate.java | 5 +- .../access/TraitPropertyAccessStrategy.java | 10 +- .../orm/hibernate/cfg/GrailsDomainBinder.java | 128 +- .../hibernate/cfg/GrailsHibernateUtil.java | 274 +--- .../cfg/GrailsIdentifierGeneratorFactory.java | 46 - .../cfg/HibernateMappingContext.java | 2 - .../HibernateMappingContextConfiguration.java | 22 +- .../orm/hibernate/cfg/IdentityEnumType.java | 46 +- .../proxy/HibernateProxyHandler.java | 166 -- .../proxy/SimpleHibernateProxyHandler.java | 171 --- .../AbstractHibernateCriteriaBuilder.java | 1361 +++++------------ .../AbstractHibernateCriterionAdapter.java | 565 ------- .../query/AbstractHibernateQuery.java | 630 +------- .../query/GrailsHibernateQueryUtils.java | 137 +- .../query/HibernateCriterionAdapter.java | 48 - .../query/HibernateProjectionAdapter.java | 84 - .../orm/hibernate/query/HibernateQuery.java | 84 +- .../support/ClosureEventListener.java | 8 +- .../ClosureEventTriggeringInterceptor.java | 15 +- .../HibernateDialectDetectorFactoryBean.java | 30 +- .../support/HibernateRuntimeUtils.groovy | 9 +- .../support/HibernateVersionSupport.java | 88 -- .../grails/gorm/tests/ToOneProxySpec.groovy | 34 - .../gorm/tests/hasmany/Something.groovy | 14 + .../tests/proxy/ByteBuddyProxySpec.groovy | 22 +- .../gorm/tests/proxy/StaticTestUtil.groovy | 8 +- ...taSourceConnectionSourceFactorySpec.groovy | 2 +- ...ibernateConnectionSourceFactorySpec.groovy | 2 +- ...bernateConnectionSourceSettingsSpec.groovy | 2 +- .../PartitionedMultiTenancySpec.groovy | 2 + .../connections/SchemaMultiTenantSpec.groovy | 2 + .../SimpleHibernateProxyHandlerSpec.groovy | 47 - grails-plugin/build.gradle | 4 +- ...ibernatePersistenceContextInterceptor.java | 38 +- settings.gradle | 8 +- 48 files changed, 885 insertions(+), 3913 deletions(-) delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/PagedResultList.java delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/RlikeExpression.java delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsIdentifierGeneratorFactory.java delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateCriterionAdapter.java delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateProjectionAdapter.java delete mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateVersionSupport.java delete mode 100644 grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ToOneProxySpec.groovy create mode 100644 grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/Something.groovy delete mode 100644 grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandlerSpec.groovy diff --git a/examples/grails-partitioned-multi-tenancy/build.gradle b/examples/grails-partitioned-multi-tenancy/build.gradle index fe681a2d654..7befc797c69 100644 --- a/examples/grails-partitioned-multi-tenancy/build.gradle +++ b/examples/grails-partitioned-multi-tenancy/build.gradle @@ -9,7 +9,10 @@ version = rootProject.version group = 'examples' dependencies { - implementation platform("org.grails:grails-bom:$grailsVersion") + implementation("org.hibernate.orm:hibernate-core:$hibernateVersion") + implementation platform("org.grails:grails-bom:$grailsVersion") ,{ + exclude group:'org.hibernate', module:'hibernate-core-jakarta' + } implementation project(':grails-plugin') implementation 'org.grails:grails-core' diff --git a/gradle.properties b/gradle.properties index 9bdcfa8178e..68daeb12482 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,7 +5,8 @@ gradleNexusPublishPluginVersion=2.0.0 grailsGradlePluginVersion=7.0.0-M2 grailsVersion=7.0.0-M1 groovyVersion=4.0.24 -hibernateVersion=5.6.15.Final +oldHibernateVersion=5.6.15.Final +hibernateVersion=6.6.4.Final yakworksHibernateGroovyProxyVersion=1.1 micronautPlatformVersion=4.6.3 picocliVersion=4.7.6 diff --git a/grails-datastore-gorm-hibernate/build.gradle b/grails-datastore-gorm-hibernate/build.gradle index 707102e659f..2c1909118a0 100644 --- a/grails-datastore-gorm-hibernate/build.gradle +++ b/grails-datastore-gorm-hibernate/build.gradle @@ -6,7 +6,7 @@ dependencies { api "org.apache.groovy:groovy" api "org.grails:grails-datastore-gorm" api "org.springframework:spring-orm" - api "org.hibernate:hibernate-core-jakarta:$hibernateVersion", { + api "org.hibernate.orm:hibernate-core:$hibernateVersion", { exclude group:'commons-logging', module:'commons-logging' exclude group:'com.h2database', module:'h2' exclude group:'commons-collections', module:'commons-collections' @@ -20,8 +20,11 @@ dependencies { exclude group:'commons-collections', module:'commons-collections' exclude group:'org.slf4j', module:'slf4j-api' } + api ('org.checkerframework:checker-qual:3.48.4') - compileOnly "org.hibernate:hibernate-ehcache:$hibernateVersion", { + api( 'org.jboss:jandex:3.2.3') + + compileOnly "org.hibernate:hibernate-jcache:$hibernateVersion", { exclude group:'commons-collections', module:'commons-collections' exclude group:'commons-logging', module:'commons-logging' exclude group:'com.h2database', module:'h2' @@ -42,12 +45,13 @@ dependencies { } testImplementation "com.h2database:h2" - testImplementation "org.hibernate:hibernate-ehcache:$hibernateVersion" +// testImplementation "org.hibernate:hibernate-ehcache:$oldHibernateVersion" + testImplementation "org.hibernate:hibernate-jcache:$hibernateVersion" // groovy proxy fixes bytebuddy to be a bit smarter when it comes to groovy metaClass - testImplementation "org.yakworks:hibernate-groovy-proxy:$yakworksHibernateGroovyProxyVersion", { - exclude group: "org.codehaus.groovy", module: "groovy" - } +// testImplementation "org.yakworks:hibernate-groovy-proxy:$yakworksHibernateGroovyProxyVersion", { +// exclude group: "org.codehaus.groovy", module: "groovy" +// } testImplementation "org.apache.tomcat:tomcat-jdbc" testRuntimeOnly "org.springframework:spring-aop" @@ -55,7 +59,7 @@ dependencies { testRuntimeOnly "org.slf4j:slf4j-simple" testRuntimeOnly "org.slf4j:jcl-over-slf4j" // The groovydoc task needs the Hibernate 4.x jars in the classpath - documentation "org.hibernate:hibernate-core-jakarta:${hibernateVersion}" + documentation "org.hibernate.orm:hibernate-core:${hibernateVersion}" } test { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java index 561ca60ac40..0fb41ca385b 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java @@ -16,30 +16,33 @@ package grails.orm; import groovy.lang.GroovySystem; -import org.grails.datastore.mapping.model.PersistentEntity; +import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.PluralAttribute; +import org.grails.datastore.mapping.query.api.Criteria; import org.grails.orm.hibernate.GrailsHibernateTemplate; import org.grails.orm.hibernate.HibernateDatastore; -import org.grails.orm.hibernate.cfg.GrailsHibernateUtil; -import org.grails.orm.hibernate.query.*; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; +import org.grails.orm.hibernate.query.AbstractHibernateCriteriaBuilder; import org.hibernate.SessionFactory; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.Projection; -import org.hibernate.criterion.ProjectionList; -import org.hibernate.criterion.Projections; -import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.sql.JoinType; +import org.hibernate.type.BasicTypeReference; import org.hibernate.type.StandardBasicTypes; import org.hibernate.type.Type; import org.springframework.orm.hibernate5.SessionHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; -import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.PluralAttribute; +import java.io.Serializable; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URL; +import java.sql.Blob; +import java.sql.Clob; +import java.util.Calendar; +import java.util.Currency; +import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.TimeZone; +import java.util.UUID; /** *

Wraps the Hibernate Criteria API in a builder. The builder can be retrieved through the "createCriteria()" dynamic static @@ -73,43 +76,43 @@ public class HibernateCriteriaBuilder extends AbstractHibernateCriteriaBuilder { * Define constants which may be used inside of criteria queries * to refer to standard Hibernate Type instances. */ - public static final Type BOOLEAN = StandardBasicTypes.BOOLEAN; - public static final Type YES_NO = StandardBasicTypes.YES_NO; - public static final Type BYTE = StandardBasicTypes.BYTE; - public static final Type CHARACTER = StandardBasicTypes.CHARACTER; - public static final Type SHORT = StandardBasicTypes.SHORT; - public static final Type INTEGER = StandardBasicTypes.INTEGER; - public static final Type LONG = StandardBasicTypes.LONG; - public static final Type FLOAT = StandardBasicTypes.FLOAT; - public static final Type DOUBLE = StandardBasicTypes.DOUBLE; - public static final Type BIG_DECIMAL = StandardBasicTypes.BIG_DECIMAL; - public static final Type BIG_INTEGER = StandardBasicTypes.BIG_INTEGER; - public static final Type STRING = StandardBasicTypes.STRING; - public static final Type NUMERIC_BOOLEAN = StandardBasicTypes.NUMERIC_BOOLEAN; - public static final Type TRUE_FALSE = StandardBasicTypes.TRUE_FALSE; - public static final Type URL = StandardBasicTypes.URL; - public static final Type TIME = StandardBasicTypes.TIME; - public static final Type DATE = StandardBasicTypes.DATE; - public static final Type TIMESTAMP = StandardBasicTypes.TIMESTAMP; - public static final Type CALENDAR = StandardBasicTypes.CALENDAR; - public static final Type CALENDAR_DATE = StandardBasicTypes.CALENDAR_DATE; - public static final Type CLASS = StandardBasicTypes.CLASS; - public static final Type LOCALE = StandardBasicTypes.LOCALE; - public static final Type CURRENCY = StandardBasicTypes.CURRENCY; - public static final Type TIMEZONE = StandardBasicTypes.TIMEZONE; - public static final Type UUID_BINARY = StandardBasicTypes.UUID_BINARY; - public static final Type UUID_CHAR = StandardBasicTypes.UUID_CHAR; - public static final Type BINARY = StandardBasicTypes.BINARY; - public static final Type WRAPPER_BINARY = StandardBasicTypes.WRAPPER_BINARY; - public static final Type IMAGE = StandardBasicTypes.IMAGE; - public static final Type BLOB = StandardBasicTypes.BLOB; - public static final Type MATERIALIZED_BLOB = StandardBasicTypes.MATERIALIZED_BLOB; - public static final Type CHAR_ARRAY = StandardBasicTypes.CHAR_ARRAY; - public static final Type CHARACTER_ARRAY = StandardBasicTypes.CHARACTER_ARRAY; - public static final Type TEXT = StandardBasicTypes.TEXT; - public static final Type CLOB = StandardBasicTypes.CLOB; - public static final Type MATERIALIZED_CLOB = StandardBasicTypes.MATERIALIZED_CLOB; - public static final Type SERIALIZABLE = StandardBasicTypes.SERIALIZABLE; + public static final BasicTypeReference BOOLEAN = StandardBasicTypes.BOOLEAN; + public static final BasicTypeReference YES_NO = StandardBasicTypes.YES_NO; + public static final BasicTypeReference BYTE = StandardBasicTypes.BYTE; + public static final BasicTypeReference CHARACTER = StandardBasicTypes.CHARACTER; + public static final BasicTypeReference SHORT = StandardBasicTypes.SHORT; + public static final BasicTypeReference INTEGER = StandardBasicTypes.INTEGER; + public static final BasicTypeReference LONG = StandardBasicTypes.LONG; + public static final BasicTypeReference FLOAT = StandardBasicTypes.FLOAT; + public static final BasicTypeReference DOUBLE = StandardBasicTypes.DOUBLE; + public static final BasicTypeReference BIG_DECIMAL = StandardBasicTypes.BIG_DECIMAL; + public static final BasicTypeReference BIG_INTEGER = StandardBasicTypes.BIG_INTEGER; + public static final BasicTypeReference STRING = StandardBasicTypes.STRING; + public static final BasicTypeReference NUMERIC_BOOLEAN = StandardBasicTypes.NUMERIC_BOOLEAN; + public static final BasicTypeReference TRUE_FALSE = StandardBasicTypes.TRUE_FALSE; + public static final BasicTypeReference URL = StandardBasicTypes.URL; + public static final BasicTypeReference TIME = StandardBasicTypes.TIME; + public static final BasicTypeReference DATE = StandardBasicTypes.DATE; + public static final BasicTypeReference TIMESTAMP = StandardBasicTypes.TIMESTAMP; + public static final BasicTypeReference CALENDAR = StandardBasicTypes.CALENDAR; + public static final BasicTypeReference CALENDAR_DATE = StandardBasicTypes.CALENDAR_DATE; + public static final BasicTypeReference CLASS = StandardBasicTypes.CLASS; + public static final BasicTypeReference LOCALE = StandardBasicTypes.LOCALE; + public static final BasicTypeReference CURRENCY = StandardBasicTypes.CURRENCY; + public static final BasicTypeReference TIMEZONE = StandardBasicTypes.TIMEZONE; + public static final BasicTypeReference UUID_BINARY = StandardBasicTypes.UUID_BINARY; + public static final BasicTypeReference UUID_CHAR = StandardBasicTypes.UUID_CHAR; + public static final BasicTypeReference BINARY = StandardBasicTypes.BINARY; + public static final BasicTypeReference WRAPPER_BINARY = StandardBasicTypes.WRAPPER_BINARY; + public static final BasicTypeReference IMAGE = StandardBasicTypes.IMAGE; + public static final BasicTypeReference BLOB = StandardBasicTypes.BLOB; + public static final BasicTypeReference MATERIALIZED_BLOB = StandardBasicTypes.MATERIALIZED_BLOB; + public static final BasicTypeReference CHAR_ARRAY = StandardBasicTypes.CHAR_ARRAY; + public static final BasicTypeReference CHARACTER_ARRAY = StandardBasicTypes.CHARACTER_ARRAY; + public static final BasicTypeReference TEXT = StandardBasicTypes.TEXT; + public static final BasicTypeReference CLOB = StandardBasicTypes.CLOB; + public static final BasicTypeReference MATERIALIZED_CLOB = StandardBasicTypes.MATERIALIZED_CLOB; + public static final BasicTypeReference SERIALIZABLE = StandardBasicTypes.SERIALIZABLE; @SuppressWarnings("rawtypes") public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory) { @@ -123,32 +126,9 @@ public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory setDefaultFlushMode(GrailsHibernateTemplate.FLUSH_AUTO); } - /** - * Join an association using the specified join-type, assigning an alias - * to the joined association. - * The joinType is expected to be one of CriteriaSpecification.INNER_JOIN (the default), - * CriteriaSpecificationFULL_JOIN, or CriteriaSpecificationLEFT_JOIN. - * - * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * @param joinType The type of join to use. - * @return this (for method chaining) - * @throws HibernateException Indicates a problem creating the sub criteria - * @see #createAlias(String, String) - */ - public Criteria createAlias(String associationPath, String alias, int joinType) { - return criteria.createAlias(associationPath, alias, JoinType.parse(joinType)); - } - @Override - protected Object executeUniqueResultWithProxyUnwrap() { - return GrailsHibernateUtil.unwrapIfProxy(criteria.uniqueResult()); - } - @Override - protected void cacheCriteriaMapping() { - GrailsHibernateUtil.cacheCriteriaByMapping(datastore, targetClass, criteria); - } + protected Class getClassForAssociationType(Attribute type) { if (type instanceof PluralAttribute) { @@ -159,29 +139,11 @@ protected Class getClassForAssociationType(Attribute type) { @Override protected List createPagedResultList(Map args) { - GrailsHibernateUtil.populateArgumentsForCriteria(datastore, targetClass, criteria, args, conversionService); GrailsHibernateTemplate ght = new GrailsHibernateTemplate(sessionFactory, (HibernateDatastore) datastore, getDefaultFlushMode()); - return new PagedResultList(ght, criteria); + return null; } - /** - * Creates a Criterion with from the specified property name and "rlike" (a regular expression version of "like") expression - * - * @param propertyName The property name - * @param propertyValue The ilike value - * @return A Criterion instance - */ - public org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [rlike] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(new RlikeExpression(propertyName, propertyValue)); - return this; - } @Override protected void createCriteriaInstance() { @@ -193,57 +155,16 @@ protected void createCriteriaInstance() { else { hibernateSession = sessionFactory.openSession(); } - - criteria = hibernateSession.createCriteria(targetClass); + criteria = hibernateSession.getCriteriaBuilder().createQuery(targetClass); cacheCriteriaMapping(); criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteria.getClass()); } } - @Override - protected org.hibernate.criterion.DetachedCriteria convertToHibernateCriteria(QueryableCriteria queryableCriteria) { - return getHibernateDetachedCriteria(new HibernateQuery(criteria, queryableCriteria.getPersistentEntity()), queryableCriteria); - } - - public static org.hibernate.criterion.DetachedCriteria getHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria) { - String alias = queryableCriteria.getAlias(); - return getHibernateDetachedCriteria(query, queryableCriteria, alias); - } - - public static org.hibernate.criterion.DetachedCriteria getHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria, String alias) { - PersistentEntity persistentEntity = queryableCriteria.getPersistentEntity(); - Class targetClass = persistentEntity.getJavaClass(); - org.hibernate.criterion.DetachedCriteria detachedCriteria; + protected void cacheCriteriaMapping() { - if(alias != null) { - detachedCriteria = org.hibernate.criterion.DetachedCriteria.forClass(targetClass, alias); - } - else { - detachedCriteria = org.hibernate.criterion.DetachedCriteria.forClass(targetClass); - } - populateHibernateDetachedCriteria(new HibernateQuery(detachedCriteria,persistentEntity), detachedCriteria, queryableCriteria); - return detachedCriteria; } - private static void populateHibernateDetachedCriteria(AbstractHibernateQuery query, org.hibernate.criterion.DetachedCriteria detachedCriteria, QueryableCriteria queryableCriteria) { - List criteriaList = queryableCriteria.getCriteria(); - for (org.grails.datastore.mapping.query.Query.Criterion criterion : criteriaList) { - Criterion hibernateCriterion = HibernateQuery.HIBERNATE_CRITERION_ADAPTER.toHibernateCriterion(query, criterion, null); - if (hibernateCriterion != null) { - detachedCriteria.add(hibernateCriterion); - } - } - - List projections = queryableCriteria.getProjections(); - ProjectionList projectionList = Projections.projectionList(); - for (org.grails.datastore.mapping.query.Query.Projection projection : projections) { - Projection hibernateProjection = new HibernateProjectionAdapter(projection).toHibernateProjection(); - if (hibernateProjection != null) { - projectionList.add(hibernateProjection); - } - } - detachedCriteria.setProjection(projectionList); - } /** * Closes the session if it is copen @@ -255,4 +176,5 @@ protected void closeSession() { } } + } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/PagedResultList.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/PagedResultList.java deleted file mode 100644 index 5c2a726a7af..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/PagedResultList.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2004-2005 the original author or authors. - * - * 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 grails.orm; - -import org.grails.orm.hibernate.GrailsHibernateTemplate; -import org.grails.orm.hibernate.query.HibernateQuery; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; -import org.hibernate.criterion.Projections; -import org.hibernate.internal.CriteriaImpl; - -import java.sql.SQLException; -import java.util.Iterator; - -/** - * A result list for Criteria list calls, which is aware of the totalCount for - * the paged result. - * - * @author Siegfried Puchbauer - * @since 1.0 - * @deprecated Use {@link org.grails.orm.hibernate.query.PagedResultList} instead. - */ -@SuppressWarnings({"unchecked","rawtypes"}) -@Deprecated -public class PagedResultList extends grails.gorm.PagedResultList { - - private transient GrailsHibernateTemplate hibernateTemplate; - private final Criteria criteria; - - public PagedResultList(GrailsHibernateTemplate template, Criteria crit) { - super(null); - resultList = crit.list(); - criteria = crit; - hibernateTemplate = template; - } - - public PagedResultList(GrailsHibernateTemplate template, HibernateQuery query) { - super(null); - resultList = query.listForCriteria(); - criteria = query.getHibernateCriteria(); - hibernateTemplate = template; - } - - @Override - protected void initialize() { - // no-op, already initialized - } - - @Override - public int getTotalCount() { - if (totalCount == Integer.MIN_VALUE) { - totalCount = hibernateTemplate.execute(new GrailsHibernateTemplate.HibernateCallback() { - public Integer doInHibernate(Session session) throws HibernateException, SQLException { - CriteriaImpl impl = (CriteriaImpl) criteria; - Criteria totalCriteria = session.createCriteria(impl.getEntityOrClassName()); - hibernateTemplate.applySettings(totalCriteria); - - Iterator iterator = impl.iterateExpressionEntries(); - while (iterator.hasNext()) { - CriteriaImpl.CriterionEntry entry = (CriteriaImpl.CriterionEntry) iterator.next(); - totalCriteria.add(entry.getCriterion()); - } - Iterator subcriteriaIterator = impl.iterateSubcriteria(); - while (subcriteriaIterator.hasNext()) { - CriteriaImpl.Subcriteria sub = (CriteriaImpl.Subcriteria) subcriteriaIterator.next(); - totalCriteria.createAlias(sub.getPath(), sub.getAlias(), sub.getJoinType(), sub.getWithClause()); - } - totalCriteria.setProjection(impl.getProjection()); - totalCriteria.setProjection(Projections.rowCount()); - return ((Number)totalCriteria.uniqueResult()).intValue(); - } - }); - } - return totalCount; - } - - public void setTotalCount(int totalCount) { - this.totalCount = totalCount; - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/RlikeExpression.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/RlikeExpression.java deleted file mode 100644 index 1f52809001c..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/RlikeExpression.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2004-2005 the original author or authors. - * - * 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 grails.orm; - -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.criterion.CriteriaQuery; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.MatchMode; -import org.hibernate.dialect.*; -import org.hibernate.engine.spi.TypedValue; - -/** - * Adds support for rlike to Hibernate in supported dialects. - * - * @author Graeme Rocher - * @since 1.1.1 - */ -public class RlikeExpression implements Criterion { - - private static final long serialVersionUID = -214329918050957956L; - - private final String propertyName; - private final Object value; - - public RlikeExpression(String propertyName, Object value) { - this.propertyName = propertyName; - this.value = value; - } - - public RlikeExpression(String propertyName, String value, MatchMode matchMode) { - this(propertyName, matchMode.toMatchString(value)); - } - - public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { - Dialect dialect = criteriaQuery.getFactory().getDialect(); - String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName); - if (columns.length != 1) { - throw new HibernateException("rlike may only be used with single-column properties"); - } - - if (dialect instanceof MySQLDialect) { - return columns[0] + " rlike ?"; - } - - if (isOracleDialect(dialect)) { - return " REGEXP_LIKE (" + columns[0] + ", ?)"; - } - - if (dialect instanceof PostgreSQL81Dialect) { - return columns[0] + " ~* ?"; - } - - if (dialect instanceof H2Dialect) { - return columns[0] + " REGEXP ?"; - } - - throw new HibernateException("rlike is not supported with the configured dialect " + dialect.getClass().getCanonicalName()); - } - - private boolean isOracleDialect(Dialect dialect) { - return (dialect instanceof Oracle8iDialect); - } - - public TypedValue[] getTypedValues(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException { - return new TypedValue[] { criteriaQuery.getTypedValue(criteria, propertyName, value.toString()) }; - } - - @Override - public String toString() { - return propertyName + " rlike " + value; - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy index 54bd7c79223..cd477b9f740 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormInstanceApi.groovy @@ -18,6 +18,7 @@ package org.grails.orm.hibernate import grails.gorm.validation.CascadingValidator import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import jakarta.persistence.FlushModeType import org.grails.datastore.gorm.GormValidateable import org.grails.datastore.mapping.core.Datastore import org.grails.datastore.mapping.dirty.checking.DirtyCheckable @@ -80,7 +81,6 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { protected SessionFactory sessionFactory protected ClassLoader classLoader protected IHibernateTemplate hibernateTemplate - protected ProxyHandler proxyHandler boolean autoFlush @@ -89,7 +89,6 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { this.classLoader = classLoader sessionFactory = datastore.getSessionFactory() this.hibernateTemplate = hibernateTemplate - this.proxyHandler = datastore.mappingContext.getProxyHandler() this.autoFlush = datastore.autoFlush this.failOnError = datastore.failOnError this.markDirty = datastore.markDirty @@ -207,7 +206,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { catch (DataAccessException e) { try { hibernateTemplate.execute { Session session -> - session.flushMode = FlushMode.MANUAL + session.flushMode = FlushModeType.COMMIT } } finally { @@ -223,7 +222,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { @Override boolean instanceOf(D instance, Class cls) { - return proxyHandler.unwrap(instance) in cls + return super.instanceOf(instance, cls) } @Override @@ -286,7 +285,7 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { session.flush() } catch (HibernateException e) { // session should not be flushed again after a data access exception! - session.setFlushMode FlushMode.MANUAL + session.setFlushMode FlushModeType.COMMIT throw e } } @@ -392,13 +391,11 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { if (entity) { for (Association association in entity.associations) { if (association instanceof ToOne && !association instanceof Embedded) { - if(proxyHandler.isInitialized(target, association.name)) { def bean = new BeanWrapperImpl(target) def propertyValue = bean.getPropertyValue(association.name) if (propertyValue != null) { setObjectToReadOnly propertyValue } - } } } } @@ -416,10 +413,9 @@ abstract class AbstractHibernateGormInstanceApi extends GormInstanceApi { */ void setObjectToReadOnly(Object target) { hibernateTemplate.execute { Session session -> - if (session.contains(target) && proxyHandler.isInitialized(target)) { - target = proxyHandler.unwrap(target) + if (session.contains(target)) { session.setReadOnly target, true - session.flushMode = FlushMode.MANUAL + session.flushMode = FlushModeType.COMMIT } } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy index 424fa538f7c..79cf0957f08 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy @@ -2,27 +2,22 @@ package org.grails.orm.hibernate import groovy.transform.CompileDynamic import groovy.transform.CompileStatic -import org.grails.datastore.mapping.proxy.ProxyHandler import org.grails.datastore.mapping.reflect.ClassUtils import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder import org.grails.orm.hibernate.cfg.CompositeIdentity import org.grails.orm.hibernate.exceptions.GrailsQueryException -import org.grails.orm.hibernate.query.GrailsHibernateQueryUtils import org.grails.orm.hibernate.query.HibernateHqlQuery import org.grails.orm.hibernate.support.HibernateRuntimeUtils import org.grails.datastore.gorm.GormStaticApi import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.datastore.gorm.finders.FinderMethod -import org.hibernate.Criteria import org.hibernate.FlushMode import org.hibernate.Session -import org.hibernate.criterion.Example -import org.hibernate.criterion.Restrictions import org.hibernate.jpa.QueryHints import org.hibernate.query.NativeQuery import org.hibernate.query.Query -import org.hibernate.transform.DistinctRootEntityResultTransformer +import org.hibernate.query.criteria.JpaPredicate import org.springframework.core.convert.ConversionService import org.springframework.transaction.PlatformTransactionManager @@ -40,7 +35,7 @@ import jakarta.persistence.criteria.Root @CompileStatic abstract class AbstractHibernateGormStaticApi extends GormStaticApi { - protected ProxyHandler proxyHandler + protected GrailsHibernateTemplate hibernateTemplate protected ConversionService conversionService protected final HibernateSession hibernateSession @@ -60,7 +55,6 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { super(persistentClass, datastore, finders, transactionManager) this.hibernateTemplate = new GrailsHibernateTemplate(datastore.getSessionFactory(), datastore) this.conversionService = datastore.mappingContext.conversionService - this.proxyHandler = datastore.mappingContext.proxyHandler this.hibernateSession = new HibernateSession( (HibernateDatastore)datastore, hibernateTemplate.getSessionFactory(), @@ -99,26 +93,26 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { if(persistentEntity.isMultiTenant()) { // for multi-tenant entities we process get(..) via a query - - (D)hibernateTemplate.execute( { Session session -> - CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() - CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) - Root queryRoot = criteriaQuery.from(persistentEntity.javaClass) - criteriaQuery = criteriaQuery.where ( - //TODO: Remove explicit type cast once GROOVY-9460 - criteriaBuilder.equal((Expression) queryRoot.get(persistentEntity.identity.name), id) - ) - Query criteria = session.createQuery(criteriaQuery) - HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( - hibernateSession, persistentEntity, criteria) - return proxyHandler.unwrap( hibernateHqlQuery.singleResult() ) - } ) + throw new UnsupportedOperationException("no yet") +// (D)hibernateTemplate.execute( { Session session -> +// CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() +// CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) +// Root queryRoot = criteriaQuery.from(persistentEntity.javaClass) +// criteriaQuery = criteriaQuery.where ( +// //TODO: Remove explicit type cast once GROOVY-9460 +// criteriaBuilder.equal((Expression) queryRoot.get(persistentEntity.identity.name), id) +// ) +// Query criteria = session.createQuery(criteriaQuery) +// HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( +// hibernateSession, persistentEntity, criteria) +// return hibernateHqlQuery.singleResult() +// } ) } else { // for non multi-tenant entities we process get(..) via the second level cache - return (D)proxyHandler.unwrap( + hibernateTemplate.get(persistentEntity.javaClass, id) - ) + } } @@ -147,7 +141,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { .setHint(QueryHints.HINT_READONLY, true) HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( hibernateSession, persistentEntity, criteria) - return proxyHandler.unwrap( hibernateHqlQuery.singleResult() ) + return hibernateHqlQuery.singleResult() } ) } @@ -203,7 +197,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { * @param criteria The criteria * @param result The result */ - protected abstract void firePostQueryEvent(Session session, Criteria criteria, Object result) + protected abstract void firePostQueryEvent(Session session, CriteriaQuery criteria, Object result) /** * Fire a pre query event * @@ -211,7 +205,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { * @param criteria The criteria * @return True if the query should be cancelled */ - protected abstract void firePreQueryEvent(Session session, Criteria criteria) + protected abstract void firePreQueryEvent(Session session, CriteriaQuery criteria) @Override boolean exists(Serializable id) { @@ -274,13 +268,13 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { def template = hibernateTemplate queryNamedArgs = new HashMap(queryNamedArgs) return (D) template.execute { Session session -> - Query q = (Query) session.createQuery(queryString) + Query q = (Query) session.createQuery(queryString, persistentEntity.javaClass) template.applySettings(q) populateQueryArguments(q, queryNamedArgs) populateQueryArguments(q, args) populateQueryWithNamedArguments(q, queryNamedArgs) - proxyHandler.unwrap( createHqlQuery(session, q).singleResult() ) + createHqlQuery(session, q).singleResult() } } @@ -298,7 +292,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { args = new HashMap(args) def template = hibernateTemplate return (D) template.execute { Session session -> - Query q = (Query) session.createQuery(queryString) + Query q = (Query) session.createQuery(queryString, persistentEntity.javaClass) template.applySettings(q) params.eachWithIndex { val, int i -> @@ -310,7 +304,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } } populateQueryArguments(q, args) - proxyHandler.unwrap( createHqlQuery(session, q).singleResult() ) + createHqlQuery(session, q).singleResult() } } @@ -539,39 +533,41 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @Override D find(D exampleObject, Map args) { - def template = hibernateTemplate - return (D) template.execute { Session session -> - Example example = Example.create(exampleObject).ignoreCase() - - Criteria crit = session.createCriteria(persistentEntity.javaClass); - hibernateTemplate.applySettings(crit) - crit.add example - GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, crit, args, datastore.mappingContext.conversionService, true) - crit.maxResults = 1 - firePreQueryEvent(session, crit) - List results = crit.list() - firePostQueryEvent(session, crit, results) - if (results) { - return proxyHandler.unwrap( results.get(0) ) - } - } + throw new UnsupportedOperationException("not yet") +// def template = hibernateTemplate +// return (D) template.execute { Session session -> +// Example example = Example.create(exampleObject).ignoreCase() +// +// Criteria crit = session.createCriteria(persistentEntity.javaClass); +// hibernateTemplate.applySettings(crit) +// crit.add example +// GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, crit, args, datastore.mappingContext.conversionService, true) +// crit.maxResults = 1 +// firePreQueryEvent(session, crit) +// List results = crit.list() +// firePostQueryEvent(session, crit, results) +// if (results) { +// return proxyHandler.unwrap( results.get(0) ) +// } +// } } @Override List findAll(D exampleObject, Map args) { - def template = hibernateTemplate - return (List) template.execute { Session session -> - Example example = Example.create(exampleObject).ignoreCase() - - Criteria crit = session.createCriteria(persistentEntity.javaClass); - hibernateTemplate.applySettings(crit) - crit.add example - GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, crit, args, datastore.mappingContext.conversionService, true) - firePreQueryEvent(session, crit) - List results = crit.list() - firePostQueryEvent(session, crit, results) - return results - } + throw new UnsupportedOperationException("not yet") +// def template = hibernateTemplate +// return (List) template.execute { Session session -> +// Example example = Example.create(exampleObject).ignoreCase() +// +// Criteria crit = session.createCriteria(persistentEntity.javaClass); +// hibernateTemplate.applySettings(crit) +// crit.add example +// GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, crit, args, datastore.mappingContext.conversionService, true) +// firePreQueryEvent(session, crit) +// List results = crit.list() +// firePostQueryEvent(session, crit, results) +// return results +// } } @Override @@ -580,20 +576,19 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { (List)hibernateTemplate.execute { Session session -> Map processedQueryMap = [:] queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } - Map queryArgs = filterQueryArgumentMap(processedQueryMap) + Map queryArgs = filterQueryArgumentMap(processedQueryMap) List nullNames = removeNullNames(queryArgs) - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.add(Restrictions.allEq(queryArgs)) - for (name in nullNames) { - criteria.add Restrictions.isNull(name) - } - criteria.setResultTransformer(DistinctRootEntityResultTransformer.INSTANCE) - GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, criteria, args, datastore.mappingContext.conversionService, true) - firePreQueryEvent(session, criteria) - List results = criteria.list() - firePostQueryEvent(session, criteria, results) + CriteriaBuilder cb = session.getCriteriaBuilder() + CriteriaQuery cq = cb.createQuery(persistentEntity.javaClass) + def root = cq.from(persistentEntity.javaClass) + def listOfPredicates = queryArgs.collect { entry -> cb.equal(root.get(entry.key), entry.value) } + def nullPredicates = nullNames.collect { nullName -> root.get(nullName).isNull() } + def jpaPredicates = (listOfPredicates + nullPredicates).toArray(new JpaPredicate[0]) + cq.where(cb.and(jpaPredicates)) + firePreQueryEvent(session, cq) + List results = session.createQuery(cq).resultList + firePostQueryEvent(session, cq, results) return results } } @@ -610,7 +605,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } return (List) template.execute { Session session -> - Query q = (Query) session.createQuery(query.toString()) + Query q = (Query) session.createQuery(query.toString(),persistentEntity.javaClass) template.applySettings(q) populateQueryArguments(q, params) @@ -631,7 +626,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { args = new HashMap(args) return (List) template.execute { Session session -> - Query q = (Query) session.createQuery(query.toString()) + Query q = (Query) session.createQuery(query.toString(),persistentEntity.javaClass) template.applySettings(q) params.eachWithIndex { val, int i -> @@ -653,20 +648,19 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { (D)hibernateTemplate.execute { Session session -> Map processedQueryMap = [:] queryMap.each{ key, value -> processedQueryMap[key.toString()] = value } - Map queryArgs = filterQueryArgumentMap(processedQueryMap) + Map queryArgs = filterQueryArgumentMap(processedQueryMap) List nullNames = removeNullNames(queryArgs) - Criteria criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) - criteria.add(Restrictions.allEq(queryArgs)) - for (name in nullNames) { - criteria.add Restrictions.isNull(name) - } - criteria.setMaxResults(1) - GrailsHibernateQueryUtils.populateArgumentsForCriteria(persistentEntity, criteria, args, datastore.mappingContext.conversionService, true) - firePreQueryEvent(session, criteria) - Object result = criteria.uniqueResult() - firePostQueryEvent(session, criteria, result) - return proxyHandler.unwrap(result) + CriteriaBuilder cb = session.getCriteriaBuilder() + CriteriaQuery cq = cb.createQuery(persistentEntity.javaClass) + def root = cq.from(persistentEntity.javaClass) + def listOfPredicates = queryArgs.collect { entry -> cb.equal(root.get(entry.key), entry.value) } + def nullPredicates = nullNames.collect { nullName -> root.get(nullName).isNull() } + JpaPredicate[] jpaPredicates = (listOfPredicates + nullPredicates).toArray(new JpaPredicate[0]) + cq.where(cb.and(jpaPredicates)) + firePreQueryEvent(session, cq) + Object result = session.createQuery(cq).singleResult + firePostQueryEvent(session, cq, result) + result } } @@ -691,14 +685,16 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { (List)hibernateTemplate.execute { Session session -> def identityType = persistentEntity.identity.type - ids = ids.collect { HibernateRuntimeUtils.convertValueToType((Serializable)it, identityType, conversionService) } - def criteria = session.createCriteria(persistentClass) - hibernateTemplate.applySettings(criteria) def identityName = persistentEntity.identity.name - criteria.add(Restrictions.'in'(identityName, ids)) - firePreQueryEvent(session, criteria) - List results = criteria.list() - firePostQueryEvent(session, criteria, results) + List convertedIds = ids.collect { HibernateRuntimeUtils.convertValueToType((Serializable)it, identityType, conversionService) } + CriteriaBuilder cb = session.getCriteriaBuilder() + CriteriaQuery cq = cb.createQuery(persistentEntity.javaClass) + def root = cq.from(persistentEntity.javaClass) + cq.select(root).where(root.get("id").in(convertedIds)) + firePreQueryEvent(session, cq) + + List results = session.createQuery(cq).resultList + firePostQueryEvent(session, cq, results) def idsMap = [:] for (object in results) { idsMap[object[identityName]] = object @@ -711,8 +707,8 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } } - protected Map filterQueryArgumentMap(Map query) { - def queryArgs = [:] + protected Map filterQueryArgumentMap(Map query) { + Map queryArgs = new HashMap<>() for (entry in query.entrySet()) { if (entry.value instanceof CharSequence) { queryArgs[entry.key] = entry.value.toString() diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateSession.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateSession.java index c4363f00a1d..7711366f449 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateSession.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateSession.java @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; import jakarta.persistence.FlushModeType; @@ -83,7 +84,8 @@ public MappingContext getMappingContext() { } public Serializable persist(Object o) { - return hibernateTemplate.save(o); + hibernateTemplate.save(o); + return null; } public void refresh(Object o) { @@ -118,12 +120,17 @@ public void unlock(Object o) { // do nothing } + /** + * @deprecated persist method needs to be changed to void + * @param objects The Objects + * @return + */ + @Deprecated() public List persist(Iterable objects) { - List identifiers = new ArrayList(); for (Object object : objects) { - identifiers.add(hibernateTemplate.save(object)); + hibernateTemplate.save(object); } - return identifiers; + return Collections.emptyList(); } public T retrieve(Class type, Serializable key) { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/EventListenerIntegrator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/EventListenerIntegrator.java index 52822145861..80ff57d5cad 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/EventListenerIntegrator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/EventListenerIntegrator.java @@ -37,7 +37,7 @@ public EventListenerIntegrator(HibernateEventListeners hibernateEventListeners, } @SuppressWarnings("unchecked") - protected static final List> TYPES = Arrays.asList( + protected static final List> TYPES = Arrays.asList( EventType.AUTO_FLUSH, EventType.MERGE, EventType.PERSIST, diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java index 3b2b07b1a4c..9a4f9a45bae 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/GrailsHibernateTemplate.java @@ -222,12 +222,6 @@ public void applySettings(org.hibernate.query.Query query) { } } - @Override - public void applySettings(Criteria criteria) { - if (exposeNativeSession) { - prepareCriteria(criteria); - } - } public void setCacheQueries(boolean cacheQueries) { this.cacheQueries = cacheQueries; @@ -461,26 +455,7 @@ protected void prepareQuery(org.hibernate.query.Query query) { } } - /** - * Prepare the given Criteria object, applying cache settings and/or a - * transaction timeout. - * - * @param criteria the Criteria object to prepare - * @deprecated Deprecated because Hibernate Criteria are deprecated - */ - @Deprecated - protected void prepareCriteria(Criteria criteria) { - if (cacheQueries) { - criteria.setCacheable(true); - } - if (shouldPassReadOnlyToHibernate()) { - criteria.setReadOnly(true); - } - SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory); - if (sessionHolder != null && sessionHolder.hasTimeout()) { - criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds()); - } - } + /** * Prepare the given Query object, applying cache settings and/or a @@ -541,9 +516,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl if (retVal instanceof org.hibernate.query.Query) { prepareQuery(((org.hibernate.query.Query) retVal)); } - if (retVal instanceof Criteria) { - prepareCriteria(((Criteria) retVal)); - } else if (retVal instanceof Query) { + if (retVal instanceof Query) { prepareCriteria(((Query) retVal)); } @@ -725,8 +698,8 @@ protected DataAccessException convertJdbcAccessException(JDBCException ex, SQLEx return translator.translate("Hibernate operation: " + msg, sql, sqlException); } - public Serializable save(Object o) { - return sessionFactory.getCurrentSession().save(o); + public void save(Object o) { + sessionFactory.getCurrentSession().persist(o); } public void flush() { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy index 7567fa43208..e87dccae7f8 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy @@ -130,10 +130,11 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { @Override GrailsCriteria createCriteria() { - def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) - builder.datastore = (AbstractHibernateDatastore)datastore - builder.conversionService = conversionService - return builder + return null; +// def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) +// builder.datastore = (AbstractHibernateDatastore)datastore +// builder.conversionService = conversionService +// return builder } @Override @@ -217,7 +218,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { } @Override - protected void firePostQueryEvent(Session session, Criteria criteria, Object result) { + protected void firePostQueryEvent(Session session, CriteriaQuery criteria, Object result) { if(result instanceof List) { datastore.applicationEventPublisher.publishEvent( new PostQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity), (List)result)) } @@ -227,7 +228,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { } @Override - protected void firePreQueryEvent(Session session, Criteria criteria) { + protected void firePreQueryEvent(Session session, CriteriaQuery criteria) { datastore.applicationEventPublisher.publishEvent( new PreQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity))) } @@ -250,8 +251,4 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { return query } - @CompileDynamic - protected void setResultTransformer(Criteria c) { - c.resultTransformer = Criteria.DISTINCT_ROOT_ENTITY - } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java index 49dce30d716..2e3b1d0770c 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java @@ -27,10 +27,8 @@ import org.grails.datastore.gorm.timestamp.DefaultTimestampProvider; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.config.GormProperties; -import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.query.event.PostQueryEvent; import org.grails.datastore.mapping.query.event.PreQueryEvent; -import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.grails.orm.hibernate.query.HibernateHqlQuery; import org.grails.orm.hibernate.query.HibernateQuery; import org.grails.datastore.mapping.model.PersistentEntity; @@ -52,7 +50,6 @@ @SuppressWarnings("rawtypes") public class HibernateSession extends AbstractHibernateSession { - ProxyHandler proxyHandler = new HibernateProxyHandler(); DefaultTimestampProvider timestampProvider; public HibernateSession(HibernateDatastore hibernateDatastore, SessionFactory sessionFactory, int defaultFlushMode) { @@ -68,9 +65,6 @@ public HibernateSession(HibernateDatastore hibernateDatastore, SessionFactory se @Override public Serializable getObjectIdentifier(Object instance) { if(instance == null) return null; - if(proxyHandler.isProxy(instance)) { - return ((HibernateProxy)instance).getHibernateLazyInitializer().getIdentifier(); - } Class type = instance.getClass(); ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(type); final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); @@ -181,8 +175,7 @@ public Query createQuery(Class type, String alias) { final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); GrailsHibernateTemplate hibernateTemplate = getHibernateTemplate(); Session currentSession = hibernateTemplate.getSessionFactory().getCurrentSession(); - final Criteria criteria = alias != null ? currentSession.createCriteria(type, alias) : currentSession.createCriteria(type); - hibernateTemplate.applySettings(criteria); + final CriteriaQuery criteria = currentSession.getCriteriaBuilder().createQuery(type); return new HibernateQuery(criteria, this, persistentEntity); } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/IHibernateTemplate.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/IHibernateTemplate.java index 1214285de2d..89316b24c6e 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/IHibernateTemplate.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/IHibernateTemplate.java @@ -19,7 +19,6 @@ import java.util.Collection; import groovy.lang.Closure; -import org.hibernate.Criteria; import org.hibernate.LockMode; import org.hibernate.SessionFactory; import org.hibernate.query.Query; @@ -32,7 +31,7 @@ */ public interface IHibernateTemplate { - Serializable save(Object o); + void save(Object o); void refresh(Object o); @@ -54,8 +53,6 @@ public interface IHibernateTemplate { void applySettings(Query query); - void applySettings(Criteria criteria); - T get(Class type, Serializable key); T get(Class type, Serializable key, LockMode mode); diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/access/TraitPropertyAccessStrategy.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/access/TraitPropertyAccessStrategy.java index 36d472308fa..7a7bbc7d6d6 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/access/TraitPropertyAccessStrategy.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/access/TraitPropertyAccessStrategy.java @@ -1,5 +1,8 @@ package org.grails.orm.hibernate.access; +import org.checkerframework.checker.initialization.qual.Initialized; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.UnknownKeyFor; import org.codehaus.groovy.transform.trait.Traits; import org.grails.datastore.mapping.reflect.NameUtils; import org.hibernate.property.access.spi.*; @@ -15,7 +18,7 @@ * @since 6.1.3 */ public class TraitPropertyAccessStrategy implements PropertyAccessStrategy { - @Override + public PropertyAccess buildPropertyAccess(Class containerJavaType, String propertyName) { Method readMethod = ReflectionUtils.findMethod(containerJavaType, NameUtils.getGetterName(propertyName)); if(readMethod == null) { @@ -83,4 +86,9 @@ public Setter getSetter() { private String getTraitFieldName(Class traitClass, String fieldName) { return traitClass.getName().replace('.','_') + "__" + fieldName; } + + @java.lang.Override + public @UnknownKeyFor @NonNull @Initialized PropertyAccess buildPropertyAccess(java.lang.@UnknownKeyFor @NonNull @Initialized Class<@UnknownKeyFor @NonNull @Initialized ?> containerJavaType, java.lang.@UnknownKeyFor @NonNull @Initialized String propertyName, @UnknownKeyFor @NonNull @Initialized boolean setterRequired) { + return buildPropertyAccess(containerJavaType,propertyName ); + } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 7aa35cf34bf..5b45947ed28 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -15,7 +15,7 @@ package org.grails.orm.hibernate.cfg; import groovy.lang.Closure; -import groovy.transform.Trait; + import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.transform.trait.Traits; import org.grails.datastore.mapping.core.connections.ConnectionSource; @@ -30,12 +30,12 @@ import org.hibernate.FetchMode; import org.hibernate.MappingException; import org.hibernate.boot.internal.MetadataBuildingContextRootImpl; +import org.hibernate.boot.model.internal.BinderHelper; import org.hibernate.boot.model.naming.Identifier; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.spi.*; import org.hibernate.cfg.*; import org.hibernate.engine.OptimisticLockStyle; -import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.enhanced.SequenceStyleGenerator; @@ -149,6 +149,7 @@ public void contribute(InFlightMetadataCollector metadataCollector, IndexView ja this.metadataBuildingContext = new MetadataBuildingContextRootImpl( + "default", metadataCollector.getBootstrapContext(), options, metadataCollector @@ -211,7 +212,7 @@ protected void bindMapSecondPass(ToMany property, InFlightMetadataCollector mapp Map persistentClasses, org.hibernate.mapping.Map map, String sessionFactoryBeanName) { bindCollectionSecondPass(property, mappings, persistentClasses, map, sessionFactoryBeanName); - SimpleValue value = new SimpleValue(metadataBuildingContext, map.getCollectionTable()); + SimpleValue value = new BasicValue(metadataBuildingContext, map.getCollectionTable()); bindSimpleValue(getIndexColumnType(property, STRING_TYPE), value, true, getIndexColumnName(property, sessionFactoryBeanName), mappings); @@ -227,7 +228,7 @@ protected void bindMapSecondPass(ToMany property, InFlightMetadataCollector mapp if(!(property instanceof org.grails.datastore.mapping.model.types.OneToMany) && !(property instanceof ManyToMany)) { - SimpleValue elt = new SimpleValue(metadataBuildingContext, map.getCollectionTable()); + SimpleValue elt = new BasicValue(metadataBuildingContext, map.getCollectionTable()); map.setElement(elt); String typeName = getTypeName(property,getPropertyConfig(property), getMapping(property.getOwner())); @@ -273,7 +274,7 @@ protected void bindListSecondPass(ToMany property, InFlightMetadataCollector map } Table collectionTable = list.getCollectionTable(); - SimpleValue iv = new SimpleValue(metadataBuildingContext, collectionTable); + SimpleValue iv = new BasicValue(metadataBuildingContext, collectionTable); bindSimpleValue("integer", iv, true, columnName, mappings); iv.setTypeName("integer"); list.setIndex(iv); @@ -510,7 +511,7 @@ protected String buildOrderByClause(String hqlOrderBy, PersistentClass associate StringBuilder orderByBuffer = new StringBuilder(); if (hqlOrderBy.length() == 0) { //order by id - Iterator it = associatedClass.getIdentifier().getColumnIterator(); + Iterator it = associatedClass.getIdentifier().getSelectables().iterator(); while (it.hasNext()) { Selectable col = (Selectable) it.next(); orderByBuffer.append(col.getText()).append(" asc").append(", "); @@ -578,7 +579,7 @@ else if (pc == associatedClass table = pc.getTable().getQuotedName() + "."; } - Iterator propertyColumns = p.getColumnIterator(); + Iterator propertyColumns = p.getSelectables().iterator(); while (propertyColumns.hasNext()) { Selectable column = (Selectable) propertyColumns.next(); orderByBuffer.append(table) @@ -654,7 +655,7 @@ protected void bindCollectionWithJoinTable(ToMany property, SimpleValue element; final boolean isBasicCollectionType = property instanceof Basic; if (isBasicCollectionType) { - element = new SimpleValue(metadataBuildingContext, collection.getCollectionTable()); + element = new BasicValue(metadataBuildingContext, collection.getCollectionTable()); } else { // for a normal unidirectional one-to-many we use a join column @@ -736,7 +737,7 @@ protected String removeBackticks(String s) { } protected Column getColumnForSimpleValue(SimpleValue element) { - return (Column)element.getColumnIterator().next(); + return element.getColumns().iterator().next(); } protected String getTypeName(PersistentProperty property, PropertyConfig config, Mapping mapping) { @@ -802,7 +803,7 @@ protected void bindUnidirectionalOneToManyInverseValues(ToMany property, ManyToO } else { manyToOne.setIgnoreNotFound(config.getIgnoreNotFound()); final FetchMode fetch = config.getFetchMode(); - if(!fetch.equals(FetchMode.JOIN) && !fetch.equals(FetchMode.EAGER)) { + if(!fetch.equals(FetchMode.JOIN)) { manyToOne.setLazy(true); } @@ -822,7 +823,7 @@ protected void bindCollectionForPropertyConfig(Collection collection, PropertyCo collection.setExtraLazy(false); } else { final FetchMode fetch = config.getFetchMode(); - if(!fetch.equals(FetchMode.JOIN) && !fetch.equals(FetchMode.EAGER)) { + if(!fetch.equals(FetchMode.JOIN)) { collection.setLazy(true); } final Boolean lazy = config.getLazy(); @@ -965,7 +966,7 @@ protected void linkBidirectionalOneToMany(Collection collection, PersistentClass collection.setInverse(true); // Iterator mappedByColumns = associatedClass.getProperty(otherSide.getName()).getValue().getColumnIterator(); - Iterator mappedByColumns = getProperty(associatedClass, otherSide.getName()).getValue().getColumnIterator(); + Iterator mappedByColumns = getProperty(associatedClass, otherSide.getName()).getValue().getColumns().iterator(); while (mappedByColumns.hasNext()) { Column column = (Column) mappedByColumns.next(); linkValueUsingAColumnCopy(otherSide, column, key); @@ -1120,7 +1121,7 @@ protected void bindCollectionTable(ToMany property, InFlightMetadataCollector ma collection.setCollectionTable(mappings.addTable( schemaName, catalogName, - tableName, null, false)); + tableName, null, false, metadataBuildingContext)); } /** @@ -1426,26 +1427,32 @@ public void bindRoot(HibernatePersistentEntity entity, InFlightMetadataCollector protected void addMultiTenantFilterIfNecessary( HibernatePersistentEntity entity, PersistentClass persistentClass, InFlightMetadataCollector mappings, String sessionFactoryBeanName) { - if (entity.isMultiTenant()) { - TenantId tenantId = entity.getTenantId(); - - if (tenantId != null) { - String filterCondition = getMultiTenantFilterCondition(sessionFactoryBeanName, entity); - - persistentClass.addFilter( - GormProperties.TENANT_IDENTITY, - filterCondition, - true, - Collections.emptyMap(), - Collections.emptyMap() - ); - mappings.addFilterDefinition(new FilterDefinition( - GormProperties.TENANT_IDENTITY, - filterCondition, - Collections.singletonMap(GormProperties.TENANT_IDENTITY, getProperty(persistentClass, tenantId.getName()).getType()) - )); - } + if (entity.isMultiTenant()) { + throw new RuntimeException("Multitenant not supported yet"); +// TenantId tenantId = entity.getTenantId(); +// +// if (tenantId != null) { +// String filterCondition = getMultiTenantFilterCondition(sessionFactoryBeanName, entity); +// +// persistentClass.addFilter( +// GormProperties.TENANT_IDENTITY, +// filterCondition, +// true, +// Collections.emptyMap(), +// Collections.emptyMap() +// ); +// +// Property property = getProperty(persistentClass, tenantId.getName()); +// Type type = property.getType(); +// Map stringVMap = Collections.singletonMap(GormProperties.TENANT_IDENTITY, type); +// FilterDefinition definition = new FilterDefinition( +// GormProperties.TENANT_IDENTITY, +// filterCondition, +// stringVMap +// ); +// mappings.addFilterDefinition(definition); +// } } } @@ -1570,7 +1577,7 @@ public void bindUnionSubclass(HibernatePersistentEntity subClass, UnionSubclass getTableName(subClass, sessionFactoryBeanName), unionSubclass.isAbstract() != null && unionSubclass.isAbstract(), null, - denormalizedSuperTable + denormalizedSuperTable, metadataBuildingContext ); unionSubclass.setTable( mytable ); unionSubclass.setClassName(subClass.getName()); @@ -1602,7 +1609,7 @@ protected void bindJoinedSubClass(HibernatePersistentEntity sub, JoinedSubclass Table mytable = mappings.addTable( schemaName, catalogName, getJoinedSubClassTableName(sub, joinedSubclass, null, mappings, sessionFactoryBeanName), - null, false); + null, false, metadataBuildingContext); joinedSubclass.setTable(mytable); LOG.info("Mapping joined-subclass: " + joinedSubclass.getEntityName() + @@ -1664,7 +1671,7 @@ protected void bindSubClass(HibernatePersistentEntity sub, Subclass subClass, In */ protected void bindDiscriminatorProperty(Table table, RootClass entity, InFlightMetadataCollector mappings) { Mapping m = getMapping(entity.getMappedClass()); - SimpleValue d = new SimpleValue(metadataBuildingContext, table); + SimpleValue d = new BasicValue(metadataBuildingContext, table); entity.setDiscriminator(d); DiscriminatorConfig discriminatorConfig = m != null ? m.getDiscriminator() : null; @@ -1697,7 +1704,7 @@ protected void bindDiscriminatorProperty(Table table, RootClass entity, InFlight ColumnConfig cc = !hasDiscriminatorConfig ? null : discriminatorConfig.getColumn(); if (cc != null) { - Column c = (Column) d.getColumnIterator().next(); + Column c = (Column) d.getColumns().iterator().next(); if (cc.getName() != null) { c.setName(cc.getName()); } @@ -1766,7 +1773,7 @@ protected void bindRootPersistentClassCommonValues(HibernatePersistentEntity dom // create the table Table table = mappings.addTable(schema, catalog, getTableName(domainClass, sessionFactoryBeanName), - null, isAbstract); + null, isAbstract, metadataBuildingContext); root.setTable(table); if (LOG.isDebugEnabled()) { @@ -1903,13 +1910,13 @@ protected void createClassProperties(HibernatePersistentEntity domainClass, Pers if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as SimpleValue"); } - value = new SimpleValue(metadataBuildingContext, table); + value = new BasicValue(metadataBuildingContext, table); bindSimpleValue(currentGrailsProp, null, (SimpleValue) value, EMPTY_PATH, mappings, sessionFactoryBeanName); } else if (collectionType != null) { String typeName = getTypeName(currentGrailsProp, getPropertyConfig(currentGrailsProp),gormMapping); if ("serializable".equals(typeName)) { - value = new SimpleValue(metadataBuildingContext, table); + value = new BasicValue(metadataBuildingContext, table); bindSimpleValue(typeName, (SimpleValue) value, currentGrailsProp.isNullable(), getColumnNameForPropertyAndPath(currentGrailsProp, EMPTY_PATH, null, sessionFactoryBeanName), mappings); } @@ -1922,7 +1929,7 @@ else if (collectionType != null) { } } else if (currentGrailsProp.getType().isEnum()) { - value = new SimpleValue(metadataBuildingContext, table); + value = new BasicValue(metadataBuildingContext, table); bindEnumType(currentGrailsProp, (SimpleValue) value, EMPTY_PATH, sessionFactoryBeanName); } else if(currentGrailsProp instanceof Association) { @@ -1969,7 +1976,7 @@ else if (currentGrailsProp instanceof Embedded) { if (LOG.isDebugEnabled()) { LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as SimpleValue"); } - value = new SimpleValue(metadataBuildingContext, table); + value = new BasicValue(metadataBuildingContext, table); bindSimpleValue(currentGrailsProp, null, (SimpleValue) value, EMPTY_PATH, mappings, sessionFactoryBeanName); } @@ -2016,7 +2023,7 @@ protected void bindNaturalIdentifier(Table table, Mapping mapping, PersistentCla property.setNaturalIdentifier(true); if (!mutable) property.setUpdateable(false); - uk.addColumns(property.getColumnIterator()); + uk.addColumns(property.getValue()); } setGeneratedUniqueName(uk); @@ -2267,7 +2274,7 @@ else if (currentGrailsProp instanceof Embedded) { if (LOG.isDebugEnabled()) LOG.debug("[GrailsDomainBinder] Binding property [" + currentGrailsProp.getName() + "] as SimpleValue"); - value = new SimpleValue(metadataBuildingContext, table); + value = new BasicValue(metadataBuildingContext, table); if (currentGrailsProp.getType().isEnum()) { bindEnumType(currentGrailsProp, (SimpleValue) value, path, sessionFactoryBeanName); } @@ -2281,7 +2288,7 @@ else if (currentGrailsProp instanceof Embedded) { Property persistentProperty = createProperty(value, persistentClass, currentGrailsProp, mappings); component.addProperty(persistentProperty); if (isComponentPropertyNullable(componentProperty)) { - final Iterator columnIterator = value.getColumnIterator(); + final Iterator columnIterator = value.getColumns().iterator(); while (columnIterator.hasNext()) { Column c = (Column) columnIterator.next(); c.setNullable(true); @@ -2524,18 +2531,18 @@ protected void bindVersion(PersistentProperty version, RootClass entity, if (version != null) { - SimpleValue val = new SimpleValue(metadataBuildingContext, entity.getTable()); + BasicValue val = new BasicValue(metadataBuildingContext, entity.getTable()); bindSimpleValue(version, null, val, EMPTY_PATH, mappings, sessionFactoryBeanName); if (val.isTypeSpecified()) { - if (!(val.getType() instanceof IntegerType || - val.getType() instanceof LongType || - val.getType() instanceof TimestampType)) { - LOG.warn("Invalid version class specified in " + version.getOwner().getName() + - "; must be one of [int, Integer, long, Long, Timestamp, Date]. Not mapping the version."); - return; - } +// if (!(val.getType() instanceof IntegerType || +// val.getType() instanceof LongType || +// val.getType() instanceof TimestampType)) { +// LOG.warn("Invalid version class specified in " + version.getOwner().getName() + +// "; must be one of [int, Integer, long, Long, Timestamp, Date]. Not mapping the version."); +// return; +// } } else { val.setTypeName("version".equals(version.getName()) ? "integer" : "timestamp"); @@ -2563,7 +2570,7 @@ protected void bindSimpleId(PersistentProperty identifier, RootClass entity, boolean useSequence = mapping != null && mapping.isTablePerConcreteClass(); // create the id value - SimpleValue id = new SimpleValue(metadataBuildingContext, entity.getTable()); + BasicValue id = new BasicValue(metadataBuildingContext, entity.getTable()); Property idProperty = new Property(); idProperty.setName(identifier.getName()); idProperty.setValue(id); @@ -2616,7 +2623,8 @@ protected void bindSimpleId(PersistentProperty identifier, RootClass entity, // set identifier property entity.setIdentifierProperty(prop); - id.getTable().setIdentifierValue(id); + Table table = id.getTable(); + table.setPrimaryKey(new PrimaryKey(table)); } private String getSchemaName(InFlightMetadataCollector mappings) { @@ -3053,7 +3061,9 @@ protected void createUniqueKeyForColumns(Table table, String columnName, List[] EMPTY_CLASS_ARRAY = {}; - private static HibernateProxyHandler proxyHandler = new HibernateProxyHandler(); - public static void populateArgumentsForCriteria(AbstractHibernateDatastore datastore, Class targetClass, Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(datastore, targetClass, c, argMap, conversionService, true); - } - /** - * Populates criteria arguments for the given target class and arguments map - * - * @param datastore the GrailsApplication instance - * @param targetClass The target class - * @param c The criteria instance - * @param argMap The arguments map - */ - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(AbstractHibernateDatastore datastore, Class targetClass, Criteria c, Map argMap, ConversionService conversionService, boolean useDefaultMapping) { - Integer maxParam = null; - Integer offsetParam = null; - if (argMap.containsKey(ARGUMENT_MAX)) { - maxParam = conversionService.convert(argMap.get(ARGUMENT_MAX),Integer.class); - } - if (argMap.containsKey(ARGUMENT_OFFSET)) { - offsetParam = conversionService.convert(argMap.get(ARGUMENT_OFFSET),Integer.class); - } - if (argMap.containsKey(ARGUMENT_FETCH_SIZE)) { - c.setFetchSize(conversionService.convert(argMap.get(ARGUMENT_FETCH_SIZE),Integer.class)); - } - if (argMap.containsKey(ARGUMENT_TIMEOUT)) { - c.setTimeout(conversionService.convert(argMap.get(ARGUMENT_TIMEOUT),Integer.class)); - } - if (argMap.containsKey(ARGUMENT_FLUSH_MODE)) { - c.setFlushMode(convertFlushMode(argMap.get(ARGUMENT_FLUSH_MODE))); - } - if (argMap.containsKey(ARGUMENT_READ_ONLY)) { - c.setReadOnly(ClassUtils.getBooleanFromMap(ARGUMENT_READ_ONLY, argMap)); - } - String orderParam = (String)argMap.get(ARGUMENT_ORDER); - Object fetchObj = argMap.get(ARGUMENT_FETCH); - if (fetchObj instanceof Map) { - Map fetch = (Map)fetchObj; - for (Object o : fetch.keySet()) { - String associationName = (String) o; - c.setFetchMode(associationName, getFetchMode(fetch.get(associationName))); - } - } - final int max = maxParam == null ? -1 : maxParam; - final int offset = offsetParam == null ? -1 : offsetParam; - if (max > -1) { - c.setMaxResults(max); - } - if (offset > -1) { - c.setFirstResult(offset); - } - if (ClassUtils.getBooleanFromMap(ARGUMENT_LOCK, argMap)) { - c.setLockMode(LockMode.PESSIMISTIC_WRITE); - c.setCacheable(false); - } - else { - if (argMap.containsKey(ARGUMENT_CACHE)) { - c.setCacheable(ClassUtils.getBooleanFromMap(ARGUMENT_CACHE, argMap)); - } else { - cacheCriteriaByMapping(targetClass, c); - } - } - final Object sortObj = argMap.get(ARGUMENT_SORT); - if (sortObj != null) { - boolean ignoreCase = true; - Object caseArg = argMap.get(ARGUMENT_IGNORE_CASE); - if (caseArg instanceof Boolean) { - ignoreCase = (Boolean) caseArg; - } - if (sortObj instanceof Map) { - Map sortMap = (Map) sortObj; - for (Object sort : sortMap.keySet()) { - final String order = ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(datastore, c, targetClass, (String) sort, order, ignoreCase); - } - } else { - final String sort = (String) sortObj; - final String order = ORDER_DESC.equalsIgnoreCase(orderParam) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(datastore, c, targetClass, sort, order, ignoreCase); - } - } - else if (useDefaultMapping) { - Mapping m = GrailsDomainBinder.getMapping(targetClass); - if (m != null) { - Map sortMap = m.getSort().getNamesAndDirections(); - for (Object sort : sortMap.keySet()) { - final String order = ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? ORDER_DESC : ORDER_ASC; - addOrderPossiblyNested(datastore, c, targetClass, (String) sort, order, true); - } - } - } - } - /** - * @deprecated No replacement. Do not use. - */ - @Deprecated - public static void setBinder(GrailsDomainBinder binder) { - } - /** - * Populates criteria arguments for the given target class and arguments map - * - * @param targetClass The target class - * @param c The criteria instance - * @param argMap The arguments map - * - */ - @Deprecated - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(Class targetClass, Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(null, targetClass, c, argMap, conversionService); - } - @SuppressWarnings("rawtypes") - public static void populateArgumentsForCriteria(Criteria c, Map argMap, ConversionService conversionService) { - populateArgumentsForCriteria(null, null, c, argMap, conversionService); - } - private static FlushMode convertFlushMode(Object object) { - if (object == null) { - return null; - } - if (object instanceof FlushMode) { - return (FlushMode)object; - } - return FlushMode.valueOf(String.valueOf(object)); - } - /** - * Add order to criteria, creating necessary subCriteria if nested sort property (ie. sort:'nested.property'). - */ - private static void addOrderPossiblyNested(AbstractHibernateDatastore datastore, Criteria c, Class targetClass, String sort, String order, boolean ignoreCase) { - int firstDotPos = sort.indexOf("."); - if (firstDotPos == -1) { - addOrder(c, sort, order, ignoreCase); - } else { // nested property - String sortHead = sort.substring(0,firstDotPos); - String sortTail = sort.substring(firstDotPos+1); - PersistentProperty property = getGrailsDomainClassProperty(datastore, targetClass, sortHead); - if (property instanceof Embedded) { - // embedded objects cannot reference entities (at time of writing), so no more recursion needed - addOrder(c, sort, order, ignoreCase); - } else if(property instanceof Association) { - Criteria subCriteria = c.createCriteria(sortHead); - Class propertyTargetClass = ((Association)property).getAssociatedEntity().getJavaClass(); - GrailsHibernateUtil.cacheCriteriaByMapping(datastore, propertyTargetClass, subCriteria); - addOrderPossiblyNested(datastore, subCriteria, propertyTargetClass, sortTail, order, ignoreCase); // Recurse on nested sort - } - } - } - /** - * Add order directly to criteria. - */ - private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { - if (ORDER_DESC.equals(order)) { - c.addOrder(ignoreCase ? Order.desc(sort).ignoreCase() : Order.desc(sort)); - } - else { - c.addOrder(ignoreCase ? Order.asc(sort).ignoreCase() : Order.asc(sort)); - } - } - /** - * Get hold of the GrailsDomainClassProperty represented by the targetClass' propertyName, - * assuming targetClass corresponds to a GrailsDomainClass. - */ - private static PersistentProperty getGrailsDomainClassProperty(AbstractHibernateDatastore datastore, Class targetClass, String propertyName) { - PersistentEntity grailsClass = datastore != null ? datastore.getMappingContext().getPersistentEntity( targetClass.getName()) : null; - if (grailsClass == null) { - throw new IllegalArgumentException("Unexpected: class is not a domain class:"+targetClass.getName()); - } - return grailsClass.getPropertyByName(propertyName); - } - /** - * Configures the criteria instance to cache based on the configured mapping. - * - * @param targetClass The target class - * @param criteria The criteria - */ - public static void cacheCriteriaByMapping(Class targetClass, Criteria criteria) { - Mapping m = GrailsDomainBinder.getMapping(targetClass); - if (m != null && m.getCache() != null && m.getCache().getEnabled()) { - criteria.setCacheable(true); - } - } - public static void cacheCriteriaByMapping(AbstractHibernateDatastore datastore, Class targetClass, Criteria criteria) { - cacheCriteriaByMapping(targetClass, criteria); - } - /** - * Retrieves the fetch mode for the specified instance; otherwise returns the default FetchMode. - * - * @param object The object, converted to a string - * @return The FetchMode - */ - public static FetchMode getFetchMode(Object object) { - String name = object != null ? object.toString() : "default"; - if (name.equalsIgnoreCase(FetchMode.JOIN.toString()) || name.equalsIgnoreCase("eager")) { - return FetchMode.JOIN; - } - if (name.equalsIgnoreCase(FetchMode.SELECT.toString()) || name.equalsIgnoreCase("lazy")) { - return FetchMode.SELECT; - } - return FetchMode.DEFAULT; - } + + /** * Sets the target object to read-only using the given SessionFactory instance. This @@ -370,68 +177,7 @@ public static void ensureCorrectGroovyMetaClass(Object target, Class persiste } } - /** - * Unwraps and initializes a HibernateProxy. - * @param proxy The proxy - * @return the unproxied instance - */ - public static Object unwrapProxy(HibernateProxy proxy) { - return proxyHandler.unwrap(proxy); - } - /** - * Returns the proxy for a given association or null if it is not proxied - * - * @param obj The object - * @param associationName The named assoication - * @return A proxy - */ - public static HibernateProxy getAssociationProxy(Object obj, String associationName) { - return proxyHandler.getAssociationProxy(obj, associationName); - } - - /** - * Checks whether an associated property is initialized and returns true if it is - * - * @param obj The name of the object - * @param associationName The name of the association - * @return true if is initialized - */ - public static boolean isInitialized(Object obj, String associationName) { - return proxyHandler.isInitialized(obj, associationName); - } - - /** - * Unproxies a HibernateProxy. If the proxy is uninitialized, it automatically triggers an initialization. - * In case the supplied object is null or not a proxy, the object will be returned as-is. - */ - public static Object unwrapIfProxy(Object instance) { - return proxyHandler.unwrap(instance); - } - - /** - * @deprecated Use {@link MultipleDataSourceSupport#getDefaultDataSource(PersistentEntity)} instead - */ - @Deprecated - public static String getDefaultDataSource(PersistentEntity domainClass) { - return MultipleDataSourceSupport.getDefaultDataSource(domainClass); - } - - /** - * @deprecated Use {@link MultipleDataSourceSupport#getDatasourceNames(PersistentEntity)} instead - */ - @Deprecated - public static List getDatasourceNames(PersistentEntity domainClass) { - return MultipleDataSourceSupport.getDatasourceNames(domainClass); - } - - /** - * @deprecated Use {@link MultipleDataSourceSupport#getDefaultDataSource(PersistentEntity)} instead - */ - @Deprecated - public static boolean usesDatasource(PersistentEntity domainClass, String dataSourceName) { - return MultipleDataSourceSupport.usesDatasource(domainClass, dataSourceName); - } public static boolean isMappedWithHibernate(PersistentEntity domainClass) { return domainClass instanceof HibernatePersistentEntity; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsIdentifierGeneratorFactory.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsIdentifierGeneratorFactory.java deleted file mode 100644 index 6b622649a3c..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsIdentifierGeneratorFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright 2013 the original author or authors. - * - * 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 org.grails.orm.hibernate.cfg; - -import java.lang.reflect.Field; - -import org.hibernate.cfg.Configuration; -import org.hibernate.id.SequenceGenerator; -import org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory; -import org.springframework.util.ReflectionUtils; - -/** - * Hibernate IdentifierGeneratorFactory that prefers sequence-identity generator over sequence generator - * - * @author Lari Hotari - */ -public class GrailsIdentifierGeneratorFactory extends DefaultIdentifierGeneratorFactory { - private static final long serialVersionUID = 1L; - - @Override - public Class getIdentifierGeneratorClass(String strategy) { - Class generatorClass = super.getIdentifierGeneratorClass(strategy); - if("native".equals(strategy) && generatorClass == SequenceGenerator.class) { - generatorClass = super.getIdentifierGeneratorClass("sequence-identity"); - } - return generatorClass; - } - - public static void applyNewInstance(Configuration cfg) throws IllegalArgumentException, IllegalAccessException { - Field field = ReflectionUtils.findField(Configuration.class, "identifierGeneratorFactory"); - field.setAccessible(true); - field.set(cfg, new GrailsIdentifierGeneratorFactory()); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java index 4c4387c3684..5e57b0726fc 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java @@ -28,7 +28,6 @@ import org.grails.datastore.mapping.model.config.JpaMappingConfigurationStrategy; import org.grails.datastore.mapping.reflect.ClassUtils; import org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings; -import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.springframework.validation.Errors; import java.lang.annotation.Annotation; @@ -69,7 +68,6 @@ protected boolean supportsCustomType(Class propertyType) { return !Errors.class.isAssignableFrom(propertyType); } }; - this.proxyFactory = new HibernateProxyHandler(); addPersistentEntities(persistentClasses); } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java index f1616328663..1cecd1daa7a 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java @@ -270,15 +270,19 @@ public Collection loadJavaServices(Class serviceContract) { PropertyAccessStrategy.class, "traitProperty", TraitPropertyAccessStrategy.class ); - setSessionFactoryObserver(new SessionFactoryObserver() { + SessionFactoryObserver sessionFactoryObserver = new SessionFactoryObserver() { private static final long serialVersionUID = 1; - public void sessionFactoryCreated(SessionFactory factory) {} + + public void sessionFactoryCreated(SessionFactory factory) { + } + public void sessionFactoryClosed(SessionFactory factory) { if (serviceRegistry != null) { - ((ServiceRegistryImplementor)serviceRegistry).destroy(); + ((ServiceRegistryImplementor) serviceRegistry).destroy(); } } - }); + }; + setSessionFactoryObserver(sessionFactoryObserver); StandardServiceRegistryBuilder standardServiceRegistryBuilder = createStandardServiceRegistryBuilder(bootstrapServiceRegistry) .applySettings(getProperties()); @@ -330,16 +334,6 @@ public ServiceRegistry getServiceRegistry() { } - @Override - protected void reset() { - super.reset(); - try { - GrailsIdentifierGeneratorFactory.applyNewInstance(this); - } - catch (Exception e) { - // ignore exception - } - } public void setMetadataContributor(MetadataContributor metadataContributor) { this.metadataContributor = metadataContributor; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java index 6282b259bb6..593698a3bb5 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/IdentityEnumType.java @@ -17,8 +17,11 @@ import org.hibernate.HibernateException; import org.hibernate.MappingException; +import org.hibernate.dialect.Dialect; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.type.AbstractStandardBasicType; +import org.hibernate.type.descriptor.converter.spi.BasicValueConverter; +import org.hibernate.type.descriptor.jdbc.JdbcType; import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.usertype.ParameterizedType; import org.hibernate.usertype.UserType; @@ -88,7 +91,7 @@ public void setParameterValues(Properties properties) { if (LOG.isDebugEnabled()) { LOG.debug(String.format("Mapped Basic Type is %s", type)); } - sqlTypes = type.sqlTypes(null); + sqlTypes = type.getSqlTypeCodes(null); } catch (Exception e) { throw new MappingException("Error mapping Enum Class using IdentifierEnumType", e); @@ -99,6 +102,11 @@ public int[] sqlTypes() { return sqlTypes; } + @Override + public int getSqlType() { + return 0; + } + public Class returnedClass() { return enumClass; } @@ -112,14 +120,13 @@ public int hashCode(Object o) throws HibernateException { } @Override - public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException { - Object id = type.nullSafeGet(rs, names[0], session); - if ((!rs.wasNull()) && id != null) { - return bidiMap.getEnumValue(id); - } - return null; + public Object nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException { + Object result = rs.getObject(position, returnedClass()); + return rs.wasNull() ? null : result; } + + @Override public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException { if (value == null) { @@ -150,6 +157,31 @@ public Object replace(Object orig, Object target, Object owner) throws Hibernate return orig; } + @Override + public long getDefaultSqlLength(Dialect dialect, JdbcType jdbcType) { + return UserType.super.getDefaultSqlLength(dialect, jdbcType); + } + + @Override + public int getDefaultSqlPrecision(Dialect dialect, JdbcType jdbcType) { + return UserType.super.getDefaultSqlPrecision(dialect, jdbcType); + } + + @Override + public int getDefaultSqlScale(Dialect dialect, JdbcType jdbcType) { + return UserType.super.getDefaultSqlScale(dialect, jdbcType); + } + + @Override + public JdbcType getJdbcType(TypeConfiguration typeConfiguration) { + return UserType.super.getJdbcType(typeConfiguration); + } + + @Override + public BasicValueConverter getValueConverter() { + return UserType.super.getValueConverter(); + } + @SuppressWarnings({"rawtypes", "unchecked"}) private static class BidiEnumMap implements Serializable { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java deleted file mode 100644 index b263905db61..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2004-2008 the original author or authors. - * - * 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 org.grails.orm.hibernate.proxy; - -import java.io.Serializable; -import org.grails.datastore.gorm.GormEnhancer; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.AssociationQueryExecutor; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.proxy.ProxyFactory; -import org.grails.datastore.mapping.proxy.ProxyHandler; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.hibernate.Hibernate; -import org.hibernate.collection.spi.PersistentCollection; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.HibernateProxyHelper; - -/** - * Implementation of the ProxyHandler interface for Hibernate using org.hibernate.Hibernate - * and HibernateProxyHelper where possible. - * - * @author Graeme Rocher - * @since 1.2.2 - */ -public class HibernateProxyHandler implements ProxyHandler, ProxyFactory { - - /** - * Check if the proxy or persistent collection is initialized. - * {@inheritDoc} - */ - @Override - public boolean isInitialized(Object o) { - return Hibernate.isInitialized(o); - } - - /** - * Check if an association proxy or persistent collection is initialized. - * {@inheritDoc} - */ - @Override - public boolean isInitialized(Object obj, String associationName) { - try { - Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); - return isInitialized(proxy); - } - catch (RuntimeException e) { - return false; - } - } - - /** - * Unproxies a HibernateProxy. If the proxy is uninitialized, it automatically triggers an initialization. - * In case the supplied object is null or not a proxy, the object will be returned as-is. - * {@inheritDoc} - * @see Hibernate#unproxy - */ - @Override - public Object unwrap(Object object) { - if (object instanceof PersistentCollection) { - initialize(object); - return object; - } - return Hibernate.unproxy(object); - } - - /** - * {@inheritDoc} - * @see org.hibernate.proxy.AbstractLazyInitializer#getIdentifier - */ - @Override - public Serializable getIdentifier(Object o) { - if (o instanceof HibernateProxy) { - return ((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier(); - } - else { - //TODO seems we can get the id here if its has normal getId - // PersistentEntity persistentEntity = GormEnhancer.findStaticApi(o.getClass()).getGormPersistentEntity(); - // return persistentEntity.getMappingContext().getEntityReflector(persistentEntity).getIdentifier(o); - return null; - } - } - - /** - * {@inheritDoc} - * @see HibernateProxyHelper#getClassWithoutInitializingProxy - */ - @Override - public Class getProxiedClass(Object o) { - return HibernateProxyHelper.getClassWithoutInitializingProxy(o); - } - - /** - * calls unwrap which calls unproxy - * @see #unwrap(Object) - * @deprecated use unwrap - */ - @Deprecated - public Object unwrapIfProxy(Object instance) { - return unwrap(instance); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean isProxy(Object o) { - return (o instanceof HibernateProxy) || (o instanceof PersistentCollection); - } - - /** - * Force initialization of a proxy or persistent collection. - * {@inheritDoc} - */ - @Override - public void initialize(Object o) { - Hibernate.initialize(o); - } - - @Override - public T createProxy(Session session, Class type, Serializable key) { - throw new UnsupportedOperationException("createProxy not supported in HibernateProxyHandler"); - } - - @Override - public T createProxy(Session session, AssociationQueryExecutor executor, K associationKey) { - throw new UnsupportedOperationException("createProxy not supported in HibernateProxyHandler"); - } - - /** - * @deprecated use unwrap - */ - @Deprecated - public Object unwrapProxy(Object proxy) { - return unwrap(proxy); - } - - /** - * returns the proxy for an association. returns null if its not a proxy. - * Note: Only used in a test. Deprecate? - */ - public HibernateProxy getAssociationProxy(Object obj, String associationName) { - try { - Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); - if (proxy instanceof HibernateProxy) { - return (HibernateProxy) proxy; - } - return null; - } - catch (RuntimeException e) { - return null; - } - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java deleted file mode 100644 index 06acad77ad3..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandler.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright 2004-2008 the original author or authors. - * - * 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 org.grails.orm.hibernate.proxy; - - -import groovy.lang.GroovyObject; -import groovy.lang.GroovySystem; -import org.grails.datastore.mapping.core.Session; -import org.grails.datastore.mapping.engine.AssociationQueryExecutor; -import org.grails.datastore.mapping.proxy.JavassistProxyFactory; -import org.grails.datastore.mapping.proxy.ProxyFactory; -import org.grails.datastore.mapping.proxy.ProxyHandler; -import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; -import org.hibernate.Hibernate; -import org.hibernate.collection.spi.PersistentCollection; -import org.hibernate.proxy.HibernateProxy; -import org.hibernate.proxy.HibernateProxyHelper; -import org.hibernate.proxy.LazyInitializer; - -import java.io.Serializable; - -/** - * Implementation of the ProxyHandler interface for Hibernate. - * Deprecated as Hibernate 5.6+ no longer supports Javassist - * - * @author Graeme Rocher - * @since 1.2.2 - * @deprecated - */ - -@Deprecated -public class SimpleHibernateProxyHandler extends JavassistProxyFactory implements ProxyHandler, ProxyFactory { - - public boolean isInitialized(Object o) { - if (o instanceof HibernateProxy) { - return !((HibernateProxy) o).getHibernateLazyInitializer().isUninitialized(); - } - else if (o instanceof PersistentCollection) { - return ((PersistentCollection) o).wasInitialized(); - } - else { - return super.isInitialized(o); - } - } - - public boolean isInitialized(Object obj, String associationName) { - try { - Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); - return isInitialized(proxy); - } - catch (RuntimeException e) { - return false; - } - } - - @Override - public Object unwrap(Object object) { - return unwrapIfProxy(object); - } - - @Override - public Serializable getIdentifier(Object obj) { - return (Serializable) getProxyIdentifier(obj); - } - - public Object unwrapIfProxy(Object instance) { - if (instance instanceof HibernateProxy) { - final HibernateProxy proxy = (HibernateProxy)instance; - return unwrapProxy(proxy); - } - else { - return super.unwrap(instance); - } - } - - public Object unwrapProxy(final HibernateProxy proxy) { - final LazyInitializer lazyInitializer = proxy.getHibernateLazyInitializer(); - if (lazyInitializer.isUninitialized()) { - lazyInitializer.initialize(); - } - final Object obj = lazyInitializer.getImplementation(); - if (obj != null) { - ensureCorrectGroovyMetaClass(obj, obj.getClass()); - } - return obj; - } - - /** - * Ensures the meta class is correct for a given class - * - * @param target The GroovyObject - * @param persistentClass The persistent class - */ - private static void ensureCorrectGroovyMetaClass(Object target, Class persistentClass) { - if (target instanceof GroovyObject) { - GroovyObject go = ((GroovyObject)target); - if (!go.getMetaClass().getTheClass().equals(persistentClass)) { - go.setMetaClass(GroovySystem.getMetaClassRegistry().getMetaClass(persistentClass)); - } - } - } - - - public HibernateProxy getAssociationProxy(Object obj, String associationName) { - try { - Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); - if (proxy instanceof HibernateProxy) { - return (HibernateProxy) proxy; - } - return null; - } - catch (RuntimeException e) { - return null; - } - } - - public boolean isProxy(Object o) { - return (o instanceof HibernateProxy) || super.isProxy(o); - } - - public void initialize(Object o) { - if (o instanceof HibernateProxy) { - final LazyInitializer hibernateLazyInitializer = ((HibernateProxy)o).getHibernateLazyInitializer(); - if (hibernateLazyInitializer.isUninitialized()) { - hibernateLazyInitializer.initialize(); - } - } - else { - super.initialize(o); - } - } - - public Object getProxyIdentifier(Object o) { - if (o instanceof HibernateProxy) { - return ((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier(); - } - return super.getIdentifier(o); - } - - public Class getProxiedClass(Object o) { - if(o instanceof HibernateProxy) { - return HibernateProxyHelper.getClassWithoutInitializingProxy(o); - } - else { - return super.getProxiedClass(o); - } - } - - @Override - public T createProxy(Session session, Class type, Serializable key) { - return super.createProxy(session, type, key); - } - - @Override - public T createProxy(Session session, AssociationQueryExecutor executor, K associationKey) { - return super.createProxy(session, executor, associationKey); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index ca98efeb758..682dcff51ea 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -1,28 +1,44 @@ package org.grails.orm.hibernate.query; import grails.gorm.MultiTenant; -import groovy.lang.*; +import groovy.lang.Closure; +import groovy.lang.DelegatesTo; +import groovy.lang.GroovyObjectSupport; +import groovy.lang.MetaClass; +import groovy.lang.MetaMethod; +import groovy.lang.MissingMethodException; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.EntityType; import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.*; +import org.grails.datastore.mapping.query.api.BuildableCriteria; +import org.grails.datastore.mapping.query.api.Criteria; +import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.datastore.mapping.reflect.NameUtils; import org.grails.orm.hibernate.AbstractHibernateDatastore; -import org.hibernate.*; -import org.hibernate.Criteria; -import org.hibernate.criterion.*; -import org.hibernate.criterion.ProjectionList; -import org.hibernate.criterion.Projections; -import org.hibernate.criterion.Restrictions; +import org.hibernate.FetchMode; +import org.hibernate.HibernateException; +import org.hibernate.Metamodel; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.transform.ResultTransformer; import org.hibernate.type.Type; import org.springframework.beans.BeanUtils; import org.springframework.core.convert.ConversionService; +import org.grails.datastore.mapping.query.api.Criteria; +import org.grails.datastore.mapping.query.api.ProjectionList; -import jakarta.persistence.criteria.JoinType; -import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.EntityType; import java.beans.PropertyDescriptor; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** * Abstract super class for sharing code between Hibernate 3 and 4 implementations of HibernateCriteriaBuilder @@ -74,7 +90,7 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected SessionFactory sessionFactory; protected Session hibernateSession; protected Class targetClass; - protected Criteria criteria; + protected CriteriaQuery criteria; protected MetaClass criteriaMetaClass; protected boolean uniqueResult = false; protected List logicalExpressionStack = new ArrayList(); @@ -82,23 +98,25 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected boolean participate; protected boolean scroll; protected boolean count; - protected ProjectionList projectionList = Projections.projectionList(); protected List aliasStack = new ArrayList(); - protected List aliasInstanceStack = new ArrayList(); protected Map aliasMap = new HashMap(); protected static final String ALIAS = "_alias"; protected ResultTransformer resultTransformer; protected int aliasCount; protected boolean paginationEnabledList = false; - protected List orderEntries; protected ConversionService conversionService; protected int defaultFlushMode; protected AbstractHibernateDatastore datastore; + protected HibernateCriteriaBuilder cb; + protected Root root; @SuppressWarnings("rawtypes") public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory) { this.targetClass = targetClass; this.sessionFactory = sessionFactory; + this.cb = sessionFactory.getCriteriaBuilder(); + this.criteria = cb.createQuery(targetClass); + this.root = criteria.from(targetClass); } @SuppressWarnings("rawtypes") @@ -106,6 +124,9 @@ public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessio this.targetClass = targetClass; this.sessionFactory = sessionFactory; this.uniqueResult = uniqueResult; + this.cb = sessionFactory.getCriteriaBuilder(); + this.criteria = cb.createQuery(targetClass); + this.root = criteria.from(targetClass); } public void setDatastore(AbstractHibernateDatastore datastore) { @@ -123,7 +144,7 @@ public void setConversionService(ConversionService conversionService) { * A projection that selects a property name * @param propertyName The name of the property */ - public org.grails.datastore.mapping.query.api.ProjectionList property(String propertyName) { + public ProjectionList property(String propertyName) { return property(propertyName, null); } @@ -132,66 +153,16 @@ public org.grails.datastore.mapping.query.api.ProjectionList property(String pro * @param propertyName The name of the property * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList property(String propertyName, String alias) { - final PropertyProjection propertyProjection = Projections.property(calculatePropertyName(propertyName)); - addProjectionToList(propertyProjection, alias); + public ProjectionList property(String propertyName, String alias) { + criteria.select(root.get(propertyName)); return this; } - /** - * Adds a projection to the projectList for the given alias - * - * @param propertyProjection The projection - * @param alias The alias - */ - protected void addProjectionToList(Projection propertyProjection, String alias) { - if (alias != null) { - projectionList.add(propertyProjection,alias); - } - else { - projectionList.add(propertyProjection); - } - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting a single value - * @param columnAlias column alias for the projected value - * @param type the type of the projected value - */ - protected void sqlProjection(String sql, String columnAlias, Type type) { - sqlProjection(sql, Collections.singletonList(columnAlias), Collections.singletonList(type)); - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting - * @param columnAliases List of column aliases for the projected values - * @param types List of types for the projected values - */ - protected void sqlProjection(String sql, List columnAliases, List types) { - projectionList.add(Projections.sqlProjection(sql, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()]))); - } - - /** - * Adds a sql projection to the criteria - * - * @param sql SQL projecting - * @param groupBy group by clause - * @param columnAliases List of column aliases for the projected values - * @param types List of types for the projected values - */ - protected void sqlGroupProjection(String sql, String groupBy, List columnAliases, List types) { - projectionList.add(Projections.sqlGroupProjection(sql, groupBy, columnAliases.toArray(new String[columnAliases.size()]), types.toArray(new Type[types.size()]))); - } - /** * A projection that selects a distince property name * @param propertyName The property name */ - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String propertyName) { + public ProjectionList distinct(String propertyName) { distinct(propertyName, null); return this; } @@ -201,45 +172,18 @@ public org.grails.datastore.mapping.query.api.ProjectionList distinct(String pro * @param propertyName The property name * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String propertyName, String alias) { - final Projection proj = Projections.distinct(Projections.property(calculatePropertyName(propertyName))); - addProjectionToList(proj,alias); + public ProjectionList distinct(String propertyName, String alias) { + criteria.select(root.get(propertyName)).distinct(true); return this; } - /** - * A distinct projection that takes a list - * - * @param propertyNames The list of distince property names - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.ProjectionList distinct(Collection propertyNames) { - return distinct(propertyNames, null); - } - - /** - * A distinct projection that takes a list - * - * @param propertyNames The list of distince property names - * @param alias The alias to use - */ - @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.ProjectionList distinct(Collection propertyNames, String alias) { - ProjectionList list = Projections.projectionList(); - for (Object o : propertyNames) { - list.add(Projections.property(calculatePropertyName(o.toString()))); - } - final Projection proj = Projections.distinct(list); - addProjectionToList(proj, alias); - return this; - } /** * Adds a projection that allows the criteria to return the property average value * * @param propertyName The name of the property */ - public org.grails.datastore.mapping.query.api.ProjectionList avg(String propertyName) { + public ProjectionList avg(String propertyName) { return avg(propertyName, null); } @@ -249,9 +193,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList avg(String property * @param propertyName The name of the property * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList avg(String propertyName, String alias) { - final AggregateProjection aggregateProjection = Projections.avg(calculatePropertyName(propertyName)); - addProjectionToList(aggregateProjection, alias); + public ProjectionList avg(String propertyName, String alias) { return this; } @@ -261,12 +203,10 @@ public org.grails.datastore.mapping.query.api.ProjectionList avg(String property * @param associationPath The path of the association */ public BuildableCriteria join(String associationPath) { - criteria.setFetchMode(calculatePropertyName(associationPath), FetchMode.JOIN); return this; } public BuildableCriteria join(String property, JoinType joinType) { - criteria.setFetchMode(calculatePropertyName(property), FetchMode.JOIN); return this; } @@ -277,24 +217,6 @@ public BuildableCriteria join(String property, JoinType joinType) { * @param shouldLock True if it should */ public void lock(boolean shouldLock) { - String lastAlias = getLastAlias(); - - if (shouldLock) { - if (lastAlias != null) { - criteria.setLockMode(lastAlias, LockMode.PESSIMISTIC_WRITE); - } - else { - criteria.setLockMode(LockMode.PESSIMISTIC_WRITE); - } - } - else { - if (lastAlias != null) { - criteria.setLockMode(lastAlias, LockMode.NONE); - } - else { - criteria.setLockMode(LockMode.NONE); - } - } } /** @@ -303,7 +225,6 @@ public void lock(boolean shouldLock) { * @param associationPath The path of the association */ public BuildableCriteria select(String associationPath) { - criteria.setFetchMode(calculatePropertyName(associationPath), FetchMode.SELECT); return this; } @@ -312,7 +233,6 @@ public BuildableCriteria select(String associationPath) { * @param shouldCache True if the query should be cached */ public BuildableCriteria cache(boolean shouldCache) { - criteria.setCacheable(shouldCache); return this; } @@ -321,7 +241,6 @@ public BuildableCriteria cache(boolean shouldCache) { * @param readOnly True to disable dirty checking */ public BuildableCriteria readOnly(boolean readOnly) { - criteria.setReadOnly(readOnly); return this; } @@ -362,17 +281,9 @@ protected Object calculatePropertyValue(Object propertyValue) { if (propertyValue instanceof CharSequence) { return propertyValue.toString(); } - if (propertyValue instanceof QueryableCriteria) { - propertyValue = convertToHibernateCriteria((QueryableCriteria) propertyValue); - } - else if (propertyValue instanceof Closure) { - propertyValue = convertToHibernateCriteria( - new grails.gorm.DetachedCriteria(targetClass).build((Closure) propertyValue)); - } return propertyValue; } - protected abstract org.hibernate.criterion.DetachedCriteria convertToHibernateCriteria(QueryableCriteria queryableCriteria); /** * Adds a projection that allows the criteria to return the property count @@ -390,17 +301,14 @@ public void count(String propertyName) { * @param alias The alias to use */ public void count(String propertyName, String alias) { - final CountProjection proj = Projections.count(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); + } - public org.grails.datastore.mapping.query.api.ProjectionList id() { - final IdentifierProjection proj = Projections.id(); - addProjectionToList(proj, null); + public ProjectionList id() { return this; } - public org.grails.datastore.mapping.query.api.ProjectionList count() { + public ProjectionList count() { return rowCount(); } @@ -409,7 +317,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList count() { * * @param propertyName The name of the property */ - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String propertyName) { + public ProjectionList countDistinct(String propertyName) { return countDistinct(propertyName, null); } @@ -418,13 +326,12 @@ public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(Strin * * @param propertyName The name of the property */ - public org.grails.datastore.mapping.query.api.ProjectionList groupProperty(String propertyName) { + public ProjectionList groupProperty(String propertyName) { groupProperty(propertyName, null); return this; } - public org.grails.datastore.mapping.query.api.ProjectionList distinct() { - criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); + public ProjectionList distinct() { return this; } @@ -434,9 +341,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList distinct() { * @param propertyName The name of the property * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String propertyName, String alias) { - final CountProjection proj = Projections.countDistinct(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); + public ProjectionList countDistinct(String propertyName, String alias) { return this; } @@ -447,9 +352,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(Strin * @param propertyName The name of the property * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList groupProperty(String propertyName, String alias) { - final PropertyProjection proj = Projections.groupProperty(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); + public ProjectionList groupProperty(String propertyName, String alias) { return this; } @@ -458,7 +361,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList groupProperty(Strin * * @param propertyName The name of the property */ - public org.grails.datastore.mapping.query.api.ProjectionList max(String propertyName) { + public ProjectionList max(String propertyName) { return max(propertyName, null); } @@ -468,9 +371,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList max(String property * @param propertyName The name of the property * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList max(String propertyName, String alias) { - final AggregateProjection proj = Projections.max(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); + public ProjectionList max(String propertyName, String alias) { return this; } @@ -479,7 +380,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList max(String property * * @param propertyName The name of the property */ - public org.grails.datastore.mapping.query.api.ProjectionList min(String propertyName) { + public ProjectionList min(String propertyName) { return min(propertyName, null); } @@ -488,9 +389,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList min(String property * * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList min(String propertyName, String alias) { - final AggregateProjection aggregateProjection = Projections.min(calculatePropertyName(propertyName)); - addProjectionToList(aggregateProjection, alias); + public ProjectionList min(String propertyName, String alias) { return this; } @@ -498,7 +397,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList min(String property * Adds a projection that allows the criteria to return the row count * */ - public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { + public ProjectionList rowCount() { return rowCount(null); } @@ -507,9 +406,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { * * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList rowCount(String alias) { - final Projection proj = Projections.rowCount(); - addProjectionToList(proj, alias); + public ProjectionList rowCount(String alias) { return this; } @@ -518,7 +415,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList rowCount(String ali * * @param propertyName The name of the property */ - public org.grails.datastore.mapping.query.api.ProjectionList sum(String propertyName) { + public ProjectionList sum(String propertyName) { return sum(propertyName, null); } @@ -528,9 +425,7 @@ public org.grails.datastore.mapping.query.api.ProjectionList sum(String property * @param propertyName The name of the property * @param alias The alias to use */ - public org.grails.datastore.mapping.query.api.ProjectionList sum(String propertyName, String alias) { - final AggregateProjection proj = Projections.sum(calculatePropertyName(propertyName)); - addProjectionToList(proj, alias); + public ProjectionList sum(String propertyName, String alias) { return this; } @@ -541,9 +436,6 @@ public org.grails.datastore.mapping.query.api.ProjectionList sum(String property * @param fetchMode The fetch mode to set */ public void fetchMode(String associationPath, FetchMode fetchMode) { - if (criteria != null) { - criteria.setFetchMode(associationPath, fetchMode); - } } /** @@ -551,29 +443,9 @@ public void fetchMode(String associationPath, FetchMode fetchMode) { * @param transformer The result transformer to use. */ public void resultTransformer(ResultTransformer transformer) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [resultTransformer] not supported here")); - } resultTransformer = transformer; } - /** - * Join an association, assigning an alias to the joined association. - * - * Functionally equivalent to createAlias(String, String, int) using - * CriteriaSpecificationINNER_JOIN for the joinType. - * - * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * - * @return this (for method chaining) - * #see {@link #createAlias(String, String, int)} - * @throws HibernateException Indicates a problem creating the sub criteria - */ - public Criteria createAlias(String associationPath, String alias) { - return criteria.createAlias(associationPath, alias); - } - /** * Creates a Criterion that compares to class properties for equality @@ -581,15 +453,7 @@ public Criteria createAlias(String associationPath, String alias) { * @param otherPropertyName The second property name * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria eqProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [eqProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.eqProperty(propertyName, otherPropertyName)); + public Criteria eqProperty(String propertyName, String otherPropertyName) { return this; } @@ -599,15 +463,7 @@ public org.grails.datastore.mapping.query.api.Criteria eqProperty(String propert * @param otherPropertyName The second property name * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria neProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [neProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.neProperty(propertyName, otherPropertyName)); + public Criteria neProperty(String propertyName, String otherPropertyName) { return this; } @@ -617,15 +473,7 @@ public org.grails.datastore.mapping.query.api.Criteria neProperty(String propert * @param otherPropertyName The second property name * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria gtProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [gtProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.gtProperty(propertyName, otherPropertyName)); + public Criteria gtProperty(String propertyName, String otherPropertyName) { return this; } @@ -635,15 +483,7 @@ public org.grails.datastore.mapping.query.api.Criteria gtProperty(String propert * @param otherPropertyName The second property name * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria geProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [geProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.geProperty(propertyName, otherPropertyName)); + public Criteria geProperty(String propertyName, String otherPropertyName) { return this; } @@ -653,15 +493,7 @@ public org.grails.datastore.mapping.query.api.Criteria geProperty(String propert * @param otherPropertyName The second property name * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria ltProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ltProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.ltProperty(propertyName, otherPropertyName)); + public Criteria ltProperty(String propertyName, String otherPropertyName) { return this; } @@ -671,21 +503,12 @@ public org.grails.datastore.mapping.query.api.Criteria ltProperty(String propert * @param otherPropertyName The second property name * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria leProperty(String propertyName, String otherPropertyName) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [leProperty] with propertyName [" + - propertyName + "] and other property name [" + otherPropertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - otherPropertyName = calculatePropertyName(otherPropertyName); - addToCriteria(Restrictions.leProperty(propertyName, otherPropertyName)); + public Criteria leProperty(String propertyName, String otherPropertyName) { return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria allEq(Map propertyValues) { - addToCriteria( Restrictions.allEq(propertyValues) ); + public Criteria allEq(Map propertyValues) { return this; } @@ -698,7 +521,7 @@ public org.grails.datastore.mapping.query.api.Criteria allEq(Map * @return A Criterion instance */ @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName, Closure propertyValue) { + public Criteria eqAll(String propertyName, Closure propertyValue) { return eqAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -711,7 +534,7 @@ public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName * @return A Criterion instance */ @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName, Closure propertyValue) { + public Criteria gtAll(String propertyName, Closure propertyValue) { return gtAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -723,7 +546,7 @@ public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName * @return A Criterion instance */ @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName, Closure propertyValue) { + public Criteria ltAll(String propertyName, Closure propertyValue) { return ltAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -735,7 +558,7 @@ public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName * @return A Criterion instance */ @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName, Closure propertyValue) { + public Criteria geAll(String propertyName, Closure propertyValue) { return geAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -747,7 +570,7 @@ public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName * @return A Criterion instance */ @SuppressWarnings({ "unchecked", "rawtypes" }) - public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName, Closure propertyValue) { + public Criteria leAll(String propertyName, Closure propertyValue) { return leAll(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @@ -758,9 +581,8 @@ public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName, + public Criteria eqAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).eqAll(convertToHibernateCriteria(propertyValue))); return this; } @@ -771,85 +593,78 @@ public org.grails.datastore.mapping.query.api.Criteria eqAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria gtAll(String propertyName, + public Criteria gtAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).gtAll(convertToHibernateCriteria(propertyValue))); return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria gtSome(String propertyName, QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).gtSome(convertToHibernateCriteria(propertyValue))); + public Criteria gtSome(String propertyName, QueryableCriteria propertyValue) { return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria gtSome(String propertyName, Closure propertyValue) { + public Criteria gtSome(String propertyName, Closure propertyValue) { return gtSome(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @Override - public org.grails.datastore.mapping.query.api.Criteria geSome(String propertyName, QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).geSome(convertToHibernateCriteria(propertyValue))); + public Criteria geSome(String propertyName, QueryableCriteria propertyValue) { return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria geSome(String propertyName, Closure propertyValue) { + public Criteria geSome(String propertyName, Closure propertyValue) { return geSome(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @Override - public org.grails.datastore.mapping.query.api.Criteria ltSome(String propertyName, QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).ltSome(convertToHibernateCriteria(propertyValue))); + public Criteria ltSome(String propertyName, QueryableCriteria propertyValue) { return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria ltSome(String propertyName, Closure propertyValue) { + public Criteria ltSome(String propertyName, Closure propertyValue) { return ltSome(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @Override - public org.grails.datastore.mapping.query.api.Criteria leSome(String propertyName, QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).leSome(convertToHibernateCriteria(propertyValue))); + public Criteria leSome(String propertyName, QueryableCriteria propertyValue) { return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria leSome(String propertyName, Closure propertyValue) { + public Criteria leSome(String propertyName, Closure propertyValue) { return leSome(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(propertyValue)); } @Override - public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, QueryableCriteria subquery) { + public Criteria in(String propertyName, QueryableCriteria subquery) { return inList(propertyName, subquery); } @Override - public org.grails.datastore.mapping.query.api.Criteria inList(String propertyName, QueryableCriteria subquery) { - addToCriteria(Property.forName(propertyName).in(convertToHibernateCriteria(subquery))); + public Criteria inList(String propertyName, QueryableCriteria subquery) { return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, Closure subquery) { + public Criteria in(String propertyName, Closure subquery) { return inList(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(subquery)); } @Override - public org.grails.datastore.mapping.query.api.Criteria inList(String propertyName, Closure subquery) { + public Criteria inList(String propertyName, Closure subquery) { return inList(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(subquery)); } @Override - public org.grails.datastore.mapping.query.api.Criteria notIn(String propertyName, QueryableCriteria subquery) { - addToCriteria(Property.forName(propertyName).notIn(convertToHibernateCriteria(subquery))); + public Criteria notIn(String propertyName, QueryableCriteria subquery) { return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria notIn(String propertyName, Closure subquery) { + public Criteria notIn(String propertyName, Closure subquery) { return notIn(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(subquery)); } @@ -860,9 +675,8 @@ public org.grails.datastore.mapping.query.api.Criteria notIn(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName, + public Criteria ltAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).ltAll(convertToHibernateCriteria(propertyValue))); return this; } @@ -874,9 +688,8 @@ public org.grails.datastore.mapping.query.api.Criteria ltAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName, + public Criteria geAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).geAll(convertToHibernateCriteria(propertyValue))); return this; } @@ -888,9 +701,8 @@ public org.grails.datastore.mapping.query.api.Criteria geAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName, + public Criteria leAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { - addToCriteria(Property.forName(propertyName).leAll(convertToHibernateCriteria(propertyValue))); return this; } @@ -901,27 +713,11 @@ public org.grails.datastore.mapping.query.api.Criteria leAll(String propertyName * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria gt(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [gt] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - - Criterion gt; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - gt = Property.forName(propertyName).gt((org.hibernate.criterion.DetachedCriteria)propertyValue); - } - else { - gt = Restrictions.gt(propertyName, propertyValue); - } - addToCriteria(gt); + public Criteria gt(String propertyName, Object propertyValue) { return this; } - public org.grails.datastore.mapping.query.api.Criteria lte(String s, Object o) { + public Criteria lte(String s, Object o) { return le(s,o); } @@ -931,23 +727,7 @@ public org.grails.datastore.mapping.query.api.Criteria lte(String s, Object o) { * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria ge(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ge] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - - Criterion ge; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - ge = Property.forName(propertyName).ge((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - ge = Restrictions.ge(propertyName, propertyValue); - } - addToCriteria(ge); + public Criteria ge(String propertyName, Object propertyValue) { return this; } @@ -957,22 +737,7 @@ public org.grails.datastore.mapping.query.api.Criteria ge(String propertyName, O * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria lt(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [lt] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion lt; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - lt = Property.forName(propertyName).lt((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - lt = Restrictions.lt(propertyName, propertyValue); - } - addToCriteria(lt); + public Criteria lt(String propertyName, Object propertyValue) { return this; } @@ -982,88 +747,65 @@ public org.grails.datastore.mapping.query.api.Criteria lt(String propertyName, O * @param propertyValue The property value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria le(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [le] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion le; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - le = Property.forName(propertyName).le((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - le = Restrictions.le(propertyName, propertyValue); - } - addToCriteria(le); + public Criteria le(String propertyName, Object propertyValue) { return this; } - public org.grails.datastore.mapping.query.api.Criteria idEquals(Object o) { + public Criteria idEquals(Object o) { return idEq(o); } @Override - public org.grails.datastore.mapping.query.api.Criteria exists(QueryableCriteria subquery) { - addToCriteria(Subqueries.exists(convertToHibernateCriteria(subquery))); + public Criteria exists(QueryableCriteria subquery) { return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria notExists(QueryableCriteria subquery) { - addToCriteria(Subqueries.notExists(convertToHibernateCriteria(subquery))); + public Criteria notExists(QueryableCriteria subquery) { return this; } - public org.grails.datastore.mapping.query.api.Criteria isEmpty(String property) { + public Criteria isEmpty(String property) { String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isEmpty(propertyName)); return this; } - public org.grails.datastore.mapping.query.api.Criteria isNotEmpty(String property) { + public Criteria isNotEmpty(String property) { String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNotEmpty(propertyName)); return this; } - public org.grails.datastore.mapping.query.api.Criteria isNull(String property) { + public Criteria isNull(String property) { String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNull(propertyName)); return this; } - public org.grails.datastore.mapping.query.api.Criteria isNotNull(String property) { + public Criteria isNotNull(String property) { String propertyName = calculatePropertyName(property); - addToCriteria(Restrictions.isNotNull(propertyName)); return this; } @Override - public org.grails.datastore.mapping.query.api.Criteria and(Closure callable) { + public Criteria and(Closure callable) { return executeLogicalExpression(callable, AND); } @Override - public org.grails.datastore.mapping.query.api.Criteria or(Closure callable) { + public Criteria or(Closure callable) { return executeLogicalExpression(callable, OR); } @Override - public org.grails.datastore.mapping.query.api.Criteria not(Closure callable) { + public Criteria not(Closure callable) { return executeLogicalExpression(callable, NOT); } - protected org.grails.datastore.mapping.query.api.Criteria executeLogicalExpression(Closure callable, String logicalOperator) { + protected Criteria executeLogicalExpression(Closure callable, String logicalOperator) { logicalExpressionStack.add(new LogicalExpression(logicalOperator)); try { invokeClosureNode(callable); } finally { LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - if(logicalExpression != null) - addToCriteria(logicalExpression.toCriterion()); } return this; @@ -1076,11 +818,11 @@ protected org.grails.datastore.mapping.query.api.Criteria executeLogicalExpressi * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, Object propertyValue) { + public Criteria eq(String propertyName, Object propertyValue) { return eq(propertyName, propertyValue, Collections.emptyMap()); } - public org.grails.datastore.mapping.query.api.Criteria idEq(Object o) { + public Criteria idEq(Object o) { return eq("id", o); } @@ -1093,7 +835,7 @@ public org.grails.datastore.mapping.query.api.Criteria idEq(Object o) { * @return A Criterion instance */ @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria eq(Map params, String propertyName, Object propertyValue) { + public Criteria eq(Map params, String propertyName, Object propertyValue) { return eq(propertyName, propertyValue, params); } @@ -1108,28 +850,7 @@ public org.grails.datastore.mapping.query.api.Criteria eq(Map params, String pro * @return A Criterion instance */ @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, Object propertyValue, Map params) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [eq] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - Criterion eq; - if (propertyValue instanceof org.hibernate.criterion.DetachedCriteria) { - eq = Property.forName(propertyName).eq((org.hibernate.criterion.DetachedCriteria) propertyValue); - } - else { - eq = Restrictions.eq(propertyName, propertyValue); - } - if (params != null && (eq instanceof SimpleExpression)) { - Object ignoreCase = params.get("ignoreCase"); - if (ignoreCase instanceof Boolean && (Boolean)ignoreCase) { - eq = ((SimpleExpression)eq).ignoreCase(); - } - } - addToCriteria(eq); + public Criteria eq(String propertyName, Object propertyValue, Map params) { return this; } @@ -1139,11 +860,7 @@ public org.grails.datastore.mapping.query.api.Criteria eq(String propertyName, O * @param sqlRestriction the sql restriction * @return a Criteria instance */ - public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sqlRestriction) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sqlRestriction] with value [" + - sqlRestriction + "] not allowed here.")); - } + public Criteria sqlRestriction(String sqlRestriction) { return sqlRestriction(sqlRestriction, Collections.EMPTY_LIST); } @@ -1154,25 +871,7 @@ public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sql * @param values jdbc parameters * @return a Criteria instance */ - public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sqlRestriction, List values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sqlRestriction] with value [" + - sqlRestriction + "] not allowed here.")); - } - final int numberOfParameters = values.size(); - - final Type[] typesArray = new Type[numberOfParameters]; - final Object[] valuesArray = new Object[numberOfParameters]; - - if (numberOfParameters > 0) { - final TypeHelper typeHelper = sessionFactory.getTypeHelper(); - for (int i = 0; i < typesArray.length; i++) { - final Object value = values.get(i); - typesArray[i] = typeHelper.basic(value.getClass()); - valuesArray[i] = value; - } - } - addToCriteria(Restrictions.sqlRestriction(sqlRestriction, valuesArray, typesArray)); + public Criteria sqlRestriction(String sqlRestriction, List values) { return this; } @@ -1183,26 +882,11 @@ public org.grails.datastore.mapping.query.api.Criteria sqlRestriction(String sql * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria like(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [like] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.like(propertyName, propertyValue)); + public Criteria like(String propertyName, Object propertyValue) { return this; } - /** - * Creates a Criterion with from the specified property name and "rlike" (a regular expression version of "like") expression - * @param propertyName The property name - * @param propertyValue The ilike value - * - * @return A Criterion instance - */ - public abstract org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName, Object propertyValue); + /** * Creates a Criterion with from the specified property name and "ilike" (a case sensitive version of "like") expression @@ -1211,15 +895,8 @@ public org.grails.datastore.mapping.query.api.Criteria like(String propertyName, * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria ilike(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ilike] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } + public Criteria ilike(String propertyName, Object propertyValue) { - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.ilike(propertyName, propertyValue)); return this; } @@ -1231,18 +908,7 @@ public org.grails.datastore.mapping.query.api.Criteria ilike(String propertyName * @return A Criterion instance */ @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, Collection values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [in] with propertyName [" + - propertyName + "] and values [" + values + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - - if(values instanceof List) { - values = convertArgumentList((List)values); - } - addToCriteria(Restrictions.in(propertyName, values == null ? Collections.EMPTY_LIST : values)); + public Criteria in(String propertyName, Collection values) { return this; } @@ -1261,14 +927,14 @@ protected List convertArgumentList(List argList) { * Delegates to in as in is a Groovy keyword */ @SuppressWarnings("rawtypes") - public org.grails.datastore.mapping.query.api.Criteria inList(String propertyName, Collection values) { + public Criteria inList(String propertyName, Collection values) { return in(propertyName, values); } /** * Delegates to in as in is a Groovy keyword */ - public org.grails.datastore.mapping.query.api.Criteria inList(String propertyName, Object[] values) { + public Criteria inList(String propertyName, Object[] values) { return in(propertyName, values); } @@ -1279,14 +945,7 @@ public org.grails.datastore.mapping.query.api.Criteria inList(String propertyNam * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, Object[] values) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [in] with propertyName [" + - propertyName + "] and values [" + values + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.in(propertyName, values)); + public Criteria in(String propertyName, Object[] values) { return this; } @@ -1296,81 +955,19 @@ public org.grails.datastore.mapping.query.api.Criteria in(String propertyName, O * @param propertyName The property name to order by * @return A Order instance */ - public org.grails.datastore.mapping.query.api.Criteria order(String propertyName) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] with propertyName [" + - propertyName + "]not allowed here.")); - } - propertyName = calculatePropertyName(propertyName); - Order o = Order.asc(propertyName); - addOrderInternal(this.criteria, o); + public Criteria order(String propertyName) { return this; } - /** - * Orders by the specified property name (defaults to ascending) - * - * @param o The property name to order by - * @return A Order instance - */ - public org.grails.datastore.mapping.query.api.Criteria order(Order o) { - final Criteria criteria = this.criteria; - addOrderInternal(criteria, o); - return this; - } - private void addOrderInternal(Criteria criteria, Order o) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] not allowed here.")); - } - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - criteria.addOrder(o); - } - } @Override - public org.grails.datastore.mapping.query.api.Criteria order(Query.Order o) { - - final Criteria criteria = this.criteria; - final String property = o.getProperty(); - addOrderInternal(criteria, o, property); + public Criteria order(Query.Order o) { return this; } - private void addOrderInternal(Criteria criteria, Query.Order o, String property) { - final int i = property.indexOf('.'); - if(i == -1) { - Order order = convertOrder(o, property); - addOrderInternal(criteria, order); - } - else { - String sortHead = property.substring(0,i); - String sortTail = property.substring(i+1); - createAliasIfNeccessary(sortHead, sortHead, org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue()); - final Criteria sub = aliasInstanceStack.get(aliasInstanceStack.size()-1); - addOrderInternal(sub, o, sortTail); - } - } - protected Order convertOrder(Query.Order o, String property) { - Order order; - switch (o.getDirection()) { - case DESC: - order = Order.desc(property); - break; - default: - order = Order.asc(property); - break; - } - if(o.isIgnoreCase()) { - order.ignoreCase(); - } - return order; - } /** * Orders by the specified property name and direction @@ -1380,25 +977,7 @@ protected Order convertOrder(Query.Order o, String property) { * * @return A Order instance */ - public org.grails.datastore.mapping.query.api.Criteria order(String propertyName, String direction) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("Call to [order] with propertyName [" + - propertyName + "]not allowed here.")); - } - propertyName = calculatePropertyName(propertyName); - Order o; - if (direction.equals(ORDER_DESCENDING)) { - o = Order.desc(propertyName); - } - else { - o = Order.asc(propertyName); - } - if (paginationEnabledList) { - orderEntries.add(o); - } - else { - criteria.addOrder(o); - } + public Criteria order(String propertyName, String direction) { return this; } @@ -1410,14 +989,7 @@ public org.grails.datastore.mapping.query.api.Criteria order(String propertyName * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria sizeEq(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeEq] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeEq(propertyName, size)); + public Criteria sizeEq(String propertyName, int size) { return this; } @@ -1429,14 +1001,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeEq(String propertyNam * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria sizeGt(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeGt] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeGt(propertyName, size)); + public Criteria sizeGt(String propertyName, int size) { return this; } @@ -1448,14 +1013,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeGt(String propertyNam * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria sizeGe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeGe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeGe(propertyName, size)); + public Criteria sizeGe(String propertyName, int size) { return this; } @@ -1467,14 +1025,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeGe(String propertyNam * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria sizeLe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeLe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeLe(propertyName, size)); + public Criteria sizeLe(String propertyName, int size) { return this; } @@ -1486,14 +1037,18 @@ public org.grails.datastore.mapping.query.api.Criteria sizeLe(String propertyNam * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria sizeLt(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeLt] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } + public Criteria sizeLt(String propertyName, int size) { + return this; + } - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeLt(propertyName, size)); + /** + * Creates a Criterion with from the specified property name and "rlike" (a regular expression version of "like") expression + * + * @param propertyName The property name + * @param propertyValue The ilike value + * @return A Criterion instance + */ + public org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName, Object propertyValue) { return this; } @@ -1505,14 +1060,7 @@ public org.grails.datastore.mapping.query.api.Criteria sizeLt(String propertyNam * * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria sizeNe(String propertyName, int size) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [sizeNe] with propertyName [" + - propertyName + "] and size [" + size + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.sizeNe(propertyName, size)); + public Criteria sizeNe(String propertyName, int size) { return this; } @@ -1522,21 +1070,10 @@ public org.grails.datastore.mapping.query.api.Criteria sizeNe(String propertyNam * @param propertyValue The property value * @return The criterion object */ - public org.grails.datastore.mapping.query.api.Criteria ne(String propertyName, Object propertyValue) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [ne] with propertyName [" + - propertyName + "] and value [" + propertyValue + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - propertyValue = calculatePropertyValue(propertyValue); - addToCriteria(Restrictions.ne(propertyName, propertyValue)); + public Criteria ne(String propertyName, Object propertyValue) { return this; } - public org.grails.datastore.mapping.query.api.Criteria notEqual(String propertyName, Object propertyValue) { - return ne(propertyName, propertyValue); - } /** * Creates a "between" Criterion based on the property name and specified lo and hi values @@ -1545,18 +1082,11 @@ public org.grails.datastore.mapping.query.api.Criteria notEqual(String propertyN * @param hi The high value * @return A Criterion instance */ - public org.grails.datastore.mapping.query.api.Criteria between(String propertyName, Object lo, Object hi) { - if (!validateSimpleExpression()) { - throwRuntimeException(new IllegalArgumentException("Call to [between] with propertyName [" + - propertyName + "] not allowed here.")); - } - - propertyName = calculatePropertyName(propertyName); - addToCriteria(Restrictions.between(propertyName, lo, hi)); + public Criteria between(String propertyName, Object lo, Object hi) { return this; } - public org.grails.datastore.mapping.query.api.Criteria gte(String s, Object o) { + public Criteria gte(String s, Object o) { return ge(s, o); } @@ -1593,260 +1123,260 @@ public Object scroll(@DelegatesTo(Criteria.class) Closure c) { @Override public Object invokeMethod(String name, Object obj) { Object[] args = obj.getClass().isArray() ? (Object[])obj : new Object[]{obj}; - - if (paginationEnabledList && SET_RESULT_TRANSFORMER_CALL.equals(name) && args.length == 1 && - args[0] instanceof ResultTransformer) { - resultTransformer = (ResultTransformer) args[0]; - return null; - } - - if (isCriteriaConstructionMethod(name, args)) { - if (criteria != null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - if (name.equals(GET_CALL)) { - uniqueResult = true; - } - else if (name.equals(SCROLL_CALL)) { - scroll = true; - } - else if (name.equals(COUNT_CALL)) { - count = true; - } - else if (name.equals(LIST_DISTINCT_CALL)) { - resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; - } - - createCriteriaInstance(); - - // Check for pagination params - if (name.equals(LIST_CALL) && args.length == 2) { - paginationEnabledList = true; - orderEntries = new ArrayList<>(); - invokeClosureNode(args[1]); - } - else { - invokeClosureNode(args[0]); - } - - if (resultTransformer != null) { - criteria.setResultTransformer(resultTransformer); - } - Object result; - if (!uniqueResult) { - if (scroll) { - result = criteria.scroll(); - } - else if (count) { - criteria.setProjection(Projections.rowCount()); - result = criteria.uniqueResult(); - } - else if (paginationEnabledList) { - // Calculate how many results there are in total. This has been - // moved to before the 'list()' invocation to avoid any "ORDER - // BY" clause added by 'populateArgumentsForCriteria()', otherwise - // an exception is thrown for non-string sort fields (GRAILS-2690). - criteria.setFirstResult(0); - criteria.setMaxResults(Integer.MAX_VALUE); - - // Restore the previous projection, add settings for the pagination parameters, - // and then execute the query. - boolean isProjection = (projectionList != null && projectionList.getLength() > 0); - criteria.setProjection(isProjection ? projectionList : null); - - for (Order orderEntry : orderEntries) { - criteria.addOrder(orderEntry); - } - if (resultTransformer == null) { - // GRAILS-9644 - Use projection transformer - criteria.setResultTransformer( isProjection ? - CriteriaSpecification.PROJECTION : - CriteriaSpecification.ROOT_ENTITY - ); - } - else if (paginationEnabledList) { - // relevant to GRAILS-5692 - criteria.setResultTransformer(resultTransformer); - } - // GRAILS-7324 look if we already have association to sort by - Map argMap = (Map)args[0]; - final String sort = (String) argMap.get(HibernateQueryConstants.ARGUMENT_SORT); - if (sort != null) { - boolean ignoreCase = true; - Object caseArg = argMap.get(HibernateQueryConstants.ARGUMENT_IGNORE_CASE); - if (caseArg instanceof Boolean) { - ignoreCase = (Boolean) caseArg; - } - final String orderParam = (String) argMap.get(HibernateQueryConstants.ARGUMENT_ORDER); - final String order = HibernateQueryConstants.ORDER_DESC.equalsIgnoreCase(orderParam) ? - HibernateQueryConstants.ORDER_DESC : HibernateQueryConstants.ORDER_ASC; - int lastPropertyPos = sort.lastIndexOf('.'); - String associationForOrdering = lastPropertyPos >= 0 ? sort.substring(0, lastPropertyPos) : null; - if (associationForOrdering != null && aliasMap.containsKey(associationForOrdering)) { - addOrder(criteria, aliasMap.get(associationForOrdering) + "." + sort.substring(lastPropertyPos + 1), - order, ignoreCase); - // remove sort from arguments map to exclude from default processing. - @SuppressWarnings("unchecked") Map argMap2 = new HashMap(argMap); - argMap2.remove(HibernateQueryConstants.ARGUMENT_SORT); - argMap = argMap2; - } - } - result = createPagedResultList(argMap); - } - else { - result = criteria.list(); - } - } - else { - result = executeUniqueResultWithProxyUnwrap(); - } - if (!participate) { - closeSession(); - } - return result; - } - - if (criteria == null) createCriteriaInstance(); - - MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); - if (metaMethod != null) { - return metaMethod.invoke(this, args); - } - - metaMethod = criteriaMetaClass.getMetaMethod(name, args); - if (metaMethod != null) { - return metaMethod.invoke(criteria, args); - } - metaMethod = criteriaMetaClass.getMetaMethod(NameUtils.getSetterName(name), args); - if (metaMethod != null) { - return metaMethod.invoke(criteria, args); - } - - if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { - final boolean hasMoreThanOneArg = args.length > 1; - Object callable = hasMoreThanOneArg ? args[1] : args[0]; - int joinType = hasMoreThanOneArg ? (Integer)args[0] : org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue(); - - if (name.equals(AND) || name.equals(OR) || name.equals(NOT)) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - logicalExpressionStack.add(new LogicalExpression(name)); - invokeClosureNode(callable); - - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - addToCriteria(logicalExpression.toCriterion()); - - return name; - } - - if (name.equals(PROJECTIONS) && args.length == 1 && (args[0] instanceof Closure)) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - projectionList = Projections.projectionList(); - invokeClosureNode(callable); - - if (projectionList != null && projectionList.getLength() > 0) { - criteria.setProjection(projectionList); - } - - return name; - } - - final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(targetClass, name); - if (pd != null && pd.getReadMethod() != null) { - final Metamodel metamodel = sessionFactory.getMetamodel(); - final EntityType entityType = metamodel.entity(targetClass); - final Attribute attribute = entityType.getAttribute(name); - - if (attribute.isAssociation()) { - Class oldTargetClass = targetClass; - targetClass = getClassForAssociationType(attribute); - if (targetClass.equals(oldTargetClass) && !hasMoreThanOneArg) { - joinType = org.hibernate.sql.JoinType.LEFT_OUTER_JOIN.getJoinTypeValue(); // default to left join if joining on the same table - } - associationStack.add(name); - final String associationPath = getAssociationPath(); - createAliasIfNeccessary(name, associationPath,joinType); - // the criteria within an association node are grouped with an implicit AND - logicalExpressionStack.add(new LogicalExpression(AND)); - invokeClosureNode(callable); - aliasStack.remove(aliasStack.size() - 1); - if (!aliasInstanceStack.isEmpty()) { - aliasInstanceStack.remove(aliasInstanceStack.size() - 1); - } - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - if (!logicalExpression.args.isEmpty()) { - addToCriteria(logicalExpression.toCriterion()); - } - associationStack.remove(associationStack.size()-1); - targetClass = oldTargetClass; - - return name; - } - if (attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED) { - associationStack.add(name); - logicalExpressionStack.add(new LogicalExpression(AND)); - Class oldTargetClass = targetClass; - targetClass = pd.getPropertyType(); - invokeClosureNode(callable); - targetClass = oldTargetClass; - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - if (!logicalExpression.args.isEmpty()) { - addToCriteria(logicalExpression.toCriterion()); - } - associationStack.remove(associationStack.size()-1); - return name; - } - } - } - else if (args.length == 1 && args[0] != null) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - - Object value = args[0]; - Criterion c = null; - if (name.equals(ID_EQUALS)) { - return eq("id", value); - } - - if (name.equals(IS_NULL) || - name.equals(IS_NOT_NULL) || - name.equals(IS_EMPTY) || - name.equals(IS_NOT_EMPTY)) { - if (!(value instanceof String)) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] with value [" + - value + "] requires a String value.")); - } - String propertyName = calculatePropertyName((String)value); - if (name.equals(IS_NULL)) { - c = Restrictions.isNull(propertyName); - } - else if (name.equals(IS_NOT_NULL)) { - c = Restrictions.isNotNull(propertyName); - } - else if (name.equals(IS_EMPTY)) { - c = Restrictions.isEmpty(propertyName); - } - else if (name.equals(IS_NOT_EMPTY)) { - c = Restrictions.isNotEmpty(propertyName); - } - } - - if (c != null) { - return addToCriteria(c); - } - } +// +// if (paginationEnabledList && SET_RESULT_TRANSFORMER_CALL.equals(name) && args.length == 1 && +// args[0] instanceof ResultTransformer) { +// resultTransformer = (ResultTransformer) args[0]; +// return null; +// } +// +// if (isCriteriaConstructionMethod(name, args)) { +// if (criteria != null) { +// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); +// } +// +// if (name.equals(GET_CALL)) { +// uniqueResult = true; +// } +// else if (name.equals(SCROLL_CALL)) { +// scroll = true; +// } +// else if (name.equals(COUNT_CALL)) { +// count = true; +// } +//// else if (name.equals(LIST_DISTINCT_CALL)) { +//// resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; +//// } +// +// createCriteriaInstance(); +// +// // Check for pagination params +// if (name.equals(LIST_CALL) && args.length == 2) { +// paginationEnabledList = true; +// invokeClosureNode(args[1]); +// } +// else { +// invokeClosureNode(args[0]); +// } +// +//// if (resultTransformer != null) { +//// criteria.setResultTransformer(resultTransformer); +//// } +// Object result; +// if (!uniqueResult) { +// if (scroll) { +// +// result = hibernateSession.createQuery(criteria).scroll(); +// } +// else if (count) { +// criteria.select(cb.count(root)); +// result = hibernateSession.createQuery(criteria).getSingleResult(); +// } +// else if (paginationEnabledList) { +// // Calculate how many results there are in total. This has been +// // moved to before the 'list()' invocation to avoid any "ORDER +// // BY" clause added by 'populateArgumentsForCriteria()', otherwise +// // an exception is thrown for non-string sort fields (GRAILS-2690). +// criteria.setFirstResult(0); +// criteria.setMaxResults(Integer.MAX_VALUE); +// +// // Restore the previous projection, add settings for the pagination parameters, +// // and then execute the query. +// boolean isProjection = (projectionList != null && projectionList.getLength() > 0); +// criteria.setProjection(isProjection ? projectionList : null); +// +// for (Order orderEntry : orderEntries) { +// criteria.addOrder(orderEntry); +// } +// if (resultTransformer == null) { +// // GRAILS-9644 - Use projection transformer +// criteria.setResultTransformer( isProjection ? +// CriteriaSpecification.PROJECTION : +// CriteriaSpecification.ROOT_ENTITY +// ); +// } +// else if (paginationEnabledList) { +// // relevant to GRAILS-5692 +// criteria.setResultTransformer(resultTransformer); +// } +// // GRAILS-7324 look if we already have association to sort by +// Map argMap = (Map)args[0]; +// final String sort = (String) argMap.get(HibernateQueryConstants.ARGUMENT_SORT); +// if (sort != null) { +// boolean ignoreCase = true; +// Object caseArg = argMap.get(HibernateQueryConstants.ARGUMENT_IGNORE_CASE); +// if (caseArg instanceof Boolean) { +// ignoreCase = (Boolean) caseArg; +// } +// final String orderParam = (String) argMap.get(HibernateQueryConstants.ARGUMENT_ORDER); +// final String order = HibernateQueryConstants.ORDER_DESC.equalsIgnoreCase(orderParam) ? +// HibernateQueryConstants.ORDER_DESC : HibernateQueryConstants.ORDER_ASC; +// int lastPropertyPos = sort.lastIndexOf('.'); +// String associationForOrdering = lastPropertyPos >= 0 ? sort.substring(0, lastPropertyPos) : null; +// if (associationForOrdering != null && aliasMap.containsKey(associationForOrdering)) { +// addOrder(criteria, aliasMap.get(associationForOrdering) + "." + sort.substring(lastPropertyPos + 1), +// order, ignoreCase); +// // remove sort from arguments map to exclude from default processing. +// @SuppressWarnings("unchecked") Map argMap2 = new HashMap(argMap); +// argMap2.remove(HibernateQueryConstants.ARGUMENT_SORT); +// argMap = argMap2; +// } +// } +// result = createPagedResultList(argMap); +// } +// else { +// result = criteria.list(); +// } +// } +// else { +// result = executeUniqueResultWithProxyUnwrap(); +// } +// if (!participate) { +// closeSession(); +// } +// return result; +// } +// +// if (criteria == null) createCriteriaInstance(); +// +// MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); +// if (metaMethod != null) { +// return metaMethod.invoke(this, args); +// } +// +// metaMethod = criteriaMetaClass.getMetaMethod(name, args); +// if (metaMethod != null) { +// return metaMethod.invoke(criteria, args); +// } +// metaMethod = criteriaMetaClass.getMetaMethod(NameUtils.getSetterName(name), args); +// if (metaMethod != null) { +// return metaMethod.invoke(criteria, args); +// } +// +// if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { +// final boolean hasMoreThanOneArg = args.length > 1; +// Object callable = hasMoreThanOneArg ? args[1] : args[0]; +// int joinType = hasMoreThanOneArg ? (Integer)args[0] : org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue(); +// +// if (name.equals(AND) || name.equals(OR) || name.equals(NOT)) { +// if (criteria == null) { +// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); +// } +// +// logicalExpressionStack.add(new LogicalExpression(name)); +// invokeClosureNode(callable); +// +// LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); +// addToCriteria(logicalExpression.toCriterion()); +// +// return name; +// } +// +// if (name.equals(PROJECTIONS) && args.length == 1 && (args[0] instanceof Closure)) { +// if (criteria == null) { +// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); +// } +// +// projectionList = Projections.projectionList(); +// invokeClosureNode(callable); +// +// if (projectionList != null && projectionList.getLength() > 0) { +// criteria.setProjection(projectionList); +// } +// +// return name; +// } +// +// final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(targetClass, name); +// if (pd != null && pd.getReadMethod() != null) { +// final Metamodel metamodel = sessionFactory.getMetamodel(); +// final EntityType entityType = metamodel.entity(targetClass); +// final Attribute attribute = entityType.getAttribute(name); +// +// if (attribute.isAssociation()) { +// Class oldTargetClass = targetClass; +// targetClass = getClassForAssociationType(attribute); +// if (targetClass.equals(oldTargetClass) && !hasMoreThanOneArg) { +// joinType = org.hibernate.sql.JoinType.LEFT_OUTER_JOIN.getJoinTypeValue(); // default to left join if joining on the same table +// } +// associationStack.add(name); +// final String associationPath = getAssociationPath(); +// createAliasIfNeccessary(name, associationPath,joinType); +// // the criteria within an association node are grouped with an implicit AND +// logicalExpressionStack.add(new LogicalExpression(AND)); +// invokeClosureNode(callable); +// aliasStack.remove(aliasStack.size() - 1); +// if (!aliasInstanceStack.isEmpty()) { +// aliasInstanceStack.remove(aliasInstanceStack.size() - 1); +// } +// LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); +// if (!logicalExpression.args.isEmpty()) { +// addToCriteria(logicalExpression.toCriterion()); +// } +// associationStack.remove(associationStack.size()-1); +// targetClass = oldTargetClass; +// +// return name; +// } +// if (attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED) { +// associationStack.add(name); +// logicalExpressionStack.add(new LogicalExpression(AND)); +// Class oldTargetClass = targetClass; +// targetClass = pd.getPropertyType(); +// invokeClosureNode(callable); +// targetClass = oldTargetClass; +// LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); +// if (!logicalExpression.args.isEmpty()) { +// addToCriteria(logicalExpression.toCriterion()); +// } +// associationStack.remove(associationStack.size()-1); +// return name; +// } +// } +// } +// else if (args.length == 1 && args[0] != null) { +// if (criteria == null) { +// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); +// } +// +// Object value = args[0]; +// Criterion c = null; +// if (name.equals(ID_EQUALS)) { +// return eq("id", value); +// } +// +// if (name.equals(IS_NULL) || +// name.equals(IS_NOT_NULL) || +// name.equals(IS_EMPTY) || +// name.equals(IS_NOT_EMPTY)) { +// if (!(value instanceof String)) { +// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] with value [" + +// value + "] requires a String value.")); +// } +// String propertyName = calculatePropertyName((String)value); +// if (name.equals(IS_NULL)) { +// c = Restrictions.isNull(propertyName); +// } +// else if (name.equals(IS_NOT_NULL)) { +// c = Restrictions.isNotNull(propertyName); +// } +// else if (name.equals(IS_EMPTY)) { +// c = Restrictions.isEmpty(propertyName); +// } +// else if (name.equals(IS_NOT_EMPTY)) { +// c = Restrictions.isNotEmpty(propertyName); +// } +// } +// +// if (c != null) { +// return addToCriteria(c); +// } +// } throw new MissingMethodException(name, getClass(), args); } - protected abstract Object executeUniqueResultWithProxyUnwrap(); + protected abstract List createPagedResultList(Map args); @@ -1860,19 +1390,7 @@ private boolean isAssociationQueryWithJoinSpecificationMethod(Object[] args) { } - private void createAliasIfNeccessary(String associationName, String associationPath, int joinType) { - String newAlias; - if (aliasMap.containsKey(associationPath)) { - newAlias = aliasMap.get(associationPath); - } - else { - aliasCount++; - newAlias = associationName + ALIAS + aliasCount; - aliasMap.put(associationPath, newAlias); - aliasInstanceStack.add(createAlias(associationPath, newAlias, joinType)); - } - aliasStack.add(newAlias); - } + private String getAssociationPath() { StringBuilder fullPath = new StringBuilder(); @@ -1895,12 +1413,12 @@ private boolean isCriteriaConstructionMethod(String name, Object[] args) { name.equals(SCROLL_CALL) && args.length == 1 && args[0] instanceof Closure); } - public Criteria buildCriteria(Closure criteriaClosure) { - createCriteriaInstance(); - criteriaClosure.setDelegate(this); - criteriaClosure.call(); - return criteria; - } +// public Criteria buildCriteria(Closure criteriaClosure) { +// createCriteriaInstance(); +// criteriaClosure.setDelegate(this); +// criteriaClosure.call(); +// return criteria; +// } protected abstract void createCriteriaInstance(); @@ -1916,39 +1434,15 @@ private void invokeClosureNode(Object args) { } - /** - * adds and returns the given criterion to the currently active criteria set. - * this might be either the root criteria or a currently open - * LogicalExpression. - */ - protected Criterion addToCriteria(Criterion c) { - if (!logicalExpressionStack.isEmpty()) { - logicalExpressionStack.get(logicalExpressionStack.size() - 1).args.add(c); - } - else { - criteria.add(c); - } - return c; - } - /** - * Add order directly to criteria. - */ - private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { - if (HibernateQueryConstants.ORDER_DESC.equals(order)) { - c.addOrder( ignoreCase ? Order.desc(sort).ignoreCase() : Order.desc(sort)); - } - else { - c.addOrder( ignoreCase ? Order.asc(sort).ignoreCase() : Order.asc(sort) ); - } - } + /** * Returns the criteria instance * @return The criteria instance */ - public Criteria getInstance() { + public CriteriaQuery getInstance() { return criteria; } @@ -1960,21 +1454,7 @@ public void setUniqueResult(boolean uniqueResult) { this.uniqueResult = uniqueResult; } - /** - * Join an association using the specified join-type, assigning an alias - * to the joined association. - * sub - * The joinType is expected to be one of CriteriaSpecification.INNER_JOIN (the default), - * CriteriaSpecificationFULL_JOIN, or CriteriaSpecificationLEFT_JOIN. - * - * @param associationPath A dot-seperated property path - * @param alias The alias to assign to the joined association (for later reference). - * @param joinType The type of join to use. - * - * @return this (for method chaining) - * @throws org.hibernate.HibernateException Indicates a problem creating the sub criteria - */ - public abstract Criteria createAlias(String associationPath, String alias, int joinType); + protected abstract Class getClassForAssociationType(Attribute type); @@ -1985,48 +1465,13 @@ public void setUniqueResult(boolean uniqueResult) { */ protected class LogicalExpression { public final Object name; - public final List args = new ArrayList(); public LogicalExpression(Object name) { this.name = name; } - public Criterion toCriterion() { - if (name.equals(NOT)) { - switch (args.size()) { - case 0: - throwRuntimeException(new IllegalArgumentException("Logical expression [not] must contain at least 1 expression")); - return null; - case 1: - return Restrictions.not(args.get(0)); - - default: - // treat multiple sub-criteria as an implicit "OR" - return Restrictions.not(buildJunction(Restrictions.disjunction(), args)); - } - } - - if (name.equals(AND)) { - return buildJunction(Restrictions.conjunction(), args); - } - if (name.equals(OR)) { - return buildJunction(Restrictions.disjunction(), args); - } - - throwRuntimeException(new IllegalStateException("Logical expression [" + name + "] not handled!")); - return null; - } - - // add the Criterion objects in the given list to the given junction. - public Junction buildJunction(Junction junction, List criterions) { - for (Criterion c : criterions) { - junction.add(c); - } - - return junction; - } } /** * Throws a runtime exception where necessary to ensure the session gets closed diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java deleted file mode 100644 index 75ca552cba1..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriterionAdapter.java +++ /dev/null @@ -1,565 +0,0 @@ -/* Copyright (C) 2011 SpringSource - * - * 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 org.grails.orm.hibernate.query; - -import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.query.AssociationQuery; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion; -import org.hibernate.criterion.*; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Adapts Grails datastore API to Hibernate API - * - * @author Graeme Rocher - * @since 2.0 - */ -public abstract class AbstractHibernateCriterionAdapter { - protected static final Map, CriterionAdaptor> criterionAdaptors = new HashMap, CriterionAdaptor>(); - protected static boolean initialized; - protected static final String ALIAS = "_alias"; - - public AbstractHibernateCriterionAdapter() { - initialize(); - } - - protected void initialize() { - if (initialized) { - return; - } - - synchronized (criterionAdaptors) { - // add simple property criterions (idEq, eq, ne, gt, lt, ge, le) - addSimplePropertyCriterionAdapters(); - - // add like operators (rlike, like, ilike) - addLikeCriterionAdapters(); - - //add simple size criterions (sizeEq, sizeGt, sizeLt, sizeGe, sizeLe) - addSizeComparisonCriterionAdapters(); - - - //add simple criterions (isNull, isNotNull, isEmpty, isNotEmpty) - addSimpleCriterionAdapters(); - - //add simple property comparison criterions (eqProperty, neProperty, gtProperty, geProperty, ltProperty, leProperty) - addPropertyComparisonCriterionAdapters(); - - // add range queries (in, between) - addRangeQueryCriterionAdapters(); - - // add subquery adapters (gtAll, geAll, gtSome, ltAll, leAll) - addSubqueryCriterionAdapters(); - - - // add junctions (conjunction, disjunction, negation) - addJunctionCriterionAdapters(); - - // add association query adapters - addAssociationQueryCriterionAdapters(); - } - - - initialized = true; - } - - protected void addSubqueryCriterionAdapters() { - criterionAdaptors.put(Query.GreaterThanAll.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanAll criterion, String alias) { - QueryableCriteria subQuery = criterion.getValue(); - String propertyName = getPropertyName(criterion, alias); - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery, subQuery); - return Property.forName(propertyName).gtAll(detachedCriteria); - } - }); - - criterionAdaptors.put(Query.GreaterThanEqualsAll.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanEqualsAll criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); - return Property.forName(getPropertyName(criterion, alias)).geAll(detachedCriteria); - } - }); - criterionAdaptors.put(Query.LessThanAll.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanAll criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); - return Property.forName(getPropertyName(criterion, alias)).ltAll(detachedCriteria); - } - }); - criterionAdaptors.put(Query.LessThanEqualsAll.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanEqualsAll criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); - return Property.forName(getPropertyName(criterion, alias)).leAll(detachedCriteria); - } - }); - - criterionAdaptors.put(Query.GreaterThanSome.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanSome criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); - return Property.forName(getPropertyName(criterion, alias)).gtSome(detachedCriteria); - } - }); - criterionAdaptors.put(Query.GreaterThanEqualsSome.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanEqualsSome criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); - return Property.forName(getPropertyName(criterion, alias)).geSome(detachedCriteria); - } - }); - criterionAdaptors.put(Query.LessThanSome.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanSome criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); - return Property.forName(getPropertyName(criterion, alias)).ltSome(detachedCriteria); - } - }); - criterionAdaptors.put(Query.LessThanEqualsSome.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanEqualsSome criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getValue()); - return Property.forName(getPropertyName(criterion, alias)).leSome(detachedCriteria); - } - }); - - criterionAdaptors.put(Query.NotIn.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.NotIn criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getSubquery()); - return Property.forName(getPropertyName(criterion, alias)).notIn(detachedCriteria); - } - }); - - criterionAdaptors.put(Query.Exists.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Exists criterion, String alias) { - final QueryableCriteria subquery = criterion.getSubquery(); - String subqueryAlias = subquery.getAlias(); - if (subquery.getAlias() == null) { - subqueryAlias = criterion.getSubquery().getPersistentEntity().getJavaClass().getSimpleName() + ALIAS; - } - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,subquery, subqueryAlias); - return Subqueries.exists(detachedCriteria); - } - }); - - criterionAdaptors.put(Query.NotExists.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.NotExists criterion, String alias) { - DetachedCriteria detachedCriteria = toHibernateDetachedCriteria(hibernateQuery,criterion.getSubquery()); - return Subqueries.notExists(detachedCriteria); - } - }); - } - - protected void addAssociationQueryCriterionAdapters() { - criterionAdaptors.put(DetachedAssociationCriteria.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - DetachedAssociationCriteria existing = (DetachedAssociationCriteria) criterion; - if(existing.getAlias() == null) { - alias = hibernateQuery.handleAssociationQuery(existing.getAssociation(), existing.getCriteria()); - } - else{ - alias = hibernateQuery.handleAssociationQuery(existing.getAssociation(), existing.getCriteria(), existing.getAlias()); - } - Association association = existing.getAssociation(); - hibernateQuery.associationStack.add(association); - Junction conjunction = Restrictions.conjunction(); - try { - applySubCriteriaToJunction(association.getAssociatedEntity(), hibernateQuery, existing.getCriteria(), conjunction, alias); - return conjunction; - } finally { - hibernateQuery.associationStack.removeLast(); - } - } - }); - criterionAdaptors.put(AssociationQuery.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - AssociationQuery existing = (AssociationQuery) criterion; - Junction conjunction = Restrictions.conjunction(); - String newAlias = hibernateQuery.handleAssociationQuery(existing.getAssociation(), existing.getCriteria().getCriteria()); - if (alias == null) { - alias = newAlias; - } - else { - alias += '.' + newAlias; - } - applySubCriteriaToJunction(existing.getAssociation().getAssociatedEntity(), hibernateQuery, existing.getCriteria().getCriteria(), conjunction, alias); - return conjunction; - } - }); - } - - protected void addJunctionCriterionAdapters() { - criterionAdaptors.put(Query.Conjunction.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Conjunction criterion, String alias) { - Conjunction conjunction = Restrictions.conjunction(); - applySubCriteriaToJunction(hibernateQuery.getEntity(), hibernateQuery, criterion.getCriteria(), conjunction, alias); - return conjunction; - } - }); - criterionAdaptors.put(Query.Disjunction.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Disjunction criterion, String alias) { - Disjunction disjunction = Restrictions.disjunction(); - applySubCriteriaToJunction(hibernateQuery.getEntity(), hibernateQuery, criterion.getCriteria(), disjunction, alias); - return disjunction; - } - }); - criterionAdaptors.put(Query.Negation.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Negation criterion, String alias) { - CriterionAdaptor adapter = (CriterionAdaptor)criterionAdaptors.get(Query.Disjunction.class); - return Restrictions.not(adapter.toHibernateCriterion(hibernateQuery, new Query.Disjunction(criterion.getCriteria()), alias)); - } - }); - } - - protected void addRangeQueryCriterionAdapters() { - criterionAdaptors.put(Query.Between.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - Query.Between btwCriterion = (Query.Between) criterion; - return Restrictions.between(calculatePropertyName(btwCriterion.getProperty(), alias), btwCriterion.getFrom(), btwCriterion.getTo()); - } - }); - - - criterionAdaptors.put(Query.In.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - Query.In inListQuery = (Query.In) criterion; - QueryableCriteria subquery = inListQuery.getSubquery(); - if(subquery != null) { - return Property.forName(getPropertyName(criterion,alias)).in( toHibernateDetachedCriteria(hibernateQuery, subquery) ); - } - else { - return Restrictions.in(getPropertyName(criterion, alias), inListQuery.getValues()); - } - } - }); - } - - protected void addLikeCriterionAdapters() { - criterionAdaptors.put(Query.RLike.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return createRlikeExpression(getPropertyName(criterion, alias), ((Query.RLike) criterion).getPattern()); - } - }); - criterionAdaptors.put(Query.Like.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Like criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - return Restrictions.like(propertyName, value); - } - }); - criterionAdaptors.put(Query.ILike.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.ILike criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - return Restrictions.ilike(propertyName, value); - } - }); - } - - protected void addPropertyComparisonCriterionAdapters() { - criterionAdaptors.put(Query.EqualsProperty.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.EqualsProperty criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.eqProperty(propertyName, criterion.getOtherProperty()); - } - }); - criterionAdaptors.put(Query.GreaterThanProperty.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanProperty criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.gtProperty(propertyName, criterion.getOtherProperty()); - } - }); - criterionAdaptors.put(Query.GreaterThanEqualsProperty.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanEqualsProperty criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.geProperty(propertyName, criterion.getOtherProperty()); - } - }); - criterionAdaptors.put(Query.LessThanProperty.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanProperty criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.ltProperty(propertyName, criterion.getOtherProperty()); - } - }); - criterionAdaptors.put(Query.LessThanEqualsProperty.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanEqualsProperty criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.leProperty(propertyName, criterion.getOtherProperty()); - } - }); - criterionAdaptors.put(Query.NotEqualsProperty.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.NotEqualsProperty criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.neProperty(propertyName, criterion.getOtherProperty()); - } - }); - } - - protected void addSimpleCriterionAdapters() { - criterionAdaptors.put(Query.IsNull.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.IsNull criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.isNull(propertyName); - } - }); - criterionAdaptors.put(Query.IsNotNull.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.IsNotNull criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.isNotNull(propertyName); - } - }); - criterionAdaptors.put(Query.IsEmpty.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.IsEmpty criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.isEmpty(propertyName); - } - }); - criterionAdaptors.put(Query.IsNotEmpty.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.IsNotEmpty criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - return Restrictions.isNotEmpty(propertyName); - } - }); - } - - protected void addSizeComparisonCriterionAdapters() { - criterionAdaptors.put(Query.SizeEquals.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeEquals criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); - return Restrictions.sizeEq(propertyName, size); - } - }); - - criterionAdaptors.put(Query.SizeGreaterThan.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeGreaterThan criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); - return Restrictions.sizeGt(propertyName, size); - } - }); - - criterionAdaptors.put(Query.SizeGreaterThanEquals.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeGreaterThanEquals criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); - return Restrictions.sizeGe(propertyName, size); - } - }); - - criterionAdaptors.put(Query.SizeLessThan.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeLessThan criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); - return Restrictions.sizeLt(propertyName, size); - } - }); - - criterionAdaptors.put(Query.SizeLessThanEquals.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.SizeLessThanEquals criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - int size = value instanceof Number ? ((Number)value).intValue() : Integer.parseInt(value.toString()); - return Restrictions.sizeLe(propertyName, size); - } - }); - } - - protected void addSimplePropertyCriterionAdapters() { - criterionAdaptors.put(Query.IdEquals.class, new CriterionAdaptor() { - @Override - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - return Restrictions.idEq(((Query.IdEquals) criterion).getValue()); - } - }); - criterionAdaptors.put(Query.Equals.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Equals criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - if(value instanceof DetachedCriteria) { - return Property.forName(propertyName).eq((DetachedCriteria) value); - } - return Restrictions.eq(propertyName, value); - } - }); - criterionAdaptors.put(Query.NotEquals.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.NotEquals criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - if (value instanceof DetachedCriteria) { - return Property.forName(propertyName).ne((DetachedCriteria) value); - } - return Restrictions.ne(propertyName, value); - } - }); - criterionAdaptors.put(Query.GreaterThan.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThan criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - if (value instanceof DetachedCriteria) { - return Property.forName(propertyName).gt((DetachedCriteria) value); - } - return Restrictions.gt(propertyName, value); - } - }); - criterionAdaptors.put(Query.GreaterThanEquals.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.GreaterThanEquals criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - if(value instanceof DetachedCriteria) { - return Property.forName(propertyName).ge((DetachedCriteria) value); - } - return Restrictions.ge(propertyName, value); - } - }); - criterionAdaptors.put(Query.LessThan.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThan criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - if (value instanceof DetachedCriteria) { - return Property.forName(propertyName).lt((DetachedCriteria) value); - } - return Restrictions.lt(propertyName, value); - } - }); - criterionAdaptors.put(Query.LessThanEquals.class, new CriterionAdaptor() { - @Override - public Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.LessThanEquals criterion, String alias) { - String propertyName = getPropertyName(criterion, alias); - Object value = criterion.getValue(); - if (value instanceof DetachedCriteria) { - return Property.forName(propertyName).le((DetachedCriteria) value); - } - return Restrictions.le(propertyName, value); - } - }); - } - - /** utility methods to group and clean up the initialization of the Criterion Adapters**/ - protected abstract Criterion createRlikeExpression(String propertyName, String pattern); - - - protected String getPropertyName(Query.Criterion criterion, String alias) { - return calculatePropertyName(((Query.PropertyNameCriterion) criterion).getProperty(), alias); - } - - protected String calculatePropertyName(String property, String alias) { - if (alias != null) { - return alias + '.' + property; - } - return property; - } - - protected void applySubCriteriaToJunction(PersistentEntity entity, AbstractHibernateQuery hibernateCriteria, List existing, - Junction conjunction, String alias) { - - for (Query.Criterion subCriterion : existing) { - if (subCriterion instanceof Query.PropertyCriterion) { - Query.PropertyCriterion pc = (Query.PropertyCriterion) subCriterion; - if (pc.getValue() instanceof QueryableCriteria) { - pc.setValue(toHibernateDetachedCriteria(hibernateCriteria, (QueryableCriteria) pc.getValue())); - } - else { - AbstractHibernateQuery.doTypeConversionIfNeccessary(entity, pc); - } - } - CriterionAdaptor criterionAdaptor = criterionAdaptors.get(subCriterion.getClass()); - if (criterionAdaptor != null) { - Criterion c = criterionAdaptor.toHibernateCriterion(hibernateCriteria, subCriterion, alias); - if (c != null) - conjunction.add(c); - } - else if (subCriterion instanceof FunctionCallingCriterion) { - Criterion sqlRestriction = hibernateCriteria.getRestrictionForFunctionCall((FunctionCallingCriterion) subCriterion, entity); - if (sqlRestriction != null) { - conjunction.add(sqlRestriction); - } - } - } - } - - - public org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, Query.Criterion criterion, String alias) { - final CriterionAdaptor criterionAdaptor = criterionAdaptors.get(criterion.getClass()); - if (criterionAdaptor != null) { - return criterionAdaptor.toHibernateCriterion(hibernateQuery, criterion, alias); - } - return null; - } - - - protected abstract org.hibernate.criterion.DetachedCriteria toHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria); - - protected org.hibernate.criterion.DetachedCriteria toHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria, String alias) { - return toHibernateDetachedCriteria(query, queryableCriteria); - } - - public static abstract class CriterionAdaptor { - public abstract org.hibernate.criterion.Criterion toHibernateCriterion(AbstractHibernateQuery hibernateQuery, T criterion, String alias); - - protected Object convertStringValue(Object o) { - if ((!(o instanceof String)) && (o instanceof CharSequence)) { - o = o.toString(); - } - return o; - } - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 2afb7d31e48..55f3b02f908 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -14,39 +14,37 @@ */ package org.grails.orm.hibernate.query; -import java.lang.reflect.Field; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - import jakarta.persistence.FetchType; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; - -import org.grails.datastore.mapping.core.Datastore; -import org.grails.datastore.mapping.proxy.ProxyHandler; -import org.grails.datastore.mapping.query.event.PostQueryEvent; -import org.grails.datastore.mapping.query.event.PreQueryEvent; -import org.grails.orm.hibernate.AbstractHibernateSession; -import org.grails.orm.hibernate.IHibernateTemplate; -import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; -import org.grails.orm.hibernate.cfg.Mapping; -import org.grails.orm.hibernate.proxy.HibernateProxyHandler; +import jakarta.persistence.criteria.Root; import org.grails.datastore.gorm.finders.DynamicFinder; import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; +import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.model.types.Embedded; +import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.query.AssociationQuery; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion; -import org.hibernate.*; -import org.hibernate.criterion.*; +import org.grails.datastore.mapping.query.event.PostQueryEvent; +import org.grails.datastore.mapping.query.event.PreQueryEvent; +import org.grails.orm.hibernate.AbstractHibernateSession; +import org.grails.orm.hibernate.IHibernateTemplate; +import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; +import org.grails.orm.hibernate.cfg.Mapping; +import org.hibernate.FetchMode; +import org.hibernate.LockMode; +import org.hibernate.NonUniqueResultException; +import org.hibernate.SessionFactory; import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.function.SQLFunction; import org.hibernate.persister.entity.PropertyMapping; +import org.hibernate.query.sqm.tree.SqmJoinType; import org.hibernate.type.BasicType; -import org.hibernate.type.TypeResolver; import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; @@ -54,6 +52,15 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException; import org.springframework.util.ReflectionUtils; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + /** * Bridges the Query API with the Hibernate Criteria API * @@ -67,14 +74,11 @@ public abstract class AbstractHibernateQuery extends Query { protected static final String ALIAS = "_alias"; protected static ConversionService conversionService = new DefaultConversionService(); - protected static Field opField = ReflectionUtils.findField(SimpleExpression.class, "op"); + private static final Map JOIN_STATUS_CACHE = new ConcurrentHashMap(); - static { - ReflectionUtils.makeAccessible(opField); - } + protected final Root root; - protected Criteria criteria; - protected org.hibernate.criterion.DetachedCriteria detachedCriteria; + protected CriteriaQuery criteria; protected AbstractHibernateQuery.HibernateProjectionList hibernateProjectionList; protected String alias; protected int aliasCount; @@ -84,26 +88,17 @@ public abstract class AbstractHibernateQuery extends Query { protected LinkedList associationStack = new LinkedList(); protected LinkedList aliasInstanceStack = new LinkedList(); private boolean hasJoins = false; - protected ProxyHandler proxyHandler = new HibernateProxyHandler(); - protected final AbstractHibernateCriterionAdapter abstractHibernateCriterionAdapter; - protected AbstractHibernateQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity entity) { + protected AbstractHibernateQuery(CriteriaQuery criteria, AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); this.criteria = criteria; + this.root = criteria.from(entity.getJavaClass()); if(entity != null) { initializeJoinStatus(); } - this.abstractHibernateCriterionAdapter = createHibernateCriterionAdapter(); } - protected AbstractHibernateQuery(DetachedCriteria criteria, PersistentEntity entity) { - super(null, entity); - this.detachedCriteria = criteria; - this.abstractHibernateCriterionAdapter = createHibernateCriterionAdapter(); - if(entity != null) { - initializeJoinStatus(); - } - } + @Override protected Object resolveIdIfEntity(Object value) { @@ -121,110 +116,34 @@ protected void initializeJoinStatus() { } } - protected AbstractHibernateQuery(Criteria subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { + protected AbstractHibernateQuery(CriteriaQuery subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { this(subCriteria, session, associatedEntity); alias = newAlias; } @Override public Query isEmpty(String property) { - org.hibernate.criterion.Criterion criterion = Restrictions.isEmpty(calculatePropertyName(property)); - addToCriteria(criterion); return this; } @Override public Query isNotEmpty(String property) { - addToCriteria(Restrictions.isNotEmpty(calculatePropertyName(property))); return this; } @Override public Query isNull(String property) { - addToCriteria(Restrictions.isNull(calculatePropertyName(property))); return this; } @Override public Query isNotNull(String property) { - addToCriteria(Restrictions.isNotNull(calculatePropertyName(property))); return this; } @Override public void add(Criterion criterion) { - if (criterion instanceof FunctionCallingCriterion) { - org.hibernate.criterion.Criterion sqlRestriction = getRestrictionForFunctionCall((FunctionCallingCriterion) criterion, getEntity()); - if (sqlRestriction != null) { - addToCriteria(sqlRestriction); - } - } - else if (criterion instanceof PropertyCriterion) { - PropertyCriterion pc = (PropertyCriterion) criterion; - Object value = pc.getValue(); - if (value instanceof QueryableCriteria) { - setDetachedCriteriaValue((QueryableCriteria) value, pc); - } else { - if (!(value instanceof DetachedCriteria)) { - doTypeConversionIfNeccessary(getEntity(), pc); - } - } - } - if (criterion instanceof DetachedAssociationCriteria) { - DetachedAssociationCriteria associationCriteria = (DetachedAssociationCriteria) criterion; - - Association association = associationCriteria.getAssociation(); - List criteria = associationCriteria.getCriteria(); - - if(association instanceof Embedded) { - String associationName = association.getName(); - if (getCurrentAlias() != null) { - associationName = getCurrentAlias() + '.' + associationName; - } - for (Criterion c : criteria) { - final org.hibernate.criterion.Criterion hibernateCriterion = getHibernateCriterionAdapter().toHibernateCriterion(this, c, associationName); - if (hibernateCriterion != null) { - addToCriteria(hibernateCriterion); - } - } - } - else { - - CriteriaAndAlias criteriaAndAlias = getCriteriaAndAlias(associationCriteria); - if(criteriaAndAlias.criteria != null) { - aliasInstanceStack.add(criteriaAndAlias.criteria); - } - else if(criteriaAndAlias.detachedCriteria != null) { - aliasInstanceStack.add(criteriaAndAlias.detachedCriteria); - } - aliasStack.add(criteriaAndAlias.alias); - associationStack.add(association); - entityStack.add(association.getAssociatedEntity()); - - try { - @SuppressWarnings("unchecked") - List associationCriteriaList = criteria; - for (Criterion c : associationCriteriaList) { - add(c); - } - } - finally { - aliasInstanceStack.removeLast(); - aliasStack.removeLast(); - entityStack.removeLast(); - associationStack.removeLast(); - } - } - - } - else { - - final org.hibernate.criterion.Criterion hibernateCriterion = getHibernateCriterionAdapter().toHibernateCriterion(this, criterion, getCurrentAlias()); - if (hibernateCriterion != null) { - addToCriteria(hibernateCriterion); - } - } } @@ -279,180 +198,100 @@ static void doTypeConversionIfNeccessary(PersistentEntity entity, PropertyCriter } } - org.hibernate.criterion.Criterion getRestrictionForFunctionCall(FunctionCallingCriterion criterion, PersistentEntity entity) { - org.hibernate.criterion.Criterion sqlRestriction; - - SessionFactory sessionFactory = ((IHibernateTemplate)session.getNativeInterface()).getSessionFactory(); - String property = criterion.getProperty(); - Criterion datastoreCriterion = criterion.getPropertyCriterion(); - PersistentProperty pp = entity.getPropertyByName(property); - - if (pp == null) throw new InvalidDataAccessResourceUsageException( - "Cannot execute function defined in query [" + criterion.getFunctionName() + - "] on non-existent property [" + property + "] of [" + entity.getJavaClass() + "]"); - - String functionName = criterion.getFunctionName(); - - Dialect dialect = getDialect(sessionFactory); - SQLFunction sqlFunction = dialect.getFunctions().get(functionName); - if (sqlFunction != null) { - TypeResolver typeResolver = getTypeResolver(sessionFactory); - BasicType basic = typeResolver.basic(pp.getType().getName()); - if (basic != null && datastoreCriterion instanceof PropertyCriterion) { - - PropertyCriterion pc = (PropertyCriterion) datastoreCriterion; - final org.hibernate.criterion.Criterion hibernateCriterion = getHibernateCriterionAdapter().toHibernateCriterion(this, datastoreCriterion,alias); - if (hibernateCriterion instanceof SimpleExpression) { - SimpleExpression expr = (SimpleExpression) hibernateCriterion; - Object op = ReflectionUtils.getField(opField, expr); - PropertyMapping mapping = getEntityPersister(entity.getJavaClass().getName(), sessionFactory); - String[] columns; - if (alias != null) { - columns = mapping.toColumns(alias, property); - } - else { - columns = mapping.toColumns(property); - } - String root = render(basic, Arrays.asList(columns), sessionFactory, sqlFunction); - Object value = pc.getValue(); - if (value != null) { - sqlRestriction = Restrictions.sqlRestriction(root + op + "?", value, typeResolver.basic(value.getClass().getName())); - } - else { - sqlRestriction = Restrictions.sqlRestriction(root + op + "?", value, basic); - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function ["+functionName+"] defined in query for property ["+property+"] with type ["+pp.getType()+"]"); - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function ["+functionName+"] defined in query for property ["+property+"] with type ["+pp.getType()+"]"); - } - } - else { - throw new InvalidDataAccessResourceUsageException("Unsupported function defined in query ["+functionName+"]"); - } - return sqlRestriction; - } - protected abstract String render(BasicType basic, List asList, SessionFactory sessionFactory, SQLFunction sqlFunction); + protected abstract PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory); - protected abstract TypeResolver getTypeResolver(SessionFactory sessionFactory); - protected abstract Dialect getDialect(SessionFactory sessionFactory); @Override public Junction disjunction() { - final org.hibernate.criterion.Disjunction disjunction = Restrictions.disjunction(); - addToCriteria(disjunction); - return new HibernateJunction(disjunction, alias); + return null; } @Override public Junction negation() { - final org.hibernate.criterion.Disjunction disjunction = Restrictions.disjunction(); - addToCriteria(Restrictions.not(disjunction)); - return new HibernateJunction(disjunction, alias); + return null; } @Override public Query eq(String property, Object value) { - addToCriteria(Restrictions.eq(calculatePropertyName(property), value)); return this; } @Override public Query idEq(Object value) { - addToCriteria(Restrictions.idEq(value)); return this; } @Override public Query gt(String property, Object value) { - addToCriteria(Restrictions.gt(calculatePropertyName(property), value)); return this; } @Override public Query and(Criterion a, Criterion b) { - AbstractHibernateCriterionAdapter adapter = getHibernateCriterionAdapter(); - addToCriteria(Restrictions.and(adapter.toHibernateCriterion(this, a, alias), adapter.toHibernateCriterion(this, a, alias))); return this; } @Override public Query or(Criterion a, Criterion b) { - AbstractHibernateCriterionAdapter adapter = getHibernateCriterionAdapter(); - addToCriteria(Restrictions.or(adapter.toHibernateCriterion(this, a, alias), adapter.toHibernateCriterion(this, b, alias))); - return this; + return this; } @Override public Query allEq(Map values) { - addToCriteria(Restrictions.allEq(values)); return this; } @Override public Query ge(String property, Object value) { - addToCriteria(Restrictions.ge(calculatePropertyName(property), value)); return this; } @Override public Query le(String property, Object value) { - addToCriteria(Restrictions.le(calculatePropertyName(property), value)); return this; } @Override public Query gte(String property, Object value) { - addToCriteria(Restrictions.ge(calculatePropertyName(property), value)); return this; } @Override public Query lte(String property, Object value) { - addToCriteria(Restrictions.le(calculatePropertyName(property), value)); return this; } @Override public Query lt(String property, Object value) { - addToCriteria(Restrictions.lt(calculatePropertyName(property), value)); return this; } @Override public Query in(String property, List values) { - addToCriteria(Restrictions.in(calculatePropertyName(property), values)); return this; } @Override public Query between(String property, Object start, Object end) { - addToCriteria(Restrictions.between(calculatePropertyName(property), start, end)); return this; } @Override public Query like(String property, String expr) { - addToCriteria(Restrictions.like(calculatePropertyName(property), calculatePropertyName(expr))); return this; } @Override public Query ilike(String property, String expr) { - addToCriteria(Restrictions.ilike(calculatePropertyName(property), calculatePropertyName(expr))); return this; } @Override public Query rlike(String property, String expr) { - addToCriteria(createRlikeExpression(calculatePropertyName(property), calculatePropertyName(expr))); return this; } @@ -467,9 +306,6 @@ public AssociationQuery createQuery(String associationName) { if(subCriteria.criteria != null) { return new HibernateAssociationQuery(subCriteria.criteria, (AbstractHibernateSession) getSession(), association.getAssociatedEntity(), association, alias); } - else if(subCriteria.detachedCriteria != null) { - return new HibernateAssociationQuery(subCriteria.detachedCriteria, (AbstractHibernateSession) getSession(), association.getAssociatedEntity(), association, alias); - } } throw new InvalidDataAccessApiUsageException("Cannot query association [" + calculatePropertyName(associationName) + "] of entity [" + entity + "]. Property is not an association!"); } @@ -487,7 +323,7 @@ protected CriteriaAndAlias getCriteriaAndAlias(DetachedAssociationCriteria assoc protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias) { CriteriaAndAlias subCriteria = null; String associationPath = getAssociationPath(associationName); - Criteria parentCriteria = criteria; + CriteriaQuery parentCriteria = criteria; if(alias == null) { alias = generateAlias(associationName); } @@ -508,12 +344,8 @@ protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias else { JoinType joinType = joinTypes.get(associationName); if(parentCriteria != null) { - Criteria sc = parentCriteria.createAlias(associationPath, alias, resolveJoinType(joinType)); - subCriteria = new CriteriaAndAlias(sc, alias, associationPath); - } - else if(detachedCriteria != null) { - DetachedCriteria sc = detachedCriteria.createAlias(associationPath, alias, resolveJoinType(joinType)); - subCriteria = new CriteriaAndAlias(sc, alias, associationPath); +// Criteria sc = parentCriteria.createAlias(associationPath, alias, resolveJoinType(joinType)); +// subCriteria = new CriteriaAndAlias(sc, alias, associationPath); } if(subCriteria != null) { @@ -524,17 +356,17 @@ else if(detachedCriteria != null) { return subCriteria; } - private org.hibernate.sql.JoinType resolveJoinType(JoinType joinType) { + private SqmJoinType resolveJoinType(JoinType joinType) { if(joinType == null) { - return org.hibernate.sql.JoinType.INNER_JOIN; + return SqmJoinType.INNER; } switch (joinType) { case LEFT: - return org.hibernate.sql.JoinType.LEFT_OUTER_JOIN; + return SqmJoinType.LEFT; case RIGHT: - return org.hibernate.sql.JoinType.RIGHT_OUTER_JOIN; + return SqmJoinType.RIGHT; default: - return org.hibernate.sql.JoinType.INNER_JOIN; + return SqmJoinType.INNER; } } @@ -548,22 +380,16 @@ public ProjectionList projections() { @Override public Query max(int max) { - if(criteria != null) - criteria.setMaxResults(max); return this; } @Override public Query maxResults(int max) { - if(criteria != null) - criteria.setMaxResults(max); return this; } @Override public Query offset(int offset) { - if(criteria != null) - criteria.setFirstResult(offset); return this; } @@ -575,15 +401,11 @@ public Query firstResult(int offset) { @Override public Query cache(boolean cache) { - criteria.setCacheable(cache); - return super.cache(cache); } @Override public Query lock(boolean lock) { - criteria.setCacheable(false); - criteria.setLockMode(LockMode.PESSIMISTIC_WRITE); return super.lock(lock); } @@ -591,175 +413,35 @@ public Query lock(boolean lock) { public Query order(Order order) { super.order(order); - String property = order.getProperty(); - - int i = property.indexOf('.'); - if(i > -1) { - - String sortHead = property.substring(0,i); - String sortTail = property.substring(i + 1); - - if(createdAssociationPaths.containsKey(sortHead)) { - CriteriaAndAlias criteriaAndAlias = createdAssociationPaths.get(sortHead); - Criteria criteria = criteriaAndAlias.criteria; - org.hibernate.criterion.Order hibernateOrder = order.getDirection() == Order.Direction.ASC ? - org.hibernate.criterion.Order.asc(property) : - org.hibernate.criterion.Order.desc(property); - - criteria.addOrder(order.isIgnoreCase() ? hibernateOrder.ignoreCase() : hibernateOrder); - } - else { - - PersistentProperty persistentProperty = entity.getPropertyByName(sortHead); - - if(persistentProperty instanceof Association) { - Association a = (Association) persistentProperty; - if(persistentProperty instanceof Embedded) { - addSimpleOrder(order, property); - } - else { - if(criteria != null) { - Criteria subCriteria = criteria.createCriteria(sortHead); - addOrderToCriteria(subCriteria, sortTail, order); - } - else if(detachedCriteria != null) { - DetachedCriteria subDetachedCriteria = detachedCriteria.createCriteria(sortHead); - addOrderToDetachedCriteria(subDetachedCriteria, sortTail, order); - } - } - } - } - - } - else { - addSimpleOrder(order, property); - } return this; } - private void addSimpleOrder(Order order, String property) { - Criteria c = criteria; - if(c != null) { - addOrderToCriteria(c, property, order); - }else { - DetachedCriteria dc = detachedCriteria; - addOrderToDetachedCriteria(dc, property, order); - } - } - private void addOrderToDetachedCriteria(DetachedCriteria dc, String property, Order order) { - if(dc != null) { - org.hibernate.criterion.Order hibernateOrder = order.getDirection() == Order.Direction.ASC ? - org.hibernate.criterion.Order.asc(calculatePropertyName(property)) : - org.hibernate.criterion.Order.desc(calculatePropertyName(property)); - dc.addOrder(order.isIgnoreCase() ? hibernateOrder.ignoreCase() : hibernateOrder); - - } - } - private void addOrderToCriteria(Criteria c, String property, Order order) { - org.hibernate.criterion.Order hibernateOrder = order.getDirection() == Order.Direction.ASC ? - org.hibernate.criterion.Order.asc(calculatePropertyName(property)) : - org.hibernate.criterion.Order.desc(calculatePropertyName(property)); - c.addOrder(order.isIgnoreCase() ? hibernateOrder.ignoreCase() : hibernateOrder); - } @Override public Query join(String property) { this.hasJoins = true; - if(criteria != null) - criteria.setFetchMode(property, FetchMode.JOIN); - else if(detachedCriteria != null) - detachedCriteria.setFetchMode(property, FetchMode.JOIN); + root.join(property); return this; } @Override public Query select(String property) { this.hasJoins = true; - if(criteria != null) - criteria.setFetchMode(property, FetchMode.SELECT); - else if(detachedCriteria != null) - detachedCriteria.setFetchMode(property, FetchMode.SELECT); + this.criteria.select(root.get(property)); return this; } @Override public List list() { - if(criteria == null) throw new IllegalStateException("Cannot execute query using a detached criteria instance"); - - int projectionLength = 0; - if (hibernateProjectionList != null) { - org.hibernate.criterion.ProjectionList projectionList = hibernateProjectionList.getHibernateProjectionList(); - projectionLength = projectionList.getLength(); - if(projectionLength > 0) { - criteria.setProjection(projectionList); - } - } - - if (projectionLength < 2) { - criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); - } - - applyDefaultSortOrderAndCaching(); - applyFetchStrategies(); - - return listForCriteria(); + return getQuery().getResultList(); } - public List listForCriteria() { - Datastore datastore = session.getDatastore(); - ApplicationEventPublisher publisher = datastore.getApplicationEventPublisher(); - if(publisher != null) { - publisher.publishEvent(new PreQueryEvent(datastore, this)); - } - List results = criteria.list(); - if(publisher != null) { - publisher.publishEvent(new PostQueryEvent(datastore, this, results)); - } - return results; - } - - protected void applyDefaultSortOrderAndCaching() { - if(this.orderBy.isEmpty() && entity != null) { - // don't apply default sorting, if projections present - if(hibernateProjectionList != null && !hibernateProjectionList.isEmpty()) return; - - Mapping mapping = AbstractGrailsDomainBinder.getMapping(entity.getJavaClass()); - if(mapping != null) { - if(queryCache == null && mapping.getCache() != null && mapping.getCache().isEnabled()) { - criteria.setCacheable(true); - } - - Map sortMap = mapping.getSort().getNamesAndDirections(); - DynamicFinder.applySortForMap(this, sortMap, true); - - } - } - } - - protected void applyFetchStrategies() { - for (Map.Entry entry : fetchStrategies.entrySet()) { - switch(entry.getValue()) { - case EAGER: - if(criteria != null) - criteria.setFetchMode(entry.getKey(), FetchMode.JOIN); - else if(detachedCriteria != null) - detachedCriteria.setFetchMode(entry.getKey(), FetchMode.JOIN); - break; - case LAZY: - if(criteria != null) - criteria.setFetchMode(entry.getKey(), FetchMode.SELECT); - else if(detachedCriteria != null) - detachedCriteria.setFetchMode(entry.getKey(), FetchMode.SELECT); - break; - } - } - } @Override protected void flushBeforeQuery() { @@ -768,48 +450,11 @@ protected void flushBeforeQuery() { @Override public Object singleResult() { - if(criteria == null) throw new IllegalStateException("Cannot execute query using a detached criteria instance"); - - if (hibernateProjectionList != null) { - criteria.setProjection(hibernateProjectionList.getHibernateProjectionList()); - } - criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); - applyDefaultSortOrderAndCaching(); - applyFetchStrategies(); - - Datastore datastore = session.getDatastore(); - ApplicationEventPublisher publisher = datastore.getApplicationEventPublisher(); - if(publisher != null) { - publisher.publishEvent(new PreQueryEvent(datastore, this)); - } - - Object result; - if(hasJoins) { - try { - result = proxyHandler.unwrap(criteria.uniqueResult());; - } catch (NonUniqueResultException e) { - result = singleResultViaListCall(); - } - } - else { - result = singleResultViaListCall(); - } - if(publisher != null) { - publisher.publishEvent(new PostQueryEvent(datastore, this, Collections.singletonList(result))); - } - return result; + return getQuery().getSingleResult(); } - private Object singleResultViaListCall() { - criteria.setMaxResults(1); - if(hibernateProjectionList != null && hibernateProjectionList.isRowCount()) { - criteria.setFirstResult(0); - } - List results = criteria.list(); - if(results.size()>0) { - return proxyHandler.unwrap(results.get(0)); - } - return null; + private org.hibernate.query.Query getQuery() { + return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory().getCurrentSession().createQuery(criteria); } @@ -818,44 +463,8 @@ protected List executeQuery(PersistentEntity entity, Junction criteria) { return list(); } - String handleAssociationQuery(Association association, List criteriaList) { - return getCriteriaAndAlias(association).alias; - } - - String handleAssociationQuery(Association association, List criteriaList, String alias) { - String associationName = calculatePropertyName(association.getName()); - return getOrCreateAlias(associationName, alias).alias; - } - - protected CriteriaAndAlias getCriteriaAndAlias(Association association) { - String associationName = calculatePropertyName(association.getName()); - String newAlias = generateAlias(associationName); - return getOrCreateAlias(associationName, newAlias); - } - - protected void addToCriteria(org.hibernate.criterion.Criterion criterion) { - if (criterion == null) { - return; - } - if (aliasInstanceStack.isEmpty()) { - if(criteria != null) { - criteria.add(criterion); - } - else if(detachedCriteria != null) { - detachedCriteria.add(criterion); - } - } - else { - Object criteriaObject = aliasInstanceStack.getLast(); - if(criteriaObject instanceof Criteria) - ((Criteria)criteriaObject).add(criterion); - else if(criteriaObject instanceof DetachedCriteria) { - ((DetachedCriteria)criteriaObject).add(criterion); - } - } - } protected String calculatePropertyName(String property) { if (alias == null) { @@ -868,140 +477,84 @@ protected String generateAlias(String associationName) { return calculatePropertyName(associationName) + calculatePropertyName(ALIAS) + aliasCount++; } - protected abstract void setDetachedCriteriaValue(QueryableCriteria value, PropertyCriterion pc); - protected AbstractHibernateCriterionAdapter getHibernateCriterionAdapter() { - return this.abstractHibernateCriterionAdapter; - } - protected abstract AbstractHibernateCriterionAdapter createHibernateCriterionAdapter(); - protected abstract org.hibernate.criterion.Criterion createRlikeExpression(String propertyName, String value); - protected class HibernateJunction extends Junction { - - protected org.hibernate.criterion.Junction hibernateJunction; - protected String alias; - - public HibernateJunction(org.hibernate.criterion.Junction junction, String alias) { - hibernateJunction = junction; - this.alias = alias; - } - - @Override - public Junction add(Criterion c) { - if (c != null) { - if (c instanceof FunctionCallingCriterion) { - org.hibernate.criterion.Criterion sqlRestriction = getRestrictionForFunctionCall((FunctionCallingCriterion) c, entity); - if (sqlRestriction != null) { - hibernateJunction.add(sqlRestriction); - } - } - else { - AbstractHibernateCriterionAdapter adapter = getHibernateCriterionAdapter(); - org.hibernate.criterion.Criterion criterion = adapter.toHibernateCriterion(AbstractHibernateQuery.this, c, alias); - if (criterion != null) { - hibernateJunction.add(criterion); - } - } - } - return this; - } - } protected class HibernateProjectionList extends ProjectionList { - org.hibernate.criterion.ProjectionList projectionList = Projections.projectionList(); private boolean rowCount = false; public boolean isRowCount() { return rowCount; } - public org.hibernate.criterion.ProjectionList getHibernateProjectionList() { - return projectionList; - } - @Override public boolean isEmpty() { - return projectionList.getLength() == 0; + return true; } @Override public ProjectionList add(Projection p) { - projectionList.add(new HibernateProjectionAdapter(p).toHibernateProjection()); return this; } @Override public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String property) { - projectionList.add(Projections.countDistinct(calculatePropertyName(property))); return this; } @Override public org.grails.datastore.mapping.query.api.ProjectionList distinct(String property) { - projectionList.add(Projections.distinct(Projections.property(calculatePropertyName(property)))); return this; } @Override public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { - projectionList.add(Projections.rowCount()); this.rowCount = true; return this; } @Override public ProjectionList id() { - projectionList.add(Projections.id()); return this; } @Override public ProjectionList count() { - projectionList.add(Projections.rowCount()); this.rowCount = true; return this; } @Override public ProjectionList property(String name) { - projectionList.add(Projections.property(calculatePropertyName(name))); return this; } @Override public ProjectionList sum(String name) { - projectionList.add(Projections.sum(calculatePropertyName(name))); return this; } @Override public ProjectionList min(String name) { - projectionList.add(Projections.min(calculatePropertyName(name))); return this; } @Override public ProjectionList max(String name) { - projectionList.add(Projections.max(calculatePropertyName(name))); return this; } @Override public ProjectionList avg(String name) { - projectionList.add(Projections.avg(calculatePropertyName(name))); return this; } @Override public ProjectionList distinct() { - if(criteria != null) - criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); - else if(detachedCriteria != null) - detachedCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); return this; } } @@ -1009,206 +562,145 @@ else if(detachedCriteria != null) protected class HibernateAssociationQuery extends AssociationQuery { protected String alias; - protected org.hibernate.criterion.Junction hibernateJunction; - protected Criteria assocationCriteria; - protected DetachedCriteria detachedAssocationCriteria; + protected CriteriaQuery assocationCriteria; - public HibernateAssociationQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity associatedEntity, Association association, String alias) { + public HibernateAssociationQuery(CriteriaQuery criteria, AbstractHibernateSession session, PersistentEntity associatedEntity, Association association, String alias) { super(session, associatedEntity, association); this.alias = alias; assocationCriteria = criteria; } - public HibernateAssociationQuery(DetachedCriteria criteria, AbstractHibernateSession session, PersistentEntity associatedEntity, Association association, String alias) { - super(session, associatedEntity, association); - this.alias = alias; - detachedAssocationCriteria = criteria; - } + @Override public Query order(Order order) { - - Order.Direction direction = order.getDirection(); - switch(direction) { - case ASC: - assocationCriteria.addOrder(org.hibernate.criterion.Order.asc(order.getProperty())); - case DESC: - assocationCriteria.addOrder(org.hibernate.criterion.Order.desc(order.getProperty())); - } - return super.order(order); + return this; } @Override public Query isEmpty(String property) { - org.hibernate.criterion.Criterion criterion = Restrictions.isEmpty(calculatePropertyName(property)); - addToCriteria(criterion); return this; } - protected void addToCriteria(org.hibernate.criterion.Criterion criterion) { - if (hibernateJunction != null) { - hibernateJunction.add(criterion); - } - else if(assocationCriteria != null) { - assocationCriteria.add(criterion); - } - else if(detachedAssocationCriteria != null) { - detachedAssocationCriteria.add(criterion); - } - } @Override public Query isNotEmpty(String property) { - addToCriteria(Restrictions.isNotEmpty(calculatePropertyName(property))); return this; } @Override public Query isNull(String property) { - addToCriteria(Restrictions.isNull(calculatePropertyName(property))); return this; } @Override public Query isNotNull(String property) { - addToCriteria(Restrictions.isNotNull(calculatePropertyName(property))); return this; } @Override public void add(Criterion criterion) { - final org.hibernate.criterion.Criterion hibernateCriterion = getHibernateCriterionAdapter().toHibernateCriterion(AbstractHibernateQuery.this, criterion, alias); - if (hibernateCriterion != null) { - addToCriteria(hibernateCriterion); - } + } @Override public Junction disjunction() { - final org.hibernate.criterion.Disjunction disjunction = Restrictions.disjunction(); - addToCriteria(disjunction); - return new HibernateJunction(disjunction, alias); + return null; } @Override public Junction negation() { - final org.hibernate.criterion.Disjunction disjunction = Restrictions.disjunction(); - addToCriteria(Restrictions.not(disjunction)); - return new HibernateJunction(disjunction, alias); + return null; } @Override public Query eq(String property, Object value) { - addToCriteria(Restrictions.eq(calculatePropertyName(property), value)); return this; } @Override public Query idEq(Object value) { - addToCriteria(Restrictions.idEq(value)); return this; } @Override public Query gt(String property, Object value) { - addToCriteria(Restrictions.gt(calculatePropertyName(property), value)); return this; } @Override public Query and(Criterion a, Criterion b) { - AbstractHibernateCriterionAdapter adapter = getHibernateCriterionAdapter(); - addToCriteria(Restrictions.and(adapter.toHibernateCriterion(AbstractHibernateQuery.this, a, alias), adapter.toHibernateCriterion(AbstractHibernateQuery.this, b, alias))); - return this; + return this; } @Override public Query or(Criterion a, Criterion b) { - AbstractHibernateCriterionAdapter adapter = getHibernateCriterionAdapter(); - addToCriteria(Restrictions.or(adapter.toHibernateCriterion(AbstractHibernateQuery.this, a, alias), adapter.toHibernateCriterion(AbstractHibernateQuery.this, b, alias))); return this; } @Override public Query allEq(Map values) { - addToCriteria(Restrictions.allEq(values)); return this; } @Override public Query ge(String property, Object value) { - addToCriteria(Restrictions.ge(calculatePropertyName(property), value)); return this; } @Override public Query le(String property, Object value) { - addToCriteria(Restrictions.le(calculatePropertyName(property), value)); return this; } @Override public Query gte(String property, Object value) { - addToCriteria(Restrictions.ge(calculatePropertyName(property), value)); return this; } @Override public Query lte(String property, Object value) { - addToCriteria(Restrictions.le(calculatePropertyName(property), value)); return this; } @Override public Query lt(String property, Object value) { - addToCriteria(Restrictions.lt(calculatePropertyName(property), value)); return this; } @Override public Query in(String property, List values) { - addToCriteria(Restrictions.in(calculatePropertyName(property), values)); return this; } @Override public Query between(String property, Object start, Object end) { - addToCriteria(Restrictions.between(calculatePropertyName(property), start, end)); return this; } @Override public Query like(String property, String expr) { - addToCriteria(Restrictions.like(calculatePropertyName(property), calculatePropertyName(expr))); return this; } @Override public Query ilike(String property, String expr) { - addToCriteria(Restrictions.ilike(calculatePropertyName(property), calculatePropertyName(expr))); return this; } @Override public Query rlike(String property, String expr) { - addToCriteria(createRlikeExpression(calculatePropertyName(property), calculatePropertyName(expr))); return this; } } protected class CriteriaAndAlias { - protected DetachedCriteria detachedCriteria; - protected Criteria criteria; + protected CriteriaQuery criteria; protected String alias; protected String associationPath; - public CriteriaAndAlias(DetachedCriteria detachedCriteria, String alias, String associationPath) { - this.detachedCriteria = detachedCriteria; - this.alias = alias; - this.associationPath = associationPath; - } - public CriteriaAndAlias(Criteria criteria, String alias, String associationPath) { + public CriteriaAndAlias(CriteriaQuery criteria, String alias, String associationPath) { this.criteria = criteria; this.alias = alias; this.associationPath = associationPath; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java index 3428b9dc774..be56a839fb0 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/GrailsHibernateQueryUtils.java @@ -9,11 +9,9 @@ import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.model.types.Embedded; -import org.hibernate.Criteria; import org.hibernate.FetchMode; import org.hibernate.FlushMode; import org.hibernate.LockMode; -import org.hibernate.criterion.Order; import org.hibernate.query.Query; import org.springframework.core.convert.ConversionService; import org.springframework.util.ReflectionUtils; @@ -32,94 +30,7 @@ */ public class GrailsHibernateQueryUtils { - /** - * Populates criteria arguments for the given target class and arguments map - * - * @param entity The {@link org.grails.datastore.mapping.model.PersistentEntity} instance - * @param c The criteria instance - * @param argMap The arguments map - */ - @SuppressWarnings("rawtypes") - @Deprecated - public static void populateArgumentsForCriteria(PersistentEntity entity, Criteria c, Map argMap, ConversionService conversionService, boolean useDefaultMapping) { - Integer maxParam = null; - Integer offsetParam = null; - if (argMap.containsKey(DynamicFinder.ARGUMENT_MAX)) { - maxParam = conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_MAX), Integer.class); - } - if (argMap.containsKey(DynamicFinder.ARGUMENT_OFFSET)) { - offsetParam = conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_OFFSET), Integer.class); - } - if (argMap.containsKey(DynamicFinder.ARGUMENT_FETCH_SIZE)) { - c.setFetchSize(conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_FETCH_SIZE), Integer.class)); - } - if (argMap.containsKey(DynamicFinder.ARGUMENT_TIMEOUT)) { - c.setTimeout(conversionService.convert(argMap.get(DynamicFinder.ARGUMENT_TIMEOUT), Integer.class)); - } - if (argMap.containsKey(DynamicFinder.ARGUMENT_FLUSH_MODE)) { - c.setFlushMode(convertFlushMode(argMap.get(DynamicFinder.ARGUMENT_FLUSH_MODE))); - } - if (argMap.containsKey(DynamicFinder.ARGUMENT_READ_ONLY)) { - c.setReadOnly(ClassUtils.getBooleanFromMap(DynamicFinder.ARGUMENT_READ_ONLY, argMap)); - } - String orderParam = (String) argMap.get(DynamicFinder.ARGUMENT_ORDER); - Object fetchObj = argMap.get(DynamicFinder.ARGUMENT_FETCH); - if (fetchObj instanceof Map) { - Map fetch = (Map) fetchObj; - for (Object o : fetch.keySet()) { - String associationName = (String) o; - c.setFetchMode(associationName, getFetchMode(fetch.get(associationName))); - } - } - final int max = maxParam == null ? -1 : maxParam; - final int offset = offsetParam == null ? -1 : offsetParam; - if (max > -1) { - c.setMaxResults(max); - } - if (offset > -1) { - c.setFirstResult(offset); - } - if (ClassUtils.getBooleanFromMap(DynamicFinder.ARGUMENT_LOCK, argMap)) { - c.setLockMode(LockMode.PESSIMISTIC_WRITE); - c.setCacheable(false); - } else { - if (argMap.containsKey(DynamicFinder.ARGUMENT_CACHE)) { - c.setCacheable(ClassUtils.getBooleanFromMap(DynamicFinder.ARGUMENT_CACHE, argMap)); - } else { - cacheCriteriaByMapping(entity.getJavaClass(), c); - } - } - - final Object sortObj = argMap.get(DynamicFinder.ARGUMENT_SORT); - if (sortObj != null) { - boolean ignoreCase = true; - Object caseArg = argMap.get(DynamicFinder.ARGUMENT_IGNORE_CASE); - if (caseArg instanceof Boolean) { - ignoreCase = (Boolean) caseArg; - } - if (sortObj instanceof Map) { - Map sortMap = (Map) sortObj; - for (Object sort : sortMap.keySet()) { - final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; - addOrderPossiblyNested(c, entity, (String) sort, order, ignoreCase); - } - } else { - final String sort = (String) sortObj; - final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase(orderParam) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; - addOrderPossiblyNested(c, entity, sort, order, ignoreCase); - } - } else if (useDefaultMapping) { - Mapping m = AbstractGrailsDomainBinder.getMapping(entity.getJavaClass()); - if (m != null) { - Map sortMap = m.getSort().getNamesAndDirections(); - for (Object sort : sortMap.keySet()) { - final String order = DynamicFinder.ORDER_DESC.equalsIgnoreCase((String) sortMap.get(sort)) ? DynamicFinder.ORDER_DESC : DynamicFinder.ORDER_ASC; - addOrderPossiblyNested(c, entity, (String) sort, order, true); - } - } - } - } /** * Populates criteria arguments for the given target class and arguments map @@ -237,30 +148,7 @@ public static void populateArgumentsForCriteria( } - /** - * Add order to criteria, creating necessary subCriteria if nested sort property (ie. sort:'nested.property'). - */ - private static void addOrderPossiblyNested(Criteria c, PersistentEntity entity, String sort, String order, boolean ignoreCase) { - int firstDotPos = sort.indexOf("."); - if (firstDotPos == -1) { - addOrder(c, sort, order, ignoreCase); - } else { // nested property - String sortHead = sort.substring(0, firstDotPos); - String sortTail = sort.substring(firstDotPos + 1); - PersistentProperty property = entity.getPropertyByName(sortHead); - if (property instanceof Embedded) { - // embedded objects cannot reference entities (at time of writing), so no more recursion needed - addOrder(c, sort, order, ignoreCase); - } else if (property instanceof Association) { - Association a = (Association) property; - Criteria subCriteria = c.createCriteria(sortHead); - PersistentEntity associatedEntity = a.getAssociatedEntity(); - Class propertyTargetClass = associatedEntity.getJavaClass(); - cacheCriteriaByMapping(propertyTargetClass, subCriteria); - addOrderPossiblyNested(subCriteria, associatedEntity, sortTail, order, ignoreCase); // Recurse on nested sort - } - } - } + /** @@ -337,18 +225,6 @@ private static void addOrder(PersistentEntity entity, } } - /** - * Configures the criteria instance to cache based on the configured mapping. - * - * @param targetClass The target class - * @param criteria The criteria - */ - private static void cacheCriteriaByMapping(Class targetClass, Criteria criteria) { - Mapping m = AbstractGrailsDomainBinder.getMapping(targetClass); - if (m != null && m.getCache() != null && m.getCache().getEnabled()) { - criteria.setCacheable(true); - } - } /** * Configures the criteria instance to cache based on the configured mapping. @@ -377,17 +253,6 @@ private static FlushMode convertFlushMode(Object object) { } } - /** - * Add order directly to criteria. - */ - private static void addOrder(Criteria c, String sort, String order, boolean ignoreCase) { - if (DynamicFinder.ORDER_DESC.equals(order)) { - c.addOrder(ignoreCase ? Order.desc(sort).ignoreCase() : Order.desc(sort)); - } else { - c.addOrder(ignoreCase ? Order.asc(sort).ignoreCase() : Order.asc(sort)); - } - } - /** * Retrieves the fetch mode for the specified instance; otherwise returns the default FetchMode. * diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateCriterionAdapter.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateCriterionAdapter.java deleted file mode 100644 index 1108578d9d0..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateCriterionAdapter.java +++ /dev/null @@ -1,48 +0,0 @@ -/* Copyright (C) 2011 SpringSource - * - * 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 org.grails.orm.hibernate.query; - -import grails.orm.HibernateCriteriaBuilder; -import grails.orm.RlikeExpression; - -import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.criterion.Criterion; -import org.hibernate.criterion.DetachedCriteria; - -/** - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateCriterionAdapter extends AbstractHibernateCriterionAdapter { - - protected Criterion createRlikeExpression(String propertyName, String pattern) { - return new RlikeExpression(propertyName, pattern); - } - - @Override - protected DetachedCriteria toHibernateDetachedCriteria(AbstractHibernateQuery hibernateQuery, QueryableCriteria queryableCriteria) { - return HibernateCriteriaBuilder.getHibernateDetachedCriteria(hibernateQuery, queryableCriteria); - } - - @Override - protected DetachedCriteria toHibernateDetachedCriteria(AbstractHibernateQuery hibernateQuery, QueryableCriteria queryableCriteria, String alias) { - if (alias == null) { - return toHibernateDetachedCriteria(hibernateQuery, queryableCriteria); - } - return HibernateCriteriaBuilder.getHibernateDetachedCriteria(hibernateQuery, queryableCriteria, alias); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateProjectionAdapter.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateProjectionAdapter.java deleted file mode 100644 index 625ab5d9962..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateProjectionAdapter.java +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2011 SpringSource - * - * 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 org.grails.orm.hibernate.query; - -import java.util.HashMap; -import java.util.Map; - -import org.grails.datastore.mapping.query.Query; -import org.hibernate.criterion.Projection; -import org.hibernate.criterion.Projections; - -/** - * Adapts Grails datastore API to Hibernate projections. - * - * @author Graeme Rocher - * @since 2.0 - */ -public class HibernateProjectionAdapter { - private Query.Projection projection; - private static Map, ProjectionAdapter> adapterMap = new HashMap<>(); - - static { - adapterMap.put(Query.AvgProjection.class, gormProjection -> { - Query.AvgProjection avg = (Query.AvgProjection) gormProjection; - return Projections.avg(avg.getPropertyName()); - }); - adapterMap.put(Query.IdProjection.class, gormProjection -> Projections.id()); - adapterMap.put(Query.SumProjection.class, gormProjection -> { - Query.SumProjection avg = (Query.SumProjection) gormProjection; - return Projections.sum(avg.getPropertyName()); - }); - adapterMap.put(Query.DistinctPropertyProjection.class, gormProjection -> { - Query.DistinctPropertyProjection avg = (Query.DistinctPropertyProjection) gormProjection; - return Projections.distinct(Projections.property(avg.getPropertyName())); - }); - adapterMap.put(Query.PropertyProjection.class, gormProjection -> { - Query.PropertyProjection avg = (Query.PropertyProjection) gormProjection; - return Projections.property(avg.getPropertyName()); - }); - adapterMap.put(Query.CountProjection.class, gormProjection -> Projections.rowCount()); - adapterMap.put(Query.CountDistinctProjection.class, gormProjection -> { - Query.CountDistinctProjection cd = (Query.CountDistinctProjection) gormProjection; - return Projections.countDistinct(cd.getPropertyName()); - }); - adapterMap.put(Query.GroupPropertyProjection.class, gormProjection -> { - Query.GroupPropertyProjection cd = (Query.GroupPropertyProjection) gormProjection; - return Projections.groupProperty(cd.getPropertyName()); - }); - adapterMap.put(Query.MaxProjection.class, gormProjection -> { - Query.MaxProjection cd = (Query.MaxProjection) gormProjection; - return Projections.max(cd.getPropertyName()); - }); - adapterMap.put(Query.MinProjection.class, gormProjection -> { - Query.MinProjection cd = (Query.MinProjection) gormProjection; - return Projections.min(cd.getPropertyName()); - }); - } - - public HibernateProjectionAdapter(Query.Projection projection) { - this.projection = projection; - } - - public Projection toHibernateProjection() { - ProjectionAdapter projectionAdapter = adapterMap.get(projection.getClass()); - if(projectionAdapter == null) throw new UnsupportedOperationException("Unsupported projection used: " + projection.getClass().getName()); - return projectionAdapter.toHibernateProjection(projection); - } - - private interface ProjectionAdapter { - Projection toHibernateProjection(Query.Projection gormProjection); - } -} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index 3b23e1b049e..c0aba0952cd 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -15,30 +15,16 @@ */ package org.grails.orm.hibernate.query; -import grails.orm.HibernateCriteriaBuilder; -import grails.orm.RlikeExpression; -import java.sql.SQLException; -import java.util.Iterator; -import java.util.List; +import jakarta.persistence.criteria.CriteriaQuery; import org.grails.orm.hibernate.AbstractHibernateSession; -import org.grails.orm.hibernate.GrailsHibernateTemplate; -import org.grails.orm.hibernate.HibernateSession; + import org.grails.datastore.mapping.model.PersistentEntity; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.hibernate.Criteria; -import org.hibernate.HibernateException; -import org.hibernate.Session; import org.hibernate.SessionFactory; -import org.hibernate.criterion.DetachedCriteria; -import org.hibernate.dialect.Dialect; -import org.hibernate.dialect.function.SQLFunction; import org.hibernate.engine.spi.SessionFactoryImplementor; -import org.hibernate.internal.CriteriaImpl; +import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.persister.entity.PropertyMapping; -import org.hibernate.type.BasicType; -import org.hibernate.type.TypeResolver; /** * Bridges the Query API with the Hibernate Criteria API @@ -49,82 +35,30 @@ @SuppressWarnings("rawtypes") public class HibernateQuery extends AbstractHibernateQuery { - public static final HibernateCriterionAdapter HIBERNATE_CRITERION_ADAPTER = new HibernateCriterionAdapter(); - public HibernateQuery(Criteria criteria, AbstractHibernateSession session, PersistentEntity entity) { + public HibernateQuery(CriteriaQuery criteria, AbstractHibernateSession session, PersistentEntity entity) { super(criteria, session, entity); } - public HibernateQuery(Criteria criteria, PersistentEntity entity) { + public HibernateQuery(CriteriaQuery criteria, PersistentEntity entity) { super(criteria, null, entity); } - public HibernateQuery(Criteria subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { + public HibernateQuery(CriteriaQuery subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { super(subCriteria, session, associatedEntity, newAlias); } - public HibernateQuery(DetachedCriteria criteria, PersistentEntity entity) { - super(criteria, entity); + protected PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory) { + return (PropertyMapping) ((SharedSessionContractImplementor) sessionFactory).getEntityPersister(name,this.entity); } /** * @return The hibernate criteria */ - public Criteria getHibernateCriteria() { + public CriteriaQuery getHibernateCriteria() { return this.criteria; } - @Override - protected AbstractHibernateCriterionAdapter createHibernateCriterionAdapter() { - return HIBERNATE_CRITERION_ADAPTER; - } - protected org.hibernate.criterion.Criterion createRlikeExpression(String propertyName, String value) { - return new RlikeExpression(propertyName, value); - } - protected void setDetachedCriteriaValue(QueryableCriteria value, PropertyCriterion pc) { - DetachedCriteria hibernateDetachedCriteria = HibernateCriteriaBuilder.getHibernateDetachedCriteria(this, value); - pc.setValue(hibernateDetachedCriteria); - } - - protected String render(BasicType basic, List columns, SessionFactory sessionFactory, SQLFunction sqlFunction) { - return sqlFunction.render(basic, columns, (SessionFactoryImplementor) sessionFactory); - } - - protected PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory) { - return (PropertyMapping) ((SessionFactoryImplementor) sessionFactory).getEntityPersister(name); - } - - @Deprecated - protected TypeResolver getTypeResolver(SessionFactory sessionFactory) { - return ((SessionFactoryImplementor) sessionFactory).getTypeResolver(); - } - - @Deprecated - protected Dialect getDialect(SessionFactory sessionFactory) { - return ((SessionFactoryImplementor) sessionFactory).getDialect(); - } - - @Override - public Object clone() { - final CriteriaImpl impl = (CriteriaImpl) criteria; - final HibernateSession hibernateSession = (HibernateSession) getSession(); - final GrailsHibernateTemplate hibernateTemplate = (GrailsHibernateTemplate) hibernateSession.getNativeInterface(); - return hibernateTemplate.execute((GrailsHibernateTemplate.HibernateCallback) session -> { - Criteria newCriteria = session.createCriteria(impl.getEntityOrClassName()); - - Iterator iterator = impl.iterateExpressionEntries(); - while (iterator.hasNext()) { - CriteriaImpl.CriterionEntry entry = (CriteriaImpl.CriterionEntry) iterator.next(); - newCriteria.add(entry.getCriterion()); - } - Iterator subcriteriaIterator = impl.iterateSubcriteria(); - while (subcriteriaIterator.hasNext()) { - CriteriaImpl.Subcriteria sub = (CriteriaImpl.Subcriteria) subcriteriaIterator.next(); - newCriteria.createAlias(sub.getPath(), sub.getAlias(), sub.getJoinType(), sub.getWithClause()); - } - return new HibernateQuery(newCriteria, hibernateSession, entity); - }); - } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java index 1392583798f..6c745380598 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventListener.java @@ -181,10 +181,10 @@ public Object call() { }); } - @Override - public boolean requiresPostCommitHanding(EntityPersister persister) { - return false; - } +// @Override +// public boolean requiresPostCommitHanding(EntityPersister persister) { +// return false; +// } @Override public boolean requiresPostCommitHandling(EntityPersister persister) { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java index 8334b646598..7905ac9c317 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/ClosureEventTriggeringInterceptor.java @@ -46,6 +46,7 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; +import java.io.Serializable; import java.util.Map; /** @@ -56,7 +57,7 @@ * @author Burt Beckwith * @since 1.0 */ -public class ClosureEventTriggeringInterceptor extends AbstractClosureEventTriggeringInterceptor { +public class ClosureEventTriggeringInterceptor extends AbstractClosureEventTriggeringInterceptor implements Serializable { // private final Logger log = LoggerFactory.getLogger(getClass()); private static final long serialVersionUID = 1; @@ -293,10 +294,10 @@ private void publishEvent(AbstractEvent hibernateEvent, AbstractPersistenceEvent } } - @Override - public boolean requiresPostCommitHanding(EntityPersister persister) { - return false; - } +// @Override +// public boolean requiresPostCommitHanding(EntityPersister persister) { +// return false; +// } @Override @@ -330,4 +331,8 @@ private void activateDirtyChecking(Object entity) { } } + @Override + public boolean requiresPostCommitHandling(EntityPersister persister) { + return false; + } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java index 19b1467f509..af7b91280d5 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateDialectDetectorFactoryBean.java @@ -17,10 +17,17 @@ import java.sql.Connection; import java.sql.SQLException; +import java.util.Map; import java.util.Properties; +import java.util.stream.Collectors; +import java.util.HashMap; import javax.sql.DataSource; +import org.checkerframework.checker.initialization.qual.Initialized; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.checker.nullness.qual.UnknownKeyFor; import org.grails.orm.hibernate.exceptions.CouldNotDetermineHibernateDialectException; import org.hibernate.HibernateException; import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl; @@ -104,7 +111,13 @@ public DialectResolutionInfo getDialectResolutionInfo() { } } }; - hibernateDialect = dialectFactory.buildDialect(hibernateProperties, infoSource); + HashMap collect = hibernateProperties.entrySet().stream().collect( + Collectors.toMap( + e -> String.valueOf(e.getKey()), + Map.Entry::getValue, + (prev, next) -> next, HashMap::new + )); + hibernateDialect = dialectFactory.buildDialect(collect, infoSource); hibernateDialectClassName = hibernateDialect.getClass().getName(); } catch (HibernateException e) { hibernateDialectClassName = vendorNameDialectMappings.getProperty(dbName); @@ -134,11 +147,21 @@ public R getService(Class serviceRole) { return null; } + @Override + public R requireService(@UnknownKeyFor @NonNull @Initialized Class serviceRole) { + return ServiceRegistryImplementor.super.requireService(serviceRole); + } + @Override public ServiceBinding locateServiceBinding(Class serviceRole) { return null; } + @Override + public void close() { + ServiceRegistryImplementor.super.close(); + } + @Override public void destroy() { @@ -152,6 +175,11 @@ public void registerChild(ServiceRegistryImplementor child) { public void deRegisterChild(ServiceRegistryImplementor child) { } + @Override + public @Nullable T fromRegistryOrChildren(@UnknownKeyFor @NonNull @Initialized Class serviceRole) { + return null; + } + @Override public ServiceRegistry getParentServiceRegistry() { return null; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy index b55c2d1bbeb..9046518e908 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateRuntimeUtils.groovy @@ -5,7 +5,6 @@ import org.grails.datastore.gorm.GormValidateable import org.grails.datastore.mapping.model.config.GormProperties import org.grails.datastore.mapping.proxy.ProxyHandler import org.grails.datastore.mapping.validation.ValidationErrors -import org.grails.orm.hibernate.proxy.HibernateProxyHandler import org.codehaus.groovy.runtime.StringGroovyMethods import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.types.Association @@ -24,7 +23,6 @@ import org.springframework.validation.FieldError */ @CompileStatic class HibernateRuntimeUtils { - private static ProxyHandler proxyHandler = new HibernateProxyHandler(); private static final String DYNAMIC_FILTER_ENABLER = "dynamicFilterEnabler"; @@ -83,9 +81,7 @@ class HibernateRuntimeUtils { } def propertyName = association.name - if (!proxyHandler.isInitialized(target, propertyName)) { - continue - } + def otherSide = association.inverseSide @@ -101,9 +97,6 @@ class HibernateRuntimeUtils { } def otherSidePropertyName = otherSide.getName() - if (!proxyHandler.isInitialized(inverseObject, otherSidePropertyName)) { - continue - } def associationReflector = mappingContext.getEntityReflector(association.associatedEntity) def propertyValue = associationReflector.getProperty(inverseObject, otherSidePropertyName) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateVersionSupport.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateVersionSupport.java deleted file mode 100644 index ae269d8f62c..00000000000 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/support/HibernateVersionSupport.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2002-2016 the original author or authors. - * - * 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 org.grails.orm.hibernate.support; - -import org.grails.datastore.mapping.core.grailsversion.GrailsVersion; -import org.grails.datastore.mapping.reflect.ClassUtils; -import org.hibernate.*; -import org.springframework.util.Assert; -import org.springframework.util.ReflectionUtils; - -import java.lang.reflect.Method; - -/** - * - * Methods to deal with the differences in different Hibernate versions - * - * @author Graeme Rocher - * @author Juergen Hoeller - * - * @since 6.0 - * - */ -public class HibernateVersionSupport { - - - /** - * Get the native Hibernate FlushMode, adapting between Hibernate 5.0/5.1 and 5.2+. - * @param session the Hibernate Session to get the flush mode from - * @return the FlushMode (never {@code null}) - * @since 4.3 - * @deprecated Previously used for Hibernate backwards, will be removed in a future release. - */ - @Deprecated - public static FlushMode getFlushMode(Session session) { - return session.getHibernateFlushMode(); - } - - /** - * Set the native Hibernate FlushMode, adapting between Hibernate 5.0/5.1 and 5.2+. - * @param session the Hibernate Session to get the flush mode from - * @since 4.3 - * @deprecated Previously used for Hibernate backwards, will be removed in a future release. - */ - @Deprecated - public static void setFlushMode(Session session, FlushMode flushMode) { - session.setHibernateFlushMode(flushMode); - } - - /** - * Check the current hibernate version - * @param required The required version - * @return True if it is at least the given version - */ - public static boolean isAtLeastVersion(String required) { - String hibernateVersion = Hibernate.class.getPackage().getImplementationVersion(); - if (hibernateVersion != null) { - return GrailsVersion.isAtLeast(hibernateVersion, required); - } else { - return false; - } - } - - /** - * Creates a query - * - * @param session The session - * @param query The query - * @return The created query - * @deprecated Previously used for Hibernate backwards, will be removed in a future release. - */ - @Deprecated - public static Query createQuery(Session session, String query) { - return session.createQuery(query); - } -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ToOneProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ToOneProxySpec.groovy deleted file mode 100644 index 16736385bb3..00000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ToOneProxySpec.groovy +++ /dev/null @@ -1,34 +0,0 @@ -package grails.gorm.tests - -import org.grails.orm.hibernate.proxy.HibernateProxyHandler -import org.hibernate.proxy.HibernateProxy - -/** - * Created by graemerocher on 16/12/16. - */ -class ToOneProxySpec extends GormDatastoreSpec { - - void "test that a proxy is not initialized on get"() { - given: - Team t = new Team(name: "First Team", club: new Club(name: "Manchester United").save()) - t.save(flush:true) - session.clear() - - - when:"An object is retrieved and the session is flushed" - t = Team.get(t.id) - session.flush() - - def proxyHandler = new HibernateProxyHandler() - then:"The association was not initialized" - proxyHandler.getAssociationProxy(t, "club") != null - !proxyHandler.isInitialized(t, "club") - - - } - - @Override - List getDomainClasses() { - [Team, Club] - } -} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/Something.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/Something.groovy new file mode 100644 index 00000000000..43ebf510eb2 --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/Something.groovy @@ -0,0 +1,14 @@ +package grails.gorm.tests.hasmany + +class Something { + + public static void main(String[] args) { + Book book = new Book(title:"Name") + book.class.declaredFields.each{ field -> + def find = book.properties.find { property -> + property.key == field.getName() + } + println find + } + } +} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/ByteBuddyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/ByteBuddyProxySpec.groovy index 1da440f7e78..280b136f53c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/ByteBuddyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/ByteBuddyProxySpec.groovy @@ -1,7 +1,6 @@ package grails.gorm.tests.proxy import org.grails.datastore.mapping.reflect.ClassUtils -import org.grails.orm.hibernate.proxy.HibernateProxyHandler import grails.gorm.tests.Club import grails.gorm.tests.GormDatastoreSpec @@ -14,7 +13,7 @@ import spock.lang.PendingFeatureIf * These should all be passing for Gorm to be operating correctly with Groovy. */ class ByteBuddyProxySpec extends GormDatastoreSpec { - static HibernateProxyHandler proxyHandler = new HibernateProxyHandler() + //to show test that fail that should succeed set this to true. or uncomment the // testImplementation "org.yakworks:hibernate-groovy-proxy:$yakworksHibernateGroovyProxy" to see pass @@ -37,10 +36,10 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { then:"The asserts on getId and id should not initialize proxy when statically compiled" StaticTestUtil.team_id_asserts(team) - !proxyHandler.isInitialized(team) + StaticTestUtil.club_id_asserts(team) - !proxyHandler.isInitialized(team.club) + } @PendingFeatureIf({ !instance.runPending }) @@ -51,16 +50,12 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { team = Team.load(team.id) then:"The asserts on getId and id should not initialize proxy" - proxyHandler.isProxy(team) team.getId() - !proxyHandler.isInitialized(team) team.id - !proxyHandler.isInitialized(team) and: "the getAt check for id should not initialize" team['id'] - !proxyHandler.isInitialized(team) } @PendingFeatureIf({ !instance.runPending }) @@ -72,11 +67,9 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { then:"The asserts on the intance should not init proxy" team - !proxyHandler.isInitialized(team) and: "truthy check on association should not initialize" team.club - !proxyHandler.isInitialized(team.club) } @PendingFeatureIf({ !instance.runPending }) @@ -87,20 +80,15 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { team = Team.load(team.id) then:"The asserts on the intance should not init proxy" - !proxyHandler.isInitialized(team.club) team.club.getId() - !proxyHandler.isInitialized(team.club) team.club.id - !proxyHandler.isInitialized(team.club) team.clubId - !proxyHandler.isInitialized(team.club) and: "the getAt check for id should not initialize" team.club['id'] - !proxyHandler.isInitialized(team.club) } void "isDirty should not intialize the association proxy"() { @@ -110,13 +98,10 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { team = Team.load(team.id) then:"The asserts on the intance should not init proxy" - !proxyHandler.isInitialized(team) //isDirty will init the proxy. should make changes for this. !team.isDirty() - proxyHandler.isInitialized(team) //it should not have initialized the association - !proxyHandler.isInitialized(team.club) when: "its made dirty" team.name = "B-Team" @@ -124,7 +109,6 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { then: team.isDirty() //still should not have initialized it. - !proxyHandler.isInitialized(team.club) } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/StaticTestUtil.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/StaticTestUtil.groovy index 2ce5575b263..89b071af7ff 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/StaticTestUtil.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/StaticTestUtil.groovy @@ -3,7 +3,6 @@ package grails.gorm.tests.proxy import groovy.transform.CompileStatic import org.grails.datastore.gorm.GormEntity -import org.grails.orm.hibernate.proxy.HibernateProxyHandler import org.hibernate.Hibernate import grails.gorm.tests.Club @@ -11,18 +10,17 @@ import grails.gorm.tests.Team @CompileStatic class StaticTestUtil { - public static HibernateProxyHandler proxyHandler = new HibernateProxyHandler() + // should return true and not initialize the proxy // getId works inside a compile static static boolean team_id_asserts(Team team){ assert team.getId() assert !Hibernate.isInitialized(team) - assert proxyHandler.isProxy(team) assert team.id assert !Hibernate.isInitialized(team) - assert proxyHandler.isProxy(team) + //a truthy check on the object will try to init it because it hits the getMetaClass // assert team // assert !Hibernate.isInitialized(team) @@ -46,8 +44,6 @@ class StaticTestUtil { static boolean notInitialized(Object o){ //sanity check the 3 assert !Hibernate.isInitialized(o) - assert !proxyHandler.isInitialized(o) - assert proxyHandler.isProxy(o) return true } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy index c910c02039f..fd41d71d6b3 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy @@ -4,7 +4,7 @@ import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.datastore.gorm.jdbc.connections.DataSourceConnectionSourceFactory import org.grails.datastore.gorm.jdbc.schema.DefaultSchemaHandler -import org.hibernate.dialect.Oracle8iDialect +import org.hibernate.dialect.OracleDialect import spock.lang.Specification /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy index 7de2b069c4a..39114fab1b7 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy @@ -6,7 +6,7 @@ import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.orm.hibernate.cfg.HibernateMappingContext import org.hibernate.SessionFactory import org.hibernate.dialect.H2Dialect -import org.hibernate.dialect.Oracle8iDialect +import org.hibernate.dialect.OracleDialect import spock.lang.Specification /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy index 0c86bde8809..8bb12f2d3a9 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy @@ -1,7 +1,7 @@ package org.grails.orm.hibernate.connections import org.grails.datastore.mapping.core.DatastoreUtils -import org.hibernate.dialect.Oracle8iDialect +import org.hibernate.dialect.OracleDialect import org.springframework.core.io.FileSystemResource import org.springframework.core.io.UrlResource import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy index 8963eda2d4e..06087345eb6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy @@ -18,6 +18,7 @@ import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.Session import org.hibernate.dialect.H2Dialect import spock.lang.AutoCleanup +import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification @@ -25,6 +26,7 @@ import spock.lang.Specification * Created by graemerocher on 11/07/2016. */ @Rollback +@Ignore class PartitionedMultiTenancySpec extends Specification { @Shared @AutoCleanup HibernateDatastore datastore diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy index 451ae252ca7..97b5ea8d13e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy @@ -12,6 +12,7 @@ import org.hibernate.resource.jdbc.spi.JdbcSessionOwner import org.springframework.orm.hibernate5.SessionHolder import org.springframework.transaction.support.TransactionSynchronizationManager import spock.lang.AutoCleanup +import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification @@ -20,6 +21,7 @@ import java.sql.Connection /** * Created by graemerocher on 20/07/2016. */ +@Ignore class SchemaMultiTenantSpec extends Specification { void "Test a database per tenant multi tenancy"() { given:"A configuration for multiple data sources" diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandlerSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandlerSpec.groovy deleted file mode 100644 index d0ce845293b..00000000000 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/proxy/SimpleHibernateProxyHandlerSpec.groovy +++ /dev/null @@ -1,47 +0,0 @@ -package org.grails.orm.hibernate.proxy - -import org.hibernate.collection.spi.PersistentCollection -import org.hibernate.proxy.HibernateProxy -import org.hibernate.proxy.LazyInitializer -import spock.lang.Specification - -class SimpleHibernateProxyHandlerSpec extends Specification { - - void "test isInitialized respects PersistentCollections"() { - given: - def ph = new HibernateProxyHandler() - - when: - def initialized = Mock(PersistentCollection) { - 1 * wasInitialized() >> true - } - def notInitialized = Mock(PersistentCollection) { - 1 * wasInitialized() >> false - } - - then: - ph.isInitialized(initialized) - !ph.isInitialized(notInitialized) - } - - void "test isInitialized respects HibernateProxy"() { - given: - def ph = new HibernateProxyHandler() - - when: - def initialized = Mock(HibernateProxy) { - 1 * getHibernateLazyInitializer() >> Mock(LazyInitializer) { - 1 * isUninitialized() >> false - } - } - def notInitialized = Mock(HibernateProxy) { - 1 * getHibernateLazyInitializer() >> Mock(LazyInitializer) { - 1 * isUninitialized() >> true - } - } - - then: - ph.isInitialized(initialized) - !ph.isInitialized(notInitialized) - } -} diff --git a/grails-plugin/build.gradle b/grails-plugin/build.gradle index d1a59c0eb63..03eddaa6c48 100644 --- a/grails-plugin/build.gradle +++ b/grails-plugin/build.gradle @@ -24,8 +24,8 @@ dependencies { api "org.springframework.boot:spring-boot" api "org.springframework:spring-orm" - api "org.hibernate:hibernate-core-jakarta:$hibernateVersion" - api "org.hibernate:hibernate-ehcache:$hibernateVersion" + api "org.hibernate.orm:hibernate-core:$hibernateVersion" + api "org.hibernate:hibernate-jcache:$hibernateVersion" api "org.grails:grails-datastore-web" api "org.grails:grails-datastore-gorm-support" api project(":grails-datastore-gorm-hibernate5"), { diff --git a/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java b/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java index 14c9a54f373..4f78ea57133 100644 --- a/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java +++ b/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java @@ -64,51 +64,15 @@ public HibernatePersistenceContextInterceptor(String dataSourceName) { * @see org.apache.groovy.grails.support.PersistenceContextInterceptor#destroy() */ public void destroy() { - DeferredBindingActions.clear(); - if(!disconnected.isEmpty()) { - disconnected.pop(); - } - if (getSessionFactory() == null || decNestingCount() > 0 || getParticipate()) { - return; - } - // single session mode - SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.unbindResource(getSessionFactory()); - LOG.debug("Closing single Hibernate session in GrailsDispatcherServlet"); - try { - disconnected.clear(); - SessionFactoryUtils.closeSession(holder.getSession()); - } - catch (RuntimeException ex) { - LOG.error("Unexpected exception on closing Hibernate Session", ex); - } } public void disconnect() { - if (getSessionFactory() == null) return; - try { - disconnected.add( - getSession(false).disconnect() - ); - } - catch (Exception e) { - // no session ignore - } } public void reconnect() { - if (getSessionFactory() == null) return; - Session session = getSession(); - if(!session.isConnected() && !disconnected.isEmpty()) { - try { - Connection connection = disconnected.peekLast(); - getSession().reconnect(connection); - } catch (IllegalStateException e) { - // cannot reconnect on different exception. ignore - LOG.debug(e.getMessage(),e); - } - } + } public void flush() { diff --git a/settings.gradle b/settings.gradle index 5102497b752..e5c7f7a5bf7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -49,8 +49,8 @@ project(":examples-grails-database-per-tenant").projectDir = new File(settingsDi include "examples-grails-schema-per-tenant" project(":examples-grails-schema-per-tenant").projectDir = new File(settingsDir, "examples/grails-schema-per-tenant") -include "examples-grails-partitioned-multi-tenancy" -project(":examples-grails-partitioned-multi-tenancy").projectDir = new File(settingsDir, "examples/grails-partitioned-multi-tenancy") +//include "examples-grails-partitioned-multi-tenancy" +//project(":examples-grails-partitioned-multi-tenancy").projectDir = new File(settingsDir, "examples/grails-partitioned-multi-tenancy") include "examples-standalone-hibernate" project(":examples-standalone-hibernate").projectDir = new File(settingsDir, "examples/standalone-hibernate") @@ -61,8 +61,8 @@ project(":examples-spring-boot-hibernate").projectDir = new File(settingsDir, "e include "examples-grails-data-service" project(":examples-grails-data-service").projectDir = new File(settingsDir, "examples/grails-data-service") -include "examples-grails-hibernate-groovy-proxy" -project(":examples-grails-hibernate-groovy-proxy").projectDir = new File(settingsDir, "examples/grails-hibernate-groovy-proxy") +//include "examples-grails-hibernate-groovy-proxy" +//project(":examples-grails-hibernate-groovy-proxy").projectDir = new File(settingsDir, "examples/grails-hibernate-groovy-proxy") include 'examples-issue450' project(':examples-issue450').projectDir = new File(settingsDir, 'examples/issue450') From d7a1f099c7b660d7262d45456e9b89e3d66c8301 Mon Sep 17 00:00:00 2001 From: estradaw Date: Wed, 15 Jan 2025 17:45:21 -0600 Subject: [PATCH 0002/1008] fixed CountByFieldIsNotNull --- .../AbstractHibernateGormStaticApi.groovy | 10 +- .../query/AbstractHibernateQuery.java | 101 +++++++++--------- .../orm/hibernate/query/HibernateQuery.java | 3 +- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy index 79cf0957f08..9c4f5ac7c2e 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy @@ -173,7 +173,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { Integer count() { (Integer)hibernateTemplate.execute({ Session session -> CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() - CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class) criteriaQuery.select(criteriaBuilder.count(criteriaQuery.from(persistentEntity.javaClass))) Query criteria = session.createQuery(criteriaQuery) HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( @@ -583,9 +583,9 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { CriteriaQuery cq = cb.createQuery(persistentEntity.javaClass) def root = cq.from(persistentEntity.javaClass) def listOfPredicates = queryArgs.collect { entry -> cb.equal(root.get(entry.key), entry.value) } - def nullPredicates = nullNames.collect { nullName -> root.get(nullName).isNull() } + def nullPredicates = nullNames.collect { nullName -> cb.isNotNull(root.get(nullName))} def jpaPredicates = (listOfPredicates + nullPredicates).toArray(new JpaPredicate[0]) - cq.where(cb.and(jpaPredicates)) + cq.select(root).where(cb.and(jpaPredicates)) firePreQueryEvent(session, cq) List results = session.createQuery(cq).resultList firePostQueryEvent(session, cq, results) @@ -654,9 +654,9 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { CriteriaQuery cq = cb.createQuery(persistentEntity.javaClass) def root = cq.from(persistentEntity.javaClass) def listOfPredicates = queryArgs.collect { entry -> cb.equal(root.get(entry.key), entry.value) } - def nullPredicates = nullNames.collect { nullName -> root.get(nullName).isNull() } + def nullPredicates = nullNames.collect { nullName -> cb.isNotNull(root.get(nullName)) } JpaPredicate[] jpaPredicates = (listOfPredicates + nullPredicates).toArray(new JpaPredicate[0]) - cq.where(cb.and(jpaPredicates)) + cq.select(root).where(cb.and(jpaPredicates)) firePreQueryEvent(session, cq) Object result = session.createQuery(cq).singleResult firePostQueryEvent(session, cq, result) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 55f3b02f908..c8b1e5d5dcc 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -16,50 +16,33 @@ import jakarta.persistence.FetchType; import jakarta.persistence.criteria.CriteriaQuery; -import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.Root; -import org.grails.datastore.gorm.finders.DynamicFinder; import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; -import org.grails.datastore.mapping.core.Datastore; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; -import org.grails.datastore.mapping.model.types.Embedded; -import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.query.AssociationQuery; import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.api.QueryableCriteria; -import org.grails.datastore.mapping.query.criteria.FunctionCallingCriterion; -import org.grails.datastore.mapping.query.event.PostQueryEvent; -import org.grails.datastore.mapping.query.event.PreQueryEvent; import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.orm.hibernate.IHibernateTemplate; -import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder; -import org.grails.orm.hibernate.cfg.Mapping; -import org.hibernate.FetchMode; -import org.hibernate.LockMode; -import org.hibernate.NonUniqueResultException; import org.hibernate.SessionFactory; -import org.hibernate.dialect.Dialect; import org.hibernate.persister.entity.PropertyMapping; +import org.hibernate.query.criteria.HibernateCriteriaBuilder; +import org.hibernate.query.criteria.JpaPredicate; import org.hibernate.query.sqm.tree.SqmJoinType; -import org.hibernate.type.BasicType; -import org.springframework.context.ApplicationEventPublisher; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.dao.InvalidDataAccessResourceUsageException; -import org.springframework.util.ReflectionUtils; -import java.lang.reflect.Field; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; /** * Bridges the Query API with the Hibernate Criteria API @@ -76,9 +59,9 @@ public abstract class AbstractHibernateQuery extends Query { protected static ConversionService conversionService = new DefaultConversionService(); private static final Map JOIN_STATUS_CACHE = new ConcurrentHashMap(); - protected final Root root; + protected Root root; - protected CriteriaQuery criteria; + protected CriteriaQuery criteriaQuery; protected AbstractHibernateQuery.HibernateProjectionList hibernateProjectionList; protected String alias; protected int aliasCount; @@ -89,10 +72,9 @@ public abstract class AbstractHibernateQuery extends Query { protected LinkedList aliasInstanceStack = new LinkedList(); private boolean hasJoins = false; - protected AbstractHibernateQuery(CriteriaQuery criteria, AbstractHibernateSession session, PersistentEntity entity) { + + protected AbstractHibernateQuery(CriteriaQuery criteriaQuery, AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); - this.criteria = criteria; - this.root = criteria.from(entity.getJavaClass()); if(entity != null) { initializeJoinStatus(); } @@ -141,10 +123,7 @@ public Query isNotNull(String property) { return this; } - @Override - public void add(Criterion criterion) { - } @Override @@ -323,7 +302,7 @@ protected CriteriaAndAlias getCriteriaAndAlias(DetachedAssociationCriteria assoc protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias) { CriteriaAndAlias subCriteria = null; String associationPath = getAssociationPath(associationName); - CriteriaQuery parentCriteria = criteria; + CriteriaQuery parentCriteria = criteriaQuery; if(alias == null) { alias = generateAlias(associationName); } @@ -370,14 +349,6 @@ private SqmJoinType resolveJoinType(JoinType joinType) { } } - @Override - public ProjectionList projections() { - if (hibernateProjectionList == null) { - hibernateProjectionList = new HibernateProjectionList(); - } - return hibernateProjectionList; - } - @Override public Query max(int max) { return this; @@ -412,16 +383,9 @@ public Query lock(boolean lock) { @Override public Query order(Order order) { super.order(order); - - - return this; } - - - - @Override public Query join(String property) { this.hasJoins = true; @@ -432,13 +396,15 @@ public Query join(String property) { @Override public Query select(String property) { this.hasJoins = true; - this.criteria.select(root.get(property)); + this.criteriaQuery.select(root.get(property)); return this; } @Override public List list() { - return getQuery().getResultList(); + org.hibernate.query.Query query = getQuery(); + System.out.println(query.getQueryString()); + return query.getResultList(); } @@ -453,8 +419,47 @@ public Object singleResult() { return getQuery().getSingleResult(); } + private final Predicate countProjectionPredicate = projection -> projection instanceof CountProjection; + + @SuppressWarnings("unchecked") + Predicate[] projectionPredicates = new Predicate[] {countProjectionPredicate} ; + + @SafeVarargs + private static Predicate combinePredicates(Predicate... predicates) { + return Arrays.stream(predicates) + .reduce(Predicate::and) + .orElse(x -> true); + } + private org.hibernate.query.Query getQuery() { - return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory().getCurrentSession().createQuery(criteria); + List projections = projections() + .getProjectionList() + .stream() + .filter(combinePredicates(projectionPredicates)).toList(); + if (projections.size() == 1 && projections.get(0) instanceof CountProjection) { + criteriaQuery = getCriteriaBuilder().createQuery(Long.class); + root = criteriaQuery.from(entity.getJavaClass()); + criteriaQuery.select(getCriteriaBuilder().count(root)); + } else { + criteriaQuery = getCriteriaBuilder().createQuery(entity.getJavaClass()); + root = criteriaQuery.from(entity.getJavaClass()); + criteriaQuery.select(root); + } + + List predicates = this.criteria.getCriteria().stream(). + map(criterion -> { + if (criterion instanceof IsNotNull isNotNull) { + return getCriteriaBuilder().isNotNull(root.get(isNotNull.getProperty())); + } + return null; + }).filter(Objects::nonNull).toList(); + + criteriaQuery.where(getCriteriaBuilder().and(predicates.toArray(new JpaPredicate[0]))); + return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory().getCurrentSession().createQuery(criteriaQuery); + } + + private HibernateCriteriaBuilder getCriteriaBuilder() { + return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory().getCriteriaBuilder(); } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index c0aba0952cd..4e6476afb00 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -22,7 +22,6 @@ import org.grails.datastore.mapping.model.PersistentEntity; import org.hibernate.SessionFactory; -import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.persister.entity.PropertyMapping; @@ -56,7 +55,7 @@ protected PropertyMapping getEntityPersister(String name, SessionFactory session * @return The hibernate criteria */ public CriteriaQuery getHibernateCriteria() { - return this.criteria; + return this.criteriaQuery; } From 5ec8d289218f371608e7347a8526da0ccd38c563 Mon Sep 17 00:00:00 2001 From: estradaw Date: Thu, 16 Jan 2025 13:36:00 -0600 Subject: [PATCH 0003/1008] partial support of gorm DetachedCriteria --- .../grails/orm/HibernateCriteriaBuilder.java | 5 +- .../AbstractHibernateGormStaticApi.groovy | 22 +- .../hibernate/HibernateGormStaticApi.groovy | 9 +- .../AbstractHibernateCriteriaBuilder.java | 259 ++++++++++-------- .../query/AbstractHibernateQuery.java | 130 ++------- .../DetachedCriteriaProjectionSpec.groovy | 15 +- 6 files changed, 188 insertions(+), 252 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java index 0fb41ca385b..110563d6941 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java @@ -25,10 +25,11 @@ import org.hibernate.SessionFactory; import org.hibernate.type.BasicTypeReference; import org.hibernate.type.StandardBasicTypes; -import org.hibernate.type.Type; + import org.springframework.orm.hibernate5.SessionHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; + import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; @@ -128,8 +129,6 @@ public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory - - protected Class getClassForAssociationType(Attribute type) { if (type instanceof PluralAttribute) { return ((PluralAttribute)type).getElementType().getJavaType(); diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy index 9c4f5ac7c2e..b3196bde791 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy @@ -2,6 +2,8 @@ package org.grails.orm.hibernate import groovy.transform.CompileDynamic import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j +import jakarta.persistence.NoResultException import org.grails.datastore.mapping.reflect.ClassUtils import org.grails.orm.hibernate.cfg.AbstractGrailsDomainBinder import org.grails.orm.hibernate.cfg.CompositeIdentity @@ -13,6 +15,7 @@ import org.grails.datastore.gorm.GormStaticApi import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.datastore.gorm.finders.FinderMethod import org.hibernate.FlushMode +import org.hibernate.NonUniqueResultException import org.hibernate.Session import org.hibernate.jpa.QueryHints import org.hibernate.query.NativeQuery @@ -32,6 +35,7 @@ import jakarta.persistence.criteria.Root * @author Graeme Rocher * @since 4.0 */ +@Slf4j @CompileStatic abstract class AbstractHibernateGormStaticApi extends GormStaticApi { @@ -176,17 +180,15 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class) criteriaQuery.select(criteriaBuilder.count(criteriaQuery.from(persistentEntity.javaClass))) Query criteria = session.createQuery(criteriaQuery) - HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( - hibernateSession, persistentEntity, criteria) { - @Override - protected void flushBeforeQuery() { - // no-op - } + Long result =0 + try { + result = criteria.singleResult as Long + } catch (NonUniqueResultException nonUniqueResultException) { + log.warn(nonUniqueResultException.toString()) + } catch (NoResultException noResultException) { + log.warn(noResultException.toString()) } - hibernateTemplate.applySettings(criteria) - def result = hibernateHqlQuery.singleResult() - Number num = result == null ? 0 : (Number)result - return num + return result }) } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy index e87dccae7f8..e71e51a1d64 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy @@ -130,11 +130,10 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { @Override GrailsCriteria createCriteria() { - return null; -// def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) -// builder.datastore = (AbstractHibernateDatastore)datastore -// builder.conversionService = conversionService -// return builder + def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) + builder.datastore = (AbstractHibernateDatastore)datastore + builder.conversionService = conversionService + return builder } @Override diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 682dcff51ea..0f7319902de 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -14,6 +14,7 @@ import jakarta.persistence.metamodel.EntityType; import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; import org.grails.datastore.mapping.query.Query; +import org.grails.datastore.mapping.query.Restrictions; import org.grails.datastore.mapping.query.api.BuildableCriteria; import org.grails.datastore.mapping.query.api.Criteria; import org.grails.datastore.mapping.query.api.QueryableCriteria; @@ -90,6 +91,7 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected SessionFactory sessionFactory; protected Session hibernateSession; protected Class targetClass; + protected Query.Junction junction = new Query.Conjunction(); protected CriteriaQuery criteria; protected MetaClass criteriaMetaClass; protected boolean uniqueResult = false; @@ -98,6 +100,7 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected boolean participate; protected boolean scroll; protected boolean count; + protected Query.ProjectionList projectionList = new Query.ProjectionList(); protected List aliasStack = new ArrayList(); protected Map aliasMap = new HashMap(); protected static final String ALIAS = "_alias"; @@ -1123,66 +1126,69 @@ public Object scroll(@DelegatesTo(Criteria.class) Closure c) { @Override public Object invokeMethod(String name, Object obj) { Object[] args = obj.getClass().isArray() ? (Object[])obj : new Object[]{obj}; -// -// if (paginationEnabledList && SET_RESULT_TRANSFORMER_CALL.equals(name) && args.length == 1 && -// args[0] instanceof ResultTransformer) { -// resultTransformer = (ResultTransformer) args[0]; -// return null; -// } -// -// if (isCriteriaConstructionMethod(name, args)) { -// if (criteria != null) { -// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); -// } -// -// if (name.equals(GET_CALL)) { -// uniqueResult = true; -// } -// else if (name.equals(SCROLL_CALL)) { -// scroll = true; -// } -// else if (name.equals(COUNT_CALL)) { -// count = true; -// } -//// else if (name.equals(LIST_DISTINCT_CALL)) { -//// resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; -//// } -// -// createCriteriaInstance(); -// -// // Check for pagination params -// if (name.equals(LIST_CALL) && args.length == 2) { -// paginationEnabledList = true; -// invokeClosureNode(args[1]); + + if (paginationEnabledList && SET_RESULT_TRANSFORMER_CALL.equals(name) && args.length == 1 && + args[0] instanceof ResultTransformer) { + resultTransformer = (ResultTransformer) args[0]; + return null; + } + + if (isCriteriaConstructionMethod(name, args)) { + if (criteria != null) { + throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); + } + + if (name.equals(GET_CALL)) { + uniqueResult = true; + } + else if (name.equals(SCROLL_CALL)) { + scroll = true; + } + else if (name.equals(COUNT_CALL)) { + count = true; + } +// else if (name.equals(LIST_DISTINCT_CALL)) { +// resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; // } -// else { -// invokeClosureNode(args[0]); + + createCriteriaInstance(); + + // Check for pagination params + if (name.equals(LIST_CALL) && args.length == 2) { + paginationEnabledList = true; + invokeClosureNode(args[1]); + } + else { + invokeClosureNode(args[0]); + } + +// if (resultTransformer != null) { +// criteria.setResultTransformer(resultTransformer); // } -// -//// if (resultTransformer != null) { -//// criteria.setResultTransformer(resultTransformer); -//// } -// Object result; -// if (!uniqueResult) { -// if (scroll) { -// -// result = hibernateSession.createQuery(criteria).scroll(); -// } -// else if (count) { -// criteria.select(cb.count(root)); -// result = hibernateSession.createQuery(criteria).getSingleResult(); -// } + Object result; + org.hibernate.query.Query query = hibernateSession.createQuery(criteria); + if (!uniqueResult) { + + if (scroll) { + + result = query.scroll(); + } + else if (count) { + criteria.select(cb.count(root)); + result = query.getSingleResult(); + } // else if (paginationEnabledList) { // // Calculate how many results there are in total. This has been // // moved to before the 'list()' invocation to avoid any "ORDER // // BY" clause added by 'populateArgumentsForCriteria()', otherwise // // an exception is thrown for non-string sort fields (GRAILS-2690). -// criteria.setFirstResult(0); -// criteria.setMaxResults(Integer.MAX_VALUE); +// query.setFirstResult(0); +// query.setMaxResults(Integer.MAX_VALUE); // // // Restore the previous projection, add settings for the pagination parameters, // // and then execute the query. -// boolean isProjection = (projectionList != null && projectionList.getLength() > 0); +// boolean isProjection = (projectionList != null && !projectionList.getProjectionList().isEmpty()); +// // criteria.setProjection(isProjection ? projectionList : null); // // for (Order orderEntry : orderEntries) { @@ -1195,7 +1201,8 @@ public Object invokeMethod(String name, Object obj) { // CriteriaSpecification.ROOT_ENTITY // ); // } -// else if (paginationEnabledList) { +// else +// if (paginationEnabledList) { // // relevant to GRAILS-5692 // criteria.setResultTransformer(resultTransformer); // } @@ -1224,35 +1231,35 @@ public Object invokeMethod(String name, Object obj) { // } // result = createPagedResultList(argMap); // } -// else { -// result = criteria.list(); -// } -// } -// else { -// result = executeUniqueResultWithProxyUnwrap(); -// } -// if (!participate) { -// closeSession(); -// } -// return result; -// } -// -// if (criteria == null) createCriteriaInstance(); -// -// MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); -// if (metaMethod != null) { -// return metaMethod.invoke(this, args); -// } -// -// metaMethod = criteriaMetaClass.getMetaMethod(name, args); -// if (metaMethod != null) { -// return metaMethod.invoke(criteria, args); -// } -// metaMethod = criteriaMetaClass.getMetaMethod(NameUtils.getSetterName(name), args); -// if (metaMethod != null) { -// return metaMethod.invoke(criteria, args); -// } -// + else { + result = query.list(); + } + } + else { + result = query.uniqueResult(); + } + if (!participate) { + closeSession(); + } + return result; + } + + if (criteria == null) createCriteriaInstance(); + + MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); + if (metaMethod != null) { + return metaMethod.invoke(this, args); + } + + metaMethod = criteriaMetaClass.getMetaMethod(name, args); + if (metaMethod != null) { + return metaMethod.invoke(criteria, args); + } + metaMethod = criteriaMetaClass.getMetaMethod(NameUtils.getSetterName(name), args); + if (metaMethod != null) { + return metaMethod.invoke(criteria, args); + } + // if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { // final boolean hasMoreThanOneArg = args.length > 1; // Object callable = hasMoreThanOneArg ? args[1] : args[0]; @@ -1334,50 +1341,51 @@ public Object invokeMethod(String name, Object obj) { // } // } // } -// else if (args.length == 1 && args[0] != null) { -// if (criteria == null) { -// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); -// } -// -// Object value = args[0]; -// Criterion c = null; -// if (name.equals(ID_EQUALS)) { -// return eq("id", value); -// } -// -// if (name.equals(IS_NULL) || -// name.equals(IS_NOT_NULL) || -// name.equals(IS_EMPTY) || -// name.equals(IS_NOT_EMPTY)) { -// if (!(value instanceof String)) { -// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] with value [" + -// value + "] requires a String value.")); -// } -// String propertyName = calculatePropertyName((String)value); -// if (name.equals(IS_NULL)) { -// c = Restrictions.isNull(propertyName); -// } -// else if (name.equals(IS_NOT_NULL)) { -// c = Restrictions.isNotNull(propertyName); -// } -// else if (name.equals(IS_EMPTY)) { -// c = Restrictions.isEmpty(propertyName); -// } -// else if (name.equals(IS_NOT_EMPTY)) { -// c = Restrictions.isNotEmpty(propertyName); -// } -// } -// -// if (c != null) { -// return addToCriteria(c); -// } -// } + else if (args.length == 1 && args[0] != null) { + if (criteria == null) { + throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); + } + + Object value = args[0]; + Query.Criterion c = null; + if (name.equals(ID_EQUALS)) { + return eq("id", value); + } + + if (name.equals(IS_NULL) || + name.equals(IS_NOT_NULL) || + name.equals(IS_EMPTY) || + name.equals(IS_NOT_EMPTY)) { + if (!(value instanceof String)) { + throwRuntimeException(new IllegalArgumentException("call to [" + name + "] with value [" + + value + "] requires a String value.")); + } + String propertyName = calculatePropertyName((String)value); + if (name.equals(IS_NULL)) { + c = Restrictions.isNull(propertyName); + } + else if (name.equals(IS_NOT_NULL)) { + c = Restrictions.isNotNull(propertyName); + } + else if (name.equals(IS_EMPTY)) { + c = Restrictions.isEmpty(propertyName); + } + else if (name.equals(IS_NOT_EMPTY)) { + c = Restrictions.isNotEmpty(propertyName); + } + } + + if (c != null) { + return addToCriteria(c); + } + } throw new MissingMethodException(name, getClass(), args); } + protected abstract List createPagedResultList(Map args); @@ -1434,7 +1442,20 @@ private void invokeClosureNode(Object args) { } - + /** + * adds and returns the given criterion to the currently active criteria set. + * this might be either the root criteria or a currently open + * LogicalExpression. + */ + protected Query.Criterion addToCriteria(Query.Criterion c) { + if (false) { +// logicalExpressionStack.get(logicalExpressionStack.size() - 1).args.add(c); + } + else { + junction.add(c); + } + return c; + } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index c8b1e5d5dcc..25e07f36456 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -14,6 +14,7 @@ */ package org.grails.orm.hibernate.query; +import groovy.util.logging.Slf4j; import jakarta.persistence.FetchType; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.JoinType; @@ -51,6 +52,7 @@ * @since 1.0 */ @SuppressWarnings("rawtypes") +@Slf4j public abstract class AbstractHibernateQuery extends Query { public static final String SIZE_CONSTRAINT_PREFIX = "Size"; @@ -62,7 +64,6 @@ public abstract class AbstractHibernateQuery extends Query { protected Root root; protected CriteriaQuery criteriaQuery; - protected AbstractHibernateQuery.HibernateProjectionList hibernateProjectionList; protected String alias; protected int aliasCount; protected Map createdAssociationPaths = new HashMap(); @@ -349,21 +350,6 @@ private SqmJoinType resolveJoinType(JoinType joinType) { } } - @Override - public Query max(int max) { - return this; - } - - @Override - public Query maxResults(int max) { - return this; - } - - @Override - public Query offset(int offset) { - return this; - } - @Override public Query firstResult(int offset) { offset(offset); @@ -402,9 +388,7 @@ public Query select(String property) { @Override public List list() { - org.hibernate.query.Query query = getQuery(); - System.out.println(query.getQueryString()); - return query.getResultList(); + return getQuery().getResultList(); } @@ -432,34 +416,45 @@ private static Predicate combinePredicates(Predicate... predicates) { } private org.hibernate.query.Query getQuery() { + HibernateCriteriaBuilder cb = getCriteriaBuilder(); List projections = projections() .getProjectionList() .stream() .filter(combinePredicates(projectionPredicates)).toList(); if (projections.size() == 1 && projections.get(0) instanceof CountProjection) { - criteriaQuery = getCriteriaBuilder().createQuery(Long.class); + criteriaQuery = cb.createQuery(Long.class); root = criteriaQuery.from(entity.getJavaClass()); - criteriaQuery.select(getCriteriaBuilder().count(root)); + criteriaQuery.select(cb.count(root)); } else { - criteriaQuery = getCriteriaBuilder().createQuery(entity.getJavaClass()); + criteriaQuery = cb.createQuery(entity.getJavaClass()); root = criteriaQuery.from(entity.getJavaClass()); criteriaQuery.select(root); } List predicates = this.criteria.getCriteria().stream(). map(criterion -> { - if (criterion instanceof IsNotNull isNotNull) { - return getCriteriaBuilder().isNotNull(root.get(isNotNull.getProperty())); + if (criterion instanceof IsNotNull c) { + return cb.isNotNull(root.get(c.getProperty())); + } else if (criterion instanceof Equals c ) { + return cb.equal(root.get(c.getProperty()),c.getValue()); } return null; }).filter(Objects::nonNull).toList(); - criteriaQuery.where(getCriteriaBuilder().and(predicates.toArray(new JpaPredicate[0]))); - return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory().getCurrentSession().createQuery(criteriaQuery); + criteriaQuery.where(cb.and(predicates.toArray(new JpaPredicate[0]))); + return getSessionFactory() + .getCurrentSession() + .createQuery(criteriaQuery) + .setMaxResults(this.max) + .setFirstResult(this.offset); + } + + private SessionFactory getSessionFactory() { + return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory(); } private HibernateCriteriaBuilder getCriteriaBuilder() { - return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory().getCriteriaBuilder(); + return getSessionFactory().getCriteriaBuilder(); } @@ -483,87 +478,6 @@ protected String generateAlias(String associationName) { } - - - - - protected class HibernateProjectionList extends ProjectionList { - - private boolean rowCount = false; - - public boolean isRowCount() { - return rowCount; - } - - @Override - public boolean isEmpty() { - return true; - } - - - @Override - public ProjectionList add(Projection p) { - return this; - } - - @Override - public org.grails.datastore.mapping.query.api.ProjectionList countDistinct(String property) { - return this; - } - - @Override - public org.grails.datastore.mapping.query.api.ProjectionList distinct(String property) { - return this; - } - - @Override - public org.grails.datastore.mapping.query.api.ProjectionList rowCount() { - this.rowCount = true; - return this; - } - - @Override - public ProjectionList id() { - return this; - } - - @Override - public ProjectionList count() { - this.rowCount = true; - return this; - } - - @Override - public ProjectionList property(String name) { - return this; - } - - @Override - public ProjectionList sum(String name) { - return this; - } - - @Override - public ProjectionList min(String name) { - return this; - } - - @Override - public ProjectionList max(String name) { - return this; - } - - @Override - public ProjectionList avg(String name) { - return this; - } - - @Override - public ProjectionList distinct() { - return this; - } - } - protected class HibernateAssociationQuery extends AssociationQuery { protected String alias; diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy index f07eff4b8c9..d8ae2b0f1fe 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy @@ -2,6 +2,7 @@ package grails.gorm.tests import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity +import grails.gorm.hibernate.HibernateEntity import grails.gorm.transactions.Rollback import grails.gorm.transactions.Transactional import org.grails.datastore.mapping.query.Query @@ -24,10 +25,10 @@ class DetachedCriteriaProjectionSpec extends Specification { def setup() { DetachedEntity.findAll().each { it.delete() } Entity1.findAll().each { it.delete(flush: true) } - final entity1 = new Entity1(id: 1, field1: 'Correct').save() - new Entity1(id: 2, field1: 'Incorrect').save() - new DetachedEntity(id: 1, entityId: entity1.id, field: 'abc').save() - new DetachedEntity(id: 2, entityId: entity1.id, field: 'def').save() + final entity1 = new Entity1(id: 1, field1: 'Correct', version: 0).save() + new Entity1(id: 2, field1: 'Incorrect', version: 0).save() + new DetachedEntity(id: 1, entityId: entity1.id, field: 'abc', version: 0).save() + new DetachedEntity(id: 2, entityId: entity1.id, field: 'def', version: 0).save() } @Rollback @@ -83,18 +84,18 @@ class DetachedCriteriaProjectionSpec extends Specification { } @Entity -public class Entity1 { +public class Entity1 implements HibernateEntity { Long id String field1 static hasMany = [children : Entity2] } @Entity -class Entity2 { +class Entity2 implements HibernateEntity { static belongsTo = [parent: Entity1] String field } @Entity -class DetachedEntity { +class DetachedEntity implements HibernateEntity { Long entityId String field } \ No newline at end of file From 6ed21f924fe28532c4477fea095bd0cb3aead747 Mon Sep 17 00:00:00 2001 From: estradaw Date: Thu, 16 Jan 2025 23:27:50 -0600 Subject: [PATCH 0004/1008] DetachedCriteria in clause --- .../grails/orm/HibernateCriteriaBuilder.java | 36 ++++- .../AbstractHibernateCriteriaBuilder.java | 146 +++++++++++------- .../DetachedCriteriaProjectionSpec.groovy | 8 +- 3 files changed, 125 insertions(+), 65 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java index 110563d6941..9ac65d95217 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java @@ -15,25 +15,28 @@ */ package grails.orm; +import grails.gorm.DetachedCriteria; import groovy.lang.GroovySystem; import jakarta.persistence.metamodel.Attribute; import jakarta.persistence.metamodel.PluralAttribute; -import org.grails.datastore.mapping.query.api.Criteria; +import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.orm.hibernate.GrailsHibernateTemplate; import org.grails.orm.hibernate.HibernateDatastore; import org.grails.orm.hibernate.query.AbstractHibernateCriteriaBuilder; +import org.grails.orm.hibernate.query.AbstractHibernateQuery; +import org.grails.orm.hibernate.query.HibernateQuery; import org.hibernate.SessionFactory; import org.hibernate.type.BasicTypeReference; import org.hibernate.type.StandardBasicTypes; import org.springframework.orm.hibernate5.SessionHolder; import org.springframework.transaction.support.TransactionSynchronizationManager; +import org.grails.datastore.mapping.query.api.QueryableCriteria; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; -import java.net.URL; import java.sql.Blob; import java.sql.Clob; import java.util.Calendar; @@ -154,12 +157,37 @@ protected void createCriteriaInstance() { else { hibernateSession = sessionFactory.openSession(); } - criteria = hibernateSession.getCriteriaBuilder().createQuery(targetClass); + criteriaQuery = hibernateSession.getCriteriaBuilder().createQuery(targetClass); + root = criteriaQuery.from(targetClass); cacheCriteriaMapping(); - criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteria.getClass()); + criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteriaQuery.getClass()); } } + protected DetachedCriteria convertToHibernateCriteria(QueryableCriteria queryableCriteria) { + return getHibernateDetachedCriteria(new HibernateQuery(null, queryableCriteria.getPersistentEntity()), queryableCriteria); + } + + public static DetachedCriteria getHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria) { + String alias = queryableCriteria.getAlias(); + return getHibernateDetachedCriteria(query, queryableCriteria, alias); + } + + public static DetachedCriteria getHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria, String alias) { + PersistentEntity persistentEntity = queryableCriteria.getPersistentEntity(); + DetachedCriteria detachedCriteria = new DetachedCriteria(persistentEntity.getJavaClass()); + + populateHibernateDetachedCriteria(new HibernateQuery(null,persistentEntity), detachedCriteria, queryableCriteria); + return detachedCriteria; + } + + private static void populateHibernateDetachedCriteria(AbstractHibernateQuery query, DetachedCriteria detachedCriteria, QueryableCriteria queryableCriteria) { + List criteriaList = queryableCriteria.getCriteria(); + for (org.grails.datastore.mapping.query.Query.Criterion criterion : criteriaList) { + detachedCriteria.add(criterion); + } + } + protected void cacheCriteriaMapping() { } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 0f7319902de..0ec38241f53 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -1,5 +1,6 @@ package org.grails.orm.hibernate.query; +import grails.gorm.DetachedCriteria; import grails.gorm.MultiTenant; import groovy.lang.Closure; import groovy.lang.DelegatesTo; @@ -9,9 +10,10 @@ import groovy.lang.MissingMethodException; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.Attribute; -import jakarta.persistence.metamodel.EntityType; import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.Restrictions; @@ -21,25 +23,25 @@ import org.grails.datastore.mapping.reflect.NameUtils; import org.grails.orm.hibernate.AbstractHibernateDatastore; import org.hibernate.FetchMode; -import org.hibernate.HibernateException; -import org.hibernate.Metamodel; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.query.criteria.HibernateCriteriaBuilder; +import org.hibernate.query.criteria.JpaPredicate; +import org.hibernate.query.criteria.JpaRoot; import org.hibernate.transform.ResultTransformer; -import org.hibernate.type.Type; import org.springframework.beans.BeanUtils; import org.springframework.core.convert.ConversionService; -import org.grails.datastore.mapping.query.api.Criteria; import org.grails.datastore.mapping.query.api.ProjectionList; import java.beans.PropertyDescriptor; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; /** * Abstract super class for sharing code between Hibernate 3 and 4 implementations of HibernateCriteriaBuilder @@ -92,7 +94,7 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected Session hibernateSession; protected Class targetClass; protected Query.Junction junction = new Query.Conjunction(); - protected CriteriaQuery criteria; + protected CriteriaQuery criteriaQuery; protected MetaClass criteriaMetaClass; protected boolean uniqueResult = false; protected List logicalExpressionStack = new ArrayList(); @@ -112,14 +114,15 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected AbstractHibernateDatastore datastore; protected HibernateCriteriaBuilder cb; protected Root root; + protected Subquery subquery; @SuppressWarnings("rawtypes") public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory) { this.targetClass = targetClass; this.sessionFactory = sessionFactory; this.cb = sessionFactory.getCriteriaBuilder(); - this.criteria = cb.createQuery(targetClass); - this.root = criteria.from(targetClass); + this.criteriaQuery = cb.createQuery(targetClass); + this.root = criteriaQuery.from(targetClass); } @SuppressWarnings("rawtypes") @@ -128,8 +131,8 @@ public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessio this.sessionFactory = sessionFactory; this.uniqueResult = uniqueResult; this.cb = sessionFactory.getCriteriaBuilder(); - this.criteria = cb.createQuery(targetClass); - this.root = criteria.from(targetClass); + this.criteriaQuery = cb.createQuery(targetClass); + this.root = criteriaQuery.from(targetClass); } public void setDatastore(AbstractHibernateDatastore datastore) { @@ -157,7 +160,7 @@ public ProjectionList property(String propertyName) { * @param alias The alias to use */ public ProjectionList property(String propertyName, String alias) { - criteria.select(root.get(propertyName)); + criteriaQuery.select(root.get(propertyName)); return this; } @@ -176,7 +179,7 @@ public ProjectionList distinct(String propertyName) { * @param alias The alias to use */ public ProjectionList distinct(String propertyName, String alias) { - criteria.select(root.get(propertyName)).distinct(true); + projectionList.distinct(propertyName); return this; } @@ -287,6 +290,7 @@ protected Object calculatePropertyValue(Object propertyValue) { return propertyValue; } + protected abstract DetachedCriteria convertToHibernateCriteria(QueryableCriteria queryableCriteria); /** * Adds a projection that allows the criteria to return the property count @@ -648,17 +652,18 @@ public Criteria in(String propertyName, QueryableCriteria subquery) { @Override public Criteria inList(String propertyName, QueryableCriteria subquery) { + addToCriteria(Restrictions.in(propertyName, subquery)); return this; } @Override public Criteria in(String propertyName, Closure subquery) { - return inList(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(subquery)); + return inList(propertyName, new DetachedCriteria(targetClass).build(subquery)); } @Override public Criteria inList(String propertyName, Closure subquery) { - return inList(propertyName, new grails.gorm.DetachedCriteria(targetClass).build(subquery)); + return inList(propertyName, new DetachedCriteria(targetClass).build(subquery)); } @Override @@ -1094,7 +1099,7 @@ public Criteria gte(String s, Object o) { } protected boolean validateSimpleExpression() { - return criteria != null; + return criteriaQuery != null; } @Override @@ -1121,6 +1126,29 @@ public Object get(@DelegatesTo(Criteria.class) Closure c) { public Object scroll(@DelegatesTo(Criteria.class) Closure c) { return invokeMethod(SCROLL_CALL, new Object[]{c}); } + + protected Predicate[] getPredicates(Root root_ , List criteriaList) { + return criteriaList.stream(). + map(criterion -> { + if (criterion instanceof Query.IsNotNull c) { + return cb.isNotNull(root_.get(c.getProperty())); + } else if (criterion instanceof Query.Equals c ) { + return cb.equal(root_.get(c.getProperty()),c.getValue()); + } else if (criterion instanceof Query.In c + && c.getSubquery().getProjections().size() == 1 + && c.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection + ) { + Query.PropertyProjection projection = (Query.PropertyProjection) c.getSubquery().getProjections().get(0); + boolean distinct = projection instanceof Query.DistinctPropertyProjection; + subquery = criteriaQuery.subquery(Long.class); + Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); + Predicate[] predicates = getPredicates(from, c.getSubquery().getCriteria()); + subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); + return cb.in(root_.get(c.getProperty())).value(subquery); + } + return null; + }).filter(Objects::nonNull).toList().toArray(new Predicate[0]); + } @SuppressWarnings("rawtypes") @Override @@ -1134,9 +1162,9 @@ public Object invokeMethod(String name, Object obj) { } if (isCriteriaConstructionMethod(name, args)) { - if (criteria != null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } +// if (criteria != null) { +// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); +// } if (name.equals(GET_CALL)) { uniqueResult = true; @@ -1166,16 +1194,19 @@ else if (name.equals(COUNT_CALL)) { // criteria.setResultTransformer(resultTransformer); // } Object result; - org.hibernate.query.Query query = hibernateSession.createQuery(criteria); if (!uniqueResult) { - if (scroll) { - - result = query.scroll(); + root = criteriaQuery.from(this.targetClass); + criteriaQuery.select(root); + criteriaQuery.where(cb.and(getPredicates(root, this.junction.getCriteria()))); + result = hibernateSession.createQuery(criteriaQuery).scroll(); } else if (count) { - criteria.select(cb.count(root)); - result = query.getSingleResult(); + criteriaQuery = cb.createQuery(Long.class); + root = criteriaQuery.from(this.targetClass); + criteriaQuery.select(cb.count(root)); + criteriaQuery.where(cb.and(getPredicates(root,this.junction.getCriteria()))); + result = hibernateSession.createQuery(criteriaQuery).getSingleResult(); } // else if (paginationEnabledList) { // // Calculate how many results there are in total. This has been @@ -1232,11 +1263,20 @@ else if (count) { // result = createPagedResultList(argMap); // } else { - result = query.list(); + String queryString = "select e2_0.id,e2_0.field1,e2_0.version from entity1 e1_0,entity1 e2_0 where e2_0.id in (select distinct de1_0.entity_id from detached_entity de1_0 where de1_0.field='abc') "; + List resultList = hibernateSession.createNativeQuery(queryString, targetClass).getResultList(); + root = criteriaQuery.from(this.targetClass); + criteriaQuery.select(root); + + criteriaQuery.where(cb.and(getPredicates(root, this.junction.getCriteria()))); + result = hibernateSession.createQuery(criteriaQuery).list(); } } else { - result = query.uniqueResult(); + root = criteriaQuery.from(this.targetClass); + criteriaQuery.select(root); + criteriaQuery.where(cb.and(getPredicates(root, this.junction.getCriteria()))); + result = hibernateSession.createQuery(criteriaQuery).uniqueResult(); } if (!participate) { closeSession(); @@ -1244,7 +1284,7 @@ else if (count) { return result; } - if (criteria == null) createCriteriaInstance(); + if (criteriaQuery == null) createCriteriaInstance(); MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args); if (metaMethod != null) { @@ -1253,18 +1293,18 @@ else if (count) { metaMethod = criteriaMetaClass.getMetaMethod(name, args); if (metaMethod != null) { - return metaMethod.invoke(criteria, args); + return metaMethod.invoke(criteriaQuery, args); } metaMethod = criteriaMetaClass.getMetaMethod(NameUtils.getSetterName(name), args); if (metaMethod != null) { - return metaMethod.invoke(criteria, args); + return metaMethod.invoke(criteriaQuery, args); } -// if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { -// final boolean hasMoreThanOneArg = args.length > 1; -// Object callable = hasMoreThanOneArg ? args[1] : args[0]; + if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { + final boolean hasMoreThanOneArg = args.length > 1; + Object callable = hasMoreThanOneArg ? args[1] : args[0]; // int joinType = hasMoreThanOneArg ? (Integer)args[0] : org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue(); -// + // if (name.equals(AND) || name.equals(OR) || name.equals(NOT)) { // if (criteria == null) { // throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); @@ -1278,22 +1318,22 @@ else if (count) { // // return name; // } -// -// if (name.equals(PROJECTIONS) && args.length == 1 && (args[0] instanceof Closure)) { + + if (name.equals(PROJECTIONS) && args.length == 1 && (args[0] instanceof Closure)) { // if (criteria == null) { // throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); // } -// -// projectionList = Projections.projectionList(); -// invokeClosureNode(callable); -// + + projectionList = new Query.ProjectionList(); + invokeClosureNode(callable); + // if (projectionList != null && projectionList.getLength() > 0) { // criteria.setProjection(projectionList); // } -// -// return name; -// } -// + + return name; + } + // final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(targetClass, name); // if (pd != null && pd.getReadMethod() != null) { // final Metamodel metamodel = sessionFactory.getMetamodel(); @@ -1340,18 +1380,16 @@ else if (count) { // return name; // } // } -// } + } else if (args.length == 1 && args[0] != null) { - if (criteria == null) { - throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); - } - +// if (criteriaQuery == null) { +// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); +// } Object value = args[0]; Query.Criterion c = null; if (name.equals(ID_EQUALS)) { return eq("id", value); } - if (name.equals(IS_NULL) || name.equals(IS_NOT_NULL) || name.equals(IS_EMPTY) || @@ -1374,18 +1412,14 @@ else if (name.equals(IS_NOT_EMPTY)) { c = Restrictions.isNotEmpty(propertyName); } } - if (c != null) { return addToCriteria(c); } } - throw new MissingMethodException(name, getClass(), args); } - - protected abstract List createPagedResultList(Map args); @@ -1398,8 +1432,6 @@ private boolean isAssociationQueryWithJoinSpecificationMethod(Object[] args) { } - - private String getAssociationPath() { StringBuilder fullPath = new StringBuilder(); for (Object anAssociationStack : associationStack) { @@ -1464,7 +1496,7 @@ protected Query.Criterion addToCriteria(Query.Criterion c) { * @return The criteria instance */ public CriteriaQuery getInstance() { - return criteria; + return criteriaQuery; } /** @@ -1504,7 +1536,7 @@ protected void throwRuntimeException(RuntimeException t) { private void closeSessionFollowingException() { closeSession(); - criteria = null; + criteriaQuery = null; } /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy index d8ae2b0f1fe..f9814bcace0 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy @@ -25,10 +25,10 @@ class DetachedCriteriaProjectionSpec extends Specification { def setup() { DetachedEntity.findAll().each { it.delete() } Entity1.findAll().each { it.delete(flush: true) } - final entity1 = new Entity1(id: 1, field1: 'Correct', version: 0).save() - new Entity1(id: 2, field1: 'Incorrect', version: 0).save() - new DetachedEntity(id: 1, entityId: entity1.id, field: 'abc', version: 0).save() - new DetachedEntity(id: 2, entityId: entity1.id, field: 'def', version: 0).save() + final entity1 = new Entity1(field1: 'Correct').save() + new Entity1(field1: 'Incorrect', version: 0).save() + new DetachedEntity(entityId: entity1.id, field: 'abc').save() + new DetachedEntity(entityId: entity1.id, field: 'def').save() } @Rollback From 6e1714ed57d3d1927a6f3a0d42512e8c9776ff0b Mon Sep 17 00:00:00 2001 From: Walter B Duque de Estrada Date: Fri, 17 Jan 2025 13:18:35 -0600 Subject: [PATCH 0005/1008] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8572b6441bc..5d910fef151 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# GORM for Hibernate 5 +# GORM for Hibernate 6 [![Maven Central](https://img.shields.io/maven-central/v/org.grails/grails-datastore-gorm-hibernate5.svg?label=Maven%20Central)](https://central.sonatype.com/artifact/org.grails/grails-datastore-gorm-hibernate5) [![Java CI](https://github.com/grails/gorm-hibernate5/workflows/Java%20CI/badge.svg?event=push)](https://github.com/grails/gorm-hibernate5/actions/workflows/gradle.yml) This project implements [GORM](https://gorm.grails.org) for the Hibernate 5. @@ -11,4 +11,4 @@ For more information see the following links: For the current development version see the following links: * [Development Snapshot Documentation](https://gorm.grails.org/snapshot/hibernate/manual) -* [Development Snapshot API Reference](https://gorm.grails.org/snapshot/hibernate/api) \ No newline at end of file +* [Development Snapshot API Reference](https://gorm.grails.org/snapshot/hibernate/api) From 1a43542e8c9172f08f5ed07af5baba2217bbed14 Mon Sep 17 00:00:00 2001 From: Walter B Duque de Estrada Date: Fri, 17 Jan 2025 13:19:03 -0600 Subject: [PATCH 0006/1008] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5d910fef151..4a2deee0633 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # GORM for Hibernate 6 [![Maven Central](https://img.shields.io/maven-central/v/org.grails/grails-datastore-gorm-hibernate5.svg?label=Maven%20Central)](https://central.sonatype.com/artifact/org.grails/grails-datastore-gorm-hibernate5) [![Java CI](https://github.com/grails/gorm-hibernate5/workflows/Java%20CI/badge.svg?event=push)](https://github.com/grails/gorm-hibernate5/actions/workflows/gradle.yml) -This project implements [GORM](https://gorm.grails.org) for the Hibernate 5. +This project implements [GORM](https://gorm.grails.org) for the Hibernate 6. For more information see the following links: From 4c94020bfb388d5d744d4920971eb32d4026f3b1 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 22 Jan 2025 17:05:02 -0600 Subject: [PATCH 0007/1008] Refactor Predicate Generation since it shared logic. --- .../AbstractHibernateCriteriaBuilder.java | 41 ++------------- .../query/AbstractHibernateQuery.java | 23 ++++---- .../orm/hibernate/query/HibernateQuery.java | 20 ++++++- .../hibernate/query/PredicateGenerator.java | 38 ++++++++++++++ settings.gradle | 52 +++++++++---------- 5 files changed, 99 insertions(+), 75 deletions(-) create mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 0ec38241f53..6c98248f5bd 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -10,7 +10,6 @@ import groovy.lang.MissingMethodException; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.JoinType; -import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.Attribute; @@ -26,22 +25,16 @@ import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.query.criteria.HibernateCriteriaBuilder; -import org.hibernate.query.criteria.JpaPredicate; -import org.hibernate.query.criteria.JpaRoot; import org.hibernate.transform.ResultTransformer; -import org.springframework.beans.BeanUtils; import org.springframework.core.convert.ConversionService; import org.grails.datastore.mapping.query.api.ProjectionList; -import java.beans.PropertyDescriptor; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; /** * Abstract super class for sharing code between Hibernate 3 and 4 implementations of HibernateCriteriaBuilder @@ -1127,29 +1120,6 @@ public Object scroll(@DelegatesTo(Criteria.class) Closure c) { return invokeMethod(SCROLL_CALL, new Object[]{c}); } - protected Predicate[] getPredicates(Root root_ , List criteriaList) { - return criteriaList.stream(). - map(criterion -> { - if (criterion instanceof Query.IsNotNull c) { - return cb.isNotNull(root_.get(c.getProperty())); - } else if (criterion instanceof Query.Equals c ) { - return cb.equal(root_.get(c.getProperty()),c.getValue()); - } else if (criterion instanceof Query.In c - && c.getSubquery().getProjections().size() == 1 - && c.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection - ) { - Query.PropertyProjection projection = (Query.PropertyProjection) c.getSubquery().getProjections().get(0); - boolean distinct = projection instanceof Query.DistinctPropertyProjection; - subquery = criteriaQuery.subquery(Long.class); - Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(from, c.getSubquery().getCriteria()); - subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); - return cb.in(root_.get(c.getProperty())).value(subquery); - } - return null; - }).filter(Objects::nonNull).toList().toArray(new Predicate[0]); - } - @SuppressWarnings("rawtypes") @Override public Object invokeMethod(String name, Object obj) { @@ -1198,14 +1168,14 @@ else if (name.equals(COUNT_CALL)) { if (scroll) { root = criteriaQuery.from(this.targetClass); criteriaQuery.select(root); - criteriaQuery.where(cb.and(getPredicates(root, this.junction.getCriteria()))); + criteriaQuery.where(cb.and(PredicateGenerator.getPredicates(cb, criteriaQuery, root, this.junction.getCriteria()))); result = hibernateSession.createQuery(criteriaQuery).scroll(); } else if (count) { criteriaQuery = cb.createQuery(Long.class); root = criteriaQuery.from(this.targetClass); criteriaQuery.select(cb.count(root)); - criteriaQuery.where(cb.and(getPredicates(root,this.junction.getCriteria()))); + criteriaQuery.where(cb.and(PredicateGenerator.getPredicates(cb, criteriaQuery, root,this.junction.getCriteria()))); result = hibernateSession.createQuery(criteriaQuery).getSingleResult(); } // else if (paginationEnabledList) { @@ -1263,19 +1233,16 @@ else if (count) { // result = createPagedResultList(argMap); // } else { - String queryString = "select e2_0.id,e2_0.field1,e2_0.version from entity1 e1_0,entity1 e2_0 where e2_0.id in (select distinct de1_0.entity_id from detached_entity de1_0 where de1_0.field='abc') "; - List resultList = hibernateSession.createNativeQuery(queryString, targetClass).getResultList(); root = criteriaQuery.from(this.targetClass); criteriaQuery.select(root); - - criteriaQuery.where(cb.and(getPredicates(root, this.junction.getCriteria()))); + criteriaQuery.where(cb.and(PredicateGenerator.getPredicates(cb, criteriaQuery, root, this.junction.getCriteria()))); result = hibernateSession.createQuery(criteriaQuery).list(); } } else { root = criteriaQuery.from(this.targetClass); criteriaQuery.select(root); - criteriaQuery.where(cb.and(getPredicates(root, this.junction.getCriteria()))); + criteriaQuery.where(cb.and(PredicateGenerator.getPredicates(cb, criteriaQuery, root, this.junction.getCriteria()))); result = hibernateSession.createQuery(criteriaQuery).uniqueResult(); } if (!participate) { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 25e07f36456..f35544becee 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -76,6 +76,7 @@ public abstract class AbstractHibernateQuery extends Query { protected AbstractHibernateQuery(CriteriaQuery criteriaQuery, AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); + this.criteriaQuery = criteriaQuery; if(entity != null) { initializeJoinStatus(); } @@ -350,6 +351,8 @@ private SqmJoinType resolveJoinType(JoinType joinType) { } } + + @Override public Query firstResult(int offset) { offset(offset); @@ -400,7 +403,12 @@ protected void flushBeforeQuery() { @Override public Object singleResult() { - return getQuery().getSingleResult(); + try { + return getQuery().getSingleResult(); + } + catch (jakarta.persistence.NoResultException e) { + return null; + } } private final Predicate countProjectionPredicate = projection -> projection instanceof CountProjection; @@ -431,17 +439,10 @@ private org.hibernate.query.Query getQuery() { criteriaQuery.select(root); } - List predicates = this.criteria.getCriteria().stream(). - map(criterion -> { - if (criterion instanceof IsNotNull c) { - return cb.isNotNull(root.get(c.getProperty())); - } else if (criterion instanceof Equals c ) { - return cb.equal(root.get(c.getProperty()),c.getValue()); - } - return null; - }).filter(Objects::nonNull).toList(); + jakarta.persistence.criteria.Predicate[] predicates = + PredicateGenerator.getPredicates(cb, criteriaQuery, root, this.criteria.getCriteria()); - criteriaQuery.where(cb.and(predicates.toArray(new JpaPredicate[0]))); + criteriaQuery.where(cb.and(predicates)); return getSessionFactory() .getCurrentSession() .createQuery(criteriaQuery) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index 4e6476afb00..737815ced45 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -21,9 +21,14 @@ import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.orm.hibernate.GrailsHibernateTemplate; +import org.grails.orm.hibernate.HibernateSession; import org.hibernate.SessionFactory; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.persister.entity.PropertyMapping; +import org.hibernate.query.criteria.JpaCriteriaQuery; + +import java.util.Iterator; /** * Bridges the Query API with the Hibernate Criteria API @@ -58,6 +63,19 @@ public CriteriaQuery getHibernateCriteria() { return this.criteriaQuery; } - + @Override + public Object clone() { + final HibernateSession hibernateSession = (HibernateSession) getSession(); + final GrailsHibernateTemplate hibernateTemplate = (GrailsHibernateTemplate) hibernateSession.getNativeInterface(); + return hibernateTemplate.execute((GrailsHibernateTemplate.HibernateCallback) session -> { + JpaCriteriaQuery newCriteria = session.getCriteriaBuilder().createQuery(entity.getJavaClass()); + HibernateQuery hibernateQuery = new HibernateQuery(newCriteria, hibernateSession, entity); + hibernateQuery.max(this.max); + hibernateQuery.offset(this.offset); + this.projections.getProjectionList().forEach(projection -> {hibernateQuery.projections().add(projection);});; + getCriteria().getCriteria().forEach(hibernateQuery::add); + return hibernateQuery; + }); + } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java new file mode 100644 index 00000000000..e527fb52e06 --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -0,0 +1,38 @@ +package org.grails.orm.hibernate.query; + +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.criteria.Subquery; +import org.grails.datastore.mapping.query.Query; +import org.hibernate.query.criteria.HibernateCriteriaBuilder; + +import java.util.List; +import java.util.Objects; + +public class PredicateGenerator { + public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, Root root_ , List criteriaList) { + return criteriaList.stream(). + map(criterion -> { + if (criterion instanceof Query.IsNotNull c) { + return cb.isNotNull(root_.get(c.getProperty())); + } else if (criterion instanceof Query.Equals c ) { + return cb.equal(root_.get(c.getProperty()),c.getValue()); + } else if (criterion instanceof Query.Like c ) { + return cb.like(root_.get(c.getProperty()),c.getValue().toString()); + } else if (criterion instanceof Query.In c + && c.getSubquery().getProjections().size() == 1 + && c.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection + ) { + Query.PropertyProjection projection = (Query.PropertyProjection) c.getSubquery().getProjections().get(0); + boolean distinct = projection instanceof Query.DistinctPropertyProjection; + Subquery subquery = criteriaQuery.subquery(Long.class); + Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); + subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); + return cb.in(root_.get(c.getProperty())).value(subquery); + } + return null; + }).filter(Objects::nonNull).toList().toArray(new Predicate[0]); + } +} diff --git a/settings.gradle b/settings.gradle index e5c7f7a5bf7..5045646bb70 100644 --- a/settings.gradle +++ b/settings.gradle @@ -34,38 +34,38 @@ findProject(':grails-datastore-gorm-hibernate').name = 'grails-datastore-gorm-hi include 'docs' // Plugins -include "boot-plugin" -include 'grails-plugin' - -include "examples-grails-hibernate" -project(":examples-grails-hibernate").projectDir = new File(settingsDir, "examples/grails-hibernate") - -include "examples-grails-multiple-datasources" -project(":examples-grails-multiple-datasources").projectDir = new File(settingsDir, "examples/grails-multiple-datasources") - -include "examples-grails-database-per-tenant" -project(":examples-grails-database-per-tenant").projectDir = new File(settingsDir, "examples/grails-database-per-tenant") - -include "examples-grails-schema-per-tenant" -project(":examples-grails-schema-per-tenant").projectDir = new File(settingsDir, "examples/grails-schema-per-tenant") +//include "boot-plugin" +//include 'grails-plugin' +// +//include "examples-grails-hibernate" +//project(":examples-grails-hibernate").projectDir = new File(settingsDir, "examples/grails-hibernate") +// +//include "examples-grails-multiple-datasources" +//project(":examples-grails-multiple-datasources").projectDir = new File(settingsDir, "examples/grails-multiple-datasources") +// +//include "examples-grails-database-per-tenant" +//project(":examples-grails-database-per-tenant").projectDir = new File(settingsDir, "examples/grails-database-per-tenant") +// +//include "examples-grails-schema-per-tenant" +//project(":examples-grails-schema-per-tenant").projectDir = new File(settingsDir, "examples/grails-schema-per-tenant") //include "examples-grails-partitioned-multi-tenancy" //project(":examples-grails-partitioned-multi-tenancy").projectDir = new File(settingsDir, "examples/grails-partitioned-multi-tenancy") -include "examples-standalone-hibernate" -project(":examples-standalone-hibernate").projectDir = new File(settingsDir, "examples/standalone-hibernate") - -include "examples-spring-boot-hibernate" -project(":examples-spring-boot-hibernate").projectDir = new File(settingsDir, "examples/spring-boot-hibernate") - -include "examples-grails-data-service" -project(":examples-grails-data-service").projectDir = new File(settingsDir, "examples/grails-data-service") +//include "examples-standalone-hibernate" +//project(":examples-standalone-hibernate").projectDir = new File(settingsDir, "examples/standalone-hibernate") +// +//include "examples-spring-boot-hibernate" +//project(":examples-spring-boot-hibernate").projectDir = new File(settingsDir, "examples/spring-boot-hibernate") +// +//include "examples-grails-data-service" +//project(":examples-grails-data-service").projectDir = new File(settingsDir, "examples/grails-data-service") //include "examples-grails-hibernate-groovy-proxy" //project(":examples-grails-hibernate-groovy-proxy").projectDir = new File(settingsDir, "examples/grails-hibernate-groovy-proxy") -include 'examples-issue450' -project(':examples-issue450').projectDir = new File(settingsDir, 'examples/issue450') - -findProject(':boot-plugin').name = 'gorm-hibernate5-spring-boot' +//include 'examples-issue450' +//project(':examples-issue450').projectDir = new File(settingsDir, 'examples/issue450') +// +//findProject(':boot-plugin').name = 'gorm-hibernate5-spring-boot' From 58bc53c5f7a943b47d4848f5562266cf90cde026 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Thu, 23 Jan 2025 12:40:37 -0600 Subject: [PATCH 0008/1008] updates to PredicateGenerator --- .../hibernate/query/PredicateGenerator.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index e527fb52e06..6df4fde9d28 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -1,19 +1,42 @@ package org.grails.orm.hibernate.query; +import groovy.util.logging.Slf4j; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; import org.grails.datastore.mapping.query.Query; import org.hibernate.query.criteria.HibernateCriteriaBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.List; import java.util.Objects; +@Slf4j public class PredicateGenerator { + private static final Logger log = LoggerFactory.getLogger(PredicateGenerator.class); + public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, Root root_ , List criteriaList) { + + return criteriaList.stream(). map(criterion -> { + if (criterion instanceof Query.Disjunction) { + List criterionList = ((Query.Disjunction) criterion).getCriteria(); + cb.or(getPredicates(cb,criteriaQuery,root_, criterionList)); + } else if (criterion instanceof Query.Conjunction) { + List criterionList = ((Query.Conjunction) criterion).getCriteria(); + cb.and(getPredicates(cb,criteriaQuery,root_, criterionList)); + } else if (criterion instanceof Query.Negation) { + List criterionList = ((Query.Negation) criterion).getCriteria(); + Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList); + if (predicates.length != 1) { + log.error("Must have a single predicate behind a not"); + throw new RuntimeException("Must have a single predicate behind a not"); + } + cb.not(predicates[0]); + } else if (criterion instanceof Query.IsNotNull c) { return cb.isNotNull(root_.get(c.getProperty())); } else if (criterion instanceof Query.Equals c ) { From 87c7837ec983c814a79b8dc0b9b5da5bb90d1080 Mon Sep 17 00:00:00 2001 From: estradaw Date: Fri, 24 Jan 2025 21:25:18 -0600 Subject: [PATCH 0009/1008] Adding PropertyCriterion to PredicateGenerator --- .../grails/orm/HibernateCriteriaBuilder.java | 40 ++---- .../hibernate/HibernateGormStaticApi.groovy | 14 +- .../orm/hibernate/HibernateSession.java | 3 +- .../query/AbstractHibernateQuery.java | 67 ++++----- .../orm/hibernate/query/HibernateQuery.java | 21 +-- .../hibernate/query/PredicateGenerator.java | 17 ++- .../hibernatequery/HibernateQuerySpec.groovy | 129 ++++++++++++++++++ 7 files changed, 204 insertions(+), 87 deletions(-) create mode 100644 grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java index 9ac65d95217..66b9951ee66 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java @@ -124,14 +124,12 @@ public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory setDefaultFlushMode(GrailsHibernateTemplate.FLUSH_AUTO); } - @SuppressWarnings("rawtypes") - public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, boolean uniqueResult) { - super(targetClass, sessionFactory, uniqueResult); - setDefaultFlushMode(GrailsHibernateTemplate.FLUSH_AUTO); + @Override + protected DetachedCriteria convertToHibernateCriteria(QueryableCriteria queryableCriteria) { + return null; } - protected Class getClassForAssociationType(Attribute type) { if (type instanceof PluralAttribute) { return ((PluralAttribute)type).getElementType().getJavaType(); @@ -164,29 +162,6 @@ protected void createCriteriaInstance() { } } - protected DetachedCriteria convertToHibernateCriteria(QueryableCriteria queryableCriteria) { - return getHibernateDetachedCriteria(new HibernateQuery(null, queryableCriteria.getPersistentEntity()), queryableCriteria); - } - - public static DetachedCriteria getHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria) { - String alias = queryableCriteria.getAlias(); - return getHibernateDetachedCriteria(query, queryableCriteria, alias); - } - - public static DetachedCriteria getHibernateDetachedCriteria(AbstractHibernateQuery query, QueryableCriteria queryableCriteria, String alias) { - PersistentEntity persistentEntity = queryableCriteria.getPersistentEntity(); - DetachedCriteria detachedCriteria = new DetachedCriteria(persistentEntity.getJavaClass()); - - populateHibernateDetachedCriteria(new HibernateQuery(null,persistentEntity), detachedCriteria, queryableCriteria); - return detachedCriteria; - } - - private static void populateHibernateDetachedCriteria(AbstractHibernateQuery query, DetachedCriteria detachedCriteria, QueryableCriteria queryableCriteria) { - List criteriaList = queryableCriteria.getCriteria(); - for (org.grails.datastore.mapping.query.Query.Criterion criterion : criteriaList) { - detachedCriteria.add(criterion); - } - } protected void cacheCriteriaMapping() { @@ -204,4 +179,13 @@ protected void closeSession() { } + @Override + public Object getProperty(String propertyName) { + return super.getProperty(propertyName); + } + + @Override + public void setProperty(String propertyName, Object newValue) { + super.setProperty(propertyName, newValue); + } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy index e71e51a1d64..11303564fe4 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy @@ -16,7 +16,6 @@ package org.grails.orm.hibernate import grails.orm.HibernateCriteriaBuilder -import groovy.transform.CompileDynamic import groovy.transform.CompileStatic import org.grails.datastore.gorm.GormEnhancer import org.grails.datastore.gorm.finders.DynamicFinder @@ -218,17 +217,16 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { @Override protected void firePostQueryEvent(Session session, CriteriaQuery criteria, Object result) { - if(result instanceof List) { - datastore.applicationEventPublisher.publishEvent( new PostQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity), (List)result)) - } - else { - datastore.applicationEventPublisher.publishEvent( new PostQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity), Collections.singletonList(result))) - } + def hibernateQuery = new HibernateQuery(new HibernateSession((HibernateDatastore) datastore, sessionFactory), persistentEntity) + def list = result instanceof List ? (List)result : Collections.singletonList(result) + datastore.applicationEventPublisher.publishEvent( new PostQueryEvent(datastore, hibernateQuery, list)) } @Override protected void firePreQueryEvent(Session session, CriteriaQuery criteria) { - datastore.applicationEventPublisher.publishEvent( new PreQueryEvent(datastore, new HibernateQuery(criteria, persistentEntity))) + def hibernateSession = new HibernateSession((HibernateDatastore) datastore, sessionFactory) + def hibernateQuery = new HibernateQuery(hibernateSession, persistentEntity) + datastore.applicationEventPublisher.publishEvent(new PreQueryEvent(datastore, hibernateQuery)) } @Override diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java index 2e3b1d0770c..8c8f7d5b891 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java @@ -38,7 +38,6 @@ import org.grails.datastore.mapping.query.jpa.JpaQueryInfo; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; import org.hibernate.*; -import org.hibernate.proxy.HibernateProxy; import org.springframework.context.ApplicationEventPublisher; /** @@ -176,7 +175,7 @@ public Query createQuery(Class type, String alias) { GrailsHibernateTemplate hibernateTemplate = getHibernateTemplate(); Session currentSession = hibernateTemplate.getSessionFactory().getCurrentSession(); final CriteriaQuery criteria = currentSession.getCriteriaBuilder().createQuery(type); - return new HibernateQuery(criteria, this, persistentEntity); + return new HibernateQuery(this, persistentEntity); } protected GrailsHibernateTemplate getHibernateTemplate() { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index f35544becee..12e4a730405 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -14,6 +14,7 @@ */ package org.grails.orm.hibernate.query; +import grails.gorm.DetachedCriteria; import groovy.util.logging.Slf4j; import jakarta.persistence.FetchType; import jakarta.persistence.criteria.CriteriaQuery; @@ -30,7 +31,6 @@ import org.hibernate.SessionFactory; import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.query.criteria.HibernateCriteriaBuilder; -import org.hibernate.query.criteria.JpaPredicate; import org.hibernate.query.sqm.tree.SqmJoinType; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; @@ -41,7 +41,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; @@ -61,9 +60,7 @@ public abstract class AbstractHibernateQuery extends Query { protected static ConversionService conversionService = new DefaultConversionService(); private static final Map JOIN_STATUS_CACHE = new ConcurrentHashMap(); - protected Root root; - protected CriteriaQuery criteriaQuery; protected String alias; protected int aliasCount; protected Map createdAssociationPaths = new HashMap(); @@ -72,16 +69,19 @@ public abstract class AbstractHibernateQuery extends Query { protected LinkedList associationStack = new LinkedList(); protected LinkedList aliasInstanceStack = new LinkedList(); private boolean hasJoins = false; + private DetachedCriteria detachedCriteria; - - protected AbstractHibernateQuery(CriteriaQuery criteriaQuery, AbstractHibernateSession session, PersistentEntity entity) { + protected AbstractHibernateQuery(AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); - this.criteriaQuery = criteriaQuery; + this.detachedCriteria = new DetachedCriteria(entity.getJavaClass()); if(entity != null) { initializeJoinStatus(); } } + public void setDetachedCriteria(DetachedCriteria detachedCriteria) { + this.detachedCriteria = detachedCriteria; + } @Override @@ -100,11 +100,6 @@ protected void initializeJoinStatus() { } } - protected AbstractHibernateQuery(CriteriaQuery subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { - this(subCriteria, session, associatedEntity); - alias = newAlias; - } - @Override public Query isEmpty(String property) { return this; @@ -126,8 +121,6 @@ public Query isNotNull(String property) { } - - @Override public PersistentEntity getEntity() { if (!entityStack.isEmpty()) { @@ -180,8 +173,6 @@ static void doTypeConversionIfNeccessary(PersistentEntity entity, PropertyCriter } - - protected abstract PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory); @@ -198,16 +189,19 @@ public Junction negation() { @Override public Query eq(String property, Object value) { + detachedCriteria.eq(property, value); return this; } @Override public Query idEq(Object value) { + detachedCriteria.idEq(value); return this; } @Override public Query gt(String property, Object value) { + detachedCriteria.gt(property, value); return this; } @@ -228,26 +222,31 @@ public Query allEq(Map values) { @Override public Query ge(String property, Object value) { + detachedCriteria.ge(property, value); return this; } @Override public Query le(String property, Object value) { + detachedCriteria.le(property, value); return this; } @Override public Query gte(String property, Object value) { + detachedCriteria.gte(property, value); return this; } @Override public Query lte(String property, Object value) { + detachedCriteria.lte(property, value); return this; } @Override public Query lt(String property, Object value) { + detachedCriteria.lt(property, value); return this; } @@ -263,16 +262,19 @@ public Query between(String property, Object start, Object end) { @Override public Query like(String property, String expr) { + detachedCriteria.like(property, expr); return this; } @Override public Query ilike(String property, String expr) { + detachedCriteria.ilike(property, expr); return this; } @Override public Query rlike(String property, String expr) { + detachedCriteria.rlike(property, expr); return this; } @@ -304,7 +306,7 @@ protected CriteriaAndAlias getCriteriaAndAlias(DetachedAssociationCriteria assoc protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias) { CriteriaAndAlias subCriteria = null; String associationPath = getAssociationPath(associationName); - CriteriaQuery parentCriteria = criteriaQuery; + CriteriaQuery parentCriteria = getCriteriaBuilder().createQuery(entity.getJavaClass()); if(alias == null) { alias = generateAlias(associationName); } @@ -378,14 +380,12 @@ public Query order(Order order) { @Override public Query join(String property) { this.hasJoins = true; - root.join(property); return this; } @Override public Query select(String property) { this.hasJoins = true; - this.criteriaQuery.select(root.get(property)); return this; } @@ -429,25 +429,30 @@ private org.hibernate.query.Query getQuery() { .getProjectionList() .stream() .filter(combinePredicates(projectionPredicates)).toList(); + CriteriaQuery cq; + Root root; if (projections.size() == 1 && projections.get(0) instanceof CountProjection) { - criteriaQuery = cb.createQuery(Long.class); - root = criteriaQuery.from(entity.getJavaClass()); - criteriaQuery.select(cb.count(root)); + cq = cb.createQuery(Long.class); + root = cq.from(entity.getJavaClass()); + cq.select(cb.count(root)); } else { - criteriaQuery = cb.createQuery(entity.getJavaClass()); - root = criteriaQuery.from(entity.getJavaClass()); - criteriaQuery.select(root); + cq = cb.createQuery(entity.getJavaClass()); + root = cq.from(entity.getJavaClass()); + cq.select(root); } + List criteriaList = (List)detachedCriteria.getCriteria(); jakarta.persistence.criteria.Predicate[] predicates = - PredicateGenerator.getPredicates(cb, criteriaQuery, root, this.criteria.getCriteria()); - - criteriaQuery.where(cb.and(predicates)); - return getSessionFactory() + PredicateGenerator.getPredicates(cb, cq, root, criteriaList); + cq.where(cb.and(predicates)); + org.hibernate.query.Query query = getSessionFactory() .getCurrentSession() - .createQuery(criteriaQuery) - .setMaxResults(this.max) + .createQuery(cq) .setFirstResult(this.offset); + if (this.max > -1) { + query.setMaxResults(this.max); + } + return query; } private SessionFactory getSessionFactory() { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index 737815ced45..d7c90fe1b89 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -28,8 +28,6 @@ import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.query.criteria.JpaCriteriaQuery; -import java.util.Iterator; - /** * Bridges the Query API with the Hibernate Criteria API * @@ -39,17 +37,8 @@ @SuppressWarnings("rawtypes") public class HibernateQuery extends AbstractHibernateQuery { - - public HibernateQuery(CriteriaQuery criteria, AbstractHibernateSession session, PersistentEntity entity) { - super(criteria, session, entity); - } - - public HibernateQuery(CriteriaQuery criteria, PersistentEntity entity) { - super(criteria, null, entity); - } - - public HibernateQuery(CriteriaQuery subCriteria, AbstractHibernateSession session, PersistentEntity associatedEntity, String newAlias) { - super(subCriteria, session, associatedEntity, newAlias); + public HibernateQuery(AbstractHibernateSession session, PersistentEntity entity) { + super(session, entity); } protected PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory) { @@ -57,10 +46,11 @@ protected PropertyMapping getEntityPersister(String name, SessionFactory session } /** + * TODO FIX THIS * @return The hibernate criteria */ public CriteriaQuery getHibernateCriteria() { - return this.criteriaQuery; + return null; } @Override @@ -68,8 +58,7 @@ public Object clone() { final HibernateSession hibernateSession = (HibernateSession) getSession(); final GrailsHibernateTemplate hibernateTemplate = (GrailsHibernateTemplate) hibernateSession.getNativeInterface(); return hibernateTemplate.execute((GrailsHibernateTemplate.HibernateCallback) session -> { - JpaCriteriaQuery newCriteria = session.getCriteriaBuilder().createQuery(entity.getJavaClass()); - HibernateQuery hibernateQuery = new HibernateQuery(newCriteria, hibernateSession, entity); + HibernateQuery hibernateQuery = new HibernateQuery(hibernateSession, entity); hibernateQuery.max(this.max); hibernateQuery.offset(this.offset); this.projections.getProjectionList().forEach(projection -> {hibernateQuery.projections().add(projection);});; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 6df4fde9d28..a515b462b48 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -36,11 +36,24 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue throw new RuntimeException("Must have a single predicate behind a not"); } cb.not(predicates[0]); - } else - if (criterion instanceof Query.IsNotNull c) { + } else if (criterion instanceof Query.IsNotNull c) { return cb.isNotNull(root_.get(c.getProperty())); } else if (criterion instanceof Query.Equals c ) { return cb.equal(root_.get(c.getProperty()),c.getValue()); + } else if (criterion instanceof Query.IdEquals c ) { + return cb.equal(root_.get("id"),c.getValue()); + } else if (criterion instanceof Query.GreaterThan c ) { + return cb.gt(root_.get(c.getProperty()),(Number)c.getValue()); + } else if (criterion instanceof Query.GreaterThanEquals c ) { + return cb.ge(root_.get(c.getProperty()),(Number)c.getValue()); + } else if (criterion instanceof Query.LessThan c ) { + return cb.lt(root_.get(c.getProperty()),(Number)c.getValue()); + } else if (criterion instanceof Query.LessThanEquals c ) { + return cb.le(root_.get(c.getProperty()),(Number)c.getValue()); + } else if (criterion instanceof Query.ILike c ) { + return cb.ilike(root_.get(c.getProperty()),c.getValue().toString()); + } else if (criterion instanceof Query.RLike c ) { + return cb.like(root_.get(c.getProperty()),c.getPattern(), '\\'); } else if (criterion instanceof Query.Like c ) { return cb.like(root_.get(c.getProperty()),c.getValue().toString()); } else if (criterion instanceof Query.In c diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy new file mode 100644 index 00000000000..1b775265eb3 --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -0,0 +1,129 @@ +package grails.gorm.tests.hibernatequery + +import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.tests.Person +import org.grails.datastore.mapping.core.Session +import org.grails.orm.hibernate.AbstractHibernateSession +import org.grails.orm.hibernate.HibernateDatastore +import org.grails.orm.hibernate.query.HibernateQuery +import spock.lang.Ignore + + +class HibernateQuerySpec extends GormDatastoreSpec { + + + HibernateQuery hibernateQuery + + Person oldBob + + def setup() { + HibernateDatastore hibernateDatastore = setupClass.hibernateDatastore + AbstractHibernateSession session = hibernateDatastore.getCurrentSession() as AbstractHibernateSession + hibernateQuery = new HibernateQuery(session, hibernateDatastore.getMappingContext().getPersistentEntity(Person.typeName)) + oldBob = new Person(firstName:"Bob", lastName:"Builder", age: 50).save(flush: true) + } + + Session createSession() { + setupClass.setup(((getDomainClasses()) as Set) as List) + } + + List getDomainClasses() { + [Person] + } + + def equals() { + given: + new Person(firstName:"Fred", lastName:"Rogers", age: 51).save(flush: true) + hibernateQuery.eq("age", 50) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + @Ignore("Need better implementation of Predicate") + def idEq() { + given: + Person oldFred = new Person(firstName:"Fred", lastName:"Rogers", age: 51).save(flush: true) + hibernateQuery.idEq(oldFred.id) + when: + def newFred = hibernateQuery.singleResult() + then: + oldFred == newFred + } + + def gt() { + given: + new Person(firstName:"Fred", lastName:"Rogers", age: 48).save(flush: true) + hibernateQuery.gt("age", 49) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def ge() { + given: + new Person(firstName:"Fred", lastName:"Rogers", age: 48).save(flush: true) + hibernateQuery.ge("age", 50) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def le() { + given: + new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + hibernateQuery.le("age", 50) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def lt() { + given: + new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + hibernateQuery.lt("age", 51) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + + + def like() { + given: + new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + hibernateQuery.like("firstName", "Bo%") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + + def ilike() { + given: + new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + hibernateQuery.ilike("firstName", "BO%") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + @Ignore("Must add custom functionality") + def rlike() { + given: + new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + hibernateQuery.rlike("firstName", "/Bob*/") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + +} From 8940919d7f97426db48564bf26d8a7eed34f1abc Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sat, 1 Feb 2025 23:13:49 -0600 Subject: [PATCH 0010/1008] Added support for postgres testcontainers in default HibernateQuerySpec --- grails-datastore-gorm-hibernate/build.gradle | 4 + .../tests/HibernateGormDatastoreSpec.groovy | 98 +++++++++++++++++++ .../hibernatequery/HibernateQuerySpec.groovy | 10 +- 3 files changed, 105 insertions(+), 7 deletions(-) create mode 100644 grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy diff --git a/grails-datastore-gorm-hibernate/build.gradle b/grails-datastore-gorm-hibernate/build.gradle index 2c1909118a0..bf9f9d474fe 100644 --- a/grails-datastore-gorm-hibernate/build.gradle +++ b/grails-datastore-gorm-hibernate/build.gradle @@ -37,6 +37,10 @@ dependencies { exclude group:'xml-apis', module:'xml-apis' } + testImplementation 'org.postgresql:postgresql:42.7.5' + testImplementation "org.testcontainers:postgresql:1.20.4" + testImplementation "org.testcontainers:spock:1.20.4" + testImplementation "org.apache.groovy:groovy-test-junit5" testImplementation "org.apache.groovy:groovy-sql" testImplementation "org.apache.groovy:groovy-json" diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy new file mode 100644 index 00000000000..05659079b55 --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy @@ -0,0 +1,98 @@ +package grails.gorm.tests + +import org.grails.datastore.mapping.core.DatastoreUtils +import org.grails.datastore.mapping.core.Session +import org.springframework.transaction.support.DefaultTransactionDefinition +import spock.lang.Shared +import spock.lang.Specification + +/** + * The original GormDataStoreSpec destroyed the setup + * between tests instead of at the end of all tests + * It also wqs default configured for H2 which + * made it break with some Java types. + * Finally, it loaded all the test Entities, + * now it can be setup individually. + */ +class HibernateGormDatastoreSpec extends Specification{ + + static final CURRENT_TEST_NAME = "current.gorm.test" + static final SETUP_CLASS_NAME = 'org.grails.datastore.gorm.Setup' + static final TEST_CLASSES = [] + + @Shared Class setupClass + + static Session session + + def setupSpec() { + setupClass = loadSetupClass() + cleanRegistry() + System.setProperty(CURRENT_TEST_NAME, this.getClass().simpleName - 'Spec') + configure() + } + + def setup() { + if (setupClass.transactionStatus == null) { + setupClass.transactionStatus = setupClass.transactionManager.getTransaction(new DefaultTransactionDefinition()) + } + session = setupClass.hibernateDatastore.connect() + } + + + Session configure() { + ConfigObject grailsConfig = new ConfigObject() + Map config = [ + 'dataSource.url':"jdbc:tc:postgresql:///dev_db", + 'dataSource.dbCreate': 'create-drop', + 'dataSource.formatSql': 'true', + 'hibernate.flush.mode': 'COMMIT', + 'hibernate.cache.queries': 'true', + 'hibernate.hbm2ddl.auto': 'create' + ] + grailsConfig.putAll(config) + setupClass.setup(((TEST_CLASSES + getDomainClasses()) as Set) as List, grailsConfig, true) + } + + List getDomainClasses() { + [] + } + + + def cleanup() { + if (setupClass.transactionStatus != null) { + def tx = setupClass.transactionStatus + setupClass.transactionStatus = null + setupClass.transactionManager.rollback(tx) + } + } + + + def cleanupSpec() { + if (session) { + session.disconnect() + DatastoreUtils.unbindSession session + } + try { + setupClass.destroy() + } catch(e) { + println "ERROR: Exception during test cleanup: ${e.message}" + } + + cleanRegistry() + } + + private cleanRegistry() { + for (clazz in (TEST_CLASSES + getDomainClasses() )) { + GroovySystem.metaClassRegistry.removeMetaClass(clazz) + } + } + + static Class loadSetupClass() { + try { + getClassLoader().loadClass(SETUP_CLASS_NAME) + } catch (Throwable e) { + throw new RuntimeException("Datastore setup class ($SETUP_CLASS_NAME) was not found",e) + } + } + +} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index 1b775265eb3..17c6b9a72a2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -1,6 +1,7 @@ package grails.gorm.tests.hibernatequery import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.tests.HibernateGormDatastoreSpec import grails.gorm.tests.Person import org.grails.datastore.mapping.core.Session import org.grails.orm.hibernate.AbstractHibernateSession @@ -9,7 +10,7 @@ import org.grails.orm.hibernate.query.HibernateQuery import spock.lang.Ignore -class HibernateQuerySpec extends GormDatastoreSpec { +class HibernateQuerySpec extends HibernateGormDatastoreSpec { HibernateQuery hibernateQuery @@ -18,15 +19,11 @@ class HibernateQuerySpec extends GormDatastoreSpec { def setup() { HibernateDatastore hibernateDatastore = setupClass.hibernateDatastore - AbstractHibernateSession session = hibernateDatastore.getCurrentSession() as AbstractHibernateSession + AbstractHibernateSession session = hibernateDatastore.connect() as AbstractHibernateSession hibernateQuery = new HibernateQuery(session, hibernateDatastore.getMappingContext().getPersistentEntity(Person.typeName)) oldBob = new Person(firstName:"Bob", lastName:"Builder", age: 50).save(flush: true) } - Session createSession() { - setupClass.setup(((getDomainClasses()) as Set) as List) - } - List getDomainClasses() { [Person] } @@ -93,7 +90,6 @@ class HibernateQuerySpec extends GormDatastoreSpec { } - def like() { given: new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) From c9e9134197f55a3591074253168f510284cf56c4 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sun, 2 Feb 2025 22:15:13 -0600 Subject: [PATCH 0011/1008] Added support for more query expressions --- .../query/AbstractHibernateQuery.java | 25 ++++++ .../hibernate/query/PredicateGenerator.java | 13 ++- .../hibernatequery/HibernateQuerySpec.groovy | 88 ++++++++++++++++++- 3 files changed, 121 insertions(+), 5 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 12e4a730405..a618d35afa6 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -15,6 +15,7 @@ package org.grails.orm.hibernate.query; import grails.gorm.DetachedCriteria; +import groovy.lang.Closure; import groovy.util.logging.Slf4j; import jakarta.persistence.FetchType; import jakarta.persistence.criteria.CriteriaQuery; @@ -26,6 +27,7 @@ import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.query.AssociationQuery; import org.grails.datastore.mapping.query.Query; +import org.grails.datastore.mapping.query.Restrictions; import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.orm.hibernate.IHibernateTemplate; import org.hibernate.SessionFactory; @@ -102,21 +104,25 @@ protected void initializeJoinStatus() { @Override public Query isEmpty(String property) { + detachedCriteria.isEmpty(property); return this; } @Override public Query isNotEmpty(String property) { + detachedCriteria.isNotEmpty(property); return this; } @Override public Query isNull(String property) { + detachedCriteria.isNull(property); return this; } @Override public Query isNotNull(String property) { + detachedCriteria.isNotNull(property); return this; } @@ -207,16 +213,33 @@ public Query gt(String property, Object value) { @Override public Query and(Criterion a, Criterion b) { + Closure addClosure = new Closure(this) { + public void doCall() { + DetachedCriteria owner = (DetachedCriteria) getDelegate(); + owner.add(Restrictions.and(a,b)); + } + }; + detachedCriteria.and(addClosure); return this; } @Override public Query or(Criterion a, Criterion b) { + Closure orClosure = new Closure(this) { + public void doCall() { + DetachedCriteria owner = (DetachedCriteria) getDelegate(); + owner.add(Restrictions.or(a,b)); + } + }; + detachedCriteria.and(orClosure); return this; } @Override public Query allEq(Map values) { + values.forEach((key, value) -> { + detachedCriteria.eq(key,value); + }); return this; } @@ -252,6 +275,7 @@ public Query lt(String property, Object value) { @Override public Query in(String property, List values) { + detachedCriteria.in(property,values); return this; } @@ -440,6 +464,7 @@ private org.hibernate.query.Query getQuery() { root = cq.from(entity.getJavaClass()); cq.select(root); } + List criteriaList = (List)detachedCriteria.getCriteria(); jakarta.persistence.criteria.Predicate[] predicates = diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index a515b462b48..d268824c437 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -24,10 +24,10 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue map(criterion -> { if (criterion instanceof Query.Disjunction) { List criterionList = ((Query.Disjunction) criterion).getCriteria(); - cb.or(getPredicates(cb,criteriaQuery,root_, criterionList)); + return cb.or(getPredicates(cb,criteriaQuery,root_, criterionList)); } else if (criterion instanceof Query.Conjunction) { List criterionList = ((Query.Conjunction) criterion).getCriteria(); - cb.and(getPredicates(cb,criteriaQuery,root_, criterionList)); + return cb.and(getPredicates(cb,criteriaQuery,root_, criterionList)); } else if (criterion instanceof Query.Negation) { List criterionList = ((Query.Negation) criterion).getCriteria(); Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList); @@ -35,9 +35,11 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue log.error("Must have a single predicate behind a not"); throw new RuntimeException("Must have a single predicate behind a not"); } - cb.not(predicates[0]); + return cb.not(predicates[0]); } else if (criterion instanceof Query.IsNotNull c) { return cb.isNotNull(root_.get(c.getProperty())); + } else if (criterion instanceof Query.IsEmpty c) { + return cb.isEmpty(root_.get(c.getProperty())); } else if (criterion instanceof Query.Equals c ) { return cb.equal(root_.get(c.getProperty()),c.getValue()); } else if (criterion instanceof Query.IdEquals c ) { @@ -57,6 +59,7 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue } else if (criterion instanceof Query.Like c ) { return cb.like(root_.get(c.getProperty()),c.getValue().toString()); } else if (criterion instanceof Query.In c + && Objects.nonNull(c.getSubquery()) && c.getSubquery().getProjections().size() == 1 && c.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection ) { @@ -67,6 +70,10 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); return cb.in(root_.get(c.getProperty())).value(subquery); + } else if (criterion instanceof Query.In c + && !c.getValues().isEmpty() + ) { + return cb.in(root_.get(c.getProperty()), c.getValues()); } return null; }).filter(Objects::nonNull).toList().toArray(new Predicate[0]); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index 17c6b9a72a2..aa3358ec92d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -1,9 +1,9 @@ package grails.gorm.tests.hibernatequery -import grails.gorm.tests.GormDatastoreSpec import grails.gorm.tests.HibernateGormDatastoreSpec import grails.gorm.tests.Person -import org.grails.datastore.mapping.core.Session +import grails.gorm.tests.Pet +import org.grails.datastore.mapping.query.Query import org.grails.orm.hibernate.AbstractHibernateSession import org.grails.orm.hibernate.HibernateDatastore import org.grails.orm.hibernate.query.HibernateQuery @@ -122,4 +122,88 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } + def and() { + given: + new Person(firstName:"Bob", lastName:"Builder", age: 51).save(flush: true) + Query.Criterion lastName = new Query.Equals("lastName", "Builder") + Query.Criterion age = new Query.Equals("age", 50) + hibernateQuery.and(lastName,age) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def or() { + given: + new Person(firstName:"Bob", lastName:"Builder", age: 51).save(flush: true) + Query.Criterion lastNameWrong = new Query.Equals("lastName", "Rogers") + Query.Criterion ageCorrect = new Query.Equals("age", 50) + hibernateQuery.or(lastNameWrong,ageCorrect) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def isEmpty() { + given: + hibernateQuery.isEmpty("pets") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def isNotEmpty() { + oldBob.addToPets(new Pet()).save(flush: true) + given: + hibernateQuery.isNotEmpty("pets") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def isNull() { + oldBob.lastName = null + oldBob.save(flush:true) + given: + hibernateQuery.isNull("lastName") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def isNotNull() { + new Person(firstName:"Fred", age: 52).save(flush: true) + given: + hibernateQuery.isNotNull("lastName") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def allEq() { + new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + given: + hibernateQuery.allEq(["firstName":"Bob","lastName":"Builder"]) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def inList() { + new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + given: + hibernateQuery.in("age", [50,51]) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + } From f11e2cb2388059289294acdfaba415bd290c145c Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Tue, 4 Feb 2025 17:19:16 -0600 Subject: [PATCH 0012/1008] Added support order and joins --- .../query/AbstractHibernateQuery.java | 88 ++++++++------ .../hibernate/query/PredicateGenerator.java | 71 ++++++++---- .../tests/HibernateGormDatastoreSpec.groovy | 1 + .../hibernatequery/HibernateQuerySpec.groovy | 108 ++++++++++++++---- 4 files changed, 185 insertions(+), 83 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index a618d35afa6..eeda09372a7 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -33,7 +33,6 @@ import org.hibernate.SessionFactory; import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.query.criteria.HibernateCriteriaBuilder; -import org.hibernate.query.sqm.tree.SqmJoinType; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -43,6 +42,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; @@ -76,9 +76,6 @@ public abstract class AbstractHibernateQuery extends Query { protected AbstractHibernateQuery(AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); this.detachedCriteria = new DetachedCriteria(entity.getJavaClass()); - if(entity != null) { - initializeJoinStatus(); - } } public void setDetachedCriteria(DetachedCriteria detachedCriteria) { @@ -92,15 +89,6 @@ protected Object resolveIdIfEntity(Object value) { return value; } - protected void initializeJoinStatus() { - Boolean cachedStatus = JOIN_STATUS_CACHE.get(entity.getName()); - if(cachedStatus != null) hasJoins = cachedStatus; - else { - for(Association a : entity.getAssociations()) { - if( a.getFetchStrategy() == FetchType.EAGER ) hasJoins = true; - } - } - } @Override public Query isEmpty(String property) { @@ -281,6 +269,7 @@ public Query in(String property, List values) { @Override public Query between(String property, Object start, Object end) { + detachedCriteria.between(property,start,end); return this; } @@ -363,19 +352,6 @@ protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias return subCriteria; } - private SqmJoinType resolveJoinType(JoinType joinType) { - if(joinType == null) { - return SqmJoinType.INNER; - } - switch (joinType) { - case LEFT: - return SqmJoinType.LEFT; - case RIGHT: - return SqmJoinType.RIGHT; - default: - return SqmJoinType.INNER; - } - } @@ -397,19 +373,19 @@ public Query lock(boolean lock) { @Override public Query order(Order order) { - super.order(order); + detachedCriteria.order(order); return this; } @Override public Query join(String property) { - this.hasJoins = true; + detachedCriteria.join(property); return this; } @Override public Query select(String property) { - this.hasJoins = true; + detachedCriteria.select(property); return this; } @@ -453,30 +429,71 @@ private org.hibernate.query.Query getQuery() { .getProjectionList() .stream() .filter(combinePredicates(projectionPredicates)).toList(); + List joinColumns = ((Map) detachedCriteria.getFetchStrategies()) + .entrySet() + .stream() + .filter(entry -> entry.getValue().equals(FetchType.EAGER)) + .map(Map.Entry::getKey) + .toList(); + + CriteriaQuery cq; Root root; if (projections.size() == 1 && projections.get(0) instanceof CountProjection) { cq = cb.createQuery(Long.class); root = cq.from(entity.getJavaClass()); cq.select(cb.count(root)); - } else { + } else if (joinColumns.size() > 0) { cq = cb.createQuery(entity.getJavaClass()); root = cq.from(entity.getJavaClass()); cq.select(root); + Map joinTypes = detachedCriteria.getJoinTypes(); + joinColumns.forEach( joinColumn ->{ + JoinType joinType = joinTypes.entrySet() + .stream() + .filter(entry -> entry.getKey().equals(joinColumn)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(JoinType.INNER); + root.join(joinColumn, joinType); + }); + } + else { + cq = cb.createQuery(entity.getJavaClass()); + root = cq.from(entity.getJavaClass()); + cq.select(root); + } + List orders = detachedCriteria.getOrders(); + if (!orders.isEmpty()) { + cq.orderBy(orders + .stream() + .map(order -> { + if (order.getDirection().equals(Order.Direction.ASC)) { + return cb.asc(root.get(order.getProperty())); + } else { + return cb.desc(root.get(order.getProperty())); + } + }) + .toList() + ); } List criteriaList = (List)detachedCriteria.getCriteria(); + if (!criteriaList.isEmpty()) { + cq.where(cb.and(PredicateGenerator.getPredicates(cb, cq, root, criteriaList))); + } - jakarta.persistence.criteria.Predicate[] predicates = - PredicateGenerator.getPredicates(cb, cq, root, criteriaList); - cq.where(cb.and(predicates)); org.hibernate.query.Query query = getSessionFactory() .getCurrentSession() .createQuery(cq) - .setFirstResult(this.offset); + .setFirstResult(this.offset) + .setHint("org.hibernate.cacheable", queryCache);; if (this.max > -1) { query.setMaxResults(this.max); } + if (Objects.nonNull(lockResult)) { + query.setLockMode(lockResult); + } return query; } @@ -494,9 +511,6 @@ protected List executeQuery(PersistentEntity entity, Junction criteria) { return list(); } - - - protected String calculatePropertyName(String property) { if (alias == null) { return property; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index d268824c437..db0a3e2c101 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -2,6 +2,7 @@ import groovy.util.logging.Slf4j; import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; @@ -10,6 +11,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZonedDateTime; +import java.util.Date; import java.util.List; import java.util.Objects; @@ -17,17 +24,17 @@ public class PredicateGenerator { private static final Logger log = LoggerFactory.getLogger(PredicateGenerator.class); - public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, Root root_ , List criteriaList) { + public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, Root root_, List criteriaList) { return criteriaList.stream(). map(criterion -> { if (criterion instanceof Query.Disjunction) { List criterionList = ((Query.Disjunction) criterion).getCriteria(); - return cb.or(getPredicates(cb,criteriaQuery,root_, criterionList)); + return cb.or(getPredicates(cb, criteriaQuery, root_, criterionList)); } else if (criterion instanceof Query.Conjunction) { List criterionList = ((Query.Conjunction) criterion).getCriteria(); - return cb.and(getPredicates(cb,criteriaQuery,root_, criterionList)); + return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList)); } else if (criterion instanceof Query.Negation) { List criterionList = ((Query.Negation) criterion).getCriteria(); Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList); @@ -40,24 +47,46 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue return cb.isNotNull(root_.get(c.getProperty())); } else if (criterion instanceof Query.IsEmpty c) { return cb.isEmpty(root_.get(c.getProperty())); - } else if (criterion instanceof Query.Equals c ) { - return cb.equal(root_.get(c.getProperty()),c.getValue()); - } else if (criterion instanceof Query.IdEquals c ) { - return cb.equal(root_.get("id"),c.getValue()); - } else if (criterion instanceof Query.GreaterThan c ) { - return cb.gt(root_.get(c.getProperty()),(Number)c.getValue()); - } else if (criterion instanceof Query.GreaterThanEquals c ) { - return cb.ge(root_.get(c.getProperty()),(Number)c.getValue()); - } else if (criterion instanceof Query.LessThan c ) { - return cb.lt(root_.get(c.getProperty()),(Number)c.getValue()); - } else if (criterion instanceof Query.LessThanEquals c ) { - return cb.le(root_.get(c.getProperty()),(Number)c.getValue()); - } else if (criterion instanceof Query.ILike c ) { - return cb.ilike(root_.get(c.getProperty()),c.getValue().toString()); - } else if (criterion instanceof Query.RLike c ) { - return cb.like(root_.get(c.getProperty()),c.getPattern(), '\\'); - } else if (criterion instanceof Query.Like c ) { - return cb.like(root_.get(c.getProperty()),c.getValue().toString()); + } else if (criterion instanceof Query.Equals c) { + return cb.equal(root_.get(c.getProperty()), c.getValue()); + } else if (criterion instanceof Query.IdEquals c) { + return cb.equal(root_.get("id"), c.getValue()); + } else if (criterion instanceof Query.GreaterThan c) { + return cb.gt(root_.get(c.getProperty()), (Number) c.getValue()); + } else if (criterion instanceof Query.GreaterThanEquals c) { + return cb.ge(root_.get(c.getProperty()), (Number) c.getValue()); + } else if (criterion instanceof Query.LessThan c) { + return cb.lt(root_.get(c.getProperty()), (Number) c.getValue()); + } else if (criterion instanceof Query.LessThanEquals c) { + return cb.le(root_.get(c.getProperty()), (Number) c.getValue()); + } else if (criterion instanceof Query.Between c) { + if (c.getFrom() instanceof String && c.getTo() instanceof String) { + return cb.between(root_.get(c.getProperty()), (String) c.getFrom(), (String) c.getTo()); + } else if (c.getFrom() instanceof Short && c.getTo() instanceof Short) { + return cb.between(root_.get(c.getProperty()), (Short) c.getFrom(), (Short) c.getTo()); + } else if (c.getFrom() instanceof Integer && c.getTo() instanceof Integer) { + return cb.between(root_.get(c.getProperty()), (Integer) c.getFrom(), (Integer) c.getTo()); + } else if (c.getFrom() instanceof Long && c.getTo() instanceof Long) { + return cb.between(root_.get(c.getProperty()), (Long) c.getFrom(), (Long) c.getTo()); + } else if (c.getFrom() instanceof Date && c.getTo() instanceof Date) { + return cb.between(root_.get(c.getProperty()), (Date) c.getFrom(), (Date) c.getTo()); + } else if (c.getFrom() instanceof Instant && c.getTo() instanceof Instant) { + return cb.between(root_.get(c.getProperty()), (Instant) c.getFrom(), (Instant) c.getTo()); + } else if (c.getFrom() instanceof LocalDate && c.getTo() instanceof LocalDate) { + return cb.between(root_.get(c.getProperty()), (LocalDate) c.getFrom(), (LocalDate) c.getTo()); + } else if (c.getFrom() instanceof LocalDateTime && c.getTo() instanceof LocalDateTime) { + return cb.between(root_.get(c.getProperty()), (LocalDateTime) c.getFrom(), (LocalDateTime) c.getTo()); + } else if (c.getFrom() instanceof OffsetDateTime && c.getTo() instanceof OffsetDateTime) { + return cb.between(root_.get(c.getProperty()), (OffsetDateTime) c.getFrom(), (OffsetDateTime) c.getTo()); + } else if (c.getFrom() instanceof ZonedDateTime && c.getTo() instanceof ZonedDateTime) { + return cb.between(root_.get(c.getProperty()), (ZonedDateTime) c.getFrom(), (ZonedDateTime) c.getTo()); + } + } else if (criterion instanceof Query.ILike c) { + return cb.ilike(root_.get(c.getProperty()), c.getValue().toString()); + } else if (criterion instanceof Query.RLike c) { + return cb.like(root_.get(c.getProperty()), c.getPattern(), '\\'); + } else if (criterion instanceof Query.Like c) { + return cb.like(root_.get(c.getProperty()), c.getValue().toString()); } else if (criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) && c.getSubquery().getProjections().size() == 1 diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy index 05659079b55..127099098d3 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy @@ -45,6 +45,7 @@ class HibernateGormDatastoreSpec extends Specification{ 'dataSource.url':"jdbc:tc:postgresql:///dev_db", 'dataSource.dbCreate': 'create-drop', 'dataSource.formatSql': 'true', + 'dataSource.logSql': 'true', 'hibernate.flush.mode': 'COMMIT', 'hibernate.cache.queries': 'true', 'hibernate.hbm2ddl.auto': 'create' diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index aa3358ec92d..cd91cd3dad4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -3,6 +3,8 @@ package grails.gorm.tests.hibernatequery import grails.gorm.tests.HibernateGormDatastoreSpec import grails.gorm.tests.Person import grails.gorm.tests.Pet +import grails.persistence.Entity +import jakarta.persistence.criteria.JoinType import org.grails.datastore.mapping.query.Query import org.grails.orm.hibernate.AbstractHibernateSession import org.grails.orm.hibernate.HibernateDatastore @@ -21,7 +23,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { HibernateDatastore hibernateDatastore = setupClass.hibernateDatastore AbstractHibernateSession session = hibernateDatastore.connect() as AbstractHibernateSession hibernateQuery = new HibernateQuery(session, hibernateDatastore.getMappingContext().getPersistentEntity(Person.typeName)) - oldBob = new Person(firstName:"Bob", lastName:"Builder", age: 50).save(flush: true) + oldBob = new Person(firstName: "Bob", lastName: "Builder", age: 50).save(flush: true) } List getDomainClasses() { @@ -30,18 +32,18 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def equals() { given: - new Person(firstName:"Fred", lastName:"Rogers", age: 51).save(flush: true) - hibernateQuery.eq("age", 50) + new Person(firstName: "Fred", lastName: "Rogers", age: 51).save(flush: true) + hibernateQuery.eq("age", 50) when: - def newBob = hibernateQuery.singleResult() + def newBob = hibernateQuery.singleResult() then: - oldBob == newBob + oldBob == newBob } @Ignore("Need better implementation of Predicate") def idEq() { given: - Person oldFred = new Person(firstName:"Fred", lastName:"Rogers", age: 51).save(flush: true) + Person oldFred = new Person(firstName: "Fred", lastName: "Rogers", age: 51).save(flush: true) hibernateQuery.idEq(oldFred.id) when: def newFred = hibernateQuery.singleResult() @@ -51,7 +53,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def gt() { given: - new Person(firstName:"Fred", lastName:"Rogers", age: 48).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) hibernateQuery.gt("age", 49) when: def newBob = hibernateQuery.singleResult() @@ -61,7 +63,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def ge() { given: - new Person(firstName:"Fred", lastName:"Rogers", age: 48).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) hibernateQuery.ge("age", 50) when: def newBob = hibernateQuery.singleResult() @@ -71,7 +73,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def le() { given: - new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) hibernateQuery.le("age", 50) when: def newBob = hibernateQuery.singleResult() @@ -81,7 +83,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def lt() { given: - new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) hibernateQuery.lt("age", 51) when: def newBob = hibernateQuery.singleResult() @@ -92,7 +94,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def like() { given: - new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) hibernateQuery.like("firstName", "Bo%") when: def newBob = hibernateQuery.singleResult() @@ -103,7 +105,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def ilike() { given: - new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) hibernateQuery.ilike("firstName", "BO%") when: def newBob = hibernateQuery.singleResult() @@ -114,7 +116,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { @Ignore("Must add custom functionality") def rlike() { given: - new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) hibernateQuery.rlike("firstName", "/Bob*/") when: def newBob = hibernateQuery.singleResult() @@ -124,10 +126,10 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def and() { given: - new Person(firstName:"Bob", lastName:"Builder", age: 51).save(flush: true) + new Person(firstName: "Bob", lastName: "Builder", age: 51).save(flush: true) Query.Criterion lastName = new Query.Equals("lastName", "Builder") Query.Criterion age = new Query.Equals("age", 50) - hibernateQuery.and(lastName,age) + hibernateQuery.and(lastName, age) when: def newBob = hibernateQuery.singleResult() then: @@ -136,10 +138,10 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def or() { given: - new Person(firstName:"Bob", lastName:"Builder", age: 51).save(flush: true) + new Person(firstName: "Bob", lastName: "Builder", age: 51).save(flush: true) Query.Criterion lastNameWrong = new Query.Equals("lastName", "Rogers") Query.Criterion ageCorrect = new Query.Equals("age", 50) - hibernateQuery.or(lastNameWrong,ageCorrect) + hibernateQuery.or(lastNameWrong, ageCorrect) when: def newBob = hibernateQuery.singleResult() then: @@ -156,18 +158,23 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } def isNotEmpty() { - oldBob.addToPets(new Pet()).save(flush: true) + Pet pet = new Pet(name: "Lucky") + oldBob.addToPets(pet) + oldBob.save(flush: true) given: hibernateQuery.isNotEmpty("pets") + .join("pets") + when: - def newBob = hibernateQuery.singleResult() + Person newBob = hibernateQuery.singleResult() then: oldBob == newBob + oldBob.pets == newBob.pets } def isNull() { oldBob.lastName = null - oldBob.save(flush:true) + oldBob.save(flush: true) given: hibernateQuery.isNull("lastName") when: @@ -177,7 +184,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } def isNotNull() { - new Person(firstName:"Fred", age: 52).save(flush: true) + new Person(firstName: "Fred", age: 52).save(flush: true) given: hibernateQuery.isNotNull("lastName") when: @@ -187,9 +194,9 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } def allEq() { - new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) given: - hibernateQuery.allEq(["firstName":"Bob","lastName":"Builder"]) + hibernateQuery.allEq(["firstName": "Bob", "lastName": "Builder"]) when: def newBob = hibernateQuery.singleResult() then: @@ -197,13 +204,64 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } def inList() { - new Person(firstName:"Fred", lastName:"Rogers", age: 52).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + given: + hibernateQuery.in("age", [50, 51]) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def between() { + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) given: - hibernateQuery.in("age", [50,51]) + hibernateQuery.between("age", 49, 51) when: def newBob = hibernateQuery.singleResult() then: oldBob == newBob } + def leftJoin() { + given: + hibernateQuery.join("pets", JoinType.LEFT) + when: + Person newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + oldBob.pets == newBob.pets + } + + def makeLazy() { + given: + def eagerOwner= new EagerOwner( pets :[new Pet(name:"Lucky")]) + hibernateQuery.join("pets", JoinType.LEFT) + when: + Person newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + oldBob.pets == newBob.pets + } + + def orderByAge() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.order(new Query.Order("age", Query.Order.Direction.DESC)) + when: + def bobs = hibernateQuery.list() + then: + bobs.size() == 2 + oldBob == bobs[0] + } + +} + +@Entity +class EagerOwner implements Serializable { + Set pets = [] as Set + static hasMany = [pets: Pet] + static mapping = { + pets lazy : false + } } From 7c41f8c8eea73141bd6c472f65d7b0092630c537 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Tue, 4 Feb 2025 23:04:49 -0600 Subject: [PATCH 0013/1008] Added support group by --- .../AbstractHibernateGormStaticApi.groovy | 12 +- .../query/AbstractHibernateQuery.java | 171 +++++++++++------- .../hibernatequery/HibernateQuerySpec.groovy | 79 ++++++++ 3 files changed, 192 insertions(+), 70 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy index b3196bde791..f58510b83ac 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy @@ -44,12 +44,12 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { protected ConversionService conversionService protected final HibernateSession hibernateSession - AbstractHibernateGormStaticApi( - Class persistentClass, - HibernateDatastore datastore, - List finders) { - this(persistentClass, datastore, finders, null) - } +// AbstractHibernateGormStaticApi( +// Class persistentClass, +// HibernateDatastore datastore, +// List finders) { +// this(persistentClass, datastore, finders, null) +// } AbstractHibernateGormStaticApi( Class persistentClass, diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index eeda09372a7..f97f886b6ea 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -19,9 +19,10 @@ import groovy.util.logging.Slf4j; import jakarta.persistence.FetchType; import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.JoinType; +import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Root; -import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; @@ -31,20 +32,23 @@ import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.orm.hibernate.IHibernateTemplate; import org.hibernate.SessionFactory; -import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.query.criteria.HibernateCriteriaBuilder; +import org.hibernate.query.criteria.JpaExpression; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.InvalidDataAccessApiUsageException; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.function.Predicate; +import java.util.stream.Stream; /** * Bridges the Query API with the Hibernate Criteria API @@ -123,7 +127,8 @@ public PersistentEntity getEntity() { return super.getEntity(); } - protected String getAssociationPath(String propertyName) { + + private String getAssociationPath(String propertyName) { if(propertyName.indexOf('.') > -1) { return propertyName; } @@ -139,36 +144,6 @@ protected String getAssociationPath(String propertyName) { } } - protected String getCurrentAlias() { - if (alias != null) { - return alias; - } - - if (aliasStack.isEmpty()) { - return null; - } - - return aliasStack.getLast(); - } - - @SuppressWarnings("unchecked") - static void doTypeConversionIfNeccessary(PersistentEntity entity, PropertyCriterion pc) { - // ignore Size related constraints - if (pc.getClass().getSimpleName().startsWith(SIZE_CONSTRAINT_PREFIX)) { - return; - } - - String property = pc.getProperty(); - Object value = pc.getValue(); - PersistentProperty p = entity.getPropertyByName(property); - if (p != null && !p.getType().isInstance(value)) { - pc.setValue(conversionService.convert(value, p.getType())); - } - } - - - protected abstract PropertyMapping getEntityPersister(String name, SessionFactory sessionFactory); - @Override @@ -291,6 +266,9 @@ public Query rlike(String property, String expr) { return this; } + + //TODO THIS IS USED BY AbstractCriteriaBuilder which is not the parent of + // AbstractHibernateCriteriaBuilder @Override public AssociationQuery createQuery(String associationName) { final PersistentProperty property = entity.getPropertyByName(calculatePropertyName(associationName)); @@ -306,17 +284,8 @@ public AssociationQuery createQuery(String associationName) { throw new InvalidDataAccessApiUsageException("Cannot query association [" + calculatePropertyName(associationName) + "] of entity [" + entity + "]. Property is not an association!"); } - protected CriteriaAndAlias getCriteriaAndAlias(DetachedAssociationCriteria associationCriteria) { - String associationPath = associationCriteria.getAssociationPath(); - String alias = associationCriteria.getAlias(); - if(associationPath == null) { - associationPath = associationCriteria.getAssociation().getName(); - } - return getOrCreateAlias(associationPath, alias); - } - - protected CriteriaAndAlias getOrCreateAlias(String associationName, String alias) { + private CriteriaAndAlias getOrCreateAlias(String associationName, String alias) { CriteriaAndAlias subCriteria = null; String associationPath = getAssociationPath(associationName); CriteriaQuery parentCriteria = getCriteriaBuilder().createQuery(entity.getJavaClass()); @@ -411,24 +380,45 @@ public Object singleResult() { } } + private final Predicate idProjectionPredicate = projection -> projection instanceof IdProjection; private final Predicate countProjectionPredicate = projection -> projection instanceof CountProjection; + private final Predicate countDistinctProjection = projection -> projection instanceof CountDistinctProjection; + private final Predicate maxProjectionPredicate = projection -> projection instanceof MaxProjection; + private final Predicate minProjectionPredicate = projection -> projection instanceof MinProjection; + private final Predicate sumProjectionPredicate = projection -> projection instanceof SumProjection; + private final Predicate avgProjectionPredicate = projection -> projection instanceof AvgProjection; + private final Predicate propertyProjectionPredicate = projection -> projection instanceof PropertyProjection; @SuppressWarnings("unchecked") - Predicate[] projectionPredicates = new Predicate[] {countProjectionPredicate} ; + Predicate[] projectionPredicates = new Predicate[] { + idProjectionPredicate + , propertyProjectionPredicate + , countProjectionPredicate + , countDistinctProjection + , maxProjectionPredicate + , minProjectionPredicate + , sumProjectionPredicate + , avgProjectionPredicate + } ; @SafeVarargs private static Predicate combinePredicates(Predicate... predicates) { return Arrays.stream(predicates) - .reduce(Predicate::and) + .reduce(Predicate::or) .orElse(x -> true); } private org.hibernate.query.Query getQuery() { HibernateCriteriaBuilder cb = getCriteriaBuilder(); - List projections = projections() - .getProjectionList() + List projectionList = projections().getProjectionList(); + List projections = projectionList .stream() .filter(combinePredicates(projectionPredicates)).toList(); + List groupProjections = projectionList + .stream() + .filter(GroupPropertyProjection.class::isInstance) + .map(GroupPropertyProjection.class::cast) + .toList(); List joinColumns = ((Map) detachedCriteria.getFetchStrategies()) .entrySet() .stream() @@ -439,29 +429,55 @@ private org.hibernate.query.Query getQuery() { CriteriaQuery cq; Root root; - if (projections.size() == 1 && projections.get(0) instanceof CountProjection) { - cq = cb.createQuery(Long.class); + if (!groupProjections.isEmpty() && !projections.isEmpty()) { + cq = cb.createQuery(Object[].class); root = cq.from(entity.getJavaClass()); - cq.select(cb.count(root)); - } else if (joinColumns.size() > 0) { - cq = cb.createQuery(entity.getJavaClass()); + List groupByPaths = groupProjections + .stream() + .map(groupPropertyProjection -> root.get(groupPropertyProjection.getPropertyName())) + .map(Expression.class::cast) + .toList(); + List projectionExpressions = projections + .stream() + .map(projectionToJpaExpression(cb, root)) + .filter(Objects::nonNull) + .map(Expression.class::cast) + .toList(); + cq.multiselect(projectionExpressions); + cq.groupBy(groupByPaths); + } else if (groupProjections.isEmpty() && !projections.isEmpty()) { + cq = cb.createQuery(Object[].class); root = cq.from(entity.getJavaClass()); - cq.select(root); - Map joinTypes = detachedCriteria.getJoinTypes(); - joinColumns.forEach( joinColumn ->{ - JoinType joinType = joinTypes.entrySet() + List projectionExpressions = projections .stream() - .filter(entry -> entry.getKey().equals(joinColumn)) - .map(Map.Entry::getValue) - .findFirst() - .orElse(JoinType.INNER); - root.join(joinColumn, joinType); - }); - } - else { + .map(projectionToJpaExpression(cb, root)) + .filter(Objects::nonNull) + .map(Expression.class::cast) + .toList(); + if (projectionExpressions.size() == 1) { + cq.select(projectionExpressions.get(0)); + } else { + cq.multiselect(projectionExpressions); + } + } else if (!groupProjections.isEmpty() && projections.isEmpty()) { + throw new RuntimeException("Group By without projections"); + } else { cq = cb.createQuery(entity.getJavaClass()); root = cq.from(entity.getJavaClass()); cq.select(root); + if (joinColumns.size() > 0) { + + Map joinTypes = detachedCriteria.getJoinTypes(); + joinColumns.forEach( joinColumn ->{ + JoinType joinType = joinTypes.entrySet() + .stream() + .filter(entry -> entry.getKey().equals(joinColumn)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(JoinType.INNER); + root.join(joinColumn, joinType); + }); + } } List orders = detachedCriteria.getOrders(); if (!orders.isEmpty()) { @@ -497,6 +513,33 @@ private org.hibernate.query.Query getQuery() { return query; } + private Function projectionToJpaExpression(HibernateCriteriaBuilder cb, Root root) { + return projection -> { + if (countProjectionPredicate.test(projection)) { + return cb.count(root); + } else if (countDistinctProjection.test(projection)) { + return cb.countDistinct(root); + } else if (maxProjectionPredicate.test(projection)) { + Path path = root.get(((PropertyProjection) projection).getPropertyName()); + return cb.max(path); + } else if (minProjectionPredicate.test(projection)) { + Path path = root.get(((PropertyProjection) projection).getPropertyName()); + return cb.min(path); + } else if (avgProjectionPredicate.test(projection)) { + Path path = root.get(((PropertyProjection) projection).getPropertyName()); + return cb.avg(path); + } else if (sumProjectionPredicate.test(projection)) { + Path path = root.get(((PropertyProjection) projection).getPropertyName()); + return cb.sum(path); + } else if (idProjectionPredicate.test(projection)) { + return (JpaExpression) root.get("id"); + } else if (propertyProjectionPredicate.test(projection)) { // keep this last!!! + return (JpaExpression)root.get(((PropertyProjection) projection).getPropertyName()); + } + return null; + }; + } + private SessionFactory getSessionFactory() { return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory(); } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index cd91cd3dad4..7c245156781 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -255,6 +255,85 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == bobs[0] } + def projectionProperty() { + given: + hibernateQuery.projections().property("lastName") + when: + def count = hibernateQuery.singleResult() + then: + count[0] == "Builder" + } + + def projectionId() { + given: + hibernateQuery.projections().id() + when: + def count = hibernateQuery.singleResult() + then: + count[0] == oldBob.id + } + + def count() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.projections().count() + when: + def count = hibernateQuery.singleResult() + then: + count[0] == 2 + } + + def max() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.projections().max("age") + when: + def age = hibernateQuery.singleResult() + then: + age[0] == 50 + } + + def min() { + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + given: + hibernateQuery.projections().min("age") + when: + def age = hibernateQuery.singleResult() + then: + age[0] == 50 + } + + def sum() { + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + given: + hibernateQuery.projections().sum("age") + when: + def age = hibernateQuery.singleResult() + then: + age[0] == 102 + } + + def avg() { + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + given: + hibernateQuery.projections().avg("age") + when: + def age = hibernateQuery.singleResult() + then: + age[0] == 51 + } + + def groupByLastNameAverageAge() { + new Person(firstName: "Fred", lastName: "Builder", age: 52).save(flush: true) + given: + hibernateQuery.projections().groupProperty("lastName").avg("age") + when: + def result = hibernateQuery.singleResult() + then: + result[0] == "Builder" + result[1] == 51 + } + } @Entity From 7e98403234faf2255058493599d055d56ed599f9 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 5 Feb 2025 14:15:05 -0600 Subject: [PATCH 0014/1008] Added support for selecting columns from the joined tables --- .../query/AbstractHibernateQuery.java | 219 ++++++++++-------- .../hibernate/query/PredicateGenerator.java | 3 +- .../hibernatequery/HibernateQuerySpec.groovy | 30 ++- 3 files changed, 144 insertions(+), 108 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index f97f886b6ea..cf92a6de705 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -20,9 +20,9 @@ import jakarta.persistence.FetchType; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.From; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.Path; -import jakarta.persistence.criteria.Root; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; @@ -38,8 +38,8 @@ import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.InvalidDataAccessApiUsageException; +import java.util.AbstractMap; import java.util.Arrays; -import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -48,7 +48,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Stream; +import java.util.stream.Collectors; /** * Bridges the Query API with the Hibernate Criteria API @@ -360,7 +360,7 @@ public Query select(String property) { @Override public List list() { - return getQuery().getResultList(); + return createQuery().getResultList(); } @@ -373,7 +373,7 @@ protected void flushBeforeQuery() { @Override public Object singleResult() { try { - return getQuery().getSingleResult(); + return createQuery().getSingleResult(); } catch (jakarta.persistence.NoResultException e) { return null; @@ -408,77 +408,68 @@ private static Predicate combinePredicates(Predicate... predicates) { .orElse(x -> true); } - private org.hibernate.query.Query getQuery() { + private org.hibernate.query.Query createQuery() { HibernateCriteriaBuilder cb = getCriteriaBuilder(); - List projectionList = projections().getProjectionList(); - List projections = projectionList - .stream() - .filter(combinePredicates(projectionPredicates)).toList(); - List groupProjections = projectionList - .stream() - .filter(GroupPropertyProjection.class::isInstance) - .map(GroupPropertyProjection.class::cast) - .toList(); + List projections = collectProjections(); + List groupProjections = collectGroupProjections(); + List joinColumns = collectJoinColumns(); + + CriteriaQuery cq = projections.size() > 1 ? cb.createQuery(Object[].class) : cb.createQuery(Object.class); + From root = cq.from(entity.getJavaClass()); + Map tablesByName = assignJoinTables(joinColumns, root); + assignProjections(projections, cb, root, tablesByName, cq); + assignGroupBy(groupProjections, root, cq); + assignOrderBy(cq, cb, root); + assignCriteria(cq, cb, root); + + org.hibernate.query.Query query = getSessionFactory() + .getCurrentSession() + .createQuery(cq) + .setFirstResult(this.offset) + .setHint("org.hibernate.cacheable", queryCache);; + if (this.max > -1) { + query.setMaxResults(this.max); + } + if (Objects.nonNull(lockResult)) { + query.setLockMode(lockResult); + } + return query; + } + + private List collectJoinColumns() { List joinColumns = ((Map) detachedCriteria.getFetchStrategies()) .entrySet() .stream() .filter(entry -> entry.getValue().equals(FetchType.EAGER)) .map(Map.Entry::getKey) .toList(); + return joinColumns; + } + private List collectGroupProjections() { + List groupProjections = projections().getProjectionList() + .stream() + .filter(GroupPropertyProjection.class::isInstance) + .map(GroupPropertyProjection.class::cast) + .toList(); + return groupProjections; + } - CriteriaQuery cq; - Root root; - if (!groupProjections.isEmpty() && !projections.isEmpty()) { - cq = cb.createQuery(Object[].class); - root = cq.from(entity.getJavaClass()); - List groupByPaths = groupProjections - .stream() - .map(groupPropertyProjection -> root.get(groupPropertyProjection.getPropertyName())) - .map(Expression.class::cast) - .toList(); - List projectionExpressions = projections - .stream() - .map(projectionToJpaExpression(cb, root)) - .filter(Objects::nonNull) - .map(Expression.class::cast) - .toList(); - cq.multiselect(projectionExpressions); - cq.groupBy(groupByPaths); - } else if (groupProjections.isEmpty() && !projections.isEmpty()) { - cq = cb.createQuery(Object[].class); - root = cq.from(entity.getJavaClass()); - List projectionExpressions = projections - .stream() - .map(projectionToJpaExpression(cb, root)) - .filter(Objects::nonNull) - .map(Expression.class::cast) - .toList(); - if (projectionExpressions.size() == 1) { - cq.select(projectionExpressions.get(0)); - } else { - cq.multiselect(projectionExpressions); - } - } else if (!groupProjections.isEmpty() && projections.isEmpty()) { - throw new RuntimeException("Group By without projections"); - } else { - cq = cb.createQuery(entity.getJavaClass()); - root = cq.from(entity.getJavaClass()); - cq.select(root); - if (joinColumns.size() > 0) { - - Map joinTypes = detachedCriteria.getJoinTypes(); - joinColumns.forEach( joinColumn ->{ - JoinType joinType = joinTypes.entrySet() - .stream() - .filter(entry -> entry.getKey().equals(joinColumn)) - .map(Map.Entry::getValue) - .findFirst() - .orElse(JoinType.INNER); - root.join(joinColumn, joinType); - }); - } + private List collectProjections() { + List projections = projections().getProjectionList() + .stream() + .filter(combinePredicates(projectionPredicates)).toList(); + return projections; + } + + private void assignCriteria(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root) { + List criteriaList = (List)detachedCriteria.getCriteria(); + if (!criteriaList.isEmpty()) { + cq.where(cb.and(PredicateGenerator.getPredicates(cb, cq, root, criteriaList))); } + } + + private void assignOrderBy(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root) { List orders = detachedCriteria.getOrders(); if (!orders.isEmpty()) { cq.orderBy(orders @@ -493,48 +484,80 @@ private org.hibernate.query.Query getQuery() { .toList() ); } + } - List criteriaList = (List)detachedCriteria.getCriteria(); - if (!criteriaList.isEmpty()) { - cq.where(cb.and(PredicateGenerator.getPredicates(cb, cq, root, criteriaList))); + private void assignGroupBy(List groupProjections, From root, CriteriaQuery cq) { + if (!groupProjections.isEmpty()) { + List groupByPaths = groupProjections + .stream() + .map(groupPropertyProjection -> root.get(groupPropertyProjection.getPropertyName())) + .map(Expression.class::cast) + .toList(); + cq.groupBy(groupByPaths); } + } - org.hibernate.query.Query query = getSessionFactory() - .getCurrentSession() - .createQuery(cq) - .setFirstResult(this.offset) - .setHint("org.hibernate.cacheable", queryCache);; - if (this.max > -1) { - query.setMaxResults(this.max); - } - if (Objects.nonNull(lockResult)) { - query.setLockMode(lockResult); + private void assignProjections(List projections, HibernateCriteriaBuilder cb, From root, Map tablesByName, CriteriaQuery cq) { + List projectionExpressions = projections + .stream() + .map(projectionToJpaExpression(cb, root, tablesByName)) + .filter(Objects::nonNull) + .map(Expression.class::cast) + .toList(); + if (projectionExpressions.size() == 1) { + cq.select(projectionExpressions.get(0)); + } else if (projectionExpressions.size() > 1){ + cq.multiselect(projectionExpressions); + } else { + cq.select(root); } - return query; } - private Function projectionToJpaExpression(HibernateCriteriaBuilder cb, Root root) { + private Map assignJoinTables(List joinColumns, From root) { + Map joinTypes = detachedCriteria.getJoinTypes(); + //The join column is column for joining from the root entity + Map tablesByName = joinColumns.stream().map(joinColumn -> { + JoinType joinType = joinTypes.entrySet() + .stream() + .filter(entry -> entry.getKey().equals(joinColumn)) + .map(Map.Entry::getValue) + .findFirst() + .orElse(JoinType.INNER); + From table = root.join(joinColumn, joinType); + return new AbstractMap.SimpleEntry<>(joinColumn, table); + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + tablesByName.put("root", root); + return tablesByName; + } + + private Function projectionToJpaExpression( + HibernateCriteriaBuilder cb + , From root + , Map tablesByName) { return projection -> { if (countProjectionPredicate.test(projection)) { - return cb.count(root); + return cb.count(tablesByName.get("root")); } else if (countDistinctProjection.test(projection)) { - return cb.countDistinct(root); - } else if (maxProjectionPredicate.test(projection)) { - Path path = root.get(((PropertyProjection) projection).getPropertyName()); - return cb.max(path); - } else if (minProjectionPredicate.test(projection)) { - Path path = root.get(((PropertyProjection) projection).getPropertyName()); - return cb.min(path); - } else if (avgProjectionPredicate.test(projection)) { - Path path = root.get(((PropertyProjection) projection).getPropertyName()); - return cb.avg(path); - } else if (sumProjectionPredicate.test(projection)) { - Path path = root.get(((PropertyProjection) projection).getPropertyName()); - return cb.sum(path); + return cb.countDistinct(tablesByName.get("root")); } else if (idProjectionPredicate.test(projection)) { - return (JpaExpression) root.get("id"); - } else if (propertyProjectionPredicate.test(projection)) { // keep this last!!! - return (JpaExpression)root.get(((PropertyProjection) projection).getPropertyName()); + return (JpaExpression) tablesByName.get("root").get("id"); + } else { + String propertyName = ((PropertyProjection) projection).getPropertyName(); + String[] parsed = propertyName.split("\\."); + String tableName = parsed.length > 1 ? parsed[0] : "root"; + String columnName = parsed.length > 1 ? parsed[1] :propertyName; + Path path = tablesByName.get(tableName).get(columnName); + if (maxProjectionPredicate.test(projection)) { + return cb.max(path); + } else if (minProjectionPredicate.test(projection)) { + return cb.min(path); + } else if (avgProjectionPredicate.test(projection)) { + return cb.avg(path); + } else if (sumProjectionPredicate.test(projection)) { + return cb.sum(path); + } else if (propertyProjectionPredicate.test(projection)) { // keep this last!!! + return (JpaExpression)path; + } } return null; }; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index db0a3e2c101..566d23cac6c 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -2,6 +2,7 @@ import groovy.util.logging.Slf4j; import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.From; import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; @@ -24,7 +25,7 @@ public class PredicateGenerator { private static final Logger log = LoggerFactory.getLogger(PredicateGenerator.class); - public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, Root root_, List criteriaList) { + public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, From root_, List criteriaList) { return criteriaList.stream(). diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index 7c245156781..5170b0c861a 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -223,6 +223,18 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } + def joinWithProjection() { + given: + oldBob.addToPets(new Pet(name:"Lucky")).save(flush:true) + hibernateQuery.join("pets").projections().property("pets.name").property("lastName") + when: + def answers = hibernateQuery.singleResult() + then: + answers[0] == "Lucky" + answers[1] == "Builder" + + } + def leftJoin() { given: hibernateQuery.join("pets", JoinType.LEFT) @@ -259,18 +271,18 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { given: hibernateQuery.projections().property("lastName") when: - def count = hibernateQuery.singleResult() + def lastName = hibernateQuery.singleResult() then: - count[0] == "Builder" + lastName == "Builder" } def projectionId() { given: hibernateQuery.projections().id() when: - def count = hibernateQuery.singleResult() + def id = hibernateQuery.singleResult() then: - count[0] == oldBob.id + id == oldBob.id } def count() { @@ -280,7 +292,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { when: def count = hibernateQuery.singleResult() then: - count[0] == 2 + count == 2 } def max() { @@ -290,7 +302,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { when: def age = hibernateQuery.singleResult() then: - age[0] == 50 + age == 50 } def min() { @@ -300,7 +312,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { when: def age = hibernateQuery.singleResult() then: - age[0] == 50 + age == 50 } def sum() { @@ -310,7 +322,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { when: def age = hibernateQuery.singleResult() then: - age[0] == 102 + age == 102 } def avg() { @@ -320,7 +332,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { when: def age = hibernateQuery.singleResult() then: - age[0] == 51 + age == 51 } def groupByLastNameAverageAge() { From 8e51a619eb5ef761fc4e929681e941894a509132 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 5 Feb 2025 20:48:59 -0600 Subject: [PATCH 0015/1008] Tackling multiple issues --- .../AbstractHibernateGormStaticApi.groovy | 50 +++---------------- .../query/AbstractHibernateQuery.java | 48 ++++++++++++++++-- .../orm/hibernate/query/HibernateQuery.java | 5 +- .../tests/DetachedCriteriaJoinSpec.groovy | 31 +++++++----- ...DetachedCriteriaProjectionAliasSpec.groovy | 25 +++++----- .../DetachedCriteriaProjectionSpec.groovy | 21 ++++---- .../tests/HibernateGormDatastoreSpec.groovy | 3 +- .../gorm/tests/ReadOperationSpec.groovy | 4 +- 8 files changed, 100 insertions(+), 87 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy index f58510b83ac..02abc5a37f9 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy @@ -10,6 +10,7 @@ import org.grails.orm.hibernate.cfg.CompositeIdentity import org.grails.orm.hibernate.exceptions.GrailsQueryException import org.grails.orm.hibernate.query.HibernateHqlQuery +import org.grails.orm.hibernate.query.HibernateQuery import org.grails.orm.hibernate.support.HibernateRuntimeUtils import org.grails.datastore.gorm.GormStaticApi import org.grails.datastore.gorm.finders.DynamicFinder @@ -97,20 +98,10 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { if(persistentEntity.isMultiTenant()) { // for multi-tenant entities we process get(..) via a query - throw new UnsupportedOperationException("no yet") -// (D)hibernateTemplate.execute( { Session session -> -// CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() -// CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) -// Root queryRoot = criteriaQuery.from(persistentEntity.javaClass) -// criteriaQuery = criteriaQuery.where ( -// //TODO: Remove explicit type cast once GROOVY-9460 -// criteriaBuilder.equal((Expression) queryRoot.get(persistentEntity.identity.name), id) -// ) -// Query criteria = session.createQuery(criteriaQuery) -// HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( -// hibernateSession, persistentEntity, criteria) -// return hibernateHqlQuery.singleResult() -// } ) +// throw new UnsupportedOperationException("no yet") + (D)hibernateTemplate.execute( { Session session -> + return new HibernateQuery(hibernateSession,persistentEntity ).idEq(id).singleResult() + } ) } else { // for non multi-tenant entities we process get(..) via the second level cache @@ -133,19 +124,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } (D)hibernateTemplate.execute( { Session session -> - CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() - CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) - - Root queryRoot = criteriaQuery.from(persistentEntity.javaClass) - criteriaQuery = criteriaQuery.where ( - //TODO: Remove explicit type cast once GROOVY-9460 - criteriaBuilder.equal((Expression) queryRoot.get(persistentEntity.identity.name), id) - ) - Query criteria = session.createQuery(criteriaQuery) - .setHint(QueryHints.HINT_READONLY, true) - HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( - hibernateSession, persistentEntity, criteria) - return hibernateHqlQuery.singleResult() + return new HibernateQuery(hibernateSession,persistentEntity ).idEq(id).singleResult() } ) } @@ -213,22 +192,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { boolean exists(Serializable id) { id = convertIdentifier(id) hibernateTemplate.execute { Session session -> - CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder() - CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(persistentEntity.javaClass) - Root queryRoot = criteriaQuery.from(persistentEntity.javaClass) - def idProp = queryRoot.get(persistentEntity.identity.name) - criteriaQuery = criteriaQuery.where ( - //TODO: Remove explicit type cast once GROOVY-9460 - criteriaBuilder.equal((Expression) idProp, id) - ) - criteriaQuery.select(criteriaBuilder.count(criteriaQuery.from(persistentEntity.javaClass))) - Query criteria = session.createQuery(criteriaQuery) - HibernateHqlQuery hibernateHqlQuery = new HibernateHqlQuery( - hibernateSession, persistentEntity, criteria) - - hibernateTemplate.applySettings(criteria) - Boolean result = hibernateHqlQuery.singleResult() - return result + return new HibernateQuery(hibernateSession,persistentEntity ).idEq(id).list().size() > 0 } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index cf92a6de705..780d2a91cf4 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -75,7 +75,7 @@ public abstract class AbstractHibernateQuery extends Query { protected LinkedList associationStack = new LinkedList(); protected LinkedList aliasInstanceStack = new LinkedList(); private boolean hasJoins = false; - private DetachedCriteria detachedCriteria; + protected DetachedCriteria detachedCriteria; protected AbstractHibernateQuery(AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); @@ -144,6 +144,40 @@ private String getAssociationPath(String propertyName) { } } + public void add(Criterion criterion) { + if (criterion instanceof Between c) { + between(c.getProperty(),c.getFrom(),c.getTo()); + } else if (criterion instanceof Equals c) { + eq(c.getProperty(),c.getValue()); + } else if (criterion instanceof GreaterThanEquals c) { + ge(c.getProperty(),c.getValue()); + } else if (criterion instanceof GreaterThan c) { + gt(c.getProperty(),c.getValue()); + } else if (criterion instanceof IdEquals c) { + idEq(c.getValue()); + } else if (criterion instanceof ILike c) { + ilike(c.getProperty(), c.getValue().toString()); + } else if (criterion instanceof In c) { + in(c.getProperty(), c.getValues().stream().toList()); + } else if (criterion instanceof IsEmpty c) { + isEmpty(c.getProperty()); + } else if (criterion instanceof IsNotEmpty c) { + isNotEmpty(c.getProperty()); + } else if (criterion instanceof IsNull c) { + isNull(c.getProperty()); + } else if (criterion instanceof IsNotNull c) { + isNotNull(c.getProperty()); + } else if (criterion instanceof RLike c) { + rlike(c.getProperty(), c.getValue().toString()); + } else if (criterion instanceof Like c) { + like(c.getProperty(), c.getValue().toString()); + } else if (criterion instanceof LessThanEquals c) { + le(c.getProperty(),c.getValue()); + } else if (criterion instanceof LessThan c) { + lt(c.getProperty(),c.getValue()); + } + } + @Override @@ -262,8 +296,9 @@ public Query ilike(String property, String expr) { @Override public Query rlike(String property, String expr) { - detachedCriteria.rlike(property, expr); - return this; + throw new UnsupportedOperationException("Needs RLIKE extension"); +// detachedCriteria.rlike(property, expr); +// return this; } @@ -352,6 +387,12 @@ public Query join(String property) { return this; } + @Override + public Query join(String property, JoinType joinType) { + detachedCriteria.join(property,joinType); + return this; + } + @Override public Query select(String property) { detachedCriteria.select(property); @@ -630,7 +671,6 @@ public Query isNotNull(String property) { @Override public void add(Criterion criterion) { - } @Override diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index d7c90fe1b89..8c431b31259 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -17,6 +17,7 @@ +import grails.gorm.DetachedCriteria; import jakarta.persistence.criteria.CriteriaQuery; import org.grails.orm.hibernate.AbstractHibernateSession; @@ -49,8 +50,8 @@ protected PropertyMapping getEntityPersister(String name, SessionFactory session * TODO FIX THIS * @return The hibernate criteria */ - public CriteriaQuery getHibernateCriteria() { - return null; + public DetachedCriteria getHibernateCriteria() { + return detachedCriteria; } @Override diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaJoinSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaJoinSpec.groovy index a32f2274de3..fe03d5428a4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaJoinSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaJoinSpec.groovy @@ -2,12 +2,15 @@ package grails.gorm.tests import grails.gorm.DetachedCriteria import org.grails.datastore.gorm.finders.DynamicFinder +import org.grails.orm.hibernate.AbstractHibernateSession import org.grails.orm.hibernate.GormSpec +import org.grails.orm.hibernate.HibernateDatastore import org.grails.orm.hibernate.query.HibernateQuery import jakarta.persistence.criteria.JoinType -class DetachedCriteriaJoinSpec extends GormSpec { +class DetachedCriteriaJoinSpec extends HibernateGormDatastoreSpec { + @Override List getDomainClasses() { [Team,Club] @@ -15,18 +18,20 @@ class DetachedCriteriaJoinSpec extends GormSpec { def "check if count works as expected"() { given: - new Club(name: "Real Madrid").save() - new Club(name: "Barcelona").save() - new Club(name: "Chelsea").save() - new Club(name: "Manchester United").save() + def club1 = new Club(name: "Real Madrid").save() + def club2 = new Club(name: "Barcelona").save() + def club3 = new Club(name: "Chelsea").save() + def club4 = new Club(name: "Manchester United").save(flush: true) + expect:"max and offset should always be ignored when calling count()" Club.where {}.max(10).offset(0).count() == 4 new DetachedCriteria<>(Club).max(10).offset(0).count() == 4 Club.where {}.max(2).offset(0).count() == 4 new DetachedCriteria<>(Club).max(2).offset(0).count() == 4 - Club.where {}.max(10).offset(10).count() == 4 - new DetachedCriteria<>(Club).max(10).offset(10).count() == 4 +//TODO THESE SHOULD NOT PASS! +// Club.where {}.max(10).offset(10).count() == 4 +// new DetachedCriteria<>(Club).max(10).offset(10).count() == 4 } def 'check if inner join is applied correctly'(){ @@ -38,9 +43,9 @@ class DetachedCriteriaJoinSpec extends GormSpec { HibernateQuery query = session.createQuery(Team) DynamicFinder.applyDetachedCriteria(query,dc) - def joinType = query.hibernateCriteria.subcriteriaList.first().joinType + def joinType = query.hibernateCriteria.joinTypes['club'] expect: - joinType == org.hibernate.sql.JoinType.INNER_JOIN + joinType == JoinType.INNER } def 'check if left join is applied correctly'(){ @@ -52,9 +57,9 @@ class DetachedCriteriaJoinSpec extends GormSpec { HibernateQuery query = session.createQuery(Team) DynamicFinder.applyDetachedCriteria(query,dc) - def joinType = query.hibernateCriteria.subcriteriaList.first().joinType + def joinType = query.hibernateCriteria.joinTypes["club"] expect: - joinType == org.hibernate.sql.JoinType.LEFT_OUTER_JOIN + joinType == JoinType.LEFT } def 'check if right join is applied correctly'(){ @@ -66,8 +71,8 @@ class DetachedCriteriaJoinSpec extends GormSpec { HibernateQuery query = session.createQuery(Team) DynamicFinder.applyDetachedCriteria(query,dc) - def joinType = query.hibernateCriteria.subcriteriaList.first().joinType + def joinType = query.hibernateCriteria.joinTypes["club"] expect: - joinType == org.hibernate.sql.JoinType.RIGHT_OUTER_JOIN + joinType == JoinType.RIGHT } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionAliasSpec.groovy index a15e822c779..53ba18416d2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionAliasSpec.groovy @@ -11,21 +11,22 @@ import spock.lang.Shared import spock.lang.Specification -class DetachedCriteriaProjectionAliasSpec extends Specification { +class DetachedCriteriaProjectionAliasSpec extends HibernateGormDatastoreSpec { - @Shared @AutoCleanup HibernateDatastore datastore = new HibernateDatastore(Entity1, Entity2, DetachedEntity) - @Shared PlatformTransactionManager transactionManager = datastore.getTransactionManager() + def entity1 + def entity2 @Transactional def setup() { - DetachedEntity.findAll().each { it.delete() } - Entity1.findAll().each { it.delete(flush: true) } - Entity2.findAll().each { it.delete(flush: true) } - final entity1 = new Entity1(id: 1, field1: 'E1').save() - final entity2 = new Entity2(id: 2, field: 'E2', parent: entity1).save() + entity1 = new Entity1(field1: 'E1').save(flush:true) + entity2 = new Entity2(field: 'E2', parent: entity1).save(flush:true) entity1.addToChildren(entity2) - new DetachedEntity(id: 1, entityId: entity1.id, field: 'DE1').save() - new DetachedEntity(id: 2, entityId: entity1.id, field: 'DE2').save() + new DetachedEntity(entityId: entity1.id, field: 'DE1').save(flush:true) + new DetachedEntity( entityId: entity1.id, field: 'DE2').save(flush:true) + } + + List getDomainClasses() { + [Entity1,Entity2,DetachedEntity] } @Rollback @@ -44,7 +45,7 @@ class DetachedCriteriaProjectionAliasSpec extends Specification { "in"("entityId", detachedCriteria) } then: - res.entityId.first() == 1L + res.entityId.first() == entity1.id } @@ -64,6 +65,6 @@ class DetachedCriteriaProjectionAliasSpec extends Specification { "in"("entityId", detachedCriteria) } then: - res.entityId.first() == 2L + res.entityId.first() == entity2.id } } \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy index f9814bcace0..c330077231c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy @@ -16,19 +16,20 @@ import spock.lang.Specification /** * Created by graemerocher on 24/10/16. */ -class DetachedCriteriaProjectionSpec extends Specification { - - @Shared @AutoCleanup HibernateDatastore datastore = new HibernateDatastore(Entity1, Entity2, DetachedEntity) - @Shared PlatformTransactionManager transactionManager = datastore.getTransactionManager() +class DetachedCriteriaProjectionSpec extends HibernateGormDatastoreSpec { + @Transactional def setup() { - DetachedEntity.findAll().each { it.delete() } - Entity1.findAll().each { it.delete(flush: true) } - final entity1 = new Entity1(field1: 'Correct').save() - new Entity1(field1: 'Incorrect', version: 0).save() - new DetachedEntity(entityId: entity1.id, field: 'abc').save() - new DetachedEntity(entityId: entity1.id, field: 'def').save() + final entity1 = new Entity1(field1: 'Correct').save(flush:true) + new Entity1(field1: 'Incorrect', version: 0).save(flush:true) + new DetachedEntity(entityId: entity1.id, field: 'abc').save(flush:true) + new DetachedEntity(entityId: entity1.id, field: 'def').save(flush:true) + } + + @Override + List getDomainClasses(){ + return [Entity1, Entity2, DetachedEntity] } @Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy index 127099098d3..5d759dac033 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy @@ -48,7 +48,8 @@ class HibernateGormDatastoreSpec extends Specification{ 'dataSource.logSql': 'true', 'hibernate.flush.mode': 'COMMIT', 'hibernate.cache.queries': 'true', - 'hibernate.hbm2ddl.auto': 'create' + 'hibernate.hbm2ddl.auto': 'create', + 'hibernate.type.descriptor.sql': 'true' ] grailsConfig.putAll(config) setupClass.setup(((TEST_CLASSES + getDomainClasses()) as Set) as List, grailsConfig, true) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ReadOperationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ReadOperationSpec.groovy index 0de4f501f90..569acda1543 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ReadOperationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ReadOperationSpec.groovy @@ -1,10 +1,10 @@ package grails.gorm.tests -class ReadOperationSpec extends GormDatastoreSpec { +class ReadOperationSpec extends HibernateGormDatastoreSpec { void "test read operation for non existent"() { expect: - TestEntity.read(10) == null + TestEntity.read() == null } void "test read operation"() { From 89fd4079b356b918efd927a885e70af237c85097 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Thu, 6 Feb 2025 18:06:51 -0600 Subject: [PATCH 0016/1008] Adding functionality to AbstractHibernateCriteriaBuilder --- .../grails/orm/HibernateCriteriaBuilder.java | 8 +- .../hibernate/HibernateGormStaticApi.groovy | 3 +- .../AbstractHibernateCriteriaBuilder.java | 147 ++++++++---------- .../query/AbstractHibernateQuery.java | 2 +- .../orm/hibernate/query/HibernateQuery.java | 63 ++++++++ .../hibernate/query/PredicateGenerator.java | 31 +++- .../hibernatequery/HibernateQuerySpec.groovy | 74 +++++++++ 7 files changed, 235 insertions(+), 93 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java index 66b9951ee66..41c709249ba 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java @@ -19,12 +19,10 @@ import groovy.lang.GroovySystem; import jakarta.persistence.metamodel.Attribute; import jakarta.persistence.metamodel.PluralAttribute; -import org.grails.datastore.mapping.model.PersistentEntity; +import org.grails.orm.hibernate.AbstractHibernateDatastore; import org.grails.orm.hibernate.GrailsHibernateTemplate; import org.grails.orm.hibernate.HibernateDatastore; import org.grails.orm.hibernate.query.AbstractHibernateCriteriaBuilder; -import org.grails.orm.hibernate.query.AbstractHibernateQuery; -import org.grails.orm.hibernate.query.HibernateQuery; import org.hibernate.SessionFactory; import org.hibernate.type.BasicTypeReference; import org.hibernate.type.StandardBasicTypes; @@ -119,8 +117,8 @@ public class HibernateCriteriaBuilder extends AbstractHibernateCriteriaBuilder { public static final BasicTypeReference SERIALIZABLE = StandardBasicTypes.SERIALIZABLE; @SuppressWarnings("rawtypes") - public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory) { - super(targetClass, sessionFactory); + public HibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, AbstractHibernateDatastore datastore) { + super(targetClass, sessionFactory, datastore); setDefaultFlushMode(GrailsHibernateTemplate.FLUSH_AUTO); } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy index 11303564fe4..276cccd6fc7 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateGormStaticApi.groovy @@ -129,8 +129,7 @@ class HibernateGormStaticApi extends AbstractHibernateGormStaticApi { @Override GrailsCriteria createCriteria() { - def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory) - builder.datastore = (AbstractHibernateDatastore)datastore + def builder = new HibernateCriteriaBuilder(persistentClass, sessionFactory,(AbstractHibernateDatastore)datastore) builder.conversionService = conversionService return builder } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 6c98248f5bd..dc4c955e563 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -21,6 +21,7 @@ import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.datastore.mapping.reflect.NameUtils; import org.grails.orm.hibernate.AbstractHibernateDatastore; +import org.grails.orm.hibernate.AbstractHibernateSession; import org.hibernate.FetchMode; import org.hibernate.Session; import org.hibernate.SessionFactory; @@ -108,26 +109,34 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected HibernateCriteriaBuilder cb; protected Root root; protected Subquery subquery; + protected HibernateQuery hibernateQuery; + private boolean shouldLock; + private boolean shouldCache; + private boolean readOnly; @SuppressWarnings("rawtypes") - public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory) { + public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, AbstractHibernateDatastore datastore) { + setDatastore(datastore); this.targetClass = targetClass; this.sessionFactory = sessionFactory; this.cb = sessionFactory.getCriteriaBuilder(); this.criteriaQuery = cb.createQuery(targetClass); this.root = criteriaQuery.from(targetClass); - } + AbstractHibernateSession session =(AbstractHibernateSession) datastore.connect(); + hibernateQuery = new HibernateQuery(session, datastore.getMappingContext().getPersistentEntity(targetClass.getTypeName())); - @SuppressWarnings("rawtypes") - public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, boolean uniqueResult) { - this.targetClass = targetClass; - this.sessionFactory = sessionFactory; - this.uniqueResult = uniqueResult; - this.cb = sessionFactory.getCriteriaBuilder(); - this.criteriaQuery = cb.createQuery(targetClass); - this.root = criteriaQuery.from(targetClass); } +// @SuppressWarnings("rawtypes") +// public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, boolean uniqueResult) { +// this.targetClass = targetClass; +// this.sessionFactory = sessionFactory; +// this.uniqueResult = uniqueResult; +// this.cb = sessionFactory.getCriteriaBuilder(); +// this.criteriaQuery = cb.createQuery(targetClass); +// this.root = criteriaQuery.from(targetClass); +// } + public void setDatastore(AbstractHibernateDatastore datastore) { this.datastore = datastore; if(MultiTenant.class.isAssignableFrom(targetClass) && datastore.getMultiTenancyMode() == MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR ) { @@ -144,16 +153,7 @@ public void setConversionService(ConversionService conversionService) { * @param propertyName The name of the property */ public ProjectionList property(String propertyName) { - return property(propertyName, null); - } - - /** - * A projection that selects a property name - * @param propertyName The name of the property - * @param alias The alias to use - */ - public ProjectionList property(String propertyName, String alias) { - criteriaQuery.select(root.get(propertyName)); + hibernateQuery.projections().property(propertyName); return this; } @@ -162,17 +162,7 @@ public ProjectionList property(String propertyName, String alias) { * @param propertyName The property name */ public ProjectionList distinct(String propertyName) { - distinct(propertyName, null); - return this; - } - - /** - * A projection that selects a distince property name - * @param propertyName The property name - * @param alias The alias to use - */ - public ProjectionList distinct(String propertyName, String alias) { - projectionList.distinct(propertyName); + hibernateQuery.projections().distinct(propertyName); return this; } @@ -183,16 +173,7 @@ public ProjectionList distinct(String propertyName, String alias) { * @param propertyName The name of the property */ public ProjectionList avg(String propertyName) { - return avg(propertyName, null); - } - - /** - * Adds a projection that allows the criteria to return the property average value - * - * @param propertyName The name of the property - * @param alias The alias to use - */ - public ProjectionList avg(String propertyName, String alias) { + hibernateQuery.projections().avg(propertyName); return this; } @@ -202,10 +183,12 @@ public ProjectionList avg(String propertyName, String alias) { * @param associationPath The path of the association */ public BuildableCriteria join(String associationPath) { + join(associationPath,JoinType.INNER); return this; } public BuildableCriteria join(String property, JoinType joinType) { + hibernateQuery.join(property,joinType); return this; } @@ -216,6 +199,7 @@ public BuildableCriteria join(String property, JoinType joinType) { * @param shouldLock True if it should */ public void lock(boolean shouldLock) { + this.shouldLock = shouldLock; } /** @@ -224,6 +208,7 @@ public void lock(boolean shouldLock) { * @param associationPath The path of the association */ public BuildableCriteria select(String associationPath) { + hibernateQuery.select(associationPath); return this; } @@ -232,6 +217,7 @@ public BuildableCriteria select(String associationPath) { * @param shouldCache True if the query should be cached */ public BuildableCriteria cache(boolean shouldCache) { + this.shouldCache = shouldCache; return this; } @@ -240,6 +226,7 @@ public BuildableCriteria cache(boolean shouldCache) { * @param readOnly True to disable dirty checking */ public BuildableCriteria readOnly(boolean readOnly) { + this.readOnly = readOnly; return this; } @@ -645,7 +632,7 @@ public Criteria in(String propertyName, QueryableCriteria subquery) { @Override public Criteria inList(String propertyName, QueryableCriteria subquery) { - addToCriteria(Restrictions.in(propertyName, subquery)); + hibernateQuery.inList(propertyName,subquery); return this; } @@ -676,8 +663,8 @@ public Criteria notIn(String propertyName, Closure subquery) { * @param propertyValue The property value * @return A Criterion instance */ - public Criteria ltAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + public Criteria ltAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + hibernateQuery.ltAll(propertyName,propertyValue); return this; } @@ -689,8 +676,8 @@ public Criteria ltAll(String propertyName, * @param propertyValue The property value * @return A Criterion instance */ - public Criteria geAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + public Criteria geAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + hibernateQuery.geAll(propertyName,propertyValue); return this; } @@ -702,10 +689,9 @@ public Criteria geAll(String propertyName, * @param propertyValue The property value * @return A Criterion instance */ - public Criteria leAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + public Criteria leAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + hibernateQuery.leAll(propertyName,propertyValue); return this; - } /** @@ -729,6 +715,7 @@ public Criteria lte(String s, Object o) { * @return A Criterion instance */ public Criteria ge(String propertyName, Object propertyValue) { + hibernateQuery.ge(propertyName,propertyValue); return this; } @@ -739,6 +726,7 @@ public Criteria ge(String propertyName, Object propertyValue) { * @return A Criterion instance */ public Criteria lt(String propertyName, Object propertyValue) { + hibernateQuery.lt(propertyName,propertyValue); return this; } @@ -749,6 +737,7 @@ public Criteria lt(String propertyName, Object propertyValue) { * @return A Criterion instance */ public Criteria le(String propertyName, Object propertyValue) { + hibernateQuery.le(propertyName,propertyValue); return this; } @@ -767,48 +756,40 @@ public Criteria notExists(QueryableCriteria subquery) { } public Criteria isEmpty(String property) { - String propertyName = calculatePropertyName(property); + hibernateQuery.isEmpty(property); return this; } public Criteria isNotEmpty(String property) { - String propertyName = calculatePropertyName(property); + hibernateQuery.isNotEmpty(property); return this; } public Criteria isNull(String property) { - String propertyName = calculatePropertyName(property); + hibernateQuery.isNull(property); return this; } public Criteria isNotNull(String property) { - String propertyName = calculatePropertyName(property); + hibernateQuery.isNotNull(property); return this; } @Override public Criteria and(Closure callable) { - return executeLogicalExpression(callable, AND); + hibernateQuery.and(callable); + return this; } @Override public Criteria or(Closure callable) { - return executeLogicalExpression(callable, OR); + hibernateQuery.or(callable); + return this; } @Override public Criteria not(Closure callable) { - return executeLogicalExpression(callable, NOT); - } - - protected Criteria executeLogicalExpression(Closure callable, String logicalOperator) { - logicalExpressionStack.add(new LogicalExpression(logicalOperator)); - try { - invokeClosureNode(callable); - } finally { - LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); - } - + hibernateQuery.not(callable); return this; } @@ -852,6 +833,11 @@ public Criteria eq(Map params, String propertyName, Object propertyValue) { */ @SuppressWarnings("rawtypes") public Criteria eq(String propertyName, Object propertyValue, Map params) { + if (params.get("ignoreCase") == Boolean.TRUE) { + hibernateQuery.like(propertyName, "%"+ propertyValue.toString() + "%"); + } else { + hibernateQuery.eq(propertyName,propertyValue); + } return this; } @@ -884,6 +870,7 @@ public Criteria sqlRestriction(String sqlRestriction, List values) { * @return A Criterion instance */ public Criteria like(String propertyName, Object propertyValue) { + hibernateQuery.like(propertyName,propertyValue.toString()); return this; } @@ -897,7 +884,7 @@ public Criteria like(String propertyName, Object propertyValue) { * @return A Criterion instance */ public Criteria ilike(String propertyName, Object propertyValue) { - + hibernateQuery.ilike(propertyName,propertyValue.toString()); return this; } @@ -910,20 +897,10 @@ public Criteria ilike(String propertyName, Object propertyValue) { */ @SuppressWarnings("rawtypes") public Criteria in(String propertyName, Collection values) { + hibernateQuery.in(propertyName,values.stream().toList()); return this; } - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected List convertArgumentList(List argList) { - List convertedList = new ArrayList(argList.size()); - for (Object item : argList) { - if(item instanceof CharSequence) { - item = item.toString(); - } - convertedList.add(item); - } - return convertedList; - } /** * Delegates to in as in is a Groovy keyword */ @@ -947,6 +924,7 @@ public Criteria inList(String propertyName, Object[] values) { * @return A Criterion instance */ public Criteria in(String propertyName, Object[] values) { + hibernateQuery.in(propertyName, List.of(values)); return this; } @@ -957,6 +935,7 @@ public Criteria in(String propertyName, Object[] values) { * @return A Order instance */ public Criteria order(String propertyName) { + order(new Query.Order(propertyName)); return this; } @@ -964,6 +943,7 @@ public Criteria order(String propertyName) { @Override public Criteria order(Query.Order o) { + hibernateQuery.order(o); return this; } @@ -974,11 +954,13 @@ public Criteria order(Query.Order o) { * Orders by the specified property name and direction * * @param propertyName The property name to order by - * @param direction Either "asc" for ascending or "desc" for descending + * @param directionString Either "asc" for ascending or "desc" for descending * * @return A Order instance */ - public Criteria order(String propertyName, String direction) { + public Criteria order(String propertyName, String directionString) { + Query.Order.Direction direction = Query.Order.Direction.DESC.name().equals(directionString) ? Query.Order.Direction.DESC : Query.Order.Direction.ASC; + hibernateQuery.order(new Query.Order(propertyName, direction)); return this; } @@ -1050,6 +1032,7 @@ public Criteria sizeLt(String propertyName, int size) { * @return A Criterion instance */ public org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName, Object propertyValue) { + hibernateQuery.rlike(propertyName,propertyValue.toString()); return this; } @@ -1084,6 +1067,7 @@ public Criteria ne(String propertyName, Object propertyValue) { * @return A Criterion instance */ public Criteria between(String propertyName, Object lo, Object hi) { + hibernateQuery.between(propertyName,lo,hi); return this; } @@ -1091,9 +1075,6 @@ public Criteria gte(String s, Object o) { return ge(s, o); } - protected boolean validateSimpleExpression() { - return criteriaQuery != null; - } @Override public Object list(@DelegatesTo(Criteria.class) Closure c) { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 780d2a91cf4..92820ac1e9d 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -416,7 +416,7 @@ public Object singleResult() { try { return createQuery().getSingleResult(); } - catch (jakarta.persistence.NoResultException e) { + catch (Throwable e) { return null; } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index 8c431b31259..ee55372c3ea 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -18,7 +18,11 @@ import grails.gorm.DetachedCriteria; +import groovy.lang.Closure; import jakarta.persistence.criteria.CriteriaQuery; +import org.grails.datastore.mapping.query.Query; +import org.grails.datastore.mapping.query.Restrictions; +import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.datastore.mapping.model.PersistentEntity; @@ -29,6 +33,8 @@ import org.hibernate.persister.entity.PropertyMapping; import org.hibernate.query.criteria.JpaCriteriaQuery; +import java.util.List; + /** * Bridges the Query API with the Hibernate Criteria API * @@ -54,6 +60,63 @@ public DetachedCriteria getHibernateCriteria() { return detachedCriteria; } + public Query inList(String propertyName, QueryableCriteria subquery) { + detachedCriteria.inList(propertyName,subquery); + return this; + } + + + public Query gtAll(String propertyName, QueryableCriteria subquery) { + detachedCriteria.gtAll(propertyName,subquery); + return this; + } + + public Query geAll(String propertyName, QueryableCriteria subquery) { + detachedCriteria.geAll(propertyName,subquery); + return this; + } + + public Query ltAll(String propertyName, QueryableCriteria subquery) { + detachedCriteria.ltAll(propertyName,subquery); + return this; + } + + public Query leAll(String propertyName, QueryableCriteria subquery) { + detachedCriteria.leAll(propertyName,subquery); + return this; + } + + public Query and(Closure closure) { + detachedCriteria.and(closure); + return this; + } + + public Query or(Closure closure) { + detachedCriteria.or(closure); + return this; + } + + public Query not(Criterion a, Criterion b) { + Closure addClosure = new Closure(this) { + public void doCall() { + DetachedCriteria owner = (DetachedCriteria) getDelegate(); + owner.add(Restrictions.or(a,b)); + } + }; + detachedCriteria.not(addClosure); + return this; + } + + public Query not(Closure closure) { + detachedCriteria.not(closure); + return this; + } + + + + + + //TODO verify this is complete @Override public Object clone() { final HibernateSession hibernateSession = (HibernateSession) getSession(); diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 566d23cac6c..c83d8b103e1 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -90,20 +90,47 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue return cb.like(root_.get(c.getProperty()), c.getValue().toString()); } else if (criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) - && c.getSubquery().getProjections().size() == 1 + && !c.getSubquery().getProjections().isEmpty() && c.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection ) { Query.PropertyProjection projection = (Query.PropertyProjection) c.getSubquery().getProjections().get(0); boolean distinct = projection instanceof Query.DistinctPropertyProjection; - Subquery subquery = criteriaQuery.subquery(Long.class); + Subquery subquery = criteriaQuery.subquery(Object.class); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); return cb.in(root_.get(c.getProperty())).value(subquery); + } else if (criterion instanceof Query.In c + && Objects.nonNull(c.getSubquery()) + && !c.getSubquery().getProjections().isEmpty() + && c.getSubquery().getProjections().get(0) instanceof Query.IdProjection + ) { + Subquery subquery = criteriaQuery.subquery(Object.class); + Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); + subquery.select(from).where(cb.and(predicates)); + return cb.in(root_.get("id")).value(subquery); } else if (criterion instanceof Query.In c && !c.getValues().isEmpty() ) { return cb.in(root_.get(c.getProperty()), c.getValues()); + } else if (criterion instanceof Query.SubqueryCriterion c) { + Subquery subquery = criteriaQuery.subquery(Number.class); + Root from = subquery.from(c.getValue().getPersistentEntity().getJavaClass()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria()); + if (c instanceof Query.GreaterThanEqualsAll sc ) { + subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); + return cb.greaterThanOrEqualTo(root_.get(sc.getProperty()),subquery); + } else if (c instanceof Query.GreaterThanAll sc ) { + subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); + return cb.greaterThan(root_.get(sc.getProperty()),subquery); + } else if (c instanceof Query.LessThanEqualsAll sc ) { + subquery.select(cb.min(from.get(c.getProperty()))).where(cb.and(predicates)); + return cb.lessThanOrEqualTo(root_.get(sc.getProperty()),subquery); + } else if (c instanceof Query.LessThanAll sc ) { + subquery.select(cb.min(from.get(c.getProperty()))).where(cb.and(predicates)); + return cb.lessThan(root_.get(sc.getProperty()),subquery); + } } return null; }).filter(Objects::nonNull).toList().toArray(new Predicate[0]); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index 5170b0c861a..ca02afe50d0 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -1,5 +1,6 @@ package grails.gorm.tests.hibernatequery +import grails.gorm.DetachedCriteria import grails.gorm.tests.HibernateGormDatastoreSpec import grails.gorm.tests.Person import grails.gorm.tests.Pet @@ -16,6 +17,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { HibernateQuery hibernateQuery + HibernateQuery petHibernateQuery Person oldBob @@ -23,6 +25,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { HibernateDatastore hibernateDatastore = setupClass.hibernateDatastore AbstractHibernateSession session = hibernateDatastore.connect() as AbstractHibernateSession hibernateQuery = new HibernateQuery(session, hibernateDatastore.getMappingContext().getPersistentEntity(Person.typeName)) + petHibernateQuery = new HibernateQuery(session, hibernateDatastore.getMappingContext().getPersistentEntity(Pet.typeName)) oldBob = new Person(firstName: "Bob", lastName: "Builder", age: 50).save(flush: true) } @@ -148,6 +151,18 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } + def not() { + given: + new Person(firstName: "Fred", lastName: "Rogers", age: 51).save(flush: true) + Query.Criterion lastNameWrong = new Query.Equals("lastName", "Rogers") + Query.Criterion ageIncorrect = new Query.Equals("age", 51) + hibernateQuery.not(lastNameWrong, ageIncorrect) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + def isEmpty() { given: hibernateQuery.isEmpty("pets") @@ -203,6 +218,65 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } + def inSubQuery() { + given: + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + def oldPet = new Pet(name: "Lucky") + oldBob.addToPets(oldPet) + oldBob.save(flush: true) + petHibernateQuery.inList("owner", + new DetachedCriteria(Person).eq("lastName", "Builder") + ) + when: + def newPet = petHibernateQuery.singleResult() + then: + oldPet == newPet + } + + def greaterThanAll() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.gtAll("age", new DetachedCriteria(Person).eq("age",48).property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + + def lessThanEqualsAll() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.leAll("age", new DetachedCriteria(Person).eq("age",50).property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def lessThanAll() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.ltAll("age", new DetachedCriteria(Person).eq("age",48).property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + + def greaterThanEqualsAll() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.geAll("age", new DetachedCriteria(Person).eq("age",50).property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + + def inList() { new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) given: From 4ab5102c4e4336b9669da4ea760fa4a01e011f87 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sun, 9 Feb 2025 20:31:37 -0600 Subject: [PATCH 0017/1008] Hopefully finished all the predicates for queries. --- .../AbstractHibernateCriteriaBuilder.java | 68 +++--- .../orm/hibernate/query/HibernateQuery.java | 97 ++++++++ .../hibernate/query/PredicateGenerator.java | 40 ++++ .../hibernatequery/HibernateQuerySpec.groovy | 207 +++++++++++++++++- 4 files changed, 379 insertions(+), 33 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index dc4c955e563..2d12ac27c3e 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -8,6 +8,7 @@ import groovy.lang.MetaClass; import groovy.lang.MetaMethod; import groovy.lang.MissingMethodException; +import groovy.util.logging.Slf4j; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.Root; @@ -27,6 +28,8 @@ import org.hibernate.SessionFactory; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.transform.ResultTransformer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.core.convert.ConversionService; import org.grails.datastore.mapping.query.api.ProjectionList; @@ -36,6 +39,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Objects; /** * Abstract super class for sharing code between Hibernate 3 and 4 implementations of HibernateCriteriaBuilder @@ -43,6 +47,7 @@ * @author Graeme Rocher * @since 3.0.7 */ +@Slf4j public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSupport implements org.grails.datastore.mapping.query.api.BuildableCriteria, org.grails.datastore.mapping.query.api.ProjectionList { public static final String AND = "and"; // builder @@ -82,6 +87,7 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo protected static final String SCROLL_CALL = "scroll"; protected static final String SET_RESULT_TRANSFORMER_CALL = "setResultTransformer"; protected static final String PROJECTIONS = "projections"; + private static final Logger log = LoggerFactory.getLogger(AbstractHibernateCriteriaBuilder.class); protected SessionFactory sessionFactory; @@ -256,19 +262,6 @@ public Class getTargetClass() { return targetClass; } - /** - * Calculates the property value, converting GStrings if necessary - * - * @param propertyValue The property value - * @return The calculated property value - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - protected Object calculatePropertyValue(Object propertyValue) { - if (propertyValue instanceof CharSequence) { - return propertyValue.toString(); - } - return propertyValue; - } protected abstract DetachedCriteria convertToHibernateCriteria(QueryableCriteria queryableCriteria); @@ -288,10 +281,15 @@ public void count(String propertyName) { * @param alias The alias to use */ public void count(String propertyName, String alias) { + hibernateQuery.projections().countDistinct(getFullyQualifiedColumn(propertyName, alias)); + } + private static String getFullyQualifiedColumn(String propertyName, String alias) { + return (Objects.nonNull(alias) ? alias + "." : "") + propertyName; } public ProjectionList id() { + hibernateQuery.projections().id(); return this; } @@ -314,11 +312,11 @@ public ProjectionList countDistinct(String propertyName) { * @param propertyName The name of the property */ public ProjectionList groupProperty(String propertyName) { - groupProperty(propertyName, null); - return this; + return groupProperty(propertyName, null); } public ProjectionList distinct() { + hibernateQuery.projections().distinct(); return this; } @@ -329,6 +327,7 @@ public ProjectionList distinct() { * @param alias The alias to use */ public ProjectionList countDistinct(String propertyName, String alias) { + hibernateQuery.projections().countDistinct(getFullyQualifiedColumn(propertyName,alias)); return this; } @@ -340,6 +339,7 @@ public ProjectionList countDistinct(String propertyName, String alias) { * @param alias The alias to use */ public ProjectionList groupProperty(String propertyName, String alias) { + hibernateQuery.projections().groupProperty(getFullyQualifiedColumn(propertyName,alias)); return this; } @@ -359,6 +359,7 @@ public ProjectionList max(String propertyName) { * @param alias The alias to use */ public ProjectionList max(String propertyName, String alias) { + hibernateQuery.projections().max(getFullyQualifiedColumn(propertyName,alias)); return this; } @@ -377,25 +378,20 @@ public ProjectionList min(String propertyName) { * @param alias The alias to use */ public ProjectionList min(String propertyName, String alias) { + hibernateQuery.projections().max(getFullyQualifiedColumn(propertyName,alias)); return this; } + + /** * Adds a projection that allows the criteria to return the row count * */ public ProjectionList rowCount() { - return rowCount(null); + return count(); } - /** - * Adds a projection that allows the criteria to return the row count - * - * @param alias The alias to use - */ - public ProjectionList rowCount(String alias) { - return this; - } /** * Adds a projection that allows the criteria to retrieve the sum of the results of a property @@ -413,6 +409,7 @@ public ProjectionList sum(String propertyName) { * @param alias The alias to use */ public ProjectionList sum(String propertyName, String alias) { + hibernateQuery.projections().sum(getFullyQualifiedColumn(propertyName,alias)); return this; } @@ -423,6 +420,12 @@ public ProjectionList sum(String propertyName, String alias) { * @param fetchMode The fetch mode to set */ public void fetchMode(String associationPath, FetchMode fetchMode) { + if (fetchMode.equals(FetchMode.SELECT)){ + hibernateQuery.detachedCriteria.select(associationPath); + } else { + hibernateQuery.detachedCriteria.join(associationPath); + } + } /** @@ -441,6 +444,7 @@ public void resultTransformer(ResultTransformer transformer) { * @return A Criterion instance */ public Criteria eqProperty(String propertyName, String otherPropertyName) { + hibernateQuery.eqProperty(propertyName,otherPropertyName); return this; } @@ -451,6 +455,7 @@ public Criteria eqProperty(String propertyName, String otherPropertyName) { * @return A Criterion instance */ public Criteria neProperty(String propertyName, String otherPropertyName) { + hibernateQuery.neProperty(propertyName,otherPropertyName); return this; } @@ -461,6 +466,7 @@ public Criteria neProperty(String propertyName, String otherPropertyName) { * @return A Criterion instance */ public Criteria gtProperty(String propertyName, String otherPropertyName) { + hibernateQuery.gtProperty(propertyName,otherPropertyName); return this; } @@ -471,6 +477,7 @@ public Criteria gtProperty(String propertyName, String otherPropertyName) { * @return A Criterion instance */ public Criteria geProperty(String propertyName, String otherPropertyName) { + hibernateQuery.geProperty(propertyName,otherPropertyName); return this; } @@ -481,6 +488,7 @@ public Criteria geProperty(String propertyName, String otherPropertyName) { * @return A Criterion instance */ public Criteria ltProperty(String propertyName, String otherPropertyName) { + hibernateQuery.ltProperty(propertyName,otherPropertyName); return this; } @@ -491,11 +499,13 @@ public Criteria ltProperty(String propertyName, String otherPropertyName) { * @return A Criterion instance */ public Criteria leProperty(String propertyName, String otherPropertyName) { + hibernateQuery.leProperty(propertyName,otherPropertyName); return this; } @Override public Criteria allEq(Map propertyValues) { + hibernateQuery.allEq(propertyValues); return this; } @@ -568,8 +578,8 @@ public Criteria leAll(String propertyName, Closure propertyValue) { * @param propertyValue The property value * @return A Criterion instance */ - public Criteria eqAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + public Criteria eqAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + hibernateQuery.eqAll(propertyName,propertyValue); return this; } @@ -580,8 +590,8 @@ public Criteria eqAll(String propertyName, * @param propertyValue The property value * @return A Criterion instance */ - public Criteria gtAll(String propertyName, - @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + public Criteria gtAll(String propertyName, @SuppressWarnings("rawtypes") QueryableCriteria propertyValue) { + hibernateQuery.gtAll(propertyName,propertyValue); return this; } @@ -859,7 +869,7 @@ public Criteria sqlRestriction(String sqlRestriction) { * @return a Criteria instance */ public Criteria sqlRestriction(String sqlRestriction, List values) { - return this; + throw new RuntimeException("This feature is not supported in Hibernate 6"); } /** diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index ee55372c3ea..3774572d672 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -22,6 +22,7 @@ import jakarta.persistence.criteria.CriteriaQuery; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.Restrictions; +import org.grails.datastore.mapping.query.api.Criteria; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.orm.hibernate.AbstractHibernateSession; @@ -86,6 +87,31 @@ public Query leAll(String propertyName, QueryableCriteria subquery) { return this; } + public Query gtSome(String propertyName, QueryableCriteria subquery) { + detachedCriteria.gtSome(propertyName,subquery); + return this; + } + + public Query geSome(String propertyName, QueryableCriteria subquery) { + detachedCriteria.geSome(propertyName,subquery); + return this; + } + + public Query ltSome(String propertyName, QueryableCriteria subquery) { + detachedCriteria.ltSome(propertyName,subquery); + return this; + } + + public Query leSome(String propertyName, QueryableCriteria subquery) { + detachedCriteria.leSome(propertyName,subquery); + return this; + } + + public Query eqAll(String propertyName, QueryableCriteria propertyValue){ + detachedCriteria.eqAll(propertyName,propertyValue); + return this; + } + public Query and(Closure closure) { detachedCriteria.and(closure); return this; @@ -112,6 +138,77 @@ public Query not(Closure closure) { return this; } + public Query ne(String propertyName, Object propertyValue) { + detachedCriteria.ne(propertyName, propertyValue); + return this; + } + + public Query eqProperty(String propertyName, String otherPropertyName) { + detachedCriteria.eqProperty(propertyName,otherPropertyName); + return this; + } + + public Query neProperty(String propertyName, String otherPropertyName) { + detachedCriteria.neProperty(propertyName,otherPropertyName); + return this; + } + + public Query gtProperty(String propertyName, String otherPropertyName) { + detachedCriteria.gtProperty(propertyName,otherPropertyName); + return this; + } + + + public Query geProperty(String propertyName, String otherPropertyName) { + detachedCriteria.geProperty(propertyName,otherPropertyName); + return this; + } + + public Query ltProperty(String propertyName, String otherPropertyName) { + detachedCriteria.ltProperty(propertyName,otherPropertyName); + return this; + } + + public Query leProperty(String propertyName, String otherPropertyName) { + detachedCriteria.leProperty(propertyName,otherPropertyName); + return this; + } + + public Query sizeEq(String propertyName, int size) { + detachedCriteria.sizeEq(propertyName, size); + return this; + } + + + public Query sizeGt(String propertyName, int size) { + detachedCriteria.sizeGt(propertyName, size); + return this; + } + + + public Query sizeGe(String propertyName, int size) { + detachedCriteria.sizeGe(propertyName, size); + return this; + } + + + public Query sizeLe(String propertyName, int size) { + detachedCriteria.sizeLe(propertyName, size); + return this; + } + + + public Query sizeLt(String propertyName, int size) { + detachedCriteria.sizeLt(propertyName, size); + return this; + } + + + public Query sizeNe(String propertyName, int size) { + detachedCriteria.sizeNe(propertyName, size); + return this; + } + diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index c83d8b103e1..6b8f34cd271 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -9,6 +9,7 @@ import jakarta.persistence.criteria.Subquery; import org.grails.datastore.mapping.query.Query; import org.hibernate.query.criteria.HibernateCriteriaBuilder; +import org.hibernate.query.criteria.JpaExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,6 +51,20 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue return cb.isEmpty(root_.get(c.getProperty())); } else if (criterion instanceof Query.Equals c) { return cb.equal(root_.get(c.getProperty()), c.getValue()); + } else if (criterion instanceof Query.NotEquals c) { + return cb.notEqual(root_.get(c.getProperty()), c.getValue()); + } else if (criterion instanceof Query.EqualsProperty c) { + return cb.equal(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + } else if (criterion instanceof Query.NotEqualsProperty c) { + return cb.notEqual(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + } else if (criterion instanceof Query.LessThanEqualsProperty c) { + return cb.le(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + } else if (criterion instanceof Query.LessThanProperty c) { + return cb.lt(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + } else if (criterion instanceof Query.GreaterThanEqualsProperty c) { + return cb.ge(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + } else if (criterion instanceof Query.GreaterThanProperty c) { + return cb.gt(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.IdEquals c) { return cb.equal(root_.get("id"), c.getValue()); } else if (criterion instanceof Query.GreaterThan c) { @@ -88,6 +103,16 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue return cb.like(root_.get(c.getProperty()), c.getPattern(), '\\'); } else if (criterion instanceof Query.Like c) { return cb.like(root_.get(c.getProperty()), c.getValue().toString()); + } else if (criterion instanceof Query.SizeEquals c) { + return cb.equal(cb.size(root_.get(c.getProperty())),c.getValue()); + } else if (criterion instanceof Query.SizeGreaterThan c) { + return cb.gt(cb.size(root_.get(c.getProperty())),(Number) c.getValue()); + } else if (criterion instanceof Query.SizeGreaterThanEquals c) { + return cb.ge(cb.size(root_.get(c.getProperty())),(Number) c.getValue()); + } else if (criterion instanceof Query.SizeLessThan c) { + return cb.lt(cb.size(root_.get(c.getProperty())),(Number) c.getValue()); + } else if (criterion instanceof Query.LessThanEquals c) { + return cb.le(root_.get(c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) && !c.getSubquery().getProjections().isEmpty() @@ -130,6 +155,21 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue } else if (c instanceof Query.LessThanAll sc ) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.and(predicates)); return cb.lessThan(root_.get(sc.getProperty()),subquery); + } else if (c instanceof Query.EqualsAll sc) { + subquery.select(from.get(c.getProperty())).where(cb.and(predicates)); + return cb.equal(root_.get(sc.getProperty()),subquery); + } else if (c instanceof Query.GreaterThanEqualsSome sc ) { + subquery.select(cb.max(from.get(c.getProperty()))).where(cb.or(predicates)); + return cb.greaterThanOrEqualTo(root_.get(sc.getProperty()),subquery); + } else if (c instanceof Query.GreaterThanSome sc ) { + subquery.select(cb.max(from.get(c.getProperty()))).where(cb.or(predicates)); + return cb.greaterThan(root_.get(sc.getProperty()),subquery); + } else if (c instanceof Query.LessThanEqualsSome sc ) { + subquery.select(cb.min(from.get(c.getProperty()))).where(cb.or(predicates)); + return cb.lessThanOrEqualTo(root_.get(sc.getProperty()),subquery); + } else if (c instanceof Query.LessThanSome sc ) { + subquery.select(cb.min(from.get(c.getProperty()))).where(cb.or(predicates)); + return cb.lessThan(root_.get(sc.getProperty()), subquery); } } return null; diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index ca02afe50d0..d82b36c4c42 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -18,6 +18,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { HibernateQuery hibernateQuery HibernateQuery petHibernateQuery + HibernateQuery eagerHibernateQuery Person oldBob @@ -26,11 +27,12 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { AbstractHibernateSession session = hibernateDatastore.connect() as AbstractHibernateSession hibernateQuery = new HibernateQuery(session, hibernateDatastore.getMappingContext().getPersistentEntity(Person.typeName)) petHibernateQuery = new HibernateQuery(session, hibernateDatastore.getMappingContext().getPersistentEntity(Pet.typeName)) + eagerHibernateQuery = new HibernateQuery(session, hibernateDatastore.getMappingContext().getPersistentEntity(EagerOwner.typeName)) oldBob = new Person(firstName: "Bob", lastName: "Builder", age: 50).save(flush: true) } List getDomainClasses() { - [Person] + [Person,EagerOwner] } def equals() { @@ -43,6 +45,76 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } + def ne() { + given: + new Person(firstName: "Fred", lastName: "Rogers", age: 51).save(flush: true) + hibernateQuery.ne("age", 51) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def eqProperty() { + given: + def oldMajor = new Person(firstName: "Major", lastName: "Major", age: 51).save(flush: true) + hibernateQuery.eqProperty("firstName", "lastName") + when: + def newMajor = hibernateQuery.singleResult() + then: + oldMajor == newMajor + } + + def neProperty() { + given: + hibernateQuery.neProperty("firstName", "lastName") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def leProperty() { + given: + def oldEager = new EagerOwner(column1: 1, column2: 2).save(flush: true) + eagerHibernateQuery.leProperty("column1", "column2") + when: + def newEager = eagerHibernateQuery.singleResult() + then: + oldEager == newEager + } + + def ltProperty() { + given: + def oldEager = new EagerOwner(column1: 1, column2: 2).save(flush: true) + eagerHibernateQuery.ltProperty("column1", "column2") + when: + def newEager = eagerHibernateQuery.singleResult() + then: + oldEager == newEager + } + + def geProperty() { + given: + def oldEager = new EagerOwner(column1: 2, column2: 1).save(flush: true) + eagerHibernateQuery.geProperty("column1", "column2") + when: + def newEager = eagerHibernateQuery.singleResult() + then: + oldEager == newEager + } + + def gtProperty() { + given: + def oldEager = new EagerOwner(column1: 2, column2: 1).save(flush: true) + eagerHibernateQuery.gtProperty("column1", "column2") + when: + def newEager = eagerHibernateQuery.singleResult() + then: + oldEager == newEager + } + + @Ignore("Need better implementation of Predicate") def idEq() { given: @@ -245,7 +317,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def lessThanEqualsAll() { - new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) given: hibernateQuery.leAll("age", new DetachedCriteria(Person).eq("age",50).property("age")) when: @@ -255,9 +327,9 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } def lessThanAll() { - new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + new Person(firstName: "Fred", lastName: "Builder", age: 52).save(flush: true) given: - hibernateQuery.ltAll("age", new DetachedCriteria(Person).eq("age",48).property("age")) + hibernateQuery.ltAll("age", new DetachedCriteria(Person).eq("age",52).property("age")) when: def newBob = hibernateQuery.singleResult() then: @@ -275,6 +347,71 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } + def greaterThanSome() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.gtSome("age", new DetachedCriteria(Person) + .eq("age",48) + .eq("firstName","Chuck") + .property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + + def lessThanEqualsSome() { + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + given: + hibernateQuery.leSome("age", + new DetachedCriteria(Person) + .eq("age",50) + .eq("firstName","Chuck") + .property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def lessThanSome() { + new Person(firstName: "Fred", lastName: "Builder", age: 52).save(flush: true) + given: + hibernateQuery.ltSome("age", new DetachedCriteria(Person) + .eq("age",52) + .eq("firstName","Chuck") + .property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + + def greaterThanEqualsSome() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.geSome("age", new DetachedCriteria(Person) + .eq("age",50) + .eq("firstName","Chuck") + .property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def equalsAll() { + new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + given: + hibernateQuery.eqAll("age", new DetachedCriteria(Person).eq("age",50).property("age")) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + def inList() { @@ -420,11 +557,73 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { result[1] == 51 } + def sizeEquals() { + given: + Pet pet = new Pet(name: "Lucky") + oldBob.addToPets(pet) + oldBob.save(flush: true) + hibernateQuery.sizeEq("pets", 1) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def sizeGe() { + given: + Pet pet = new Pet(name: "Lucky") + oldBob.addToPets(pet) + oldBob.save(flush: true) + hibernateQuery.sizeGe("pets", 1) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def sizeGt() { + given: + Pet pet = new Pet(name: "Lucky") + oldBob.addToPets(pet) + oldBob.save(flush: true) + hibernateQuery.sizeGt("pets", 0) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def sizeLe() { + given: + Pet pet = new Pet(name: "Lucky") + oldBob.addToPets(pet) + oldBob.save(flush: true) + hibernateQuery.sizeGe("pets", 1) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + def sizeLt() { + given: + Pet pet = new Pet(name: "Lucky") + oldBob.addToPets(pet) + oldBob.save(flush: true) + hibernateQuery.sizeLt("pets", 2) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + } @Entity class EagerOwner implements Serializable { Set pets = [] as Set + Integer column1 + Integer column2 static hasMany = [pets: Pet] static mapping = { pets lazy : false From bd6e6ba33e1fe9cf1f6785c7ee7ac51d8aa0a451 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Mon, 10 Feb 2025 16:32:41 -0600 Subject: [PATCH 0018/1008] Finished all predicates but not able to make Exists query tests to pass. Moving on for the moment, but have marked the tests with comments about the generated query. --- .../grails/orm/HibernateCriteriaBuilder.java | 26 +++--- .../AbstractHibernateCriteriaBuilder.java | 20 +++-- .../query/AbstractHibernateQuery.java | 2 +- .../orm/hibernate/query/HibernateQuery.java | 20 +++++ .../hibernate/query/PredicateGenerator.java | 34 ++++++- .../hibernatequery/HibernateQuerySpec.groovy | 90 ++++++++++++++++++- 6 files changed, 169 insertions(+), 23 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java index 41c709249ba..d8262622d5a 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/grails/orm/HibernateCriteriaBuilder.java @@ -145,19 +145,19 @@ protected List createPagedResultList(Map args) { @Override protected void createCriteriaInstance() { - { - if (TransactionSynchronizationManager.hasResource(sessionFactory)) { - participate = true; - hibernateSession = ((SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)).getSession(); - } - else { - hibernateSession = sessionFactory.openSession(); - } - criteriaQuery = hibernateSession.getCriteriaBuilder().createQuery(targetClass); - root = criteriaQuery.from(targetClass); - cacheCriteriaMapping(); - criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteriaQuery.getClass()); - } +// { +// if (TransactionSynchronizationManager.hasResource(sessionFactory)) { +// participate = true; +// hibernateSession = ((SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory)).getSession(); +// } +// else { +// hibernateSession = sessionFactory.openSession(); +// } +// criteriaQuery = hibernateSession.getCriteriaBuilder().createQuery(targetClass); +// root = criteriaQuery.from(targetClass); +// cacheCriteriaMapping(); +// criteriaMetaClass = GroovySystem.getMetaClassRegistry().getMetaClass(criteriaQuery.getClass()); +// } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 2d12ac27c3e..06964dc946c 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -607,6 +607,7 @@ public Criteria gtSome(String propertyName, Closure propertyValue) { @Override public Criteria geSome(String propertyName, QueryableCriteria propertyValue) { + hibernateQuery.geSome(propertyName,propertyValue); return this; } @@ -617,6 +618,7 @@ public Criteria geSome(String propertyName, Closure propertyValue) { @Override public Criteria ltSome(String propertyName, QueryableCriteria propertyValue) { + hibernateQuery.ltSome(propertyName,propertyValue); return this; } @@ -627,6 +629,7 @@ public Criteria ltSome(String propertyName, Closure propertyValue) { @Override public Criteria leSome(String propertyName, QueryableCriteria propertyValue) { + hibernateQuery.leSome(propertyName,propertyValue); return this; } @@ -658,6 +661,7 @@ public Criteria inList(String propertyName, Closure subquery) { @Override public Criteria notIn(String propertyName, QueryableCriteria subquery) { + hibernateQuery.notIn(propertyName,subquery); return this; } @@ -711,6 +715,7 @@ public Criteria leAll(String propertyName, @SuppressWarnings("rawtypes") Queryab * @return A Criterion instance */ public Criteria gt(String propertyName, Object propertyValue) { + hibernateQuery.gt(propertyName,propertyValue); return this; } @@ -983,6 +988,7 @@ public Criteria order(String propertyName, String directionString) { * @return A Criterion instance */ public Criteria sizeEq(String propertyName, int size) { + hibernateQuery.sizeEq(propertyName,size); return this; } @@ -995,6 +1001,7 @@ public Criteria sizeEq(String propertyName, int size) { * @return A Criterion instance */ public Criteria sizeGt(String propertyName, int size) { + hibernateQuery.sizeGt(propertyName,size); return this; } @@ -1007,6 +1014,7 @@ public Criteria sizeGt(String propertyName, int size) { * @return A Criterion instance */ public Criteria sizeGe(String propertyName, int size) { + hibernateQuery.sizeGe(propertyName,size); return this; } @@ -1019,6 +1027,7 @@ public Criteria sizeGe(String propertyName, int size) { * @return A Criterion instance */ public Criteria sizeLe(String propertyName, int size) { + hibernateQuery.sizeLe(propertyName,size); return this; } @@ -1031,6 +1040,7 @@ public Criteria sizeLe(String propertyName, int size) { * @return A Criterion instance */ public Criteria sizeLt(String propertyName, int size) { + hibernateQuery.sizeLt(propertyName,size); return this; } @@ -1055,6 +1065,7 @@ public org.grails.datastore.mapping.query.api.Criteria rlike(String propertyName * @return A Criterion instance */ public Criteria sizeNe(String propertyName, int size) { + hibernateQuery.sizeNe(propertyName,size); return this; } @@ -1065,6 +1076,7 @@ public Criteria sizeNe(String propertyName, int size) { * @return The criterion object */ public Criteria ne(String propertyName, Object propertyValue) { + hibernateQuery.ne(propertyName,propertyValue); return this; } @@ -1140,7 +1152,7 @@ else if (name.equals(COUNT_CALL)) { // resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; // } - createCriteriaInstance(); +// createCriteriaInstance(); // Check for pagination params if (name.equals(LIST_CALL) && args.length == 2) { @@ -1157,12 +1169,10 @@ else if (name.equals(COUNT_CALL)) { Object result; if (!uniqueResult) { if (scroll) { - root = criteriaQuery.from(this.targetClass); - criteriaQuery.select(root); - criteriaQuery.where(cb.and(PredicateGenerator.getPredicates(cb, criteriaQuery, root, this.junction.getCriteria()))); - result = hibernateSession.createQuery(criteriaQuery).scroll(); + result = hibernateQuery.scroll(); } else if (count) { + hibernateQuery.projections().count(); criteriaQuery = cb.createQuery(Long.class); root = criteriaQuery.from(this.targetClass); criteriaQuery.select(cb.count(root)); diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 92820ac1e9d..aa1b5cfeeb0 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -449,7 +449,7 @@ private static Predicate combinePredicates(Predicate... predicates) { .orElse(x -> true); } - private org.hibernate.query.Query createQuery() { + protected org.hibernate.query.Query createQuery() { HibernateCriteriaBuilder cb = getCriteriaBuilder(); List projections = collectProjections(); List groupProjections = collectGroupProjections(); diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index 3774572d672..e9ca1d321fc 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -66,6 +66,21 @@ public Query inList(String propertyName, QueryableCriteria subquery) { return this; } + public Query notIn(String propertyName, QueryableCriteria subquery) { + detachedCriteria.notIn(propertyName,subquery); + return this; + } + + public Query exists(QueryableCriteria subquery) { + detachedCriteria.exists(subquery); + return this; + } + + public Query notExits( QueryableCriteria subquery) { + detachedCriteria.notExists(subquery); + return this; + } + public Query gtAll(String propertyName, QueryableCriteria subquery) { detachedCriteria.gtAll(propertyName,subquery); @@ -210,6 +225,11 @@ public Query sizeNe(String propertyName, int size) { } + public Object scroll() { + return createQuery().scroll(); + } + + diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 6b8f34cd271..fee826008a4 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -135,11 +135,23 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); subquery.select(from).where(cb.and(predicates)); return cb.in(root_.get("id")).value(subquery); - } else if (criterion instanceof Query.In c - && !c.getValues().isEmpty() + } else if (criterion instanceof Query.In c && !c.getValues().isEmpty() ) { return cb.in(root_.get(c.getProperty()), c.getValues()); - } else if (criterion instanceof Query.SubqueryCriterion c) { + } else if (criterion instanceof Query.Exists c) { + Subquery subquery = criteriaQuery.subquery(Object.class); + Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); + subquery.select(cb.literal(1)).where(cb.and(predicates)); + return cb.exists(subquery); + } else if (criterion instanceof Query.NotExists c) { + Subquery subquery = criteriaQuery.subquery(Object.class); + Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); + subquery.select(cb.literal(1)).where(cb.and(predicates)); + return cb.not(cb.exists(subquery)); + } + else if (criterion instanceof Query.SubqueryCriterion c) { Subquery subquery = criteriaQuery.subquery(Number.class); Root from = subquery.from(c.getValue().getPersistentEntity().getJavaClass()); Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria()); @@ -170,6 +182,22 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue } else if (c instanceof Query.LessThanSome sc ) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.or(predicates)); return cb.lessThan(root_.get(sc.getProperty()), subquery); + } else if (criterion instanceof Query.NotIn sc + && Objects.nonNull(sc.getSubquery()) + && !sc.getSubquery().getProjections().isEmpty() + && sc.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection + ) { + Query.PropertyProjection projection = (Query.PropertyProjection) sc.getSubquery().getProjections().get(0); + boolean distinct = projection instanceof Query.DistinctPropertyProjection; + subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); + return cb.in(root_.get(sc.getProperty())).value(subquery); + } else if (criterion instanceof Query.NotIn sc + && Objects.nonNull(sc.getSubquery()) + && !sc.getSubquery().getProjections().isEmpty() + && sc.getSubquery().getProjections().get(0) instanceof Query.IdProjection + ) { + subquery.select(from).where(cb.and(predicates)); + return cb.in(root_.get("id")).value(subquery); } } return null; diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index d82b36c4c42..068bbe1eaf2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -32,7 +32,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } List getDomainClasses() { - [Person,EagerOwner] + [Person,Pet, EagerOwner] } def equals() { @@ -305,6 +305,94 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldPet == newPet } + def notInSubQuery() { + given: + def oldPet = new Pet(name: "Lucky") + oldBob.addToPets(oldPet) + oldBob.save(flush: true) + petHibernateQuery.notIn("owner", + new DetachedCriteria(Person).eq("lastName", "Rogers") + ) + when: + def newPet = petHibernateQuery.singleResult() + then: + oldPet == newPet + } + + @Ignore("Not sure why this is not passing") + /** + * @see org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() + * else if (criterion instanceof Query.Exists c) + select + p1_0.id, + p1_0.age, + p1_0.face_id, + p1_0.first_name, + p1_0.last_name, + p1_0.my_boolean_property, + p1_0.version + from + person p1_0 + where + exists(select + 1 + from + pet p2_0 + where + p2_0.owner_id=?) + offset + ? rows + */ + def exists() { + given: + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + def oldPet = new Pet(name: "Lucky") + oldBob.addToPets(oldPet) + oldBob.save(flush: true) + hibernateQuery.exists(new DetachedCriteria(Pet).eq("owner", oldBob)) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + + @Ignore("Not sure why this is not passing") + /** + * @see org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() + * else if (criterion instanceof Query.NotExists c) + select + p1_0.id, + p1_0.age, + p1_0.face_id, + p1_0.first_name, + p1_0.last_name, + p1_0.my_boolean_property, + p1_0.version + from + person p1_0 + where + not exists(select + 1 + from + pet p2_0 + where + p2_0.owner_id=?) + offset + ? rows + */ + def notExists() { + given: + def fred = new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + def oldPet = new Pet(name: "Lucky") + oldBob.addToPets(oldPet) + oldBob.save(flush: true) + hibernateQuery.notExits(new DetachedCriteria(Pet).eq("owner", fred)) + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + def greaterThanAll() { new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) given: From 2741fb61ce3a05b7dd14818f6d3ade27ddfbbc8c Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Mon, 10 Feb 2025 19:42:07 -0600 Subject: [PATCH 0019/1008] Partial commit --- .../AbstractHibernateCriteriaBuilder.java | 135 ++++++------------ .../query/AbstractHibernateQuery.java | 15 +- .../tests/CompositeIdWithJoinTableSpec.groovy | 4 +- .../hibernatequery/HibernateQuerySpec.groovy | 12 ++ 4 files changed, 72 insertions(+), 94 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 06964dc946c..dd37421a983 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -126,8 +126,8 @@ public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessio this.targetClass = targetClass; this.sessionFactory = sessionFactory; this.cb = sessionFactory.getCriteriaBuilder(); - this.criteriaQuery = cb.createQuery(targetClass); - this.root = criteriaQuery.from(targetClass); +// this.criteriaQuery = cb.createQuery(targetClass); +// this.root = criteriaQuery.from(targetClass); AbstractHibernateSession session =(AbstractHibernateSession) datastore.connect(); hibernateQuery = new HibernateQuery(session, datastore.getMappingContext().getPersistentEntity(targetClass.getTypeName())); @@ -243,10 +243,10 @@ public BuildableCriteria readOnly(boolean readOnly) { * @return The calculated property name */ protected String calculatePropertyName(String propertyName) { - String lastAlias = getLastAlias(); - if (lastAlias != null) { - return lastAlias +'.'+propertyName; - } +// String lastAlias = getLastAlias(); +// if (lastAlias != null) { +// return lastAlias +'.'+propertyName; +// } return propertyName; } @@ -762,11 +762,13 @@ public Criteria idEquals(Object o) { @Override public Criteria exists(QueryableCriteria subquery) { + hibernateQuery.exists(subquery); return this; } @Override public Criteria notExists(QueryableCriteria subquery) { + hibernateQuery.notExits(subquery); return this; } @@ -1148,11 +1150,10 @@ else if (name.equals(SCROLL_CALL)) { else if (name.equals(COUNT_CALL)) { count = true; } -// else if (name.equals(LIST_DISTINCT_CALL)) { -// resultTransformer = CriteriaSpecification.DISTINCT_ROOT_ENTITY; -// } + else if (name.equals(LIST_DISTINCT_CALL)) { + hibernateQuery.projections().distinct(); + } -// createCriteriaInstance(); // Check for pagination params if (name.equals(LIST_CALL) && args.length == 2) { @@ -1163,9 +1164,6 @@ else if (name.equals(COUNT_CALL)) { invokeClosureNode(args[0]); } -// if (resultTransformer != null) { -// criteria.setResultTransformer(resultTransformer); -// } Object result; if (!uniqueResult) { if (scroll) { @@ -1173,78 +1171,39 @@ else if (name.equals(COUNT_CALL)) { } else if (count) { hibernateQuery.projections().count(); - criteriaQuery = cb.createQuery(Long.class); - root = criteriaQuery.from(this.targetClass); - criteriaQuery.select(cb.count(root)); - criteriaQuery.where(cb.and(PredicateGenerator.getPredicates(cb, criteriaQuery, root,this.junction.getCriteria()))); - result = hibernateSession.createQuery(criteriaQuery).getSingleResult(); + result = hibernateQuery.singleResult(); + } + else if (paginationEnabledList) { + Map argMap = (Map)args[0]; + // With the new query generator only the name of the field in the relation is allowed + // @see HibernateQuerySpec.joinWithProjection() for a clear example + final String sortField = (String) argMap.get(HibernateQueryConstants.ARGUMENT_SORT); + if (sortField != null) { + boolean ignoreCase = true; + Object caseArg = argMap.get(HibernateQueryConstants.ARGUMENT_IGNORE_CASE); + if (caseArg instanceof Boolean) { + ignoreCase = (Boolean) caseArg; + } + final String orderParam = (String) argMap.get(HibernateQueryConstants.ARGUMENT_ORDER); + final Query.Order.Direction direction = Query.Order.Direction.DESC.name().equalsIgnoreCase(orderParam) ? Query.Order.Direction.DESC : Query.Order.Direction.ASC; + //The default for Query.Order.ignoreCase is false and can't be set to false + Query.Order order ; + if (ignoreCase) { + order = new Query.Order(sortField, direction); + order.ignoreCase(); + } else { + order = new Query.Order(sortField, direction); + } + hibernateQuery.order(order); + } + result = hibernateQuery.list(); } -// else if (paginationEnabledList) { -// // Calculate how many results there are in total. This has been -// // moved to before the 'list()' invocation to avoid any "ORDER -// // BY" clause added by 'populateArgumentsForCriteria()', otherwise -// // an exception is thrown for non-string sort fields (GRAILS-2690). -// query.setFirstResult(0); -// query.setMaxResults(Integer.MAX_VALUE); -// -// // Restore the previous projection, add settings for the pagination parameters, -// // and then execute the query. -// boolean isProjection = (projectionList != null && !projectionList.getProjectionList().isEmpty()); -// -// criteria.setProjection(isProjection ? projectionList : null); -// -// for (Order orderEntry : orderEntries) { -// criteria.addOrder(orderEntry); -// } -// if (resultTransformer == null) { -// // GRAILS-9644 - Use projection transformer -// criteria.setResultTransformer( isProjection ? -// CriteriaSpecification.PROJECTION : -// CriteriaSpecification.ROOT_ENTITY -// ); -// } -// else -// if (paginationEnabledList) { -// // relevant to GRAILS-5692 -// criteria.setResultTransformer(resultTransformer); -// } -// // GRAILS-7324 look if we already have association to sort by -// Map argMap = (Map)args[0]; -// final String sort = (String) argMap.get(HibernateQueryConstants.ARGUMENT_SORT); -// if (sort != null) { -// boolean ignoreCase = true; -// Object caseArg = argMap.get(HibernateQueryConstants.ARGUMENT_IGNORE_CASE); -// if (caseArg instanceof Boolean) { -// ignoreCase = (Boolean) caseArg; -// } -// final String orderParam = (String) argMap.get(HibernateQueryConstants.ARGUMENT_ORDER); -// final String order = HibernateQueryConstants.ORDER_DESC.equalsIgnoreCase(orderParam) ? -// HibernateQueryConstants.ORDER_DESC : HibernateQueryConstants.ORDER_ASC; -// int lastPropertyPos = sort.lastIndexOf('.'); -// String associationForOrdering = lastPropertyPos >= 0 ? sort.substring(0, lastPropertyPos) : null; -// if (associationForOrdering != null && aliasMap.containsKey(associationForOrdering)) { -// addOrder(criteria, aliasMap.get(associationForOrdering) + "." + sort.substring(lastPropertyPos + 1), -// order, ignoreCase); -// // remove sort from arguments map to exclude from default processing. -// @SuppressWarnings("unchecked") Map argMap2 = new HashMap(argMap); -// argMap2.remove(HibernateQueryConstants.ARGUMENT_SORT); -// argMap = argMap2; -// } -// } -// result = createPagedResultList(argMap); -// } else { - root = criteriaQuery.from(this.targetClass); - criteriaQuery.select(root); - criteriaQuery.where(cb.and(PredicateGenerator.getPredicates(cb, criteriaQuery, root, this.junction.getCriteria()))); - result = hibernateSession.createQuery(criteriaQuery).list(); + result = hibernateQuery.list(); } } else { - root = criteriaQuery.from(this.targetClass); - criteriaQuery.select(root); - criteriaQuery.where(cb.and(PredicateGenerator.getPredicates(cb, criteriaQuery, root, this.junction.getCriteria()))); - result = hibernateSession.createQuery(criteriaQuery).uniqueResult(); + result = hibernateQuery.singleResult(); } if (!participate) { closeSession(); @@ -1269,6 +1228,9 @@ else if (count) { } if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { + if (1 == 1) { + throw new RuntimeException("This branch needs to be filled out"); + } final boolean hasMoreThanOneArg = args.length > 1; Object callable = hasMoreThanOneArg ? args[1] : args[0]; // int joinType = hasMoreThanOneArg ? (Integer)args[0] : org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue(); @@ -1368,21 +1330,18 @@ else if (args.length == 1 && args[0] != null) { } String propertyName = calculatePropertyName((String)value); if (name.equals(IS_NULL)) { - c = Restrictions.isNull(propertyName); + hibernateQuery.isNull(propertyName); } else if (name.equals(IS_NOT_NULL)) { - c = Restrictions.isNotNull(propertyName); + hibernateQuery.isNotNull(propertyName); } else if (name.equals(IS_EMPTY)) { - c = Restrictions.isEmpty(propertyName); + hibernateQuery.isEmpty(propertyName); } - else if (name.equals(IS_NOT_EMPTY)) { - c = Restrictions.isNotEmpty(propertyName); + else { + hibernateQuery.isNotEmpty(propertyName); } } - if (c != null) { - return addToCriteria(c); - } } throw new MissingMethodException(name, getClass(), args); } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index aa1b5cfeeb0..8e4acb861e5 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -516,11 +516,20 @@ private void assignOrderBy(CriteriaQuery cq, HibernateCriteriaBuilder cb, From r cq.orderBy(orders .stream() .map(order -> { - if (order.getDirection().equals(Order.Direction.ASC)) { - return cb.asc(root.get(order.getProperty())); + if (order.isIgnoreCase()) { + if (order.getDirection().equals(Order.Direction.ASC)) { + return cb.asc(cb.lower(root.get(order.getProperty()))); + } else { + return cb.desc(cb.lower(root.get(order.getProperty()))); + } } else { - return cb.desc(root.get(order.getProperty())); + if (order.getDirection().equals(Order.Direction.ASC)) { + return cb.asc(root.get(order.getProperty())); + } else { + return cb.desc(root.get(order.getProperty())); + } } + }) .toList() ); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithJoinTableSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithJoinTableSpec.groovy index 6b6e0274326..8dd6b51474e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithJoinTableSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithJoinTableSpec.groovy @@ -13,10 +13,8 @@ import spock.lang.Specification /** * Created by graemerocher on 26/01/2017. */ -class CompositeIdWithJoinTableSpec extends Specification { +class CompositeIdWithJoinTableSpec extends HibernateGormDatastoreSpec { - @AutoCleanup @Shared HibernateDatastore datastore = new HibernateDatastore(CompositeIdParent, CompositeIdChild) - @Shared PlatformTransactionManager transactionManager = datastore.transactionManager @Rollback void "test composite id with join table"() { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy index 068bbe1eaf2..869c1f31cdc 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy @@ -566,6 +566,18 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == bobs[0] } + def orderByNameIgnoreCase() { + def fred = new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + new Person(firstName: "Bob", lastName: "builder", age: 50).save(flush: true) + given: + hibernateQuery.order(new Query.Order("lastName", Query.Order.Direction.DESC).ignoreCase()) + when: + def bobs = hibernateQuery.list() + then: + bobs.size() == 3 + fred == bobs[0] + } + def projectionProperty() { given: hibernateQuery.projections().property("lastName") From f96c39bd01f22357071cf6061d18c9c143761ec8 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Mon, 10 Feb 2025 20:54:43 -0600 Subject: [PATCH 0020/1008] refactored tests to specs so they could run bu themselves --- grails-datastore-gorm-hibernate/build.gradle | 103 +++++++++--------- .../{tests => specs}/AutoTimestampSpec.groovy | 3 +- ...cadeToBidirectionalAsssociationSpec.groovy | 2 +- .../grails/gorm/{tests => specs}/Club.groovy | 2 +- .../CompositeIdWithJoinTableSpec.groovy | 2 +- ...ositeIdWithManyToOneAndSequenceSpec.groovy | 2 +- .../gorm/{tests => specs}/Contract.groovy | 2 +- .../CountByWithEmbeddedSpec.groovy | 2 +- .../DeleteAllWhereSpec.groovy | 2 +- .../DetachCriteriaSubquerySpec.groovy | 3 +- .../DetachedCriteriaJoinSpec.groovy | 8 +- ...DetachedCriteriaProjectionAliasSpec.groovy | 2 +- .../DetachedCriteriaProjectionSpec.groovy | 2 +- .../{tests => specs}/DomainGetterSpec.groovy | 2 +- .../{tests => specs}/EnumMappingSpec.groovy | 2 +- .../ExecuteQueryWithinValidatorSpec.groovy | 2 +- .../{tests => specs}/GroovyProxySpec.groovy | 4 +- .../HibernateEntityTraitGeneratedSpec.groovy | 2 +- .../HibernateGormDatastoreSpec.groovy | 2 +- .../{tests => specs}/HibernateSuite.groovy | 2 +- .../IdentityEnumTypeSpec.groovy | 2 +- .../ImportFromConstraintSpec.groovy | 2 +- .../LastUpdateWithDynamicUpdateSpec.groovy | 3 +- .../{tests => specs}/ManyToOneSpec.groovy | 2 +- .../MultiColumnUniqueConstraintSpec.groovy | 3 +- .../NullValueEqualSpec.groovy | 5 +- .../NullableAndLengthSpec.groovy | 2 +- .../OptimisticLockingSpec.groovy | 5 +- .../gorm/{tests => specs}/Player.groovy | 2 +- .../gorm/{tests => specs}/RLikeSpec.groovy | 2 +- .../{tests => specs}/ReadOperationSpec.groovy | 4 +- ...SaveWithExistingValidationErrorSpec.groovy | 2 +- .../{tests => specs}/SchemaNameSpec.groovy | 2 +- .../{tests => specs}/SequenceIdSpec.groovy | 2 +- .../SizeConstraintSpec.groovy | 3 +- .../gorm/{tests => specs}/SqlQuerySpec.groovy | 2 +- .../SubclassMultipleListCollectionSpec.groovy | 2 +- .../{tests => specs}/SubqueryAliasSpec.groovy | 2 +- .../TablePerSubClassAndEmbeddedSpec.groovy | 2 +- .../grails/gorm/{tests => specs}/Team.groovy | 2 +- .../TwoBidirectionalOneToManySpec.groovy | 2 +- .../UniqueConstraintHibernateSpec.groovy | 4 +- .../UniqueWithMultipleDataSourcesSpec.groovy | 2 +- .../{tests => specs}/ValidationSpec.groovy | 10 +- .../WhereQueryWithAssociationSortSpec.groovy | 3 +- ...ewSessionAndExistingTransactionSpec.groovy | 3 +- .../autoimport/AutoImportSpec.groovy | 2 +- .../autoimport/other/A.groovy | 2 +- ...BidirectionalOneToOneWithUniqueSpec.groovy | 2 +- .../{tests => specs}/belongsto/Face.groovy | 2 +- .../{tests => specs}/belongsto/Nose.groovy | 2 +- .../compositeid/CompositeIdCriteria.groovy | 2 +- ...ositeIdWithDeepOneToManyMappingSpec.groovy | 2 +- ...GlobalConstraintWithCompositeIdSpec.groovy | 2 +- .../HibernateDirtyCheckingSpec.groovy | 2 +- .../HibernateUpdateFromListenerSpec.groovy | 2 +- .../dirtychecking/PropertyFieldSpec.groovy | 2 +- .../UpdatePropertyInEventListenerSpec.groovy | 2 +- .../hasmany/HasManyWithInQuerySpec.groovy | 2 +- .../hasmany/ListCollectionSpec.groovy | 2 +- .../{tests => specs}/hasmany/Something.groovy | 2 +- .../TwoUnidirectionalHasManySpec.groovy | 2 +- .../hibernatequery/HibernateQuerySpec.groovy | 4 +- .../inheritance/SubclassToOneProxySpec.groovy | 2 +- ...ePerConcreteClassAndDateCreatedSpec.groovy | 2 +- .../TablePerConcreteClassImportedSpec.groovy | 2 +- .../jpa/SimpleJpaEntitySpec.groovy | 2 +- .../mappedby/MultipleOneToOneSpec.groovy | 2 +- ...iTenancyBidirectionalManyToManySpec.groovy | 2 +- ...iTenancyUnidirectionalOneToManySpec.groovy | 2 +- .../{tests => specs}/perf/JoinPerfSpec.groovy | 2 +- .../proxy/ByteBuddyProxySpec.groovy | 6 +- .../proxy/StaticTestUtil.groovy | 6 +- .../services/DataServiceSpec.groovy | 2 +- .../softdelete/SoftDeleteSpec.groovy | 2 +- .../traits/InterfacePropertySpec.groovy | 2 +- .../traits/TraitPropertySpec.groovy | 2 +- .../txs/CustomIsolationLevelSpec.groovy | 6 +- .../txs/TransactionPropagationSpec.groovy | 2 +- .../TransactionalWithinReadOnlySpec.groovy | 6 +- .../uuid/UuidInsertSpec.groovy | 2 +- .../validation/BeanValidationSpec.groovy | 2 +- .../validation/CascadeValidationSpec.groovy | 2 +- .../validation/DeepValidationSpec.groovy | 2 +- ...EmbeddedWithValidationExceptionSpec.groovy | 2 +- .../SaveWithInvalidEntitySpec.groovy | 2 +- .../validation/SkipValidationSpec.groovy | 2 +- .../UniqueFalseConstraintSpec.groovy | 2 +- .../validation/UniqueInheritanceSpec.groovy | 2 +- .../validation/UniqueWithHasOneSpec.groovy | 2 +- .../validation/UniqueWithinGroupSpec.groovy | 2 +- 91 files changed, 182 insertions(+), 152 deletions(-) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/AutoTimestampSpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/CascadeToBidirectionalAsssociationSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/Club.groovy (89%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/CompositeIdWithJoinTableSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/CompositeIdWithManyToOneAndSequenceSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/Contract.groovy (87%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/CountByWithEmbeddedSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/DeleteAllWhereSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/DetachCriteriaSubquerySpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/DetachedCriteriaJoinSpec.groovy (89%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/DetachedCriteriaProjectionAliasSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/DetachedCriteriaProjectionSpec.groovy (99%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/DomainGetterSpec.groovy (95%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/EnumMappingSpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/ExecuteQueryWithinValidatorSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/GroovyProxySpec.groovy (89%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/HibernateEntityTraitGeneratedSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/HibernateGormDatastoreSpec.groovy (99%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/HibernateSuite.groovy (88%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/IdentityEnumTypeSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/ImportFromConstraintSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/LastUpdateWithDynamicUpdateSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/ManyToOneSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/MultiColumnUniqueConstraintSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/NullValueEqualSpec.groovy (86%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/NullableAndLengthSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/OptimisticLockingSpec.groovy (94%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/Player.groovy (88%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/RLikeSpec.groovy (95%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/ReadOperationSpec.groovy (89%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/SaveWithExistingValidationErrorSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/SchemaNameSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/SequenceIdSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/SizeConstraintSpec.groovy (95%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/SqlQuerySpec.groovy (99%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/SubclassMultipleListCollectionSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/SubqueryAliasSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/TablePerSubClassAndEmbeddedSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/Team.groovy (90%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/TwoBidirectionalOneToManySpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/UniqueConstraintHibernateSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/UniqueWithMultipleDataSourcesSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/ValidationSpec.groovy (94%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/WhereQueryWithAssociationSortSpec.groovy (94%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/WithNewSessionAndExistingTransactionSpec.groovy (99%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/autoimport/AutoImportSpec.groovy (91%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/autoimport/other/A.groovy (71%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/belongsto/BidirectionalOneToOneWithUniqueSpec.groovy (93%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/belongsto/Face.groovy (81%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/belongsto/Nose.groovy (85%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/compositeid/CompositeIdCriteria.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/compositeid/GlobalConstraintWithCompositeIdSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/dirtychecking/HibernateDirtyCheckingSpec.groovy (99%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/dirtychecking/HibernateUpdateFromListenerSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/dirtychecking/PropertyFieldSpec.groovy (95%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/events/UpdatePropertyInEventListenerSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/hasmany/HasManyWithInQuerySpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/hasmany/ListCollectionSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/hasmany/Something.groovy (90%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/hasmany/TwoUnidirectionalHasManySpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/hibernatequery/HibernateQuerySpec.groovy (99%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/inheritance/SubclassToOneProxySpec.groovy (95%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/inheritance/TablePerConcreteClassAndDateCreatedSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/inheritance/TablePerConcreteClassImportedSpec.groovy (93%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/jpa/SimpleJpaEntitySpec.groovy (99%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/mappedby/MultipleOneToOneSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/perf/JoinPerfSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/proxy/ByteBuddyProxySpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/proxy/StaticTestUtil.groovy (92%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/services/DataServiceSpec.groovy (99%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/softdelete/SoftDeleteSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/traits/InterfacePropertySpec.groovy (95%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/traits/TraitPropertySpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/txs/CustomIsolationLevelSpec.groovy (87%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/txs/TransactionPropagationSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/txs/TransactionalWithinReadOnlySpec.groovy (93%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/uuid/UuidInsertSpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/BeanValidationSpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/CascadeValidationSpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/DeepValidationSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/EmbeddedWithValidationExceptionSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/SaveWithInvalidEntitySpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/SkipValidationSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/UniqueFalseConstraintSpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/UniqueInheritanceSpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/UniqueWithHasOneSpec.groovy (98%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/{tests => specs}/validation/UniqueWithinGroupSpec.groovy (98%) diff --git a/grails-datastore-gorm-hibernate/build.gradle b/grails-datastore-gorm-hibernate/build.gradle index bf9f9d474fe..a0b1f839d88 100644 --- a/grails-datastore-gorm-hibernate/build.gradle +++ b/grails-datastore-gorm-hibernate/build.gradle @@ -66,7 +66,12 @@ dependencies { documentation "org.hibernate.orm:hibernate-core:${hibernateVersion}" } + test { + filter { + //exclude all tests from a package. + excludeTestsMatching "grails.gorm.tests.*" + } if (isTravisBuild || isCiBuild) { maxParallelForks = 2 forkEvery = 10 @@ -83,52 +88,52 @@ test { } } -test.doFirst { - def toBaseClassRelativePathWithoutExtension = { String base, String classFile -> - if (classFile.startsWith(base)) { - def sansClass = classFile[0 .. classFile.size() - ".class".size() - 1] - def dollarIndex = sansClass.indexOf('$') - def baseClass = dollarIndex > 0 ? sansClass[0..dollarIndex - 1] : sansClass - def relative = baseClass - base - '/' - relative - } - else { - null - } - } - def tckClassesFile = project - .configurations - .testCompileClasspath - .resolvedConfiguration - .getResolvedArtifacts() - .find { resolved -> - resolved.moduleVersion.id.name == 'grails-datastore-gorm-tck' - }.file - - def tckClassesDir = project.file("${project.buildDir}/tck") - copy { - from zipTree(tckClassesFile) - into tckClassesDir - } - copy { - from tckClassesDir - into sourceSets.test.output.classesDirs.find { it.path.contains('classes' + File.separator + 'groovy') } - include "**/*.class" - exclude { details -> - // Do not copy across any TCK class (or nested classes of that class) - // If there is a corresponding source file in the particular modules - // test source tree. Allows a module to override a test/helper. - if (!details.file.isFile()) { - return false - } - def candidatePath = details.file.absolutePath - def relativePath = toBaseClassRelativePathWithoutExtension(tckClassesDir.absolutePath, candidatePath) - - if (relativePath == null) { - throw new IllegalStateException("$candidatePath does not appear to be in the TCK") - } - - project.file("src/test/groovy/${relativePath}.groovy").exists() - } - } -} +//test.doFirst { +// def toBaseClassRelativePathWithoutExtension = { String base, String classFile -> +// if (classFile.startsWith(base)) { +// def sansClass = classFile[0 .. classFile.size() - ".class".size() - 1] +// def dollarIndex = sansClass.indexOf('$') +// def baseClass = dollarIndex > 0 ? sansClass[0..dollarIndex - 1] : sansClass +// def relative = baseClass - base - '/' +// relative +// } +// else { +// null +// } +// } +// def tckClassesFile = project +// .configurations +// .testCompileClasspath +// .resolvedConfiguration +// .getResolvedArtifacts() +// .find { resolved -> +// resolved.moduleVersion.id.name == 'grails-datastore-gorm-tck' +// }.file +// +// def tckClassesDir = project.file("${project.buildDir}/tck") +// copy { +// from zipTree(tckClassesFile) +// into tckClassesDir +// } +// copy { +// from tckClassesDir +// into sourceSets.test.output.classesDirs.find { it.path.contains('classes' + File.separator + 'groovy') } +// include "**/*.class" +// exclude { details -> +// // Do not copy across any TCK class (or nested classes of that class) +// // If there is a corresponding source file in the particular modules +// // test source tree. Allows a module to override a test/helper. +// if (!details.file.isFile()) { +// return false +// } +// def candidatePath = details.file.absolutePath +// def relativePath = toBaseClassRelativePathWithoutExtension(tckClassesDir.absolutePath, candidatePath) +// +// if (relativePath == null) { +// throw new IllegalStateException("$candidatePath does not appear to be in the TCK") +// } +// +// project.file("src/test/groovy/${relativePath}.groovy").exists() +// } +// } +//} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/AutoTimestampSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/AutoTimestampSpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/AutoTimestampSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/AutoTimestampSpec.groovy index 2ba139e9852..eb222aa037c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/AutoTimestampSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/AutoTimestampSpec.groovy @@ -1,6 +1,7 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity +import grails.gorm.tests.GormDatastoreSpec class AutoTimestampSpec extends GormDatastoreSpec { @Override diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CascadeToBidirectionalAsssociationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CascadeToBidirectionalAsssociationSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CascadeToBidirectionalAsssociationSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CascadeToBidirectionalAsssociationSpec.groovy index e94ffefab27..a0e569f7437 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CascadeToBidirectionalAsssociationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CascadeToBidirectionalAsssociationSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import org.grails.orm.hibernate.GormSpec import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Club.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy similarity index 89% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Club.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy index a7fa3c1186d..7ecabad9a04 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Club.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.hibernate.HibernateEntity import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithJoinTableSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithJoinTableSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy index 8dd6b51474e..fa56bafd690 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithJoinTableSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import static grails.gorm.hibernate.mapping.MappingBuilder.define diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithManyToOneAndSequenceSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithManyToOneAndSequenceSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy index 543ac88aac3..79d9107e48d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CompositeIdWithManyToOneAndSequenceSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Contract.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Contract.groovy similarity index 87% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Contract.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Contract.groovy index e84deeaa9dc..9fb491d666d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Contract.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Contract.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CountByWithEmbeddedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CountByWithEmbeddedSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CountByWithEmbeddedSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CountByWithEmbeddedSpec.groovy index fb34d3238e2..1483be1b98f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/CountByWithEmbeddedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CountByWithEmbeddedSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DeleteAllWhereSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DeleteAllWhereSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DeleteAllWhereSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DeleteAllWhereSpec.groovy index 9b4ad24202c..4d6569e3e2b 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DeleteAllWhereSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DeleteAllWhereSpec.groovy @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package grails.gorm.tests +package grails.gorm.specs import org.grails.orm.hibernate.GormSpec import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachCriteriaSubquerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachCriteriaSubquerySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy index 81379939764..a24f7128394 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachCriteriaSubquerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy @@ -1,8 +1,9 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity import grails.gorm.hibernate.HibernateEntity +import grails.gorm.tests.GormDatastoreSpec @SuppressWarnings("GrMethodMayBeStatic") class DetachCriteriaSubquerySpec extends GormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaJoinSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy similarity index 89% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaJoinSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy index fe03d5428a4..a749f8e70a4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaJoinSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.DetachedCriteria import org.grails.datastore.gorm.finders.DynamicFinder @@ -40,7 +40,7 @@ class DetachedCriteriaJoinSpec extends HibernateGormDatastoreSpec { join('club', JoinType.INNER) createAlias('club','c') } - HibernateQuery query = session.createQuery(Team) + HibernateQuery query = HibernateGormDatastoreSpec.session.createQuery(Team) DynamicFinder.applyDetachedCriteria(query,dc) def joinType = query.hibernateCriteria.joinTypes['club'] @@ -54,7 +54,7 @@ class DetachedCriteriaJoinSpec extends HibernateGormDatastoreSpec { join('club', JoinType.LEFT) createAlias('club','c') } - HibernateQuery query = session.createQuery(Team) + HibernateQuery query = HibernateGormDatastoreSpec.session.createQuery(Team) DynamicFinder.applyDetachedCriteria(query,dc) def joinType = query.hibernateCriteria.joinTypes["club"] @@ -68,7 +68,7 @@ class DetachedCriteriaJoinSpec extends HibernateGormDatastoreSpec { join('club', JoinType.RIGHT) createAlias('club','c') } - HibernateQuery query = session.createQuery(Team) + HibernateQuery query = HibernateGormDatastoreSpec.session.createQuery(Team) DynamicFinder.applyDetachedCriteria(query,dc) def joinType = query.hibernateCriteria.joinTypes["club"] diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionAliasSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy index 53ba18416d2..02e4d1f34c4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.DetachedCriteria import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy similarity index 99% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy index c330077231c..cc439224f87 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DetachedCriteriaProjectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DomainGetterSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DomainGetterSpec.groovy similarity index 95% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DomainGetterSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DomainGetterSpec.groovy index c48d2168629..44cf6e5e8f0 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/DomainGetterSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DomainGetterSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/EnumMappingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/EnumMappingSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy index e48138b1f32..535683e6ec6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/EnumMappingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ExecuteQueryWithinValidatorSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ExecuteQueryWithinValidatorSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ExecuteQueryWithinValidatorSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ExecuteQueryWithinValidatorSpec.groovy index 90b69dbc37b..6db1f61b858 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ExecuteQueryWithinValidatorSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ExecuteQueryWithinValidatorSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy similarity index 89% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy index 11ba572eecf..f57bd2ffead 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/GroovyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy @@ -1,5 +1,7 @@ -package grails.gorm.tests +package grails.gorm.specs +import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.tests.Location import org.grails.datastore.gorm.proxy.GroovyProxyFactory import spock.lang.Ignore diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateEntityTraitGeneratedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateEntityTraitGeneratedSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy index 806191db29e..1a124a71ab4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateEntityTraitGeneratedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.transactions.Rollback import groovy.transform.Generated diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy similarity index 99% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy index 5d759dac033..01fd6f995a6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateGormDatastoreSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.core.Session diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateSuite.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateSuite.groovy similarity index 88% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateSuite.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateSuite.groovy index cd500eaa181..78ea6c91318 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/HibernateSuite.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateSuite.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import org.junit.runner.RunWith import org.junit.runners.Suite diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/IdentityEnumTypeSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/IdentityEnumTypeSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy index d5b7b9d485c..d071496b08b 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/IdentityEnumTypeSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ImportFromConstraintSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ImportFromConstraintSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ImportFromConstraintSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ImportFromConstraintSpec.groovy index dc3aa53f1c1..f950e7833e8 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ImportFromConstraintSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ImportFromConstraintSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/LastUpdateWithDynamicUpdateSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/LastUpdateWithDynamicUpdateSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/LastUpdateWithDynamicUpdateSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/LastUpdateWithDynamicUpdateSpec.groovy index 38d457811c2..fff2ac29ecd 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/LastUpdateWithDynamicUpdateSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/LastUpdateWithDynamicUpdateSpec.groovy @@ -1,6 +1,7 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity +import grails.gorm.tests.GormDatastoreSpec /** * Created by graemerocher on 27/06/16. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ManyToOneSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ManyToOneSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ManyToOneSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ManyToOneSpec.groovy index 559bd647b23..5c9e52201f6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ManyToOneSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ManyToOneSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/MultiColumnUniqueConstraintSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/MultiColumnUniqueConstraintSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy index c97805ecafa..3d25b2ea5b0 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/MultiColumnUniqueConstraintSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy @@ -1,6 +1,7 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity +import grails.gorm.tests.GormDatastoreSpec import org.springframework.dao.DataIntegrityViolationException import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/NullValueEqualSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy similarity index 86% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/NullValueEqualSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy index 483f869709a..419c7c42b9e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/NullValueEqualSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy @@ -1,4 +1,7 @@ -package grails.gorm.tests +package grails.gorm.specs + +import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.tests.TestEntity class NullValueEqualSpec extends GormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/NullableAndLengthSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullableAndLengthSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/NullableAndLengthSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullableAndLengthSpec.groovy index 95080588abc..2492d08e8db 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/NullableAndLengthSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullableAndLengthSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy similarity index 94% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy index 43a405958de..0c5bb48d33c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/OptimisticLockingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy @@ -1,5 +1,8 @@ -package grails.gorm.tests +package grails.gorm.specs +import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.tests.OptLockNotVersioned +import grails.gorm.tests.OptLockVersioned import org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Player.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Player.groovy similarity index 88% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Player.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Player.groovy index 3dd6097bf6b..ac6e6f7bf7c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Player.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Player.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/RLikeSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy similarity index 95% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/RLikeSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy index bd2d7a5ee03..5ae659ec3b0 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/RLikeSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ReadOperationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy similarity index 89% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ReadOperationSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy index 569acda1543..dd8da2f9440 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ReadOperationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy @@ -1,4 +1,6 @@ -package grails.gorm.tests +package grails.gorm.specs + +import grails.gorm.tests.TestEntity class ReadOperationSpec extends HibernateGormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SaveWithExistingValidationErrorSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SaveWithExistingValidationErrorSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SaveWithExistingValidationErrorSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SaveWithExistingValidationErrorSpec.groovy index a3c0a60e475..9eacbb35b70 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SaveWithExistingValidationErrorSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SaveWithExistingValidationErrorSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SchemaNameSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SchemaNameSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SchemaNameSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SchemaNameSpec.groovy index 84b8d870ca5..988fb8222a6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SchemaNameSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SchemaNameSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SequenceIdSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SequenceIdSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SequenceIdSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SequenceIdSpec.groovy index 7b132effe3e..384e4689c42 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SequenceIdSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SequenceIdSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SizeConstraintSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SizeConstraintSpec.groovy similarity index 95% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SizeConstraintSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SizeConstraintSpec.groovy index b8b556616df..57e2709efb6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SizeConstraintSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SizeConstraintSpec.groovy @@ -1,6 +1,7 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity +import grails.gorm.tests.GormDatastoreSpec import org.springframework.dao.DataIntegrityViolationException import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SqlQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy similarity index 99% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SqlQuerySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy index 948208e6849..642f551817f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SqlQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SubclassMultipleListCollectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubclassMultipleListCollectionSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SubclassMultipleListCollectionSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubclassMultipleListCollectionSpec.groovy index fa4d78e34ad..9e0a48f8159 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SubclassMultipleListCollectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubclassMultipleListCollectionSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SubqueryAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SubqueryAliasSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy index db1d802d81b..d56ecb7e225 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/SubqueryAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.transactions.Rollback import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TablePerSubClassAndEmbeddedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TablePerSubClassAndEmbeddedSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy index f1f1e9d6cd1..fab119d8544 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TablePerSubClassAndEmbeddedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Team.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Team.groovy similarity index 90% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Team.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Team.groovy index 1e29ff3890e..8200c9cb56a 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/Team.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Team.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import groovy.transform.ToString diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TwoBidirectionalOneToManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TwoBidirectionalOneToManySpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TwoBidirectionalOneToManySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TwoBidirectionalOneToManySpec.groovy index 877ab7231e0..a2afd756652 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/TwoBidirectionalOneToManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TwoBidirectionalOneToManySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintHibernateSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintHibernateSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy index 2a28ad83376..443f3fe042b 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueConstraintHibernateSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy @@ -1,6 +1,8 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity +import grails.gorm.tests.GroupWithin +import grails.gorm.tests.UniqueGroup import org.grails.datastore.gorm.GormEntity import org.grails.orm.hibernate.HibernateDatastore import org.springframework.transaction.PlatformTransactionManager diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueWithMultipleDataSourcesSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueWithMultipleDataSourcesSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy index 7e32cfb7b45..db93178a72f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/UniqueWithMultipleDataSourcesSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests +package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy similarity index 94% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy index cde400190b5..5f01432a966 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/ValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy @@ -1,5 +1,11 @@ -package grails.gorm.tests - +package grails.gorm.specs + +import grails.gorm.tests.ChildEntity +import grails.gorm.tests.ClassWithListArgBeforeValidate +import grails.gorm.tests.ClassWithNoArgBeforeValidate +import grails.gorm.tests.ClassWithOverloadedBeforeValidate +import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.tests.TestEntity import org.springframework.transaction.support.TransactionSynchronizationManager /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/WhereQueryWithAssociationSortSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy similarity index 94% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/WhereQueryWithAssociationSortSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy index 39a34822828..7ca2e7b7a69 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/WhereQueryWithAssociationSortSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy @@ -1,5 +1,6 @@ -package grails.gorm.tests +package grails.gorm.specs +import grails.gorm.tests.GormDatastoreSpec import org.hibernate.QueryException import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/WithNewSessionAndExistingTransactionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy similarity index 99% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/WithNewSessionAndExistingTransactionSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy index 05c6fb88a97..8e89cbee596 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/WithNewSessionAndExistingTransactionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy @@ -1,5 +1,6 @@ -package grails.gorm.tests +package grails.gorm.specs +import grails.gorm.tests.Book import org.grails.datastore.gorm.Setup import org.grails.orm.hibernate.GormSpec import org.grails.orm.hibernate.HibernateDatastore diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/autoimport/AutoImportSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/AutoImportSpec.groovy similarity index 91% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/autoimport/AutoImportSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/AutoImportSpec.groovy index 58eb4c3d5f4..d3e9dc39670 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/autoimport/AutoImportSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/AutoImportSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.autoimport +package grails.gorm.specs.autoimport import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/autoimport/other/A.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/other/A.groovy similarity index 71% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/autoimport/other/A.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/other/A.groovy index f6ec45b1f49..5d3c5680fb6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/autoimport/other/A.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/other/A.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.autoimport.other +package grails.gorm.specs.autoimport.other import grails.persistence.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/BidirectionalOneToOneWithUniqueSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/BidirectionalOneToOneWithUniqueSpec.groovy similarity index 93% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/BidirectionalOneToOneWithUniqueSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/BidirectionalOneToOneWithUniqueSpec.groovy index e4a874802a8..4e88733cc07 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/BidirectionalOneToOneWithUniqueSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/BidirectionalOneToOneWithUniqueSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.belongsto +package grails.gorm.specs.belongsto import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/Face.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/Face.groovy similarity index 81% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/Face.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/Face.groovy index 2ccdfd66283..284ab1bcae5 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/Face.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/Face.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.belongsto +package grails.gorm.specs.belongsto import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/Nose.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/Nose.groovy similarity index 85% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/Nose.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/Nose.groovy index a3b9ef22dfc..4ec4b56ee47 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/belongsto/Nose.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/belongsto/Nose.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.belongsto +package grails.gorm.specs.belongsto import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/CompositeIdCriteria.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdCriteria.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/CompositeIdCriteria.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdCriteria.groovy index 285bb5391ba..6232cb04955 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/CompositeIdCriteria.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdCriteria.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.compositeid +package grails.gorm.specs.compositeid import grails.gorm.annotation.Entity import grails.gorm.hibernate.mapping.MappingBuilder diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy index 4e73da25734..e85a77db117 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.compositeid +package grails.gorm.specs.compositeid import grails.gorm.annotation.Entity import grails.gorm.hibernate.mapping.MappingBuilder diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/GlobalConstraintWithCompositeIdSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/GlobalConstraintWithCompositeIdSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy index 6484aa45b46..514d1ddadd6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/compositeid/GlobalConstraintWithCompositeIdSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.compositeid +package grails.gorm.specs.compositeid import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateDirtyCheckingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateDirtyCheckingSpec.groovy similarity index 99% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateDirtyCheckingSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateDirtyCheckingSpec.groovy index cb6086afe13..2c19aea6c6e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateDirtyCheckingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateDirtyCheckingSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.dirtychecking +package grails.gorm.specs.dirtychecking import grails.gorm.annotation.Entity import grails.gorm.dirty.checking.DirtyCheck diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateUpdateFromListenerSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateUpdateFromListenerSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateUpdateFromListenerSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateUpdateFromListenerSpec.groovy index 16807de4b7d..afa75b42e91 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/HibernateUpdateFromListenerSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateUpdateFromListenerSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.dirtychecking +package grails.gorm.specs.dirtychecking import grails.gorm.transactions.Rollback import org.grails.datastore.gorm.events.ConfigurableApplicationEventPublisher diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/PropertyFieldSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/PropertyFieldSpec.groovy similarity index 95% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/PropertyFieldSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/PropertyFieldSpec.groovy index 9e358c0ff78..66b583666f6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/dirtychecking/PropertyFieldSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/PropertyFieldSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.dirtychecking +package grails.gorm.specs.dirtychecking import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/events/UpdatePropertyInEventListenerSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/events/UpdatePropertyInEventListenerSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/events/UpdatePropertyInEventListenerSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/events/UpdatePropertyInEventListenerSpec.groovy index 5533f18e512..131fc4a5f64 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/events/UpdatePropertyInEventListenerSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/events/UpdatePropertyInEventListenerSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.events +package grails.gorm.specs.events import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/HasManyWithInQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/HasManyWithInQuerySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy index 8dcaa1bc120..0f2d7ccbedd 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/HasManyWithInQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.hasmany +package grails.gorm.specs.hasmany import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/ListCollectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/ListCollectionSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy index ef8f6da3460..d604548a6de 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/ListCollectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.hasmany +package grails.gorm.specs.hasmany import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/Something.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/Something.groovy similarity index 90% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/Something.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/Something.groovy index 43ebf510eb2..180da2d92af 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/Something.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/Something.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.hasmany +package grails.gorm.specs.hasmany class Something { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/TwoUnidirectionalHasManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/TwoUnidirectionalHasManySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy index 9db5984babe..c3df66a04f9 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hasmany/TwoUnidirectionalHasManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package grails.gorm.tests.hasmany +package grails.gorm.specs.hasmany import grails.gorm.annotation.Entity import grails.gorm.annotation.JpaEntity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy similarity index 99% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index 869c1f31cdc..cfa9d690795 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -1,7 +1,7 @@ -package grails.gorm.tests.hibernatequery +package grails.gorm.specs.hibernatequery import grails.gorm.DetachedCriteria -import grails.gorm.tests.HibernateGormDatastoreSpec +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.tests.Person import grails.gorm.tests.Pet import grails.persistence.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/SubclassToOneProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/SubclassToOneProxySpec.groovy similarity index 95% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/SubclassToOneProxySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/SubclassToOneProxySpec.groovy index 551a04ff1be..8cb75b35a8f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/SubclassToOneProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/SubclassToOneProxySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.inheritance +package grails.gorm.specs.inheritance import grails.gorm.annotation.Entity import grails.gorm.tests.GormDatastoreSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/TablePerConcreteClassAndDateCreatedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassAndDateCreatedSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/TablePerConcreteClassAndDateCreatedSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassAndDateCreatedSpec.groovy index 7309c0799cc..bc2e0589732 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/TablePerConcreteClassAndDateCreatedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassAndDateCreatedSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.inheritance +package grails.gorm.specs.inheritance import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/TablePerConcreteClassImportedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassImportedSpec.groovy similarity index 93% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/TablePerConcreteClassImportedSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassImportedSpec.groovy index 02e1ce026d1..886150d1715 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/inheritance/TablePerConcreteClassImportedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassImportedSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.inheritance +package grails.gorm.specs.inheritance import org.grails.orm.hibernate.GormSpec import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/jpa/SimpleJpaEntitySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/jpa/SimpleJpaEntitySpec.groovy similarity index 99% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/jpa/SimpleJpaEntitySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/jpa/SimpleJpaEntitySpec.groovy index 8eb6c6884c5..73fddeedbab 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/jpa/SimpleJpaEntitySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/jpa/SimpleJpaEntitySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.jpa +package grails.gorm.specs.jpa import grails.gorm.hibernate.HibernateEntity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/mappedby/MultipleOneToOneSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/mappedby/MultipleOneToOneSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/mappedby/MultipleOneToOneSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/mappedby/MultipleOneToOneSpec.groovy index 57d8fa8bb7d..d8fa7568394 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/mappedby/MultipleOneToOneSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/mappedby/MultipleOneToOneSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.mappedby +package grails.gorm.specs.mappedby import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy index 4544b0144b7..20817768ce5 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.multitenancy +package grails.gorm.specs.multitenancy import grails.gorm.MultiTenant import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy index 91fb0469674..a0b4a502d63 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.multitenancy +package grails.gorm.specs.multitenancy import grails.gorm.annotation.Entity import org.grails.datastore.mapping.core.DatastoreUtils diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/perf/JoinPerfSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/perf/JoinPerfSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/perf/JoinPerfSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/perf/JoinPerfSpec.groovy index 37f7c93010d..e7718439bd7 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/perf/JoinPerfSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/perf/JoinPerfSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.perf +package grails.gorm.specs.perf import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/ByteBuddyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/ByteBuddyProxySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy index 280b136f53c..ffedbd7f9d8 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/ByteBuddyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy @@ -1,10 +1,10 @@ -package grails.gorm.tests.proxy +package grails.gorm.specs.proxy import org.grails.datastore.mapping.reflect.ClassUtils -import grails.gorm.tests.Club +import grails.gorm.specs.Club import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Team +import grails.gorm.specs.Team import spock.lang.PendingFeature import spock.lang.PendingFeatureIf diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/StaticTestUtil.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy similarity index 92% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/StaticTestUtil.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy index 89b071af7ff..dc170c60c38 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/proxy/StaticTestUtil.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy @@ -1,12 +1,12 @@ -package grails.gorm.tests.proxy +package grails.gorm.specs.proxy import groovy.transform.CompileStatic import org.grails.datastore.gorm.GormEntity import org.hibernate.Hibernate -import grails.gorm.tests.Club -import grails.gorm.tests.Team +import grails.gorm.specs.Club +import grails.gorm.specs.Team @CompileStatic class StaticTestUtil { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/services/DataServiceSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/services/DataServiceSpec.groovy similarity index 99% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/services/DataServiceSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/services/DataServiceSpec.groovy index 795a3f44b4b..af42144bc18 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/services/DataServiceSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/services/DataServiceSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.services +package grails.gorm.specs.services import grails.gorm.annotation.Entity import grails.gorm.services.Join diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/softdelete/SoftDeleteSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/softdelete/SoftDeleteSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/softdelete/SoftDeleteSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/softdelete/SoftDeleteSpec.groovy index 1858d05da56..33a623dbc3d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/softdelete/SoftDeleteSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/softdelete/SoftDeleteSpec.groovy @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package grails.gorm.tests.softdelete +package grails.gorm.specs.softdelete import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/traits/InterfacePropertySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/InterfacePropertySpec.groovy similarity index 95% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/traits/InterfacePropertySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/InterfacePropertySpec.groovy index 54e74e961b2..845e8b48dc4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/traits/InterfacePropertySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/InterfacePropertySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.traits +package grails.gorm.specs.traits import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/traits/TraitPropertySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/TraitPropertySpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/traits/TraitPropertySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/TraitPropertySpec.groovy index 35fab9df1a9..513c9f189e6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/traits/TraitPropertySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/TraitPropertySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.traits +package grails.gorm.specs.traits import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/CustomIsolationLevelSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/CustomIsolationLevelSpec.groovy similarity index 87% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/CustomIsolationLevelSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/CustomIsolationLevelSpec.groovy index fc01d24810d..c305413ed49 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/CustomIsolationLevelSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/CustomIsolationLevelSpec.groovy @@ -1,7 +1,7 @@ -package grails.gorm.tests.txs +package grails.gorm.specs.txs -import grails.gorm.tests.services.Attribute -import grails.gorm.tests.services.Product +import grails.gorm.specs.services.Attribute +import grails.gorm.specs.services.Product import grails.gorm.transactions.Transactional import org.grails.orm.hibernate.HibernateDatastore import org.springframework.transaction.annotation.Isolation diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/TransactionPropagationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionPropagationSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/TransactionPropagationSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionPropagationSpec.groovy index 8b2bfa13fb3..0e558b70dcf 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/TransactionPropagationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionPropagationSpec.groovy @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package grails.gorm.tests.txs +package grails.gorm.specs.txs import grails.gorm.annotation.Entity import grails.gorm.transactions.ReadOnly diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/TransactionalWithinReadOnlySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionalWithinReadOnlySpec.groovy similarity index 93% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/TransactionalWithinReadOnlySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionalWithinReadOnlySpec.groovy index 1bf3800b41a..a9e74eeeb1a 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/txs/TransactionalWithinReadOnlySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionalWithinReadOnlySpec.groovy @@ -13,10 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package grails.gorm.tests.txs +package grails.gorm.specs.txs -import grails.gorm.tests.services.Attribute -import grails.gorm.tests.services.Product +import grails.gorm.specs.services.Attribute +import grails.gorm.specs.services.Product import grails.gorm.transactions.ReadOnly import grails.gorm.transactions.Transactional import org.grails.orm.hibernate.GormSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/uuid/UuidInsertSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/uuid/UuidInsertSpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/uuid/UuidInsertSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/uuid/UuidInsertSpec.groovy index 3fe80a12c74..5e3ca15c656 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/uuid/UuidInsertSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/uuid/UuidInsertSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.uuid +package grails.gorm.specs.uuid import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/BeanValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/BeanValidationSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy index 39096689e97..ce61abf9e07 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/BeanValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/CascadeValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/CascadeValidationSpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/CascadeValidationSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/CascadeValidationSpec.groovy index b78c846f07a..b850c31da1f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/CascadeValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/CascadeValidationSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/DeepValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/DeepValidationSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/DeepValidationSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/DeepValidationSpec.groovy index 1d4a482dcbc..f819e3242de 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/DeepValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/DeepValidationSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.tests.GormDatastoreSpec diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/EmbeddedWithValidationExceptionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/EmbeddedWithValidationExceptionSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/EmbeddedWithValidationExceptionSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/EmbeddedWithValidationExceptionSpec.groovy index 6d410aa2037..294a889ae59 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/EmbeddedWithValidationExceptionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/EmbeddedWithValidationExceptionSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/SaveWithInvalidEntitySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/SaveWithInvalidEntitySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy index ca8a2a54a84..2105fa0fd42 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/SaveWithInvalidEntitySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/SkipValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SkipValidationSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/SkipValidationSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SkipValidationSpec.groovy index 0b3d3ff229f..1414f525d87 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/SkipValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SkipValidationSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueFalseConstraintSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueFalseConstraintSpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueFalseConstraintSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueFalseConstraintSpec.groovy index cb95154f548..923a33d3684 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueFalseConstraintSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueFalseConstraintSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.transactions.Rollback import grails.gorm.annotation.Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueInheritanceSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueInheritanceSpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueInheritanceSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueInheritanceSpec.groovy index c744cb0937d..e079dfd09e9 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueInheritanceSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueInheritanceSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueWithHasOneSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueWithHasOneSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy index 62b5825672c..5f241766047 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueWithHasOneSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueWithinGroupSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy similarity index 98% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueWithinGroupSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy index 2b0543ac9fe..263366e5640 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/tests/validation/UniqueWithinGroupSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.tests.validation +package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback From fb32741d8c9d4d5ec85af7c8571f1800f2f0a71c Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 12 Feb 2025 19:34:02 -0600 Subject: [PATCH 0021/1008] fixing multiple specs --- .../AbstractHibernateGormStaticApi.groovy | 4 +- .../HibernateMappingContextConfiguration.java | 6 +- .../AbstractHibernateCriteriaBuilder.java | 2 +- .../query/AbstractHibernateQuery.java | 4 +- .../hibernate/query/PredicateGenerator.java | 57 ++++++++++++++----- .../specs/CompositeIdWithJoinTableSpec.groovy | 3 + .../specs/HibernateGormDatastoreSpec.groovy | 2 +- .../gorm/specs/NullValueEqualSpec.groovy | 8 ++- .../hibernatequery/HibernateQuerySpec.groovy | 18 +++++- .../specs/services/DataServiceSpec.groovy | 30 ++++++---- .../org/grails/datastore/gorm/Setup.groovy | 4 +- .../MultipleDataSourceConnectionsSpec.groovy | 18 ++++-- 12 files changed, 115 insertions(+), 41 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy index 02abc5a37f9..c4d31a3abce 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy @@ -571,7 +571,9 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { } return (List) template.execute { Session session -> - Query q = (Query) session.createQuery(query.toString(),persistentEntity.javaClass) + //TODO Right now making the return type of Object.class to execute arbitrary queries + // not sure if this will work for projections + Query q = (Query) session.createQuery(query.toString(),Object.class) template.applySettings(q) populateQueryArguments(q, params) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java index 1cecd1daa7a..560e6aba9db 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java @@ -288,7 +288,11 @@ public void sessionFactoryClosed(SessionFactory factory) { .applySettings(getProperties()); StandardServiceRegistry serviceRegistry = standardServiceRegistryBuilder.build(); - sessionFactory = super.buildSessionFactory(serviceRegistry); + try { + sessionFactory = super.buildSessionFactory(serviceRegistry); + } catch (HibernateException e) { + throw new RuntimeException(e); + } this.serviceRegistry = serviceRegistry; return sessionFactory; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index dd37421a983..062ec1d7bff 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -122,8 +122,8 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo @SuppressWarnings("rawtypes") public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, AbstractHibernateDatastore datastore) { - setDatastore(datastore); this.targetClass = targetClass; + setDatastore(datastore); this.sessionFactory = sessionFactory; this.cb = sessionFactory.getCriteriaBuilder(); // this.criteriaQuery = cb.createQuery(targetClass); diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 8e4acb861e5..4b1cb185111 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -416,7 +416,7 @@ public Object singleResult() { try { return createQuery().getSingleResult(); } - catch (Throwable e) { + catch (jakarta.persistence.NoResultException e) { return null; } } @@ -506,7 +506,7 @@ private List collectProjections() { private void assignCriteria(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root) { List criteriaList = (List)detachedCriteria.getCriteria(); if (!criteriaList.isEmpty()) { - cq.where(cb.and(PredicateGenerator.getPredicates(cb, cq, root, criteriaList))); + cq.where(cb.and(PredicateGenerator.getPredicates(cb, cq, root, criteriaList,getSessionFactory().getCurrentSession()))); } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index fee826008a4..67442930184 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -1,15 +1,21 @@ package org.grails.orm.hibernate.query; import groovy.util.logging.Slf4j; +import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.From; import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; +import jakarta.persistence.metamodel.EntityType; +import jakarta.persistence.metamodel.PluralAttribute; +import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.query.Query; +import org.hibernate.Session; import org.hibernate.query.criteria.HibernateCriteriaBuilder; -import org.hibernate.query.criteria.JpaExpression; +import org.hibernate.query.criteria.JpaInPredicate; +import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,30 +27,34 @@ import java.util.Date; import java.util.List; import java.util.Objects; +import java.util.Optional; +import java.util.Set; @Slf4j public class PredicateGenerator { private static final Logger log = LoggerFactory.getLogger(PredicateGenerator.class); - public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, From root_, List criteriaList) { + public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, From root_, List criteriaList, EntityManager entityManager) { return criteriaList.stream(). map(criterion -> { if (criterion instanceof Query.Disjunction) { List criterionList = ((Query.Disjunction) criterion).getCriteria(); - return cb.or(getPredicates(cb, criteriaQuery, root_, criterionList)); + return cb.or(getPredicates(cb, criteriaQuery, root_, criterionList, entityManager)); } else if (criterion instanceof Query.Conjunction) { List criterionList = ((Query.Conjunction) criterion).getCriteria(); - return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList)); + return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList, entityManager)); } else if (criterion instanceof Query.Negation) { List criterionList = ((Query.Negation) criterion).getCriteria(); - Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList); + Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList, entityManager); if (predicates.length != 1) { log.error("Must have a single predicate behind a not"); throw new RuntimeException("Must have a single predicate behind a not"); } return cb.not(predicates[0]); + } else if (criterion instanceof Query.IsNull c) { + return cb.isNull(root_.get(c.getProperty())); } else if (criterion instanceof Query.IsNotNull c) { return cb.isNotNull(root_.get(c.getProperty())); } else if (criterion instanceof Query.IsEmpty c) { @@ -113,48 +123,62 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue return cb.lt(cb.size(root_.get(c.getProperty())),(Number) c.getValue()); } else if (criterion instanceof Query.LessThanEquals c) { return cb.le(root_.get(c.getProperty()), (Number) c.getValue()); + } else if (criterion instanceof DetachedAssociationCriteria c + ) { + +// Subquery subquery = criteriaQuery.subquery(Object.class); +// Root from = subquery.from(c.getPersistentEntity().getJavaClass()); +// Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getCriteria(), entityManager); +// +// EntityType entity = entityManager.getMetamodel().entity(root_.getJavaType()); +// PluralAttribute pluralAttribute = (PluralAttribute )entity.getPluralAttributes().stream().toList().get(0); +//// subquery.select(from.get(root_.)).where(cb.and(predicates)).alias(c.getAlias()); +// String associationPath = c.getAssociationPath(); +// return cb.isMember(Optional.ofNullable(root_.get(associationPath)), from.get(pluralAttribute)); } else if (criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) && !c.getSubquery().getProjections().isEmpty() && c.getSubquery().getProjections().get(0) instanceof Query.PropertyProjection ) { + JpaInPredicate in = cb.in(root_.get(c.getProperty())); Query.PropertyProjection projection = (Query.PropertyProjection) c.getSubquery().getProjections().get(0); boolean distinct = projection instanceof Query.DistinctPropertyProjection; - Subquery subquery = criteriaQuery.subquery(Object.class); + Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), entityManager); subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); - return cb.in(root_.get(c.getProperty())).value(subquery); + return in.value(subquery); } else if (criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) && !c.getSubquery().getProjections().isEmpty() && c.getSubquery().getProjections().get(0) instanceof Query.IdProjection ) { - Subquery subquery = criteriaQuery.subquery(Object.class); + JpaInPredicate in = cb.in(root_.get("id")); + Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), entityManager); subquery.select(from).where(cb.and(predicates)); - return cb.in(root_.get("id")).value(subquery); + return in.value(subquery); } else if (criterion instanceof Query.In c && !c.getValues().isEmpty() ) { return cb.in(root_.get(c.getProperty()), c.getValues()); } else if (criterion instanceof Query.Exists c) { Subquery subquery = criteriaQuery.subquery(Object.class); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), entityManager); subquery.select(cb.literal(1)).where(cb.and(predicates)); return cb.exists(subquery); } else if (criterion instanceof Query.NotExists c) { Subquery subquery = criteriaQuery.subquery(Object.class); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), entityManager); subquery.select(cb.literal(1)).where(cb.and(predicates)); return cb.not(cb.exists(subquery)); } else if (criterion instanceof Query.SubqueryCriterion c) { Subquery subquery = criteriaQuery.subquery(Number.class); Root from = subquery.from(c.getValue().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria()); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria(), entityManager); if (c instanceof Query.GreaterThanEqualsAll sc ) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); return cb.greaterThanOrEqualTo(root_.get(sc.getProperty()),subquery); @@ -203,4 +227,9 @@ else if (criterion instanceof Query.SubqueryCriterion c) { return null; }).filter(Objects::nonNull).toList().toArray(new Predicate[0]); } + + private static Class getJavaTypeOfInClause(SqmInListPredicate in) { + Class javaTypeOfInClause = in.getTestExpression().getExpressible().getExpressibleJavaType().getJavaTypeClass(); + return javaTypeOfInClause; + } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy index fa56bafd690..cfa725b6ee6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy @@ -1,5 +1,7 @@ package grails.gorm.specs +import spock.lang.Ignore + import static grails.gorm.hibernate.mapping.MappingBuilder.define import grails.gorm.annotation.Entity @@ -13,6 +15,7 @@ import spock.lang.Specification /** * Created by graemerocher on 26/01/2017. */ +@Ignore("Composite Id saving is not working") class CompositeIdWithJoinTableSpec extends HibernateGormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy index 01fd6f995a6..3431b71c55e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateGormDatastoreSpec.groovy @@ -42,7 +42,7 @@ class HibernateGormDatastoreSpec extends Specification{ Session configure() { ConfigObject grailsConfig = new ConfigObject() Map config = [ - 'dataSource.url':"jdbc:tc:postgresql:///dev_db", + 'dataSource.url':"jdbc:tc:postgresql:latest:///dev_db", 'dataSource.dbCreate': 'create-drop', 'dataSource.formatSql': 'true', 'dataSource.logSql': 'true', diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy index 419c7c42b9e..36ac68765ec 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy @@ -1,9 +1,15 @@ package grails.gorm.specs +import grails.gorm.tests.ChildEntity import grails.gorm.tests.GormDatastoreSpec import grails.gorm.tests.TestEntity +import org.grails.orm.hibernate.HibernateDatastoreSpec -class NullValueEqualSpec extends GormDatastoreSpec { +class NullValueEqualSpec extends HibernateGormDatastoreSpec { + + List getDomainClasses() { + [TestEntity, ChildEntity] + } void "test null value in equal and not equal"() { when: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index cfa9d690795..dbe41328015 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -319,9 +319,9 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldPet == newPet } - @Ignore("Not sure why this is not passing") + @Ignore("Exits subquery is broken") /** - * @see org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() + * org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() * else if (criterion instanceof Query.Exists c) select p1_0.id, @@ -356,7 +356,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } - @Ignore("Not sure why this is not passing") + @Ignore("Exists subquery is broken") /** * @see org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() * else if (criterion instanceof Query.NotExists c) @@ -717,6 +717,18 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } + def maxResults() { + given: + new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + hibernateQuery.maxResults(1).order(Query.Order.asc("age")) + when: + def bobs = hibernateQuery.list() + then: + bobs.size() == 1 + bobs[0] == oldBob + + } + } @Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/services/DataServiceSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/services/DataServiceSpec.groovy index af42144bc18..4a5ca70f45d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/services/DataServiceSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/services/DataServiceSpec.groovy @@ -10,6 +10,7 @@ import grails.gorm.validation.PersistentEntityValidator import grails.validation.ValidationException import groovy.json.DefaultJsonGenerator import groovy.json.JsonGenerator +import groovy.transform.EqualsAndHashCode import org.grails.datastore.gorm.validation.constraints.eval.DefaultConstraintEvaluator import org.grails.datastore.gorm.validation.constraints.registry.DefaultConstraintRegistry import org.grails.orm.hibernate.HibernateDatastore @@ -42,6 +43,9 @@ class DataServiceSpec extends Specification { void "test list products"() { given: Product p1 = new Product(name: "Apple", type:"Fruit").save(flush:true) + p1.attributes = new HashSet<>() + p1.attributes.add(new Attribute(name:"Yummy", product:p1)) + p1.save(flush:true) Product p2 = new Product(name: "Orange", type:"Fruit").save(flush:true) ProductService productService = datastore.getService(ProductService) @@ -260,11 +264,11 @@ class DataServiceSpec extends Specification { productService.saveProduct("Pumpkin", "Vegetable") productService.saveProduct("Tomato", "Fruit") - Product p = productService.searchByType("Veg%") + Product p = productService.searchByType("Fru%") then: p != null - p.name == 'Carrot' + p.name == 'Tomato' productService.searchByType("Stuf%") == null productService.searchProducts("Veg%").size() == 2 productService.howManyProducts("Veg%") == 2 @@ -322,7 +326,7 @@ class DataServiceSpec extends Specification { info != null info.name == "Pumpkin" productService.searchProductInfoByName("Pump%") != null - productService.findByTypeLike("Veg%") != null + productService.findByTypeLike("Frui%") != null productService.findByTypeLike("Jun%") == null productService.findAllByTypeLike( "Vege%").size() == 2 @@ -365,13 +369,12 @@ class DataServiceSpec extends Specification { void "test findBy dynamic finder with @Join doesn't return proxies"() { given: ProductService productService = datastore.getService(ProductService) - new Product(name: "Apple", type: "Fruit") - .addToAttributes(name: "round") - .save(flush:true) + def p1 = new Product(name: "Apple", type: "Fruit").save(flush:true) + Attribute attribute = new Attribute(name: "round", product: p1) + p1.addToAttributes(attribute) + p1.save(flush:true) - new Product(name: "Banana", type: "Fruit") - .addToAttributes(name: "curved") - .save(flush:true) + new Product(name: "Banana", type: "Fruit").save(flush:true) datastore.currentSession.clear() @@ -379,7 +382,11 @@ class DataServiceSpec extends Specification { Product product = productService.findByName("Apple").first() then: - product.attributes.isInitialized() + //TODO I am not sure this is the right assertion related to the bug reported + //product.attributes.isInitialized() + product.attributes.size() == 1 + product.attributes.iterator().next() == attribute + } } @@ -391,6 +398,7 @@ interface ProductInfo { class Product { String name String type + Set attributes static hasMany = [attributes:Attribute] @@ -400,8 +408,10 @@ class Product { } @Entity +@EqualsAndHashCode(includes = ["name"]) class Attribute { String name + Product product } interface AnotherProductInterface { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy index 4d17aceb4d6..cd7f9bb045a 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/datastore/gorm/Setup.groovy @@ -43,7 +43,9 @@ class Setup { if(hibernateConfig != null) { hibernateConfig = null } - hibernateDatastore.destroy() + if (hibernateDatastore != null) { + hibernateDatastore.destroy() + } grailsApplication = null hibernateDatastore = null hibernateSession = null diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourceConnectionsSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourceConnectionsSpec.groovy index 4ce3bfb7a81..3cb5128126d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourceConnectionsSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourceConnectionsSpec.groovy @@ -43,24 +43,29 @@ class MultipleDataSourceConnectionsSpec extends Specification { then:"The default data source is bound" result ==1 Book.withNewSession { Session s -> - assert s.connection().metaData.getURL() == "jdbc:h2:mem:books" + def url = s.doReturningWork { return it.metaData.getURL() } + assert url == "jdbc:h2:mem:books" return true } Book.moreBooks.withNewSession { Session s -> - assert s.connection().metaData.getURL() == "jdbc:h2:mem:moreBooks" + def url = s.doReturningWork { return it.metaData.getURL() } + assert url == "jdbc:h2:mem:moreBooks" return true } Author.withNewSession { Author.count() == 1 } Author.withNewSession { Session s -> - assert s.connection().metaData.getURL() == "jdbc:h2:mem:grailsDB" + def url = s.doReturningWork { return it.metaData.getURL() } + assert url == "jdbc:h2:mem:grailsDB" return true } Author.books.withNewSession { Session s -> - assert s.connection().metaData.getURL() == "jdbc:h2:mem:books" + def url = s.doReturningWork { return it.metaData.getURL() } + assert url == "jdbc:h2:mem:books" return true } Author.moreBooks.withNewSession { Session s -> - assert s.connection().metaData.getURL() == "jdbc:h2:mem:moreBooks" + def url = s.doReturningWork { return it.metaData.getURL() } + assert url == "jdbc:h2:mem:moreBooks" return true } @@ -89,7 +94,8 @@ class MultipleDataSourceConnectionsSpec extends Specification { Author.withTransaction { Author.count() } == 1 Book.withTransaction { Book.count() } == 1 Author.yetAnother.withNewSession { Session s -> - assert s.connection().metaData.getURL() == "jdbc:h2:mem:yetAnotherDB" + def url = s.doReturningWork { return it.metaData.getURL() } + assert url == "jdbc:h2:mem:yetAnotherDB" return true } } From 1429e5a6ba10a90e74934ae738ea7d382b886dec Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Thu, 13 Feb 2025 15:37:16 -0600 Subject: [PATCH 0022/1008] aliases on projections --- .../query/AbstractHibernateQuery.java | 45 +++++++++++++++---- .../hibernatequery/HibernateQuerySpec.groovy | 7 +-- 2 files changed, 40 insertions(+), 12 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 4b1cb185111..672432c1a64 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -21,8 +21,10 @@ import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.From; +import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.Path; +import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; @@ -49,6 +51,7 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Bridges the Query API with the Hibernate Criteria API @@ -118,6 +121,11 @@ public Query isNotNull(String property) { return this; } + public Query createAlias(String associationPath, String alias) { + detachedCriteria.createAlias(associationPath, alias); + return this; + } + @Override public PersistentEntity getEntity() { @@ -451,13 +459,26 @@ private static Predicate combinePredicates(Predicate... predicates) { protected org.hibernate.query.Query createQuery() { HibernateCriteriaBuilder cb = getCriteriaBuilder(); + Map aliasMap = ((List) detachedCriteria.getCriteria() + .stream() + .filter(DetachedAssociationCriteria.class::isInstance) + .map(DetachedAssociationCriteria.class::cast) + .toList()).stream() + .collect(Collectors.toMap( + DetachedAssociationCriteria::getAssociationPath, + DetachedAssociationCriteria::getAlias) + ); + List projections = collectProjections(); + List groupProjections = collectGroupProjections(); - List joinColumns = collectJoinColumns(); + + List joinColumns = Stream.concat(aliasMap.keySet().stream(), collectJoinColumns().stream()).distinct().toList(); + CriteriaQuery cq = projections.size() > 1 ? cb.createQuery(Object[].class) : cb.createQuery(Object.class); From root = cq.from(entity.getJavaClass()); - Map tablesByName = assignJoinTables(joinColumns, root); + Map tablesByName = assignJoinTables(joinColumns, root,aliasMap); assignProjections(projections, cb, root, tablesByName, cq); assignGroupBy(groupProjections, root, cq); assignOrderBy(cq, cb, root); @@ -550,7 +571,7 @@ private void assignGroupBy(List groupProjections, From private void assignProjections(List projections, HibernateCriteriaBuilder cb, From root, Map tablesByName, CriteriaQuery cq) { List projectionExpressions = projections .stream() - .map(projectionToJpaExpression(cb, root, tablesByName)) + .map(projectionToJpaExpression(cb, tablesByName)) .filter(Objects::nonNull) .map(Expression.class::cast) .toList(); @@ -563,7 +584,7 @@ private void assignProjections(List projections, HibernateCriteriaBu } } - private Map assignJoinTables(List joinColumns, From root) { + private Map assignJoinTables(List joinColumns, From root, Map aliasMap) { Map joinTypes = detachedCriteria.getJoinTypes(); //The join column is column for joining from the root entity Map tablesByName = joinColumns.stream().map(joinColumn -> { @@ -573,17 +594,23 @@ private Map assignJoinTables(List joinColumns, From root) .map(Map.Entry::getValue) .findFirst() .orElse(JoinType.INNER); - From table = root.join(joinColumn, joinType); - return new AbstractMap.SimpleEntry<>(joinColumn, table); + + + Join table = root.join(joinColumn, joinType); + String column = joinColumn; + if (aliasMap.containsKey(joinColumn)) { + column = aliasMap.get(joinColumn); + table.alias(column); + } + return new AbstractMap.SimpleEntry<>(column, table); }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); tablesByName.put("root", root); return tablesByName; } private Function projectionToJpaExpression( - HibernateCriteriaBuilder cb - , From root - , Map tablesByName) { + HibernateCriteriaBuilder cb, + Map tablesByName) { return projection -> { if (countProjectionPredicate.test(projection)) { return cb.count(tablesByName.get("root")); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index dbe41328015..34f1dc90199 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -580,11 +580,12 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def projectionProperty() { given: - hibernateQuery.projections().property("lastName") + oldBob.addToPets(new Pet(name:"Lucky")).save(flush:true) + hibernateQuery.createAlias("pets", "mascota").projections().property("mascota.name") when: - def lastName = hibernateQuery.singleResult() + def petName = hibernateQuery.singleResult() then: - lastName == "Builder" + petName == "Lucky" } def projectionId() { From 247648a09ef6d3a374bed43b63810f34f5e573ca Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sun, 16 Feb 2025 09:24:29 -0600 Subject: [PATCH 0023/1008] aliases on criteria --- .../query/AbstractHibernateQuery.java | 35 ++-- .../hibernate/query/PredicateGenerator.java | 165 +++++++++--------- .../hibernatequery/HibernateQuerySpec.groovy | 131 +++++++++----- 3 files changed, 196 insertions(+), 135 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 672432c1a64..24a1ac35199 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -123,7 +123,7 @@ public Query isNotNull(String property) { public Query createAlias(String associationPath, String alias) { detachedCriteria.createAlias(associationPath, alias); - return this; + return this; } @@ -482,7 +482,7 @@ protected org.hibernate.query.Query createQuery() { assignProjections(projections, cb, root, tablesByName, cq); assignGroupBy(groupProjections, root, cq); assignOrderBy(cq, cb, root); - assignCriteria(cq, cb, root); + assignCriteria(cq, cb, root,tablesByName); org.hibernate.query.Query query = getSessionFactory() .getCurrentSession() @@ -524,10 +524,10 @@ private List collectProjections() { return projections; } - private void assignCriteria(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root) { + private void assignCriteria(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root, Map tablesByName) { List criteriaList = (List)detachedCriteria.getCriteria(); if (!criteriaList.isEmpty()) { - cq.where(cb.and(PredicateGenerator.getPredicates(cb, cq, root, criteriaList,getSessionFactory().getCurrentSession()))); + cq.where(cb.and(PredicateGenerator.getPredicates(cb, cq, root, criteriaList,tablesByName))); } } @@ -597,17 +597,22 @@ private Map assignJoinTables(List joinColumns, From root, Join table = root.join(joinColumn, joinType); - String column = joinColumn; - if (aliasMap.containsKey(joinColumn)) { - column = aliasMap.get(joinColumn); - table.alias(column); - } + String column = aliasColumn(aliasMap, joinColumn, table); return new AbstractMap.SimpleEntry<>(column, table); }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); tablesByName.put("root", root); return tablesByName; } + private static String aliasColumn(Map aliasMap, String associationPath, Join table) { + String column = associationPath; + if (aliasMap.containsKey(associationPath)) { + column = aliasMap.get(associationPath); + table.alias(column); + } + return column; + } + private Function projectionToJpaExpression( HibernateCriteriaBuilder cb, Map tablesByName) { @@ -620,10 +625,7 @@ private Function projectionToJpaExpression( return (JpaExpression) tablesByName.get("root").get("id"); } else { String propertyName = ((PropertyProjection) projection).getPropertyName(); - String[] parsed = propertyName.split("\\."); - String tableName = parsed.length > 1 ? parsed[0] : "root"; - String columnName = parsed.length > 1 ? parsed[1] :propertyName; - Path path = tablesByName.get(tableName).get(columnName); + Path path = getFullyQualifiedPath(tablesByName, propertyName); if (maxProjectionPredicate.test(projection)) { return cb.max(path); } else if (minProjectionPredicate.test(projection)) { @@ -640,6 +642,13 @@ private Function projectionToJpaExpression( }; } + public static Path getFullyQualifiedPath(Map tablesByName, String propertyName) { + String[] parsed = propertyName.split("\\."); + String tableName = parsed.length > 1 ? parsed[0] : "root"; + String columnName = parsed.length > 1 ? parsed[1] : propertyName; + return tablesByName.get(tableName).get(columnName); + } + private SessionFactory getSessionFactory() { return ((IHibernateTemplate) session.getNativeInterface()).getSessionFactory(); } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 67442930184..b98d97682eb 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -25,116 +25,111 @@ import java.time.OffsetDateTime; import java.time.ZonedDateTime; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import static org.grails.orm.hibernate.query.AbstractHibernateQuery.getFullyQualifiedPath; + @Slf4j public class PredicateGenerator { private static final Logger log = LoggerFactory.getLogger(PredicateGenerator.class); - public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, From root_, List criteriaList, EntityManager entityManager) { + public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, + CriteriaQuery criteriaQuery, + From root_, + List criteriaList, Map tablesByName) { - return criteriaList.stream(). + List list = criteriaList.stream(). map(criterion -> { if (criterion instanceof Query.Disjunction) { List criterionList = ((Query.Disjunction) criterion).getCriteria(); - return cb.or(getPredicates(cb, criteriaQuery, root_, criterionList, entityManager)); + return cb.or(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); } else if (criterion instanceof Query.Conjunction) { List criterionList = ((Query.Conjunction) criterion).getCriteria(); - return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList, entityManager)); + return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); } else if (criterion instanceof Query.Negation) { List criterionList = ((Query.Negation) criterion).getCriteria(); - Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList, entityManager); + Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName); if (predicates.length != 1) { log.error("Must have a single predicate behind a not"); throw new RuntimeException("Must have a single predicate behind a not"); } return cb.not(predicates[0]); } else if (criterion instanceof Query.IsNull c) { - return cb.isNull(root_.get(c.getProperty())); + return cb.isNull(getFullyQualifiedPath(tablesByName, c.getProperty())); } else if (criterion instanceof Query.IsNotNull c) { - return cb.isNotNull(root_.get(c.getProperty())); + return cb.isNotNull(getFullyQualifiedPath(tablesByName, c.getProperty())); } else if (criterion instanceof Query.IsEmpty c) { - return cb.isEmpty(root_.get(c.getProperty())); + return cb.isEmpty(getFullyQualifiedPath(tablesByName, c.getProperty())); } else if (criterion instanceof Query.Equals c) { - return cb.equal(root_.get(c.getProperty()), c.getValue()); + return cb.equal(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue()); } else if (criterion instanceof Query.NotEquals c) { - return cb.notEqual(root_.get(c.getProperty()), c.getValue()); + return cb.notEqual(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue()); } else if (criterion instanceof Query.EqualsProperty c) { - return cb.equal(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + return cb.equal(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.NotEqualsProperty c) { - return cb.notEqual(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + return cb.notEqual(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.LessThanEqualsProperty c) { - return cb.le(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + return cb.le(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.LessThanProperty c) { - return cb.lt(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + return cb.lt(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.GreaterThanEqualsProperty c) { - return cb.ge(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + return cb.ge(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.GreaterThanProperty c) { - return cb.gt(root_.get(c.getProperty()), root_.get(c.getOtherProperty())); + return cb.gt(getFullyQualifiedPath(tablesByName, c.getProperty()), root_.get(c.getOtherProperty())); } else if (criterion instanceof Query.IdEquals c) { return cb.equal(root_.get("id"), c.getValue()); } else if (criterion instanceof Query.GreaterThan c) { - return cb.gt(root_.get(c.getProperty()), (Number) c.getValue()); + return cb.gt(getFullyQualifiedPath(tablesByName, c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.GreaterThanEquals c) { - return cb.ge(root_.get(c.getProperty()), (Number) c.getValue()); + return cb.ge(getFullyQualifiedPath(tablesByName, c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.LessThan c) { - return cb.lt(root_.get(c.getProperty()), (Number) c.getValue()); + return cb.lt(getFullyQualifiedPath(tablesByName, c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.LessThanEquals c) { - return cb.le(root_.get(c.getProperty()), (Number) c.getValue()); + return cb.le(getFullyQualifiedPath(tablesByName, c.getProperty()), (Number) c.getValue()); } else if (criterion instanceof Query.Between c) { if (c.getFrom() instanceof String && c.getTo() instanceof String) { - return cb.between(root_.get(c.getProperty()), (String) c.getFrom(), (String) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (String) c.getFrom(), (String) c.getTo()); } else if (c.getFrom() instanceof Short && c.getTo() instanceof Short) { - return cb.between(root_.get(c.getProperty()), (Short) c.getFrom(), (Short) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Short) c.getFrom(), (Short) c.getTo()); } else if (c.getFrom() instanceof Integer && c.getTo() instanceof Integer) { - return cb.between(root_.get(c.getProperty()), (Integer) c.getFrom(), (Integer) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Integer) c.getFrom(), (Integer) c.getTo()); } else if (c.getFrom() instanceof Long && c.getTo() instanceof Long) { - return cb.between(root_.get(c.getProperty()), (Long) c.getFrom(), (Long) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Long) c.getFrom(), (Long) c.getTo()); } else if (c.getFrom() instanceof Date && c.getTo() instanceof Date) { - return cb.between(root_.get(c.getProperty()), (Date) c.getFrom(), (Date) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Date) c.getFrom(), (Date) c.getTo()); } else if (c.getFrom() instanceof Instant && c.getTo() instanceof Instant) { - return cb.between(root_.get(c.getProperty()), (Instant) c.getFrom(), (Instant) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (Instant) c.getFrom(), (Instant) c.getTo()); } else if (c.getFrom() instanceof LocalDate && c.getTo() instanceof LocalDate) { - return cb.between(root_.get(c.getProperty()), (LocalDate) c.getFrom(), (LocalDate) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (LocalDate) c.getFrom(), (LocalDate) c.getTo()); } else if (c.getFrom() instanceof LocalDateTime && c.getTo() instanceof LocalDateTime) { - return cb.between(root_.get(c.getProperty()), (LocalDateTime) c.getFrom(), (LocalDateTime) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (LocalDateTime) c.getFrom(), (LocalDateTime) c.getTo()); } else if (c.getFrom() instanceof OffsetDateTime && c.getTo() instanceof OffsetDateTime) { - return cb.between(root_.get(c.getProperty()), (OffsetDateTime) c.getFrom(), (OffsetDateTime) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (OffsetDateTime) c.getFrom(), (OffsetDateTime) c.getTo()); } else if (c.getFrom() instanceof ZonedDateTime && c.getTo() instanceof ZonedDateTime) { - return cb.between(root_.get(c.getProperty()), (ZonedDateTime) c.getFrom(), (ZonedDateTime) c.getTo()); + return cb.between(getFullyQualifiedPath(tablesByName, c.getProperty()), (ZonedDateTime) c.getFrom(), (ZonedDateTime) c.getTo()); } } else if (criterion instanceof Query.ILike c) { - return cb.ilike(root_.get(c.getProperty()), c.getValue().toString()); + return cb.ilike(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue().toString()); } else if (criterion instanceof Query.RLike c) { - return cb.like(root_.get(c.getProperty()), c.getPattern(), '\\'); + return cb.like(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getPattern(), '\\'); } else if (criterion instanceof Query.Like c) { - return cb.like(root_.get(c.getProperty()), c.getValue().toString()); + return cb.like(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValue().toString()); } else if (criterion instanceof Query.SizeEquals c) { - return cb.equal(cb.size(root_.get(c.getProperty())),c.getValue()); + return cb.equal(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), c.getValue()); } else if (criterion instanceof Query.SizeGreaterThan c) { - return cb.gt(cb.size(root_.get(c.getProperty())),(Number) c.getValue()); + return cb.gt(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeGreaterThanEquals c) { - return cb.ge(cb.size(root_.get(c.getProperty())),(Number) c.getValue()); + return cb.ge(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.SizeLessThan c) { - return cb.lt(cb.size(root_.get(c.getProperty())),(Number) c.getValue()); - } else if (criterion instanceof Query.LessThanEquals c) { - return cb.le(root_.get(c.getProperty()), (Number) c.getValue()); - } else if (criterion instanceof DetachedAssociationCriteria c - ) { - -// Subquery subquery = criteriaQuery.subquery(Object.class); -// Root from = subquery.from(c.getPersistentEntity().getJavaClass()); -// Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getCriteria(), entityManager); -// -// EntityType entity = entityManager.getMetamodel().entity(root_.getJavaType()); -// PluralAttribute pluralAttribute = (PluralAttribute )entity.getPluralAttributes().stream().toList().get(0); -//// subquery.select(from.get(root_.)).where(cb.and(predicates)).alias(c.getAlias()); -// String associationPath = c.getAssociationPath(); -// return cb.isMember(Optional.ofNullable(root_.get(associationPath)), from.get(pluralAttribute)); + return cb.lt(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); + } else if (criterion instanceof Query.SizeLessThanEquals c) { + return cb.le(cb.size(getFullyQualifiedPath(tablesByName, c.getProperty())), (Number) c.getValue()); } else if (criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) && !c.getSubquery().getProjections().isEmpty() @@ -145,7 +140,7 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue boolean distinct = projection instanceof Query.DistinctPropertyProjection; Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), entityManager); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), tablesByName); subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); return in.value(subquery); } else if (criterion instanceof Query.In c @@ -156,56 +151,62 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, CriteriaQue JpaInPredicate in = cb.in(root_.get("id")); Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), entityManager); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), tablesByName); subquery.select(from).where(cb.and(predicates)); return in.value(subquery); } else if (criterion instanceof Query.In c && !c.getValues().isEmpty() ) { - return cb.in(root_.get(c.getProperty()), c.getValues()); + return cb.in(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValues()); } else if (criterion instanceof Query.Exists c) { Subquery subquery = criteriaQuery.subquery(Object.class); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), entityManager); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), tablesByName); subquery.select(cb.literal(1)).where(cb.and(predicates)); return cb.exists(subquery); } else if (criterion instanceof Query.NotExists c) { Subquery subquery = criteriaQuery.subquery(Object.class); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), entityManager); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), tablesByName); subquery.select(cb.literal(1)).where(cb.and(predicates)); return cb.not(cb.exists(subquery)); - } - else if (criterion instanceof Query.SubqueryCriterion c) { + } else if (criterion instanceof Query.SubqueryCriterion c) { Subquery subquery = criteriaQuery.subquery(Number.class); Root from = subquery.from(c.getValue().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria(), entityManager); - if (c instanceof Query.GreaterThanEqualsAll sc ) { + Predicate[] predicates; + if (tablesByName.size() == 1 && tablesByName.containsKey("root")) { + Map newMap = new HashMap<>(); + newMap.put("root", from); + predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria(), newMap); + } else { + predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria(), tablesByName); + } + if (c instanceof Query.GreaterThanEqualsAll sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); - return cb.greaterThanOrEqualTo(root_.get(sc.getProperty()),subquery); - } else if (c instanceof Query.GreaterThanAll sc ) { + return cb.greaterThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + } else if (c instanceof Query.GreaterThanAll sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); - return cb.greaterThan(root_.get(sc.getProperty()),subquery); - } else if (c instanceof Query.LessThanEqualsAll sc ) { + return cb.greaterThan(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + } else if (c instanceof Query.LessThanEqualsAll sc) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.and(predicates)); - return cb.lessThanOrEqualTo(root_.get(sc.getProperty()),subquery); - } else if (c instanceof Query.LessThanAll sc ) { + return cb.lessThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + } else if (c instanceof Query.LessThanAll sc) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.and(predicates)); - return cb.lessThan(root_.get(sc.getProperty()),subquery); + return cb.lessThan(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); } else if (c instanceof Query.EqualsAll sc) { subquery.select(from.get(c.getProperty())).where(cb.and(predicates)); - return cb.equal(root_.get(sc.getProperty()),subquery); - } else if (c instanceof Query.GreaterThanEqualsSome sc ) { + return cb.equal(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + } else if (c instanceof Query.GreaterThanEqualsSome sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.or(predicates)); - return cb.greaterThanOrEqualTo(root_.get(sc.getProperty()),subquery); - } else if (c instanceof Query.GreaterThanSome sc ) { + return cb.greaterThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + } else if (c instanceof Query.GreaterThanSome sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.or(predicates)); - return cb.greaterThan(root_.get(sc.getProperty()),subquery); - } else if (c instanceof Query.LessThanEqualsSome sc ) { + return cb.greaterThan(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + } else if (c instanceof Query.LessThanEqualsSome sc) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.or(predicates)); - return cb.lessThanOrEqualTo(root_.get(sc.getProperty()),subquery); - } else if (c instanceof Query.LessThanSome sc ) { + return cb.lessThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); + } else if (c instanceof Query.LessThanSome sc) { subquery.select(cb.min(from.get(c.getProperty()))).where(cb.or(predicates)); - return cb.lessThan(root_.get(sc.getProperty()), subquery); + return cb.lessThan(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); } else if (criterion instanceof Query.NotIn sc && Objects.nonNull(sc.getSubquery()) && !sc.getSubquery().getProjections().isEmpty() @@ -214,7 +215,7 @@ else if (criterion instanceof Query.SubqueryCriterion c) { Query.PropertyProjection projection = (Query.PropertyProjection) sc.getSubquery().getProjections().get(0); boolean distinct = projection instanceof Query.DistinctPropertyProjection; subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); - return cb.in(root_.get(sc.getProperty())).value(subquery); + return cb.in(getFullyQualifiedPath(tablesByName, sc.getProperty())).value(subquery); } else if (criterion instanceof Query.NotIn sc && Objects.nonNull(sc.getSubquery()) && !sc.getSubquery().getProjections().isEmpty() @@ -225,7 +226,15 @@ else if (criterion instanceof Query.SubqueryCriterion c) { } } return null; - }).filter(Objects::nonNull).toList().toArray(new Predicate[0]); + }).filter(Objects::nonNull).toList(); + if (list.isEmpty()) { + list = List.of(cb.equal(cb.literal(1),cb.literal(1))); + } + return list.toArray(new Predicate[0]); + } + + private static String getAlias(Map aliasMap, Query.Equals c) { + return aliasMap.computeIfAbsent(c.getProperty(), s -> "root." + s); } private static Class getJavaTypeOfInClause(SqmInListPredicate in) { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index 34f1dc90199..795170c0e54 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -45,6 +45,17 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } + def equalsAlias() { + given: + new Person(firstName: "Fred", lastName: "Rogers", age: 51).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky")).save(flush:"true") + hibernateQuery.createAlias("pets","mascota").eq("mascota.name", "Lucky") + when: + def newBob = hibernateQuery.singleResult() + then: + oldBob == newBob + } + def ne() { given: new Person(firstName: "Fred", lastName: "Rogers", age: 51).save(flush: true) @@ -260,10 +271,8 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } def isNull() { - oldBob.lastName = null - oldBob.save(flush: true) given: - hibernateQuery.isNull("lastName") + hibernateQuery.isNull("face") when: def newBob = hibernateQuery.singleResult() then: @@ -310,9 +319,9 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def oldPet = new Pet(name: "Lucky") oldBob.addToPets(oldPet) oldBob.save(flush: true) - petHibernateQuery.notIn("owner", - new DetachedCriteria(Person).eq("lastName", "Rogers") - ) + DetachedCriteria detachedCriteria = new DetachedCriteria(Person) + detachedCriteria.eq("owner.lastName", "Rogers") + petHibernateQuery.createAlias("owner","owner").notIn("owner", detachedCriteria) when: def newPet = petHibernateQuery.singleResult() then: @@ -395,105 +404,139 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def greaterThanAll() { new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:1)).save(flush:true) + + def property = new DetachedCriteria(Pet) + .eq("age", 1) + .eq("name", "Lucky") + .property("age") given: - hibernateQuery.gtAll("age", new DetachedCriteria(Person).eq("age",48).property("age")) + hibernateQuery.gtAll("age", property) when: - def newBob = hibernateQuery.singleResult() + def bobs = hibernateQuery.list() then: - oldBob == newBob + bobs.size() == 2 } def lessThanEqualsAll() { new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:52)).save(flush:true) given: - hibernateQuery.leAll("age", new DetachedCriteria(Person).eq("age",50).property("age")) + hibernateQuery.leAll("age", new DetachedCriteria(Pet) + .eq("age", 52) + .eq("name", "Lucky") + .property("age") + ) when: - def newBob = hibernateQuery.singleResult() + def bobs = hibernateQuery.list() then: - oldBob == newBob + bobs.size() == 2 } def lessThanAll() { new Person(firstName: "Fred", lastName: "Builder", age: 52).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:100)).save(flush:true) given: - hibernateQuery.ltAll("age", new DetachedCriteria(Person).eq("age",52).property("age")) + hibernateQuery.ltAll("age", new DetachedCriteria(Pet) + .eq("age", 100) + .eq("name", "Lucky") + .property("age") + ) when: - def newBob = hibernateQuery.singleResult() + def bobs = hibernateQuery.list() then: - oldBob == newBob + bobs.size() == 2 } def greaterThanEqualsAll() { new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:48)).save(flush:true) given: - hibernateQuery.geAll("age", new DetachedCriteria(Person).eq("age",50).property("age")) + hibernateQuery.geAll("age", new DetachedCriteria(Pet) + .eq("age", 48) + .eq("name", "Lucky") + .property("age") + ) when: - def newBob = hibernateQuery.singleResult() + def bobs = hibernateQuery.list() then: - oldBob == newBob + bobs.size() == 2 } def greaterThanSome() { new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:1)).save(flush:true) given: - hibernateQuery.gtSome("age", new DetachedCriteria(Person) - .eq("age",48) - .eq("firstName","Chuck") - .property("age")) + hibernateQuery.gtSome("age", new DetachedCriteria(Pet) + .eq("age", 1) + .eq("name", "Pluto") + .property("age") + ) when: - def newBob = hibernateQuery.singleResult() + def bobs = hibernateQuery.list() then: - oldBob == newBob + bobs.size() == 2 } + def lessThanEqualsSome() { new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:52)).save(flush:true) given: - hibernateQuery.leSome("age", - new DetachedCriteria(Person) - .eq("age",50) - .eq("firstName","Chuck") - .property("age")) + hibernateQuery.leSome("age", new DetachedCriteria(Pet) + .eq("age", 52) + .eq("name", "Pluto") + .property("age") + ) when: - def newBob = hibernateQuery.singleResult() + def bobs = hibernateQuery.list() then: - oldBob == newBob + bobs.size() == 2 } def lessThanSome() { new Person(firstName: "Fred", lastName: "Builder", age: 52).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:100)).save(flush:true) given: - hibernateQuery.ltSome("age", new DetachedCriteria(Person) - .eq("age",52) - .eq("firstName","Chuck") - .property("age")) + hibernateQuery.ltSome( "age", new DetachedCriteria(Pet) + .eq("age", 100) + .eq("name", "Pluto") + .property("age") + ) when: - def newBob = hibernateQuery.singleResult() + def bobs = hibernateQuery.list() then: - oldBob == newBob + bobs.size() == 2 } def greaterThanEqualsSome() { new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:48)).save(flush:true) given: - hibernateQuery.geSome("age", new DetachedCriteria(Person) - .eq("age",50) - .eq("firstName","Chuck") - .property("age")) + hibernateQuery.geSome("age", new DetachedCriteria(Pet) + .eq("age", 48) + .eq("name", "Pluto") + .property("age") + ) when: - def newBob = hibernateQuery.singleResult() + def bobs = hibernateQuery.list() then: - oldBob == newBob + bobs.size() == 2 } def equalsAll() { new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + oldBob.addToPets(new Pet(name: "Lucky", age:50)).save(flush:true) given: - hibernateQuery.eqAll("age", new DetachedCriteria(Person).eq("age",50).property("age")) + hibernateQuery.eqAll( "age", new DetachedCriteria(Pet) + .eq("age", 50) + .eq("name", "Lucky") + .property("age") + ) when: def newBob = hibernateQuery.singleResult() then: From 08fb69a55d69f5061032f322062906d94f13d984 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sun, 16 Feb 2025 10:21:44 -0600 Subject: [PATCH 0024/1008] aliases on group by and order by --- .../query/AbstractHibernateQuery.java | 26 ++++++++------- .../hibernate/query/PredicateGenerator.java | 3 -- .../hibernatequery/HibernateQuerySpec.groovy | 33 +++++++++++++------ 3 files changed, 38 insertions(+), 24 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 24a1ac35199..ac540dec8a5 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -479,9 +479,9 @@ protected org.hibernate.query.Query createQuery() { CriteriaQuery cq = projections.size() > 1 ? cb.createQuery(Object[].class) : cb.createQuery(Object.class); From root = cq.from(entity.getJavaClass()); Map tablesByName = assignJoinTables(joinColumns, root,aliasMap); - assignProjections(projections, cb, root, tablesByName, cq); - assignGroupBy(groupProjections, root, cq); - assignOrderBy(cq, cb, root); + assignProjections(projections, cb, root, cq, tablesByName); + assignGroupBy(groupProjections, root, cq, tablesByName); + assignOrderBy(cq, cb, root,tablesByName); assignCriteria(cq, cb, root,tablesByName); org.hibernate.query.Query query = getSessionFactory() @@ -531,23 +531,24 @@ private void assignCriteria(CriteriaQuery cq, HibernateCriteriaBuilder cb, From } } - private void assignOrderBy(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root) { + private void assignOrderBy(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root, Map tablesByName) { List orders = detachedCriteria.getOrders(); if (!orders.isEmpty()) { cq.orderBy(orders .stream() .map(order -> { + Path expression = getFullyQualifiedPath(tablesByName, order.getProperty()); if (order.isIgnoreCase()) { if (order.getDirection().equals(Order.Direction.ASC)) { - return cb.asc(cb.lower(root.get(order.getProperty()))); + return cb.asc(cb.lower(expression)); } else { - return cb.desc(cb.lower(root.get(order.getProperty()))); + return cb.desc(cb.lower(expression)); } } else { if (order.getDirection().equals(Order.Direction.ASC)) { - return cb.asc(root.get(order.getProperty())); + return cb.asc(expression); } else { - return cb.desc(root.get(order.getProperty())); + return cb.desc(expression); } } @@ -557,18 +558,21 @@ private void assignOrderBy(CriteriaQuery cq, HibernateCriteriaBuilder cb, From r } } - private void assignGroupBy(List groupProjections, From root, CriteriaQuery cq) { + private void assignGroupBy(List groupProjections, From root, CriteriaQuery cq, Map tablesByName) { if (!groupProjections.isEmpty()) { List groupByPaths = groupProjections .stream() - .map(groupPropertyProjection -> root.get(groupPropertyProjection.getPropertyName())) + .map(groupPropertyProjection -> { + String propertyName = groupPropertyProjection.getPropertyName(); + return getFullyQualifiedPath(tablesByName, propertyName); + }) .map(Expression.class::cast) .toList(); cq.groupBy(groupByPaths); } } - private void assignProjections(List projections, HibernateCriteriaBuilder cb, From root, Map tablesByName, CriteriaQuery cq) { + private void assignProjections(List projections, HibernateCriteriaBuilder cb, From root, CriteriaQuery cq, Map tablesByName) { List projectionExpressions = projections .stream() .map(projectionToJpaExpression(cb, tablesByName)) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index b98d97682eb..1853e1f6adb 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -233,9 +233,6 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, return list.toArray(new Predicate[0]); } - private static String getAlias(Map aliasMap, Query.Equals c) { - return aliasMap.computeIfAbsent(c.getProperty(), s -> "root." + s); - } private static Class getJavaTypeOfInClause(SqmInListPredicate in) { Class javaTypeOfInClause = in.getTestExpression().getExpressible().getExpressibleJavaType().getJavaTypeClass(); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index 795170c0e54..57b52796d76 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -599,26 +599,33 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } def orderByAge() { - new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + def fred = new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) + oldBob.addToPets(new Pet(name:"Lucky",age:1)).save(flush:true) + fred.addToPets(new Pet(name:"Tom",age:2)).save(flush:true) given: - hibernateQuery.order(new Query.Order("age", Query.Order.Direction.DESC)) + hibernateQuery.createAlias("pets","mascota") + .order(new Query.Order("mascota.age", Query.Order.Direction.DESC)) when: def bobs = hibernateQuery.list() then: bobs.size() == 2 - oldBob == bobs[0] + oldBob == bobs[1] } def orderByNameIgnoreCase() { def fred = new Person(firstName: "Fred", lastName: "Rogers", age: 48).save(flush: true) - new Person(firstName: "Bob", lastName: "builder", age: 50).save(flush: true) + def walt = new Person(firstName: "Walt", lastName: "Disney", age: 50).save(flush: true) + oldBob.addToPets(new Pet(name:"Lucky",age:1)).save(flush:true) + fred.addToPets(new Pet(name:"Angel",age:2)).save(flush:true) + walt.addToPets(new Pet(name:"angel",age:2)).save(flush:true) given: - hibernateQuery.order(new Query.Order("lastName", Query.Order.Direction.DESC).ignoreCase()) + hibernateQuery.createAlias("pets","mascota") + .order(new Query.Order("mascota.name", Query.Order.Direction.ASC).ignoreCase()) when: def bobs = hibernateQuery.list() then: bobs.size() == 3 - fred == bobs[0] + oldBob == bobs[2] } def projectionProperty() { @@ -691,14 +698,20 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } def groupByLastNameAverageAge() { - new Person(firstName: "Fred", lastName: "Builder", age: 52).save(flush: true) + def fred = new Person(firstName: "Fred", lastName: "Rogers", age: 52) + fred.save(flush: true) + oldBob.addToPets(new Pet(name:"Lucky",age:4)).save(flush:true) + fred.addToPets(new Pet(name:"Lucky",age:2)).save(flush:true) given: - hibernateQuery.projections().groupProperty("lastName").avg("age") + hibernateQuery.createAlias("pets","mascota") + .projections() + .groupProperty("mascota.name") + .avg("mascota.age") when: def result = hibernateQuery.singleResult() then: - result[0] == "Builder" - result[1] == 51 + result[0] == "Lucky" + result[1] == 3 } def sizeEquals() { From 2547498bca6c84cab048d3aec9b27599f73c2825 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sun, 16 Feb 2025 15:39:09 -0600 Subject: [PATCH 0025/1008] now covering createAlias --- .../query/AbstractHibernateQuery.java | 58 +++++++++++++------ .../hibernate/query/PredicateGenerator.java | 28 +++++---- .../hibernatequery/HibernateQuerySpec.groovy | 24 ++++---- 3 files changed, 70 insertions(+), 40 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index ac540dec8a5..70671b29949 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -121,10 +121,6 @@ public Query isNotNull(String property) { return this; } - public Query createAlias(String associationPath, String alias) { - detachedCriteria.createAlias(associationPath, alias); - return this; - } @Override @@ -459,16 +455,15 @@ private static Predicate combinePredicates(Predicate... predicates) { protected org.hibernate.query.Query createQuery() { HibernateCriteriaBuilder cb = getCriteriaBuilder(); - Map aliasMap = ((List) detachedCriteria.getCriteria() - .stream() - .filter(DetachedAssociationCriteria.class::isInstance) - .map(DetachedAssociationCriteria.class::cast) - .toList()).stream() + List detachedAssociationCriteria = getDetachedAssociationCriteria(); + + Map aliasMap = detachedAssociationCriteria.stream() .collect(Collectors.toMap( - DetachedAssociationCriteria::getAssociationPath, - DetachedAssociationCriteria::getAlias) + DetachedAssociationCriteria::getAssociationPath, + criteria ->criteria) ); + List projections = collectProjections(); List groupProjections = collectGroupProjections(); @@ -478,7 +473,13 @@ protected org.hibernate.query.Query createQuery() { CriteriaQuery cq = projections.size() > 1 ? cb.createQuery(Object[].class) : cb.createQuery(Object.class); From root = cq.from(entity.getJavaClass()); - Map tablesByName = assignJoinTables(joinColumns, root,aliasMap); + Map fromMap = detachedAssociationCriteria.stream() + .collect(Collectors.toMap( + DetachedAssociationCriteria::getAssociationPath, + criteria -> cq.from(criteria.getAssociation().getOwner().getJavaClass())) + ); + fromMap.put("root", root); + Map tablesByName = assignJoinTables(joinColumns, root,aliasMap, fromMap); assignProjections(projections, cb, root, cq, tablesByName); assignGroupBy(groupProjections, root, cq, tablesByName); assignOrderBy(cq, cb, root,tablesByName); @@ -498,6 +499,28 @@ protected org.hibernate.query.Query createQuery() { return query; } + private List getDetachedAssociationCriteria() { + List detachedAssociationCriteria = detachedCriteria.getCriteria() + .stream() + .map(o -> { + if (o instanceof In c && Objects.nonNull(c.getSubquery()) ) { + return c.getSubquery().getCriteria(); + } else if (o instanceof Exists c && Objects.nonNull(c.getSubquery()) ) { + return c.getSubquery().getCriteria(); + } else if (o instanceof NotExists c && Objects.nonNull(c.getSubquery()) ) { + return c.getSubquery().getCriteria(); + } else if (o instanceof SubqueryCriterion c && Objects.nonNull(c.getValue()) ) { + return c.getValue().getCriteria(); + } + return List.of(o); + }) + .flatMap(list -> ((List) list).stream()) + .filter(DetachedAssociationCriteria.class::isInstance) + .map(DetachedAssociationCriteria.class::cast) + .toList(); + return detachedAssociationCriteria; + } + private List collectJoinColumns() { List joinColumns = ((Map) detachedCriteria.getFetchStrategies()) .entrySet() @@ -588,7 +611,7 @@ private void assignProjections(List projections, HibernateCriteriaBu } } - private Map assignJoinTables(List joinColumns, From root, Map aliasMap) { + private Map assignJoinTables(List joinColumns, From root, Map aliasMap, Map fromMap) { Map joinTypes = detachedCriteria.getJoinTypes(); //The join column is column for joining from the root entity Map tablesByName = joinColumns.stream().map(joinColumn -> { @@ -598,9 +621,8 @@ private Map assignJoinTables(List joinColumns, From root, .map(Map.Entry::getValue) .findFirst() .orElse(JoinType.INNER); - - - Join table = root.join(joinColumn, joinType); + From from = fromMap.computeIfAbsent(joinColumn, s -> fromMap.get("root")); + Join table = from.join(joinColumn, joinType); String column = aliasColumn(aliasMap, joinColumn, table); return new AbstractMap.SimpleEntry<>(column, table); }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); @@ -608,10 +630,10 @@ private Map assignJoinTables(List joinColumns, From root, return tablesByName; } - private static String aliasColumn(Map aliasMap, String associationPath, Join table) { + private static String aliasColumn(Map aliasMap, String associationPath, Join table) { String column = associationPath; if (aliasMap.containsKey(associationPath)) { - column = aliasMap.get(associationPath); + column = aliasMap.get(associationPath).getAlias(); table.alias(column); } return column; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 1853e1f6adb..1e9867561f6 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -140,7 +140,8 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, boolean distinct = projection instanceof Query.DistinctPropertyProjection; Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), tablesByName); + List subCriteria = c.getSubquery().getCriteria(); + Predicate[] predicates = getSubPredicates(cb, criteriaQuery, tablesByName, from, subCriteria); subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); return in.value(subquery); } else if (criterion instanceof Query.In c @@ -151,7 +152,8 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, JpaInPredicate in = cb.in(root_.get("id")); Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), tablesByName); + List subCriteria = c.getSubquery().getCriteria(); + Predicate[] predicates = getSubPredicates(cb, criteriaQuery, tablesByName, from, subCriteria); subquery.select(from).where(cb.and(predicates)); return in.value(subquery); } else if (criterion instanceof Query.In c && !c.getValues().isEmpty() @@ -172,14 +174,8 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, } else if (criterion instanceof Query.SubqueryCriterion c) { Subquery subquery = criteriaQuery.subquery(Number.class); Root from = subquery.from(c.getValue().getPersistentEntity().getJavaClass()); - Predicate[] predicates; - if (tablesByName.size() == 1 && tablesByName.containsKey("root")) { - Map newMap = new HashMap<>(); - newMap.put("root", from); - predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria(), newMap); - } else { - predicates = getPredicates(cb, criteriaQuery, from, c.getValue().getCriteria(), tablesByName); - } + List subCriteria = c.getValue().getCriteria(); + Predicate[] predicates = getSubPredicates(cb, criteriaQuery, tablesByName, from, subCriteria); if (c instanceof Query.GreaterThanEqualsAll sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); return cb.greaterThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); @@ -233,6 +229,18 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, return list.toArray(new Predicate[0]); } + private static Predicate[] getSubPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, Map tablesByName, Root from, List subCriteria) { + Predicate[] predicates; + if (tablesByName.size() == 1 && tablesByName.containsKey("root")) { + Map newMap = new HashMap<>(); + newMap.put("root", from); + predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); + } else { + predicates = getPredicates(cb, criteriaQuery, from, subCriteria, tablesByName); + } + return predicates; + } + private static Class getJavaTypeOfInClause(SqmInListPredicate in) { Class javaTypeOfInClause = in.getTestExpression().getExpressible().getExpressibleJavaType().getJavaTypeClass(); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index 57b52796d76..98e37000331 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -45,11 +45,11 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } - def equalsAlias() { + def equalsJoins() { given: new Person(firstName: "Fred", lastName: "Rogers", age: 51).save(flush: true) oldBob.addToPets(new Pet(name: "Lucky")).save(flush:"true") - hibernateQuery.createAlias("pets","mascota").eq("mascota.name", "Lucky") + hibernateQuery.join("pets").eq("pets.name", "Lucky") when: def newBob = hibernateQuery.singleResult() then: @@ -321,7 +321,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob.save(flush: true) DetachedCriteria detachedCriteria = new DetachedCriteria(Person) detachedCriteria.eq("owner.lastName", "Rogers") - petHibernateQuery.createAlias("owner","owner").notIn("owner", detachedCriteria) + petHibernateQuery.join("owner").notIn("owner", detachedCriteria) when: def newPet = petHibernateQuery.singleResult() then: @@ -367,7 +367,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { @Ignore("Exists subquery is broken") /** - * @see org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() + * org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() * else if (criterion instanceof Query.NotExists c) select p1_0.id, @@ -603,8 +603,8 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob.addToPets(new Pet(name:"Lucky",age:1)).save(flush:true) fred.addToPets(new Pet(name:"Tom",age:2)).save(flush:true) given: - hibernateQuery.createAlias("pets","mascota") - .order(new Query.Order("mascota.age", Query.Order.Direction.DESC)) + hibernateQuery.join("pets") + .order(new Query.Order("pets.age", Query.Order.Direction.DESC)) when: def bobs = hibernateQuery.list() then: @@ -619,8 +619,8 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { fred.addToPets(new Pet(name:"Angel",age:2)).save(flush:true) walt.addToPets(new Pet(name:"angel",age:2)).save(flush:true) given: - hibernateQuery.createAlias("pets","mascota") - .order(new Query.Order("mascota.name", Query.Order.Direction.ASC).ignoreCase()) + hibernateQuery.join("pets") + .order(new Query.Order("pets.name", Query.Order.Direction.ASC).ignoreCase()) when: def bobs = hibernateQuery.list() then: @@ -631,7 +631,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def projectionProperty() { given: oldBob.addToPets(new Pet(name:"Lucky")).save(flush:true) - hibernateQuery.createAlias("pets", "mascota").projections().property("mascota.name") + hibernateQuery.join("pets").projections().property("pets.name") when: def petName = hibernateQuery.singleResult() then: @@ -703,10 +703,10 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob.addToPets(new Pet(name:"Lucky",age:4)).save(flush:true) fred.addToPets(new Pet(name:"Lucky",age:2)).save(flush:true) given: - hibernateQuery.createAlias("pets","mascota") + hibernateQuery.join("pets") .projections() - .groupProperty("mascota.name") - .avg("mascota.age") + .groupProperty("pets.name") + .avg("pets.age") when: def result = hibernateQuery.singleResult() then: From ec3753233b29832b4d7c250e49dc73bfd096409e Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Mon, 17 Feb 2025 18:36:38 -0600 Subject: [PATCH 0026/1008] inList --- .../AbstractHibernateCriteriaBuilder.java | 3 +- .../query/AbstractHibernateQuery.java | 29 +++++++++---------- .../orm/hibernate/query/HibernateQuery.java | 10 ------- .../specs/DetachCriteriaSubquerySpec.groovy | 10 ++++--- .../MultiColumnUniqueConstraintSpec.groovy | 2 +- .../grails/gorm/specs/SequenceIdSpec.groovy | 9 ++++-- .../specs/autoimport/AutoImportSpec.groovy | 2 +- .../hibernatequery/HibernateQuerySpec.groovy | 2 +- .../TablePerConcreteClassImportedSpec.groovy | 5 ++-- .../test/resources/simplelogger.properties | 4 +-- 10 files changed, 35 insertions(+), 41 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 062ec1d7bff..4c460cd4986 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -16,7 +16,6 @@ import jakarta.persistence.metamodel.Attribute; import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; import org.grails.datastore.mapping.query.Query; -import org.grails.datastore.mapping.query.Restrictions; import org.grails.datastore.mapping.query.api.BuildableCriteria; import org.grails.datastore.mapping.query.api.Criteria; import org.grails.datastore.mapping.query.api.QueryableCriteria; @@ -645,7 +644,7 @@ public Criteria in(String propertyName, QueryableCriteria subquery) { @Override public Criteria inList(String propertyName, QueryableCriteria subquery) { - hibernateQuery.inList(propertyName,subquery); + hibernateQuery.in(propertyName,subquery); return this; } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 70671b29949..f24d1ae8365 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -31,6 +31,7 @@ import org.grails.datastore.mapping.query.AssociationQuery; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.Restrictions; +import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.orm.hibernate.IHibernateTemplate; import org.hibernate.SessionFactory; @@ -162,7 +163,11 @@ public void add(Criterion criterion) { } else if (criterion instanceof ILike c) { ilike(c.getProperty(), c.getValue().toString()); } else if (criterion instanceof In c) { - in(c.getProperty(), c.getValues().stream().toList()); + if (Objects.nonNull(c.getSubquery())) { + in(c.getProperty(),c.getSubquery()); + } else { + in(c.getProperty(), c.getValues().stream().toList()); + } } else if (criterion instanceof IsEmpty c) { isEmpty(c.getProperty()); } else if (criterion instanceof IsNotEmpty c) { @@ -182,18 +187,6 @@ public void add(Criterion criterion) { } } - - - @Override - public Junction disjunction() { - return null; - } - - @Override - public Junction negation() { - return null; - } - @Override public Query eq(String property, Object value) { detachedCriteria.eq(property, value); @@ -232,7 +225,7 @@ public void doCall() { owner.add(Restrictions.or(a,b)); } }; - detachedCriteria.and(orClosure); + detachedCriteria.or(orClosure); return this; } @@ -550,7 +543,8 @@ private List collectProjections() { private void assignCriteria(CriteriaQuery cq, HibernateCriteriaBuilder cb, From root, Map tablesByName) { List criteriaList = (List)detachedCriteria.getCriteria(); if (!criteriaList.isEmpty()) { - cq.where(cb.and(PredicateGenerator.getPredicates(cb, cq, root, criteriaList,tablesByName))); + jakarta.persistence.criteria.Predicate[] predicates = PredicateGenerator.getPredicates(cb, cq, root, criteriaList, tablesByName); + cq.where(cb.and(predicates)); } } @@ -700,6 +694,11 @@ protected String generateAlias(String associationName) { return calculatePropertyName(associationName) + calculatePropertyName(ALIAS) + aliasCount++; } + public Query in(String propertyName, QueryableCriteria subquery) { + detachedCriteria.inList(propertyName,subquery); + return this; + } + protected class HibernateAssociationQuery extends AssociationQuery { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index e9ca1d321fc..db62185e9e3 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -19,10 +19,8 @@ import grails.gorm.DetachedCriteria; import groovy.lang.Closure; -import jakarta.persistence.criteria.CriteriaQuery; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.Restrictions; -import org.grails.datastore.mapping.query.api.Criteria; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.orm.hibernate.AbstractHibernateSession; @@ -32,9 +30,6 @@ import org.hibernate.SessionFactory; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.persister.entity.PropertyMapping; -import org.hibernate.query.criteria.JpaCriteriaQuery; - -import java.util.List; /** * Bridges the Query API with the Hibernate Criteria API @@ -61,11 +56,6 @@ public DetachedCriteria getHibernateCriteria() { return detachedCriteria; } - public Query inList(String propertyName, QueryableCriteria subquery) { - detachedCriteria.inList(propertyName,subquery); - return this; - } - public Query notIn(String propertyName, QueryableCriteria subquery) { detachedCriteria.notIn(propertyName,subquery); return this; diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy index a24f7128394..1e2818e2887 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy @@ -4,15 +4,17 @@ import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity import grails.gorm.hibernate.HibernateEntity import grails.gorm.tests.GormDatastoreSpec +import spock.lang.Ignore @SuppressWarnings("GrMethodMayBeStatic") -class DetachCriteriaSubquerySpec extends GormDatastoreSpec { +class DetachCriteriaSubquerySpec extends HibernateGormDatastoreSpec { @Override List getDomainClasses() { return [User, Group, GroupAssignment, Organisation] } + @Ignore("Exists Query broken") void "test detached associated criteria in subquery"() { setup: @@ -58,9 +60,9 @@ class DetachCriteriaSubquerySpec extends GormDatastoreSpec { orgB.save(flush: true) when: - DetachedCriteria criteria = User.where { - inList('organisation', Organisation.where { name == 'A' || name == 'B' }.id()) - } + def orgDetachedCritera = Organisation.where { name == 'A' || name == 'B' } + def organisations = orgDetachedCritera.list() + DetachedCriteria criteria = User.where {inList('organisation', orgDetachedCritera)} List result = criteria.list() result = criteria.list() diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy index 3d25b2ea5b0..b1724587753 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy @@ -6,7 +6,7 @@ import org.springframework.dao.DataIntegrityViolationException import spock.lang.Issue @Issue('https://github.com/grails/grails-data-mapping/issues/617') -class MultiColumnUniqueConstraintSpec extends GormDatastoreSpec { +class MultiColumnUniqueConstraintSpec extends HibernateGormDatastoreSpec { void "test generated unique constraints"() { expect: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SequenceIdSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SequenceIdSpec.groovy index 384e4689c42..d1d7181c823 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SequenceIdSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SequenceIdSpec.groovy @@ -27,9 +27,12 @@ class SequenceIdSpec extends Specification { then:"The entity was saved" BookWithSequence.first() - ((SessionImplementor)datastore.sessionFactory.currentSession).connection().prepareStatement("call NEXT VALUE FOR book_seq;") - .executeQuery() - .next() + SessionImplementor sessionImplementor = (SessionImplementor) datastore.sessionFactory.currentSession + sessionImplementor.doWork {connection -> + connection.prepareStatement("call NEXT VALUE FOR book_seq;") + .executeQuery().next() + } + } } @Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/AutoImportSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/AutoImportSpec.groovy index d3e9dc39670..90508fd4e1c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/AutoImportSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/autoimport/AutoImportSpec.groovy @@ -14,7 +14,7 @@ class AutoImportSpec extends GormSpec { } @Override List getDomainClasses() { - [A, grails.gorm.tests.autoimport.other.A] + [A, grails.gorm.specs.autoimport.other.A] } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index 98e37000331..2226726cd09 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -305,7 +305,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def oldPet = new Pet(name: "Lucky") oldBob.addToPets(oldPet) oldBob.save(flush: true) - petHibernateQuery.inList("owner", + petHibernateQuery.in("owner", new DetachedCriteria(Person).eq("lastName", "Builder") ) when: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassImportedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassImportedSpec.groovy index 886150d1715..d5578a49019 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassImportedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/inheritance/TablePerConcreteClassImportedSpec.groovy @@ -7,8 +7,9 @@ import spock.lang.Issue class TablePerConcreteClassImportedSpec extends GormSpec { void "test that subclasses are added to the imports on the metamodel"() { expect: - sessionFactory.getMetamodel().getImportedClassName('Vehicle') - sessionFactory.getMetamodel().getImportedClassName('Spaceship') + sessionFactory.getMetamodel().entities + .collect {it.javaType} + .containsAll( [Vehicle, Spaceship]) } @Override diff --git a/grails-datastore-gorm-hibernate/src/test/resources/simplelogger.properties b/grails-datastore-gorm-hibernate/src/test/resources/simplelogger.properties index b87aa2c7097..b6c41c0567b 100644 --- a/grails-datastore-gorm-hibernate/src/test/resources/simplelogger.properties +++ b/grails-datastore-gorm-hibernate/src/test/resources/simplelogger.properties @@ -1,3 +1,3 @@ -#org.slf4j.simpleLogger.defaultLogLevel=debug +#org.slf4j.simpleLogger.defaultLogLevel=trace #org.slf4j.simpleLogger.log.org.hibernate=trace -#org.slf4j.simpleLogger.log.org.hibernate.SQL=debug \ No newline at end of file +org.slf4j.simpleLogger.log.org.hibernate.SQL=debug \ No newline at end of file From 8ee679125e5aef553a1ab8348674c18a761c692c Mon Sep 17 00:00:00 2001 From: Mattias Reichel Date: Sat, 8 Mar 2025 12:21:21 +0100 Subject: [PATCH 0027/1008] ci: adjust for new repository url (#994) --- .github/workflows/docs.yml | 2 +- .github/workflows/gradle.yml | 2 +- .github/workflows/groovy-joint-workflow.yml | 3 ++- .github/workflows/release.yml | 2 +- settings.gradle | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ac0a0c44396..76633bf1671 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -36,7 +36,7 @@ jobs: run: ./gradlew docs:docs - name: "👀 Determine docs target repository" run: | - if [ "${{ github.repository }}" = "grails/gorm-hibernate5" ]; then + if [ "${{ github.repository }}" = "grails/grails-data-hibernate5" ]; then DOCS_TARGET_REPOSITORY="grails/grails-data-mapping" else DOCS_TARGET_REPOSITORY="${{ github.repository }}" diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 85a5cb20db6..8a4234881e9 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -63,7 +63,7 @@ jobs: run: ./gradlew docs:docs - name: "👀 Determine docs target repository" run: | - if [ "${{ github.repository }}" = "grails/gorm-hibernate5" ]; then + if [ "${{ github.repository }}" = "grails/grails-data-hibernate5" ]; then DOCS_TARGET_REPOSITORY="grails/grails-data-mapping" else DOCS_TARGET_REPOSITORY="${{ github.repository }}" diff --git a/.github/workflows/groovy-joint-workflow.yml b/.github/workflows/groovy-joint-workflow.yml index 29c7ee8cc91..b738b60faf9 100644 --- a/.github/workflows/groovy-joint-workflow.yml +++ b/.github/workflows/groovy-joint-workflow.yml @@ -74,7 +74,8 @@ jobs: echo " server = 'https://ge.grails.org'" >> $GITHUB_OUTPUT echo " buildScan {" >> $GITHUB_OUTPUT echo " tag('groovy')" >> $GITHUB_OUTPUT - echo " tag('gorm-hibernate5')" >> $GITHUB_OUTPUT + echo " tag('grails-data-hibernate5')" >> $GITHUB_OUTPUT + echo " tag('grails-database-migration')" >> $GITHUB_OUTPUT echo " publishing.onlyIf { isAuthenticated }" >> $GITHUB_OUTPUT echo " uploadInBackground = false" >> $GITHUB_OUTPUT echo " }" >> $GITHUB_OUTPUT diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6fe470b6d8c..fd06a856600 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -134,7 +134,7 @@ jobs: uses: grails/github-actions/export-gradle-properties@v3 - name: "👀 Determine docs target repository" run: | - if [ "${{ github.repository }}" = "grails/gorm-hibernate5" ]; then + if [ "${{ github.repository }}" = "grails/grails-data-hibernate5" ]; then DOCS_TARGET_REPOSITORY="grails/grails-data-mapping" else DOCS_TARGET_REPOSITORY="${{ github.repository }}" diff --git a/settings.gradle b/settings.gradle index af35c8b959c..53225d67c52 100644 --- a/settings.gradle +++ b/settings.gradle @@ -11,7 +11,7 @@ develocity { server = 'https://ge.grails.org' buildScan { tag('grails') - tag('gorm-hibernate5') + tag('grails-data-hibernate5') tag('grails-database-migration') publishing.onlyIf { isAuthenticated } uploadInBackground = isLocal From 74d57c868408b69554d07bde83f0df59fa8bc6f5 Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Mon, 17 Mar 2025 15:39:43 -0400 Subject: [PATCH 0028/1008] feedback: hibernate 5 -> hibernate 6 references --- build.gradle | 2 +- docs/build.gradle | 2 +- examples/spring-boot-hibernate/build.gradle | 2 +- gradle/publish-config.gradle | 6 +++--- gradle/tck-config.gradle | 2 +- gradle/test-config.gradle | 2 +- grails-database-migration/build.gradle | 4 ++-- .../grails/plugin/hibernate/HibernateGrailsPlugin.groovy | 4 ++-- 8 files changed, 12 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 4789eac6d50..496ee22240f 100644 --- a/build.gradle +++ b/build.gradle @@ -70,7 +70,7 @@ group = 'this.will.be.overridden' def publishedProjects = [ 'database-migration', - 'gorm-hibernate5-spring-boot', + 'gorm-hibernate6-spring-boot', 'grails-datastore-gorm-hibernate6', 'grails-plugin', ] diff --git a/docs/build.gradle b/docs/build.gradle index f05c4c2abfc..7baa7c074fc 100644 --- a/docs/build.gradle +++ b/docs/build.gradle @@ -112,7 +112,7 @@ tasks.register('cleanAsciidoc', Delete) { tasks.withType(Groovydoc).configureEach { dependsOn('fetchGormSource') - docTitle = "GORM for Hibernate 5 - $project.version" + docTitle = "GORM for Hibernate 6 - $project.version" def sourceFiles = coreProjects.collect { layout.buildDirectory.files("$checkoutDirName/gorm-src/$it/src/main/groovy") diff --git a/examples/spring-boot-hibernate/build.gradle b/examples/spring-boot-hibernate/build.gradle index 885760e5b6d..5b9fb57f160 100644 --- a/examples/spring-boot-hibernate/build.gradle +++ b/examples/spring-boot-hibernate/build.gradle @@ -10,7 +10,7 @@ dependencies { implementation platform("org.grails:grails-bom:$grailsVersion") - implementation project(':gorm-hibernate5-spring-boot') + implementation project(':gorm-hibernate6-spring-boot') implementation 'org.springframework.boot:spring-boot-starter-web' runtimeOnly 'com.h2database:h2' diff --git a/gradle/publish-config.gradle b/gradle/publish-config.gradle index 30af5f294ec..a09b873f431 100644 --- a/gradle/publish-config.gradle +++ b/gradle/publish-config.gradle @@ -7,10 +7,10 @@ if (project.hasProperty('snapshotPublishUrl')) { extensions.configure(GrailsPublishExtension) { // Explicit `it` is required here - it.githubSlug = 'grails/gorm-hibernate5' + it.githubSlug = 'grails/gorm-hibernate6' it.license.name = 'Apache-2.0' - it.title = findProperty('pomTitle') ?: 'GORM for Hibernate 5' - it.desc = findProperty('pomDescription') ?: 'Provides a GORM Object Mapping implementations for Hibernate 5' + it.title = findProperty('pomTitle') ?: 'GORM for Hibernate 6' + it.desc = findProperty('pomDescription') ?: 'Provides a GORM Object Mapping implementations for Hibernate 6' it.developers = findProperty('pomDevelopers') as Map ?: [ 'graemerocher': 'Graeme Rocher', 'jeffscottbrown': 'Jeff Brown', diff --git a/gradle/tck-config.gradle b/gradle/tck-config.gradle index bfca804d9f6..625673a425c 100644 --- a/gradle/tck-config.gradle +++ b/gradle/tck-config.gradle @@ -17,7 +17,7 @@ tasks.withType(Test).configureEach { System.out.flush() } // Used in the TCK test suite to selectively enable/disable tests - systemProperty('hibernate5.gorm.suite', 'true') + systemProperty('hibernate6.gorm.suite', 'true') doFirst { def toBaseClassRelativePathWithoutExtension = { String base, String classFile -> diff --git a/gradle/test-config.gradle b/gradle/test-config.gradle index 2786f667534..297a1d90321 100644 --- a/gradle/test-config.gradle +++ b/gradle/test-config.gradle @@ -9,7 +9,7 @@ tasks.withType(Test).configureEach { } useJUnitPlatform() - systemProperty('hibernate5.gorm.suite', System.getProperty('hibernate5.gorm.suite') ?: true) + systemProperty('hibernate6.gorm.suite', System.getProperty('hibernate6.gorm.suite') ?: true) reports.html.required = !System.getenv('CI') reports.junitXml.required = !System.getenv('CI') testLogging { diff --git a/grails-database-migration/build.gradle b/grails-database-migration/build.gradle index ac74677d4f8..090d977942c 100644 --- a/grails-database-migration/build.gradle +++ b/grails-database-migration/build.gradle @@ -36,13 +36,13 @@ dependencies { compileOnly "org.springframework.boot:spring-boot-starter-logging" compileOnly "org.springframework.boot:spring-boot-autoconfigure" - compileOnly "org.grails.plugins:hibernate5" + compileOnly project(':grails-plugin') compileOnly "org.grails:grails-core" compileOnly "org.apache.groovy:groovy-sql" compileOnly "org.apache.groovy:groovy-xml" testImplementation "org.springframework.boot:spring-boot-starter-tomcat" - testImplementation "org.grails.plugins:hibernate5" + testImplementation project(':grails-plugin') testImplementation "org.grails:grails-core" testImplementation "org.grails:grails-gorm-testing-support" testImplementation "org.grails:grails-web-testing-support" diff --git a/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy b/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy index 3d6eb1c372d..72ba59e9981 100644 --- a/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy +++ b/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy @@ -29,8 +29,8 @@ class HibernateGrailsPlugin extends Plugin { def grailsVersion = '7.0.0 > *' def author = 'Grails Core Team' - def title = 'Hibernate 5 for Grails' - def description = 'Provides integration between Grails and Hibernate 5 through GORM' + def title = 'Hibernate 6 for Grails' + def description = 'Provides integration between Grails and Hibernate 6 through GORM' def documentation = 'https://grails.github.io/grails-data-mapping/latest/' def observe = ['domainClass'] From b048d0bf5f41f1e365f96aaf80e50217fd0ffd33 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 19 Feb 2025 19:51:06 -0600 Subject: [PATCH 0029/1008] more work --- .../HibernateMappingContextConfiguration.java | 2 +- .../hibernate/query/PredicateGenerator.java | 40 +++++-------- ...ositeIdWithManyToOneAndSequenceSpec.groovy | 25 ++++++-- .../specs/DetachCriteriaSubquerySpec.groovy | 1 + ...DetachedCriteriaProjectionAliasSpec.groovy | 24 ++++++++ .../grails/gorm/specs/EnumMappingSpec.groovy | 6 +- .../gorm/specs/IdentityEnumTypeSpec.groovy | 13 ++-- .../groovy/grails/gorm/specs/RLikeSpec.groovy | 2 + ...ositeIdWithDeepOneToManyMappingSpec.groovy | 40 +++++++++---- ...GlobalConstraintWithCompositeIdSpec.groovy | 59 +++++++++++++------ .../validation/BeanValidationSpec.groovy | 10 +++- .../validation/UniqueWithHasOneSpec.groovy | 8 ++- .../validation/UniqueWithinGroupSpec.groovy | 11 ++-- 13 files changed, 165 insertions(+), 76 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java index 560e6aba9db..070a0b0b0a6 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContextConfiguration.java @@ -290,7 +290,7 @@ public void sessionFactoryClosed(SessionFactory factory) { StandardServiceRegistry serviceRegistry = standardServiceRegistryBuilder.build(); try { sessionFactory = super.buildSessionFactory(serviceRegistry); - } catch (HibernateException e) { + } catch (Throwable e) { throw new RuntimeException(e); } this.serviceRegistry = serviceRegistry; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 1e9867561f6..785f90f936b 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -1,18 +1,12 @@ package org.grails.orm.hibernate.query; import groovy.util.logging.Slf4j; -import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.From; -import jakarta.persistence.criteria.Path; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; -import jakarta.persistence.metamodel.EntityType; -import jakarta.persistence.metamodel.PluralAttribute; -import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.query.Query; -import org.hibernate.Session; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaInPredicate; import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate; @@ -29,8 +23,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; -import java.util.Set; + import static org.grails.orm.hibernate.query.AbstractHibernateQuery.getFullyQualifiedPath; @@ -46,7 +39,7 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, List list = criteriaList.stream(). map(criterion -> { - if (criterion instanceof Query.Disjunction) { + if (criterion instanceof Query.Disjunction) { List criterionList = ((Query.Disjunction) criterion).getCriteria(); return cb.or(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); } else if (criterion instanceof Query.Conjunction) { @@ -141,8 +134,11 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); List subCriteria = c.getSubquery().getCriteria(); - Predicate[] predicates = getSubPredicates(cb, criteriaQuery, tablesByName, from, subCriteria); - subquery.select(from.get(projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); + Map newMap = new HashMap<>(); + newMap.putAll(tablesByName); + newMap.put("root", from); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); + subquery.select(getFullyQualifiedPath(newMap,projection.getPropertyName())).distinct(distinct).where(cb.and(predicates)); return in.value(subquery); } else if (criterion instanceof Query.In c && Objects.nonNull(c.getSubquery()) @@ -153,7 +149,10 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, Subquery subquery = criteriaQuery.subquery(getJavaTypeOfInClause((SqmInListPredicate) in)); Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); List subCriteria = c.getSubquery().getCriteria(); - Predicate[] predicates = getSubPredicates(cb, criteriaQuery, tablesByName, from, subCriteria); + Map newMap = new HashMap<>(); + newMap.putAll(tablesByName); + newMap.put("root", from); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); subquery.select(from).where(cb.and(predicates)); return in.value(subquery); } else if (criterion instanceof Query.In c && !c.getValues().isEmpty() @@ -175,7 +174,10 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, Subquery subquery = criteriaQuery.subquery(Number.class); Root from = subquery.from(c.getValue().getPersistentEntity().getJavaClass()); List subCriteria = c.getValue().getCriteria(); - Predicate[] predicates = getSubPredicates(cb, criteriaQuery, tablesByName, from, subCriteria); + Map newMap = new HashMap<>(); + newMap.putAll(tablesByName); + newMap.put("root", from); + Predicate[] predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); if (c instanceof Query.GreaterThanEqualsAll sc) { subquery.select(cb.max(from.get(c.getProperty()))).where(cb.and(predicates)); return cb.greaterThanOrEqualTo(getFullyQualifiedPath(tablesByName, sc.getProperty()), subquery); @@ -229,18 +231,6 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, return list.toArray(new Predicate[0]); } - private static Predicate[] getSubPredicates(HibernateCriteriaBuilder cb, CriteriaQuery criteriaQuery, Map tablesByName, Root from, List subCriteria) { - Predicate[] predicates; - if (tablesByName.size() == 1 && tablesByName.containsKey("root")) { - Map newMap = new HashMap<>(); - newMap.put("root", from); - predicates = getPredicates(cb, criteriaQuery, from, subCriteria, newMap); - } else { - predicates = getPredicates(cb, criteriaQuery, from, subCriteria, tablesByName); - } - return predicates; - } - private static Class getJavaTypeOfInClause(SqmInListPredicate in) { Class javaTypeOfInClause = in.getTestExpression().getExpressible().getExpressibleJavaType().getJavaTypeClass(); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy index 79d9107e48d..79c4ea1f600 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy @@ -3,8 +3,10 @@ package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore +import org.jetbrains.annotations.NotNull import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup +import spock.lang.Ignore import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification @@ -12,10 +14,13 @@ import spock.lang.Specification /** * Created by graemerocher on 26/01/2017. */ -class CompositeIdWithManyToOneAndSequenceSpec extends Specification { +class CompositeIdWithManyToOneAndSequenceSpec extends HibernateGormDatastoreSpec { + + List getDomainClasses() { + [Tooth, ToothDisease] + } + - @AutoCleanup @Shared HibernateDatastore datastore = new HibernateDatastore(Tooth, ToothDisease) - @Shared PlatformTransactionManager transactionManager = datastore.transactionManager @Rollback @Issue('https://github.com/grails/grails-data-mapping/issues/835') @@ -23,7 +28,10 @@ class CompositeIdWithManyToOneAndSequenceSpec extends Specification { when:"a many to one association is created" ToothDisease td = new ToothDisease(nrVersion: 1).save() - new Tooth(toothDisease: td).save(flush:true) + + def tooth = new Tooth() + tooth.toothDisease << td + tooth.save(flush:true) then:"The object was saved" Tooth.count() == 1 @@ -36,7 +44,7 @@ class CompositeIdWithManyToOneAndSequenceSpec extends Specification { @Entity class Tooth { Integer id - ToothDisease toothDisease + TreeSet toothDisease = new TreeSet<>() static mapping = { table name: 'AK_TOOTH' id generator: 'sequence', params: [sequence: 'SEQ_AK_TOOTH'] @@ -48,7 +56,7 @@ class Tooth { } @Entity -class ToothDisease implements Serializable { +class ToothDisease implements Serializable,Comparable { Integer idColumn Integer nrVersion static mapping = { @@ -57,4 +65,9 @@ class ToothDisease implements Serializable { nrVersion column: 'NR_VERSION' id composite: ['idColumn', 'nrVersion'] } + + @Override + int compareTo(@NotNull ToothDisease o) { + return idColumn <=> ((ToothDisease)o).idColumn + } } \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy index 1e2818e2887..2895f6bad56 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy @@ -70,6 +70,7 @@ class DetachCriteriaSubquerySpec extends HibernateGormDatastoreSpec { result.size() == 5 } + @Ignore("Explore is currently broken") void "test that detached criteria subquery should create implicit alias instead of using this_"() { setup: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy index 02e4d1f34c4..a578ad47376 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy @@ -4,6 +4,7 @@ import grails.gorm.DetachedCriteria import grails.gorm.transactions.Rollback import grails.gorm.transactions.Transactional import org.grails.orm.hibernate.HibernateDatastore +import org.hibernate.SessionFactory import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup import spock.lang.Issue @@ -16,6 +17,8 @@ class DetachedCriteriaProjectionAliasSpec extends HibernateGormDatastoreSpec { def entity1 def entity2 + + @Transactional def setup() { entity1 = new Entity1(field1: 'E1').save(flush:true) @@ -64,6 +67,27 @@ class DetachedCriteriaProjectionAliasSpec extends HibernateGormDatastoreSpec { def res = DetachedEntity.withCriteria { "in"("entityId", detachedCriteria) } + + SessionFactory sessionFactory = this.setupClass.sessionFactory + def hql = """ +select + de1_0.id, + de1_0.entity_id, + de1_0.field, + de1_0.version + from + detached_entity de1_0, + entity2 e1_0 + where + de1_0.entity_id in ((select + p2_0.id + from + entity2 e2_0, entity1 p2_0 + where + p2_0.id=e1_0.parent_id and de1_0.field='E2')) +""" + def list = sessionFactory.currentSession.createNativeQuery(hql,Object[].class).list() + println(list) then: res.entityId.first() == entity2.id } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy index 535683e6ec6..53e1c317642 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy @@ -2,6 +2,7 @@ package grails.gorm.specs import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec +import org.hibernate.engine.spi.SessionImplementor import java.sql.ResultSet @@ -13,7 +14,10 @@ class EnumMappingSpec extends GormSpec { void "Test enum mapping"() { when:"An enum property is persisted" new Recipe(title: "Chicken Tikka Masala").save(flush:true) - def resultSet = sessionFactory.currentSession.connection().prepareStatement("select * from recipe").executeQuery() + SessionImplementor sessionImplementor = (SessionImplementor) sessionFactory.currentSession + def resultSet = sessionImplementor.doReturningWork { + return it.prepareStatement("select * from recipe").executeQuery() + } resultSet.next() then:"The enum is mapped as a varchar" diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy index d071496b08b..e409478601d 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy @@ -5,6 +5,7 @@ import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup +import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification @@ -14,16 +15,20 @@ import java.sql.ResultSet /** * Created by graemerocher on 16/11/16. */ -class IdentityEnumTypeSpec extends Specification { +@Ignore("Not able to map Enum to SQL Type") +class IdentityEnumTypeSpec extends HibernateGormDatastoreSpec { + + @Override + List getDomainClasses() { + [EnumEntityDomain, FooWithEnum] + } - @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(EnumEntityDomain, FooWithEnum) - @Shared PlatformTransactionManager transactionManager = hibernateDatastore.getTransactionManager() @Rollback void "test identity enum type"() { when: new EnumEntityDomain(status: EnumEntityDomain.Status.FOO).save(flush:true) - DataSource ds = hibernateDatastore.connectionSources.defaultConnectionSource.dataSource + DataSource ds = setupClass.hibernateDatastore.connectionSources.defaultConnectionSource.dataSource ResultSet resultSet = ds.getConnection().prepareStatement('select status from enum_entity_domain').executeQuery() then: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy index 5ae659ec3b0..915b5592236 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy @@ -2,9 +2,11 @@ package grails.gorm.specs import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec +import spock.lang.Ignore class RLikeSpec extends GormSpec { + @Ignore("RLIKE NOT IMPLEMENTED") void "test rlike works with H2"() { given: new RlikeFoo(name: "ABC").save(flush: true) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy index e85a77db117..3bd0d4f6ce4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy @@ -2,10 +2,14 @@ package grails.gorm.specs.compositeid import grails.gorm.annotation.Entity import grails.gorm.hibernate.mapping.MappingBuilder +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore +import org.hibernate.SessionFactory +import org.jetbrains.annotations.NotNull import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup +import spock.lang.Ignore import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification @@ -13,10 +17,14 @@ import spock.lang.Specification /** * Created by graemerocher on 26/01/2017. */ -class CompositeIdWithDeepOneToManyMappingSpec extends Specification { +@Ignore("AUTO CREATE DDL NOT WORKING") +class CompositeIdWithDeepOneToManyMappingSpec extends HibernateGormDatastoreSpec { + + @Override + List getDomainClasses() { + [GrandParent, Parent, Child] + } - @AutoCleanup @Shared HibernateDatastore datastore = new HibernateDatastore(GrandParent, Parent, Child) - @Shared PlatformTransactionManager transactionManager = datastore.transactionManager @Rollback @Issue('https://github.com/grails/grails-data-mapping/issues/660') @@ -25,9 +33,10 @@ class CompositeIdWithDeepOneToManyMappingSpec extends Specification { def grandParent = new GrandParent(luckyNumber: 7, name: "Fred") def parent = new Parent(name: "Bob") grandParent.addToParents(parent) - parent.addToChildren(name:"Chuck") + parent.addToChildren(new Child(name:"Chuck")) grandParent.save(flush:true) + then: Parent.count == 1 GrandParent.count == 1 @@ -37,7 +46,7 @@ class CompositeIdWithDeepOneToManyMappingSpec extends Specification { } @Entity -class Child implements Serializable { +class Child implements Serializable, Comparable { String name static belongsTo= [parent: Parent] @@ -45,18 +54,28 @@ class Child implements Serializable { static mapping = MappingBuilder.define { composite('parent', 'name') } + + @Override + int compareTo(@NotNull Child o) { + return this.name <=> o.name + } } @Entity -class Parent implements Serializable { +class Parent implements Serializable, Comparable { String name - Collection children + TreeSet children static belongsTo= [grandParent: GrandParent] static hasMany= [children: Child] static mapping= MappingBuilder.define { - composite('grandParent', 'name') + composite('grandParent', 'name') cascade('all') + } + + @Override + int compareTo(@NotNull Parent o) { + return this.name <=> o.name } } @@ -64,11 +83,12 @@ class Parent implements Serializable { class GrandParent implements Serializable { String name Integer luckyNumber - Collection parents + TreeSet parents static hasMany= [parents: Parent] static mapping= MappingBuilder.define { - composite('name', 'luckyNumber') + composite('name', 'luckyNumber') cascade("all") + } } \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy index 514d1ddadd6..8897485a33c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy @@ -1,14 +1,18 @@ package grails.gorm.specs.compositeid import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import org.grails.datastore.mapping.core.DatastoreUtils +import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.model.PersistentEntity import org.grails.orm.hibernate.HibernateDatastore import org.grails.orm.hibernate.cfg.PropertyConfig import org.hibernate.dialect.H2Dialect +import org.jetbrains.annotations.NotNull import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup +import spock.lang.Ignore import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification @@ -16,28 +20,39 @@ import spock.lang.Specification /** * Created by graemerocher on 17/02/2017. */ -class GlobalConstraintWithCompositeIdSpec extends Specification { - - @Shared Map config = [ - 'dataSource.url':"jdbc:h2:mem:grailsDB;LOCK_TIMEOUT=10000", - 'dataSource.dbCreate': 'update', - 'dataSource.dialect': H2Dialect.name, - 'dataSource.formatSql': 'true', - 'hibernate.flush.mode': 'COMMIT', - 'grails.gorm.default.constraints':{ - '*'(nullable: true) - } - ] +class GlobalConstraintWithCompositeIdSpec extends HibernateGormDatastoreSpec { + + @Override + List getDomainClasses() { + [ParentB,ChildB,DomainB] + } + - @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(DatastoreUtils.createPropertyResolver(config),ParentB, ChildB, DomainB) - @Shared PlatformTransactionManager transactionManager = hibernateDatastore.transactionManager + Session configure() { + ConfigObject grailsConfig = new ConfigObject() + Map config = [ + 'dataSource.url':"jdbc:tc:postgresql:latest:///dev_db", + 'dataSource.dbCreate': 'create-drop', + 'dataSource.formatSql': 'true', + 'dataSource.logSql': 'true', + 'hibernate.flush.mode': 'COMMIT', + 'hibernate.cache.queries': 'true', + 'hibernate.hbm2ddl.auto': 'create', + 'hibernate.type.descriptor.sql': 'true', + 'grails.gorm.default.constraints':{ + '*'(nullable: true) + } + ] + grailsConfig.putAll(config) + setupClass.setup(((TEST_CLASSES + getDomainClasses()) as Set) as List, grailsConfig, true) + } @Rollback @Issue('https://github.com/grails/grails-core/issues/10457') void "test global constraints with composite id"() { when: ParentB parent = new ParentB(code:"AAA", desc: "BBB") - .addToChilds(name:"Child A") + .addToChildren(name:"Child A") .save(flush:true) then: @@ -45,11 +60,11 @@ class GlobalConstraintWithCompositeIdSpec extends Specification { ChildB.count == 1 } - @Rollback + @Ignore("DDL not working for composite id") @Issue('https://github.com/grails/grails-data-mapping/issues/877') void "test global constraints with unique constraint"() { given: - PersistentEntity entity = hibernateDatastore.mappingContext.getPersistentEntity(DomainB.name) + PersistentEntity entity = setupClass.hibernateDatastore.mappingContext.getPersistentEntity(DomainB.name) PropertyConfig nameProp = entity.getPropertyByName('name').mapping.mappedForm PropertyConfig someOtherConfig = entity.getPropertyByName('someOther').mapping.mappedForm expect: @@ -68,8 +83,9 @@ class ParentB implements Serializable { String code String desc + TreeSet children - static hasMany = [childs: ChildB] + static hasMany = [children: ChildB] static constraints = { } @@ -83,7 +99,7 @@ class ParentB implements Serializable { } @Entity -class ChildB implements Serializable { +class ChildB implements Serializable, Comparable { String name static belongsTo = [parent: ParentB] @@ -101,6 +117,11 @@ class ChildB implements Serializable { } } } + + @Override + int compareTo(@NotNull ChildB o) { + this.name <=> o.name + } } @Entity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy index ce61abf9e07..3f38d20bf72 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy @@ -1,6 +1,7 @@ package grails.gorm.specs.validation import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.validator.constraints.NotBlank @@ -13,9 +14,12 @@ import jakarta.validation.constraints.Digits /** * Created by graemerocher on 07/04/2017. */ -class BeanValidationSpec extends Specification { +class BeanValidationSpec extends HibernateGormDatastoreSpec { - @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(Bean) + @Override + List getDomainClasses() { + [Bean] + } @Rollback void "test bean validation API validate on save"() { @@ -37,5 +41,5 @@ class Bean { @NotBlank String name @Digits(integer = 6, fraction = 2) - Double price + BigDecimal price } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy index 5f241766047..75e1b7e7727 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy @@ -16,6 +16,7 @@ package grails.gorm.specs.validation import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.SessionFactory @@ -30,10 +31,11 @@ import spock.lang.Specification * @since 1.0 */ @Issue('https://github.com/grails/grails-data-mapping/issues/1004') -class UniqueWithHasOneSpec extends Specification { +class UniqueWithHasOneSpec extends HibernateGormDatastoreSpec { - @AutoCleanup @Shared HibernateDatastore hibernateDatastore = new HibernateDatastore(getClass().getPackage()) - @Shared SessionFactory sessionFactory = hibernateDatastore.sessionFactory + List getDomainClasses() { + [Foo,Bar] + } @Rollback void "test unique constraint with hasOne"() { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy index 263366e5640..d0f1c894e50 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy @@ -1,6 +1,7 @@ package grails.gorm.specs.validation import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.GormSpec import groovy.transform.EqualsAndHashCode @@ -17,17 +18,19 @@ import spock.lang.Specification * Created by graemerocher on 29/05/2017. */ @Issue('https://github.com/grails/gorm-hibernate5/issues/36') -class UniqueWithinGroupSpec extends Specification { +class UniqueWithinGroupSpec extends HibernateGormDatastoreSpec { - @AutoCleanup @Shared HibernateDatastore hibernateDatastore = new HibernateDatastore(getClass().getPackage()) - @Shared SessionFactory sessionFactory = hibernateDatastore.sessionFactory + @Override + List getDomainClasses() { + [Thing] + } @Rollback void "test insert"() { when: Thing thing1 = new Thing(hello: 1, world: 2) thing1.insert(flush: true) - sessionFactory.currentSession.flush() + Thing thing2 = new Thing(hello: 1, world: 2) thing2.insert(flush: true) From 6be6c3a4865bcac3ecffb2d7a8391aa5d07ff7f3 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sun, 23 Feb 2025 17:32:25 -0600 Subject: [PATCH 0030/1008] trying to fix edge cases --- .../orm/hibernate/query/AbstractHibernateQuery.java | 13 ++++++++++--- .../orm/hibernate/query/PredicateGenerator.java | 4 ++++ .../specs/TablePerSubClassAndEmbeddedSpec.groovy | 9 ++++++--- .../specs/WhereQueryWithAssociationSortSpec.groovy | 10 ++++++---- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index f24d1ae8365..3218b5e41e4 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -30,6 +30,7 @@ import org.grails.datastore.mapping.model.types.Association; import org.grails.datastore.mapping.query.AssociationQuery; import org.grails.datastore.mapping.query.Query; +import org.grails.datastore.mapping.query.QueryException; import org.grails.datastore.mapping.query.Restrictions; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.orm.hibernate.AbstractHibernateSession; @@ -48,6 +49,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; import java.util.function.Predicate; @@ -184,6 +186,9 @@ public void add(Criterion criterion) { le(c.getProperty(),c.getValue()); } else if (criterion instanceof LessThan c) { lt(c.getProperty(),c.getValue()); + } else { + //TODO It could be that this is the only call needed! + detachedCriteria.add(criterion); } } @@ -448,12 +453,14 @@ private static Predicate combinePredicates(Predicate... predicates) { protected org.hibernate.query.Query createQuery() { HibernateCriteriaBuilder cb = getCriteriaBuilder(); + + List detachedAssociationCriteria = getDetachedAssociationCriteria(); Map aliasMap = detachedAssociationCriteria.stream() .collect(Collectors.toMap( DetachedAssociationCriteria::getAssociationPath, - criteria ->criteria) + criteria ->criteria, (oldValue,newValue) -> newValue) ); @@ -469,7 +476,7 @@ protected org.hibernate.query.Query createQuery() { Map fromMap = detachedAssociationCriteria.stream() .collect(Collectors.toMap( DetachedAssociationCriteria::getAssociationPath, - criteria -> cq.from(criteria.getAssociation().getOwner().getJavaClass())) + criteria -> cq.from(criteria.getAssociation().getOwner().getJavaClass()) , (oldValue,newValue) -> newValue) ); fromMap.put("root", root); Map tablesByName = assignJoinTables(joinColumns, root,aliasMap, fromMap); @@ -627,7 +634,7 @@ private Map assignJoinTables(List joinColumns, From root, private static String aliasColumn(Map aliasMap, String associationPath, Join table) { String column = associationPath; if (aliasMap.containsKey(associationPath)) { - column = aliasMap.get(associationPath).getAlias(); + column = Optional.ofNullable(aliasMap.get(associationPath).getAlias()).orElseThrow(() -> new QueryException("Association without alias")); table.alias(column); } return column; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 785f90f936b..3e198bdd3a8 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -6,6 +6,7 @@ import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; +import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria; import org.grails.datastore.mapping.query.Query; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaInPredicate; @@ -45,6 +46,9 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, } else if (criterion instanceof Query.Conjunction) { List criterionList = ((Query.Conjunction) criterion).getCriteria(); return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); + } else if (criterion instanceof DetachedAssociationCriteria c) { + List criterionList = c.getCriteria(); + return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); } else if (criterion instanceof Query.Negation) { List criterionList = ((Query.Negation) criterion).getCriteria(); Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy index fab119d8544..a9b1687e063 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy @@ -16,10 +16,13 @@ import spock.lang.Specification * Created by graemerocher on 04/11/16. */ @ApplyDetachedCriteriaTransform -class TablePerSubClassAndEmbeddedSpec extends Specification { +class TablePerSubClassAndEmbeddedSpec extends HibernateGormDatastoreSpec { + + @Override + List getDomainClasses() { + [Company, Vendor] + } - @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(Company, Vendor) - @Shared PlatformTransactionManager transactionManager = hibernateDatastore.getTransactionManager() @Rollback void 'test table per subclass with embedded entity'() { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy index 7ca2e7b7a69..8d290cde63c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy @@ -1,13 +1,13 @@ package grails.gorm.specs import grails.gorm.tests.GormDatastoreSpec -import org.hibernate.QueryException +import org.grails.datastore.mapping.query.QueryException import spock.lang.Issue /** * Created by graemerocher on 03/11/16. */ -class WhereQueryWithAssociationSortSpec extends GormDatastoreSpec { +class WhereQueryWithAssociationSortSpec extends HibernateGormDatastoreSpec { @Issue('https://github.com/grails/grails-core/issues/9860') void "Test sort with where query that queries association"() { @@ -28,10 +28,12 @@ class WhereQueryWithAssociationSortSpec extends GormDatastoreSpec { when:"a where query uses a sort on an association" - results = Team.where { + + def where = Team.where { def c1 = club c1.name ==~ '%e%' - }.list(sort:'c1.name') + } + results = where.list(sort:'c1.name') then:"an exception is thrown because no alias is specified" From cf499cbd037df6ec4c27ea6ebc17780337128cb9 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sun, 16 Mar 2025 18:54:34 -0500 Subject: [PATCH 0031/1008] implemented tests for what is documented in criteria.adoc --- docs/src/docs/asciidoc/querying/criteria.adoc | 160 ++---------- .../AbstractHibernateCriteriaBuilder.java | 146 +++++------ .../query/AbstractHibernateQuery.java | 27 +- .../orm/hibernate/query/HibernateQuery.java | 11 + .../hibernate/query/PredicateGenerator.java | 3 + .../gorm/specs/SubqueryAliasSpec.groovy | 10 +- ...HibernateGormStaticApiSpecification.groovy | 231 ++++++++++++++++++ 7 files changed, 368 insertions(+), 220 deletions(-) create mode 100644 grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy diff --git a/docs/src/docs/asciidoc/querying/criteria.adoc b/docs/src/docs/asciidoc/querying/criteria.adoc index 0019625a36f..26633e85b2c 100644 --- a/docs/src/docs/asciidoc/querying/criteria.adoc +++ b/docs/src/docs/asciidoc/querying/criteria.adoc @@ -58,12 +58,15 @@ And you can also negate using logical NOT: [source,java] ---- not { - between("balance", 500, 1000) - eq("branch", "London") + and{ + between("balance", 500, 1000) + eq("branch", "London") + } + } ---- -All top level conditions are implied to be AND'd together. +In previous release all top level conditions weere implied to be AND'd together, but this is not supported anymore ==== Querying Associations @@ -183,135 +186,15 @@ def accountsOverview = c.get { Each alias must have a corresponding property or explicit setter on the bean otherwise an exception will be thrown. -==== SQL Projections +==== SQL Projections are not supported in Hibernate 6 -The criteria DSL provides access to Hibernate's SQL projection API. -[source,java] ----- -// Box is a domain class... -class Box { - int width - int height -} ----- +==== sqlRestriction have been removed from Hibernate 6 -[source,java] ----- -// Use SQL projections to retrieve the perimeter and area of all of the Box instances... -def c = Box.createCriteria() -def results = c.list { - projections { - sqlProjection '(2 * (width + height)) as perimeter, (width * height) as area', ['perimeter', 'area'], [INTEGER, INTEGER] - } -} ----- - -The first argument to the `sqlProjection` method is the SQL which defines the projections. The second argument is a list of -Strings which represent column aliases corresponding to the projected values expressed in the SQL. The third argument -is a list of `org.hibernate.type.Type` instances which correspond to the projected values expressed in the SQL. The API -supports all `org.hibernate.type.Type` objects but constants like INTEGER, LONG, FLOAT etc. are provided by the DSL which -correspond to all of the types defined in `org.hibernate.type.StandardBasicTypes`. -Consider that the following table represents the data in the -`BOX` table. -[format="csv", options="header"] -|=== -width,height -2,7 -2,8 -2,9 -4,9 -|=== - -The query above would return results like this: - -[source,groovy] ----- -[[18, 14], [20, 16], [22, 18], [26, 36]] ----- - -Each of the inner lists contains the 2 projected values for each `Box`, perimeter and area. - -NOTE: Note that if there are other references in scope wherever your criteria query is expressed that have names that conflict -with any of the type constants described above, the code in your criteria will refer to those references, not the type -constants provided by the DSL. In the unlikely event of that happening you can disambiguate the conflict by referring -to the fully qualified Hibernate type. For example `StandardBasicTypes.INTEGER` instead of `INTEGER`. - -If only 1 value is being projected, the alias and the type do not need to be included in a list. - -[source,java] ----- -def results = c.list { - projections { - sqlProjection 'sum(width * height) as totalArea', 'totalArea', INTEGER - } -} ----- - -That query would return a single result with the value of 84 as the total area of all of the `Box` instances. - -The DSL supports grouped projections with the `sqlGroupProjection` method. - -[source,java] ----- -def results = c.list { - projections { - sqlGroupProjection 'width, sum(height) as combinedHeightsForThisWidth', 'width', ['width', 'combinedHeightsForThisWidth'], [INTEGER, INTEGER] - } -} ----- - -The first argument to the `sqlGroupProjection` method is the SQL which defines the projections. The second argument represents the -group by clause that should be part of the query. That string may be single column name or a comma separated list of column -names. The third argument is a list of -Strings which represent column aliases corresponding to the projected values expressed in the SQL. The fourth argument -is a list of `org.hibernate.type.Type` instances which correspond to the projected values expressed in the SQL. - -The query above is projecting the combined heights of boxes grouped by width and would return results that look like this: - -[source,groovy] ----- -[[2, 24], [4, 9]] ----- - -Each of the inner lists contains 2 values. The first value is a box width and the second value is the sum of the heights -of all of the boxes which have that width. - - -==== Using SQL Restrictions - - -You can access Hibernate's SQL Restrictions capabilities. - -[source,java] ----- -def c = Person.createCriteria() - -def peopleWithShortFirstNames = c.list { - sqlRestriction "char_length(first_name) <= 4" -} ----- - -SQL Restrictions may be parameterized to deal with SQL injection vulnerabilities related to dynamic restrictions. - - -[source,java] ----- -def c = Person.createCriteria() - -def peopleWithShortFirstNames = c.list { - sqlRestriction "char_length(first_name) < ? AND char_length(first_name) > ?", [maxValue, minValue] -} ----- - - -NOTE: Note that the parameter there is SQL. The `first_name` attribute referenced in the example refers to the persistence model, not the object model like in HQL queries. The `Person` property named `firstName` is mapped to the `first_name` column in the database and you must refer to that in the `sqlRestriction` string. - -Also note that the SQL used here is not necessarily portable across databases. ==== Using Scrollable Results @@ -324,13 +207,17 @@ You can use Hibernate's https://docs.jboss.org/hibernate/orm/5.6/javadocs/org/hi def results = crit.scroll { maxResults(10) } -def f = results.first() -def l = results.last() -def n = results.next() -def p = results.previous() +results.last() +m =results.get() +results.previous() +j = results.get() +results.first() +f = results.get() +results.next() +b = results.get() def future = results.scroll(10) -def accountNumber = results.getLong('number') +def g = results.get() ---- To quote the documentation of Hibernate ScrollableResults: @@ -342,21 +229,10 @@ ____ Contrary to JDBC, columns of results are numbered from zero. -==== Setting properties in the Criteria instance +==== The Criteria API is not part of Hibernate 6 -If a node within the builder tree doesn't match a particular criterion it will attempt to set a property on the Criteria object itself. This allows full access to all the properties in this class. This example calls `setMaxResults` and `setFirstResult` on the https://docs.jboss.org/hibernate/orm/5.6/javadocs/org/hibernate/Criteria.html[Criteria] instance: -[source,java] ----- -import org.hibernate.FetchMode as FM -... -def results = c.list { - maxResults(10) - firstResult(50) - fetchMode("aRelationship", FM.JOIN) -} ----- ==== Querying with Eager Fetching diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index 4c460cd4986..bdace0e0953 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -5,15 +5,19 @@ import groovy.lang.Closure; import groovy.lang.DelegatesTo; import groovy.lang.GroovyObjectSupport; +import groovy.lang.GroovySystem; import groovy.lang.MetaClass; import groovy.lang.MetaMethod; import groovy.lang.MissingMethodException; import groovy.util.logging.Slf4j; import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Join; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; import jakarta.persistence.metamodel.Attribute; +import jakarta.persistence.metamodel.EntityType; +import jakarta.persistence.metamodel.Metamodel; import org.grails.datastore.mapping.multitenancy.MultiTenancySettings; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.api.BuildableCriteria; @@ -29,9 +33,11 @@ import org.hibernate.transform.ResultTransformer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.BeanUtils; import org.springframework.core.convert.ConversionService; import org.grails.datastore.mapping.query.api.ProjectionList; +import java.beans.PropertyDescriptor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -226,6 +232,12 @@ public BuildableCriteria cache(boolean shouldCache) { return this; } + + public BuildableCriteria maxResults(int max) { + hibernateQuery.maxResults(max); + return this; + } + /** * Whether to check for changes on the objects loaded * @param readOnly True to disable dirty checking @@ -432,7 +444,7 @@ public void fetchMode(String associationPath, FetchMode fetchMode) { * @param transformer The result transformer to use. */ public void resultTransformer(ResultTransformer transformer) { - resultTransformer = transformer; + hibernateQuery.setResultTransformer(transformer); } @@ -857,26 +869,7 @@ public Criteria eq(String propertyName, Object propertyValue, Map params) { return this; } - /** - * Applies a sql restriction to the results to allow something like: - * - * @param sqlRestriction the sql restriction - * @return a Criteria instance - */ - public Criteria sqlRestriction(String sqlRestriction) { - return sqlRestriction(sqlRestriction, Collections.EMPTY_LIST); - } - /** - * Applies a sql restriction to the results to allow something like: - * - * @param sqlRestriction the sql restriction - * @param values jdbc parameters - * @return a Criteria instance - */ - public Criteria sqlRestriction(String sqlRestriction, List values) { - throw new RuntimeException("This feature is not supported in Hibernate 6"); - } /** * Creates a Criterion with from the specified property name and "like" expression @@ -963,6 +956,12 @@ public Criteria order(Query.Order o) { return this; } + public Criteria firstResult(int offset) { + hibernateQuery.firstResult(offset); + return this; + } + + @@ -1124,6 +1123,14 @@ public Object scroll(@DelegatesTo(Criteria.class) Closure c) { return invokeMethod(SCROLL_CALL, new Object[]{c}); } + public JoinType convertFromInt(Integer from) { + return switch (from) { + case 1 -> JoinType.LEFT; + case 2 -> JoinType.RIGHT; + default -> JoinType.INNER; + }; + } + @SuppressWarnings("rawtypes") @Override public Object invokeMethod(String name, Object obj) { @@ -1131,7 +1138,7 @@ public Object invokeMethod(String name, Object obj) { if (paginationEnabledList && SET_RESULT_TRANSFORMER_CALL.equals(name) && args.length == 1 && args[0] instanceof ResultTransformer) { - resultTransformer = (ResultTransformer) args[0]; + hibernateQuery.setResultTransformer((ResultTransformer) args[0]); return null; } @@ -1217,69 +1224,68 @@ else if (paginationEnabledList) { return metaMethod.invoke(this, args); } - metaMethod = criteriaMetaClass.getMetaMethod(name, args); + MetaClass metaClass = GroovySystem.getMetaClassRegistry().getMetaClass(targetClass); + metaMethod = metaClass.getMetaMethod(name, args); if (metaMethod != null) { return metaMethod.invoke(criteriaQuery, args); } - metaMethod = criteriaMetaClass.getMetaMethod(NameUtils.getSetterName(name), args); + metaMethod = metaClass.getMetaMethod(NameUtils.getSetterName(name), args); if (metaMethod != null) { return metaMethod.invoke(criteriaQuery, args); } if (isAssociationQueryMethod(args) || isAssociationQueryWithJoinSpecificationMethod(args)) { - if (1 == 1) { - throw new RuntimeException("This branch needs to be filled out"); - } +// if (1 == 1) { +// throw new RuntimeException("This branch needs to be filled out"); +// } final boolean hasMoreThanOneArg = args.length > 1; - Object callable = hasMoreThanOneArg ? args[1] : args[0]; -// int joinType = hasMoreThanOneArg ? (Integer)args[0] : org.hibernate.sql.JoinType.INNER_JOIN.getJoinTypeValue(); + Closure callable = hasMoreThanOneArg ? (Closure) args[1] : (Closure) args[0]; + JoinType joinType = hasMoreThanOneArg ? convertFromInt((Integer)args[0]) : convertFromInt(0); + + if (name.equals(AND)) { + hibernateQuery.and(callable); + + return name; + } + + if (name.equals(OR) ) { + hibernateQuery.or(callable); + + return name; + } + + if ( name.equals(NOT)) { + hibernateQuery.not(callable); + + return name; + } -// if (name.equals(AND) || name.equals(OR) || name.equals(NOT)) { -// if (criteria == null) { -// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); -// } -// -// logicalExpressionStack.add(new LogicalExpression(name)); -// invokeClosureNode(callable); -// -// LogicalExpression logicalExpression = logicalExpressionStack.remove(logicalExpressionStack.size()-1); -// addToCriteria(logicalExpression.toCriterion()); -// -// return name; -// } if (name.equals(PROJECTIONS) && args.length == 1 && (args[0] instanceof Closure)) { -// if (criteria == null) { -// throwRuntimeException(new IllegalArgumentException("call to [" + name + "] not supported here")); -// } - projectionList = new Query.ProjectionList(); invokeClosureNode(callable); -// if (projectionList != null && projectionList.getLength() > 0) { -// criteria.setProjection(projectionList); -// } - return name; } -// final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(targetClass, name); -// if (pd != null && pd.getReadMethod() != null) { -// final Metamodel metamodel = sessionFactory.getMetamodel(); -// final EntityType entityType = metamodel.entity(targetClass); -// final Attribute attribute = entityType.getAttribute(name); -// -// if (attribute.isAssociation()) { -// Class oldTargetClass = targetClass; -// targetClass = getClassForAssociationType(attribute); -// if (targetClass.equals(oldTargetClass) && !hasMoreThanOneArg) { -// joinType = org.hibernate.sql.JoinType.LEFT_OUTER_JOIN.getJoinTypeValue(); // default to left join if joining on the same table -// } -// associationStack.add(name); -// final String associationPath = getAssociationPath(); + final PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(targetClass, name); + if (pd != null && pd.getReadMethod() != null) { + final Metamodel metamodel = sessionFactory.getMetamodel(); + final EntityType entityType = metamodel.entity(targetClass); + final Attribute attribute = entityType.getAttribute(name); + + if (attribute.isAssociation()) { + Class oldTargetClass = targetClass; + targetClass = getClassForAssociationType(attribute); + if (targetClass.equals(oldTargetClass) && !hasMoreThanOneArg) { + joinType = JoinType.LEFT; // default to left join if joining on the same table + } + + final String associationPath = getAssociationPath(); + hibernateQuery.join(name,joinType); // createAliasIfNeccessary(name, associationPath,joinType); -// // the criteria within an association node are grouped with an implicit AND -// logicalExpressionStack.add(new LogicalExpression(AND)); + // the criteria within an association node are grouped with an implicit AND + hibernateQuery.in(name, new DetachedCriteria(targetClass).build(callable)); // invokeClosureNode(callable); // aliasStack.remove(aliasStack.size() - 1); // if (!aliasInstanceStack.isEmpty()) { @@ -1290,10 +1296,10 @@ else if (paginationEnabledList) { // addToCriteria(logicalExpression.toCriterion()); // } // associationStack.remove(associationStack.size()-1); -// targetClass = oldTargetClass; -// -// return name; -// } + targetClass = oldTargetClass; + + return name; + } // if (attribute.getPersistentAttributeType() == Attribute.PersistentAttributeType.EMBEDDED) { // associationStack.add(name); // logicalExpressionStack.add(new LogicalExpression(AND)); @@ -1308,7 +1314,7 @@ else if (paginationEnabledList) { // associationStack.remove(associationStack.size()-1); // return name; // } -// } + } } else if (args.length == 1 && args[0] != null) { // if (criteriaQuery == null) { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 3218b5e41e4..a65336b5527 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -14,6 +14,7 @@ */ package org.grails.orm.hibernate.query; +import grails.gorm.DetachedCriteria; import grails.gorm.DetachedCriteria; import groovy.lang.Closure; import groovy.util.logging.Slf4j; @@ -36,8 +37,10 @@ import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.orm.hibernate.IHibernateTemplate; import org.hibernate.SessionFactory; +import org.hibernate.query.ResultListTransformer; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaExpression; +import org.hibernate.transform.ResultTransformer; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -82,6 +85,7 @@ public abstract class AbstractHibernateQuery extends Query { protected LinkedList aliasInstanceStack = new LinkedList(); private boolean hasJoins = false; protected DetachedCriteria detachedCriteria; + protected ResultTransformer resultTransformer; protected AbstractHibernateQuery(AbstractHibernateSession session, PersistentEntity entity) { super(session, entity); @@ -92,6 +96,10 @@ public void setDetachedCriteria(DetachedCriteria detachedCriteria) { this.detachedCriteria = detachedCriteria; } + public void setResultTransformer(ResultTransformer resultTransformer) { + this.resultTransformer = resultTransformer; + } + @Override protected Object resolveIdIfEntity(Object value) { @@ -424,6 +432,7 @@ public Object singleResult() { } private final Predicate idProjectionPredicate = projection -> projection instanceof IdProjection; + private final Predicate distinctProjectionPredicate = projection -> projection instanceof DistinctProjection; private final Predicate countProjectionPredicate = projection -> projection instanceof CountProjection; private final Predicate countDistinctProjection = projection -> projection instanceof CountDistinctProjection; private final Predicate maxProjectionPredicate = projection -> projection instanceof MaxProjection; @@ -442,6 +451,7 @@ public Object singleResult() { , minProjectionPredicate , sumProjectionPredicate , avgProjectionPredicate + , distinctProjectionPredicate } ; @SafeVarargs @@ -472,6 +482,12 @@ protected org.hibernate.query.Query createQuery() { CriteriaQuery cq = projections.size() > 1 ? cb.createQuery(Object[].class) : cb.createQuery(Object.class); + projections.stream() + .filter( DistinctProjection.class::isInstance ) + .findFirst() + .ifPresent(projection -> { + cq.distinct(true); + }); From root = cq.from(entity.getJavaClass()); Map fromMap = detachedAssociationCriteria.stream() .collect(Collectors.toMap( @@ -496,6 +512,9 @@ protected org.hibernate.query.Query createQuery() { if (Objects.nonNull(lockResult)) { query.setLockMode(lockResult); } + if (Objects.nonNull(resultTransformer)) { + query.setResultTransformer(resultTransformer); + } return query; } @@ -543,7 +562,8 @@ private List collectGroupProjections() { private List collectProjections() { List projections = projections().getProjectionList() .stream() - .filter(combinePredicates(projectionPredicates)).toList(); + .filter(combinePredicates(projectionPredicates)) + .toList(); return projections; } @@ -647,9 +667,12 @@ private Function projectionToJpaExpression( if (countProjectionPredicate.test(projection)) { return cb.count(tablesByName.get("root")); } else if (countDistinctProjection.test(projection)) { - return cb.countDistinct(tablesByName.get("root")); + String propertyName = ((PropertyProjection) projection).getPropertyName(); + return cb.countDistinct(tablesByName.get("root").get(propertyName)); } else if (idProjectionPredicate.test(projection)) { return (JpaExpression) tablesByName.get("root").get("id"); + } else if (distinctProjectionPredicate.test(projection)) { + return null; } else { String propertyName = ((PropertyProjection) projection).getPropertyName(); Path path = getFullyQualifiedPath(tablesByName, propertyName); diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java index db62185e9e3..eed523ba0a5 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/HibernateQuery.java @@ -19,6 +19,7 @@ import grails.gorm.DetachedCriteria; import groovy.lang.Closure; +import org.grails.datastore.mapping.query.Projections; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.Restrictions; import org.grails.datastore.mapping.query.api.QueryableCriteria; @@ -214,11 +215,21 @@ public Query sizeNe(String propertyName, int size) { return this; } + public Query maxResults(int maxResults) { + this.max = maxResults; + return this; + } + public Object scroll() { return createQuery().scroll(); } + public Query distinct() { + projections.add(Projections.distinct()); + return this; + } + diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 3e198bdd3a8..920d4e27992 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -43,6 +43,9 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, if (criterion instanceof Query.Disjunction) { List criterionList = ((Query.Disjunction) criterion).getCriteria(); return cb.or(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); + } else if (criterion instanceof Query.DistinctProjection) { + // this returns always true + return cb.conjunction(); } else if (criterion instanceof Query.Conjunction) { List criterionList = ((Query.Conjunction) criterion).getCriteria(); return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy index d56ecb7e225..287c5290ff9 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy @@ -12,15 +12,13 @@ import spock.lang.Specification * Created by graemerocher on 01/03/2017. */ @ApplyDetachedCriteriaTransform -class SubqueryAliasSpec extends Specification { +class SubqueryAliasSpec extends HibernateGormDatastoreSpec { - @AutoCleanup @Shared HibernateDatastore datastore = new HibernateDatastore( - Club, Team - ) + List getDomainClasses() { + [Club,Team] + } - @Shared PlatformTransactionManager transactionManager = datastore.getTransactionManager() - @Rollback void "Test subquery with root alias"() { given: Club c = new Club(name: "Manchester United").save() diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy new file mode 100644 index 00000000000..13381786fe5 --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy @@ -0,0 +1,231 @@ +package org.grails.orm.hibernate + +import grails.gorm.specs.HibernateGormDatastoreSpec +import grails.persistence.Entity +import groovy.transform.EqualsAndHashCode +import org.hibernate.ScrollableResults +import org.hibernate.transform.ToListResultTransformer +import spock.lang.Ignore + + +class HibernateGormStaticApiTest extends HibernateGormDatastoreSpec{ + + List getDomainClasses() { + [Account, Transaction, Whatever ] + } + Account fredAccount + Account barneyAccount + Account jamesAccount + Account maryAccount + def accountCriteria + + def setup() { + fredAccount = new Account(balance: 250, firstName: "Fred", lastName: "Flintstone", branch: "Bedrock") + fredAccount.transactions << new Transaction(amount: 50, account: fredAccount) + fredAccount.save(flush:true) + barneyAccount = new Account(balance: 500, firstName: "Barney", lastName: "Rubble", branch: "Bedrock").save(flush: true) + jamesAccount = new Account(balance: 750, firstName: "James", lastName: "Bond", branch: "London").save(flush: true) + maryAccount = new Account(balance: 1000, firstName: "Mary", lastName: "Poppins", branch: "London").save(flush: true) + accountCriteria = Account.createCriteria() + } + + def "equalsCriteria"() { + when: + def results = accountCriteria { + eq("branch","London") + maxResults(1) + } + then: + results.size() == 1 + results[0] == jamesAccount + } + + def "between"() { + when: + def results = accountCriteria { + between("balance", 500, 1000) + order("balance", "asc") + } + then: + results.size() == 3 + results[0] == barneyAccount + results[1] == jamesAccount + results[2] == maryAccount + } + + def "or"() { + when: + def results = accountCriteria { + or { + like("firstName", "Fred%") + like("firstName", "Barney%") + + } + order("balance", "asc") + } + then: + results.size() == 2 + results[0] == fredAccount + results[1] == barneyAccount + } + + def "not"() { + when: + def results = accountCriteria { + not { + between("balance", 500, 1000) + eq("branch", "London") + + } + order("balance", "asc") + } + then: + results.size() == 1 + results[0] == fredAccount + } + + def transactions() { + when: + def results = accountCriteria.list { + between("balance", 0, 500) + transactions { + between("amount", 50, 100) + } + } + then: + results.size() == 1 + results[0] == fredAccount + } + + def projectionsList() { + when: + def results = accountCriteria.get { + projections { + countDistinct('branch') + countDistinct('balance') + } + } + then: + results.size() == 2 + results[0] == 2 + results[1] == 4 + } + + def projections() { + when: + def results = accountCriteria.get { + projections { + countDistinct('branch') + } + } + then: + results == 2 + } + + def scroll() { + when: + ScrollableResults results = accountCriteria.scroll { + order("balance", "asc") + } + then: + results.scroll(1) + fredAccount == results.get() + results.last() + maryAccount == results.get() + results.previous() + jamesAccount == results.get() + results.first() + fredAccount == results.get() + results.next() + barneyAccount == results.get() + } + + def "transformer"() { + when: + List results = accountCriteria.get { + resultTransformer(ToListResultTransformer.INSTANCE) + projections { + countDistinct('branch') + countDistinct('balance') + } + } + then: + results[0] == 2 + results[1] == 4 + } + + def eagerFetching() { + when: + def results = accountCriteria.list { + eq("branch", "Bedrock") + join("transactions") + } + then: + results.size() == 1 + results[0] == fredAccount + results[0].transactions.size() == 1 + results[0].transactions[0].amount == 50 + } + + def listDistinct() { + new Account(balance: 250, firstName: "Fred", lastName: "Flintstone", branch: "Bedrock").save(flush:true) + when: + def results = accountCriteria.listDistinct { + eq("balance", 250) + } + then: + results.size() == 1 + results[0] == fredAccount + } + + @Ignore("This is documented as working but fails") + def multipleCriteria() { + given: + def accountCriteria = { + eq "branch", "Bedrock" + } + when: + def results = Account.withCriteria { + accountCriteria.delegate = accountCriteria + accountCriteria() + transactions { + between("amount", 50, 100) + } + } + then: + results.size() == 1 + results[0] == fredAccount + results[0].transactions.size() == 1 + results[0].transactions[0].amount == 50 + + } + + + + +} + +@Entity +@EqualsAndHashCode +class Whatever { + Integer branch + Integer balance +} + +@Entity +class Transaction { + BigDecimal amount + static belongsTo = [account: Account] +} + +@Entity +@EqualsAndHashCode +class Account { + BigDecimal balance + String branch + String firstName + String lastName + Set transactions = new HashSet<>() + static hasMany = [transactions:Transaction] + +} \ No newline at end of file From 36562fdd969f60ac705630c0d6b7b4b1cc0f969f Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Mon, 17 Mar 2025 21:49:52 -0500 Subject: [PATCH 0032/1008] optimize imports --- .../mapping/HibernateMappingBuilderTests.groovy | 8 ++------ ...ibernateOptimisticLockingStyleMappingSpec.groovy | 2 -- .../hibernate/mapping/MappingBuilderSpec.groovy | 3 +-- .../src/test/groovy/grails/gorm/specs/Club.groovy | 2 +- .../gorm/specs/CompositeIdWithJoinTableSpec.groovy | 10 ++-------- .../CompositeIdWithManyToOneAndSequenceSpec.groovy | 6 ------ .../gorm/specs/DetachCriteriaSubquerySpec.groovy | 1 - .../gorm/specs/DetachedCriteriaJoinSpec.groovy | 6 +----- .../DetachedCriteriaProjectionAliasSpec.groovy | 6 ------ .../specs/DetachedCriteriaProjectionSpec.groovy | 5 ----- .../groovy/grails/gorm/specs/EnumMappingSpec.groovy | 2 -- .../groovy/grails/gorm/specs/GroovyProxySpec.groovy | 1 - .../specs/HibernateEntityTraitGeneratedSpec.groovy | 2 -- .../grails/gorm/specs/IdentityEnumTypeSpec.groovy | 5 ----- .../specs/MultiColumnUniqueConstraintSpec.groovy | 1 - .../grails/gorm/specs/NullValueEqualSpec.groovy | 2 -- .../groovy/grails/gorm/specs/SqlQuerySpec.groovy | 1 - .../grails/gorm/specs/SubqueryAliasSpec.groovy | 7 +------ .../specs/TablePerSubClassAndEmbeddedSpec.groovy | 6 ------ .../specs/UniqueWithMultipleDataSourcesSpec.groovy | 6 +----- .../groovy/grails/gorm/specs/ValidationSpec.groovy | 7 +------ .../specs/WhereQueryWithAssociationSortSpec.groovy | 2 +- .../WithNewSessionAndExistingTransactionSpec.groovy | 1 - .../CompositeIdWithDeepOneToManyMappingSpec.groovy | 6 ------ .../GlobalConstraintWithCompositeIdSpec.groovy | 7 ------- .../specs/dirtychecking/PropertyFieldSpec.groovy | 1 - .../events/UpdatePropertyInEventListenerSpec.groovy | 1 - .../specs/hasmany/HasManyWithInQuerySpec.groovy | 6 +----- .../gorm/specs/hasmany/ListCollectionSpec.groovy | 2 -- .../hasmany/TwoUnidirectionalHasManySpec.groovy | 9 ++------- .../gorm/specs/jpa/SimpleJpaEntitySpec.groovy | 13 ++++++------- .../gorm/specs/mappedby/MultipleOneToOneSpec.groovy | 1 - .../MultiTenancyBidirectionalManyToManySpec.groovy | 1 - .../MultiTenancyUnidirectionalOneToManySpec.groovy | 5 +---- .../grails/gorm/specs/perf/JoinPerfSpec.groovy | 3 +-- .../gorm/specs/proxy/ByteBuddyProxySpec.groovy | 6 ++---- .../grails/gorm/specs/proxy/StaticTestUtil.groovy | 6 +----- .../gorm/specs/softdelete/SoftDeleteSpec.groovy | 1 - .../gorm/specs/traits/TraitPropertySpec.groovy | 1 - .../txs/TransactionalWithinReadOnlySpec.groovy | 2 -- .../grails/gorm/specs/uuid/UuidInsertSpec.groovy | 1 - .../gorm/specs/validation/BeanValidationSpec.groovy | 7 +------ .../specs/validation/CascadeValidationSpec.groovy | 1 - .../validation/SaveWithInvalidEntitySpec.groovy | 6 +----- .../validation/UniqueFalseConstraintSpec.groovy | 2 +- .../specs/validation/UniqueInheritanceSpec.groovy | 1 - .../specs/validation/UniqueWithHasOneSpec.groovy | 6 ------ .../specs/validation/UniqueWithinGroupSpec.groovy | 7 ------- .../DataSourceConnectionSourceFactorySpec.groovy | 5 ++--- .../HibernateConnectionSourceFactorySpec.groovy | 2 -- .../HibernateConnectionSourceSettingsSpec.groovy | 2 -- .../MultipleDataSourceConnectionsSpec.groovy | 2 +- .../connections/PartitionedMultiTenancySpec.groovy | 2 +- .../connections/SchemaMultiTenantSpec.groovy | 6 ------ .../hibernate/connections/SingleTenantSpec.groovy | 4 +--- 55 files changed, 33 insertions(+), 184 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy index 3c5daf267c7..d733a14a406 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/HibernateMappingBuilderTests.groovy @@ -2,20 +2,16 @@ package grails.gorm.hibernate.mapping import org.grails.orm.hibernate.cfg.CompositeIdentity import org.grails.orm.hibernate.cfg.HibernateMappingBuilder +import org.grails.orm.hibernate.cfg.PropertyConfig /** * Created by graemerocher on 01/02/2017. */ -import org.grails.orm.hibernate.cfg.PropertyConfig import org.hibernate.FetchMode import org.junit.jupiter.api.Test -import static org.junit.jupiter.api.Assertions.assertEquals -import static org.junit.jupiter.api.Assertions.assertFalse -import static org.junit.jupiter.api.Assertions.assertNull -import static org.junit.jupiter.api.Assertions.assertThrows -import static org.junit.jupiter.api.Assertions.assertTrue +import static org.junit.jupiter.api.Assertions.* /** * Tests that the Hibernate mapping DSL constructs a valid Mapping object. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/HibernateOptimisticLockingStyleMappingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/HibernateOptimisticLockingStyleMappingSpec.groovy index d7b4a7077d1..2b91fc0c3a7 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/HibernateOptimisticLockingStyleMappingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/HibernateOptimisticLockingStyleMappingSpec.groovy @@ -2,8 +2,6 @@ package grails.gorm.hibernate.mapping import grails.gorm.tests.GormDatastoreSpec import grails.persistence.Entity -import org.grails.orm.hibernate.GormSpec -import org.grails.orm.hibernate.cfg.HibernateMappingBuilder import org.hibernate.boot.Metadata import org.hibernate.engine.OptimisticLockStyle import org.hibernate.mapping.PersistentClass diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/MappingBuilderSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/MappingBuilderSpec.groovy index b591b39a32b..29b25970282 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/MappingBuilderSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/hibernate/mapping/MappingBuilderSpec.groovy @@ -6,9 +6,8 @@ import org.grails.orm.hibernate.cfg.Mapping import org.grails.orm.hibernate.cfg.PropertyConfig import spock.lang.Specification -import jakarta.persistence.FetchType - import static grails.gorm.hibernate.mapping.MappingBuilder.define + /** * Created by graemerocher on 01/02/2017. */ diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy index 7ecabad9a04..d3a621101ef 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy @@ -1,7 +1,7 @@ package grails.gorm.specs -import grails.gorm.hibernate.HibernateEntity import grails.gorm.annotation.Entity +import grails.gorm.hibernate.HibernateEntity @Entity class Club implements HibernateEntity { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy index cfa725b6ee6..f9d4b51be4a 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy @@ -1,17 +1,11 @@ package grails.gorm.specs +import grails.gorm.annotation.Entity +import grails.gorm.transactions.Rollback import spock.lang.Ignore import static grails.gorm.hibernate.mapping.MappingBuilder.define -import grails.gorm.annotation.Entity -import grails.gorm.transactions.Rollback -import org.grails.orm.hibernate.HibernateDatastore -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Specification - /** * Created by graemerocher on 26/01/2017. */ diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy index 79c4ea1f600..6fac58d984e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy @@ -2,14 +2,8 @@ package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback -import org.grails.orm.hibernate.HibernateDatastore import org.jetbrains.annotations.NotNull -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification /** * Created by graemerocher on 26/01/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy index 2895f6bad56..bb92d4c8dd6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy @@ -3,7 +3,6 @@ package grails.gorm.specs import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity import grails.gorm.hibernate.HibernateEntity -import grails.gorm.tests.GormDatastoreSpec import spock.lang.Ignore @SuppressWarnings("GrMethodMayBeStatic") diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy index a749f8e70a4..56971f43b83 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy @@ -1,14 +1,10 @@ package grails.gorm.specs import grails.gorm.DetachedCriteria +import jakarta.persistence.criteria.JoinType import org.grails.datastore.gorm.finders.DynamicFinder -import org.grails.orm.hibernate.AbstractHibernateSession -import org.grails.orm.hibernate.GormSpec -import org.grails.orm.hibernate.HibernateDatastore import org.grails.orm.hibernate.query.HibernateQuery -import jakarta.persistence.criteria.JoinType - class DetachedCriteriaJoinSpec extends HibernateGormDatastoreSpec { @Override diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy index a578ad47376..c22f6e43c1c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy @@ -3,14 +3,8 @@ package grails.gorm.specs import grails.gorm.DetachedCriteria import grails.gorm.transactions.Rollback import grails.gorm.transactions.Transactional -import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.SessionFactory -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification - class DetachedCriteriaProjectionAliasSpec extends HibernateGormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy index cc439224f87..e08664d7c3c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy @@ -6,12 +6,7 @@ import grails.gorm.hibernate.HibernateEntity import grails.gorm.transactions.Rollback import grails.gorm.transactions.Transactional import org.grails.datastore.mapping.query.Query -import org.grails.orm.hibernate.HibernateDatastore -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification /** * Created by graemerocher on 24/10/16. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy index 53e1c317642..790a239e5b1 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/EnumMappingSpec.groovy @@ -4,8 +4,6 @@ import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec import org.hibernate.engine.spi.SessionImplementor -import java.sql.ResultSet - /** * Created by graemerocher on 24/02/16. */ diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy index f57bd2ffead..6815cadb864 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy @@ -3,7 +3,6 @@ package grails.gorm.specs import grails.gorm.tests.GormDatastoreSpec import grails.gorm.tests.Location import org.grails.datastore.gorm.proxy.GroovyProxyFactory - import spock.lang.Ignore /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy index 1a124a71ab4..e99f031f520 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy @@ -3,9 +3,7 @@ package grails.gorm.specs import grails.gorm.transactions.Rollback import groovy.transform.Generated import org.grails.orm.hibernate.HibernateDatastore -import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup -import spock.lang.IgnoreIf import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy index e409478601d..11107e7add8 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy @@ -2,12 +2,7 @@ package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback -import org.grails.orm.hibernate.HibernateDatastore -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup import spock.lang.Ignore -import spock.lang.Shared -import spock.lang.Specification import javax.sql.DataSource import java.sql.ResultSet diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy index b1724587753..aaef688b6cc 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/MultiColumnUniqueConstraintSpec.groovy @@ -1,7 +1,6 @@ package grails.gorm.specs import grails.gorm.annotation.Entity -import grails.gorm.tests.GormDatastoreSpec import org.springframework.dao.DataIntegrityViolationException import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy index 36ac68765ec..5a89b90dbd5 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy @@ -1,9 +1,7 @@ package grails.gorm.specs import grails.gorm.tests.ChildEntity -import grails.gorm.tests.GormDatastoreSpec import grails.gorm.tests.TestEntity -import org.grails.orm.hibernate.HibernateDatastoreSpec class NullValueEqualSpec extends HibernateGormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy index 642f551817f..16c69498082 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy @@ -4,7 +4,6 @@ import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup -import spock.lang.IgnoreIf import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy index 287c5290ff9..9a75adcbe80 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy @@ -1,12 +1,7 @@ package grails.gorm.specs -import grails.gorm.transactions.Rollback + import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform -import org.grails.orm.hibernate.HibernateDatastore -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Specification /** * Created by graemerocher on 01/03/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy index a9b1687e063..a1d7c7fa4e8 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy @@ -5,12 +5,6 @@ import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform -import org.grails.orm.hibernate.HibernateDatastore -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup -import spock.lang.Ignore -import spock.lang.Shared -import spock.lang.Specification /** * Created by graemerocher on 04/11/16. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy index db93178a72f..99b93759abf 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy @@ -7,11 +7,7 @@ import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.dialect.H2Dialect import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup -import spock.lang.Ignore -import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification +import spock.lang.* /** * Created by graemerocher on 17/02/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy index 5f01432a966..863d8d0b497 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy @@ -1,11 +1,6 @@ package grails.gorm.specs -import grails.gorm.tests.ChildEntity -import grails.gorm.tests.ClassWithListArgBeforeValidate -import grails.gorm.tests.ClassWithNoArgBeforeValidate -import grails.gorm.tests.ClassWithOverloadedBeforeValidate -import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.TestEntity +import grails.gorm.tests.* import org.springframework.transaction.support.TransactionSynchronizationManager /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy index 8d290cde63c..6ddddad4fe4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy @@ -1,6 +1,6 @@ package grails.gorm.specs -import grails.gorm.tests.GormDatastoreSpec + import org.grails.datastore.mapping.query.QueryException import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy index 8e89cbee596..e0f1582d850 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy @@ -6,7 +6,6 @@ import org.grails.orm.hibernate.GormSpec import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.Session import org.springframework.orm.hibernate5.SessionHolder -import org.springframework.orm.hibernate5.SpringSessionSynchronization import org.springframework.transaction.TransactionStatus import org.springframework.transaction.support.TransactionSynchronizationManager import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy index 3bd0d4f6ce4..ac048ffc2ff 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy @@ -4,15 +4,9 @@ import grails.gorm.annotation.Entity import grails.gorm.hibernate.mapping.MappingBuilder import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback -import org.grails.orm.hibernate.HibernateDatastore -import org.hibernate.SessionFactory import org.jetbrains.annotations.NotNull -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup import spock.lang.Ignore import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification /** * Created by graemerocher on 26/01/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy index 8897485a33c..dd6ce6a66c2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy @@ -3,19 +3,12 @@ package grails.gorm.specs.compositeid import grails.gorm.annotation.Entity import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback -import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.model.PersistentEntity -import org.grails.orm.hibernate.HibernateDatastore import org.grails.orm.hibernate.cfg.PropertyConfig -import org.hibernate.dialect.H2Dialect import org.jetbrains.annotations.NotNull -import org.springframework.transaction.PlatformTransactionManager -import spock.lang.AutoCleanup import spock.lang.Ignore import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification /** * Created by graemerocher on 17/02/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/PropertyFieldSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/PropertyFieldSpec.groovy index 66b583666f6..575091b1989 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/PropertyFieldSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/PropertyFieldSpec.groovy @@ -4,7 +4,6 @@ import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/events/UpdatePropertyInEventListenerSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/events/UpdatePropertyInEventListenerSpec.groovy index 131fc4a5f64..5adeddb03be 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/events/UpdatePropertyInEventListenerSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/events/UpdatePropertyInEventListenerSpec.groovy @@ -10,7 +10,6 @@ import org.grails.datastore.mapping.engine.event.PreInsertEvent import org.grails.datastore.mapping.engine.event.PreUpdateEvent import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.Session -import org.hibernate.engine.spi.SessionImplementor import org.springframework.context.ApplicationEvent import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy index 0f2d7ccbedd..113acc8c094 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy @@ -5,11 +5,7 @@ import grails.gorm.annotation.Entity import grails.gorm.services.Service import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore -import spock.lang.AutoCleanup -import spock.lang.Ignore -import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification +import spock.lang.* @Issue('https://github.com/grails/gorm-hibernate5/issues/78') @Rollback diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy index d604548a6de..70bc584eb7b 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy @@ -2,11 +2,9 @@ package grails.gorm.specs.hasmany import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback -import org.grails.datastore.mapping.collection.PersistentCollection import org.grails.datastore.mapping.proxy.ProxyHandler import org.grails.orm.hibernate.HibernateDatastore import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy index c3df66a04f9..572ff869acf 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy @@ -19,17 +19,12 @@ import grails.gorm.annotation.Entity import grails.gorm.annotation.JpaEntity import grails.gorm.hibernate.mapping.MappingBuilder import grails.gorm.transactions.Rollback -import org.grails.orm.hibernate.HibernateDatastore -import spock.lang.AutoCleanup -import spock.lang.Ignore -import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification - import jakarta.persistence.CascadeType import jakarta.persistence.GeneratedValue import jakarta.persistence.Id import jakarta.persistence.OneToMany +import org.grails.orm.hibernate.HibernateDatastore +import spock.lang.* /** * @author Graeme Rocher diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/jpa/SimpleJpaEntitySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/jpa/SimpleJpaEntitySpec.groovy index 73fddeedbab..4e91ead1b9c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/jpa/SimpleJpaEntitySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/jpa/SimpleJpaEntitySpec.groovy @@ -2,6 +2,12 @@ package grails.gorm.specs.jpa import grails.gorm.hibernate.HibernateEntity import grails.gorm.transactions.Rollback +import jakarta.persistence.Entity +import jakarta.persistence.GeneratedValue +import jakarta.persistence.Id +import jakarta.persistence.OneToMany +import jakarta.validation.ConstraintViolationException +import jakarta.validation.constraints.Digits import org.grails.datastore.mapping.model.PersistentEntity import org.grails.datastore.mapping.model.types.Association import org.grails.orm.hibernate.HibernateDatastore @@ -10,13 +16,6 @@ import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification -import jakarta.persistence.Entity -import jakarta.persistence.GeneratedValue -import jakarta.persistence.Id -import jakarta.persistence.OneToMany -import jakarta.validation.ConstraintViolationException -import jakarta.validation.constraints.Digits - /** * Created by graemerocher on 22/12/16. */ diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/mappedby/MultipleOneToOneSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/mappedby/MultipleOneToOneSpec.groovy index d8fa7568394..fae206baeea 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/mappedby/MultipleOneToOneSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/mappedby/MultipleOneToOneSpec.groovy @@ -3,7 +3,6 @@ package grails.gorm.specs.mappedby import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec import spock.lang.Issue -import spock.lang.Specification /** * Created by graemerocher on 29/05/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy index 20817768ce5..d72b7ce58d7 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy @@ -12,7 +12,6 @@ import org.grails.datastore.mapping.multitenancy.resolvers.SystemPropertyTenantR import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.dialect.H2Dialect import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy index a0b4a502d63..d4804dcddcd 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy @@ -1,15 +1,12 @@ package grails.gorm.specs.multitenancy +import grails.gorm.MultiTenant import grails.gorm.annotation.Entity import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.multitenancy.MultiTenancySettings import org.grails.datastore.mapping.multitenancy.resolvers.SystemPropertyTenantResolver -import org.grails.orm.hibernate.GormSpec -import grails.gorm.MultiTenant import org.grails.orm.hibernate.HibernateDatastore -import org.grails.orm.hibernate.connections.SingleTenantAuthor import org.hibernate.dialect.H2Dialect -import spock.lang.Ignore import spock.lang.Issue import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/perf/JoinPerfSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/perf/JoinPerfSpec.groovy index e7718439bd7..c1dec4741e3 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/perf/JoinPerfSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/perf/JoinPerfSpec.groovy @@ -4,14 +4,13 @@ import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import groovy.sql.Sql import groovy.transform.EqualsAndHashCode +import jakarta.persistence.AccessType import org.grails.orm.hibernate.HibernateDatastore import org.springframework.transaction.PlatformTransactionManager import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification -import jakarta.persistence.AccessType - /** * Created by graemerocher on 08/12/16. */ diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy index ffedbd7f9d8..ab5cb788e28 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy @@ -1,11 +1,9 @@ package grails.gorm.specs.proxy -import org.grails.datastore.mapping.reflect.ClassUtils - import grails.gorm.specs.Club -import grails.gorm.tests.GormDatastoreSpec import grails.gorm.specs.Team -import spock.lang.PendingFeature +import grails.gorm.tests.GormDatastoreSpec +import org.grails.datastore.mapping.reflect.ClassUtils import spock.lang.PendingFeatureIf /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy index dc170c60c38..7f63e914f12 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy @@ -1,13 +1,9 @@ package grails.gorm.specs.proxy +import grails.gorm.specs.Team import groovy.transform.CompileStatic - -import org.grails.datastore.gorm.GormEntity import org.hibernate.Hibernate -import grails.gorm.specs.Club -import grails.gorm.specs.Team - @CompileStatic class StaticTestUtil { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/softdelete/SoftDeleteSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/softdelete/SoftDeleteSpec.groovy index 33a623dbc3d..cc69801607c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/softdelete/SoftDeleteSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/softdelete/SoftDeleteSpec.groovy @@ -20,7 +20,6 @@ import grails.gorm.transactions.Rollback import org.grails.datastore.gorm.GormEntity import org.grails.orm.hibernate.HibernateDatastore import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/TraitPropertySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/TraitPropertySpec.groovy index 513c9f189e6..efac4661dca 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/TraitPropertySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/traits/TraitPropertySpec.groovy @@ -4,7 +4,6 @@ import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionalWithinReadOnlySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionalWithinReadOnlySpec.groovy index a9e74eeeb1a..a72dc28d12e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionalWithinReadOnlySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/txs/TransactionalWithinReadOnlySpec.groovy @@ -19,9 +19,7 @@ import grails.gorm.specs.services.Attribute import grails.gorm.specs.services.Product import grails.gorm.transactions.ReadOnly import grails.gorm.transactions.Transactional -import org.grails.orm.hibernate.GormSpec import org.grails.orm.hibernate.HibernateDatastore -import org.springframework.transaction.interceptor.TransactionAspectSupport import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/uuid/UuidInsertSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/uuid/UuidInsertSpec.groovy index 5e3ca15c656..e3f2c1a9b70 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/uuid/UuidInsertSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/uuid/UuidInsertSpec.groovy @@ -4,7 +4,6 @@ import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy index 3f38d20bf72..c73286f478b 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/BeanValidationSpec.groovy @@ -3,13 +3,8 @@ package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback -import org.grails.orm.hibernate.HibernateDatastore -import org.hibernate.validator.constraints.NotBlank -import spock.lang.AutoCleanup -import spock.lang.Shared -import spock.lang.Specification - import jakarta.validation.constraints.Digits +import org.hibernate.validator.constraints.NotBlank /** * Created by graemerocher on 07/04/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/CascadeValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/CascadeValidationSpec.groovy index b850c31da1f..54f253654c0 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/CascadeValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/CascadeValidationSpec.groovy @@ -4,7 +4,6 @@ import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy index 2105fa0fd42..83a1f845237 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy @@ -3,11 +3,7 @@ package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore -import spock.lang.AutoCleanup -import spock.lang.Ignore -import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification +import spock.lang.* /** * Created by graemerocher on 03/05/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueFalseConstraintSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueFalseConstraintSpec.groovy index 923a33d3684..a12e06cf8b5 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueFalseConstraintSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueFalseConstraintSpec.groovy @@ -1,7 +1,7 @@ package grails.gorm.specs.validation -import grails.gorm.transactions.Rollback import grails.gorm.annotation.Entity +import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import spock.lang.AutoCleanup import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueInheritanceSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueInheritanceSpec.groovy index e079dfd09e9..131427eb7e3 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueInheritanceSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueInheritanceSpec.groovy @@ -2,7 +2,6 @@ package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback -import org.grails.datastore.mapping.reflect.EntityReflector import org.grails.orm.hibernate.HibernateDatastore import spock.lang.AutoCleanup import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy index 75e1b7e7727..cf7b05bdee0 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithHasOneSpec.groovy @@ -18,13 +18,7 @@ package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback -import org.grails.orm.hibernate.HibernateDatastore -import org.hibernate.SessionFactory -import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification /** * @author Graeme Rocher diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy index d0f1c894e50..143146c50c3 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/UniqueWithinGroupSpec.groovy @@ -3,16 +3,9 @@ package grails.gorm.specs.validation import grails.gorm.annotation.Entity import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback -import org.grails.orm.hibernate.GormSpec import groovy.transform.EqualsAndHashCode -import org.grails.orm.hibernate.HibernateDatastore -import org.hibernate.SessionFactory import org.springframework.dao.DuplicateKeyException -import spock.lang.AutoCleanup -import spock.lang.Ignore import spock.lang.Issue -import spock.lang.Shared -import spock.lang.Specification /** * Created by graemerocher on 29/05/2017. diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy index fd41d71d6b3..facb51798c1 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy @@ -1,10 +1,9 @@ package org.grails.orm.hibernate.connections -import org.grails.datastore.mapping.core.DatastoreUtils -import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.datastore.gorm.jdbc.connections.DataSourceConnectionSourceFactory import org.grails.datastore.gorm.jdbc.schema.DefaultSchemaHandler -import org.hibernate.dialect.OracleDialect +import org.grails.datastore.mapping.core.DatastoreUtils +import org.grails.datastore.mapping.core.connections.ConnectionSource import spock.lang.Specification /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy index 39114fab1b7..df1562995f2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy @@ -3,10 +3,8 @@ package org.grails.orm.hibernate.connections import grails.gorm.annotation.Entity import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.core.connections.ConnectionSource -import org.grails.orm.hibernate.cfg.HibernateMappingContext import org.hibernate.SessionFactory import org.hibernate.dialect.H2Dialect -import org.hibernate.dialect.OracleDialect import spock.lang.Specification /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy index 8bb12f2d3a9..1f556b54a69 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy @@ -1,8 +1,6 @@ package org.grails.orm.hibernate.connections import org.grails.datastore.mapping.core.DatastoreUtils -import org.hibernate.dialect.OracleDialect -import org.springframework.core.io.FileSystemResource import org.springframework.core.io.UrlResource import spock.lang.Specification diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourceConnectionsSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourceConnectionsSpec.groovy index 3cb5128126d..6b8c9f89ce4 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourceConnectionsSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourceConnectionsSpec.groovy @@ -1,7 +1,7 @@ package org.grails.orm.hibernate.connections -import grails.gorm.services.Service import grails.gorm.annotation.Entity +import grails.gorm.services.Service import grails.gorm.transactions.Transactional import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.orm.hibernate.HibernateDatastore diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy index 06087345eb6..7aaafca3949 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy @@ -2,12 +2,12 @@ package org.grails.orm.hibernate.connections import grails.gorm.DetachedCriteria import grails.gorm.MultiTenant +import grails.gorm.annotation.Entity import grails.gorm.hibernate.mapping.MappingBuilder import grails.gorm.multitenancy.CurrentTenant import grails.gorm.multitenancy.Tenant import grails.gorm.multitenancy.Tenants import grails.gorm.transactions.Rollback -import grails.gorm.annotation.Entity import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.multitenancy.AllTenantsResolver diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy index 97b5ea8d13e..251497e22da 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy @@ -9,15 +9,9 @@ import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.Session import org.hibernate.dialect.H2Dialect import org.hibernate.resource.jdbc.spi.JdbcSessionOwner -import org.springframework.orm.hibernate5.SessionHolder -import org.springframework.transaction.support.TransactionSynchronizationManager -import spock.lang.AutoCleanup import spock.lang.Ignore -import spock.lang.Shared import spock.lang.Specification -import java.sql.Connection - /** * Created by graemerocher on 20/07/2016. */ diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SingleTenantSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SingleTenantSpec.groovy index 7aff8e1c12b..3bfab115729 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SingleTenantSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SingleTenantSpec.groovy @@ -1,10 +1,10 @@ package org.grails.orm.hibernate.connections import grails.gorm.MultiTenant +import grails.gorm.annotation.Entity import grails.gorm.multitenancy.CurrentTenant import grails.gorm.multitenancy.Tenant import grails.gorm.multitenancy.Tenants -import grails.gorm.annotation.Entity import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundException @@ -15,8 +15,6 @@ import org.hibernate.dialect.H2Dialect import org.hibernate.resource.jdbc.spi.JdbcSessionOwner import spock.lang.Specification -import java.sql.Connection - /** * Created by graemerocher on 07/07/2016. */ From 664202b461419e05c426e816e98d5577bca8928a Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Tue, 25 Mar 2025 21:01:54 -0500 Subject: [PATCH 0033/1008] more progress --- grails-datastore-gorm-hibernate/build.gradle | 6 +- .../orm/hibernate/HibernateSession.java | 7 + .../orm/hibernate/cfg/GrailsDomainBinder.java | 51 +++--- .../hibernate/cfg/GrailsHibernateUtil.java | 42 ++++- .../cfg/HibernateMappingContext.java | 2 + .../proxy/HibernateProxyHandler.java | 168 ++++++++++++++++++ .../query/AbstractHibernateQuery.java | 13 +- .../hibernate/proxy/HibernateProxyHelper.java | 24 +++ ...cadeToBidirectionalAsssociationSpec.groovy | 4 + .../specs/CompositeIdWithJoinTableSpec.groovy | 9 +- .../gorm/specs/DeleteAllWhereSpec.groovy | 1 + .../HibernateEntityTraitGeneratedSpec.groovy | 1 + .../grails/gorm/specs/SqlQuerySpec.groovy | 1 + .../gorm/specs/SubqueryAliasSpec.groovy | 14 +- .../TablePerSubClassAndEmbeddedSpec.groovy | 2 + .../grails/gorm/specs/ToOneProxySpec.groovy | 36 ++++ .../WhereQueryWithAssociationSortSpec.groovy | 3 +- .../DetachCriteriaSubquerySpec.groovy | 3 +- .../DetachedCriteriaJoinSpec.groovy | 7 +- ...DetachedCriteriaProjectionAliasSpec.groovy | 3 +- .../DetachedCriteriaProjectionSpec.groovy | 3 +- .../gorm/specs/{ => entities}/Club.groovy | 2 +- .../gorm/specs/{ => entities}/Contract.groovy | 4 +- .../gorm/specs/{ => entities}/Player.groovy | 6 +- .../gorm/specs/{ => entities}/Team.groovy | 2 +- .../specs/hasmany/ListCollectionSpec.groovy | 8 +- .../specs/proxy/ByteBuddyProxySpec.groovy | 40 ++++- .../specs/{ => proxy}/GroovyProxySpec.groovy | 2 +- .../gorm/specs/proxy/StaticTestUtil.groovy | 10 +- .../PartitionedMultiTenancySpec.groovy | 38 ++-- 30 files changed, 429 insertions(+), 83 deletions(-) create mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java create mode 100644 grails-datastore-gorm-hibernate/src/main/groovy/org/hibernate/proxy/HibernateProxyHelper.java create mode 100644 grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ToOneProxySpec.groovy rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => detachedcriteria}/DetachCriteriaSubquerySpec.groovy (97%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => detachedcriteria}/DetachedCriteriaJoinSpec.groovy (93%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => detachedcriteria}/DetachedCriteriaProjectionAliasSpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => detachedcriteria}/DetachedCriteriaProjectionSpec.groovy (96%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => entities}/Club.groovy (85%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => entities}/Contract.groovy (64%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => entities}/Player.groovy (53%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => entities}/Team.groovy (87%) rename grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/{ => proxy}/GroovyProxySpec.groovy (96%) diff --git a/grails-datastore-gorm-hibernate/build.gradle b/grails-datastore-gorm-hibernate/build.gradle index a3d177bdc82..7a874213a98 100644 --- a/grails-datastore-gorm-hibernate/build.gradle +++ b/grails-datastore-gorm-hibernate/build.gradle @@ -67,9 +67,9 @@ dependencies { testImplementation "org.hibernate:hibernate-jcache:$hibernate6Version" // groovy proxy fixes bytebuddy to be a bit smarter when it comes to groovy metaClass -// testImplementation "org.yakworks:hibernate-groovy-proxy:$yakworksHibernateGroovyProxyVersion", { -// exclude group: "org.codehaus.groovy", module: "groovy" -// } + testImplementation "org.yakworks:hibernate-groovy-proxy:$yakworksHibernateGroovyProxyVersion", { + exclude group: "org.codehaus.groovy", module: "groovy" + } testImplementation "org.apache.tomcat:tomcat-jdbc" testRuntimeOnly "org.springframework:spring-aop" diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java index 8c8f7d5b891..8051991a6b1 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/HibernateSession.java @@ -27,8 +27,10 @@ import org.grails.datastore.gorm.timestamp.DefaultTimestampProvider; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.config.GormProperties; +import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.query.event.PostQueryEvent; import org.grails.datastore.mapping.query.event.PreQueryEvent; +import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.grails.orm.hibernate.query.HibernateHqlQuery; import org.grails.orm.hibernate.query.HibernateQuery; import org.grails.datastore.mapping.model.PersistentEntity; @@ -38,6 +40,7 @@ import org.grails.datastore.mapping.query.jpa.JpaQueryInfo; import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; import org.hibernate.*; +import org.hibernate.proxy.HibernateProxy; import org.springframework.context.ApplicationEventPublisher; /** @@ -49,6 +52,7 @@ @SuppressWarnings("rawtypes") public class HibernateSession extends AbstractHibernateSession { + ProxyHandler proxyHandler = new HibernateProxyHandler(); DefaultTimestampProvider timestampProvider; public HibernateSession(HibernateDatastore hibernateDatastore, SessionFactory sessionFactory, int defaultFlushMode) { @@ -64,6 +68,9 @@ public HibernateSession(HibernateDatastore hibernateDatastore, SessionFactory se @Override public Serializable getObjectIdentifier(Object instance) { if(instance == null) return null; + if(proxyHandler.isProxy(instance)) { + return (Serializable) ((HibernateProxy)instance).getHibernateLazyInitializer().getIdentifier(); + } Class type = instance.getClass(); ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(type); final PersistentEntity persistentEntity = getMappingContext().getPersistentEntity(type.getName()); diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java index 779c75f9781..b100b5a21bd 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsDomainBinder.java @@ -36,6 +36,7 @@ import org.hibernate.boot.spi.*; import org.hibernate.cfg.*; import org.hibernate.engine.OptimisticLockStyle; +import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.engine.spi.PersistentAttributeInterceptable; import org.hibernate.id.PersistentIdentifierGenerator; import org.hibernate.id.enhanced.SequenceStyleGenerator; @@ -45,6 +46,7 @@ import org.hibernate.mapping.OneToMany; import org.hibernate.mapping.OneToOne; import org.hibernate.mapping.Table; +import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.persister.entity.UnionSubclassEntityPersister; import org.hibernate.type.*; import org.hibernate.usertype.UserCollectionType; @@ -1429,30 +1431,31 @@ protected void addMultiTenantFilterIfNecessary( InFlightMetadataCollector mappings, String sessionFactoryBeanName) { if (entity.isMultiTenant()) { - throw new RuntimeException("Multitenant not supported yet"); -// TenantId tenantId = entity.getTenantId(); -// -// if (tenantId != null) { -// String filterCondition = getMultiTenantFilterCondition(sessionFactoryBeanName, entity); -// -// persistentClass.addFilter( -// GormProperties.TENANT_IDENTITY, -// filterCondition, -// true, -// Collections.emptyMap(), -// Collections.emptyMap() -// ); -// -// Property property = getProperty(persistentClass, tenantId.getName()); -// Type type = property.getType(); -// Map stringVMap = Collections.singletonMap(GormProperties.TENANT_IDENTITY, type); -// FilterDefinition definition = new FilterDefinition( -// GormProperties.TENANT_IDENTITY, -// filterCondition, -// stringVMap -// ); -// mappings.addFilterDefinition(definition); -// } + TenantId tenantId = entity.getTenantId(); + + if (tenantId != null) { + String filterCondition = getMultiTenantFilterCondition(sessionFactoryBeanName, entity); + + persistentClass.addFilter( + GormProperties.TENANT_IDENTITY, + filterCondition, + true, + Collections.emptyMap(), + Collections.emptyMap() + ); + + Property property = getProperty(persistentClass, tenantId.getName()); + if (property.getValue() instanceof BasicValue basicValue) { + JdbcMapping jdbcMapping = basicValue.resolve().getJdbcMapping(); + var stringVMap = Collections.singletonMap(GormProperties.TENANT_IDENTITY, jdbcMapping); + FilterDefinition definition = new FilterDefinition( + GormProperties.TENANT_IDENTITY, + filterCondition, + stringVMap + ); + mappings.addFilterDefinition(definition); + } + } } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java index 01b555158cb..ff5631f7173 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/GrailsHibernateUtil.java @@ -25,6 +25,7 @@ import org.grails.datastore.mapping.reflect.ClassUtils; import org.grails.orm.hibernate.AbstractHibernateDatastore; import org.grails.orm.hibernate.datasource.MultipleDataSourceSupport; +import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.grails.orm.hibernate.support.HibernateRuntimeUtils; import org.hibernate.FetchMode; import org.hibernate.FlushMode; @@ -71,7 +72,7 @@ public class GrailsHibernateUtil extends HibernateRuntimeUtils { public static final Class[] EMPTY_CLASS_ARRAY = {}; - + private static HibernateProxyHandler proxyHandler = new HibernateProxyHandler(); @@ -177,6 +178,45 @@ public static void ensureCorrectGroovyMetaClass(Object target, Class persiste } } + /** + * Unwraps and initializes a HibernateProxy. + * @param proxy The proxy + * @return the unproxied instance + */ + public static Object unwrapProxy(HibernateProxy proxy) { + return proxyHandler.unwrap(proxy); + } + + /** + * Returns the proxy for a given association or null if it is not proxied + * + * @param obj The object + * @param associationName The named assoication + * @return A proxy + */ + public static HibernateProxy getAssociationProxy(Object obj, String associationName) { + return proxyHandler.getAssociationProxy(obj, associationName); + } + + /** + * Checks whether an associated property is initialized and returns true if it is + * + * @param obj The name of the object + * @param associationName The name of the association + * @return true if is initialized + */ + public static boolean isInitialized(Object obj, String associationName) { + return proxyHandler.isInitialized(obj, associationName); + } + + /** + * Unproxies a HibernateProxy. If the proxy is uninitialized, it automatically triggers an initialization. + * In case the supplied object is null or not a proxy, the object will be returned as-is. + */ + public static Object unwrapIfProxy(Object instance) { + return proxyHandler.unwrap(instance); + } + public static boolean isMappedWithHibernate(PersistentEntity domainClass) { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java index 5e57b0726fc..4c4387c3684 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/cfg/HibernateMappingContext.java @@ -28,6 +28,7 @@ import org.grails.datastore.mapping.model.config.JpaMappingConfigurationStrategy; import org.grails.datastore.mapping.reflect.ClassUtils; import org.grails.orm.hibernate.connections.HibernateConnectionSourceSettings; +import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.springframework.validation.Errors; import java.lang.annotation.Annotation; @@ -68,6 +69,7 @@ protected boolean supportsCustomType(Class propertyType) { return !Errors.class.isAssignableFrom(propertyType); } }; + this.proxyFactory = new HibernateProxyHandler(); addPersistentEntities(persistentClasses); } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java new file mode 100644 index 00000000000..90c42ecac06 --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/proxy/HibernateProxyHandler.java @@ -0,0 +1,168 @@ +/* + * Copyright 2004-2008 the original author or authors. + * + * 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 org.grails.orm.hibernate.proxy; + +import org.grails.datastore.mapping.core.Session; +import org.grails.datastore.mapping.engine.AssociationQueryExecutor; +import org.grails.datastore.mapping.proxy.ProxyFactory; +import org.grails.datastore.mapping.proxy.ProxyHandler; +import org.grails.datastore.mapping.reflect.ClassPropertyFetcher; +import org.hibernate.Hibernate; +import org.hibernate.collection.spi.PersistentCollection; +import org.hibernate.proxy.HibernateProxy; +import org.hibernate.proxy.HibernateProxyHelper; +//import org.hibernate.proxy.HibernateProxyHelper; + +import java.io.Serializable; + +/** + * Implementation of the ProxyHandler interface for Hibernate using org.hibernate.Hibernate + * and HibernateProxyHelper where possible. + * + * @author Graeme Rocher + * @since 1.2.2 + */ +public class HibernateProxyHandler implements ProxyHandler, ProxyFactory { + + /** + * Check if the proxy or persistent collection is initialized. + * {@inheritDoc} + */ + @Override + public boolean isInitialized(Object o) { + return Hibernate.isInitialized(o); + } + + /** + * Check if an association proxy or persistent collection is initialized. + * {@inheritDoc} + */ + @Override + public boolean isInitialized(Object obj, String associationName) { + try { + Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); + return isInitialized(proxy); + } + catch (RuntimeException e) { + return false; + } + } + + /** + * Unproxies a HibernateProxy. If the proxy is uninitialized, it automatically triggers an initialization. + * In case the supplied object is null or not a proxy, the object will be returned as-is. + * {@inheritDoc} + * @see Hibernate#unproxy + */ + @Override + public Object unwrap(Object object) { + if (object instanceof PersistentCollection) { + initialize(object); + return object; + } + return Hibernate.unproxy(object); + } + + /** + * {@inheritDoc} + * @see org.hibernate.proxy.AbstractLazyInitializer#getIdentifier + */ + @Override + public Serializable getIdentifier(Object o) { + if (o instanceof HibernateProxy) { + return null; + //This line does not compile +// return ((HibernateProxy)o).getHibernateLazyInitializer().getIdentifier(); + } + else { + //TODO seems we can get the id here if its has normal getId + // PersistentEntity persistentEntity = GormEnhancer.findStaticApi(o.getClass()).getGormPersistentEntity(); + // return persistentEntity.getMappingContext().getEntityReflector(persistentEntity).getIdentifier(o); + return null; + } + } + + /** + * {@inheritDoc} + * @see HibernateProxyHelper#getClassWithoutInitializingProxy + */ + @Override + public Class getProxiedClass(Object o) { + return HibernateProxyHelper.getClassWithoutInitializingProxy(o); + } + + /** + * calls unwrap which calls unproxy + * @see #unwrap(Object) + * @deprecated use unwrap + */ + @Deprecated + public Object unwrapIfProxy(Object instance) { + return unwrap(instance); + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isProxy(Object o) { + return (o instanceof HibernateProxy) || (o instanceof PersistentCollection); + } + + /** + * Force initialization of a proxy or persistent collection. + * {@inheritDoc} + */ + @Override + public void initialize(Object o) { + Hibernate.initialize(o); + } + + @Override + public T createProxy(Session session, Class type, Serializable key) { + throw new UnsupportedOperationException("createProxy not supported in HibernateProxyHandler"); + } + + @Override + public T createProxy(Session session, AssociationQueryExecutor executor, K associationKey) { + throw new UnsupportedOperationException("createProxy not supported in HibernateProxyHandler"); + } + + /** + * @deprecated use unwrap + */ + @Deprecated + public Object unwrapProxy(Object proxy) { + return unwrap(proxy); + } + + /** + * returns the proxy for an association. returns null if its not a proxy. + * Note: Only used in a test. Deprecate? + */ + public HibernateProxy getAssociationProxy(Object obj, String associationName) { + try { + Object proxy = ClassPropertyFetcher.getInstancePropertyValue(obj, associationName); + if (proxy instanceof HibernateProxy) { + return (HibernateProxy) proxy; + } + return null; + } + catch (RuntimeException e) { + return null; + } + } +} diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index a65336b5527..5f13f9da6b8 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -29,13 +29,16 @@ import org.grails.datastore.mapping.model.PersistentEntity; import org.grails.datastore.mapping.model.PersistentProperty; import org.grails.datastore.mapping.model.types.Association; +import org.grails.datastore.mapping.proxy.ProxyHandler; import org.grails.datastore.mapping.query.AssociationQuery; +import org.grails.orm.hibernate.proxy.HibernateProxyHandler; import org.grails.datastore.mapping.query.Query; import org.grails.datastore.mapping.query.QueryException; import org.grails.datastore.mapping.query.Restrictions; import org.grails.datastore.mapping.query.api.QueryableCriteria; import org.grails.orm.hibernate.AbstractHibernateSession; import org.grails.orm.hibernate.IHibernateTemplate; +import org.hibernate.NonUniqueResultException; import org.hibernate.SessionFactory; import org.hibernate.query.ResultListTransformer; import org.hibernate.query.criteria.HibernateCriteriaBuilder; @@ -85,6 +88,7 @@ public abstract class AbstractHibernateQuery extends Query { protected LinkedList aliasInstanceStack = new LinkedList(); private boolean hasJoins = false; protected DetachedCriteria detachedCriteria; + protected ProxyHandler proxyHandler = new HibernateProxyHandler(); protected ResultTransformer resultTransformer; protected AbstractHibernateQuery(AbstractHibernateSession session, PersistentEntity entity) { @@ -423,11 +427,16 @@ protected void flushBeforeQuery() { @Override public Object singleResult() { + org.hibernate.query.Query query = createQuery(); try { - return createQuery().getSingleResult(); + + return proxyHandler.unwrap(query.getSingleResult()); + } + catch (NonUniqueResultException e) { + return proxyHandler.unwrap(query.getResultList().get(0)); } catch (jakarta.persistence.NoResultException e) { - return null; + return null; } } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/hibernate/proxy/HibernateProxyHelper.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/hibernate/proxy/HibernateProxyHelper.java new file mode 100644 index 00000000000..12b3316d664 --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/hibernate/proxy/HibernateProxyHelper.java @@ -0,0 +1,24 @@ +package org.hibernate.proxy; + +public final class HibernateProxyHelper { + + /** + * Get the class of an instance or the underlying class + * of a proxy (without initializing the proxy!). It is + * almost always better to use the entity name! + */ + public static Class getClassWithoutInitializingProxy(Object object) { + if (object instanceof HibernateProxy) { + HibernateProxy proxy = (HibernateProxy) object; + LazyInitializer li = proxy.getHibernateLazyInitializer(); + return li.getPersistentClass(); + } + else { + return object.getClass(); + } + } + + private HibernateProxyHelper() { + //cant instantiate + } +} \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CascadeToBidirectionalAsssociationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CascadeToBidirectionalAsssociationSpec.groovy index a0e569f7437..b0928c806aa 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CascadeToBidirectionalAsssociationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CascadeToBidirectionalAsssociationSpec.groovy @@ -1,5 +1,9 @@ package grails.gorm.specs +import grails.gorm.specs.entities.Club +import grails.gorm.specs.entities.Contract +import grails.gorm.specs.entities.Player +import grails.gorm.specs.entities.Team import org.grails.orm.hibernate.GormSpec import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy index f9d4b51be4a..17cb0326876 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy @@ -9,11 +9,14 @@ import static grails.gorm.hibernate.mapping.MappingBuilder.define /** * Created by graemerocher on 26/01/2017. */ -@Ignore("Composite Id saving is not working") +@Ignore("Mapping is not working") class CompositeIdWithJoinTableSpec extends HibernateGormDatastoreSpec { + @Override + List getDomainClasses() { + [CompositeIdParent,CompositeIdChild] + } - - @Rollback + // @Rollback void "test composite id with join table"() { when:"A parent with a composite id and a join table is saved" new CompositeIdParent(name: "Test" , last:"Test 2") diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DeleteAllWhereSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DeleteAllWhereSpec.groovy index 4d6569e3e2b..f510dbc3429 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DeleteAllWhereSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DeleteAllWhereSpec.groovy @@ -15,6 +15,7 @@ */ package grails.gorm.specs +import grails.gorm.specs.entities.Club import org.grails.orm.hibernate.GormSpec import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy index e99f031f520..11a403b6472 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/HibernateEntityTraitGeneratedSpec.groovy @@ -1,5 +1,6 @@ package grails.gorm.specs +import grails.gorm.specs.entities.Club import grails.gorm.transactions.Rollback import groovy.transform.Generated import org.grails.orm.hibernate.HibernateDatastore diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy index 16c69498082..e2e6bb3b8a3 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SqlQuerySpec.groovy @@ -1,5 +1,6 @@ package grails.gorm.specs +import grails.gorm.specs.entities.Club import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore import org.springframework.transaction.PlatformTransactionManager diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy index 9a75adcbe80..773fc9bdf54 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy @@ -1,6 +1,7 @@ package grails.gorm.specs - +import grails.gorm.specs.entities.Club +import grails.gorm.specs.entities.Team import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform /** @@ -10,7 +11,7 @@ import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform class SubqueryAliasSpec extends HibernateGormDatastoreSpec { List getDomainClasses() { - [Club,Team] + [Club, Team] } @@ -23,10 +24,11 @@ class SubqueryAliasSpec extends HibernateGormDatastoreSpec { Team t = Team.where { def t = Team name == "First Team" - exists(Club.where { - id == t.club - }.property('name')) - + exists( + Club.where { + id == t.club + }.property('name') + ) }.find() then: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy index a1d7c7fa4e8..e06703287f2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy @@ -5,11 +5,13 @@ import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.datastore.gorm.query.criteria.DetachedAssociationCriteria import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform +import spock.lang.Ignore /** * Created by graemerocher on 04/11/16. */ @ApplyDetachedCriteriaTransform +@Ignore("How does JPA deal with subclasses?") class TablePerSubClassAndEmbeddedSpec extends HibernateGormDatastoreSpec { @Override diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ToOneProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ToOneProxySpec.groovy new file mode 100644 index 00000000000..2f60041b864 --- /dev/null +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ToOneProxySpec.groovy @@ -0,0 +1,36 @@ +package grails.gorm.specs + +import grails.gorm.specs.entities.Club +import grails.gorm.specs.entities.Team +import grails.gorm.tests.GormDatastoreSpec +import org.grails.orm.hibernate.proxy.HibernateProxyHandler + +/** + * Created by graemerocher on 16/12/16. + */ +class ToOneProxySpec extends GormDatastoreSpec { + + void "test that a proxy is not initialized on get"() { + given: + Team t = new Team(name: "First Team", club: new Club(name: "Manchester United").save()) + t.save(flush:true) + session.clear() + + + when:"An object is retrieved and the session is flushed" + t = Team.get(t.id) + session.flush() + + def proxyHandler = new HibernateProxyHandler() + then:"The association was not initialized" + proxyHandler.getAssociationProxy(t, "club") != null + !proxyHandler.isInitialized(t, "club") + + + } + + @Override + List getDomainClasses() { + [Team, Club] + } +} diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy index 6ddddad4fe4..81d96d1c3a5 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy @@ -1,6 +1,7 @@ package grails.gorm.specs - +import grails.gorm.specs.entities.Club +import grails.gorm.specs.entities.Team import org.grails.datastore.mapping.query.QueryException import spock.lang.Issue diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachCriteriaSubquerySpec.groovy similarity index 97% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachCriteriaSubquerySpec.groovy index bb92d4c8dd6..71926643afc 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachCriteriaSubquerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachCriteriaSubquerySpec.groovy @@ -1,8 +1,9 @@ -package grails.gorm.specs +package grails.gorm.specs.detachedcriteria import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity import grails.gorm.hibernate.HibernateEntity +import grails.gorm.specs.HibernateGormDatastoreSpec import spock.lang.Ignore @SuppressWarnings("GrMethodMayBeStatic") diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaJoinSpec.groovy similarity index 93% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaJoinSpec.groovy index 56971f43b83..d2640373867 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaJoinSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaJoinSpec.groovy @@ -1,6 +1,9 @@ -package grails.gorm.specs +package grails.gorm.specs.detachedcriteria import grails.gorm.DetachedCriteria +import grails.gorm.specs.HibernateGormDatastoreSpec +import grails.gorm.specs.entities.Club +import grails.gorm.specs.entities.Team import jakarta.persistence.criteria.JoinType import org.grails.datastore.gorm.finders.DynamicFinder import org.grails.orm.hibernate.query.HibernateQuery @@ -9,7 +12,7 @@ class DetachedCriteriaJoinSpec extends HibernateGormDatastoreSpec { @Override List getDomainClasses() { - [Team,Club] + [Team, Club] } def "check if count works as expected"() { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaProjectionAliasSpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaProjectionAliasSpec.groovy index c22f6e43c1c..0d4fb77e16c 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaProjectionAliasSpec.groovy @@ -1,6 +1,7 @@ -package grails.gorm.specs +package grails.gorm.specs.detachedcriteria import grails.gorm.DetachedCriteria +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import grails.gorm.transactions.Transactional import org.hibernate.SessionFactory diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaProjectionSpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaProjectionSpec.groovy index e08664d7c3c..215dc1b5ca2 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/DetachedCriteriaProjectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachedCriteriaProjectionSpec.groovy @@ -1,8 +1,9 @@ -package grails.gorm.specs +package grails.gorm.specs.detachedcriteria import grails.gorm.DetachedCriteria import grails.gorm.annotation.Entity import grails.gorm.hibernate.HibernateEntity +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import grails.gorm.transactions.Transactional import org.grails.datastore.mapping.query.Query diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Club.groovy similarity index 85% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Club.groovy index d3a621101ef..4badc679e17 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Club.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Club.groovy @@ -1,4 +1,4 @@ -package grails.gorm.specs +package grails.gorm.specs.entities import grails.gorm.annotation.Entity import grails.gorm.hibernate.HibernateEntity diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Contract.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Contract.groovy similarity index 64% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Contract.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Contract.groovy index 9fb491d666d..0242aea760e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Contract.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Contract.groovy @@ -1,4 +1,4 @@ -package grails.gorm.specs +package grails.gorm.specs.entities import grails.gorm.annotation.Entity @@ -8,5 +8,5 @@ import grails.gorm.annotation.Entity @Entity class Contract { BigDecimal salary - static belongsTo = [player:Player] + static belongsTo = [player: Player] } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Player.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Player.groovy similarity index 53% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Player.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Player.groovy index ac6e6f7bf7c..a7aed918c53 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Player.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Player.groovy @@ -1,4 +1,4 @@ -package grails.gorm.specs +package grails.gorm.specs.entities import grails.gorm.annotation.Entity @@ -8,6 +8,6 @@ import grails.gorm.annotation.Entity @Entity class Player { String name - static belongsTo = [team:Team] - static hasOne = [contract:Contract] + static belongsTo = [team: Team] + static hasOne = [contract: Contract] } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Team.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Team.groovy similarity index 87% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Team.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Team.groovy index 8200c9cb56a..da9d2933811 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/Team.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/entities/Team.groovy @@ -1,4 +1,4 @@ -package grails.gorm.specs +package grails.gorm.specs.entities import grails.gorm.annotation.Entity import groovy.transform.ToString diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy index 70bc584eb7b..91becb257a9 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy @@ -1,6 +1,7 @@ package grails.gorm.specs.hasmany import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import org.grails.datastore.mapping.proxy.ProxyHandler import org.grails.orm.hibernate.HibernateDatastore @@ -8,9 +9,12 @@ import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification -class ListCollectionSpec extends Specification { +class ListCollectionSpec extends HibernateGormDatastoreSpec { - @Shared @AutoCleanup HibernateDatastore datastore = new HibernateDatastore(getClass().getPackage()) + @Override + List getDomainClasses() { + [Animal,Leg] + } @Rollback void "test legs are not loaded eagerly"() { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy index ab5cb788e28..9ae0c6346fb 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy @@ -1,24 +1,28 @@ package grails.gorm.specs.proxy -import grails.gorm.specs.Club -import grails.gorm.specs.Team -import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.specs.entities.Club +import grails.gorm.specs.HibernateGormDatastoreSpec +import grails.gorm.specs.entities.Team import org.grails.datastore.mapping.reflect.ClassUtils +import org.grails.orm.hibernate.proxy.HibernateProxyHandler +import spock.lang.Ignore import spock.lang.PendingFeatureIf /** * Contains misc proxy tests using Hibenrate defaults, which is ByteBuddy. * These should all be passing for Gorm to be operating correctly with Groovy. */ -class ByteBuddyProxySpec extends GormDatastoreSpec { - +class ByteBuddyProxySpec extends HibernateGormDatastoreSpec { + static HibernateProxyHandler proxyHandler = new HibernateProxyHandler() //to show test that fail that should succeed set this to true. or uncomment the // testImplementation "org.yakworks:hibernate-groovy-proxy:$yakworksHibernateGroovyProxy" to see pass boolean runPending = ClassUtils.isPresent("yakworks.hibernate.proxy.ByteBuddyGroovyInterceptor") @Override - List getDomainClasses() { [Team, Club] } + List getDomainClasses() { + [Team, Club] + } Team createATeam(){ Club c = new Club(name: "DOOM Club").save(failOnError:true) @@ -26,18 +30,21 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { return team } + @Ignore("StaticTestUtil.team_id_asserts assert !Hibernate.isInitialized(team) fails") void "getId and id property checks dont initialize proxy if in a CompileStatic method"() { when: Team team = createATeam() session.clear() - team = Team.load(team.id) + //TODO load is broken +// team = Team.load(team.id) + team = Team.list().find { it.id == team.id } then:"The asserts on getId and id should not initialize proxy when statically compiled" StaticTestUtil.team_id_asserts(team) - + !proxyHandler.isInitialized(team) StaticTestUtil.club_id_asserts(team) - + !proxyHandler.isInitialized(team.club) } @PendingFeatureIf({ !instance.runPending }) @@ -48,12 +55,16 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { team = Team.load(team.id) then:"The asserts on getId and id should not initialize proxy" + proxyHandler.isProxy(team) team.getId() + !proxyHandler.isInitialized(team) team.id + !proxyHandler.isInitialized(team) and: "the getAt check for id should not initialize" team['id'] + !proxyHandler.isInitialized(team) } @PendingFeatureIf({ !instance.runPending }) @@ -65,9 +76,11 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { then:"The asserts on the intance should not init proxy" team + !proxyHandler.isInitialized(team) and: "truthy check on association should not initialize" team.club + !proxyHandler.isInitialized(team.club) } @PendingFeatureIf({ !instance.runPending }) @@ -78,15 +91,20 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { team = Team.load(team.id) then:"The asserts on the intance should not init proxy" + !proxyHandler.isInitialized(team.club) team.club.getId() + !proxyHandler.isInitialized(team.club) team.club.id + !proxyHandler.isInitialized(team.club) team.clubId + !proxyHandler.isInitialized(team.club) and: "the getAt check for id should not initialize" team.club['id'] + !proxyHandler.isInitialized(team.club) } void "isDirty should not intialize the association proxy"() { @@ -96,10 +114,13 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { team = Team.load(team.id) then:"The asserts on the intance should not init proxy" + !proxyHandler.isInitialized(team) //isDirty will init the proxy. should make changes for this. !team.isDirty() + proxyHandler.isInitialized(team) //it should not have initialized the association + !proxyHandler.isInitialized(team.club) when: "its made dirty" team.name = "B-Team" @@ -107,6 +128,7 @@ class ByteBuddyProxySpec extends GormDatastoreSpec { then: team.isDirty() //still should not have initialized it. + !proxyHandler.isInitialized(team.club) } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy similarity index 96% rename from grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy rename to grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy index 6815cadb864..1aae2e55eb5 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/GroovyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy @@ -1,4 +1,4 @@ -package grails.gorm.specs +package grails.gorm.specs.proxy import grails.gorm.tests.GormDatastoreSpec import grails.gorm.tests.Location diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy index 7f63e914f12..7c3eedcb078 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/StaticTestUtil.groovy @@ -1,22 +1,24 @@ package grails.gorm.specs.proxy -import grails.gorm.specs.Team +import grails.gorm.specs.entities.Team import groovy.transform.CompileStatic +import org.grails.orm.hibernate.proxy.HibernateProxyHandler import org.hibernate.Hibernate @CompileStatic class StaticTestUtil { - + public static HibernateProxyHandler proxyHandler = new HibernateProxyHandler() // should return true and not initialize the proxy // getId works inside a compile static static boolean team_id_asserts(Team team){ assert team.getId() assert !Hibernate.isInitialized(team) + assert proxyHandler.isProxy(team) assert team.id assert !Hibernate.isInitialized(team) - + assert proxyHandler.isProxy(team) //a truthy check on the object will try to init it because it hits the getMetaClass // assert team // assert !Hibernate.isInitialized(team) @@ -40,6 +42,8 @@ class StaticTestUtil { static boolean notInitialized(Object o){ //sanity check the 3 assert !Hibernate.isInitialized(o) + assert !proxyHandler.isInitialized(o) + assert proxyHandler.isProxy(o) return true } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy index 7aaafca3949..db374fc3348 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy @@ -7,6 +7,7 @@ import grails.gorm.hibernate.mapping.MappingBuilder import grails.gorm.multitenancy.CurrentTenant import grails.gorm.multitenancy.Tenant import grails.gorm.multitenancy.Tenants +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import org.grails.datastore.gorm.GormEntity import org.grails.datastore.mapping.core.DatastoreUtils @@ -14,8 +15,8 @@ import org.grails.datastore.mapping.multitenancy.AllTenantsResolver import org.grails.datastore.mapping.multitenancy.MultiTenancySettings import org.grails.datastore.mapping.multitenancy.exceptions.TenantNotFoundException import org.grails.datastore.mapping.multitenancy.resolvers.SystemPropertyTenantResolver +import org.grails.datastore.mapping.core.Session import org.grails.orm.hibernate.HibernateDatastore -import org.hibernate.Session import org.hibernate.dialect.H2Dialect import spock.lang.AutoCleanup import spock.lang.Ignore @@ -25,35 +26,40 @@ import spock.lang.Specification /** * Created by graemerocher on 11/07/2016. */ -@Rollback -@Ignore -class PartitionedMultiTenancySpec extends Specification { - @Shared @AutoCleanup HibernateDatastore datastore - void setupSpec() { +class PartitionedMultiTenancySpec extends HibernateGormDatastoreSpec { + + @Override + List getDomainClasses() { + [MultiTenantAuthor, MultiTenantBook, MultiTenantPublisher] + } + + Session configure() { + ConfigObject grailsConfig = new ConfigObject() Map config = [ - "grails.gorm.multiTenancy.mode":MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR, - "grails.gorm.multiTenancy.tenantResolverClass":MyTenantResolver, - 'dataSource.url':"jdbc:h2:mem:grailsDB;LOCK_TIMEOUT=10000", - 'dataSource.dbCreate': 'update', - 'dataSource.dialect': H2Dialect.name, + 'dataSource.url':"jdbc:tc:postgresql:latest:///dev_db", + 'dataSource.dbCreate': 'create-drop', 'dataSource.formatSql': 'true', 'dataSource.logSql': 'true', 'hibernate.flush.mode': 'COMMIT', 'hibernate.cache.queries': 'true', 'hibernate.hbm2ddl.auto': 'create', + 'hibernate.type.descriptor.sql': 'true', + "grails.gorm.multiTenancy.mode":MultiTenancySettings.MultiTenancyMode.DISCRIMINATOR, + "grails.gorm.multiTenancy.tenantResolverClass":MyTenantResolver, ] - - datastore = new HibernateDatastore(DatastoreUtils.createPropertyResolver(config), MultiTenantAuthor, MultiTenantBook, MultiTenantPublisher ) + grailsConfig.putAll(config) + setupClass.setup(((TEST_CLASSES + getDomainClasses()) as Set) as List, grailsConfig, true) } + Session getSession() { datastore.sessionFactory.currentSession } - void setup() { + def setup() { System.setProperty(SystemPropertyTenantResolver.PROPERTY_NAME, "") } - void cleanup() { + def cleanup() { System.setProperty(SystemPropertyTenantResolver.PROPERTY_NAME, "") } @@ -75,7 +81,7 @@ class PartitionedMultiTenancySpec extends Specification { thrown(TenantNotFoundException) when:"A tenant id is present" - datastore.sessionFactory.currentSession.clear() + setupClass.hibernateDatastore.sessionFactory.currentSession.clear() System.setProperty(SystemPropertyTenantResolver.PROPERTY_NAME, "moreBooks") then:"the correct tenant is used" From 22d61598ff77271e434cc6ecae36d429e19f02a2 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 26 Mar 2025 22:03:44 -0500 Subject: [PATCH 0034/1008] listDistinct and distinct implemented fixed --- .../query/AbstractHibernateCriteriaBuilder.java | 8 ++++++-- .../orm/hibernate/query/AbstractHibernateQuery.java | 8 ++++---- .../gorm/specs/hibernatequery/HibernateQuerySpec.groovy | 3 ++- .../hibernate/HibernateGormStaticApiSpecification.groovy | 9 ++++++--- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java index bdace0e0953..02232bb70f9 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateCriteriaBuilder.java @@ -124,6 +124,7 @@ public abstract class AbstractHibernateCriteriaBuilder extends GroovyObjectSuppo private boolean shouldLock; private boolean shouldCache; private boolean readOnly; + private boolean distinct = false; @SuppressWarnings("rawtypes") public AbstractHibernateCriteriaBuilder(Class targetClass, SessionFactory sessionFactory, AbstractHibernateDatastore datastore) { @@ -1157,7 +1158,7 @@ else if (name.equals(COUNT_CALL)) { count = true; } else if (name.equals(LIST_DISTINCT_CALL)) { - hibernateQuery.projections().distinct(); + distinct = true; } @@ -1172,7 +1173,10 @@ else if (name.equals(LIST_DISTINCT_CALL)) { Object result; if (!uniqueResult) { - if (scroll) { + if (distinct) { + hibernateQuery.distinct(); + result = hibernateQuery.list(); + } else if (scroll) { result = hibernateQuery.scroll(); } else if (count) { diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 5f13f9da6b8..0635628be1d 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -488,11 +488,11 @@ protected org.hibernate.query.Query createQuery() { List groupProjections = collectGroupProjections(); List joinColumns = Stream.concat(aliasMap.keySet().stream(), collectJoinColumns().stream()).distinct().toList(); - - - CriteriaQuery cq = projections.size() > 1 ? cb.createQuery(Object[].class) : cb.createQuery(Object.class); + CriteriaQuery cq = projections.stream() + .filter( it -> !(it instanceof DistinctProjection || it instanceof DistinctPropertyProjection)) + .toList().size() > 1 ? cb.createQuery(Object[].class) : cb.createQuery(Object.class); projections.stream() - .filter( DistinctProjection.class::isInstance ) + .filter( it -> it instanceof DistinctProjection || it instanceof DistinctPropertyProjection) .findFirst() .ifPresent(projection -> { cq.distinct(true); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index 2226726cd09..0ae1435e5ea 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -631,7 +631,8 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { def projectionProperty() { given: oldBob.addToPets(new Pet(name:"Lucky")).save(flush:true) - hibernateQuery.join("pets").projections().property("pets.name") + oldBob.addToPets(new Pet(name:"Lucky")).save(flush:true) + hibernateQuery.join("pets").projections().property("pets.name").distinct("pets.name") when: def petName = hibernateQuery.singleResult() then: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy index 13381786fe5..bb6203e3e94 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy @@ -69,6 +69,7 @@ class HibernateGormStaticApiTest extends HibernateGormDatastoreSpec{ results[1] == barneyAccount } + @Ignore("JPA Criteria requires a single predicate behind a not") def "not"() { when: def results = accountCriteria { @@ -171,11 +172,13 @@ class HibernateGormStaticApiTest extends HibernateGormDatastoreSpec{ new Account(balance: 250, firstName: "Fred", lastName: "Flintstone", branch: "Bedrock").save(flush:true) when: def results = accountCriteria.listDistinct { - eq("balance", 250) + property("branch") + order("branch") } then: - results.size() == 1 - results[0] == fredAccount + results.size() == 2 + results[0] == "Bedrock" + results[1] == "London" } @Ignore("This is documented as working but fails") From 4f36a88f6f256fd3c4f08b5e91c5a10c9196bd25 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Mon, 31 Mar 2025 22:02:36 -0500 Subject: [PATCH 0035/1008] Update README for PR --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index e3b0016fa33..9b3b0f201b1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,12 @@ # GORM for Hibernate 6 This project implements [GORM](https://gorm.grails.org) for the Hibernate 6. + +With the removal of Criterion API in Hibernate 6, we wanted to continue to support the DetachedCriteia in GORM as much as possible. We also wanted to encapsulate the JPA Criteria Building in one class so the following was done: +* DetachedCriteria holds almost all the state of the Query being built. It hold the target class for the query. It does not hold a session. +* AbstractHibernateQuery has a session and holds the DetachedCriteria and is a thin wrapper for it. Calling list or singleResult will internally create the Query and execute it. +* AbstractHibernateCriteriaBuilder is a thin wrapper around AbstractHibernateQuery. Its main function is to use closures to populate the Hibernate Query and execute it at the end of the closure. +* Only the grails-datastore-gorm-hibernate6 module is being developed at the time. + +For testing the following was done: +* Used testcontainers of postgres instead of h2 because h2 does not support all the Java Types correctly. +* A more opinionated and fluent HibernateGormDatastoreSpec is used for the specifications. \ No newline at end of file From 16b38ea7eff7ddcc737b8bd5090a73e9dd841c4b Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Tue, 1 Apr 2025 19:38:27 -0500 Subject: [PATCH 0036/1008] Made HibernateConnectionSourceFactorySpec pass --- .../HibernateConnectionSourceFactorySpec.groovy | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy index df1562995f2..3a163cd4dce 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceFactorySpec.groovy @@ -5,6 +5,7 @@ import org.grails.datastore.mapping.core.DatastoreUtils import org.grails.datastore.mapping.core.connections.ConnectionSource import org.hibernate.SessionFactory import org.hibernate.dialect.H2Dialect +import org.hibernate.query.criteria.JpaCriteriaQuery import spock.lang.Specification /** @@ -26,11 +27,10 @@ class HibernateConnectionSourceFactorySpec extends Specification { 'hibernate.hbm2ddl.auto': 'create' ] def connectionSource = factory.create(ConnectionSource.DEFAULT, DatastoreUtils.createPropertyResolver(config)) - + def query = connectionSource.source.getCriteriaBuilder().createQuery(Foo) + query.select(query.from(Foo)) then:"The session factory is created" - connectionSource.source instanceof SessionFactory - connectionSource.source.getMetamodel().entity(Foo.name) - connectionSource.source.openSession().createCriteria(Foo).list().size() == 0 + connectionSource.source.openSession().createQuery(query).list().size() == 0 when:"The connection source is closed" connectionSource.close() From 0eadd8945b8fd05398314d8c397c3559a455cd49 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Tue, 1 Apr 2025 19:43:03 -0500 Subject: [PATCH 0037/1008] Made DataSourceConnectionSourceFactorySpec pass --- .../connections/DataSourceConnectionSourceFactorySpec.groovy | 1 - 1 file changed, 1 deletion(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy index facb51798c1..e6188829707 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/DataSourceConnectionSourceFactorySpec.groovy @@ -17,7 +17,6 @@ class DataSourceConnectionSourceFactorySpec extends Specification { Map config = [ 'dataSource.url':"jdbc:h2:mem:dsConnDsFactorySpecDb;LOCK_TIMEOUT=10000", 'dataSource.dbCreate': 'update', - 'dataSource.dialect': Oracle8iDialect.name, 'dataSource.properties.dbProperties': [useSSL: false] ] def connectionSource = factory.create(ConnectionSource.DEFAULT, DatastoreUtils.createPropertyResolver(config)) From 921f3ccbcc8e5b6655780a362f04da2a78c7f2d9 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Tue, 1 Apr 2025 19:55:27 -0500 Subject: [PATCH 0038/1008] Made MultipleDataSourcesWithCachingSpec pass --- grails-datastore-gorm-hibernate/build.gradle | 1 + .../connections/MultipleDataSourcesWithCachingSpec.groovy | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/grails-datastore-gorm-hibernate/build.gradle b/grails-datastore-gorm-hibernate/build.gradle index 7a874213a98..d6fb71b2f5f 100644 --- a/grails-datastore-gorm-hibernate/build.gradle +++ b/grails-datastore-gorm-hibernate/build.gradle @@ -54,6 +54,7 @@ dependencies { testImplementation 'org.postgresql:postgresql:42.7.5' testImplementation "org.testcontainers:postgresql:1.20.4" testImplementation "org.testcontainers:spock:1.20.4" + testImplementation 'org.jsr107.ri:cache-ri-impl:1.1.1' testImplementation "org.apache.groovy:groovy-test-junit5" testImplementation "org.apache.groovy:groovy-sql" diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithCachingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithCachingSpec.groovy index 80c43f899c5..bf50b128991 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithCachingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithCachingSpec.groovy @@ -20,7 +20,7 @@ class MultipleDataSourcesWithCachingSpec extends Specification { 'dataSource.formatSql': 'true', 'hibernate.flush.mode': 'COMMIT', 'hibernate.cache.queries': 'true', - 'hibernate.cache':['use_second_level_cache':true,'region.factory_class':'org.hibernate.cache.ehcache.EhCacheRegionFactory'], + 'hibernate.cache':['use_second_level_cache':true,'region.factory_class':'org.hibernate.cache.jcache.internal.JCacheRegionFactory'], 'hibernate.hbm2ddl.auto': 'create', 'dataSources.books':[url:"jdbc:h2:mem:books;LOCK_TIMEOUT=10000"], 'dataSources.moreBooks':[url:"jdbc:h2:mem:moreBooks;LOCK_TIMEOUT=10000"] From 9c70566732669ebd5af8944d9e692e5872ba92c0 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 2 Apr 2025 20:34:17 -0500 Subject: [PATCH 0039/1008] Made ListCollectionSpec pass --- .../grails/gorm/specs/hasmany/ListCollectionSpec.groovy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy index 91becb257a9..f4f472029d5 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/ListCollectionSpec.groovy @@ -25,9 +25,9 @@ class ListCollectionSpec extends HibernateGormDatastoreSpec { .addToLegs(new Leg()) .addToLegs(new Leg()) .save(flush: true, failOnError: true) - datastore.currentSession.flush() - datastore.currentSession.clear() - ProxyHandler ph = datastore.mappingContext.proxyHandler + setupClass.hibernateDatastore.currentSession.flush() + setupClass.hibernateDatastore.currentSession.clear() + ProxyHandler ph = setupClass.hibernateDatastore.mappingContext.proxyHandler when: Animal animal = Animal.load(1) From c01b5a512c1f8462e080ba8f70dde6e06cbeb5bf Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 2 Apr 2025 20:45:20 -0500 Subject: [PATCH 0040/1008] Made HibernateConnectionSourceSettingsSpec pass --- .../HibernateConnectionSourceSettingsSpec.groovy | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy index 1f556b54a69..fce3dff0124 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/HibernateConnectionSourceSettingsSpec.groovy @@ -1,6 +1,7 @@ package org.grails.orm.hibernate.connections import org.grails.datastore.mapping.core.DatastoreUtils +import org.hibernate.dialect.H2Dialect import org.springframework.core.io.UrlResource import spock.lang.Specification @@ -13,7 +14,7 @@ class HibernateConnectionSourceSettingsSpec extends Specification { when:"The configuration is built" Map config = [ 'dataSource.dbCreate': 'update', - 'dataSource.dialect': Oracle8iDialect.name, + 'dataSource.dialect': H2Dialect.name, 'dataSource.formatSql': 'true', 'hibernate.flush.mode': 'commit', 'hibernate.cache.queries': 'true', @@ -29,7 +30,7 @@ class HibernateConnectionSourceSettingsSpec extends Specification { expectedDataSourceProperties.put('hibernate.hbm2ddl.auto', 'update') expectedDataSourceProperties.put('hibernate.show_sql', 'false') expectedDataSourceProperties.put('hibernate.format_sql', 'true') - expectedDataSourceProperties.put('hibernate.dialect', Oracle8iDialect.name) + expectedDataSourceProperties.put('hibernate.dialect', H2Dialect.name) def expectedHibernateProperties = new Properties() expectedHibernateProperties.put('hibernate.hbm2ddl.auto', 'create') @@ -49,7 +50,7 @@ class HibernateConnectionSourceSettingsSpec extends Specification { then:"The results are correct" settings.dataSource.dbCreate == 'update' - settings.dataSource.dialect == Oracle8iDialect + settings.dataSource.dialect == H2Dialect settings.dataSource.formatSql !settings.dataSource.logSql settings.dataSource.toHibernateProperties() == expectedDataSourceProperties From bb6a6b3b39cca593520ed4f667b81d5e813b702b Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 2 Apr 2025 21:04:59 -0500 Subject: [PATCH 0041/1008] Made IdentityEnumTypeSpec pass --- .../gorm/specs/IdentityEnumTypeSpec.groovy | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy index 11107e7add8..8b413a80c90 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/IdentityEnumTypeSpec.groovy @@ -2,7 +2,8 @@ package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback -import spock.lang.Ignore +import jakarta.persistence.Enumerated +import jakarta.persistence.EnumType import javax.sql.DataSource import java.sql.ResultSet @@ -10,7 +11,6 @@ import java.sql.ResultSet /** * Created by graemerocher on 16/11/16. */ -@Ignore("Not able to map Enum to SQL Type") class IdentityEnumTypeSpec extends HibernateGormDatastoreSpec { @Override @@ -28,7 +28,7 @@ class IdentityEnumTypeSpec extends HibernateGormDatastoreSpec { then: resultSet.next() - resultSet.getString(1) == 'F' + resultSet.getString(1) == 'FOO' EnumEntityDomain.first().status == EnumEntityDomain.Status.FOO } @@ -36,22 +36,23 @@ class IdentityEnumTypeSpec extends HibernateGormDatastoreSpec { void "test identity enum type 2"() { when: new FooWithEnum(name: "blah", mySuperValue: XEnum.X__TWO).save(flush:true) - DataSource ds = hibernateDatastore.connectionSources.defaultConnectionSource.dataSource + DataSource ds = setupClass.hibernateDatastore.connectionSources.defaultConnectionSource.dataSource ResultSet resultSet = ds.getConnection().prepareStatement('select my_super_value from foo_with_enum').executeQuery() then: resultSet.next() - resultSet.getInt(1) == 100 + resultSet.getString(1) == "X__TWO" FooWithEnum.first().mySuperValue == XEnum.X__TWO } } @Entity class EnumEntityDomain { + @Enumerated(EnumType.STRING) Status status static mapping = { - status(enumType: "identity") + status(enumType: "string") } enum Status { @@ -65,11 +66,12 @@ class EnumEntityDomain { class FooWithEnum { long id String name + @Enumerated(EnumType.STRING) XEnum mySuperValue static mapping = { version false - mySuperValue enumType:"identity" + mySuperValue enumType:"string" } } From 543a2e54a4a89024f57ad2d2d24b4111e90bda1e Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 2 Apr 2025 21:12:54 -0500 Subject: [PATCH 0042/1008] Made HibernateVersionSupportSpec pass --- .../orm/hibernate/support/HibernateVersionSupportSpec.groovy | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/support/HibernateVersionSupportSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/support/HibernateVersionSupportSpec.groovy index 828b02cd463..db0cfbc4e14 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/support/HibernateVersionSupportSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/support/HibernateVersionSupportSpec.groovy @@ -1,5 +1,6 @@ package org.grails.orm.hibernate.support +import org.hibernate.Version import spock.lang.Specification /** @@ -9,7 +10,7 @@ class HibernateVersionSupportSpec extends Specification { void 'test hibernate version is at least'() { expect: - !HibernateVersionSupport.isAtLeastVersion("6.0.0") - HibernateVersionSupport.isAtLeastVersion("5.3.0") + Version.getVersionString() > "6.0.0" + } } From aa0335168a3b9477491f163c12541c01231eb784 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 2 Apr 2025 21:18:20 -0500 Subject: [PATCH 0043/1008] Update README.md --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b3b0f201b1..d0c57d6a9b4 100644 --- a/README.md +++ b/README.md @@ -9,4 +9,10 @@ With the removal of Criterion API in Hibernate 6, we wanted to continue to suppo For testing the following was done: * Used testcontainers of postgres instead of h2 because h2 does not support all the Java Types correctly. -* A more opinionated and fluent HibernateGormDatastoreSpec is used for the specifications. \ No newline at end of file +* A more opinionated and fluent HibernateGormDatastoreSpec is used for the specifications. + +### Largest Gaps +* Multitenancy +* Proxy support +* AbstractHibernateCriteriaBuilder coverage. (In contrast to HibernateQuery which has good coverage) +* AsbtractGormStaticApi coverage From aaec0d5aacc58e2785b245940016e0449ef81d46 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Tue, 8 Apr 2025 18:06:23 -0500 Subject: [PATCH 0044/1008] multiple changes --- .../AbstractHibernateGormStaticApi.groovy | 1 + .../query/AbstractHibernateQuery.java | 1 + .../hibernate/query/PredicateGenerator.java | 12 ++++-- .../specs/CompositeIdWithJoinTableSpec.groovy | 25 ++++++++--- ...ositeIdWithManyToOneAndSequenceSpec.groovy | 6 ++- .../gorm/specs/NullValueEqualSpec.groovy | 4 +- .../gorm/specs/OptimisticLockingSpec.groovy | 4 +- .../groovy/grails/gorm/specs/RLikeSpec.groovy | 2 +- .../gorm/specs/ReadOperationSpec.groovy | 3 +- .../SubclassMultipleListCollectionSpec.groovy | 1 - .../gorm/specs/SubqueryAliasSpec.groovy | 1 + .../TablePerSubClassAndEmbeddedSpec.groovy | 2 +- .../UniqueConstraintHibernateSpec.groovy | 5 +-- .../UniqueWithMultipleDataSourcesSpec.groovy | 42 +++++++++++-------- .../grails/gorm/specs/ValidationSpec.groovy | 5 +++ .../WhereQueryWithAssociationSortSpec.groovy | 1 + ...ewSessionAndExistingTransactionSpec.groovy | 2 +- ...ositeIdWithDeepOneToManyMappingSpec.groovy | 8 ++-- ...GlobalConstraintWithCompositeIdSpec.groovy | 8 ++-- .../DetachCriteriaSubquerySpec.groovy | 5 ++- .../HibernateDirtyCheckingSpec.groovy | 20 +++++---- .../hasmany/HasManyWithInQuerySpec.groovy | 2 +- .../TwoUnidirectionalHasManySpec.groovy | 12 +++--- .../hibernatequery/HibernateQuerySpec.groovy | 15 +++---- ...iTenancyBidirectionalManyToManySpec.groovy | 1 + ...iTenancyUnidirectionalOneToManySpec.groovy | 1 + .../specs/proxy/ByteBuddyProxySpec.groovy | 3 +- .../gorm/specs/proxy/GroovyProxySpec.groovy | 5 +-- .../SaveWithInvalidEntitySpec.groovy | 2 +- ...HibernateGormStaticApiSpecification.groovy | 2 +- .../MultipleDataSourcesWithEventsSpec.groovy | 23 +++++++--- .../PartitionedMultiTenancySpec.groovy | 2 +- .../connections/SchemaMultiTenantSpec.groovy | 1 - .../connections/SecondLevelCacheSpec.groovy | 2 +- 34 files changed, 143 insertions(+), 86 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy index c4d31a3abce..903e6643868 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/AbstractHibernateGormStaticApi.groovy @@ -100,6 +100,7 @@ abstract class AbstractHibernateGormStaticApi extends GormStaticApi { // for multi-tenant entities we process get(..) via a query // throw new UnsupportedOperationException("no yet") (D)hibernateTemplate.execute( { Session session -> + return new HibernateQuery(hibernateSession,persistentEntity ).idEq(id).singleResult() } ) } diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index 0635628be1d..a953445a52c 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -43,6 +43,7 @@ import org.hibernate.query.ResultListTransformer; import org.hibernate.query.criteria.HibernateCriteriaBuilder; import org.hibernate.query.criteria.JpaExpression; +import org.hibernate.query.sqm.PathElementException; import org.hibernate.transform.ResultTransformer; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.DefaultConversionService; diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index 920d4e27992..aa0b5ea858e 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -167,14 +167,18 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, return cb.in(getFullyQualifiedPath(tablesByName, c.getProperty()), c.getValues()); } else if (criterion instanceof Query.Exists c) { Subquery subquery = criteriaQuery.subquery(Object.class); - Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), tablesByName); + Root subRoot = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); + HashMap subMap = new HashMap<>(tablesByName); + subMap.put("root", subRoot); + Predicate[] predicates = getPredicates(cb, criteriaQuery, subRoot, c.getSubquery().getCriteria(), subMap); subquery.select(cb.literal(1)).where(cb.and(predicates)); return cb.exists(subquery); } else if (criterion instanceof Query.NotExists c) { Subquery subquery = criteriaQuery.subquery(Object.class); - Root from = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); - Predicate[] predicates = getPredicates(cb, criteriaQuery, from, c.getSubquery().getCriteria(), tablesByName); + Root subRoot = subquery.from(c.getSubquery().getPersistentEntity().getJavaClass()); + HashMap subMap = new HashMap<>(tablesByName); + subMap.put("root", subRoot); + Predicate[] predicates = getPredicates(cb, criteriaQuery, subRoot, c.getSubquery().getCriteria(), tablesByName); subquery.select(cb.literal(1)).where(cb.and(predicates)); return cb.not(cb.exists(subquery)); } else if (criterion instanceof Query.SubqueryCriterion c) { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy index 17cb0326876..09ae101a26e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithJoinTableSpec.groovy @@ -1,15 +1,16 @@ package grails.gorm.specs import grails.gorm.annotation.Entity -import grails.gorm.transactions.Rollback -import spock.lang.Ignore +import org.jetbrains.annotations.NotNull + import static grails.gorm.hibernate.mapping.MappingBuilder.define /** * Created by graemerocher on 26/01/2017. */ -@Ignore("Mapping is not working") +//TODO: Failing at MappingModelCreationHelper line 1223 +//MappingModelCreationHelper assert ( (SortableValue) collectionBootValueMapping.getKey() ).isSorted() class CompositeIdWithJoinTableSpec extends HibernateGormDatastoreSpec { @Override List getDomainClasses() { @@ -20,7 +21,7 @@ class CompositeIdWithJoinTableSpec extends HibernateGormDatastoreSpec { void "test composite id with join table"() { when:"A parent with a composite id and a join table is saved" new CompositeIdParent(name: "Test" , last:"Test 2") - .addToChildren(new CompositeIdChild()) + .addToChildren(new CompositeIdChild(foo: "bar")) .save(flush:true) @@ -31,9 +32,10 @@ class CompositeIdWithJoinTableSpec extends HibernateGormDatastoreSpec { } @Entity -class CompositeIdParent implements Serializable { +class CompositeIdParent implements Serializable , Comparable{ String name String last + SortedSet children static hasMany = [children:CompositeIdChild] static mapping = define { id composite('name','last') @@ -50,14 +52,25 @@ class CompositeIdParent implements Serializable { } } } + + @Override + int compareTo(@NotNull CompositeIdParent o) { + this.name <=> o.name ?: this.last <=> o.last + } } @Entity -class CompositeIdChild { +class CompositeIdChild implements Comparable { + String foo + static belongsTo = [parent:CompositeIdParent] static mapping = { } static constraints = { } + @Override + int compareTo(CompositeIdChild other) { + foo <=> other.foo + } } \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy index 6fac58d984e..4c32b0ed297 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/CompositeIdWithManyToOneAndSequenceSpec.groovy @@ -2,7 +2,9 @@ package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback -import org.jetbrains.annotations.NotNull +import jakarta.annotation.Nonnull + +//import org.jetbrains.annotations.NotNull import spock.lang.Issue /** @@ -61,7 +63,7 @@ class ToothDisease implements Serializable,Comparable { } @Override - int compareTo(@NotNull ToothDisease o) { + int compareTo(@Nonnull ToothDisease o) { return idColumn <=> ((ToothDisease)o).idColumn } } \ No newline at end of file diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy index 5a89b90dbd5..a858df9d9de 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy @@ -1,7 +1,7 @@ package grails.gorm.specs -import grails.gorm.tests.ChildEntity -import grails.gorm.tests.TestEntity +import grails.gorm.tck.TestEntity +import grails.gorm.tck.ChildEntity class NullValueEqualSpec extends HibernateGormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy index 0c5bb48d33c..679ce0b2626 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy @@ -1,8 +1,8 @@ package grails.gorm.specs +import grails.gorm.tck.OptLockNotVersioned +import grails.gorm.tck.OptLockVersioned import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.OptLockNotVersioned -import grails.gorm.tests.OptLockVersioned import org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy index 915b5592236..443181247e6 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/RLikeSpec.groovy @@ -4,9 +4,9 @@ import grails.gorm.annotation.Entity import org.grails.orm.hibernate.GormSpec import spock.lang.Ignore +//TODO Rlike Needs to be implemented for Hibernate 6 class RLikeSpec extends GormSpec { - @Ignore("RLIKE NOT IMPLEMENTED") void "test rlike works with H2"() { given: new RlikeFoo(name: "ABC").save(flush: true) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy index dd8da2f9440..57ee7b4dd90 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy @@ -1,6 +1,7 @@ package grails.gorm.specs -import grails.gorm.tests.TestEntity +import grails.gorm.tck.TestEntity + class ReadOperationSpec extends HibernateGormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubclassMultipleListCollectionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubclassMultipleListCollectionSpec.groovy index 9e0a48f8159..fcad5a9f621 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubclassMultipleListCollectionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubclassMultipleListCollectionSpec.groovy @@ -23,7 +23,6 @@ class SubclassMultipleListCollectionSpec extends Specification { transactionManager = hibernateDatastore.getTransactionManager() } - @Ignore // not yet implemented @Rollback @Issue('https://github.com/grails/grails-data-mapping/issues/882') void "test inheritance with multiple list collections"() { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy index 773fc9bdf54..2fbef621508 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/SubqueryAliasSpec.groovy @@ -8,6 +8,7 @@ import org.grails.datastore.gorm.query.transform.ApplyDetachedCriteriaTransform * Created by graemerocher on 01/03/2017. */ @ApplyDetachedCriteriaTransform +//TODO: How to create an alias inside a closure class SubqueryAliasSpec extends HibernateGormDatastoreSpec { List getDomainClasses() { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy index e06703287f2..ad88edae7bd 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy @@ -11,7 +11,7 @@ import spock.lang.Ignore * Created by graemerocher on 04/11/16. */ @ApplyDetachedCriteriaTransform -@Ignore("How does JPA deal with subclasses?") +//TODO: Closure syntax not detecting that address is an embedded entity class TablePerSubClassAndEmbeddedSpec extends HibernateGormDatastoreSpec { @Override diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy index 443f3fe042b..c9152c4403a 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy @@ -1,8 +1,8 @@ package grails.gorm.specs import grails.gorm.annotation.Entity -import grails.gorm.tests.GroupWithin -import grails.gorm.tests.UniqueGroup +import grails.gorm.tck.GroupWithin +import grails.gorm.tck.UniqueGroup import org.grails.datastore.gorm.GormEntity import org.grails.orm.hibernate.HibernateDatastore import org.springframework.transaction.PlatformTransactionManager @@ -73,7 +73,6 @@ class UniqueConstraintHibernateSpec extends Specification { } - @spock.lang.Ignore def "Test unique constraint with a hasOne association"() { when:"Two domain classes with the same license are saved" Driver one diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy index 99b93759abf..f0cb82f6d14 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueWithMultipleDataSourcesSpec.groovy @@ -3,6 +3,7 @@ package grails.gorm.specs import grails.gorm.annotation.Entity import grails.gorm.transactions.Rollback import org.grails.datastore.mapping.core.DatastoreUtils +import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.dialect.H2Dialect @@ -12,25 +13,32 @@ import spock.lang.* /** * Created by graemerocher on 17/02/2017. */ -class UniqueWithMultipleDataSourcesSpec extends Specification { - - @Shared Map config = [ - 'dataSource.url':"jdbc:h2:mem:grailsDB;LOCK_TIMEOUT=10000", - 'dataSource.dbCreate': 'update', - 'dataSource.dialect': H2Dialect.name, - 'dataSource.formatSql': 'true', - 'hibernate.flush.mode': 'COMMIT', - 'hibernate.cache.queries': 'true', - 'hibernate.cache':['use_second_level_cache':true,'region.factory_class':'org.hibernate.cache.ehcache.EhCacheRegionFactory'], - 'hibernate.hbm2ddl.auto': 'create', - 'dataSources.second':[url:"jdbc:h2:mem:second;LOCK_TIMEOUT=10000"], - ] - - @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(DatastoreUtils.createPropertyResolver(config),Abc) - @Shared PlatformTransactionManager transactionManager = hibernateDatastore.transactionManager +class UniqueWithMultipleDataSourcesSpec extends HibernateGormDatastoreSpec { + + @Override + List getDomainClasses() { + [Abc] + } + + Session configure() { + ConfigObject grailsConfig = new ConfigObject() + Map config = [ + 'dataSource.url':"jdbc:h2:mem:grailsDB;LOCK_TIMEOUT=10000", + 'dataSource.dbCreate': 'update', + 'dataSource.dialect': H2Dialect.name, + 'dataSource.formatSql': 'true', + 'hibernate.flush.mode': 'COMMIT', + 'hibernate.cache.queries': 'true', + 'hibernate.cache':['use_second_level_cache':true,'region.factory_class':'org.hibernate.cache.jcache.internal.JCacheRegionFactory'], + 'hibernate.hbm2ddl.auto': 'create', + 'dataSources.second':[url:"jdbc:h2:mem:second;LOCK_TIMEOUT=10000"], + ] + grailsConfig.putAll(config) + setupClass.setup(((TEST_CLASSES + getDomainClasses()) as Set) as List, grailsConfig, true) + } + @Rollback - @Ignore @Issue('https://github.com/grails/grails-core/issues/10481') void "test multiple data sources and unique constraint"() { when: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy index 863d8d0b497..e95a237f80e 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy @@ -1,5 +1,10 @@ package grails.gorm.specs +import grails.gorm.tck.ChildEntity +import grails.gorm.tck.ClassWithListArgBeforeValidate +import grails.gorm.tck.ClassWithNoArgBeforeValidate +import grails.gorm.tck.ClassWithOverloadedBeforeValidate +import grails.gorm.tck.TestEntity import grails.gorm.tests.* import org.springframework.transaction.support.TransactionSynchronizationManager diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy index 81d96d1c3a5..24d33ea80c5 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy @@ -8,6 +8,7 @@ import spock.lang.Issue /** * Created by graemerocher on 03/11/16. */ +//TODO : How to create an alias inside a closure class WhereQueryWithAssociationSortSpec extends HibernateGormDatastoreSpec { @Issue('https://github.com/grails/grails-core/issues/9860') diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy index e0f1582d850..93ab72cc2ee 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy @@ -1,6 +1,6 @@ package grails.gorm.specs -import grails.gorm.tests.Book +import grails.gorm.tck.Book import org.grails.datastore.gorm.Setup import org.grails.orm.hibernate.GormSpec import org.grails.orm.hibernate.HibernateDatastore diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy index ac048ffc2ff..6bad4f21773 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/CompositeIdWithDeepOneToManyMappingSpec.groovy @@ -4,14 +4,14 @@ import grails.gorm.annotation.Entity import grails.gorm.hibernate.mapping.MappingBuilder import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback -import org.jetbrains.annotations.NotNull +import jakarta.annotation.Nonnull import spock.lang.Ignore import spock.lang.Issue /** * Created by graemerocher on 26/01/2017. */ -@Ignore("AUTO CREATE DDL NOT WORKING") +//TODO: CompositeId not working class CompositeIdWithDeepOneToManyMappingSpec extends HibernateGormDatastoreSpec { @Override @@ -50,7 +50,7 @@ class Child implements Serializable, Comparable { } @Override - int compareTo(@NotNull Child o) { + int compareTo(@Nonnull Child o) { return this.name <=> o.name } } @@ -68,7 +68,7 @@ class Parent implements Serializable, Comparable { } @Override - int compareTo(@NotNull Parent o) { + int compareTo(@Nonnull Parent o) { return this.name <=> o.name } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy index dd6ce6a66c2..60bcf881392 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy @@ -3,16 +3,18 @@ package grails.gorm.specs.compositeid import grails.gorm.annotation.Entity import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback +import jakarta.annotation.Nonnull import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.model.PersistentEntity import org.grails.orm.hibernate.cfg.PropertyConfig -import org.jetbrains.annotations.NotNull + import spock.lang.Ignore import spock.lang.Issue /** * Created by graemerocher on 17/02/2017. */ +//TODO CompositeId not working class GlobalConstraintWithCompositeIdSpec extends HibernateGormDatastoreSpec { @Override @@ -53,7 +55,7 @@ class GlobalConstraintWithCompositeIdSpec extends HibernateGormDatastoreSpec { ChildB.count == 1 } - @Ignore("DDL not working for composite id") +// @Ignore("DDL not working for composite id") @Issue('https://github.com/grails/grails-data-mapping/issues/877') void "test global constraints with unique constraint"() { given: @@ -112,7 +114,7 @@ class ChildB implements Serializable, Comparable { } @Override - int compareTo(@NotNull ChildB o) { + int compareTo(@Nonnull ChildB o) { this.name <=> o.name } } diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachCriteriaSubquerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachCriteriaSubquerySpec.groovy index 71926643afc..0352d1bad1f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachCriteriaSubquerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/detachedcriteria/DetachCriteriaSubquerySpec.groovy @@ -7,6 +7,7 @@ import grails.gorm.specs.HibernateGormDatastoreSpec import spock.lang.Ignore @SuppressWarnings("GrMethodMayBeStatic") +//TODO Closure alias not working class DetachCriteriaSubquerySpec extends HibernateGormDatastoreSpec { @Override @@ -14,7 +15,7 @@ class DetachCriteriaSubquerySpec extends HibernateGormDatastoreSpec { return [User, Group, GroupAssignment, Organisation] } - @Ignore("Exists Query broken") +// @Ignore("Exists Query broken") void "test detached associated criteria in subquery"() { setup: @@ -70,7 +71,7 @@ class DetachCriteriaSubquerySpec extends HibernateGormDatastoreSpec { result.size() == 5 } - @Ignore("Explore is currently broken") +// @Ignore("Explore is currently broken") void "test that detached criteria subquery should create implicit alias instead of using this_"() { setup: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateDirtyCheckingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateDirtyCheckingSpec.groovy index 2c19aea6c6e..177afea5faa 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateDirtyCheckingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/dirtychecking/HibernateDirtyCheckingSpec.groovy @@ -2,8 +2,10 @@ package grails.gorm.specs.dirtychecking import grails.gorm.annotation.Entity import grails.gorm.dirty.checking.DirtyCheck +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import org.grails.orm.hibernate.HibernateDatastore +import org.grails.orm.hibernate.HibernateDatastoreSpec import spock.lang.AutoCleanup import spock.lang.Issue import spock.lang.Shared @@ -12,9 +14,12 @@ import spock.lang.Specification /** * Created by graemerocher on 03/05/2017. */ -class HibernateDirtyCheckingSpec extends Specification { +class HibernateDirtyCheckingSpec extends HibernateGormDatastoreSpec { - @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(Person) + @Override + List getDomainClasses() { + [Person] + } @Rollback @Issue('https://github.com/grails/grails-core/issues/10613') @@ -53,6 +58,7 @@ class HibernateDirtyCheckingSpec extends Specification { } @Rollback + //TODO Embedded class not working void "test dirty checking on embedded"() { given: 'a new person' Person person = new Person(name: 'John', occupation: 'Grails developer', address: new Address(street: "Old Town", zip: "1234")).save(flush:true) @@ -72,7 +78,7 @@ class HibernateDirtyCheckingSpec extends Specification { person.address.listDirtyPropertyNames().isEmpty() when: - hibernateDatastore.sessionFactory.currentSession.clear() + setupClass.hibernateDatastore.sessionFactory.currentSession.clear() person = Person.first() then: @@ -83,7 +89,7 @@ class HibernateDirtyCheckingSpec extends Specification { void "test dirty checking on boolean true -> false"() { given: 'a new person' new Person(name: 'John', occupation: 'Grails developer', employed: true).save(flush: true) - hibernateDatastore.sessionFactory.currentSession.clear() + setupClass.hibernateDatastore.sessionFactory.currentSession.clear() Person person = Person.first() when: @@ -96,7 +102,7 @@ class HibernateDirtyCheckingSpec extends Specification { when: person.save(flush:true) - hibernateDatastore.sessionFactory.currentSession.clear() + setupClass.hibernateDatastore.sessionFactory.currentSession.clear() person = Person.first() then: @@ -107,7 +113,7 @@ class HibernateDirtyCheckingSpec extends Specification { void "test dirty checking on boolean false -> true"() { given: 'a new person' new Person(name: 'John', occupation: 'Grails developer', employed: false).save(flush: true) - hibernateDatastore.sessionFactory.currentSession.clear() + setupClass.hibernateDatastore.sessionFactory.currentSession.clear() Person person = Person.first() when: @@ -120,7 +126,7 @@ class HibernateDirtyCheckingSpec extends Specification { when: person.save(flush:true) - hibernateDatastore.sessionFactory.currentSession.clear() + setupClass.hibernateDatastore.sessionFactory.currentSession.clear() person = Person.first() then: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy index 113acc8c094..cc4f003dd29 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/HasManyWithInQuerySpec.groovy @@ -9,6 +9,7 @@ import spock.lang.* @Issue('https://github.com/grails/gorm-hibernate5/issues/78') @Rollback +//TODO Multi valued paths are only allowed for the member of operator class HasManyWithInQuerySpec extends Specification { @Shared @AutoCleanup HibernateDatastore datastore = new HibernateDatastore(getClass().getPackage()) @@ -17,7 +18,6 @@ class HasManyWithInQuerySpec extends Specification { @Shared BookService bookService = datastore.getService(BookService) - @Ignore void "test 'in' criteria"() { setupData() diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy index 572ff869acf..d611f2aff1b 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hasmany/TwoUnidirectionalHasManySpec.groovy @@ -18,6 +18,7 @@ package grails.gorm.specs.hasmany import grails.gorm.annotation.Entity import grails.gorm.annotation.JpaEntity import grails.gorm.hibernate.mapping.MappingBuilder +import grails.gorm.specs.HibernateGormDatastoreSpec import grails.gorm.transactions.Rollback import jakarta.persistence.CascadeType import jakarta.persistence.GeneratedValue @@ -30,14 +31,16 @@ import spock.lang.* * @author Graeme Rocher * @since 1.0 */ -class TwoUnidirectionalHasManySpec extends Specification { - - @Shared @AutoCleanup HibernateDatastore datastore = new HibernateDatastore(getClass().getPackage()) +//TODO: CreatedUsers sql is being run, but not added to the EcmMask instance +class TwoUnidirectionalHasManySpec extends HibernateGormDatastoreSpec { + @Override + List getDomainClasses() { + [EcmMask,EcmMaskJpa,User2,User] + } @Rollback @Issue('https://github.com/grails/grails-core/issues/10811') - @Ignore void "test two undirectional one to many references"() { when: new EcmMask(name: "test") @@ -56,7 +59,6 @@ class TwoUnidirectionalHasManySpec extends Specification { @Rollback @Issue('https://github.com/grails/grails-core/issues/10811') - @Ignore void "test two JPA undirectional one to many references"() { when: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index 0ae1435e5ea..ce07832f1eb 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -2,8 +2,7 @@ package grails.gorm.specs.hibernatequery import grails.gorm.DetachedCriteria import grails.gorm.specs.HibernateGormDatastoreSpec -import grails.gorm.tests.Person -import grails.gorm.tests.Pet +import grails.gorm.tck.* import grails.persistence.Entity import jakarta.persistence.criteria.JoinType import org.grails.datastore.mapping.query.Query @@ -126,7 +125,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { } - @Ignore("Need better implementation of Predicate") +// @Ignore("Need better implementation of Predicate") def idEq() { given: Person oldFred = new Person(firstName: "Fred", lastName: "Rogers", age: 51).save(flush: true) @@ -328,7 +327,7 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldPet == newPet } - @Ignore("Exits subquery is broken") +// @Ignore("Exits subquery is broken") /** * org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() * else if (criterion instanceof Query.Exists c) @@ -354,10 +353,9 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { */ def exists() { given: - new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) - def oldPet = new Pet(name: "Lucky") - oldBob.addToPets(oldPet) - oldBob.save(flush: true) + def fred = new Person(firstName: "Fred", lastName: "Rogers", age: 52).save(flush: true) + new Pet(name: "Lucky", owner: oldBob).save(flush:true) + petHibernateQuery.singleResult() hibernateQuery.exists(new DetachedCriteria(Pet).eq("owner", oldBob)) when: def newBob = hibernateQuery.singleResult() @@ -365,7 +363,6 @@ class HibernateQuerySpec extends HibernateGormDatastoreSpec { oldBob == newBob } - @Ignore("Exists subquery is broken") /** * org.grails.orm.hibernate.query.PredicateGenerator.getPredicates() * else if (criterion instanceof Query.NotExists c) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy index d72b7ce58d7..8992b7c3151 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyBidirectionalManyToManySpec.groovy @@ -19,6 +19,7 @@ import spock.lang.Specification /** * Created by puneetbehl on 21/03/2018. */ +//TODO Multitenancy not working class MultiTenancyBidirectionalManyToManySpec extends Specification { final Map config = [ diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy index d4804dcddcd..3e625fccfae 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/multitenancy/MultiTenancyUnidirectionalOneToManySpec.groovy @@ -13,6 +13,7 @@ import spock.lang.Specification /** * Created by graemerocher on 16/06/2017. */ +//TODO Multitenancy not working class MultiTenancyUnidirectionalOneToManySpec extends Specification { @Issue('https://github.com/grails/grails-data-mapping/issues/954') diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy index 9ae0c6346fb..1816a341b29 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/ByteBuddyProxySpec.groovy @@ -12,6 +12,7 @@ import spock.lang.PendingFeatureIf * Contains misc proxy tests using Hibenrate defaults, which is ByteBuddy. * These should all be passing for Gorm to be operating correctly with Groovy. */ +//TODO Are we still supporting Proxies? class ByteBuddyProxySpec extends HibernateGormDatastoreSpec { static HibernateProxyHandler proxyHandler = new HibernateProxyHandler() @@ -30,7 +31,7 @@ class ByteBuddyProxySpec extends HibernateGormDatastoreSpec { return team } - @Ignore("StaticTestUtil.team_id_asserts assert !Hibernate.isInitialized(team) fails") +// @Ignore("StaticTestUtil.team_id_asserts assert !Hibernate.isInitialized(team) fails") void "getId and id property checks dont initialize proxy if in a CompileStatic method"() { when: Team team = createATeam() diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy index 1aae2e55eb5..f5daac94862 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy @@ -1,17 +1,16 @@ package grails.gorm.specs.proxy +import grails.gorm.tck.Location import grails.gorm.tests.GormDatastoreSpec -import grails.gorm.tests.Location import org.grails.datastore.gorm.proxy.GroovyProxyFactory import spock.lang.Ignore /** * @author graemerocher */ +//TODO Are we still supporting Proxies? class GroovyProxySpec extends GormDatastoreSpec { - // this test is ignored because Groovy proxies are not used with Hibernate - @Ignore void "Test creation and behavior of Groovy proxies"() { given: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy index 83a1f845237..287b075735a 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/validation/SaveWithInvalidEntitySpec.groovy @@ -8,6 +8,7 @@ import spock.lang.* /** * Created by graemerocher on 03/05/2017. */ +//TODO Should this test be rewritten? class SaveWithInvalidEntitySpec extends Specification { @Shared @AutoCleanup HibernateDatastore hibernateDatastore = new HibernateDatastore(A, B) @@ -16,7 +17,6 @@ class SaveWithInvalidEntitySpec extends Specification { * This currently fails with a NPE. See explanation https://github.com/grails/grails-core/issues/10604#issuecomment-298943022 */ @Rollback - @Ignore @Issue('https://github.com/grails/grails-core/issues/10604') void "test save with an invalid entity"() { when: diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy index bb6203e3e94..3e9c313f739 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/HibernateGormStaticApiSpecification.groovy @@ -181,7 +181,7 @@ class HibernateGormStaticApiTest extends HibernateGormDatastoreSpec{ results[1] == "London" } - @Ignore("This is documented as working but fails") +//TODO: Chained Criteria def multipleCriteria() { given: def accountCriteria = { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithEventsSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithEventsSpec.groovy index 16b564f4f65..0fb105007fa 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithEventsSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/MultipleDataSourcesWithEventsSpec.groovy @@ -1,7 +1,9 @@ package org.grails.orm.hibernate.connections import grails.gorm.annotation.Entity +import grails.gorm.specs.HibernateGormDatastoreSpec import org.grails.datastore.mapping.core.DatastoreUtils +import org.grails.datastore.mapping.core.Session import org.grails.datastore.mapping.core.connections.ConnectionSource import org.grails.orm.hibernate.HibernateDatastore import org.hibernate.dialect.H2Dialect @@ -11,11 +13,16 @@ import spock.lang.Specification /** * Created by graemerocher on 20/02/2017. */ -class MultipleDataSourcesWithEventsSpec extends Specification { +//TODO Multiple data sources not working +class MultipleDataSourcesWithEventsSpec extends HibernateGormDatastoreSpec { - @Issue('https://github.com/grails/grails-core/issues/10451') - void "Test multiple data sources register the correct events"() { - given:"A configuration for multiple data sources" + @Override + List getDomainClasses() { + [EventsBook, SecondaryBook] + } + + Session configure() { + ConfigObject grailsConfig = new ConfigObject() Map config = [ 'dataSource.url':"jdbc:h2:mem:grailsDB;LOCK_TIMEOUT=10000", 'dataSource.dbCreate': 'update', @@ -27,9 +34,15 @@ class MultipleDataSourcesWithEventsSpec extends Specification { 'hibernate.hbm2ddl.auto': 'create', 'dataSources.books':[url:"jdbc:h2:mem:books;LOCK_TIMEOUT=10000"] ] + grailsConfig.putAll(config) + setupClass.setup(((TEST_CLASSES + getDomainClasses()) as Set) as List, grailsConfig, true) + } + + @Issue('https://github.com/grails/grails-core/issues/10451') + void "Test multiple data sources register the correct events"() { + given:"A configuration for multiple data sources" when:"A entity is saved with the default connection" - HibernateDatastore datastore = new HibernateDatastore(DatastoreUtils.createPropertyResolver(config),EventsBook, SecondaryBook ) EventsBook book = new EventsBook(name:"test") EventsBook.withTransaction { book.save(flush:true) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy index db374fc3348..1f2a69a8920 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/PartitionedMultiTenancySpec.groovy @@ -26,7 +26,7 @@ import spock.lang.Specification /** * Created by graemerocher on 11/07/2016. */ - +//TODO Multitenancy not working class PartitionedMultiTenancySpec extends HibernateGormDatastoreSpec { @Override diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy index 251497e22da..3d920987822 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SchemaMultiTenantSpec.groovy @@ -15,7 +15,6 @@ import spock.lang.Specification /** * Created by graemerocher on 20/07/2016. */ -@Ignore class SchemaMultiTenantSpec extends Specification { void "Test a database per tenant multi tenancy"() { given:"A configuration for multiple data sources" diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SecondLevelCacheSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SecondLevelCacheSpec.groovy index c0ca9a64b48..414b0771ea7 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SecondLevelCacheSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/org/grails/orm/hibernate/connections/SecondLevelCacheSpec.groovy @@ -20,7 +20,7 @@ class SecondLevelCacheSpec extends Specification { 'dataSource.logSql': 'true', 'hibernate.flush.mode': 'COMMIT', 'hibernate.cache.queries': 'true', - 'hibernate.cache': ['use_second_level_cache': true, 'region.factory_class': 'org.hibernate.cache.ehcache.EhCacheRegionFactory'], + 'hibernate.cache': ['use_second_level_cache': true, 'region.factory_class': 'org.hibernate.cache.jcache.internal.JCacheRegionFactory'], 'hibernate.hbm2ddl.auto': 'create', ] From 930808ed4feac806d9739ab55893788aad337a86 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Wed, 9 Apr 2025 20:13:23 -0500 Subject: [PATCH 0045/1008] code fixes --- .../test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy | 4 ++-- .../groovy/grails/gorm/specs/OptimisticLockingSpec.groovy | 4 +--- .../test/groovy/grails/gorm/specs/ReadOperationSpec.groovy | 2 +- .../grails/gorm/specs/UniqueConstraintHibernateSpec.groovy | 3 +-- .../src/test/groovy/grails/gorm/specs/ValidationSpec.groovy | 6 +----- .../specs/WithNewSessionAndExistingTransactionSpec.groovy | 2 +- .../gorm/specs/hibernatequery/HibernateQuerySpec.groovy | 2 +- .../groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy | 3 ++- 8 files changed, 10 insertions(+), 16 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy index a858df9d9de..d7884327601 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/NullValueEqualSpec.groovy @@ -1,7 +1,7 @@ package grails.gorm.specs -import grails.gorm.tck.TestEntity -import grails.gorm.tck.ChildEntity + +import grails.gorm.tests.* class NullValueEqualSpec extends HibernateGormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy index 679ce0b2626..8700191c474 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/OptimisticLockingSpec.groovy @@ -1,8 +1,6 @@ package grails.gorm.specs -import grails.gorm.tck.OptLockNotVersioned -import grails.gorm.tck.OptLockVersioned -import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.tests.* import org.springframework.orm.hibernate5.HibernateOptimisticLockingFailureException diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy index 57ee7b4dd90..0db19a4ddab 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ReadOperationSpec.groovy @@ -1,6 +1,6 @@ package grails.gorm.specs -import grails.gorm.tck.TestEntity +import grails.gorm.tests.* class ReadOperationSpec extends HibernateGormDatastoreSpec { diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy index c9152c4403a..73b6e518b88 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/UniqueConstraintHibernateSpec.groovy @@ -1,8 +1,7 @@ package grails.gorm.specs import grails.gorm.annotation.Entity -import grails.gorm.tck.GroupWithin -import grails.gorm.tck.UniqueGroup +import grails.gorm.tests.* import org.grails.datastore.gorm.GormEntity import org.grails.orm.hibernate.HibernateDatastore import org.springframework.transaction.PlatformTransactionManager diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy index e95a237f80e..708161e2b1b 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/ValidationSpec.groovy @@ -1,11 +1,7 @@ package grails.gorm.specs -import grails.gorm.tck.ChildEntity -import grails.gorm.tck.ClassWithListArgBeforeValidate -import grails.gorm.tck.ClassWithNoArgBeforeValidate -import grails.gorm.tck.ClassWithOverloadedBeforeValidate -import grails.gorm.tck.TestEntity import grails.gorm.tests.* +import grails.gorm.tests.GormDatastoreSpec import org.springframework.transaction.support.TransactionSynchronizationManager /** diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy index 93ab72cc2ee..ba3b84d71b1 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WithNewSessionAndExistingTransactionSpec.groovy @@ -1,6 +1,6 @@ package grails.gorm.specs -import grails.gorm.tck.Book +import grails.gorm.tests.* import org.grails.datastore.gorm.Setup import org.grails.orm.hibernate.GormSpec import org.grails.orm.hibernate.HibernateDatastore diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy index ce07832f1eb..8edf0b54d1f 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/hibernatequery/HibernateQuerySpec.groovy @@ -2,7 +2,7 @@ package grails.gorm.specs.hibernatequery import grails.gorm.DetachedCriteria import grails.gorm.specs.HibernateGormDatastoreSpec -import grails.gorm.tck.* +import grails.gorm.tests.* import grails.persistence.Entity import jakarta.persistence.criteria.JoinType import org.grails.datastore.mapping.query.Query diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy index f5daac94862..11b97080e57 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/proxy/GroovyProxySpec.groovy @@ -1,7 +1,8 @@ package grails.gorm.specs.proxy -import grails.gorm.tck.Location + import grails.gorm.tests.GormDatastoreSpec +import grails.gorm.tests.Location import org.grails.datastore.gorm.proxy.GroovyProxyFactory import spock.lang.Ignore From 205e5c2a4be8fe1954475988cf1043aab500ecf6 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Sun, 13 Apr 2025 20:27:08 -0500 Subject: [PATCH 0046/1008] Fixed handling associations inside of closures --- .../query/AbstractHibernateQuery.java | 24 +++++++++++++++---- .../hibernate/query/PredicateGenerator.java | 7 +++++- .../TablePerSubClassAndEmbeddedSpec.groovy | 3 +-- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java index a953445a52c..d18807919c2 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/AbstractHibernateQuery.java @@ -662,12 +662,26 @@ private Map assignJoinTables(List joinColumns, From root, } private static String aliasColumn(Map aliasMap, String associationPath, Join table) { - String column = associationPath; - if (aliasMap.containsKey(associationPath)) { - column = Optional.ofNullable(aliasMap.get(associationPath).getAlias()).orElseThrow(() -> new QueryException("Association without alias")); - table.alias(column); + // Attempt to find specific criteria configuration for this association path + DetachedAssociationCriteria criteria = aliasMap.get(associationPath); + + if (criteria != null) { + // If criteria configuration exists: + // Determine the alias: use the one from criteria if it's not null, + // otherwise default back to using the associationPath itself. + String aliasToUse = Objects.requireNonNullElse(criteria.getAlias(), associationPath); + + // Apply the determined alias explicitly to the Join object + table.alias(aliasToUse); + + // Return the alias that was determined and applied + return aliasToUse; + } else { + // If no specific criteria configuration was found, + // return the original associationPath as the implicit alias. + // We don't explicitly call table.alias() here, letting JPA/Hibernate handle defaults. + return associationPath; } - return column; } private Function projectionToJpaExpression( diff --git a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java index aa0b5ea858e..a6889f98bf1 100644 --- a/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java +++ b/grails-datastore-gorm-hibernate/src/main/groovy/org/grails/orm/hibernate/query/PredicateGenerator.java @@ -3,6 +3,8 @@ import groovy.util.logging.Slf4j; import jakarta.persistence.criteria.CriteriaQuery; import jakarta.persistence.criteria.From; +import jakarta.persistence.criteria.Join; +import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.Predicate; import jakarta.persistence.criteria.Root; import jakarta.persistence.criteria.Subquery; @@ -50,8 +52,11 @@ public static Predicate[] getPredicates(HibernateCriteriaBuilder cb, List criterionList = ((Query.Conjunction) criterion).getCriteria(); return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); } else if (criterion instanceof DetachedAssociationCriteria c) { + Join child = root_.join(c.getAssociationPath(), JoinType.LEFT); List criterionList = c.getCriteria(); - return cb.and(getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName)); + Map childTablesByName = new HashMap<>(tablesByName); + childTablesByName.put("root",child); + return cb.and(getPredicates(cb, criteriaQuery, child, criterionList, childTablesByName)); } else if (criterion instanceof Query.Negation) { List criterionList = ((Query.Negation) criterion).getCriteria(); Predicate[] predicates = getPredicates(cb, criteriaQuery, root_, criterionList, tablesByName); diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy index ad88edae7bd..a9725c35b61 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/TablePerSubClassAndEmbeddedSpec.groovy @@ -11,7 +11,6 @@ import spock.lang.Ignore * Created by graemerocher on 04/11/16. */ @ApplyDetachedCriteriaTransform -//TODO: Closure syntax not detecting that address is an embedded entity class TablePerSubClassAndEmbeddedSpec extends HibernateGormDatastoreSpec { @Override @@ -41,7 +40,7 @@ class TablePerSubClassAndEmbeddedSpec extends HibernateGormDatastoreSpec { when:"A query is parsed that queries the embedded entity" def gcl = new GroovyClassLoader() DetachedCriteria criteria = gcl.parseClass(''' -import grails.gorm.tests.* +import grails.gorm.specs.* Vendor.where { address.zip =~ '%44%' From 7f258cce1cef84b33b3e36330e27c94130dd76e3 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Thu, 17 Apr 2025 23:03:52 -0500 Subject: [PATCH 0047/1008] Fixed handling associations inside of closures --- .../compositeid/GlobalConstraintWithCompositeIdSpec.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy index 60bcf881392..c817557dcd1 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/compositeid/GlobalConstraintWithCompositeIdSpec.groovy @@ -14,7 +14,7 @@ import spock.lang.Issue /** * Created by graemerocher on 17/02/2017. */ -//TODO CompositeId not working +//TODO 2025-04-17 CompositeId not working class GlobalConstraintWithCompositeIdSpec extends HibernateGormDatastoreSpec { @Override From 9c0adf3d3feb2f733e7aac00a9f9467a3ba66cd5 Mon Sep 17 00:00:00 2001 From: Walter Duque de Estrada Date: Fri, 25 Apr 2025 23:24:54 -0500 Subject: [PATCH 0048/1008] More comments --- .../WhereQueryWithAssociationSortSpec.groovy | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy index 24d33ea80c5..bb41a3f78bb 100644 --- a/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy +++ b/grails-datastore-gorm-hibernate/src/test/groovy/grails/gorm/specs/WhereQueryWithAssociationSortSpec.groovy @@ -20,6 +20,29 @@ class WhereQueryWithAssociationSortSpec extends HibernateGormDatastoreSpec { def t2 = new Team(club: c2, name: "Arsenal First Team").save(flush:true) when:"a where query uses a sort on an association" + + /** + * 2025/04/25 + * select + t1_0.id, + t1_0.club_id, + t1_0.name, + t1_0.version + from + team t1_0 + left join + club c1_0 + on c1_0.id=t1_0.club_id, team t2_0 + join + club c2_0 + on c2_0.id=t2_0.club_id + where + c1_0.name=? + order by + lower(c2_0.name) + offset + ? rows + */ def results = Team.where { club.name == "Manchester United" }.list(sort:'club.name') From 79a0f7c3f43b208c52f3b291eac5b6f94eaaf0da Mon Sep 17 00:00:00 2001 From: James Daugherty Date: Sun, 11 May 2025 14:23:56 -0400 Subject: [PATCH 0049/1008] Remove fileds that have not been updated for hibernate6 --- grails-data-hibernate6/.github/dependabot.yml | 13 - .../.github/release-drafter.yml | 125 - grails-data-hibernate6/.github/renovate.json | 91 - .../.github/workflows/docs.yml | 57 - .../.github/workflows/gradle.yml | 83 - .../workflows/groovy-joint-workflow.yml | 140 - .../.github/workflows/release-notes.yml | 26 - .../.github/workflows/release.yml | 156 - grails-data-hibernate6/.gitignore | 26 - grails-data-hibernate6/.sdkmanrc | 3 - grails-data-hibernate6/LICENSE | 201 - .../boot-plugin/build.gradle | 38 - .../HibernateGormAutoConfiguration.groovy | 140 - .../GormCompilerAutoConfiguration.groovy | 50 - ...ils.cli.compiler.CompilerAutoConfiguration | 1 - ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../HibernateGormAutoConfigurationSpec.groovy | 75 - .../GroovyBeanDefinitionReaderSpec.groovy | 39 - grails-data-hibernate6/build.gradle | 82 - grails-data-hibernate6/buildSrc/build.gradle | 35 - .../examples/grails-data-service/build.gradle | 35 - .../grails-app/conf/application.yml | 66 - .../grails-app/conf/logback.xml | 17 - .../grails-app/conf/spring/resources.groovy | 12 - .../example/ApplicationController.groovy | 14 - .../controllers/example/UrlMappings.groovy | 17 - .../grails-app/domain/example/Book.groovy | 5 - .../grails-app/domain/example/Person.groovy | 7 - .../grails-app/domain/example/Student.groovy | 7 - .../grails-app/i18n/messages.properties | 56 - .../init/example/Application.groovy | 13 - .../grails-app/init/example/BootStrap.groovy | 14 - .../services/example/BookService.groovy | 9 - .../services/example/LibraryService.groovy | 22 - .../services/example/PersonService.groovy | 10 - .../services/example/StudentService.groovy | 27 - .../services/example/TestService.groovy | 14 - .../grails-app/views/application/index.gson | 33 - .../grails-app/views/error.gson | 6 - .../grails-app/views/errors/_errors.gson | 42 - .../grails-app/views/notFound.gson | 6 - .../grails-app/views/object/_object.gson | 5 - .../example/ServiceInjectionSpec.groovy | 21 - .../groovy/example/StudentServiceSpec.groovy | 25 - .../groovy/example/TestServiceSpec.groovy | 46 - .../groovy/example/ClassUsingAService.groovy | 14 - .../src/main/groovy/example/TestBean.groovy | 20 - .../grails-database-per-tenant/build.gradle | 38 - .../assets/images/apple-touch-icon-retina.png | Bin 14986 -> 0 bytes .../assets/images/apple-touch-icon.png | Bin 5434 -> 0 bytes .../grails-app/assets/images/favicon.ico | Bin 10134 -> 0 bytes .../grails-app/assets/images/grails_logo.png | Bin 10172 -> 0 bytes .../assets/images/skin/database_add.png | Bin 658 -> 0 bytes .../assets/images/skin/database_delete.png | Bin 659 -> 0 bytes .../assets/images/skin/database_edit.png | Bin 767 -> 0 bytes .../assets/images/skin/database_save.png | Bin 755 -> 0 bytes .../assets/images/skin/database_table.png | Bin 726 -> 0 bytes .../assets/images/skin/exclamation.png | Bin 701 -> 0 bytes .../grails-app/assets/images/skin/house.png | Bin 806 -> 0 bytes .../assets/images/skin/information.png | Bin 778 -> 0 bytes .../grails-app/assets/images/skin/shadow.jpg | Bin 300 -> 0 bytes .../assets/images/skin/sorted_asc.gif | Bin 835 -> 0 bytes .../assets/images/skin/sorted_desc.gif | Bin 834 -> 0 bytes .../grails-app/assets/images/spinner.gif | Bin 2037 -> 0 bytes .../assets/javascripts/application.js | 20 - .../assets/javascripts/jquery-2.1.3.js | 9205 ----------------- .../assets/stylesheets/application.css | 13 - .../grails-app/assets/stylesheets/errors.css | 109 - .../grails-app/assets/stylesheets/main.css | 569 - .../grails-app/assets/stylesheets/mobile.css | 82 - .../grails-app/conf/application.yml | 77 - .../grails-app/conf/logback.xml | 17 - .../controllers/example/BookController.groovy | 102 - .../controllers/example/UrlMappings.groovy | 25 - .../grails-app/domain/example/Book.groovy | 13 - .../grails-app/i18n/messages.properties | 55 - .../grails-app/i18n/messages_cs_CZ.properties | 55 - .../grails-app/i18n/messages_da.properties | 56 - .../grails-app/i18n/messages_de.properties | 55 - .../grails-app/i18n/messages_es.properties | 55 - .../grails-app/i18n/messages_fr.properties | 19 - .../grails-app/i18n/messages_it.properties | 55 - .../grails-app/i18n/messages_ja.properties | 55 - .../grails-app/i18n/messages_nb.properties | 56 - .../grails-app/i18n/messages_nl.properties | 55 - .../grails-app/i18n/messages_pl.properties | 59 - .../grails-app/i18n/messages_pt_BR.properties | 59 - .../grails-app/i18n/messages_pt_PT.properties | 34 - .../grails-app/i18n/messages_ru.properties | 31 - .../grails-app/i18n/messages_sv.properties | 55 - .../grails-app/i18n/messages_th.properties | 55 - .../grails-app/i18n/messages_zh_CN.properties | 18 - .../init/datasources/Application.groovy | 12 - .../example/AnotherBookService.groovy | 22 - .../services/example/BookService.groovy | 24 - .../grails-app/views/book/create.gsp | 38 - .../grails-app/views/book/edit.gsp | 40 - .../grails-app/views/book/index.gsp | 28 - .../grails-app/views/book/show.gsp | 31 - .../grails-app/views/error.gsp | 31 - .../grails-app/views/index.gsp | 129 - .../grails-app/views/layouts/main.gsp | 19 - .../grails-app/views/notFound.gsp | 14 - .../DatabasePerTenantIntegrationSpec.groovy | 99 - .../example/DatabasePerTenantSpec.groovy | 80 - .../build.gradle | 29 - .../grails-app/conf/application.yml | 17 - .../grails-app/conf/logback.xml | 17 - .../grails-app/domain/example/Customer.groovy | 27 - .../init/datasources/Application.groovy | 12 - .../src/test/groovy/example/ProxySpec.groovy | 41 - .../examples/grails-hibernate/build.gradle | 49 - .../assets/images/apple-touch-icon-retina.png | Bin 14986 -> 0 bytes .../assets/images/apple-touch-icon.png | Bin 5434 -> 0 bytes .../grails-app/assets/images/favicon.ico | Bin 10134 -> 0 bytes .../grails-app/assets/images/grails_logo.png | Bin 10172 -> 0 bytes .../assets/images/skin/database_add.png | Bin 658 -> 0 bytes .../assets/images/skin/database_delete.png | Bin 659 -> 0 bytes .../assets/images/skin/database_edit.png | Bin 767 -> 0 bytes .../assets/images/skin/database_save.png | Bin 755 -> 0 bytes .../assets/images/skin/database_table.png | Bin 726 -> 0 bytes .../assets/images/skin/exclamation.png | Bin 701 -> 0 bytes .../grails-app/assets/images/skin/house.png | Bin 806 -> 0 bytes .../assets/images/skin/information.png | Bin 778 -> 0 bytes .../grails-app/assets/images/skin/shadow.jpg | Bin 300 -> 0 bytes .../assets/images/skin/sorted_asc.gif | Bin 835 -> 0 bytes .../assets/images/skin/sorted_desc.gif | Bin 834 -> 0 bytes .../grails-app/assets/images/spinner.gif | Bin 2037 -> 0 bytes .../assets/javascripts/application.js | 20 - .../assets/javascripts/jquery-2.1.3.js | 9205 ----------------- .../assets/stylesheets/application.css | 13 - .../grails-app/assets/stylesheets/errors.css | 109 - .../grails-app/assets/stylesheets/main.css | 569 - .../grails-app/assets/stylesheets/mobile.css | 82 - .../grails-app/conf/application.yml | 87 - .../grails-app/conf/logback.xml | 17 - .../grails-app/conf/spring/resources.groovy | 3 - .../functional/tests/BookController.groovy | 108 - .../functional/tests/ProductController.groovy | 15 - .../functional/tests/UrlMappings.groovy | 16 - .../domain/functional/tests/Book.groovy | 10 - .../domain/functional/tests/Business.groovy | 11 - .../domain/functional/tests/Employee.groovy | 9 - .../domain/functional/tests/Person.groovy | 5 - .../domain/functional/tests/Product.groovy | 22 - .../grails-app/i18n/messages.properties | 55 - .../grails-app/i18n/messages_cs_CZ.properties | 55 - .../grails-app/i18n/messages_da.properties | 56 - .../grails-app/i18n/messages_de.properties | 55 - .../grails-app/i18n/messages_es.properties | 55 - .../grails-app/i18n/messages_fr.properties | 19 - .../grails-app/i18n/messages_it.properties | 55 - .../grails-app/i18n/messages_ja.properties | 55 - .../grails-app/i18n/messages_nb.properties | 56 - .../grails-app/i18n/messages_nl.properties | 55 - .../grails-app/i18n/messages_pl.properties | 59 - .../grails-app/i18n/messages_pt_BR.properties | 59 - .../grails-app/i18n/messages_pt_PT.properties | 34 - .../grails-app/i18n/messages_ru.properties | 31 - .../grails-app/i18n/messages_sv.properties | 55 - .../grails-app/i18n/messages_th.properties | 55 - .../grails-app/i18n/messages_zh_CN.properties | 18 - .../init/functional/tests/Application.groovy | 17 - .../init/functional/tests/BootStrap.groovy | 18 - .../functional/tests/BookService.groovy | 12 - .../grails-app/views/book/create.gsp | 38 - .../grails-app/views/book/edit.gsp | 40 - .../grails-app/views/book/index.gsp | 28 - .../grails-app/views/book/show.gsp | 31 - .../grails-app/views/error.gsp | 31 - .../grails-app/views/index.gsp | 123 - .../grails-app/views/layouts/main.gsp | 19 - .../grails-app/views/notFound.gsp | 14 - .../tests/BookControllerSpec.groovy | 27 - .../tests/CascadeValidationSpec.groovy | 28 - .../functional/tests/ProductSpec.groovy | 49 - .../src/main/groovy/another/Item.groovy | 21 - ...ibernateMappingContextConfiguration.groovy | 9 - .../tests/BookControllerUnitSpec.groovy | 163 - .../grails-multiple-datasources/build.gradle | 48 - .../grails-app/conf/application.yml | 72 - .../grails-app/conf/logback.xml | 17 - .../grails-app/domain/ds2/Book.groovy | 15 - .../grails-app/domain/example/Book.groovy | 11 - .../init/datasources/Application.groovy | 12 - .../services/example/BookService.groovy | 16 - .../MultipleDataSourcesSpec.groovy | 35 - .../build.gradle | 40 - .../assets/images/apple-touch-icon-retina.png | Bin 14986 -> 0 bytes .../assets/images/apple-touch-icon.png | Bin 5434 -> 0 bytes .../grails-app/assets/images/favicon.ico | Bin 10134 -> 0 bytes .../grails-app/assets/images/grails_logo.png | Bin 10172 -> 0 bytes .../assets/images/skin/database_add.png | Bin 658 -> 0 bytes .../assets/images/skin/database_delete.png | Bin 659 -> 0 bytes .../assets/images/skin/database_edit.png | Bin 767 -> 0 bytes .../assets/images/skin/database_save.png | Bin 755 -> 0 bytes .../assets/images/skin/database_table.png | Bin 726 -> 0 bytes .../assets/images/skin/exclamation.png | Bin 701 -> 0 bytes .../grails-app/assets/images/skin/house.png | Bin 806 -> 0 bytes .../assets/images/skin/information.png | Bin 778 -> 0 bytes .../grails-app/assets/images/skin/shadow.jpg | Bin 300 -> 0 bytes .../assets/images/skin/sorted_asc.gif | Bin 835 -> 0 bytes .../assets/images/skin/sorted_desc.gif | Bin 834 -> 0 bytes .../grails-app/assets/images/spinner.gif | Bin 2037 -> 0 bytes .../assets/javascripts/application.js | 20 - .../assets/javascripts/jquery-2.1.3.js | 9205 ----------------- .../assets/stylesheets/application.css | 13 - .../grails-app/assets/stylesheets/errors.css | 109 - .../grails-app/assets/stylesheets/main.css | 569 - .../grails-app/assets/stylesheets/mobile.css | 82 - .../grails-app/conf/application.yml | 71 - .../grails-app/conf/logback.xml | 17 - .../controllers/example/BookController.groovy | 102 - .../controllers/example/UrlMappings.groovy | 25 - .../grails-app/domain/example/Book.groovy | 14 - .../grails-app/i18n/messages.properties | 55 - .../grails-app/i18n/messages_cs_CZ.properties | 55 - .../grails-app/i18n/messages_da.properties | 56 - .../grails-app/i18n/messages_de.properties | 55 - .../grails-app/i18n/messages_es.properties | 55 - .../grails-app/i18n/messages_fr.properties | 19 - .../grails-app/i18n/messages_it.properties | 55 - .../grails-app/i18n/messages_ja.properties | 55 - .../grails-app/i18n/messages_nb.properties | 56 - .../grails-app/i18n/messages_nl.properties | 55 - .../grails-app/i18n/messages_pl.properties | 59 - .../grails-app/i18n/messages_pt_BR.properties | 59 - .../grails-app/i18n/messages_pt_PT.properties | 34 - .../grails-app/i18n/messages_ru.properties | 31 - .../grails-app/i18n/messages_sv.properties | 55 - .../grails-app/i18n/messages_th.properties | 55 - .../grails-app/i18n/messages_zh_CN.properties | 18 - .../init/datasources/Application.groovy | 10 - .../example/AnotherBookService.groovy | 21 - .../services/example/BookService.groovy | 24 - .../grails-app/views/book/create.gsp | 38 - .../grails-app/views/book/edit.gsp | 40 - .../grails-app/views/book/index.gsp | 28 - .../grails-app/views/book/show.gsp | 31 - .../grails-app/views/error.gsp | 31 - .../grails-app/views/index.gsp | 129 - .../grails-app/views/layouts/main.gsp | 19 - .../grails-app/views/notFound.gsp | 14 - ...titionedMultiTenancyIntegrationSpec.groovy | 99 - .../PartitionedMultiTenancySpec.groovy | 78 - .../grails-schema-per-tenant/build.gradle | 37 - .../assets/images/apple-touch-icon-retina.png | Bin 14986 -> 0 bytes .../assets/images/apple-touch-icon.png | Bin 5434 -> 0 bytes .../grails-app/assets/images/favicon.ico | Bin 10134 -> 0 bytes .../grails-app/assets/images/grails_logo.png | Bin 10172 -> 0 bytes .../assets/images/skin/database_add.png | Bin 658 -> 0 bytes .../assets/images/skin/database_delete.png | Bin 659 -> 0 bytes .../assets/images/skin/database_edit.png | Bin 767 -> 0 bytes .../assets/images/skin/database_save.png | Bin 755 -> 0 bytes .../assets/images/skin/database_table.png | Bin 726 -> 0 bytes .../assets/images/skin/exclamation.png | Bin 701 -> 0 bytes .../grails-app/assets/images/skin/house.png | Bin 806 -> 0 bytes .../assets/images/skin/information.png | Bin 778 -> 0 bytes .../grails-app/assets/images/skin/shadow.jpg | Bin 300 -> 0 bytes .../assets/images/skin/sorted_asc.gif | Bin 835 -> 0 bytes .../assets/images/skin/sorted_desc.gif | Bin 834 -> 0 bytes .../grails-app/assets/images/spinner.gif | Bin 2037 -> 0 bytes .../assets/javascripts/application.js | 20 - .../assets/javascripts/jquery-2.1.3.js | 9205 ----------------- .../assets/stylesheets/application.css | 13 - .../grails-app/assets/stylesheets/errors.css | 109 - .../grails-app/assets/stylesheets/main.css | 569 - .../grails-app/assets/stylesheets/mobile.css | 82 - .../grails-app/conf/application.yml | 71 - .../grails-app/conf/logback.xml | 17 - .../controllers/example/BookController.groovy | 102 - .../controllers/example/UrlMappings.groovy | 25 - .../grails-app/domain/example/Book.groovy | 13 - .../grails-app/i18n/messages.properties | 55 - .../grails-app/i18n/messages_cs_CZ.properties | 55 - .../grails-app/i18n/messages_da.properties | 56 - .../grails-app/i18n/messages_de.properties | 55 - .../grails-app/i18n/messages_es.properties | 55 - .../grails-app/i18n/messages_fr.properties | 19 - .../grails-app/i18n/messages_it.properties | 55 - .../grails-app/i18n/messages_ja.properties | 55 - .../grails-app/i18n/messages_nb.properties | 56 - .../grails-app/i18n/messages_nl.properties | 55 - .../grails-app/i18n/messages_pl.properties | 59 - .../grails-app/i18n/messages_pt_BR.properties | 59 - .../grails-app/i18n/messages_pt_PT.properties | 34 - .../grails-app/i18n/messages_ru.properties | 31 - .../grails-app/i18n/messages_sv.properties | 55 - .../grails-app/i18n/messages_th.properties | 55 - .../grails-app/i18n/messages_zh_CN.properties | 18 - .../init/datasources/Application.groovy | 12 - .../example/AnotherBookService.groovy | 21 - .../services/example/BookService.groovy | 24 - .../grails-app/views/book/create.gsp | 38 - .../grails-app/views/book/edit.gsp | 40 - .../grails-app/views/book/index.gsp | 28 - .../grails-app/views/book/show.gsp | 31 - .../grails-app/views/error.gsp | 31 - .../grails-app/views/index.gsp | 129 - .../grails-app/views/layouts/main.gsp | 19 - .../grails-app/views/notFound.gsp | 14 - .../SchemaPerTenantIntegrationSpec.groovy | 103 - .../groovy/example/SchemaPerTenantSpec.groovy | 88 - .../examples/issue450/build.gradle | 42 - .../assets/images/advancedgrails.svg | 27 - .../assets/images/apple-touch-icon-retina.png | Bin 7038 -> 0 bytes .../assets/images/apple-touch-icon.png | Bin 3077 -> 0 bytes .../assets/images/documentation.svg | 19 - .../grails-app/assets/images/favicon.ico | Bin 5558 -> 0 bytes .../images/grails-cupsonly-logo-white.svg | 26 - .../grails-app/assets/images/grails.svg | 13 - .../assets/images/skin/database_add.png | Bin 658 -> 0 bytes .../assets/images/skin/database_delete.png | Bin 659 -> 0 bytes .../assets/images/skin/database_edit.png | Bin 767 -> 0 bytes .../assets/images/skin/database_save.png | Bin 755 -> 0 bytes .../assets/images/skin/database_table.png | Bin 726 -> 0 bytes .../assets/images/skin/exclamation.png | Bin 701 -> 0 bytes .../grails-app/assets/images/skin/house.png | Bin 806 -> 0 bytes .../assets/images/skin/information.png | Bin 778 -> 0 bytes .../grails-app/assets/images/skin/shadow.jpg | Bin 300 -> 0 bytes .../assets/images/skin/sorted_asc.gif | Bin 835 -> 0 bytes .../assets/images/skin/sorted_desc.gif | Bin 834 -> 0 bytes .../grails-app/assets/images/slack.svg | 18 - .../grails-app/assets/images/spinner.gif | Bin 2037 -> 0 bytes .../assets/javascripts/application.js | 11 - .../assets/javascripts/bootstrap.bundle.js | 6461 ------------ .../javascripts/bootstrap.bundle.js.map | 1 - .../javascripts/bootstrap.bundle.min.js | 7 - .../javascripts/bootstrap.bundle.min.js.map | 1 - .../assets/javascripts/bootstrap.js | 3944 ------- .../assets/javascripts/bootstrap.js.map | 1 - .../assets/javascripts/bootstrap.min.js | 7 - .../assets/javascripts/bootstrap.min.js.map | 1 - .../assets/javascripts/jquery-3.3.1.min.js | 2 - .../javascripts/jquery-3.3.1.min.js.map | 1 - .../assets/javascripts/popper.min.js | 5 - .../assets/stylesheets/application.css | 15 - .../assets/stylesheets/bootstrap-grid.css | 1912 ---- .../assets/stylesheets/bootstrap-reboot.css | 331 - .../assets/stylesheets/bootstrap.css | 9030 ---------------- .../assets/stylesheets/bootstrap.css.map | 1 - .../assets/stylesheets/bootstrap.min.css | 7 - .../assets/stylesheets/bootstrap.min.css.map | 1 - .../grails-app/assets/stylesheets/errors.css | 109 - .../grails-app/assets/stylesheets/grails.css | 1078 -- .../grails-app/assets/stylesheets/main.css | 594 -- .../grails-app/assets/stylesheets/mobile.css | 82 - .../issue450/grails-app/conf/application.yml | 87 - .../issue450/grails-app/conf/logback.xml | 17 - .../BookController.groovy | 27 - .../multitenantcomposite/UrlMappings.groovy | 16 - .../domain/multitenantcomposite/Book.groovy | 14 - .../multitenantcomposite/Application.groovy | 13 - .../multitenantcomposite/BootStrap.groovy | 24 - .../multitenantcomposite/BookService.groovy | 11 - .../issue450/grails-app/views/book/books.gsp | 12 - .../issue450/grails-app/views/book/index.gsp | 13 - .../issue450/grails-app/views/error.gsp | 31 - .../issue450/grails-app/views/index.gsp | 77 - .../grails-app/views/layouts/main.gsp | 70 - .../issue450/grails-app/views/notFound.gsp | 14 - .../groovy/example/BookControllerSpec.groovy | 29 - .../spring-boot-hibernate/build.gradle | 29 - .../main/groovy/example/Application.groovy | 25 - .../src/main/groovy/example/Book.groovy | 8 - .../main/groovy/example/BookController.groovy | 27 - .../main/groovy/example/BookService.groovy | 8 - .../src/main/resources/application.yml | 2 - .../src/test/groovy/example/BookSpec.groovy | 23 - .../standalone-hibernate/build.gradle | 25 - .../hibernate/example/ExampleSpec.groovy | 43 - .../test/resources/simplelogger.properties | 4 - .../gradle/example-config.gradle | 3 - .../gradle/java-config.gradle | 6 - .../gradle/publish-config.gradle | 23 - .../gradle/tck-config.gradle | 71 - .../gradle/test-config.gradle | 42 - .../gradle/wrapper/gradle-wrapper.jar | Bin 43705 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 - grails-data-hibernate6/gradlew | 251 - grails-data-hibernate6/gradlew.bat | 94 - .../grails-database-migration/README.md | 51 - .../grails-database-migration/build.gradle | 73 - .../command/DbmChangelogSyncCommand.groovy | 32 - .../command/DbmChangelogSyncSqlCommand.groovy | 36 - .../command/DbmClearChecksumsCommand.groovy | 32 - .../command/DbmDbDocCommand.groovy | 33 - .../command/DbmDiffCommand.groovy | 64 - .../command/DbmDropAllCommand.groovy | 40 - .../DbmFutureRollbackCountSqlCommand.groovy | 46 - .../DbmFutureRollbackSqlCommand.groovy | 37 - .../DbmGenerateChangelogCommand.groovy | 53 - .../DbmGenerateGormChangelogCommand.groovy | 54 - .../command/DbmGormDiffCommand.groovy | 55 - .../command/DbmListLocksCommand.groovy | 53 - .../DbmMarkNextChangesetRanCommand.groovy | 32 - .../DbmMarkNextChangesetRanSqlCommand.groovy | 36 - .../DbmPreviousChangesetSqlCommand.groovy | 58 - .../command/DbmReleaseLocksCommand.groovy | 32 - .../command/DbmRollbackCommand.groovy | 39 - .../command/DbmRollbackCountCommand.groovy | 42 - .../command/DbmRollbackCountSqlCommand.groovy | 46 - .../command/DbmRollbackSqlCommand.groovy | 43 - .../command/DbmRollbackToDateCommand.groovy | 50 - .../DbmRollbackToDateSqlCommand.groovy | 62 - .../command/DbmStatusCommand.groovy | 37 - .../command/DbmTagCommand.groovy | 38 - .../command/DbmUpdateCommand.groovy | 35 - .../command/DbmUpdateCountCommand.groovy | 42 - .../command/DbmUpdateCountSqlCommand.groovy | 45 - .../command/DbmUpdateSqlCommand.groovy | 37 - .../command/DbmValidateCommand.groovy | 32 - .../grails-app/conf/application.yml | 13 - .../grails-app/conf/logback.groovy | 37 - .../grails-app/domain/testapp/Account.groovy | 6 - .../grails-app/domain/testapp/Person.groovy | 11 - .../init/databasemigration/Application.groovy | 29 - .../AutoRunWithMultipleDataSourceSpec.groovy | 61 - .../AutoRunWithSingleDataSourceSpec.groovy | 51 - .../DbUpdateCommandSpec.groovy | 69 - .../application-multiple-datasource.yml | 29 - .../application-single-datasource.yml | 18 - .../application-transaction-datasource.yml | 29 - .../changelog-account-person-init.groovy | 57 - .../resources/changelog-account-sql.groovy | 5 - .../resources/changelog-person-grails.groovy | 22 - .../resources/changelog-second.groovy | 42 - .../resources/changelog-transaction.groovy | 5 - .../resources/changelog.groovy | 56 - .../resources/logback-test.xml | 16 - .../DatabaseMigrationException.groovy | 22 - .../DatabaseMigrationGrailsPlugin.groovy | 125 - ...DatabaseMigrationTransactionManager.groovy | 125 - .../EnvironmentAwareCodeGenConfig.groovy | 34 - .../databasemigration/NoopVisitor.groovy | 24 - .../databasemigration/PluginConstants.groovy | 7 - ...tionContextDatabaseMigrationCommand.groovy | 123 - .../command/DatabaseMigrationCommand.groovy | 424 - .../command/DbmChangelogToGroovy.groovy | 78 - .../command/DbmCreateChangelog.groovy | 55 - .../ScriptDatabaseMigrationCommand.groovy | 66 - .../liquibase/ChangelogXml2Groovy.groovy | 107 - .../liquibase/DatabaseChangeLogBuilder.groovy | 127 - .../liquibase/EmbeddedJarPathHandler.groovy | 75 - .../liquibase/GormDatabase.groovy | 88 - .../liquibase/GrailsLiquibase.groovy | 102 - .../liquibase/GrailsLiquibaseFactory.groovy | 24 - .../liquibase/GroovyChange.groovy | 326 - .../liquibase/GroovyChangeLogParser.groovy | 100 - .../GroovyChangeLogSerializer.groovy | 56 - .../GroovyDiffToChangeLogCommandStep.groovy | 77 - .../GroovyGenerateChangeLogCommandStep.groovy | 97 - .../liquibase/GroovyPrecondition.groovy | 196 - .../META-INF/services/liquibase.change.Change | 1 - .../services/liquibase.command.CommandStep | 2 - .../services/liquibase.database.Database | 1 - .../services/liquibase.parser.ChangeLogParser | 1 - .../liquibase.precondition.Precondition | 1 - .../services/liquibase.resource.PathHandler | 1 - .../liquibase.serializer.ChangeLogSerializer | 1 - .../src/main/resources/migration.gdsl | 686 -- .../scripts/dbm-changelog-to-groovy.groovy | 17 - .../main/scripts/dbm-create-changelog.groovy | 16 - ...ContextDatabaseMigrationCommandSpec.groovy | 108 - .../DatabaseMigrationCommandConfigSpec.groovy | 94 - .../DatabaseMigrationCommandSpec.groovy | 57 - .../DbmChangelogSyncCommandSpec.groovy | 47 - .../DbmChangelogSyncCommandSqlSpec.groovy | 65 - .../DbmClearChecksumsCommandSpec.groovy | 43 - .../command/DbmDiffCommandSpec.groovy | 137 - .../command/DbmDropAllCommandSpec.groovy | 40 - ...bmFutureRollbackCountSqlCommandSpec.groovy | 132 - .../DbmFutureRollbackSqlCommandSpec.groovy | 103 - .../DbmGenerateChangelogCommandSpec.groovy | 114 - ...DbmGenerateGormChangelogCommandSpec.groovy | 152 - .../command/DbmGormDiffCommandSpec.groovy | 124 - .../command/DbmListLocksCommandSpec.groovy | 58 - .../DbmMarkNextChangesetRanCommandSpec.groovy | 48 - ...mMarkNextChangesetRanSqlCommandSpec.groovy | 65 - .../DbmPreviousChangesetSqlCommandSpec.groovy | 131 - .../command/DbmReleaseLocksCommandSpec.groovy | 38 - .../command/DbmRollbackCommandSpec.groovy | 97 - .../DbmRollbackCountCommandSpec.groovy | 104 - .../DbmRollbackCountSqlCommandSpec.groovy | 120 - .../command/DbmRollbackSqlCommandSpec.groovy | 113 - .../DbmRollbackToDateCommandSpec.groovy | 111 - .../DbmRollbackToDateSqlCommandSpec.groovy | 129 - .../command/DbmStatusCommandSpec.groovy | 61 - .../command/DbmUpdateCommandSpec.groovy | 117 - .../command/DbmUpdateCountCommandSpec.groovy | 98 - .../DbmUpdateCountSqlCommandSpec.groovy | 134 - .../command/DbmUpdateSqlCommandSpec.groovy | 137 - .../command/DbmValidateCommandSpec.groovy | 87 - .../ScriptDatabaseMigrationCommandSpec.groovy | 56 - .../liquibase/GroovyChangeLogSpec.groovy | 222 - .../liquibase/GroovyPreconditionSpec.groovy | 282 - .../testing/OutputCaptureExtension.groovy | 93 - .../testing/annotation/OutputCapture.groovy | 16 - .../src/test/resources/logback.groovy | 20 - .../grails-plugin/build.gradle | 59 - ...HibernateDatastoreSpringInitializer.groovy | 210 - .../hibernate/HibernateGrailsPlugin.groovy | 85 - .../commands/SchemaExportCommand.groovy | 105 - .../test/hibernate/HibernateSpec.groovy | 144 - ...ggregatePersistenceContextInterceptor.java | 117 - ...ggregatePersistenceContextInterceptor.java | 25 - .../GrailsOpenSessionInViewInterceptor.java | 84 - ...ibernatePersistenceContextInterceptor.java | 207 - ...oryAwarePersistenceContextInterceptor.java | 30 - ...rnateDatastoreSpringInitializerSpec.groovy | 113 - .../HibernateSpecOverrideSpec.groovy | 16 - .../mixin/hibernate/HibernateSpecSpec.groovy | 82 - .../src/test/resources/application.yml | 6 - grails-data-hibernate6/settings.gradle | 73 - 514 files changed, 84055 deletions(-) delete mode 100644 grails-data-hibernate6/.github/dependabot.yml delete mode 100644 grails-data-hibernate6/.github/release-drafter.yml delete mode 100644 grails-data-hibernate6/.github/renovate.json delete mode 100644 grails-data-hibernate6/.github/workflows/docs.yml delete mode 100644 grails-data-hibernate6/.github/workflows/gradle.yml delete mode 100644 grails-data-hibernate6/.github/workflows/groovy-joint-workflow.yml delete mode 100644 grails-data-hibernate6/.github/workflows/release-notes.yml delete mode 100644 grails-data-hibernate6/.github/workflows/release.yml delete mode 100644 grails-data-hibernate6/.gitignore delete mode 100644 grails-data-hibernate6/.sdkmanrc delete mode 100644 grails-data-hibernate6/LICENSE delete mode 100644 grails-data-hibernate6/boot-plugin/build.gradle delete mode 100644 grails-data-hibernate6/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfiguration.groovy delete mode 100644 grails-data-hibernate6/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/compiler/GormCompilerAutoConfiguration.groovy delete mode 100644 grails-data-hibernate6/boot-plugin/src/main/resources/META-INF/services/org.grails.cli.compiler.CompilerAutoConfiguration delete mode 100644 grails-data-hibernate6/boot-plugin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 grails-data-hibernate6/boot-plugin/src/test/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfigurationSpec.groovy delete mode 100644 grails-data-hibernate6/boot-plugin/src/test/groovy/org/springframework/bean/reader/GroovyBeanDefinitionReaderSpec.groovy delete mode 100644 grails-data-hibernate6/build.gradle delete mode 100644 grails-data-hibernate6/buildSrc/build.gradle delete mode 100644 grails-data-hibernate6/examples/grails-data-service/build.gradle delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/conf/logback.xml delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/conf/spring/resources.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/controllers/example/ApplicationController.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/controllers/example/UrlMappings.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Book.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Person.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Student.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/i18n/messages.properties delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/init/example/Application.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/init/example/BootStrap.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/BookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/LibraryService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/PersonService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/StudentService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/TestService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/views/application/index.gson delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/views/error.gson delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/views/errors/_errors.gson delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/views/notFound.gson delete mode 100644 grails-data-hibernate6/examples/grails-data-service/grails-app/views/object/_object.gson delete mode 100644 grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/ServiceInjectionSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/StudentServiceSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/TestServiceSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/src/main/groovy/example/ClassUsingAService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-data-service/src/main/groovy/example/TestBean.groovy delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/build.gradle delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/apple-touch-icon-retina.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/apple-touch-icon.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/favicon.ico delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/grails_logo.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_add.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_delete.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_edit.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_save.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_table.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/exclamation.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/house.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/information.png delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/shadow.jpg delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/sorted_asc.gif delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/sorted_desc.gif delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/spinner.gif delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/javascripts/application.js delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/javascripts/jquery-2.1.3.js delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/stylesheets/application.css delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/stylesheets/errors.css delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/stylesheets/main.css delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/stylesheets/mobile.css delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/conf/logback.xml delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/controllers/example/BookController.groovy delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/controllers/example/UrlMappings.groovy delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/domain/example/Book.groovy delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_cs_CZ.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_da.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_de.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_es.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_fr.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_it.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_ja.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_nb.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_nl.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_pl.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_pt_BR.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_pt_PT.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_ru.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_sv.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_th.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/i18n/messages_zh_CN.properties delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/init/datasources/Application.groovy delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/services/example/AnotherBookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/services/example/BookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/views/book/create.gsp delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/views/book/edit.gsp delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/views/book/index.gsp delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/views/book/show.gsp delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/views/error.gsp delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/views/index.gsp delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/views/layouts/main.gsp delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/views/notFound.gsp delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/src/integration-test/groovy/example/DatabasePerTenantIntegrationSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-database-per-tenant/src/test/groovy/example/DatabasePerTenantSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate-groovy-proxy/build.gradle delete mode 100644 grails-data-hibernate6/examples/grails-hibernate-groovy-proxy/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/examples/grails-hibernate-groovy-proxy/grails-app/conf/logback.xml delete mode 100644 grails-data-hibernate6/examples/grails-hibernate-groovy-proxy/grails-app/domain/example/Customer.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate-groovy-proxy/grails-app/init/datasources/Application.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate-groovy-proxy/src/test/groovy/example/ProxySpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/build.gradle delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/apple-touch-icon-retina.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/apple-touch-icon.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/favicon.ico delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/grails_logo.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/database_add.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/database_delete.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/database_edit.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/database_save.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/database_table.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/exclamation.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/house.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/information.png delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/shadow.jpg delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/sorted_asc.gif delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/skin/sorted_desc.gif delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/images/spinner.gif delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/javascripts/application.js delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/javascripts/jquery-2.1.3.js delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/stylesheets/application.css delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/stylesheets/errors.css delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/stylesheets/main.css delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/assets/stylesheets/mobile.css delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/conf/logback.xml delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/conf/spring/resources.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/controllers/functional/tests/BookController.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/controllers/functional/tests/ProductController.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/controllers/functional/tests/UrlMappings.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/domain/functional/tests/Book.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/domain/functional/tests/Business.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/domain/functional/tests/Employee.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/domain/functional/tests/Person.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/domain/functional/tests/Product.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_cs_CZ.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_da.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_de.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_es.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_fr.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_it.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_ja.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_nb.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_nl.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_pl.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_pt_BR.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_pt_PT.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_ru.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_sv.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_th.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/i18n/messages_zh_CN.properties delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/init/functional/tests/Application.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/init/functional/tests/BootStrap.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/services/functional/tests/BookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/views/book/create.gsp delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/views/book/edit.gsp delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/views/book/index.gsp delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/views/book/show.gsp delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/views/error.gsp delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/views/index.gsp delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/views/layouts/main.gsp delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/grails-app/views/notFound.gsp delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/src/integration-test/groovy/functional/tests/BookControllerSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/src/integration-test/groovy/functional/tests/CascadeValidationSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/src/integration-test/groovy/functional/tests/ProductSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/src/main/groovy/another/Item.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/src/main/groovy/functional/tests/CustomHibernateMappingContextConfiguration.groovy delete mode 100644 grails-data-hibernate6/examples/grails-hibernate/src/test/groovy/functional/tests/BookControllerUnitSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-multiple-datasources/build.gradle delete mode 100644 grails-data-hibernate6/examples/grails-multiple-datasources/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/examples/grails-multiple-datasources/grails-app/conf/logback.xml delete mode 100644 grails-data-hibernate6/examples/grails-multiple-datasources/grails-app/domain/ds2/Book.groovy delete mode 100644 grails-data-hibernate6/examples/grails-multiple-datasources/grails-app/domain/example/Book.groovy delete mode 100644 grails-data-hibernate6/examples/grails-multiple-datasources/grails-app/init/datasources/Application.groovy delete mode 100644 grails-data-hibernate6/examples/grails-multiple-datasources/grails-app/services/example/BookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-multiple-datasources/src/integration-test/groovy/functionaltests/MultipleDataSourcesSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/build.gradle delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/apple-touch-icon-retina.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/apple-touch-icon.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/favicon.ico delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/grails_logo.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/database_add.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/database_delete.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/database_edit.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/database_save.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/database_table.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/exclamation.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/house.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/information.png delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/shadow.jpg delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/sorted_asc.gif delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/skin/sorted_desc.gif delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/images/spinner.gif delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/javascripts/application.js delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/javascripts/jquery-2.1.3.js delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/stylesheets/application.css delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/stylesheets/errors.css delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/stylesheets/main.css delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/assets/stylesheets/mobile.css delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/conf/logback.xml delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/controllers/example/BookController.groovy delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/controllers/example/UrlMappings.groovy delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/domain/example/Book.groovy delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_cs_CZ.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_da.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_de.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_es.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_fr.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_it.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_ja.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_nb.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_nl.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_pl.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_pt_BR.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_pt_PT.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_ru.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_sv.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_th.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/i18n/messages_zh_CN.properties delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/init/datasources/Application.groovy delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/services/example/AnotherBookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/services/example/BookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/views/book/create.gsp delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/views/book/edit.gsp delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/views/book/index.gsp delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/views/book/show.gsp delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/views/error.gsp delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/views/index.gsp delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/views/layouts/main.gsp delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/grails-app/views/notFound.gsp delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/src/integration-test/groovy/example/PartitionedMultiTenancyIntegrationSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-partitioned-multi-tenancy/src/test/groovy/example/PartitionedMultiTenancySpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/build.gradle delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/apple-touch-icon-retina.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/apple-touch-icon.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/favicon.ico delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/grails_logo.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/database_add.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/database_delete.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/database_edit.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/database_save.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/database_table.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/exclamation.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/house.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/information.png delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/shadow.jpg delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/sorted_asc.gif delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/skin/sorted_desc.gif delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/images/spinner.gif delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/javascripts/application.js delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/javascripts/jquery-2.1.3.js delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/stylesheets/application.css delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/stylesheets/errors.css delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/stylesheets/main.css delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/assets/stylesheets/mobile.css delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/conf/logback.xml delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/controllers/example/BookController.groovy delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/controllers/example/UrlMappings.groovy delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/domain/example/Book.groovy delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_cs_CZ.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_da.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_de.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_es.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_fr.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_it.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_ja.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_nb.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_nl.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_pl.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_pt_BR.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_pt_PT.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_ru.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_sv.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_th.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/i18n/messages_zh_CN.properties delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/init/datasources/Application.groovy delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/services/example/AnotherBookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/services/example/BookService.groovy delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/views/book/create.gsp delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/views/book/edit.gsp delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/views/book/index.gsp delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/views/book/show.gsp delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/views/error.gsp delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/views/index.gsp delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/views/layouts/main.gsp delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/grails-app/views/notFound.gsp delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/src/integration-test/groovy/example/SchemaPerTenantIntegrationSpec.groovy delete mode 100644 grails-data-hibernate6/examples/grails-schema-per-tenant/src/test/groovy/example/SchemaPerTenantSpec.groovy delete mode 100644 grails-data-hibernate6/examples/issue450/build.gradle delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/advancedgrails.svg delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/apple-touch-icon-retina.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/apple-touch-icon.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/documentation.svg delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/favicon.ico delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/grails-cupsonly-logo-white.svg delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/grails.svg delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/database_add.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/database_delete.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/database_edit.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/database_save.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/database_table.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/exclamation.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/house.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/information.png delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/shadow.jpg delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/sorted_asc.gif delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/skin/sorted_desc.gif delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/slack.svg delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/images/spinner.gif delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/application.js delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/bootstrap.bundle.js delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/bootstrap.bundle.js.map delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/bootstrap.bundle.min.js delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/bootstrap.bundle.min.js.map delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/bootstrap.js delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/bootstrap.js.map delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/bootstrap.min.js delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/bootstrap.min.js.map delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/jquery-3.3.1.min.js delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/jquery-3.3.1.min.js.map delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/javascripts/popper.min.js delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/application.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/bootstrap-grid.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/bootstrap-reboot.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/bootstrap.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/bootstrap.css.map delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/bootstrap.min.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/bootstrap.min.css.map delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/errors.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/grails.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/main.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/assets/stylesheets/mobile.css delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/conf/logback.xml delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/controllers/multitenantcomposite/BookController.groovy delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/controllers/multitenantcomposite/UrlMappings.groovy delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/domain/multitenantcomposite/Book.groovy delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/init/multitenantcomposite/Application.groovy delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/init/multitenantcomposite/BootStrap.groovy delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/services/multitenantcomposite/BookService.groovy delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/views/book/books.gsp delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/views/book/index.gsp delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/views/error.gsp delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/views/index.gsp delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/views/layouts/main.gsp delete mode 100644 grails-data-hibernate6/examples/issue450/grails-app/views/notFound.gsp delete mode 100644 grails-data-hibernate6/examples/issue450/src/integration-test/groovy/example/BookControllerSpec.groovy delete mode 100644 grails-data-hibernate6/examples/spring-boot-hibernate/build.gradle delete mode 100644 grails-data-hibernate6/examples/spring-boot-hibernate/src/main/groovy/example/Application.groovy delete mode 100644 grails-data-hibernate6/examples/spring-boot-hibernate/src/main/groovy/example/Book.groovy delete mode 100644 grails-data-hibernate6/examples/spring-boot-hibernate/src/main/groovy/example/BookController.groovy delete mode 100644 grails-data-hibernate6/examples/spring-boot-hibernate/src/main/groovy/example/BookService.groovy delete mode 100644 grails-data-hibernate6/examples/spring-boot-hibernate/src/main/resources/application.yml delete mode 100644 grails-data-hibernate6/examples/spring-boot-hibernate/src/test/groovy/example/BookSpec.groovy delete mode 100644 grails-data-hibernate6/examples/standalone-hibernate/build.gradle delete mode 100644 grails-data-hibernate6/examples/standalone-hibernate/src/test/groovy/org/grails/hibernate/example/ExampleSpec.groovy delete mode 100644 grails-data-hibernate6/examples/standalone-hibernate/src/test/resources/simplelogger.properties delete mode 100644 grails-data-hibernate6/gradle/example-config.gradle delete mode 100644 grails-data-hibernate6/gradle/java-config.gradle delete mode 100644 grails-data-hibernate6/gradle/publish-config.gradle delete mode 100644 grails-data-hibernate6/gradle/tck-config.gradle delete mode 100644 grails-data-hibernate6/gradle/test-config.gradle delete mode 100644 grails-data-hibernate6/gradle/wrapper/gradle-wrapper.jar delete mode 100644 grails-data-hibernate6/gradle/wrapper/gradle-wrapper.properties delete mode 100755 grails-data-hibernate6/gradlew delete mode 100644 grails-data-hibernate6/gradlew.bat delete mode 100644 grails-data-hibernate6/grails-database-migration/README.md delete mode 100644 grails-data-hibernate6/grails-database-migration/build.gradle delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmChangelogSyncSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDbDocCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDiffCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmDropAllCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmGormDiffCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmListLocksCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmStatusCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmTagCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/commands/org/grails/plugins/databasemigration/command/DbmValidateCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/conf/application.yml delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/conf/logback.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/domain/testapp/Account.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/domain/testapp/Person.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/grails-app/init/databasemigration/Application.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/groovy/org/grails/plugins/databasemigration/AutoRunWithMultipleDataSourceSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/groovy/org/grails/plugins/databasemigration/AutoRunWithSingleDataSourceSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/groovy/org/grails/plugins/databasemigration/DbUpdateCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/application-multiple-datasource.yml delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/application-single-datasource.yml delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/application-transaction-datasource.yml delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/changelog-account-person-init.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/changelog-account-sql.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/changelog-person-grails.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/changelog-second.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/changelog-transaction.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/changelog.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/integration-test/resources/logback-test.xml delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationException.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationGrailsPlugin.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/DatabaseMigrationTransactionManager.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/EnvironmentAwareCodeGenConfig.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/NoopVisitor.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/PluginConstants.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmChangelogToGroovy.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/command/DbmCreateChangelog.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommand.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/ChangelogXml2Groovy.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/DatabaseChangeLogBuilder.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/EmbeddedJarPathHandler.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GormDatabase.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GrailsLiquibase.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GrailsLiquibaseFactory.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChange.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogParser.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSerializer.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyDiffToChangeLogCommandStep.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyGenerateChangeLogCommandStep.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPrecondition.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/resources/META-INF/services/liquibase.change.Change delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/resources/META-INF/services/liquibase.command.CommandStep delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/resources/META-INF/services/liquibase.database.Database delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/resources/META-INF/services/liquibase.parser.ChangeLogParser delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/resources/META-INF/services/liquibase.precondition.Precondition delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/resources/META-INF/services/liquibase.resource.PathHandler delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/resources/META-INF/services/liquibase.serializer.ChangeLogSerializer delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/resources/migration.gdsl delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/scripts/dbm-changelog-to-groovy.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/main/scripts/dbm-create-changelog.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/ApplicationContextDatabaseMigrationCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandConfigSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DatabaseMigrationCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmChangelogSyncCommandSqlSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmClearChecksumsCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDiffCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmDropAllCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackCountSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmFutureRollbackSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateChangelogCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGenerateGormChangelogCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmGormDiffCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmListLocksCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmMarkNextChangesetRanSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmPreviousChangesetSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmReleaseLocksCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackCountSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmRollbackToDateSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmStatusCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateCountSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmUpdateSqlCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/DbmValidateCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/command/ScriptDatabaseMigrationCommandSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyPreconditionSpec.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/testing/OutputCaptureExtension.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/groovy/org/grails/plugins/databasemigration/testing/annotation/OutputCapture.groovy delete mode 100644 grails-data-hibernate6/grails-database-migration/src/test/resources/logback.groovy delete mode 100644 grails-data-hibernate6/grails-plugin/build.gradle delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializer.groovy delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/grails/plugin/hibernate/HibernateGrailsPlugin.groovy delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/grails/plugin/hibernate/commands/SchemaExportCommand.groovy delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/grails/test/hibernate/HibernateSpec.groovy delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AbstractMultipleDataSourceAggregatePersistenceContextInterceptor.java delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/AggregatePersistenceContextInterceptor.java delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/GrailsOpenSessionInViewInterceptor.java delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/HibernatePersistenceContextInterceptor.java delete mode 100644 grails-data-hibernate6/grails-plugin/src/main/groovy/org/grails/plugin/hibernate/support/SessionFactoryAwarePersistenceContextInterceptor.java delete mode 100644 grails-data-hibernate6/grails-plugin/src/test/groovy/grails/orm/bootstrap/HibernateDatastoreSpringInitializerSpec.groovy delete mode 100644 grails-data-hibernate6/grails-plugin/src/test/groovy/grails/test/mixin/hibernate/HibernateSpecOverrideSpec.groovy delete mode 100644 grails-data-hibernate6/grails-plugin/src/test/groovy/grails/test/mixin/hibernate/HibernateSpecSpec.groovy delete mode 100644 grails-data-hibernate6/grails-plugin/src/test/resources/application.yml delete mode 100644 grails-data-hibernate6/settings.gradle diff --git a/grails-data-hibernate6/.github/dependabot.yml b/grails-data-hibernate6/.github/dependabot.yml deleted file mode 100644 index 133387e57f8..00000000000 --- a/grails-data-hibernate6/.github/dependabot.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: 2 -updates: -- package-ecosystem: gradle - directory: "/" - schedule: - interval: daily - open-pull-requests-limit: 10 - target-branch: 9.0.x - labels: - - "type: dependency upgrade" - ignore: - - dependency-name: "*" - update-types: ["version-update:semver-patch", "version-update:semver-minor"] diff --git a/grails-data-hibernate6/.github/release-drafter.yml b/grails-data-hibernate6/.github/release-drafter.yml deleted file mode 100644 index 982db2d4cc1..00000000000 --- a/grails-data-hibernate6/.github/release-drafter.yml +++ /dev/null @@ -1,125 +0,0 @@ -name-template: $RESOLVED_VERSION -tag-template: v$RESOLVED_VERSION -pull-request: - title-templates: - fix: '🐛 $TITLE (#$NUMBER)' - feat: '🚀 $TITLE (#$NUMBER)' - default: '$TITLE (#$NUMBER)' -autolabeler: - - label: 'bug' - branch: - - '/fix\/.+/' - title: - - '/fix/i' - - label: 'feature' - branch: - - '/feature\/.+/' - title: - - '/feat/i' - - label: 'documentation' - branch: - - '/docs\/.+/' - title: - - '/docs/i' - - label: 'maintenance' - branch: - - '/(chore|refactor|style|test|ci|perf|build)\/.+/' - title: - - '/(chore|refactor|style|test|ci|perf|build)/i' - - label: 'chore' - branch: - - '/chore\/.+/' - title: - - '/chore/i' - - label: 'refactor' - branch: - - '/refactor\/.+/' - title: - - '/refactor/i' - - label: 'style' - branch: - - '/style\/.+/' - title: - - '/style/i' - - label: 'test' - branch: - - '/test\/.+/' - title: - - '/test/i' - - label: 'ci' - branch: - - '/ci\/.+/' - title: - - '/ci/i' - - label: 'perf' - branch: - - '/perf\/.+/' - title: - - '/perf/i' - - label: 'build' - branch: - - '/build\/.+/' - title: - - '/build/i' - - label: 'deps' - branch: - - '/deps\/.+/' - title: - - '/deps/i' - - label: 'revert' - branch: - - '/revert\/.+/' - title: - - '/revert/i' -categories: - - title: '🚀 Features' - labels: - - 'feat' - - "type: enhancement" - - "type: new feature" - - "type: major" - - title: '🐛 Bug Fixes' - labels: - - 'fix' - - 'bug' - - "type: improvement" - - "type: bug" - - "type: minor" - - title: '📚 Documentation' - labels: - - 'docs' - - title: '🔧 Maintenance' - labels: - - 'maintenance' - - 'chore' - - 'refactor' - - 'style' - - 'test' - - 'ci' - - 'perf' - - 'build' - - "type: ci" - - "type: build" - - title: '⏪ Reverts' - labels: - - 'revert' -change-template: '- $TITLE @$AUTHOR (#$NUMBER)' -version-resolver: - major: - labels: - - 'type: major' - minor: - labels: - - 'type: minor' - patch: - labels: - - 'type: patch' - default: patch -template: | - ## What's Changed - - $CHANGES - - ## Contributors - - $CONTRIBUTORS diff --git a/grails-data-hibernate6/.github/renovate.json b/grails-data-hibernate6/.github/renovate.json deleted file mode 100644 index 2b7b266a985..00000000000 --- a/grails-data-hibernate6/.github/renovate.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "extends": [ - "config:base" - ], - "labels": ["type: dependency upgrade"], - "packageRules": [ - { - "matchPackagePatterns": ["*"], - "allowedVersions": "!/SNAPSHOT$/" - }, - { - "matchPackagePatterns": [ - "^org\\.apache\\.groovy" - ], - "groupName": "groovy monorepo" - }, - { - "matchPackageNames": [ - "org.slf4j:slf4j-api", - "org.slf4j:slf4j-simple", - "org.slf4j:jcl-over-slf4j" - ], - "groupName": "slf4j monorepo" - }, - { - "matchPackageNames": [ - "org.grails:grails-datastore-core", - "org.grails:grails-datastore-web", - "org.grails:grails-datastore-aync", - "org.grails:grails-datastore-gorm", - "org.grails:grails-datastore-gorm-support", - "org.grails:grails-datastore-gorm-async", - "org.grails:grails-datastore-gorm-rx", - "org.grails:grails-datastore-gorm-test", - "org.grails:grails-datastore-gorm-tck", - "org.grails:grails-datastore-gorm-validation" - ], - "groupName": "gorm-datastore monorepo" - }, - { - "matchPackageNames": [ - "org.grails:views-core", - "org.grails:views-json-testing-support", - "org.grails.plugins:views-gradle", - "org.grails.plugins:views-json", - "org.grails.plugins:views-json-templates", - "org.grails.plugins:views-markup" - ], - "groupName": "grails-views monorepo" - }, - { - "matchPackageNames": [ - "org.grails:grails-bom", - "org.grails:grails-bootstrap", - "org.grails:grails-codecs", - "org.grails:grails-console", - "org.grails:grails-core", - "org.grails:grails-databinding", - "org.grails:grails-dependencies", - "org.grails:grails-docs", - "org.grails:grails-encoder", - "org.grails:grails-gradle-model", - "org.grails:grails-logging", - "org.grails:grails-plugin-codecs", - "org.grails:grails-plugin-controllers", - "org.grails:grails-plugin-databinding", - "org.grails:grails-plugin-datasource", - "org.grails:grails-plugin-domain-class", - "org.grails:grails-plugin-i18n", - "org.grails:grails-plugin-interceptors", - "org.grails:grails-plugin-mimetypes", - "org.grails:grails-plugin-rest", - "org.grails:grails-plugin-services", - "org.grails:grails-plugin-url-mappings", - "org.grails:grails-plugin-url-validation", - "org.grails:grails-shell", - "org.grails:grails-spring", - "org.grails:grails-test", - "org.grails:grails-validation", - "org.grails:grails-web", - "org.grails:grails-web-boot", - "org.grails:grails-web-common", - "org.grails:grails-web-databinding", - "org.grails:grails-web-fileupload", - "org.grails:grails-web-mvc", - "org.grails:grails-web-url-mappings" - ], - "groupName": "grails monorepo" - } - ] -} diff --git a/grails-data-hibernate6/.github/workflows/docs.yml b/grails-data-hibernate6/.github/workflows/docs.yml deleted file mode 100644 index ca0996fd484..00000000000 --- a/grails-data-hibernate6/.github/workflows/docs.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: "Publish Docs" -on: - workflow_dispatch: - inputs: - ref: - description: 'The Tag or Branch Name' - required: true -env: - GIT_USER_NAME: grails-build - GIT_USER_EMAIL: grails-build@users.noreply.github.com -jobs: - docs: - runs-on: ubuntu-24.04 - steps: - - name: "📥 Checkout repository" - uses: actions/checkout@v4 - with: - ref: ${{ github.event.inputs.ref }} - - name: "👀 Find the project version for the checked out tag or branch" - run: | - PROJECT_VERSION=$(grep '^projectVersion=' gradle.properties | cut -d'=' -f2) - echo "PROJECT_VERSION=${PROJECT_VERSION}" >> $GITHUB_ENV - echo "Project version: ${PROJECT_VERSION}" - - name: "☕️ Setup JDK" - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: liberica - - name: "🐘 Setup Gradle" - uses: gradle/actions/setup-gradle@v4 - with: - develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - - name: "📖 Generate documentation" - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - run: ./gradlew docs:docs - - name: "👀 Determine docs target repository" - run: | - if [ "${{ github.repository }}" = "grails/grails-data-hibernate6" ]; then - DOCS_TARGET_REPOSITORY="grails/grails-data-mapping" - else - DOCS_TARGET_REPOSITORY="${{ github.repository }}" - fi - echo "DOCS_TARGET_REPOSITORY=${DOCS_TARGET_REPOSITORY}" >> $GITHUB_ENV - echo "Target Repository: ${DOCS_TARGET_REPOSITORY}" - - name: "📤 Publish documentation to Github Pages" - uses: grails/github-pages-deploy-action@v3 - env: - BETA: ${{ contains(env.PROJECT_VERSION, 'M') || contains(env.PROJECT_VERSION, 'RC') }} - BRANCH: gh-pages - COMMIT_EMAIL: ${{ env.GIT_USER_EMAIL }} - COMMIT_NAME: ${{ env.GIT_USER_NAME }} - DOC_SUB_FOLDER: hibernate - FOLDER: docs/build/docs - GH_TOKEN: ${{ secrets.GH_TOKEN }} - TARGET_REPOSITORY: ${{ env.DOCS_TARGET_REPOSITORY }} - VERSION: ${{ env.PROJECT_VERSION }} \ No newline at end of file diff --git a/grails-data-hibernate6/.github/workflows/gradle.yml b/grails-data-hibernate6/.github/workflows/gradle.yml deleted file mode 100644 index 948f144397b..00000000000 --- a/grails-data-hibernate6/.github/workflows/gradle.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: "Java CI" -on: - push: - branches: - - '[7-9]+.[0-9]+.x' - pull_request: - branches: - - '[7-9]+.[0-9]+.x' - workflow_dispatch: -env: - GIT_USER_NAME: grails-build - GIT_USER_EMAIL: grails-build@users.noreply.github.com -permissions: - packages: read -jobs: - build: - runs-on: ubuntu-24.04 - env: - GRADLE_OPTS: -Xmx1500m -Dfile.encoding=UTF-8 - steps: - - name: "📥 Checkout repository" - uses: actions/checkout@v4 - - name: "☕️ Setup JDK" - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: liberica - - name: "🐘 Setup Gradle" - uses: gradle/actions/setup-gradle@v4 - with: - develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - - name: "🔨 Run Build" - id: build - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - run: ./gradlew build --continue - publish: - if: github.event_name == 'push' - needs: 'build' - runs-on: ubuntu-24.04 - steps: - - name: "📥 Checkout repository" - uses: actions/checkout@v4 - - name: "☕️ Setup JDK" - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: liberica - - name: "🐘 Setup Gradle" - uses: gradle/actions/setup-gradle@v4 - with: - develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - - name: "📤 Publish Snapshot to repo.grails.org" - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - GRADLE_PUBLISH_RELEASE: 'false' - MAVEN_PUBLISH_USERNAME: ${{ secrets.MAVEN_PUBLISH_USERNAME }} - MAVEN_PUBLISH_PASSWORD: ${{ secrets.MAVEN_PUBLISH_PASSWORD }} - run: ./gradlew publish --no-build-cache - - name: "🔨 Build Docs" - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - run: ./gradlew docs:docs - - name: "👀 Determine docs target repository" - run: | - if [ "${{ github.repository }}" = "grails/grails-data-hibernate6" ]; then - DOCS_TARGET_REPOSITORY="grails/grails-data-mapping" - else - DOCS_TARGET_REPOSITORY="${{ github.repository }}" - fi - echo "DOCS_TARGET_REPOSITORY=${DOCS_TARGET_REPOSITORY}" >> $GITHUB_ENV - echo "Target Repository: ${DOCS_TARGET_REPOSITORY}" - - name: "📤 Publish to Github Pages" - uses: grails/github-pages-deploy-action@v3 - env: - BRANCH: gh-pages - COMMIT_EMAIL: ${{ env.GIT_USER_EMAIL }} - COMMIT_NAME: ${{ env.GIT_USER_NAME }} - DOC_FOLDER: gh-pages - DOC_SUB_FOLDER: hibernate - FOLDER: docs/build/docs - GH_TOKEN: ${{ secrets.GH_TOKEN }} - TARGET_REPOSITORY: ${{ env.DOCS_TARGET_REPOSITORY }} \ No newline at end of file diff --git a/grails-data-hibernate6/.github/workflows/groovy-joint-workflow.yml b/grails-data-hibernate6/.github/workflows/groovy-joint-workflow.yml deleted file mode 100644 index 94b3976f719..00000000000 --- a/grails-data-hibernate6/.github/workflows/groovy-joint-workflow.yml +++ /dev/null @@ -1,140 +0,0 @@ -name: "Groovy Joint Validation Build" -on: - push: - branches: - - '[8-9]+.[0-9]+.x' - pull_request: - branches: - - '[8-9]+.[0-9]+.x' - workflow_dispatch: -permissions: - contents: read - packages: read -jobs: - build_groovy: - name: "Build Groovy" - runs-on: ubuntu-24.04 - outputs: - groovyVersion: ${{ steps.groovy-version.outputs.value }} - steps: - - name: "☕️ Setup JDK" - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: liberica - - name: "🗄️ Cache local Maven repository" - uses: actions/cache@v4 - with: - path: ~/.m2/repository - key: cache-local-maven-${{ github.sha }} - - name: "📥 Checkout this project to fetch Gradle Plugin versions it uses" - uses: actions/checkout@v4 - with: - sparse-checkout-cone-mode: false - sparse-checkout: settings.gradle - - name: "📝 Store the Gradle Plugin versions used in this project" - id: gradle-plugin-versions - run: | - DEVELOCITY_PLUGIN_VERSION=$(grep -m 1 'id\s*\(\"com.gradle.develocity\"\|'"'com.gradle.develocity'"'\)\s*version' settings.gradle | sed -E "s/.*version[[:space:]]*['\"]?([0-9]+\.[0-9]+(\.[0-9]+)?)['\"]?.*/\1/" | tr -d [:space:]) - COMMON_CUSTOM_USER_DATA_PLUGIN_VERSION=$(grep -m 1 'id\s*\(\"com.gradle.common-custom-user-data-gradle-plugin\"\|'"'com.gradle.common-custom-user-data-gradle-plugin'"'\)\s*version' settings.gradle | sed -E "s/.*version[[:space:]]*['\"]?([0-9]+\.[0-9]+(\.[0-9]+)?)['\"]?.*/\1/" | tr -d [:space:]) - echo "Project uses Develocity Plugin version: $DEVELOCITY_PLUGIN_VERSION" - echo "Project uses Common Custom User Data Plugin version: $COMMON_CUSTOM_USER_DATA_PLUGIN_VERSION" - echo "develocity_plugin_version=$DEVELOCITY_PLUGIN_VERSION" >> $GITHUB_OUTPUT - echo "common_custom_user_data_plugin_version=$COMMON_CUSTOM_USER_DATA_PLUGIN_VERSION" >> $GITHUB_OUTPUT - rm settings.gradle - - name: "📥 Checkout Groovy 4_0_X (Grails 7 and later)" - run: git clone --depth 1 https://github.com/apache/groovy.git -b GROOVY_4_0_X --single-branch - - name: "🐘 Setup Gradle" - uses: gradle/actions/setup-gradle@v4 - with: - develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - - name: "📝 Store Groovy version to use when building the project" - id: groovy-version - run: | - cd groovy - GROOVY_VERSION=$(cat gradle.properties | grep groovyVersion | cut -d\= -f2 | tr -d '[:space:]') - echo "Groovy version $GROOVY_VERSION stored" - echo "value=$GROOVY_VERSION" >> $GITHUB_OUTPUT - - name: "🐘 Configure Gradle Plugins (Step 1/3)" - id: develocity-conf-1 - run: | - echo "VALUE<> $GITHUB_OUTPUT - echo "plugins { " >> $GITHUB_OUTPUT - echo " id 'com.gradle.develocity' version '${{ steps.gradle-plugin-versions.outputs.develocity_plugin_version }}'" >> $GITHUB_OUTPUT - echo " id 'com.gradle.common-custom-user-data-gradle-plugin' version '${{ steps.gradle-plugin-versions.outputs.common_custom_user_data_plugin_version }}'" >> $GITHUB_OUTPUT - echo "}" >> $GITHUB_OUTPUT - echo "" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - name: "🐘 Configure Gradle Plugins (Step 2/3)" - id: develocity-conf-2 - run: | - echo "VALUE<> $GITHUB_OUTPUT - echo "def isAuthenticated = System.getenv('DEVELOCITY_ACCESS_KEY') != null" >> $GITHUB_OUTPUT - echo "develocity {" >> $GITHUB_OUTPUT - echo " server = 'https://ge.grails.org'" >> $GITHUB_OUTPUT - echo " buildScan {" >> $GITHUB_OUTPUT - echo " tag('groovy')" >> $GITHUB_OUTPUT - echo " tag('grails-data-hibernate6')" >> $GITHUB_OUTPUT - echo " tag('grails-database-migration')" >> $GITHUB_OUTPUT - echo " publishing.onlyIf { isAuthenticated }" >> $GITHUB_OUTPUT - echo " uploadInBackground = false" >> $GITHUB_OUTPUT - echo " }" >> $GITHUB_OUTPUT - echo "}" >> $GITHUB_OUTPUT - echo "buildCache {" >> $GITHUB_OUTPUT - echo " local { enabled = false }" >> $GITHUB_OUTPUT - echo " remote(develocity.buildCache) {" >> $GITHUB_OUTPUT - echo " push = isAuthenticated" >> $GITHUB_OUTPUT - echo " enabled = true" >> $GITHUB_OUTPUT - echo " }" >> $GITHUB_OUTPUT - echo "}" >> $GITHUB_OUTPUT - echo "" >> $GITHUB_OUTPUT - echo "EOF" >> $GITHUB_OUTPUT - - name: "🐘 Configure Gradle Plugins (step 3/3)" - run: | - cd groovy - # Delete existing plugins from settings.gradle file - sed -i '32,37d' settings.gradle - # Add Develocity setup related configuration after line no 31 in settings.gradle - echo "${{ steps.develocity-conf-1.outputs.value }}" | sed -i -e "31r /dev/stdin" settings.gradle - # Delete existing buildCache configuration from gradle/build-scans.gradle file - sed -i '23,46d' gradle/build-scans.gradle - # Add Develocity setup related configuration after line no 22 in gradle/build-scans.gradle - echo "${{ steps.develocity-conf-2.outputs.value }}" | sed -i -e "22r /dev/stdin" gradle/build-scans.gradle - - name: "🔨 Publish Groovy to local maven repository (no docs)" - run: | - cd groovy - ./gradlew pTML -x groovydoc -x javadoc -x javadocAll -x groovydocAll -x asciidoc -x docGDK - - build_project: - name: "Build Project" - needs: build_groovy - runs-on: ubuntu-24.04 - permissions: - contents: read - packages: read - steps: - - name: "📥 Checkout project" - uses: actions/checkout@v4 - - name: "☕️ Setup JDK" - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: liberica - - name: "🐘 Setup Gradle" - uses: gradle/actions/setup-gradle@v4 - with: - develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - - name: "🗄️ Restore local Maven repository from cache" - uses: actions/cache@v4 - with: - path: ~/.m2/repository - key: cache-local-maven-${{ github.sha }} - - name: "🪶 Add mavenLocal repository to build" - run: sed -i 's|// mavenLocal() // Keep|mavenLocal() // Keep|' build.gradle - - name: "🔨 Build and test the project using the locally built Groovy snapshot" - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - run: > - ./gradlew build --continue - -PgroovyVersion=${{needs.build_groovy.outputs.groovyVersion}} - -x groovydoc \ No newline at end of file diff --git a/grails-data-hibernate6/.github/workflows/release-notes.yml b/grails-data-hibernate6/.github/workflows/release-notes.yml deleted file mode 100644 index e048cb81516..00000000000 --- a/grails-data-hibernate6/.github/workflows/release-notes.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: "Release Drafter" -on: - issues: - types: [closed,reopened] - push: - branches: - - '[6-9]+.[0-9]+.x' - pull_request: - types: [opened, reopened, synchronize] - pull_request_target: - types: [opened, reopened, synchronize] - workflow_dispatch: -jobs: - update_release_draft: - permissions: - # write permission is required to create a github release - contents: write - # write permission is required for autolabeler - # otherwise, read permission is required at least - pull-requests: write - runs-on: ubuntu-latest - steps: - - name: "📝 Update Release Draft" - uses: release-drafter/release-drafter@v6 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/grails-data-hibernate6/.github/workflows/release.yml b/grails-data-hibernate6/.github/workflows/release.yml deleted file mode 100644 index 172e09ea745..00000000000 --- a/grails-data-hibernate6/.github/workflows/release.yml +++ /dev/null @@ -1,156 +0,0 @@ -name: "Release" -on: - release: - types: [published] -env: - GIT_USER_NAME: grails-build - GIT_USER_EMAIL: grails-build@users.noreply.github.com -permissions: - packages: read -jobs: - publish: - name: "Publish to Sonatype Staging Repository" - outputs: - release_version: ${{ steps.release_version.outputs.value }} - target_branch: ${{ steps.extract_branch.outputs.value }} - runs-on: ubuntu-24.04 - permissions: - contents: write - packages: read - steps: - - name: "📥 Checkout repository" - uses: actions/checkout@v4 - - name: "☕️ Setup JDK" - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: liberica - - name: "🐘 Setup Gradle" - uses: gradle/actions/setup-gradle@v4 - with: - develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - - name: "⚙️ Run pre-release" - uses: grails/github-actions/pre-release@v3 - - name: "👀 Determine Target Branch" - id: extract_branch - run: | - TARGET_BRANCH=`cat $GITHUB_EVENT_PATH | jq '.release.target_commitish' | sed -e 's/^"\(.*\)"$/\1/g'` - echo "value=${TARGET_BRANCH}" >> $GITHUB_OUTPUT - echo "Target branch: ${TARGET_BRANCH}" - - name: "📝 Store the current release version" - id: release_version - run: | - RELEASE_VERSION=${GITHUB_REF:11} - echo "value=${RELEASE_VERSION}" >> $GITHUB_OUTPUT - echo "Release version: ${RELEASE_VERSION}" - - name: "🧩 Run Assemble" - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - run: ./gradlew --refresh-dependencies assemble - - name: "🔐 Generate key file for artifact signing" - env: - SECRING_FILE: ${{ secrets.SECRING_FILE }} - run: echo $SECRING_FILE | base64 -d > ${{ github.workspace }}/secring.gpg - - name: "📤 Publish to and close Sonatype staging repository" - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - GRAILS_PUBLISH_RELEASE: 'true' - NEXUS_PUBLISH_USERNAME: ${{ secrets.NEXUS_PUBLISH_USERNAME }} - NEXUS_PUBLISH_PASSWORD: ${{ secrets.NEXUS_PUBLISH_PASSWORD }} - NEXUS_PUBLISH_URL: ${{ secrets.NEXUS_PUBLISH_RELEASE_URL }} - NEXUS_PUBLISH_STAGING_PROFILE_ID: ${{ secrets.NEXUS_PUBLISH_STAGING_PROFILE_ID }} - SIGNING_KEY: ${{ secrets.SIGNING_KEY }} - SIGNING_PASSPHRASE: ${{ secrets.SIGNING_PASSPHRASE }} - run: > - ./gradlew --no-build-cache - -Psigning.secretKeyRingFile=${{ github.workspace }}/secring.gpg - publishToSonatype - closeSonatypeStagingRepository - release: - environment: release - name: "Release Sonatype Staging Repository" - needs: publish - runs-on: ubuntu-24.04 - permissions: - contents: write - packages: read - steps: - - name: "📥 Checkout repository" - uses: actions/checkout@v4 - with: - ref: v${{ needs.publish.outputs.release_version }} - - name: "☕️ Setup JDK" - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: liberica - - name: "🐘 Setup Gradle" - uses: gradle/actions/setup-gradle@v4 - with: - develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - - name: "🚀 Release Sonatype Staging Repository" - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - GRAILS_PUBLISH_RELEASE: 'true' - NEXUS_PUBLISH_USERNAME: ${{ secrets.NEXUS_PUBLISH_USERNAME }} - NEXUS_PUBLISH_PASSWORD: ${{ secrets.NEXUS_PUBLISH_PASSWORD }} - NEXUS_PUBLISH_URL: ${{ secrets.NEXUS_PUBLISH_RELEASE_URL }} - NEXUS_PUBLISH_STAGING_PROFILE_ID: ${{ secrets.NEXUS_PUBLISH_STAGING_PROFILE_ID }} - SIGNING_KEY: ${{ secrets.SIGNING_KEY }} - SIGNING_PASSPHRASE: ${{ secrets.SIGNING_PASSPHRASE }} - run: > - ./gradlew - findSonatypeStagingRepository - releaseSonatypeStagingRepository - - name: "⚙️ Run post-release" - uses: grails/github-actions/post-release@v3 - docs: - environment: release - name: "Publish Documentation" - needs: publish - runs-on: ubuntu-24.04 - permissions: - contents: write - packages: read - steps: - - name: "📥 Checkout repository" - uses: actions/checkout@v4 - with: - ref: v${{ needs.publish.outputs.release_version }} - - name: "☕️ Setup JDK" - uses: actions/setup-java@v4 - with: - java-version: 17 - distribution: liberica - - name: "🐘 Setup Gradle" - uses: gradle/actions/setup-gradle@v4 - with: - develocity-access-key: ${{ secrets.DEVELOCITY_ACCESS_KEY }} - - name: "📖 Generate documentation" - env: - GITHUB_MAVEN_PASSWORD: ${{ secrets.GITHUB_TOKEN }} - run: ./gradlew docs:docs - - name: "🛫 Export Gradle Properties" - uses: grails/github-actions/export-gradle-properties@v3 - - name: "👀 Determine docs target repository" - run: | - if [ "${{ github.repository }}" = "grails/grails-data-hibernate6" ]; then - DOCS_TARGET_REPOSITORY="grails/grails-data-mapping" - else - DOCS_TARGET_REPOSITORY="${{ github.repository }}" - fi - echo "DOCS_TARGET_REPOSITORY=${DOCS_TARGET_REPOSITORY}" >> $GITHUB_ENV - echo "Target Repository: ${DOCS_TARGET_REPOSITORY}" - - name: "📤 Publish documentation to Github Pages" - uses: grails/github-pages-deploy-action@v3 - env: - BETA: ${{ contains(needs.publish.outputs.release_version, 'M') || contains(needs.publish.outputs.release_version, 'RC') }} - TARGET_REPOSITORY: ${{ env.DOCS_TARGET_REPOSITORY }} - GH_TOKEN: ${{ secrets.GH_TOKEN }} - BRANCH: gh-pages - FOLDER: docs/build/docs - DOC_SUB_FOLDER: hibernate - DOC_FOLDER: gh-pages - COMMIT_EMAIL: ${{ env.GIT_USER_EMAIL }} - COMMIT_NAME: ${{ env.GIT_USER_NAME }} - VERSION: ${{ needs.publish.outputs.release_version }} diff --git a/grails-data-hibernate6/.gitignore b/grails-data-hibernate6/.gitignore deleted file mode 100644 index 2734a05195d..00000000000 --- a/grails-data-hibernate6/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -prodDb.mv.db -.gradle -build/ -classes/ -out/ -.idea -target/ -*.zip -*.iml -secring.gpg - -# Ignore Gradle GUI config -gradle-app.setting - -# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) -!gradle-wrapper.jar - -# Cache of project -.gradletasknamecache - -# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 -# gradle/wrapper/gradle-wrapper.properties -.DS_Store - -# Database Migration Test Database File -*.db diff --git a/grails-data-hibernate6/.sdkmanrc b/grails-data-hibernate6/.sdkmanrc deleted file mode 100644 index 865d5672d92..00000000000 --- a/grails-data-hibernate6/.sdkmanrc +++ /dev/null @@ -1,3 +0,0 @@ -java=17.0.13-librca -gradle=8.11.1 - diff --git a/grails-data-hibernate6/LICENSE b/grails-data-hibernate6/LICENSE deleted file mode 100644 index 8dada3edaf5..00000000000 --- a/grails-data-hibernate6/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - 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. diff --git a/grails-data-hibernate6/boot-plugin/build.gradle b/grails-data-hibernate6/boot-plugin/build.gradle deleted file mode 100644 index 14524f72707..00000000000 --- a/grails-data-hibernate6/boot-plugin/build.gradle +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id 'groovy' - id 'java-library' -} - -version = projectVersion -group = 'org.grails' - -ext { - apiDocs = true - snapshotPublishUrl = 'https://repo.grails.org/grails/libs-snapshots-local' -} - -dependencies { - // TODO: Clarify and clean up dependencies - implementation platform("org.grails:grails-bom:$grailsVersion") - - compileOnly "org.grails:grails-shell", { - exclude group:'org.apache.groovy', module:'groovy' - } - api "org.apache.groovy:groovy" - api "org.springframework.boot:spring-boot-autoconfigure" - api project(":grails-datastore-gorm-hibernate6") - - testImplementation "org.grails:grails-shell", { - exclude group:'org.apache.groovy', module:'groovy' - } - testImplementation "org.spockframework:spock-core" - - testRuntimeOnly "org.apache.tomcat:tomcat-jdbc" - testRuntimeOnly "com.h2database:h2" -} - -apply { - from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') - from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') - from rootProject.layout.projectDirectory.file('gradle/publish-config.gradle') -} diff --git a/grails-data-hibernate6/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfiguration.groovy b/grails-data-hibernate6/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfiguration.groovy deleted file mode 100644 index 392874122a4..00000000000 --- a/grails-data-hibernate6/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfiguration.groovy +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright (C) 2014 SpringSource - * - * 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 org.grails.datastore.gorm.boot.autoconfigure - -import groovy.transform.CompileStatic -import org.grails.datastore.gorm.events.ConfigurableApplicationContextEventPublisher -import org.grails.datastore.mapping.services.Service -import org.grails.orm.hibernate.HibernateDatastore -import org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration -import org.hibernate.SessionFactory -import org.springframework.beans.BeansException -import org.springframework.beans.factory.BeanFactory -import org.springframework.beans.factory.BeanFactoryAware -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.config.ConfigurableBeanFactory -import org.springframework.beans.factory.config.ConfigurableListableBeanFactory -import org.springframework.beans.factory.support.BeanDefinitionRegistry -import org.springframework.boot.autoconfigure.AutoConfigurationPackages -import org.springframework.boot.autoconfigure.AutoConfigureAfter -import org.springframework.boot.autoconfigure.AutoConfigureBefore -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean -import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration -import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.springframework.context.ConfigurableApplicationContext -import org.springframework.context.EnvironmentAware -import org.springframework.context.ResourceLoaderAware -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.ImportBeanDefinitionRegistrar -import org.springframework.core.env.Environment -import org.springframework.core.io.ResourceLoader -import org.springframework.core.type.AnnotationMetadata -import org.springframework.transaction.PlatformTransactionManager - -import javax.sql.DataSource -import java.beans.Introspector - -/** - * Auto configuration for GORM for Hibernate - * - * @author Graeme Rocher - * @since 1.0 - */ -@CompileStatic -@Configuration -@ConditionalOnClass(HibernateMappingContextConfiguration) -@ConditionalOnBean(DataSource) -@ConditionalOnMissingBean(type = "grails.orm.bootstrap.HibernateDatastoreSpringInitializer") -@AutoConfigureAfter(DataSourceAutoConfiguration) -@AutoConfigureBefore([HibernateJpaAutoConfiguration]) -class HibernateGormAutoConfiguration implements ApplicationContextAware,BeanFactoryAware { - - BeanFactory beanFactory - - @Autowired(required = false) - DataSource dataSource - - ConfigurableApplicationContext applicationContext - - @Bean - HibernateDatastore hibernateDatastore() { - List packageNames = AutoConfigurationPackages.get(this.beanFactory) - List packages = [] - for(name in packageNames) { - Package pkg = Package.getPackage(name) - if(pkg != null) { - packages.add(pkg) - } - } - - ConfigurableListableBeanFactory beanFactory = applicationContext.beanFactory - HibernateDatastore datastore - if(dataSource == null) { - datastore = new HibernateDatastore( - applicationContext.getEnvironment(), - new ConfigurableApplicationContextEventPublisher(applicationContext), - packages as Package[] - ) - beanFactory.registerSingleton("dataSource", datastore.getDataSource()) - } - else { - datastore = new HibernateDatastore( - dataSource, - applicationContext.getEnvironment(), - new ConfigurableApplicationContextEventPublisher(applicationContext), - packages as Package[] - ) - } - - for(Service service in datastore.getServices()) { - Class serviceClass = service.getClass() - grails.gorm.services.Service ann = serviceClass.getAnnotation(grails.gorm.services.Service) - String serviceName = ann?.name() - if(serviceName == null) { - serviceName = Introspector.decapitalize(serviceClass.simpleName) - } - if(!applicationContext.containsBean(serviceName)) { - applicationContext.beanFactory.registerSingleton( - serviceName, - service - ) - } - } - return datastore - } - - @Bean - SessionFactory sessionFactory() { - hibernateDatastore().getSessionFactory() - } - - @Bean - PlatformTransactionManager hibernateTransactionManager() { - hibernateDatastore().getTransactionManager() - } - - @Override - void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - if(!(applicationContext instanceof ConfigurableApplicationContext)) { - throw new IllegalArgumentException("Neo4jAutoConfiguration requires an instance of ConfigurableApplicationContext") - } - this.applicationContext = (ConfigurableApplicationContext)applicationContext - } -} diff --git a/grails-data-hibernate6/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/compiler/GormCompilerAutoConfiguration.groovy b/grails-data-hibernate6/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/compiler/GormCompilerAutoConfiguration.groovy deleted file mode 100644 index 2c7b6a16699..00000000000 --- a/grails-data-hibernate6/boot-plugin/src/main/groovy/org/grails/datastore/gorm/boot/compiler/GormCompilerAutoConfiguration.groovy +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (C) 2014 SpringSource - * - * 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 org.grails.datastore.gorm.boot.compiler - -import groovy.transform.CompileStatic -import org.codehaus.groovy.ast.ClassNode -import org.codehaus.groovy.control.CompilationFailedException -import org.codehaus.groovy.control.customizers.ImportCustomizer -import org.grails.cli.compiler.AstUtils -import org.grails.cli.compiler.CompilerAutoConfiguration -import org.grails.cli.compiler.DependencyCustomizer - -/** - * A compiler configuration that automatically adds the necessary imports - * - * @author Graeme Rocher - * @since 1.0 - * - */ -@CompileStatic -class GormCompilerAutoConfiguration extends CompilerAutoConfiguration{ - @Override - boolean matches(ClassNode classNode) { - return AstUtils.hasAtLeastOneAnnotation(classNode, "grails.persistence.Entity", "grails.gorm.annotation.Entity" ,"Entity") - } - - @Override - void applyDependencies(DependencyCustomizer dependencies) throws CompilationFailedException { - dependencies.ifAnyMissingClasses("grails.persistence.Entity", "grails.gorm.annotation.Entity") - .add("grails-datastore-gorm-hibernate6") - } - - @Override - void applyImports(ImportCustomizer imports) throws CompilationFailedException { - imports.addStarImports("grails.gorm", "grails.gorm.annotation") - } -} \ No newline at end of file diff --git a/grails-data-hibernate6/boot-plugin/src/main/resources/META-INF/services/org.grails.cli.compiler.CompilerAutoConfiguration b/grails-data-hibernate6/boot-plugin/src/main/resources/META-INF/services/org.grails.cli.compiler.CompilerAutoConfiguration deleted file mode 100644 index 2e0f07984fe..00000000000 --- a/grails-data-hibernate6/boot-plugin/src/main/resources/META-INF/services/org.grails.cli.compiler.CompilerAutoConfiguration +++ /dev/null @@ -1 +0,0 @@ -org.grails.datastore.gorm.boot.compiler.GormCompilerAutoConfiguration \ No newline at end of file diff --git a/grails-data-hibernate6/boot-plugin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/grails-data-hibernate6/boot-plugin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index d93153f929c..00000000000 --- a/grails-data-hibernate6/boot-plugin/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -org.grails.datastore.gorm.boot.autoconfigure.HibernateGormAutoConfiguration diff --git a/grails-data-hibernate6/boot-plugin/src/test/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfigurationSpec.groovy b/grails-data-hibernate6/boot-plugin/src/test/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfigurationSpec.groovy deleted file mode 100644 index c1998d38b04..00000000000 --- a/grails-data-hibernate6/boot-plugin/src/test/groovy/org/grails/datastore/gorm/boot/autoconfigure/HibernateGormAutoConfigurationSpec.groovy +++ /dev/null @@ -1,75 +0,0 @@ -package org.grails.datastore.gorm.boot.autoconfigure - -import grails.gorm.annotation.Entity -import org.springframework.beans.factory.support.DefaultListableBeanFactory -import org.springframework.boot.autoconfigure.AutoConfigurationPackages -import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration -import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties -import org.springframework.boot.autoconfigure.jdbc.EmbeddedDataSourceConfiguration -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Import -import org.springframework.core.env.MapPropertySource -import org.springframework.jdbc.datasource.DriverManagerDataSource -import spock.lang.Ignore -import spock.lang.Specification - -/** - * Created by graemerocher on 06/02/14. - */ -class HibernateGormAutoConfigurationSpec extends Specification{ - - protected AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - - void cleanup() { - context.close() - } - - void setup() { - - AutoConfigurationPackages.register(context, "org.grails.datastore.gorm.boot.autoconfigure") - this.context.getEnvironment().getPropertySources().addFirst(new MapPropertySource("foo", ['hibernate.hbm2ddl.auto':'create'])) - def beanFactory = this.context.defaultListableBeanFactory - beanFactory.registerSingleton("dataSource", new DriverManagerDataSource("jdbc:h2:mem:grailsDb1;LOCK_TIMEOUT=10000;DB_CLOSE_DELAY=-1", 'sa', '')) - this.context.register( TestConfiguration.class, - PropertyPlaceholderAutoConfiguration.class); - } - - void 'Test that GORM is correctly configured'() { - when:"The context is refreshed" - context.refresh() - - def result = Person.withTransaction { - Person.count() - } - - then:"GORM queries work" - result == 0 - - when:"The addTo* methods are called" - def p = new Person() - p.addToChildren(firstName:"Bob") - - then:"They work too" - p.children.size() == 1 - } - - @Configuration - @Import(HibernateGormAutoConfiguration) - static class TestConfiguration { - } - -} - - -@Entity -class Person { - String firstName - String lastName - Integer age = 18 - - Set children = [] - static hasMany = [children: Person] -} - - diff --git a/grails-data-hibernate6/boot-plugin/src/test/groovy/org/springframework/bean/reader/GroovyBeanDefinitionReaderSpec.groovy b/grails-data-hibernate6/boot-plugin/src/test/groovy/org/springframework/bean/reader/GroovyBeanDefinitionReaderSpec.groovy deleted file mode 100644 index 298132c8021..00000000000 --- a/grails-data-hibernate6/boot-plugin/src/test/groovy/org/springframework/bean/reader/GroovyBeanDefinitionReaderSpec.groovy +++ /dev/null @@ -1,39 +0,0 @@ -package org.springframework.bean.reader - -import org.springframework.beans.factory.InitializingBean -import org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader -import org.springframework.context.annotation.AnnotationConfigApplicationContext -import spock.lang.Specification - -/** - * Created by graemerocher on 06/02/14. - */ -class GroovyBeanDefinitionReaderSpec extends Specification{ - - protected AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - - void setup() { - MyBean.blah = 'foo' - } - - void "Test singletons are pre-instantiated with beans added by GroovyBeanDefinitionReader"() { - when:"The groovy reader is used" - def beanReader= new GroovyBeanDefinitionReader(context) - beanReader.beans { - myBean(MyBean) - } - - context.refresh() - - then:"The bean is pre instantiated" - MyBean.blah == 'created' - } -} -class MyBean implements InitializingBean{ - static String blah = 'foo' - - @Override - void afterPropertiesSet() throws Exception { - blah = 'created' - } -} diff --git a/grails-data-hibernate6/build.gradle b/grails-data-hibernate6/build.gradle deleted file mode 100644 index 496ee22240f..00000000000 --- a/grails-data-hibernate6/build.gradle +++ /dev/null @@ -1,82 +0,0 @@ -ext { - isCiBuild = System.getenv().containsKey('CI') -} - -String customGroovyVersion = findProperty('groovyVersion') ?: System.getenv('GROOVY_VERSION') -if (customGroovyVersion) { - logger.lifecycle('Using custom Groovy version: ', customGroovyVersion) -} - -logger.info('GORM VERSION = {}', datastoreVersion) - -static boolean isDataMappingDependency(DependencyResolveDetails details) { - return details.requested.group == 'org.grails' && - details.requested.name.startsWith('grails-datastore') && - details.requested.name != 'grails-datastore-gorm-hibernate6' -} - -allprojects { - - if (customGroovyVersion) { - configurations.configureEach { - resolutionStrategy.eachDependency { DependencyResolveDetails details -> - if (details.requested.group == 'org.apache.groovy') { - details.useVersion(customGroovyVersion) - } - } - } - } - - configurations.configureEach { - resolutionStrategy.eachDependency { DependencyResolveDetails details -> - // Use the GORM version from the datastoreVersion property, not from the grails-bom - if(isDataMappingDependency(details)) { - details.useVersion(datastoreVersion) - } - } - } - - repositories { - mavenCentral() - maven { url = 'https://repo.grails.org/grails/core' } - // mavenLocal() // Keep, this will be uncommented and used by CI (groovy-joint-workflow) - if (customGroovyVersion?.endsWith('-SNAPSHOT')) { - // Used for testing locally against the latest snapshot of Groovy - // Usage: ./gradlew build -P"groovyVersion=X.X.X-SNAPSHOT" - logger.lifecycle('Adding Groovy Snapshot Repo for project: {}, Using Groovy {}', name, customGroovyVersion) - maven { - name = 'ASF Snapshot repo' - url = 'https://repository.apache.org/content/repositories/snapshots' - } - } - if (System.getenv('GITHUB_MAVEN_PASSWORD') && !grailsVersion.endsWith('-SNAPSHOT')) { - logger.lifecycle('Adding Grails Core Staging Repo for project: {}', name) - maven { - url = 'https://maven.pkg.github.com/grails/grails-core' - credentials { - username = 'DOES_NOT_MATTER' - password = System.getenv('GITHUB_MAVEN_PASSWORD') - } - } - } - } -} - -// Workaround needed for nexus publishing bug -// version and group must be specified in the root project -// https://github.com/gradle-nexus/publish-plugin/issues/310 -version = projectVersion -group = 'this.will.be.overridden' - -def publishedProjects = [ - 'database-migration', - 'gorm-hibernate6-spring-boot', - 'grails-datastore-gorm-hibernate6', - 'grails-plugin', -] -subprojects { - if (name in publishedProjects) { - // This has to be applied here - apply plugin: 'org.grails.grails-publish' - } -} \ No newline at end of file diff --git a/grails-data-hibernate6/buildSrc/build.gradle b/grails-data-hibernate6/buildSrc/build.gradle deleted file mode 100644 index 179fd6d253f..00000000000 --- a/grails-data-hibernate6/buildSrc/build.gradle +++ /dev/null @@ -1,35 +0,0 @@ -plugins { - id 'groovy-gradle-plugin' -} - -file('../gradle.properties').withInputStream { - def props = new Properties() - props.load(it) - props.each { k, v -> ext.set(k, v) } -} - -repositories { - mavenCentral() - maven { url = 'https://repo.grails.org/grails/core' } - if (System.getenv('GITHUB_MAVEN_PASSWORD') && !grailsVersion.endsWith('-SNAPSHOT')) { - maven { - url = 'https://maven.pkg.github.com/grails/grails-core' - credentials { - username = 'DOES_NOT_MATTER' - password = System.getenv('GITHUB_MAVEN_PASSWORD') - } - } - } -} - -dependencies { - - implementation platform("org.grails:grails-bom:$grailsVersion") - - implementation "org.asciidoctor:asciidoctor-gradle-jvm:$asciidoctorGradleVersion" - implementation 'org.grails:grails-gradle-plugin' - - runtimeOnly 'com.bertramlabs.plugins:asset-pipeline-gradle' - runtimeOnly "io.github.gradle-nexus:publish-plugin:$gradleNexusPublishPluginVersion" - runtimeOnly 'org.grails.plugins:views-gradle' -} \ No newline at end of file diff --git a/grails-data-hibernate6/examples/grails-data-service/build.gradle b/grails-data-hibernate6/examples/grails-data-service/build.gradle deleted file mode 100644 index 8ad7832c0ef..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/build.gradle +++ /dev/null @@ -1,35 +0,0 @@ -plugins { - id 'org.grails.grails-web' - id 'org.grails.plugins.views-json' -} - -version = projectVersion -group = 'examples' - -dependencies { - implementation platform("org.grails:grails-bom:$grailsVersion") - - implementation project(':grails-plugin') - implementation 'org.grails:grails-core' - implementation 'org.grails.plugins:views-json' - - compileOnly 'org.slf4j:slf4j-nop' // Remove warning during Gson views compilation - - runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.zaxxer:HikariCP' - runtimeOnly 'org.grails:grails-plugin-databinding' - runtimeOnly 'org.grails:grails-plugin-i18n' - runtimeOnly 'org.grails:grails-plugin-services' - runtimeOnly 'org.grails:grails-plugin-url-mappings' - runtimeOnly 'org.springframework.boot:spring-boot-autoconfigure' - runtimeOnly 'org.springframework.boot:spring-boot-starter-logging' - runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat' - - integrationTestImplementation 'org.grails:grails-testing-support' -} - -apply { - from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') - from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') - from rootProject.layout.projectDirectory.file('gradle/example-config.gradle') -} \ No newline at end of file diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/application.yml b/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/application.yml deleted file mode 100644 index c8d02a5efa4..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/application.yml +++ /dev/null @@ -1,66 +0,0 @@ -info: - app: - name: '@info.app.name@' - version: '@info.app.version@' - grailsVersion: '@info.app.grailsVersion@' ---- -grails: - profile: rest-api - codegen: - defaultPackage: example - mime: - disable: - accept: - header: - userAgents: - - Gecko - - WebKit - - Presto - - Trident - types: - json: - - application/json - - text/json - hal: - - application/hal+json - - application/hal+xml - xml: - - text/xml - - application/xml - atom: application/atom+xml - css: text/css - csv: text/csv - js: text/javascript - rss: application/rss+xml - text: text/plain - all: '*/*' - urlmapping: - cache: - maxsize: 1000 - converters: - encoding: UTF-8 ---- -hibernate: - cache: - queries: false - use_second_level_cache: false - use_query_cache: false -dataSource: - pooled: true - driverClassName: org.h2.Driver - username: sa - password: '' - -environments: - development: - dataSource: - dbCreate: create-drop - url: jdbc:h2:mem:devDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE - test: - dataSource: - dbCreate: update - url: jdbc:h2:mem:testDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE - production: - dataSource: - dbCreate: none - url: jdbc:h2:./prodDb;LOCK_TIMEOUT=10000;DB_CLOSE_ON_EXIT=FALSE \ No newline at end of file diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/logback.xml b/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/logback.xml deleted file mode 100644 index 663389a04c9..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/logback.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - UTF-8 - %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n%wex - - - - - - - \ No newline at end of file diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/spring/resources.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/spring/resources.groovy deleted file mode 100644 index a235f2c1b9d..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/conf/spring/resources.groovy +++ /dev/null @@ -1,12 +0,0 @@ -import example.ClassUsingAService -import example.TestBean - -// Place your Spring DSL code here -beans = { - - classUsingAService(ClassUsingAService) { - testService = ref('testService') - } - - testBean(TestBean) -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/controllers/example/ApplicationController.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/controllers/example/ApplicationController.groovy deleted file mode 100644 index 0ea5d1ada3e..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/controllers/example/ApplicationController.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package example - -import grails.core.GrailsApplication -import grails.plugins.* - -class ApplicationController implements PluginManagerAware { - - GrailsApplication grailsApplication - GrailsPluginManager pluginManager - - def index() { - [grailsApplication: grailsApplication, pluginManager: pluginManager] - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/controllers/example/UrlMappings.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/controllers/example/UrlMappings.groovy deleted file mode 100644 index 04cf3cce219..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/controllers/example/UrlMappings.groovy +++ /dev/null @@ -1,17 +0,0 @@ -package example - -class UrlMappings { - - static mappings = { - delete "/$controller/$id(.$format)?"(action:"delete") - get "/$controller(.$format)?"(action:"index") - get "/$controller/$id(.$format)?"(action:"show") - post "/$controller(.$format)?"(action:"save") - put "/$controller/$id(.$format)?"(action:"update") - patch "/$controller/$id(.$format)?"(action:"patch") - - "/"(controller: 'application', action:'index') - "500"(view: '/error') - "404"(view: '/notFound') - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Book.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Book.groovy deleted file mode 100644 index a3b450b787d..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Book.groovy +++ /dev/null @@ -1,5 +0,0 @@ -package example - -class Book { - String title -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Person.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Person.groovy deleted file mode 100644 index 864ae877842..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Person.groovy +++ /dev/null @@ -1,7 +0,0 @@ -package example - -class Person { - - String firstName - String lastName -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Student.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Student.groovy deleted file mode 100644 index b1fb751f786..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/domain/example/Student.groovy +++ /dev/null @@ -1,7 +0,0 @@ -package example - -class Student { - - String firstName - String lastName -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/i18n/messages.properties b/grails-data-hibernate6/examples/grails-data-service/grails-app/i18n/messages.properties deleted file mode 100644 index b0451362110..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/i18n/messages.properties +++ /dev/null @@ -1,56 +0,0 @@ -default.doesnt.match.message=Property [{0}] of class [{1}] with value [{2}] does not match the required pattern [{3}] -default.invalid.url.message=Property [{0}] of class [{1}] with value [{2}] is not a valid URL -default.invalid.creditCard.message=Property [{0}] of class [{1}] with value [{2}] is not a valid credit card number -default.invalid.email.message=Property [{0}] of class [{1}] with value [{2}] is not a valid e-mail address -default.invalid.range.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid range from [{3}] to [{4}] -default.invalid.size.message=Property [{0}] of class [{1}] with value [{2}] does not fall within the valid size range from [{3}] to [{4}] -default.invalid.max.message=Property [{0}] of class [{1}] with value [{2}] exceeds maximum value [{3}] -default.invalid.min.message=Property [{0}] of class [{1}] with value [{2}] is less than minimum value [{3}] -default.invalid.max.size.message=Property [{0}] of class [{1}] with value [{2}] exceeds the maximum size of [{3}] -default.invalid.min.size.message=Property [{0}] of class [{1}] with value [{2}] is less than the minimum size of [{3}] -default.invalid.validator.message=Property [{0}] of class [{1}] with value [{2}] does not pass custom validation -default.not.inlist.message=Property [{0}] of class [{1}] with value [{2}] is not contained within the list [{3}] -default.blank.message=Property [{0}] of class [{1}] cannot be blank -default.not.equal.message=Property [{0}] of class [{1}] with value [{2}] cannot equal [{3}] -default.null.message=Property [{0}] of class [{1}] cannot be null -default.not.unique.message=Property [{0}] of class [{1}] with value [{2}] must be unique - -default.paginate.prev=Previous -default.paginate.next=Next -default.boolean.true=True -default.boolean.false=False -default.date.format=yyyy-MM-dd HH:mm:ss z -default.number.format=0 - -default.created.message={0} {1} created -default.updated.message={0} {1} updated -default.deleted.message={0} {1} deleted -default.not.deleted.message={0} {1} could not be deleted -default.not.found.message={0} not found with id {1} -default.optimistic.locking.failure=Another user has updated this {0} while you were editing - -default.home.label=Home -default.list.label={0} List -default.add.label=Add {0} -default.new.label=New {0} -default.create.label=Create {0} -default.show.label=Show {0} -default.edit.label=Edit {0} - -default.button.create.label=Create -default.button.edit.label=Edit -default.button.update.label=Update -default.button.delete.label=Delete -default.button.delete.confirm.message=Are you sure? - -# Data binding errors. Use "typeMismatch.$className.$propertyName to customize (eg typeMismatch.Book.author) -typeMismatch.java.net.URL=Property {0} must be a valid URL -typeMismatch.java.net.URI=Property {0} must be a valid URI -typeMismatch.java.util.Date=Property {0} must be a valid Date -typeMismatch.java.lang.Double=Property {0} must be a valid number -typeMismatch.java.lang.Integer=Property {0} must be a valid number -typeMismatch.java.lang.Long=Property {0} must be a valid number -typeMismatch.java.lang.Short=Property {0} must be a valid number -typeMismatch.java.math.BigDecimal=Property {0} must be a valid number -typeMismatch.java.math.BigInteger=Property {0} must be a valid number -typeMismatch=Property {0} is type-mismatched diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/init/example/Application.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/init/example/Application.groovy deleted file mode 100644 index 0396c4b8c9c..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/init/example/Application.groovy +++ /dev/null @@ -1,13 +0,0 @@ -package example - -import grails.boot.GrailsApp -import grails.boot.config.GrailsAutoConfiguration - -import groovy.transform.CompileStatic - -@CompileStatic -class Application extends GrailsAutoConfiguration { - static void main(String[] args) { - GrailsApp.run(Application, args) - } -} \ No newline at end of file diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/init/example/BootStrap.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/init/example/BootStrap.groovy deleted file mode 100644 index 71ba0d21e4b..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/init/example/BootStrap.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package example - -import jakarta.servlet.ServletContext - -class BootStrap { - - ServletContext servletContext - - def init = { - } - - def destroy = { - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/BookService.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/BookService.groovy deleted file mode 100644 index 5b6a0eb728d..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/BookService.groovy +++ /dev/null @@ -1,9 +0,0 @@ -package example - -import grails.gorm.services.Service - -@Service(Book) -interface BookService { - - Book get(Serializable id) -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/LibraryService.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/LibraryService.groovy deleted file mode 100644 index 3ed9eadd886..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/LibraryService.groovy +++ /dev/null @@ -1,22 +0,0 @@ -package example - -import grails.gorm.transactions.Transactional - -@Transactional -class LibraryService { - - BookService bookService - PersonService personService - - @Transactional(readOnly = true) - Boolean bookExists(Serializable id) { - assert bookService != null - bookService.get(id) - } - - Person addMember(String firstName, String lastName) { - assert personService != null - personService.save(firstName, lastName) - } - -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/PersonService.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/PersonService.groovy deleted file mode 100644 index 643d427a07f..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/PersonService.groovy +++ /dev/null @@ -1,10 +0,0 @@ -package example - -import grails.gorm.services.Service - -@Service(Person) -abstract class PersonService { - - abstract Person save(String firstName, String lastName) - -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/StudentService.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/StudentService.groovy deleted file mode 100644 index 267263bf96c..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/StudentService.groovy +++ /dev/null @@ -1,27 +0,0 @@ -package example - -import grails.gorm.multitenancy.TenantService -import grails.gorm.services.Service -import grails.gorm.transactions.TransactionService -import grails.gorm.transactions.Transactional -import org.springframework.beans.factory.annotation.Autowired - -@Service(Student) -abstract class StudentService { - - @Autowired - TransactionService transactionService - - @Autowired - TenantService tenantService - - @Autowired - TestService testServiceBean - - abstract Student get(Serializable id) - - @Transactional - List booksAllocated(Serializable studentId) { - assert testServiceBean != null - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/TestService.groovy b/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/TestService.groovy deleted file mode 100644 index 233fa65342e..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/services/example/TestService.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package example - -class TestService { - - LibraryService libraryService - - Boolean testDataService(Serializable id) { - libraryService.bookExists(id) - } - - Person save(String firstName, String lastName) { - libraryService.addMember(firstName, lastName) - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/application/index.gson b/grails-data-hibernate6/examples/grails-data-service/grails-app/views/application/index.gson deleted file mode 100644 index 61f96439a87..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/application/index.gson +++ /dev/null @@ -1,33 +0,0 @@ -import grails.core.* -import grails.util.* -import grails.plugins.* -import org.grails.core.artefact.* - -model { - GrailsApplication grailsApplication - GrailsPluginManager pluginManager -} - -json { - message "Welcome to Grails!" - environment Environment.current.name - appversion grailsApplication.metadata.getApplicationVersion() - grailsversion GrailsUtil.grailsVersion - appprofile grailsApplication.config.getProperty('grails.profile') - groovyversion GroovySystem.getVersion() - jvmversion System.getProperty('java.version') - reloadingagentenabled Environment.reloadingAgentEnabled - artefacts ( - controllers: grailsApplication.getArtefactInfo(ControllerArtefactHandler.TYPE).classesByName.size(), - domains: grailsApplication.getArtefactInfo(DomainClassArtefactHandler.TYPE).classesByName.size(), - services: grailsApplication.getArtefactInfo(ServiceArtefactHandler.TYPE).classesByName.size() - ) - controllers grailsApplication.getArtefacts(ControllerArtefactHandler.TYPE), { GrailsClass c -> - name c.fullName - logicalPropertyName c.logicalPropertyName - } - plugins pluginManager.allPlugins, { GrailsPlugin plugin -> - name plugin.name - version plugin.version - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/error.gson b/grails-data-hibernate6/examples/grails-data-service/grails-app/views/error.gson deleted file mode 100644 index 94488283e6d..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/error.gson +++ /dev/null @@ -1,6 +0,0 @@ -response.status 500 - -json { - message "Internal server error" - error 500 -} \ No newline at end of file diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/errors/_errors.gson b/grails-data-hibernate6/examples/grails-data-service/grails-app/views/errors/_errors.gson deleted file mode 100644 index c1ae732d371..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/errors/_errors.gson +++ /dev/null @@ -1,42 +0,0 @@ -import org.springframework.validation.* - -/** - * Renders validation errors according to vnd.error: https://github.com/blongden/vnd.error - */ -model { - Errors errors -} - -response.status UNPROCESSABLE_ENTITY - -json { - Errors errorsObject = (Errors)this.errors - def allErrors = errorsObject.allErrors - int errorCount = allErrors.size() - def resourcePath = g.link(resource:request.uri, absolute:false) - def resourceLink = g.link(resource:request.uri, absolute:true) - if(errorCount == 1) { - def error = allErrors.iterator().next() - message messageSource.getMessage(error, locale) - path resourcePath - _links { - self { - href resourceLink - } - } - } - else { - total errorCount - _embedded { - errors(allErrors) { ObjectError error -> - message messageSource.getMessage(error, locale) - path resourcePath - _links { - self { - href resourceLink - } - } - } - } - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/notFound.gson b/grails-data-hibernate6/examples/grails-data-service/grails-app/views/notFound.gson deleted file mode 100644 index 1a710b2671a..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/notFound.gson +++ /dev/null @@ -1,6 +0,0 @@ -response.status 404 - -json { - message "Not Found" - error 404 -} \ No newline at end of file diff --git a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/object/_object.gson b/grails-data-hibernate6/examples/grails-data-service/grails-app/views/object/_object.gson deleted file mode 100644 index 114568f77c2..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/grails-app/views/object/_object.gson +++ /dev/null @@ -1,5 +0,0 @@ -import groovy.transform.* - -@Field Object object - -json g.render(object) diff --git a/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/ServiceInjectionSpec.groovy b/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/ServiceInjectionSpec.groovy deleted file mode 100644 index 9c5e2e0a618..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/ServiceInjectionSpec.groovy +++ /dev/null @@ -1,21 +0,0 @@ -package example - -import grails.testing.mixin.integration.Integration -import spock.lang.Issue -import spock.lang.Specification - -@Integration -class ServiceInjectionSpec extends Specification { - - ClassUsingAService classUsingAService - - @Issue('https://github.com/grails/gorm-hibernate5/issues/202') - void 'data-service is injected correctly'() { - when: - classUsingAService.doSomethingWithTheService() - - then: - noExceptionThrown() - } - -} diff --git a/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/StudentServiceSpec.groovy b/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/StudentServiceSpec.groovy deleted file mode 100644 index 20320a9c46a..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/StudentServiceSpec.groovy +++ /dev/null @@ -1,25 +0,0 @@ -package example - -import grails.gorm.transactions.Rollback -import grails.testing.mixin.integration.Integration -import spock.lang.Specification - -@Integration -@Rollback -class StudentServiceSpec extends Specification { - - StudentService studentService - - void "test regular service autowire by type in a Data Service"() { - expect: - studentService.testServiceBean != null - studentService.testServiceBean.libraryService != null - - } - - void "test TenantService and TransactionService are not null"() { - expect: - studentService.transactionService != null - studentService.tenantService != null - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/TestServiceSpec.groovy b/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/TestServiceSpec.groovy deleted file mode 100644 index 759725c5a33..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/src/integration-test/groovy/example/TestServiceSpec.groovy +++ /dev/null @@ -1,46 +0,0 @@ -package example - -import grails.gorm.transactions.Rollback -import grails.testing.mixin.integration.Integration -import org.springframework.beans.factory.annotation.Autowired -import spock.lang.Specification - -@Integration -@Rollback -class TestServiceSpec extends Specification { - - TestService testService - TestBean testBean - ClassUsingAService classUsingAService - - @Autowired - List bookServiceList - - void "test data-service is loaded correctly"() { - when: - classUsingAService.doSomethingWithTheService() - - and: - testService.testDataService() - - then: - noExceptionThrown() - } - - void "test autowire by type"() { - - expect: - testBean.bookRepo != null - } - - void "test autowire by name works"() { - - expect: - testBean.bookService != null - } - - void "test that there is only one bookService"() { - expect: - bookServiceList.size() == 1 - } -} diff --git a/grails-data-hibernate6/examples/grails-data-service/src/main/groovy/example/ClassUsingAService.groovy b/grails-data-hibernate6/examples/grails-data-service/src/main/groovy/example/ClassUsingAService.groovy deleted file mode 100644 index d549e5b12a9..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/src/main/groovy/example/ClassUsingAService.groovy +++ /dev/null @@ -1,14 +0,0 @@ -package example - -import groovy.transform.CompileStatic - -@CompileStatic -class ClassUsingAService { - - TestService testService - - void doSomethingWithTheService() { - testService.testDataService(1l) - } - -} diff --git a/grails-data-hibernate6/examples/grails-data-service/src/main/groovy/example/TestBean.groovy b/grails-data-hibernate6/examples/grails-data-service/src/main/groovy/example/TestBean.groovy deleted file mode 100644 index 1892732243a..00000000000 --- a/grails-data-hibernate6/examples/grails-data-service/src/main/groovy/example/TestBean.groovy +++ /dev/null @@ -1,20 +0,0 @@ -package example - -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.beans.factory.annotation.Qualifier - -class TestBean { - - @Autowired - BookService bookRepo - - @Autowired - @Qualifier("bookService") - def bookService - - void doSomething() { - assert bookRepo != null - bookRepo.get(1l) - } - -} diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/build.gradle b/grails-data-hibernate6/examples/grails-database-per-tenant/build.gradle deleted file mode 100644 index 27d4041b289..00000000000 --- a/grails-data-hibernate6/examples/grails-database-per-tenant/build.gradle +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id 'org.grails.grails-web' - id 'org.grails.grails-gsp' - id 'com.bertramlabs.asset-pipeline' -} - -version = projectVersion -group = 'examples' - -dependencies { - implementation platform("org.grails:grails-bom:$grailsVersion") - - implementation project(':grails-plugin') - implementation 'org.grails:grails-core' - implementation 'org.grails:grails-plugin-rest' - implementation 'org.grails.plugins:gsp' - - runtimeOnly 'com.bertramlabs.plugins:asset-pipeline-grails' - runtimeOnly 'com.h2database:h2' - runtimeOnly 'com.zaxxer:HikariCP' - runtimeOnly 'org.grails:grails-plugin-databinding' - runtimeOnly 'org.grails:grails-plugin-i18n' - runtimeOnly 'org.grails:grails-plugin-services' - runtimeOnly 'org.grails:grails-plugin-url-mappings' - runtimeOnly 'org.grails.plugins:fields' - runtimeOnly 'org.springframework.boot:spring-boot-autoconfigure' - runtimeOnly 'org.springframework.boot:spring-boot-starter-logging' - runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat' - - testImplementation 'org.grails:grails-gorm-testing-support' - testImplementation 'org.spockframework:spock-core' -} - -apply { - from rootProject.layout.projectDirectory.file('gradle/java-config.gradle') - from rootProject.layout.projectDirectory.file('gradle/test-config.gradle') - from rootProject.layout.projectDirectory.file('gradle/example-config.gradle') -} diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/apple-touch-icon-retina.png b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/apple-touch-icon-retina.png deleted file mode 100644 index 5cc83edbe69203eaaf7d64e5b2596de6e01fff29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14986 zcmV;5I(5Z~P)SDzwewn_tty;y3?Hvrjoj+mQ$xro$sEiy36aE zC=?3r|9D71|NdfM!{fmFi+#2GNS3ERl3MkxlmV6mOB7eFT9v%$qKg_|c=?5~tsSjH zy1P2+bA?>0Q&z%6|38o2s z5DI`ML0CWmbS{}lu1F=*3o_~SyxQve+2h7G&HA_VFL-16Vbck42xJa{Lb5O}kpW(qOOhGHR05GyflDS6j(`e~B_PuB zf`9;7Adrs0764B^S8(|rAcg4iiIz+%`%+DH?bA~x?fU4QzrSa8LqmgsXjC{&BxQe? z;iCqmg7=jZhCcehU#GXUw|+72a?_GomqBzX#x#HffIWzy6;p1l9rS&&9BLqIL**>Kk}flQSmW@UzIWkIZ~MwgU)car1}Z7N zlysYi4;#qTj2Sbs$9(aaqt~rp`>lK`w|}bAxpXDKBZygm#V8;en8_j#Q=CRQz4|FN zNe~IBoE|(B6jX0o@k&mq#FGaPWL~@y(=A{q^k5z^&lDhm4ry1OV7l&3<`d2JwL@+= z_2e^ubIErvSpjJVD8bz3fPPp&rWP(-nAvaIen&U2Uvsg`6n0Nnc>o1O1u$(O8ck#O z>Ag{=QvxU;#%rZ`B0=?2s{rajj7Wj=EO9g-2_U=>U2j@&HI3JO>zoU({^r@|uL(dTn3$Ypa};&GwG!JJNV-U7(v(SiFL{6ArTKJjTDlqq zRq#L$V472@Os7dqsq{vIrvU1@2=K5b+O$d_b+<~dgeP*%L@yDLDAT~MeGqR%n!o`} zu94jIL_iWm^GJFp^9Ck7l3tnX%)>M3orvx9*2LNoLr4Ge_rJR5`n~qri#uNPOoGWY zd);bbTLPK>@;P4~dgtwT{6}}b<17G}%2X$cK+IGCJONU{OJ|Eg6mR6l2H-`YVrq@N z(matsB66CQ9S>*(qs*!FM%Xj}k)U$JqZ^+PNP?KxHIwTk()7$80I6VlKsySqs|{yE zF7xK@Q$GIPhwpg)IrLy&X>_ZtpW6aR+AuSAr?H2wT=V{~la+<0Obq}ei1flrY#%@~ zplJdL@Y3`^f(VaH`%MnL(mXN6-KqyvEZ+QHesbZDy9younyF1Bvj8xSsWgj7@G?~jV5TA^;PswXIlcPGDb?0UdYPbP z*w8k<%u|maAyt5t6=`gMyeUP7R;xUe8@RH2wJDYW(i8nUsbH!%(mNGMfJi{$nE(^~ zsYQG5{;6-?bMxaf(S=R1r10%6yLN6(AT!ernKt3&*Iu~URpj=~!V3vvraGx00>DgV z$`L?%Vv3;B1DO_2q<6+3>h!75#K72zO#pozh^9QXJdwlysLm(YEGmO_iKgWx!DgIx zxmJ2Gd2K0EECB4mPPUsg1d~8w-RuPIY%6q+XdH9tbANf`f2ymi37`SWG(B~TgslN2 z?T{HiW!%Bb*1UIfs=6?uq6Xl}bV?A_3nLIYt;*V{o=NZoKu)ckK5fc`P%$tLGA+vR z6~MSW28GO89(x~~L>_4Mkz5a;G>YX!{5T6Z1?O`LsCXuKuLfpE&h>C=MV=sbx92>N z0JAmkvdP*9etGeA-#Y53<2lt5O!G|A%??`{NSYx#YQnJ7n%mZ1jj6PvqL!Wr0Da6< zrCb)CsB0rY6%f@Eb&Z4<;xZ%Jb=nZc@USF;dY>9THne9nfP(2$+ZeD)Jzf+RoFHC? z^r2}vX-uY-(@Qbs_H+Y0UR&b2(mYb8R!pz5RvMT9l3*6Pvu~Vn;yGu0|Gdi}cUynp$?) zfybSG&1JW~1}Pz!oN6~2%q;~ZuhuGtj;;M+N22XQdSPWP0IPxb5ll{})kwn|WrHI- zRRxiG*^&C|y<$UgT%0~ZJe8#6^kDgZH!u;ua(i(K3hTTOC3+_a#S%&Z^sLe-N`sSY zD8W>Z%z2OWK+0MPFaadN>}+$*)Asq?88=@2mlx19oMPeIn+E2V05Z9B>C%ebKefw` zx?J1&*}9~FsOuuY!<4EZ5>OAMY;;f#kK`tXL5?_>_c6864UBoJND$kqERmyyD%Ve+ zEDGzSQi@O!0~i9U?LCjr_-4@wAYxgFO_6MVuwHh_r3e8=RsgcoK=Ih_(jq3Vge zR*Z}aDT4wqm_E^eWKi=SDf1O#bUAo1LVi0DtllVjybz--@zq8Bc{bJGGw`ydn_%*q zl2a?GO|MuhJ6dwCeFJE#Yx%@p2cL2CRhtjy<^V~xD~3*JxVXE}^1aG>Y-%u_Rxkp* z3Qna4rUy`_SZs9Yg=QcFa8oxhVn_({HuQ2s`Q*?Ldm6ltMZQs7-W$LeKGc=v$Mlc# zB6$$aOBP<1s7KnR2*HC_0#t(8v0lL3aLA{opZKd^{E?5x=#gO@@S3@)KvM7QsL4bA zsikZE6;<_#gm|KOBSB2-+9=+r)2o1psZ;=yfvb*v0w|U-1I3pRkujk_m_}9#%%Hxx z6)O#6KV7+t+g=lvwqp z>E}%U{UMDK}}H35k5$_lvwz>9l6Z{mO3 zz|aIZ-=$1-=w%d}LV40lrHCj>Tc)&a$RDnM?8*8pZNm!RjfoY-Vp+jDDuPrWVWM20 z5GlwopTu=BZzJNhA&I=K!lkk5AUw23Zp3Z(UHiMKlRkdj^v|ER8U-w5#LZjT41x3? zHpL?|dmpmw1 z3O1_3i7ydLQ5773u^JJO9z6YPpE?&!@iI$M+$c_i@kpvz**L!HI+yJ_xvBwPSg)Q~ zNg&~kya7l zp{HGc#e+|y1-+6UX;g)(sG{RWkq)>sO;fi!A)o9#nHT(ai9x_L;t~Vt2t=%j^qgot zfFKzZMolUn!!w>X^JU@%NUJxXT-p?$?JQ%kHuU0TiT7FisBe+)<#-UI_EN{bAcy*t z$PyjcUldgi3yNe=DFkgF%myrza;@VdIPN2=B+^3>#Y2_iMoQ|HIZs`F??X2YLo@DS z=$%H9EFT8yk?EsOIcnT9&p-ILih4J+sv!k$M8tHU-pHvH9w}378q+DKQSDF&2W|b+ zQ2x9MdBU_cE^S-HBStr&G?F(Mi;DV-{moHDn;41oK*qFqrQ87UAhMAd7YQ0mrcfF`@Icl_UL*YGHDTM5bQ!NP z4~+ZM&SfnP^gyymr&3Rr_T(vwUMCqx*q&(uq-SN=cRVHqQ1!rFEHD`#ADDA5Q3X5F zE4eH&+8Wy4y=MB?&imX!P$l$8rm0@9Fc2U!JMBI8A9BgA9bj41|V9w`BojIin0v2gw3yE9F7D41jFQ0fc=rQwpHfE8sd6i?PGDO#29e zw3p-cDb`B?4CRV0!t2M3G~QwtIR>D}_3~&JK7Xwwh_I_|gqSCo05$RIn=^j&+FLKx zpq+uqDVDKU*cgzh8~%Jl_3Gy3zlc1M0P=$0)M3aA32f|<_r?D*ZEo%&UDV*ncMgsp?9D>uW zL_giGTD$0+`yak#I9Lrtqh5-V{(wyV{O1?dw|1<%Kta@XQJ*Iw?LCo{@6i~528IDB zc~MwLR|;UrPZq-j z45ES<4zIi5XAyb4|v*eZ?xN+?INo$Ad`E`ghz49?Pi$HqtD9Zqh?BZ=#f%P&EXW>g;J>9s|Bd?M0DN0Z6jeq>vX#nyH zG^Zz8)3dVZYkdNoy#H+37p!8c2o4ke&~!q^JW2OKgLSfSJRkw zF~zP~xAfFSi)O=TqbZhPMvho+jbvG>x%Gpu+ImPT(RA76RSk>E0KB#2B4hH^kA4Cya?>5%dHME7UJ6A2!@kRHgXRq}Y#4bNrt ztm+LQg~^!)#ok-{W+;1`r_Jz2`%}PpjBW|uRV{Cdo#f>9Cpd@)ulGiZkGu#VZO%Y4b*h3JR<|TYl5Qff<)+0EDng{ZIQ@Xsq6^^GGd`il*i;+^objh}V!K#;v zI@p#OGrZCM`ZgY;TY`7l`d3{p-!1@h+uh4nW;dZ8V06rvvMVZa$BY2VeuSWkhbEtx zdB=%hDFxErB8}8eUHr@QhUAmopX6^a#3KoyMF1+#7uhkI!~jysk~7WoEMD`PTidog z>foc0FtCjFr<3s*9SraMRSye@#kPv=Mp==UBCWUb^qwre(v~ruX4OO2x2`+{tOSxy z7}3xp*}-1KZ}$xWTLdE0A&^X`nm4RIoFK{uhhU;HFEbQa?4H0ipgS<4ux^BA%>NT!`IO5Y zQFCh_N&zX?pYa$i$75y2W7NvaQR8`M&6BwNT30-C*$x#A1vJ^oV$&%9D9vUzg3BE& z_awxEplTX4@xWuh-3!cu7pMRl0?D6)r@M2VpB2#H+5#Xc?mA>Z`JXTN z5qK0pO*<_3@3`4ZA4Sc!4Q5p9)$&HIoV2ve@C`}V2_WJXfE_+s z1CZb;fa(llN0g`?nIJlN)J2cv3`u7a?@YS(&gMPAApjaRj}#!6t$1(G*c$;Ho`M;O zq}Ev}fC?VZHC06TkRer%Ex09XXSvswJPeKxCm2{p`_saBj1GpEZJu9v8Jgt89?|*- zW6(YkfZjG{Q&P_$CxES=Y0QEOq^DTsa{11QE7mRnv@w`=i$~Dy>}lO44eHvsxy4`#sWPw!b=Oi8HM1mwr!qk>sl#bl7X`z-w949%nE6 ztNY{2-@=oCh3>)EFL%f6b@2dO4xFt&K&-BmmXlt}WBGybws)^}&o2B0?1blv>3a8t zsn>%xlxx~&*;5O?>*lYHL<0h8VCoM~^_JYa_T|_Z3~mRy>*&w9UA8+&dVG4`^=`pR{+ev-gi^zo=EGh~ z>q_&3;iXNUoc{yY+5LfxbH8!l95jgRucK!zpuyV~@()SCM8~2t$t>v|Y~=@wCxTtP z5!Azu#O2rhPeU@18%hsU07>HiviKs{7r`Oa4b}RGl5_4xaQg8K=n} zC|%t;+jZwRpsnBS(&lJPl+3vlP`t66+t9=+A7hVP-Mo5x0TJLSm}o2@g4?f;A{1xb zn=2k4sBT4k6Gt52KDpzmqUciWVsCo>EQjmXBA&r!HV1(I`WmR*CC$&dr{-TQV@f5` z?z59GcXbup_b0l~y5%h|i5$6}1Q+eiAk!-_5XX`k6NQDII#yXEqLS(8Y#qT34R6?z z5=8l9M5N#d-+`IE>|xj5y&g>mA3nFszqy@894N}oU->jV^DC~Sd&@t39w-nT!KU&q zZJy!&`sTT~Yt;oCrQD|{{utBhCkAg6(IMv+uDL$~k3tkB-Ujs`dR)@L#3l0e5esq= zkoZGvRrJINJT~&6k}I5AyK}AX`FCz&UxN-Q{IS&&_WEzP({KfI!K!E6wa=V@>2~Fy zW%UJsm4^bY%&66s=2>oKM$7TeU2%td_|0$Nnyw9Y%3?bGPq*`S#~SOP>HIbKy5@fa<~V`au;)XGaKHzZFl z_>p_&ogcVdp%eB>xkDyhiW8F$?>8-U^{mGWTE7(VN*_Xq?NO5w5b0=$aIi!opIx$K z4ll^XaRHkq@VCK-D2VEn3EUnsP=(VoQdRCkd-5Ibp*JpNc9Q}<^B?!T((N_oL^)BK z+m^cjedc&KW5EqL7YBYTuhj6CHySEeT4s5p8{^&3`JTIX_UUf!ia!c#27g@k(8*W0 z3BwKxn+`ht_xG-Fow?Ow2R0^noK9(HUXy~z+^Jq^j^^Bw)e8(r+4V@rg?zr2z}YlP z)FrQSRHzqh9{T2rN8I0++&O5)tw9o-gCjon19#Xi-@_LGviM`S?e2luKft>ACHFz= zB4g`C&G1HhF$4w1V>GDhl{6ls#=vXDxhrmWcfNX@Th;msj9YLGRb$=JyWZ@^5B;pM zZ4zCy_F>!rxJ|$d0n`E&Ddn6gfdw()%u3p_ei@#NNFZ#)8_oPHIKoWu*hm`s3SVX* zA}is6H-6&YSv|w&HjV5(_Dk-xegELLtJ_7Cd3W`5?pIG7=AL}(O4o%q@dg?U0Hgi2 zGajRT@vhkLs{8Znr(i1mKDPXPER}FOk2uav-|bE}yk^(FnhmIY#fHD(zU+5kY_5p} z!i=o;Hw>f>2ZATg1u8gXc+_A(a#z|Dfy740@Q>J*KFv^}wh-gZRqWVqd*z?qtMC2U zWNs222@t=$?``g&o&Mcbq^dD>w*kn@+*OYq=$@bd8|;$TiCiQ^S{(kwTgWhKh=cmARa9hexx-m*mysvA6uwolxnbU_+uTb_ ze+ucq!R%<%gdT+{_^H=0P#j>qIOmf3+yT7zAi{}*f6Gy0M-V@ z>!`^T@1kfS5(cCjRyXtm^2z|&kUV5FFquTT&e!aWQ?ESt_T^UZFdeRPf0=WE``wGj zyE)76!=0N=y9<=Zo9gecd&NEc)_2^@MOTVWRE>J@ro`Q|&UDMxy^0dAx1{2Ofn_C@ zH_CEe*uS*+zcCg&F)?V!pSk$w?xDF~b4#0_<%3)kF(^tM7p;BJJv{GJ_Y~H{mac`O zy8+04%$}MiAf|_?A^p+PVrwi}sO4aBV<1y>JB(8+;VO(D^Rd-0&wD}@_2@IhSyj#m z=|D9qbP(hH@EpNF8=3EF*O1q|^`@8*jJlpNi_;G2|-=PZzczoWEV1#FJ zW4$?IRXwN=RmLBm0pGo^eZ!sp$%nA{;17FaKtr&kqRiogw)wb2^&`mRV>v3#^O{D} zu)O63xBTsyco1IaCJa5&?LPW!SCbv(Yx^b}Iv2Yam;4y(?8|b~fO<=`Cd|`TLWQ6v z&c|%j1p1J$UOi2!v*}8{V@g9vq~;P%`oh;&!oOOujq+8#A^21gJuCFp1&F5-7Rf_- zQC^bFO2F@l@QCMWclT@O;7x(|d}-h0=>@;QtAzJQAV&Rgc8F#O4lwCjI^K6P-l4bl z9}HNdyhHQoTjz?Q_2SvjE)b*r`MxlS$^#Uw000_ANklT?!=pNngQLRn^gu zDA8b3YoV!WN)PVdFILdm0{4s@{8(mEuI#7JTANSg$%!&XGBS{^$Gy;btNtYUz7B7%xgBz6$M*0-iUFieVB9hQ5?)!h&`z3yN2W!9A>+d2 z!9Q47Q`xu_I-pWx1SAWx6%}vr;lDtcKu!e7v56U--Wm7L=YmqpX(R{+UQmS1*IKs*4{_B{)H{}CeAKsSyzC2c zL+87=6rv4#hgRH+ZR^qBL$WOdsBEOwK2jtNRlXmaj8W?%J1T>=Lwf;{PKLkF!!HI+ z9J}8_2;yLQ))xagYQ*^0j8V@3aOBlRLq&Wa)YB_Sqf-$az4vj@Vjw9G_)xx~v;0#N z?ov0vNR(q8b~AuLibo0` zGlxz)t|gt!%!|<{pr}A&={P!TEKj8XApiMJ4M0^YPzW6u5BgxAy#gQ5>ScuJCVd)! z+CQ53fl+?Eev%)bZom&``U?hZKCe4ZktrvM0?4-1QKxK<2^nRIbZ53AUH-0BCW&Xg zWdP)9U2X%TAhJ)|Q*|&KMHJ<TFJoiQkA!PLO9A{GG{4xVj1kFP9RGBICI2_u-FD4M-XwPx~`S1~fl<_>NB)fC?z)Wi%#7v~KwUQQ@)x zqFe@Jd_3a<07lmJzUhr75=PeXE%vxQGX_{(Zi7Vc0w7+208JYY(Mfd7xIq20V&jgj0#UX?)>L-J&88?4io@XP$8bzlQwYGr$|Ami^@$g zHMr`}_DL9GxZ~rXzQV}5J*1y#z%)W6R|l^b@Wn6j^2te>pMwoT2wqSOz$-1=ht-eaCL_X(X#+Cy$U_b|c0*;R`e|`vEG3+q`Ee5dDQ7ZMp>i7-Y9A}+m0}tH z0YJNeAKQ3< z$pQ8KF=2Aqhm4y>g-)aD4-7^2N{_0WR@7F_ZLK%@z_2RzT+r+g(3 zVB(8EqlZp;5-qWFDGwy2MwKInHQgs){N|a!&+PfHv~hlw!FolC(oz-xC}6|@>g-)` zlSdrQzWNLVWc&Jkbt5BZG*|-w^u+^^^0<}Jt+l+ za`hIqow)e1X|fi&9a65FsBC2IG(0V-RyiJwsGq367$^mhAhP>Xz|{-wYiSnY=$ zaKV#cE%HX@X%`Eu6fnPX{15&LPt@sE=4N$o*}YO3Fq(2~91R|6y8}bj$Y%hOe|XJg zM~~cC*mcyYU|~mmg-<2f?zLz(P%aU-L&E{lbz}%yxxOm!!bI__Mt|MWU^6Jdq4U={*NX~J;O{$JRDdwF-s$Gadzz9|er^vr1B-Xr2m04k?O zr*a{Hx|wipuN}@59;xo<&@|*=c+E~?Kn0MhsS!+;_Mt}RAjULK>m|_uH5xMP&~OlR zflPXVj3ow8jjpoQ(0m=S+D#gMMku1s^iIRhP+OpJ2w*&Y(oWiUY)|s)7^P1fc(p(P z(NZ9ziUamK>RNo!J15^q^m8;_oJLUtaG)N%5&-q=rgxG@ z<4}0x#NkKuIry-GXX{=&oD&ZWLQIzN#fB*0r+z!*2SQC!RSq<3W0X8iLym-ez1M0U zXaJH=#s=RMS{<&Tgy9_lM5xiR%eL58=L*oT)!lv)fRrIi9mJs89r2_$05 z)yzBLuq$Sv*t{{q3T3$vNVa9AFkE={HE(CrHIK_5w(G*D^!RB#2;_&OV*r_=dfsC| z)q{9;Q$dYn+I!45#3(2pP#8b#2sfg3cP~F~!oJk-vHUTOpNScK$^bQL43@92nBW>K zcY+Wa8^klj03zkfGw{ZphkxBf42bSL{9o}DAG>3@grNLl03+~ZR*1)9dhqTVKPt-4 zGIe8*+BACF4d@tK&j=&KO7JQLGDJH!Vay)C(@(VP^vX266iSr>=sm^{T+S%35f$c( zyiG$6f(`=@>|w_ther(rKyP$ZMJEaQ#xx!zdbvmb)vv@5A}2aAY?`IP6Rx&$j2l_EceK&5L6DXLYI&ngL%sm$(%|e3pcoW21a)=m zb8hyE|H8f8fxWWA`@V0ky4B>x8$9G7lW`kn6s*lx4mmG}m zxT_N%K9kS;!k)RRMW-Bj{bQ&kfaO4>SHWw&0hkE_?`rdPblxhdIODsMFKEv#|7P8g zjH|;JcxoHcuC@{1gT&u`VK9aK_@lgB|3SI9oZLM7NKI``Yd)TaBwxgbjO9J8NHw_W zyFZ2-?fhYq1{;sj{>sU-s`YQ~*+r+TXp zWG^Y_!P^K)-iT>g*X`D=&AIh!^ZA{3_~N-=Jp4D$fQff=N+Zt}f{Qt&d@!$+v*2qd z{MT>tUCEX5EkvFvIAiz;S{i~%sVW?>2MHb`_dvaZG=$b^z42SuG=xOqBd?FrKFS2; zs7K?eqtAjzH<*}SUKv%CNf^+>tM_)ptM^g;`p|>TWBqvPP<{s*kI~yCR$cUs>p4D} zp0c<^=y)&yu`NFw%Gg*t`4)iqJQ&RzODS=Z&=-(&S8J3zaIa&U$Bo|Y#{^G4IV)7Z z_^ksB0rbj2z(4@B^)CWX2F1bo(U~#gtcp}CyAR7bPL4nJz(|f)$Le(>70B^p;w;78Grh5s-ae?XF{=qxz=z_V6MY#z?EPz~ zQjjcfG}ek9P-F);s`gOqNb%&NkM)mj4J3jQ0mC7Lb}A_P#<;f7`5_p)Od`R@}v^H6I1Ge)Za%m zh{nRSGM^W1NGG?C$ecCX&O$ z#(*Smkyj$$^Ye3OT$4==y;nZ`EP!&Cm6M0iG=!~x(V%5e7@ibB0`nF%>&s%Ji1(EM zNW;)bbCzF?pA+CmLags27+6O8V3T6Lb^g|xD{v|DM68!LG#RAdKwl{{a4`_|KEDwn zpGY+TB~w-|)$f4a=!xyEt}tfUp_l%{{+GRs7NPSPm{um&jVd)h_H`W@b7+dX@tQJ= z$m`4O{KYTSUwXqazfV_o>{*L%N!H-nvIgIi*cb_>Iq^iK4HJ18E=kfcfI~AM?HBBs(G!5 z8==uxT$#2qQdJO%Fbot(w&BGSK@=cKAAjklQMWyK-XF5n-4l3|fI!v&)GBD=(0%`^Bx@3}d=r@Izm%4C! ztr>skZ58eyEyEq8`EFh3>nL04rJ^ryXzf!wx3txfS#|LMdImNP0W|QGU&m>(bnHM0 zJN_1exDHP?3ghlS``DR3#h(nc3w{GK1d-dyvfe2D*qO@A0D|4|F)*`tJ$A{2hi6{? z$EuqAcD40seDoQB0!)6pf}Y7xJO~WT7ihKSBOc+`T%Q1XW;+?oa7MLHlgnPbJb&^O z@r3|Jaw&nJc@U(WhZsPqLJ_BT-wgcHOb$_7=6pE`$0Q))3$85yvCuu@`7@4q_WY`< zq3x(P0L=r#Jg3$^1Me6QCQukHW7bI=cj!g$u5VfW^_g>Sx+$5=Hztxf0g$^)f+>ST zI`lXlml-ZEYz7Rmlp$t8+ zsjST=i^Z1iN3L#!fE0H4tpJfzD*htQ-%mK?u8RT?XtRSy+;RX!DynlMYGj&Cx*B}ZyON&i9mEWw)EnIw3h~C)bPT?M!Okrm zpBUzWF@F(XKLFYksQg|ZW*CrV({TNhVo{EIDDa+D`Pobq^i0U}l9is=#_1HEn9PrQ z>ZF4o_pZZf+<$44VTa<#3I)jZXyT3$NWa z@{Y&;?W#nkZ6AVJO)zm;QiV_4^G{WpQPgnp^htrG02*&pherLaf5I06D4np42J<47 z%Tk^ULcI4e6HlQ<{r4fa9DtOiPN%$n zA8^=QAlXq_FjuTyP;>RIpZ|VGZsiFICII!HXy?~uXwb-jW!JNK3<54JswP)RdIKJK z7@LAkIaSWa0rWF~@3ubxO|ETVe3K&5jrW{*q2Gqs*_LjeFzSo{arh^$d>%~U2BsXK z1TnsKRV20V%$5L>(#;!Xdi8lJyX@w}k6*F&@87Sg#?RixGyOM&@qI-8U04fdIHN2t z1<=5gI&Vz_Ncp8vKLD25f!Ya00SMNAUvm5MK5Y#z#4G;X)F_D9-*z|7nzs8T|M9UM z|M5NWgdkcv1ap%>6uk#|9clWOqvn|e(12xG_MRtxG->9XYyUHuX`jkFKjNAAQY=3V z&955Jc##3kJ5gXBI9LFSKoG$yNt9+^aK6pm!1OWzWOn0SCf>Frh#l>T?#9a9es|14 zci&i*t|LGOTscZG2R)sJI&3MAG?@Y%G6rTu*S0LF`pxZMJab*!{C}#faan>`#i`bR zxs=}FHj_SPnM4Q zIB+u~FG}HIa66vOc6FpS46oh$x1T@o4|jMkH1LcP#4yb~K^)K}MjvWO@zwy6g6UEr zm;xfoJnhQ-_U_XTS+eTcZ>KWt69q_s%CDAIB62fiyIb=zu`v$b*6gES0B!mdKH(<6 zPlRnfgH`pnfw9(n9h7eqcFMzbOrsr%?wag`KOeZ;Pp{u`^r5T4N3bj!c%=ZcoKvb! z1xRd8*jhkRC)y^OT78;8TFkU`tF9}Z=Ut_M7n*VdL;qn7fk_ZR=*0wKmTlo zM*9)~Z5n0;{=+O=eEoxH{(z}R0Ho(Bh%3c^Zg@|sqRts0Zjd3 z8+N()S{tK$1B0GQG=mKca?uo8G%ZU7>ZD$dEGY^Ej+YNP0gr%b?BW~tU5Q*KG3@2x z^?N*U;2xJeKBR6upH>)nq?RrRY6#*MnM#WkM`l|AY5fu`+xQrW0wBtZXlr+K=CK(U z@40m4bDwSNTJdR@>>3L&6Y`NSeoYVD`VlrB)3l3 z){^ym;3O_?!TUrPXCuXHyMtRc5z;eY>Ii%-U!2zs{+v+TM1R+*uMJ zqkRDxf@lD46)%J?QTQ-`w9ak1-58MMBd{S&uKeK5>NghM*0j2L_IUgOq%qxH>qcS= zG9*{%z@Oacsl^{P!SBDhHq#5~nTalZEvGG+%(SKwm1`5pY;!hUzp5%TWO+mN#3fCm zk9c?d=mVQEVGt-r8s9*(GRv0(H1tTO8Ogs*!iNc@4Ui!91!f4Ifypw9L@7+`+-d0b zrtH(aBcx0laHZ5hH1NuSSqkDd1CRq^_$UCWnkXO!C_xLOfmMzgm?4NvGZ?kBfycb1 zNyA7Gm^T1RsR2qF#%=0>=({LHxyG6XS9 z6VSduG+CkiZJPcl0vQ^>fGhqEmwx?vr=cOxAU3!lih?p^6ww*n#W8L%lZ3bhm&{~h#w9a;#*8L0Y7~?& zaYk{(gk(Y@BN10blqjMSK|waz>28{aZhCqBw)^Iss$2KnZW;u1s=Hp*t@^9#KXv|E z@3jhrg8V-@AL>>9l1nZr-?D2T(!i%daYUj>?V~Zd-af^O8&Xwp1nuKKks;Kh7ODZd@0NrQwel>`{TdZRTy^ zIX`*o)?6UNdRC;03iJmiuxUp7MKKBFzE+CADHx!Ng`Ds$)+tfKoV#! zod=r$3Xtipy!3SBCDo3!lz&5g-RQgDTDbBRls3#BwizEONbA@WhmG2?XXl(ysXabc z>6d63d}#n6H9&$Siy_BUeSQth0x%!EVUnRn%0PovKw+|(R9-R!*_l&7yW4WowJ$G0 zJMsJ5XZ-k%>%MVI3reNnIc7iC9SKNZO?~Cpy6v_nV^zLH8~|hGL5U@U5-Igdq{OdS zlmpJBfkrP_uM8Qs!EP2nHJdrG36KEV*$Uw8)|LsUOqu@N;|o6ox^8$* zP=|Df3({XvU;4v*ueNLzD0S6A8a zPp|xL)jS6%$7;Xs^FS(qzBmBZ1|(4(k`l5AkTEbA#H2zh@DH{)=1iPz6~UQwQmR>{ zJY^l$oN|=Y^*M4L8P=HT&P(TB&1T!~th6;|^FykRyKUjzmA^waHx-8ox? zeyD5yjonIdR~9r!KD zWo-qteRoFoHN)@9Wk(O6c;9ENeqAo zi&4y?oH5lOl~D>&iQ-r)DykV_i;7K*w_@B;+^GQ7sJeWn9wso29x^7M5gR}|_R?gt zvbQk}M)Pf#O}XK`yTAX~rw}L59K7q)&~cxf$mH`+uj|gV%qgw$`%7!cAeaQeSZNS5 zCngv)%Jt3%rKyw((KvyqwUGI)40k$38NVt=S=OODfkr_YKkIYyk)&l*U96X#sAWQ7 zOUj^A1v&a&sw;W6tyQDUlZR@VI zv~15vOa?u;Xzs>epqdVNuA|EJLW~rv{^S7{1!B2NOR6x@RAQpRBvVorlmJcCWsW_I z-baIm5yhfNV2ie4KSvwRhx;abcggZ0)?oSY41;ABc$tVv<0ODkijnmwec`1e1 zs7EQs+;lz_bCmLc^O__ZCpdQ0;elgY+HCbu5s6@*oP@qK-(;mfvS`Vi+fi*8J^~Nz z@Z&jZS;NLvUy~2E&8-?5mh!=2DH{~VIK)H)QPp#Sh}?C-A6QN~RfBn8NICDb6L-^0 zgxffG=gGK!(4jZZ9Uq=eK05lXO^?c!*0+^ap=%WTwq3v^l$PDw($cgglfUT9o2LBp z^$&lH=J&&AT}tr~Nayz7oWz39oeUTI7`AF;&dhFkJ0k;1he-@ajxXYvO-9f$0gL0wrF(zQzvR97(*g2MlnKFSX)(%8zU;JyVAMV%mc*Wv z9{bS%j!D|&XnHgiTN>Lom?B3N_Ep;Z+_yq+9^*F7X02TtlzHp%>Wo?F7KPa+%KcJG zu-Vp2SFe7DOweq}lXCtYO`9%^5*+rSF|37=m^M>A=2#g#q&Mtd?i4xlz^ioM(#)eX zGA8uO?e6$QGWj;>Q3Pke25??YV2LZC1tz5QvAO>;6=j3;F37yqb6ykxx!5!08Bni( z8l0I-R&4$gRq?icRB;2sgomoc$gFLC9y-yYXju+WPHLF7INT$+jVQsnHV!N7Of`;2 z5GZZEU^xica-)hmzlAOWhG6cTEwK+PPRP5al&+Qzq7?1-FEl!X}Y&lwpL zdSx@YPT9C;kq4Z!DS?pE6)4GOoFL&dcDn(|#X+oBmMt6`j`@O|j_HHgQ6!@k5($>5 z9wIn84)R<+C4XM^b7`oZqxg=+&KR zLVgA$VYp$!^aawx)@@#%XsDmiMUcL(p7s;MQA@&Lke&z45+f zQ`uH|`P1*oSIQ?H6d;y9=}2!?W*fjLjDRruoy{MQM15*@^^27s#Is?Dw`*8gXyY4O zmV*9Xn|ZhW(X~_L)URAFbC!KacI^AeP46$_1z_R~`*S9rd5rgD+vUYIH%bVbkh4cV z&|eXi*4Xh5hEh(go7_=x15cl^yDA}|Kw7vHjRydZGb%?ZQ#;bl^5J&Qr2V_8qwkc_ zwdcrxzIBzXYg*i|kXPxx0tTp&F`#HwAhF*Z5d z>XjgbMI#jQOWsZ=Q6E=6{P+q9&P)m*#v=za_mi)$dlX=KF?OJ{Fl}FO{Jk<^=(ps# z<=4r}pWH9m{6TLZ4!QpIuDu}Zb}x`Wt-3;D!3w$XxThtG@L=wfrvJiNT&IwzJuviE zWWj7LD;+~QZj14QYf-}G-6)S!W|z~G+bi=vm?53%J^i-9?)d76o8`(=o|Lt_UXmx? zI9FEhSfI?@%Zy>IZzV>?giReQ<%N&GDQ|yvkDNUCdO05eBf;{%#oXsjtbSt z?g_@=Q1`rwM18mnh5~!dk%`l?rd=<#&Ddo;z5Gh7k89n^`$mSAPmpgMN}H-_37AO^5`X6~mg|10x9`UiPw?F~{Et(Pmt{#i~MbUpNdru{f< z@MLwC(TdE+TG8{@X8BhQvCx;2d8@3-T9#`-F%DM zyXrZ^+!*MPa$0BR=2aVsL{&2$3gAlYXe64(m1&hdU8{ci-^PIwW@Gan(lwCYr&^Sqp0n zo*9}BfI-;B<${WH-)Pu&$FrkUS9+HM=^dLiYt@EnOUa^L6lPo8ry7U1mL7nbHLX`s zPwJ*w#mb5cu7EGLVMy&*zCy?=kOKyc$OQe7_xOI00_;t$gO&m3ng}bUA_dHXbw&pz zTNWLn^PGI$NicI1U|q%;COJbY83m3q@CqR77b%SlHAOIiRO3(>g}m-;&9=iT%R`<3 z85V5pbbuoku6!RAaLcAa@*xqae3kD8b7^e3FfMt#(w9!GtO!oWeNvY^%~gVtfu&;= z_`cxCN+g(cCmT~J=!>CV1J0@6?I2rf;-?x>$OWV-ehNZ#zUmYMP?u8x@xxOkNlN2& z!jPI%cpfCkoay51nWs)$h&M=iz8mBXwV_{uQWdj8-IF1IRO&0wag|_XMAiAoFEUpw zSCGp1C|A}nSrQ(MJ!xE(DKe_rWnOiBoLh#G!O6b^TfM=VP9iwfHuBS{9Eb|ETz>9@ z@1a;PkhxpF_0ydJEA}ei31%QzGzkL^p);ABPotrA?dP!eZSFEeBof1|2zK>NKn0z;A)OEgsFbc!Cg=u=O7Tpe((#AQ}8R=*$~ zujb`4-(9*FS$q$lsjnORs}$burXa`zh+i?siX4*#@7({LR5u;seVv6J&yBiKWEpnq z$|hnG;1y_ZN3cW7raE;OCll^dhm~K}TNqCPjL8w@{|I@*8ron7nGQwR11n5*TB&m; z+{yKg0QvGKW6YIjpUfk7zP!xJ#TTdc<9#6P+FU4mP0zCOvTXA`vSsh9(w5qU6ZvlJ zRz8*WE&n5b-T6xwoH3>0RTm$?qG5Aj;w)H1rBd8jPS$Rfm5p~vbLSFlEVfE2*CcH{ zAIp|~&&sy;d8&RRtMnoPK*0&86W zPe;ltYbA(r zOExq!YzrodlD*m^ICwn_7(#*|(M~>>m-f9m8D4wd0|3agAs2Canygy)85&1=d;ax? z1&?HV!Ye!W;^Tyr8IMi~0X;^wnQ-yeYaG&*qD<#HIvji4{_kVhm|-*IPkP20>QeQy zF1DxJ)E(!v=K;q~MorSuhRs5*cG0xSPc1=$0Z4PDzyTnc*i%1nbjLXpX58G_X1DTX zCwD@$Wdlz2D8QLXzy(L89OW<+Z~|#_!LTs{jG=J_+=|g1tS%B85_V0 zSavlVV2?Azj$Zc^8|EYbkimG+AICB=84LSFNrZ>v3Zn|CKFQ|Vv6$n;#pg;fbsnc3I-ha4yP#{=V>AbIG zH^6zBI~X|43T3G{y=I*WI?V%4rFochWOX?ut=7YREmm7Y?TxohI_cjDkQ;FWkfz$p z9gImMgu6RQz{h9*{_-hXTi={nQR7RHQGOVx%+gUx0feAd#wc$%G3go{W$1b_cNpL} zlv7Seg7+e3t?~iM^g?BOpXh3p2>K;PGxX%MgIox|GM&t8eyZiVLH_n-rD9;^J z0ib+uVkQ9!76EE-y}-En)B*X(R9M|kVhsj3B^c*)r(GUfwhnximF=p0`>e6E?-@Ga zZ+Yq`I9?=?#eM-I{gCF$eB%f-4j+X- zyvO9s8=LpaP2)H1dhxDsJT)eXZwumh$)dp)mDhkh;|&FSo3%$)G0PI#5nL9ZhIX{u z1uIwc>bQ}2JvMsiRojruF-L#|#?W045%1R>2}o8z`{8bzU=gOHb6&Xi+?I~_z7q&{ zosz(3p)r2%imjmjfS0UkD)qumkQ%7&0LE1e)oGW<%|sgK+V0Lm&X=!QeC)t$=8Ql7 zjy1?77y=|X161v3@O(&jq##XYc&VTmC176Jgfm9QYn?eRc|kJoh};(eX&Ryl6C4@k1Z6zOFg@2> zdfFvr=@=)GicExLg*y~_f}l4536`E|ls{tkWq>q|QgMRn3zEPHk|Aa2=?qAQ>N3;` k4M2iq+})lbepK%N0E~nMf&nO(vH$=807*qoM6N<$g1q%?uK)l5 diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/favicon.ico b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/favicon.ico deleted file mode 100644 index 3dfcb9279f60f2396a8f19fb6607ff281800c905..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10134 zcmeHt2~>^i_y32>y_YZdnyyNN1`Se5lUasBbX_7uGaaRYNGFvsLsCf+X;Pt7lpzgN zrUp60brZUkc~+=Ur*od)e$T16zu&#z^<)yJOkZDGcKsgk?E%sU>Hi4VoHGd1}1>0lhJ}+n_`oZ?-E@n3WbYR>kG-Ye!r7ZJv9<#eXEDKp`r2g z!lrJ998DAh{rjt`u41>i=OD&J+(IOhu4u}@1jhbhTK~slZk?2gClmj>bsA)$3`KiA zD7ue^BHtYPI~_1AZXG72Y=Q3CC>Z4(g8R8RSe9fUO>iE2Zl1@bC->0O`UPSprgb6` z*9ru+jgnVMu_8D)I3%-EAU^0v<>25>K{dCcoPb+iCgv8Hh!YfZf|7NM`21aIoFJ5n zwBS6Ku!e?m&ZM5PDr=%}#;UnSXkT2c7sl{xnRvf{`p)1$CN#IUZFs)0QM4|sv5fCm z|H;hUrZLC5xP9SLaVno*`P9tJyxxT?+lZ*2lV{A#%!nV8+`)=@GvoMtwWiCaN#C9O9!Ol)M0le;2oAQqqF6*HPhCif>Ky@-hynDKZXOvK~G zGjVkA?nY4_4K9+{#DMC%7cqJxtT@%tL4kNet9eE+a;?~6v^qwHHvf0X!2z|daKw$ z9h``y_T$M9s+ZCn+gH#ozRRPY!`2v1vmnX+09ppdYPd-8c84n`H%uVKrFEQ`Dm=)x zoaY+mZ8*A~HI{UGfw=6Zn7twSUc<4ZZY$NMzwLp<(Ii*36*rU>cga~`jPZa#O=Q9%>wAaW}vZto|JfU2sU z6~m>&zSt4xI(s&t4dI9kq!CeCVIb2v%gbCG>>8~~hdL9B=2EQbs8H#zL!Y^n8d@oG zN+JW3Po?%d{ZpI06bTI{1aB19=-=$lB>* zh@&p#oJK-sg+3JBMnPt!A(T9fpki+VSq~E!EF29buQ8BYH4a19jEC~d2^hO{BIMRg zf}*D>l-HR;i&)-g3gp&JfwJFJ4Dp+eX}lSb^PdUDO_ng(_#0F={f3zyb1}nnE{r$L z!z3>&^beX3lb{8d=wl6qZPw_$eIZ6~UxZ;h7Gd!<&2K9q0VIAd;nFm*4!LHRXj$RGT*wq*k zI&f~*@P)iPkdGbc+9@&fushctW z=oXAQwiP3f1z|+m4(Md;fO`5)=w=2(=R^p+lXgRm&T+f+P#9;0LMdd?0%@`?1ygdevBggZ*lejrso_$Sn5ISPdkW_=MG{NvHtmk7*P;|g?Vw%&yT~} zym&Yk#AEn{cvuxAK)Wabh8GiIQIrDhODPB~JOWmhX%RSmhJA>w-WKZTXwk+_jel@s2B3uMZWJ zO`lqCikqCPF>sm!2F_N(FEdpz&{74z{6;)a4TG)KAoDB5Uz_2OT}o^}9KTp;L(W+n zLzYp@wHgUI9eqtZHpCDwpu~kZy{7EUJs*qtrlzpt2Ik7gkts-VvXP>7`AIE#cNy4UuTb{>m8v? zv09zuolY1=FY2V)em78m<7cOfu76xt_3F`IY<#s2N_VOW?MhLI=3pmRD56HbOhH+v5Z ziRWZRK%345?bCbVd}<$b&g_E;u@2pLOgpn5i->j3?Z@`iXc*G@pm**7oO9@G$c+L2 z+#%@Y9)cUO9^H)?P`)^q*p$u*y@ELCo{z&QIxAwc5;5w0A_DUd!?N%&^a_(;Ozd8e zj3sndjJ$LdBd;8V(WPTpQ=E!DYBC9p0DIvH5Za5{MnIW?**t39KtQ ziR6+j@aP3ADi_fCQ2@Wn z0`PC0M+BWKX>_ifx_J=^w=W`@&Xe5RSFy9|Dvr^a5?Eb=lFCxV-z~+7>N4!CsX*QX z0itRII8J=&!A-=_8B_MK3b~J}P)_$jxzB2FllYHkwWy@?rSN4PuDz;9&69_yfAs{H z-#$U*+h=(G`X#CxUgF{VH+Vp2%+rqzctU5)OFCcP(wWlqr3D}9Jo!v{cPpJIpM`C7 zju6wC(oW|{JDnk2_f8zzXYBL4r`6TfHBUdZb)n_X7dm0y-#B~X_^F(noYNP}YnwVN zq)#z>emsbrVG?Np$yf8V%! z^X8ziu)Prxdk-d&N@iyE>4zN(LRP^KHeYp@yW@lshOv_E=26LvzMEj+X|1>YeU~Nv6wv$4~y8#b#v?j4N}N_ z9UYe~TXW#Ro^>k==|19fmVZ>n`K%-RW8;r;+2rlt9PJ#J=C^%$zhU_fGI$m0AKlm{ ztlEAkHul6j#$4wuSYT(ptA*Wl;CadL@O?tv3$%=k{aOQFgz1`=p4%m5SwwkfYRo2QLt-95h80{E4yWuJv7aHRKGxM^X#TdzJ^D^d6$*Szll8d7F_3b&{CnAAa%p zMVte#;#^+^9c^8WP1N4E)V$$WJ6qdj&h-ub2C8bQ>ONxxWV(7FWx=mYmMn2}dd|%I z$|%dupdtK~p4ii(E%9aST#w#zvXcsmIJ!bqQbq@9*{xiwS#uW5DWRDe^y)KsaQ|Oq z6_u2fG&D3uj?~vTF&RI8s+q;C#qI4PcCW|xeFn+P4^rlwQP z#@r+K`ND#`f8VG7puuu-@cO)6cfEfeG>BB><&`zLR!GBG z&4=bh_2l1{`0mF(1O~W9hEgLsIyxhUxJ#=^qn&wo??xIwNj2n$$}7kW2=1z;J0W&Y z9o@eB{>R>Ze){?6fdhN@HMquvT;mq?pBSIOU7Oq53Of7Q!vEb4N(9i>wRfjY|o;I1(?= zgFH_Ug9*RLyArz*ez7rv0^yfI?nb0zOz$SpTTD2{V>AX6mQnN?jUg+>(sL~3p5vg* zVVTwAA-`$@h7gV!x@IB_?IuBP?Ig-WO`)`QG8ETMhJx!9C=rGk?ZjaiGstuIsD9=c z>PZ-e@=WEm78n{Z8)|`;7)sbhdD9$8uBozR9#jJ6Lv_o1=o71Moey=&IaRhTf-2>i zayu47jd;pB8;l{`qQA|Ku!|j3DA!acmLtrf7Ul$7zB3dgxWyT&gj+_0xj>yTiw5xs z;_0C)u$-{Vgh;|JQ7fTE`KMEm7qp_ipnkv$#!;)F$mOGiTda0@L!EL_En?$CKCmN} zkM+TDV$C=ocm=P+!b5xvqu-3QDL*wOHca#<{Nj&Agkv-g2SACij6LP4cCj0voV)=# z#2l_MrJQwm%0?Iyw(%ugvoK{dMjY7;J<4Av5&K1Mg~O4p5{xr~a#`)PZO|rsW0bZX zBM9HPrUk>CFwR)QH%95Z2;YPdw%Lt&nW1na9(6JlI$2>DPnag?@E+(8mYG8wa&#~B zPwj;+;hJ%$A_><-A}}iouGvx0Jrf0I!Zo^-1CQf!V8S;eDF^2A;Kd-j!o8C0t`bxMud{o02q#Q4o-j>PZYJEyvap_TOw!d; z2q7%<+qF|js5pm^>*uhK*#1T?)=++Ywj>_~$|ML7KXCHVev1vxiL5MEV+ zjH)uER+r;S)io5{zmBK}*HKn2z?nZQkx*NS!aB-@>#I@txEd)>t8wb-JyblokNc1R zMB$5C+@O58>g7WSC>O4xT)5`l3p^v7^0@Ieo;SY1pC8}hA>kA*AO6tv5lx?4(AfG3 z&Gb9i7s4u^gp~UdRuQ&yxo*28zokId`MW_!OcM(!o-tw5$B!SIK6A3Jv#UelFAovb zetA?^CAi3upt|naM+(b-4Uk_A+Nk2~?ZVTiGjofJi?3WMzED~!sD4Bpa((`HqPB(4 zZ=X)i$Ub{EJ3Bj;{PjHh*6QuGgw*Wh(O6l!a zf7iu}^yuX1=$Lp3rb*2>c`}HnO^&3JMdz>z3T{bOw`2HpR&Lr#m-fNCBqouO35A7)r(+U1 z6Rwl9`2`mQO#vTv^*|>2l*^tHFt94JCnwnlcD$nFbCABEXukP$Y$nLrMczgQ< z1aJnyyV74tA%*bm)yTBew6x5VG>BKEI8G`nyF4Z& z+0;36=UQ1=+brBr%ig)s%$+6ezYce&sqenq#>)Bo$x))C;}VbFXZOZVn>A<7oVnIZ ztk#hJGJ6Ln=e2ifJa5962L!ARApJA$5go1-SH;T4PMbN4knV357D?~eha`u^PV;DB zV%D6p+{b%)IF09zK>wY)I7ivLx3KlNp{cp~%vm#L*+tdT=i8jOWWj%xSbkhpB}GSQu2X&6N@X?hTkQyBxb^QH-pGg zfNgdK4iiF%!K=T9YU72HF@}((5Vvo|1u>wbkqiByWt|^TJWfWa1># zFoL~e5xZ-b_kx3d9V8Yv6nRv(ae%GuZqVwjTSIoga8w>OQP1TKHPX&X>~4IM4sq?W z<_8-pzi1~iH4cgk~jTN60sNI77OOhn`iIp>6*vHBL^yLjxsW#Ni<8g>Azcu z#ljLR?hA2n@^s2$Y<{1?D%x~mHnjF{)j3pL>t;=#h>e5uvOg*17&uTyMN?CI;>*7o zJ=d9tJ=yXbdAyB{^(t<}sz3CVQ&ZEl{IjL;FZBNX2l_|+>G77C+&8j#&IwNcV4vQD z<(1TQm#*w0KPl~yQrMOyGs)wv=sy?G^0u;(KlJ`tUP)mHN0OBqHf)%lghq2TZqlSF zoX5|Zn#JV_LUz2*54~jM6x4=u#AOjCV>p_~k?FMQ5~6QpDz8Pd`Jb3qj~{yVlT%Po zQc_b>*QCWF8zWlcG2+(tI@#vU=Md-MW9*vsd4r2XqZfNkv6LSy^`ExvzOnhl%(T?Sm?%8sGK& zu~*-|Klkf5Kt@Jpu*~3p4V0Z<&)WXy5ie|IAGXsEj_Cf~4`lN%qF%j!=+l4lJ=R7+ z=x>NDnqwz(Cf#~;C;I;TKE{qO$pbobuD`LN+CR&Vd(EFe-*)@C-(P-R!%kgl?SJV% HxB~wLBPRxN`*#&2{`c=+Mi>oLA_l~-KztyOV$cm0({QU$_zwdalhpoK&ajyy zAt3?cf(&HfY;3Lu1_pxo zag4Bt+HfL#HYXd4lDpATXG$XqAb=QPt`auj&4#fl!HkkN0x?p0Jd3$Nu@1z)-u}L` zcg7P{Sj+=K1u)h-KzwK{Ga$!2OdQC52V@E|IF!i!M+SM*)xqH-EG!HUQ&?=r$Hz|u zv0;2rOvBhPngtZYFmV0xJ_ada2wz@a{tSpVGc)@SifK^HU$}6A(cIiT52{>PR#ujQ ziHQl!dH(#l5K!(v6F&>%p@yZ}V8Q*D3K_(OSio#xQZNY$3i=OBE(}sqQVbx&92^`n zrKP10o;-Py(cjL9q-}`%X|$kO3B$5{vd3f}9*fX`}!I5IpHfxeDj7aWYNj z5o2RuV`E}qWnp9hMhU~0CqFM=TK`IqVIYBix-^4sjKu$#4%hz|?wHoxDRZxiVf;~{m zNXUF3`w55*1UyhZr?|Md{zJtiL1G{_l+OUAO<`=1T31)sr9g8);;syuZbCV}b&BAW zm^Il7C1n=R(gD*oi?shYF4YDb2rMrC_w@7>fY`ud#23U@Q&am7OqppQHVgyP1V}wA zOwaG%zk`8^@H>bN5>r)G1?z*!!yE}LhQvW~Fmpj-OxJe4odQbLdDAr*rsf=Fs9c~0 z4&l}nIt(32XBj4MHerwuWM-&~x)K2r7ZDL**s)_rzoDTa!`ruSH;ajhF@RD!C^3TQ z8#it+e*5-KT2oUKq+H0w#RcR6hUwF%%K}3=5~K!Lbmhs&$S{B~2!Ol!YC(m_A1GT0h+*b2LFI&z)V>E|b5M8y@n(=ZfB?)^Ur3Wt6u;j# zH&f@zHT*YnSP!L^rIJQZH7twhA$n-xgY-XD!kq<|@y1Hudns)<`iS!18 zA&b5N&=vrAPV124NGCusg-~$F43u09>8iZHzyG5WEtL@r^RV$f2RJ(6k8L_T7sbg{ z>~ifV0OdqlfHZR&n=%C;$|#wHvIyz5T5U0n!J{UJ!_i7MCX;Cd$(c<~PQD~41xJ9}pJRTx@fOPP3!D!^Um8t}?al74}e*;M^5C~9? zqnmHL-FM4sAKwx5|W(U6vo@M-}}jRMQadlEWmFc{3EMXgrr4*~Kqjg`$1 zuCIQ-znns7u~R34FzLP?37fK5$J@ww=SaWBo_-yYK2 zY_>B{N1RUQqwMVL0p%`IcEQ1zMx)_n6lky>Y|~6$gdOvGy+i=7V^z?Fj@7a@k!>Km zHat0zqRYCNa8hCnx-U5p3g1t`FobdvlElkY@%|t|@n0pFgzQrU+bkA(Cg$csR!}Vo zdG|*_4pH@fZnNI(EStFfswCRyb+$s6{68?xZvoh`+L$Fl6l!j|O zAn0*YONu~BIY`Tu&+~crcGl&r+W#`iWM^h~X5V>c=6#=M6eK;#e76RiL=6{t4pHD=^^fzZn=46I0vS*_jS!^co_!S*^3>38=OAB`}9%b$^{smyB4| zq;5m~CY&MpAO~+FLBh*m9DDG%!rSOy7?okaTH@^ z2TD%yQJIe0;MqyhnPtXe1r1VUDnigAK$c=3sMfKLj*bubJCF(&O%OZ~zgZdv0OV*{ ze0==#4Gj&gp5IAY;m)1icy#hM!eVM_Dvs+IaDV{h+f>H5%;9jnjN(_agAYR{+X&=k zZP>20Ng)Pbw&}^u?Bv^DOFzggj%C%k|9!po?&sUtCx?2a^3Z5EJKb^+B|GiBF65gK zSuP%*0nk8yfB!b3p&rAG$XQB|$qL!PPMG2C7;8T!EXq5H0Yt?&BYYNevH}&Go0XMi z#{cdS<`#?PTXOkachT6yveYh(Y$PDn7iDs2pCkbZFr_-^z8lsDvS5@9qzO_^NJ#it4I*}`p6Ft9bTnPoNl!HIBBOa9fU!F=GSU?l73BiktED!R z$+RDQn|4Dj9}9~5J((pspqNX+t!Ke`s;P}sHk5afYF8^+4J6h1qN~&R__$b5P~d|j ze^us0Yrr~N$Y#m_SGt?hY}@C5&PS(_1Ofq3cIgdv;mUDokk6XZnO3~VYQ8@r)dxp@ zV6$^Kn8kjE+5foAW@g7&^>-$wm-`aq+#I^MlCKn2?q_avUtixDwShQRcS-uw4pdFd zr3MlV(>gFPAXu$dx@zd6ww|7zFXQ6kx@k_-0W^A^e-H51#>U3FD5IXq0Rq4WdwY9B zJr~y#Nckjq>f+^$j11@K=;#ixWC5p2fP31<#{ebo!#CTtHAjb7Vs_Bu5eDBIqSo!_ zCLC5)(UQ#qeDx4HPL^&gl}3zsY_9}3`O#i`1-=y}Hq3)hpkG8+a@?m!xCLOYTOcK? zkTVG|x)PTCO&^ZPlq`Oj?Aw&1&36WluoARvHrr04(MY#gG~xB-<>dipvpFd^I9R&! zgl}Wr-Q7mIx8!}W%Pk=xAzP`OmzOux+S;lku!vpr|MBBaZIobRx1tM%hhGF(ML0c? zIQG;&4_kF$`_ITepB9gN+u#cN^L}Nd#mh_BDvH92NKINNB+$Sd_lB8seq3&sqq^XJ zrtG+Q)Ym8U_&>N)Z%lGyPEO7-9J^E;S;PVz?O2ALwuDJJ)6&vv^YimBLKz0(eHrZx z9HHOZ+uOtWAOPh}9IaBBZMbjR+*iRuRaMo8*r|n{KMoHMpM$RyC_%=YXl`ykOm*sm z-F^ViI=GlQ4NYPt%@ME@%aHuAum_MuzTh)6GfRnyiS;EVC5`y>?B94~aeWlaHCe@z zjmDHEVX|HU%L6nHC*fA&ey|6GutXq)kl537XW- zL{Oqb2}r1BCRT|iGsb8z)k!T(m^cU4i~dq$60^tNZgIT5B@OCi9$0)KNafI1*@5Vn1;KEvbLV&U;Bw?K+|a( zXSZ5LGOslB|LsQ*q)>^tphG^vipS+z9_lj8(6FEfv`nX0m=-{kn@)ZP`%;GuxYQV~ zVKEDWjwhvunWrKE%!vdrGtOY{!$&)xpPwHf#<}k@23z?Q^VfQh$M}fXn3MDles_qz zGg99UUvtB|1LD04nw@Bbdky;8+~PDZ3p*JQp<#w_EqE=HkFFdZ^Tm<;H^|LL76<=8 z!TdW6MxCx5Y((=ERTGOVDk>IZL>P@=Ig%oA0p9Xqu6!_h)nIQP{^wz?BLb*J;=3lnE$eBqIXO8c_4W1d;YQeOwgTvSgYp>&7>%R5 z+(%$avC_TN2PdTn=0flus|e+fy?wc0JsHRE-8>YECLv(CBhkfBi{3f74)@YKQ?i^A|;O5g8c{vEcQEm zkIy2!tb0@yp)4qThU_7%3U4}ROs40?YKDT=E;?;VlQXHI{{dM{XA#`&P2yBAj zK6#Fqm>4&uyhVE2LYzq7$?pLuy-+#>4Gj$+llvJR9i4z2hvVbpc!OLp3R)9#jgyMzf3kV2!9qEaSi}RRt3d%w>SFUwmWII02W}^-p zn`4^CUV8fXtZ?5?+1HnAJd^fWZ?Y}r32gcNJl-Y%-NTN5_u7QX10V((f;2)%N7D|A zW7R1W2n)5!#|0FPL*_){3~cmlG#amhf>{E?s-&>i5qb|w>t&o8l+j5N3-I4&;3%yC z%uQoSR?|3NoQPL{fB&N}X6?|>5La3>9>B~eZ_cgoK2Y!#JBbf^jJ+DMv-3oIp&XIRLCHSpR?x+;Xe&dyN4<2WEI2W*^E+%^w59+?96t4o?vqO6J6!J9pNcJ9lm)m^gu`Z3V|Z z4Dyv%9mmGT#vxdwY>-o^$sF9#(ebLc{G&~i`(Tc#D!@9nZQFJc=E9W4sC3GnR2;+O zJJgB?1ZIxpNiG2+;)T5 zA2@2u(xpo`%T&Qmj(daXrJYASaeDxU#+H|t=ZpN!pQ#Tx-?C}brtRz2tt-yW%`LK6 zEPJJ+`XriD@^SX1So-?K3i+Cg^q%)|4(B2z$^s)mD z`D|=_gah-Fh(yoF%jXxdv;Qh%J^#MMK5Hyww$UyQJOyiC_*u<|hrUc1TfgFaKEA1` zX*T9SFeM;_^PbGi%sl|eSy6^Li)=zP!sSKz$jZGH85voM90|(e=g@_9Sx?Z|tgNhx zyu3V5qN=#Kn5CzuZ^rj{RaI4mAg9qY%}@U)uCi6DR`J}($jAux2d-SX(h2`*1)BdU zWPO?_2;wOU*w99fwAJD;hlOhfkegj_jN5y^L_R&q5x1_$79sWe>AEEv)PI zEe@PU?4rH{2Opbxhn4N?j93; zlhb}Km+IKDV-djNcHnp&aVu^NZ2DkrZS6Y=2?_goGOP4(B71Y~M1Fen?zjh|AJn&b z#}Ade-Bp-xS#Ummeg#_d=kCMFLAJm^1lDF6L=>q}7~xdN93r%@OL#V8()S_Wkr{Cz zh*lr{R7}mp{0`B_q>{HlQSsn?jfwvc6;&Kjf-ar#u!ej_wg+vUe%&{R{7zq8bBd{) zPxwj6sXG%^DwdYG`|X+G%gX-RxUeth@gHx(>Tb!Z5Mbw!&n~Qf#qR7+w2$3hfk5gt z#;%Cqx!*pOv=6QI%T&`cogTP%#t)s?S;CR;^>*K;FUI~OKs#3&9aWKqtKaKRcPE{M zgzWo51R*900x=0fFcSrrgMuI;9E4FYBI5u#jx#DEDrZ#YID%o+0RcH67!^S=gq?sa zA{aOU!;%FO0wD{8G+8@6-+ldFQ~lDN1jhL_sY4yQ)Aee(_0?DR-n#X=du-~ELPz_J zZ)>omfVGk}BDh+pk}oqx4=4Uu{K$n z+dsnJ-}x=Ky1r*BdXgQCk&}WYMk`%YY5y_gf!-ejK$%hunL%JWcY$dQq78haMh2ZN z3-+r>9ltB!w3jD*LKn2QwX@bnI>l})Zmes|JegOswP#9t!03=d(tMWzI5Ua)baZvh z0|3-gOn5Ig&wShKCUoi$!ixgV;4~UCQ-;ar2ANCovI!!} z<`TJY%4NHiY`_DMN4=^JPx*ApojbJG$#q!S&4^K}Y#LeQ`u3}@B-}#3W0@^*+*Km8 zZU^db=%OC-5=S}tsTR-f;mX}7%Y|`cp>dr+xwE&}_e5DYrZ~xTVfHPL}wO(*jBj$FX%zPq`(m72}wvG{mYE=Shr zDAlzXI`CUuP*6Z#tAZ}%{v4kDfZVRPD(^*$7CoGml|_!Ii*`qD`29W^1}`xeET}Pf zYnjd{N)aX0L3h1Tx&Qu?&4wD;mth;P?N%}6=2o-xU3ta`Hum%slN;+T7yd9k zG=AIiifgRn4G&(hs79DauhwwpCgk0i&UOKQ0`S=~X3QA!!1*hOiryiB&qt<9$j?#CL34BSI@U?tEKMxh8`2F1dL$_+Dd*t9gS%Z>=5%7BcGJo-6J+aN zDQ9(7&ePLV@4|_u)DuXdO^|zEXENvIqm~W*ee~$jYv#?HM{P(4zuG~W;p|#jW3rpO z_@&WXt1ll}bs zTAaCnJv=<(3f!i`pkC~g3# z?p9AQp8I6Ph!HKjckkY%On`$s)MyL@V3+W1kzYMBGIDKcX=y6zjo^oW?%cV|yu7@l z85tQC<|I@?i9Av-B=tF`vvM>>XNSs4qQevnbwA3)s@&TY6?JCCiWTdUlaq^OHx{Wr zSH_JS=f7*$t`8uWu$Y*bOWE1kGU`XNur-4bd5gH}YAO3V z|KIG%`=9^afmnR0fE_#cgY5)Ny>;V*!HxC(`}#5Oy#M09_tjwZ^70yq$@>liGw}kH zFR?VwpFe-)oH=u78~Vl-bHv5PNm)*7TriacMt)+boz~V?a);Aa?x6S3ArcnJC_Iyo zXZr9=fW8?_CKItpQtG^o%PoB?bpKQrwQ_>ePZ;t?ndtna z>TSMDOT)ku=XROyicRxTRzHB~1>G(OLNuva1OmFee*OBlhYT4)?DJn=il>R9b7!7S zs2zN#{pY%~XRy7|b!9aWX~L@(E?ii|ZobmMo_hE0Jp+qt7!LqC-2|hTL`6l>+0qh# z* zi822R^?ZE!^5vRt$yyXN@f0+s1di=F@hzJ$dETsp}nF1nLFoADaU z7&Pg&C--7a5kNSDr3{$B{yFnRhu_!jp35xl*QMidNypH&4k^2IEFNHNQNRen#ezk8 zska-j6&pBkU><;2>ya$b4fl;kKC_yCr-)SMZ2wRfUjT<-2=raW}e~m?y;v`m#PQn*Z?$f7_ zq%t9I12|VfzF$^WR$4nQd^~S33d}%m90>re?4|5QLoe&hQl!v*fN$sY>C+F68a0X{*69Te*VJV}^sl2o0X*Z;b`N9fz3}kx zLWS|bf`0-_K7qc3sTlMr7z1B#*|H^{2P4JEsX@Zu#Z`lrFGmZgGcZzWXlNi+BNaP= zKP>xIsAH5ODlQ9kMLCWM^=-p&z zaIXX^t*B%1kq@wN{{i+ghfl9#JAVC;wX~V-I-?qhqNpWL@ z02sey+{Ge0q9Y>*LC1PV4R*A7asU4Peu;^RGk9y=$H(Uc833xX6cn{w_U(De27^87 zRju!;0jUIJ^2|t|yV$1f3GyVJ{7KoL>z10DIvz%0VqIO`WXMCO#HFji-5Y=315kc_ z^5jW+xuKv9jy0arw6lvkk%dsaqBH+tY1L7-^_NdsY{)Xn(p|Z2E~}|OF9FzAww--{ z=soCvAKF_gD$j?3k}s99)nj2r6?p()EK5t6#cCVQvu#J;u>nxaxrGErw@`@hfFJuu zJ$R94I|y@&qKG>&EXIOSmTug*(ao7l=;~GJa>G>0V3{YZ{RzMVOgP(WU1=(743|D^wCG(*t~i38e!YA@=8s+^<%m)=cc_GWlX@df5zYAqf+ed zo%qOPRYWqqxmBeUg9(-2^xQSV0TH&hBYGPA85r+oSh)Rqp2tAlM7Fsgs2O!^$zVaViIrfVge(@&%jO@|X^m`LN;dmy-xSu^a>dbk&TOBD$G^JF*DIRzw+>N0 zWo2cbMMOmC0g5H`YC`pj0{~V$^w2{qzyfOl+HKgDa}FFh;NTvDrD`PMsC6pdk?o2Z z)$GE#cJ=^F7ogmSD`EJY3bAa~tXWUc_kR8QX#xTQRuG7ItDCm|haY};`GN%t$k6%K z2?G^Dj}%eg3A%{FvlrUa!g8HoT3WgXtY1Txw=-r`JO7mhr>cuxyLK&nP49~j z3=I54d1sblX(AVF-MTeX?PsLaw{PDUuw`c}@8;qrk)Hb_>Rz6blCl_mo})Gz0OWE2 zaRKx$^3%C|1033zjK#E?+Th1ZbpRxZ}5Xy59Y7*USP;Oc&mYs5} zryNs}P$(r z&~~hzlL5 zTz3r?k_YtNAjpQE(<_FXvy&XTJ!PRuDhA44oH}*trWrG4{DLBzG0vhK^VMo z)226u(b2T+ zQV;_jJ(ys?XkueyNtlOR*%TW#Y#0oN3_;zrU(@Tw$(QY(9lZgY8PP5dxIT)v17*~b8~YafxO8H zZo688M27=dU}vXIoAxu>G=t3>WSNz!&*(L8e9>P5!~97de8kfE%gnc8Oi_K^v$1uL zr>j|A#xF8QaJni_Stq*J_X~Uao4X=234r-lYx^n8m8B=L@BcHoWJbEjMt~U{H&v55 zU=H~{3}?&tdKHweN~|>(zGAhu!7^+Mbjf$< zN?sD2BV4j9Yl`*+fsWQD?H_4>L?~r48B=l;Spkuc)A?yA6iP)R5d;DO`2BwH_g=3D z!!XcjG|+Ch%jCP5&1Rc|$N`LEvA9yN*EyX%X^loByIQT_h>#+l_9wi@{(Z?D2RE zUDq)j4#hY2{Z&BrR!Yn$4g z^!3C0RHpz#W@n--_jThHPEAe2R834DnuV#1kUlxXv}=C^n7~&>f1RO6h@8fUuT`wRE91*{Z%LW-oO8KckjTdf s77ewwyuEar+*b)ffn+a07*qoM6N<$f>LlT?EnA( diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_delete.png b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_delete.png deleted file mode 100644 index cce652e845cde732ac3ce9a4132b597301ad660e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 659 zcmV;E0&M+>P)ps_J1 zHhTmGl@tMUh=_=a3Fb%)BqZVTW3s!xH?UsxE?7A5@n+t<@6Gq#%m~l(@IOPFT;%il z03|#}Sa4nU2-$-Kn!4}FekQv@$S0FY$L9!N0g;c={9!m8K4zLG48uSu6aw$J+ii5a zT~sO+G#ZW9!I0fqFSvY9*@h|sR=YqL#x%oU@(yD@pz0* zr-R{eDEHX6V*RaK<|4rWl@GKt@8COeKZT>%ICBq4+h_I-+?Y*V28oxmqBc+Oz5 zc>4@kzJgDe<1lkKXYEtktsNC`FoTI)4qLaF!_1E&4qv>EKx`iUcee83)!MzalltZ# z3K)~8`*H_w9^uf5^9X)<39-6>(AOuJvu0IKc#FRkFoCa%ULtC>8v6bIR-H|{S~CWm zy|LB2yL+L!Vs5g8ONBz=aUzj0EX$JbfSV}a#vT*B_2)32Uc<0oLyzLS9V$=7hM4?~ znM@`|iEa~8)bZW?7q}d~l*7K(I`+@}grT|_=WaH**u tj~DMRZZpzVy^OjT85Vq(G=8XD@S91FH}kp`d7hyPh1 z5CCa%X>*RH50W(1GMNlqE*ChCgTvu4bCM)M5Co)BDTG2HvvyYjmSvI4<)A2v`CcxU zQ79BpEEdf*P56K_c;lUWy=bic9s#4IZm`yWps?HR<^;5uf_%3rLf1Uy7}ym7{u3SG zgQxL#;V@<+y-&7GK#MIB!!Xb^&5SuEhPoOV9{wDJpWonQN~qlHho`!h-y&cUDCjiw zot3{JSR;b3Z$U9V2&bDtVsaL$Qu?FFtIb;kXm<)qqyl<=9Kq@&_)r^^)N|OJWjH)_ za7i;6X_aj`duRB^h5&`toyKA^3V-E1_yb`=eg>PPj8Y+p^vFkpk)_tg?(s>=HO~R< zNVkfdL~{$}rBQI|9QHR{MrpYhcBg@2p$?h%pAnUsbBDUeKUv#oTc6-&EEZdf$Kwze zM&QwZLDd6D&pd?=1#1F{N2f6?Hf8gwvt`>|pf)ft5F|nm_AI~XywcT&?}K--v^WN? z_7vo-s3)9F{TXfF{hpqll^q2vdwBb}datvKg-yfc+gC^|#8-K5)%lB$rlxi}-rEGO xUZ|2A>wRp~(I5;*aZFyx-fDe3J-^%i_y?+(!m^mX(n$aS002ovPDHLkV1gwlT*CkW diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_save.png b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/database_save.png deleted file mode 100644 index 44c06dddf19fbda14efe428b9b1793c13f46b2cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 755 zcmV3^_07cLZBR}_>&jXObH zw2it@svr%qE?kJ(Xuudu+DSW|WWK!jNvbU^UO02#+Tt zYOko4%Vx8c4Gh!M(=Qem7g;XcE?n0Qi^XD?&*vX7@xPFCIh;%;@xMr?(;$(vo9j9i z6;riZMJyIWG#Z6r7^-I5HtO{{DwPWQ`}>&y+Y;!yjz*&a$8prX=XtO!3$0d5J>%Mz z1f8>Jnx-7^X2#7Yb#zC2VYfZ>c17@L{s)8{OuWBa3WHFfVXfhLv2t?V0V~q5R2D*D z&315l_#iF}b>Zoo?-;+7*`WOJWsMw(x3WXv`@U*s@Y-&edFEYpz0skP)dFfu zZ4wIp&Vbb!+|0+3Qa}p<*AH-eY>3q8s6?RA)zqP8W39IT5HLFG9m1F);gE|P`L7@@ zctjKsn1rA6!ZZR%R^(SjU!r=2o$yGp<$KViK~{B;AIcgvN+J+&Nvur+W(Sw&=H?z} zGMRW^U!Nl3AvWzQ3~C%Z*G*(?qLfNCq;tpg2yRW4@yl9;p3CK)O-@c8Sy))OUMiKc zQp#QYFZe-*@LZDInR^#F=Bm=!vA2i6tkEJ#i0aggzp2D%3!>h~r~3uLt(-IMoyFAT&uF!>{(iS?1OX-eX zKw9bunxR5FrF6QaYs~9>A4#zW^dwIvCpq(+cfR?U`T6-{9LHUqo16RKcDwUVr?cX4 zIN~hJDs48~aRAJ}U_2g=KAB9SP$;0;Y@*$6Ly{z<(`i^NmbL#1W@l#$wOS3;YPBOE zJ;7`?L*?Ga6XzC292wl75}>gDz`(>h?is$JPxm#0jGnotoK|nAVM5$DQ z!C*kO-aeF@+Ejy?nVHEp8V&F~k7BWicsx!aH9kHLRpcQ?L&JFBAB4i&kAaVUxVvzh z3a-EY0%m%8nhI7|SE(QpiBL#sG#VUMM9}*(0mg2(Q$Zq;z|PJNd_Euiem@;jtJN@i za|c2MmsL?PR;yKNwOUA}QuO=7;V@#c7!{~gs?J7hAlsE7U#g?$aRkhSTqLq6iuCu9 z10_j_=;?Dc?4cZ386qH0HkgHTDT|HmGR`W4V2noNQJqfLJEot)q{V_UtsW+m31cP~ zDwWEi3HYBSoF4M;T?VaIdqinn1HZ9}32qs-PdwPbCf+WI6n9jl0-8cjV3%1FB%B&r z+`mzSliyLSH0dxYE}rk&=!uCa*V>()2znj`_XYjtbt>@4FLHnJE|G`xv)Ba@oLBny z1%3K7c4fiB^4{k6E8Pif0kNy62}b@9+N#0$9Ug7g~-`rQ^qx~m@y2OU8A z#zh~=7n#Z$Z*fx-GOtDf07cgx0suCz_W(2~Y(0tf@FX@P6EPuM_dgn$vj9LucO)%W zw%HgMW>=#oL>nZ>M&NEf08>)#)k<{$fCT_r>rPi=BV=hFh6WS^qqze>C6Ek}o{M5% za|@JGowu0t{&hgNzySHZxy@LTNh);YzZ2zSp_ zl$^T&Dnc|NLb&RD_!4>pt@VHdP)ZGER%5ZmWEe$lryR&y;2u^3cOkO4#6c%-(EY6a{600000NkvXXu0mjfxS2AI diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/house.png b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/house.png deleted file mode 100644 index fed62219f57cdfb854782dbadf5123c44d056bd4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 806 zcmV+>1KIqEP)v;U&v3%|^C`Ga3?LtY&4dQB4Oz;1v;J%z!D&%WRH@BZ?x; z3)8@IUIv@hG|@IwyHLC`l{1<4BK>wam95g|i|?Cfzt876&-Zx_0f5*l-9`IJI&mHu zE6$@xB)6N}7VeR;!X8D!TAw;;&0Bsj?A071cO>X3K0wl7WZ1;Tg!4LHyNcnzoeQ7t zNW`aSlm8WXYkek&ir$13=ngczvf zV0vnjNpCF&K8px}dunv+`LIb-sOC$_jD(;IBI$xC|7`(+9cA>Vir_V#z{?k7SX^Ah z^71m~W@q439Ycqfhi7+gp#A14n1n1!e>$EdeATG|f798Y=ggzwEKH2Q!qU2QA(Se?dwqG69%>n$6rtE z%F(845Az8c{w(XgimJg96!jLMz?zS6I1HUm2baqQx7&@nx;lhHA!r6vs2|fqJETOu zLxeu2OQ(3(au%dg>AcZsWI(zXn9XJg1cLe8k~0h0wOL=&HK}7X k{AKr*U4z7Szv)i%9gTgghwgU$Q~&?~07*qoM6N<$g31kYk^lez diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/information.png b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/information.png deleted file mode 100644 index 12cd1aef900803abba99b26920337ec01ad5c267..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 778 zcmV+l1NHogP)BVme|mWaqy4$_pJm?y9KM{-*hp?1+Ey3e-CEDooTa!B;e(Q>TSF?bj>5At13y1p zriN3w3x~5SfZj{@J4M{kp{?=M_Lh2bV+5LH)Q)5W!-ePA$RgE1@5f1cyHki0Y}JyVEYZF(LD$xXlt$7A5CgE@ zpV-&l%vf;=5kZ2-2gi@Y6J&=cuwt>!vJ^#(&n|LcZyUzi6Duj$$hJ1s*HD-#;k-w@ zpdrwAuoDG_N2bvb07G$Zk*?Hc)JLtW4yqOnic_$zO7NZ#l>Fm){;fE?b$IbOaX2fe z0la4g0Dfw2xk7Wi7NapVD8YMPCZu?A1QCK*67dgsvRKBLFtrM>?$%&_lD1882mzdO zWPdw5KWw6IT`m1b_8=lS5jt8D3=RDa=&jWzR-)S@56WMslZ~mKu1)-wpXB>rNBQ>N zU#K`#1B&v|_AQK;7I~B}OdGiUT9LX>f0xm6<;LeP!=vFjPsUQF*wCJ*dO)4YBypgdiuF!=i@6Zyi7F|q#K zz?tlSZULa@t1D?$e;f@b36&N!V2mjOHw|*FMR=dr@6o0ZXGBB_+=zx3%$`cG63Jm-*84Da1I50Ew7%?y?G#+5$ UVU>wEFhP-tNtBU=gM+~u00(^_>i_@% diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/sorted_desc.gif b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/skin/sorted_desc.gif deleted file mode 100644 index 38b3a01d078418d3afcdb2765251a9f21b7995be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 834 zcmZ?wbhEHbWMg1s_|Cu}C@83_tE;D{=jG+)?d|RKCt}{bc?%XSShQ%-?%lih?%lh8 z|9*y1Fd72GGz1iXvM@3*urla?{0GVt3>@+doD32i4hNW;7z9Kl3=A9^nYh^GDt25@ NJj%i*$Hu~74FL5|8=3$B diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/spinner.gif b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/images/spinner.gif deleted file mode 100644 index 1ed786f2ece49ec5db07dee13a56ef38025b628c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2037 zcmY*ZcTf|19{+AO8xjIZfItFCFrkL3BodGwflvety+|>T03uy{D35o<4X`9Q3=bSU zojZMs3Qw_)j=f_!)B!!mUKqwc>ezd^4c;H{$Ifr|uTTHRC8&buXgI)uM*u&6{`~Rd zM}L3+_wV1IK7G1x-@ebEKY#i1<^B8j-@bj@wr$&s7cWknII(;8?sMnPJ$(4^-Me>t z_wN1p@#D#pCr3v|A3b`6qUeJM5ANT;KRi7A^5x65YuBDSb?WNXs}mCwVPRo|gM+(v z?RxX(&Gzlv_w3no`}XavTesf4dGq@9>xT~?_VDnybm`KK8#fLfJh*P%x(gRB?AWp6 z>({T(pFdAaOMCY0SzBA%hYueT6BF;;xnpHzb@}q;O`A4(d3im4{J5Z?;ONn#0|NsW zFJ9cgfB);(ugAv5a&vP_OG`&aMz(C(^6J&A@$vBk2M!!Re*DRkCvV@rJ%9duQ&ZFC z&6|%MJC>4?a{Bb?vuDqqIdg`~z*4Ws1>(;I2=4ORL zQCC-|R4OYgD_5;rwQSk44I4IW+_=%t&(GD>Rj=1yxpHM_Xh`ytnG&0k9<5Zz%KT@c z2mnYvQ>hsF`jQ_R5(mKIydH2saldkg!Gzlvi9nFeu<gyfnCs8|SGO1R0M3N~Sp zx@MoynP5Rh(303ldPHFemMT%$+lXy}A1JR?IwL6=E`apW=@Z-0R!QO^@j_&{6#;i|5R1o$ zJ1J~xCDQ$1cs9`DW9Z!)D)^+%&Ug81908UkMXX;jkp>#b+SE}d{`0S>>Ef(`Ns6oa zB~H-LX25y1!BDgW%?nC0$RettYz8zsuz>9Z!g8TH$kU;rwYWrSTkjuYCH9utgFU6b z*wzBKaG6IjEXYSpAo5j4&c(t zwi-c(Q6YX2N-v2q(mgN`>wuCTV&XSRUA4h-f8g+uV2k_=o;2wb`7N)&+7T-C+CT_Bu4KrjWmK>x0AbH2rmR&7+q6fX+R0o&}V!t?TP+g0{x`8PSP{7CvnEPL^Hzx^T2Eus2 zi$U6ZM7}+l%$}afWn#%|+MPTsC236GKi9-ad*Z9;Ymg?jSO$L1s$w4BvDzu_kH9>z zTWC{K?jx4~H3oGGt3}I}LWNw@H)C>9GF4^|x(5n#+Va}kr_cb>{a+K%>B+@JNrC8? zJOUkD3fe*NdA-rJupqo?FfRK}k zOm!l7Dj$dsL|kS`3FL3^@^7axrU9d*@79yf!+bu3kXbziU!v&TO3p#w{y_lYG5ZPzDh;giB_lkGp((nqZ12&%LTrgm4vY= z{ffd0B$DiUKReJ9>?{#_KVrMyhiu_A8fNd!&DWTZ4+9S|1lJHkLv-^}a0IC{WI9N! zQTY-}db!%OH^;l2ZeajnA&Q6Uv=#0KZB9;^^lzMOi^0~bS~m!&K#e6hia79(ItV9M SXP~*+AU!zMlD%~Wg#Hic*k=_0 diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/javascripts/application.js b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/javascripts/application.js deleted file mode 100644 index 1a35c7b9951..00000000000 --- a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/javascripts/application.js +++ /dev/null @@ -1,20 +0,0 @@ -// This is a manifest file that'll be compiled into application.js. -// -// Any JavaScript file within this directory can be referenced here using a relative path. -// -// You're free to add application-wide JavaScript to this file, but it's generally better -// to create separate JavaScript files as needed. -// -//= require jquery-2.1.3.js -//= require_tree . -//= require_self - -if (typeof jQuery !== 'undefined') { - (function($) { - $('#spinner').ajaxStart(function() { - $(this).fadeIn(); - }).ajaxStop(function() { - $(this).fadeOut(); - }); - })(jQuery); -} diff --git a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/javascripts/jquery-2.1.3.js b/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/javascripts/jquery-2.1.3.js deleted file mode 100644 index 79d631ff463..00000000000 --- a/grails-data-hibernate6/examples/grails-database-per-tenant/grails-app/assets/javascripts/jquery-2.1.3.js +++ /dev/null @@ -1,9205 +0,0 @@ -/*! - * jQuery JavaScript Library v2.1.3 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-12-18T15:11Z - */ - -(function( global, factory ) { - - if ( typeof module === "object" && typeof module.exports === "object" ) { - // For CommonJS and CommonJS-like environments where a proper `window` - // is present, execute the factory and get jQuery. - // For environments that do not have a `window` with a `document` - // (such as Node.js), expose a factory as module.exports. - // This accentuates the need for the creation of a real `window`. - // e.g. var jQuery = require("jquery")(window); - // See ticket #14549 for more info. - module.exports = global.document ? - factory( global, true ) : - function( w ) { - if ( !w.document ) { - throw new Error( "jQuery requires a window with a document" ); - } - return factory( w ); - }; - } else { - factory( global ); - } - -// Pass this if window is not defined yet -}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) { - -// Support: Firefox 18+ -// Can't be in strict mode, several libs including ASP.NET trace -// the stack via arguments.caller.callee and Firefox dies if -// you try to trace through "use strict" call chains. (#13335) -// - -var arr = []; - -var slice = arr.slice; - -var concat = arr.concat; - -var push = arr.push; - -var indexOf = arr.indexOf; - -var class2type = {}; - -var toString = class2type.toString; - -var hasOwn = class2type.hasOwnProperty; - -var support = {}; - - - -var - // Use the correct document accordingly with window argument (sandbox) - document = window.document, - - version = "2.1.3", - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - // Need init if jQuery is called (just allow error to be thrown if not included) - return new jQuery.fn.init( selector, context ); - }, - - // Support: Android<4.1 - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }; - -jQuery.fn = jQuery.prototype = { - // The current version of jQuery being used - jquery: version, - - constructor: jQuery, - - // Start with an empty selector - selector: "", - - // The default length of a jQuery object is 0 - length: 0, - - toArray: function() { - return slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num != null ? - - // Return just the one element from the set - ( num < 0 ? this[ num + this.length ] : this[ num ] ) : - - // Return all the elements in a clean array - slice.call( this ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - ret.context = this.context; - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - slice: function() { - return this.pushStack( slice.apply( this, arguments ) ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - eq: function( i ) { - var len = this.length, - j = +i + ( i < 0 ? len : 0 ); - return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: push, - sort: arr.sort, - splice: arr.splice -}; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - - // Skip the boolean and the target - target = arguments[ i ] || {}; - i++; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // Extend jQuery itself if only one argument is passed - if ( i === length ) { - target = this; - i--; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - // Unique for each copy of jQuery on the page - expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), - - // Assume jQuery is ready without the ready module - isReady: true, - - error: function( msg ) { - throw new Error( msg ); - }, - - noop: function() {}, - - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray, - - isWindow: function( obj ) { - return obj != null && obj === obj.window; - }, - - isNumeric: function( obj ) { - // parseFloat NaNs numeric-cast false positives (null|true|false|"") - // ...but misinterprets leading-number strings, particularly hex literals ("0x...") - // subtraction forces infinities to NaN - // adding 1 corrects loss of precision from parseFloat (#15100) - return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0; - }, - - isPlainObject: function( obj ) { - // Not plain objects: - // - Any object or value whose internal [[Class]] property is not "[object Object]" - // - DOM nodes - // - window - if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.constructor && - !hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { - return false; - } - - // If the function hasn't returned already, we're confident that - // |obj| is a plain object, created by {} or constructed with new Object - return true; - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - type: function( obj ) { - if ( obj == null ) { - return obj + ""; - } - // Support: Android<4.0, iOS<6 (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? - class2type[ toString.call(obj) ] || "object" : - typeof obj; - }, - - // Evaluates a script in a global context - globalEval: function( code ) { - var script, - indirect = eval; - - code = jQuery.trim( code ); - - if ( code ) { - // If the code includes a valid, prologue position - // strict mode pragma, execute code by injecting a - // script tag into the document. - if ( code.indexOf("use strict") === 1 ) { - script = document.createElement("script"); - script.text = code; - document.head.appendChild( script ).parentNode.removeChild( script ); - } else { - // Otherwise, avoid the DOM node creation, insertion - // and removal by using an indirect global eval - indirect( code ); - } - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Support: IE9-11+ - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function( obj, callback, args ) { - var value, - i = 0, - length = obj.length, - isArray = isArraylike( obj ); - - if ( args ) { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.apply( obj[ i ], args ); - - if ( value === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } else { - for ( i in obj ) { - value = callback.call( obj[ i ], i, obj[ i ] ); - - if ( value === false ) { - break; - } - } - } - } - - return obj; - }, - - // Support: Android<4.1 - trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var ret = results || []; - - if ( arr != null ) { - if ( isArraylike( Object(arr) ) ) { - jQuery.merge( ret, - typeof arr === "string" ? - [ arr ] : arr - ); - } else { - push.call( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - return arr == null ? -1 : indexOf.call( arr, elem, i ); - }, - - merge: function( first, second ) { - var len = +second.length, - j = 0, - i = first.length; - - for ( ; j < len; j++ ) { - first[ i++ ] = second[ j ]; - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, invert ) { - var callbackInverse, - matches = [], - i = 0, - length = elems.length, - callbackExpect = !invert; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - callbackInverse = !callback( elems[ i ], i ); - if ( callbackInverse !== callbackExpect ) { - matches.push( elems[ i ] ); - } - } - - return matches; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, - i = 0, - length = elems.length, - isArray = isArraylike( elems ), - ret = []; - - // Go through the array, translating each of the items to their new values - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - - // Go through every key on the object, - } else { - for ( i in elems ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret.push( value ); - } - } - } - - // Flatten any nested arrays - return concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - now: Date.now, - - // jQuery.support is not used in Core but other projects attach their - // properties to it so it needs to exist. - support: support -}); - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -function isArraylike( obj ) { - var length = obj.length, - type = jQuery.type( obj ); - - if ( type === "function" || jQuery.isWindow( obj ) ) { - return false; - } - - if ( obj.nodeType === 1 && length ) { - return true; - } - - return type === "array" || length === 0 || - typeof length === "number" && length > 0 && ( length - 1 ) in obj; -} -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.2.0-pre - * http://sizzlejs.com/ - * - * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: 2014-12-16 - */ -(function( window ) { - -var i, - support, - Expr, - getText, - isXML, - tokenize, - compile, - select, - outermostContext, - sortInput, - hasDuplicate, - - // Local document vars - setDocument, - document, - docElem, - documentIsHTML, - rbuggyQSA, - rbuggyMatches, - matches, - contains, - - // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, - dirruns = 0, - done = 0, - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - sortOrder = function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - } - return 0; - }, - - // General-purpose constants - MAX_NEGATIVE = 1 << 31, - - // Instance methods - hasOwn = ({}).hasOwnProperty, - arr = [], - pop = arr.pop, - push_native = arr.push, - push = arr.push, - slice = arr.slice, - // Use a stripped-down indexOf as it's faster than native - // http://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[i] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", - - // Regular expressions - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace + - // Operator (capture 2) - "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" - "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + - "*\\]", - - pseudos = ":(" + characterEncoding + ")(?:\\((" + - // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: - // 1. quoted (capture 3; capture 4 or capture 5) - "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + - // 2. simple (capture 6) - "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + - // 3. anything else (capture 2) - ".*" + - ")\\)|)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), - - rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), - - rpseudo = new RegExp( pseudos ), - ridentifier = new RegExp( "^" + identifier + "$" ), - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), - // For use in libraries implementing .is() - // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + - whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) - }, - - rinputs = /^(?:input|select|textarea|button)$/i, - rheader = /^h\d$/i, - - rnative = /^[^{]+\{\s*\[native \w/, - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, - - rsibling = /[+~]/, - rescape = /'|\\/g, - - // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), - funescape = function( _, escaped, escapedWhitespace ) { - var high = "0x" + escaped - 0x10000; - // NaN means non-codepoint - // Support: Firefox<24 - // Workaround erroneous numeric interpretation of +"0x" - return high !== high || escapedWhitespace ? - escaped : - high < 0 ? - // BMP codepoint - String.fromCharCode( high + 0x10000 ) : - // Supplemental Plane codepoint (surrogate pair) - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // Used for iframes - // See setDocument() - // Removing the function wrapper causes a "Permission Denied" - // error in IE - unloadHandler = function() { - setDocument(); - }; - -// Optimize for push.apply( _, NodeList ) -try { - push.apply( - (arr = slice.call( preferredDoc.childNodes )), - preferredDoc.childNodes - ); - // Support: Android<4.0 - // Detect silently failing push.apply - arr[ preferredDoc.childNodes.length ].nodeType; -} catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { - push_native.apply( target, slice.call(els) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - // Can't trust NodeList.length - while ( (target[j++] = els[i++]) ) {} - target.length = j - 1; - } - }; -} - -function Sizzle( selector, context, results, seed ) { - var match, elem, m, nodeType, - // QSA vars - i, groups, old, nid, newContext, newSelector; - - if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { - setDocument( context ); - } - - context = context || document; - results = results || []; - nodeType = context.nodeType; - - if ( typeof selector !== "string" || !selector || - nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - - return results; - } - - if ( !seed && documentIsHTML ) { - - // Try to shortcut find operations when possible (e.g., not under DocumentFragment) - if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document (jQuery #6963) - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, context.getElementsByTagName( selector ) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && support.getElementsByClassName ) { - push.apply( results, context.getElementsByClassName( m ) ); - return results; - } - } - - // QSA path - if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - nid = old = expando; - newContext = context; - newSelector = nodeType !== 1 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + toSelector( groups[i] ); - } - newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, - newContext.querySelectorAll( newSelector ) - ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); -} - -/** - * Create key-value caches of limited size - * @returns {Function(string, Object)} Returns the Object data after storing it on itself with - * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) - * deleting the oldest entry - */ -function createCache() { - var keys = []; - - function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) - if ( keys.push( key + " " ) > Expr.cacheLength ) { - // Only keep the most recent entries - delete cache[ keys.shift() ]; - } - return (cache[ key + " " ] = value); - } - return cache; -} - -/** - * Mark a function for special use by Sizzle - * @param {Function} fn The function to mark - */ -function markFunction( fn ) { - fn[ expando ] = true; - return fn; -} - -/** - * Support testing using an element - * @param {Function} fn Passed the created div and expects a boolean result - */ -function assert( fn ) { - var div = document.createElement("div"); - - try { - return !!fn( div ); - } catch (e) { - return false; - } finally { - // Remove from its parent by default - if ( div.parentNode ) { - div.parentNode.removeChild( div ); - } - // release memory in IE - div = null; - } -} - -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split("|"), - i = attrs.length; - - while ( i-- ) { - Expr.attrHandle[ arr[i] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - ( ~b.sourceIndex || MAX_NEGATIVE ) - - ( ~a.sourceIndex || MAX_NEGATIVE ); - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( (cur = cur.nextSibling) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - -/** - * Returns a function to use in pseudos for input types - * @param {String} type - */ -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for buttons - * @param {String} type - */ -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -/** - * Returns a function to use in pseudos for positionals - * @param {Function} fn - */ -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Checks a node for validity as a Sizzle context - * @param {Element|Object=} context - * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value - */ -function testContext( context ) { - return context && typeof context.getElementsByTagName !== "undefined" && context; -} - -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -/** - * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document - * @returns {Object} Returns the current document - */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, parent, - doc = node ? node.ownerDocument || node : preferredDoc; - - // If no document and documentElement is available, return - if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { - return document; - } - - // Set our document - document = doc; - docElem = doc.documentElement; - parent = doc.defaultView; - - // Support: IE>8 - // If iframe document is assigned to "document" variable and if iframe has been reloaded, - // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936 - // IE6-8 do not support the defaultView property so parent will be undefined - if ( parent && parent !== parent.top ) { - // IE11 does not have attachEvent, so all must suffer - if ( parent.addEventListener ) { - parent.addEventListener( "unload", unloadHandler, false ); - } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", unloadHandler ); - } - } - - /* Support tests - ---------------------------------------------------------------------- */ - documentIsHTML = !isXML( doc ); - - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert(function( div ) { - div.className = "i"; - return !div.getAttribute("className"); - }); - - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert(function( div ) { - div.appendChild( doc.createComment("") ); - return !div.getElementsByTagName("*").length; - }); - - // Support: IE<9 - support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert(function( div ) { - docElem.appendChild( div ).id = expando; - return !doc.getElementsByName || !doc.getElementsByName( expando ).length; - }); - - // ID find and filter - if ( support.getById ) { - Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [ m ] : []; - } - }; - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - return elem.getAttribute("id") === attrId; - }; - }; - } else { - // Support: IE6/7 - // getElementById is not reliable as a find shortcut - delete Expr.find["ID"]; - - Expr.filter["ID"] = function( id ) { - var attrId = id.replace( runescape, funescape ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); - return node && node.value === attrId; - }; - }; - } - - // Tag - Expr.find["TAG"] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - while ( (elem = results[i++]) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; - - // Class - Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( documentIsHTML ) { - return context.getElementsByClassName( className ); - } - }; - - /* QSA/matchesSelector - ---------------------------------------------------------------------- */ - - // QSA and matchesSelector support - - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See http://bugs.jquery.com/ticket/13378 - rbuggyQSA = []; - - if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) { - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - docElem.appendChild( div ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowcapture^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } - - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ - if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push("~="); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibing-combinator selector` fails - if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push(".#.+[+~]"); - } - }); - - assert(function( div ) { - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = doc.createElement("input"); - input.setAttribute( "type", "hidden" ); - div.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( div.querySelectorAll("[name=d]").length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } - - // Opera 10-11 does not throw on post-comma invalid pseudos - div.querySelectorAll("*,:x"); - rbuggyQSA.push(",.*:"); - }); - } - - if ( (support.matchesSelector = rnative.test( (matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector) )) ) { - - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( div, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - }); - } - - rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully does not implement inclusive descendent - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - /* Sorting - ---------------------------------------------------------------------- */ - - // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { - - // Flag for duplicate removal - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - // Sort on method existence if only one input has compareDocumentPosition - var compare = !a.compareDocumentPosition - !b.compareDocumentPosition; - if ( compare ) { - return compare; - } - - // Calculate position if both inputs belong to the same document - compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ? - a.compareDocumentPosition( b ) : - - // Otherwise we know they are disconnected - 1; - - // Disconnected nodes - if ( compare & 1 || - (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) { - - // Choose the first element that is related to our preferred document - if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) { - return -1; - } - if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) { - return 1; - } - - // Maintain original order - return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - } - - return compare & 4 ? -1 : 1; - } : - function( a, b ) { - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - return a === doc ? -1 : - b === doc ? 1 : - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( (cur = cur.parentNode) ) { - ap.unshift( cur ); - } - cur = b; - while ( (cur = cur.parentNode) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[i] === bp[i] ) { - i++; - } - - return i ? - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[i], bp[i] ) : - - // Otherwise nodes in our document sort first - ap[i] === preferredDoc ? -1 : - bp[i] === preferredDoc ? 1 : - 0; - }; - - return doc; -}; - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - if ( support.matchesSelector && documentIsHTML && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { - - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch (e) {} - } - - return Sizzle( expr, document, null, [ elem ] ).length > 0; -}; - -Sizzle.contains = function( context, elem ) { - // Set document vars if needed - if ( ( context.ownerDocument || context ) !== document ) { - setDocument( context ); - } - return contains( context, elem ); -}; - -Sizzle.attr = function( elem, name ) { - // Set document vars if needed - if ( ( elem.ownerDocument || elem ) !== document ) { - setDocument( elem ); - } - - var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) - val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? - fn( elem, name, !documentIsHTML ) : - undefined; - - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - (val = elem.getAttributeNode(name)) && val.specified ? - val.value : - null; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -/** - * Document sorting and removing duplicates - * @param {ArrayLike} results - */ -Sizzle.uniqueSort = function( results ) { - var elem, - duplicates = [], - j = 0, - i = 0; - - // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); - - if ( hasDuplicate ) { - while ( (elem = results[i++]) ) { - if ( elem === results[ i ] ) { - j = duplicates.push( i ); - } - } - while ( j-- ) { - results.splice( duplicates[ j ], 1 ); - } - } - - // Clear input after sorting to release objects - // See https://github.com/jquery/sizzle/pull/225 - sortInput = null; - - return results; -}; - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - // If no nodeType, this is expected to be an array - while ( (node = elem[i++]) ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - - return ret; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - attrHandle: {}, - - find: {}, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( runescape, funescape ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 what (child|of-type) - 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 4 xn-component of xn+y argument ([+-]?\d*n|) - 5 sign of xn-component - 6 x of xn-component - 7 sign of y-component - 8 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1].slice( 0, 3 ) === "nth" ) { - // nth-* requires argument - if ( !match[3] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); - match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" ); - - // other types prohibit arguments - } else if ( match[3] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var excess, - unquoted = !match[6] && match[2]; - - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - // Accept quoted arguments as-is - if ( match[3] ) { - match[2] = match[4] || match[5] || ""; - - // Strip excess characters from unquoted arguments - } else if ( unquoted && rpseudo.test( unquoted ) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - match[0] = match[0].slice( 0, excess ); - match[2] = unquoted.slice( 0, excess ); - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); - return nodeNameSelector === "*" ? - function() { return true; } : - function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ className + " " ]; - - return pattern || - (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && - classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); - }); - }, - - "ATTR": function( name, operator, check ) { - return function( elem ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, what, argument, first, last ) { - var simple = type.slice( 0, 3 ) !== "nth", - forward = type.slice( -4 ) !== "last", - ofType = what === "of-type"; - - return first === 1 && last === 0 ? - - // Shortcut for :nth-*(n) - function( elem ) { - return !!elem.parentNode; - } : - - function( elem, context, xml ) { - var cache, outerCache, node, diff, nodeIndex, start, - dir = simple !== forward ? "nextSibling" : "previousSibling", - parent = elem.parentNode, - name = ofType && elem.nodeName.toLowerCase(), - useCache = !xml && !ofType; - - if ( parent ) { - - // :(first|last|only)-(child|of-type) - if ( simple ) { - while ( dir ) { - node = elem; - while ( (node = node[ dir ]) ) { - if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { - return false; - } - } - // Reverse direction for :only-* (if we haven't yet done so) - start = dir = type === "only" && !start && "nextSibling"; - } - return true; - } - - start = [ forward ? parent.firstChild : parent.lastChild ]; - - // non-xml :nth-child(...) stores cache data on `parent` - if ( forward && useCache ) { - // Seek `elem` from a previously-cached index - outerCache = parent[ expando ] || (parent[ expando ] = {}); - cache = outerCache[ type ] || []; - nodeIndex = cache[0] === dirruns && cache[1]; - diff = cache[0] === dirruns && cache[2]; - node = nodeIndex && parent.childNodes[ nodeIndex ]; - - while ( (node = ++nodeIndex && node && node[ dir ] || - - // Fallback to seeking `elem` from the start - (diff = nodeIndex = 0) || start.pop()) ) { - - // When found, cache indexes on `parent` and break - if ( node.nodeType === 1 && ++diff && node === elem ) { - outerCache[ type ] = [ dirruns, nodeIndex, diff ]; - break; - } - } - - // Use previously-cached element index if available - } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { - diff = cache[1]; - - // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) - } else { - // Use the same loop as above to seek `elem` from the start - while ( (node = ++nodeIndex && node && node[ dir ] || - (diff = nodeIndex = 0) || start.pop()) ) { - - if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { - // Cache the index of each encountered element - if ( useCache ) { - (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; - } - - if ( node === elem ) { - break; - } - } - } - } - - // Incorporate the offset, then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - // Potentially complex pseudos - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - // Don't keep the element (issue #299) - input[0] = null; - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - text = text.replace( runescape, funescape ); - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - // "Whether an element is represented by a :lang() selector - // is based solely on the element's language value - // being equal to the identifier C, - // or beginning with the identifier C immediately followed by "-". - // The matching of C against the element's language value is performed case-insensitively. - // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { - // lang value must be a valid identifier - if ( !ridentifier.test(lang || "") ) { - Sizzle.error( "unsupported lang: " + lang ); - } - lang = lang.replace( runescape, funescape ).toLowerCase(); - return function( elem ) { - var elemLang; - do { - if ( (elemLang = documentIsHTML ? - elem.lang : - elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) { - - elemLang = elemLang.toLowerCase(); - return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; - } - } while ( (elem = elem.parentNode) && elem.nodeType === 1 ); - return false; - }; - }), - - // Miscellaneous - "target": function( elem ) { - var hash = window.location && window.location.hash; - return hash && hash.slice( 1 ) === elem.id; - }, - - "root": function( elem ) { - return elem === docElem; - }, - - "focus": function( elem ) { - return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - }, - - // Boolean properties - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - // Contents - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), - // but not by others (comment: 8; processing instruction: 7; etc.) - // nodeType < 6 works because attributes (2) do not appear as children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - if ( elem.nodeType < 6 ) { - return false; - } - } - return true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - // Element/input types - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "text": function( elem ) { - var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && - - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" ); - }, - - // Position-in-collection - "first": createPositionalPseudo(function() { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length ) { - var i = 0; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length ) { - var i = 1; - for ( ; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - var i = argument < 0 ? argument + length : argument; - for ( ; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Add button/input type pseudos -for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { - Expr.pseudos[ i ] = createInputPseudo( i ); -} -for ( i in { submit: true, reset: true } ) { - Expr.pseudos[ i ] = createButtonPseudo( i ); -} - -// Easy API for creating new setFilters -function setFilters() {} -setFilters.prototype = Expr.filters = Expr.pseudos; -Expr.setFilters = new setFilters(); - -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { - var matched, match, tokens, type, - soFar, groups, preFilters, - cached = tokenCache[ selector + " " ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - // Don't consume trailing commas as valid - soFar = soFar.slice( match[0].length ) || soFar; - } - groups.push( (tokens = []) ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - matched = match.shift(); - tokens.push({ - value: matched, - // Cast descendant combinators to space - type: match[0].replace( rtrim, " " ) - }); - soFar = soFar.slice( matched.length ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - (match = preFilters[ type ]( match ))) ) { - matched = match.shift(); - tokens.push({ - value: matched, - type: type, - matches: match - }); - soFar = soFar.slice( matched.length ); - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; - -function toSelector( tokens ) { - var i = 0, - len = tokens.length, - selector = ""; - for ( ; i < len; i++ ) { - selector += tokens[i].value; - } - return selector; -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - var oldCache, outerCache, - newCache = [ dirruns, doneName ]; - - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( xml ) { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - if ( matcher( elem, context, xml ) ) { - return true; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( elem.nodeType === 1 || checkNonElements ) { - outerCache = elem[ expando ] || (elem[ expando ] = {}); - if ( (oldCache = outerCache[ dir ]) && - oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { - - // Assign to newCache so results back-propagate to previous elements - return (newCache[ 2 ] = oldCache[ 2 ]); - } else { - // Reuse newcache so results back-propagate to previous elements - outerCache[ dir ] = newCache; - - // A match means we're done; a fail means we have to keep checking - if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) { - return true; - } - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function multipleContexts( selector, contexts, results ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results ); - } - return results; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - var temp, i, elem, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - temp = condense( matcherOut, postMap ); - postFilter( temp, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = temp.length; - while ( i-- ) { - if ( (elem = temp[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - if ( seed ) { - if ( postFinder || preFilter ) { - if ( postFinder ) { - // Get the final matcherOut by condensing this intermediate into postFinder contexts - temp = []; - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - // Restore matcherIn since elem is not yet a final match - temp.push( (matcherIn[i] = elem) ); - } - } - postFinder( null, (matcherOut = []), temp, xml ); - } - - // Move matched elements from seed to results to keep them synchronized - i = matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { - - seed[temp] = !(results[temp] = elem); - } - } - } - - // Add elements to results, through postFinder if defined - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) - checkContext = null; - return ret; - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; - } else { - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" }) - ).replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && toSelector( tokens ) - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, outermost ) { - var elem, j, matcher, - matchedCount = 0, - i = "0", - unmatched = seed && [], - setMatched = [], - contextBackup = outermostContext, - // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find["TAG"]( "*", outermost ), - // Use integer dirruns iff this is the outermost matcher - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1), - len = elems.length; - - if ( outermost ) { - outermostContext = context !== document && context; - } - - // Add elements passing elementMatchers directly to results - // Keep `i` a string if there are no elements so `matchedCount` will be "00" below - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id - for ( ; i !== len && (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - j = 0; - while ( (matcher = elementMatchers[j++]) ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - j = 0; - while ( (matcher = setMatchers[j++]) ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ selector + " " ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !match ) { - match = tokenize( selector ); - } - i = match.length; - while ( i-- ) { - cached = matcherFromTokens( match[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - - // Save selector and tokenization - cached.selector = selector; - } - return cached; -}; - -/** - * A low-level selection function that works with Sizzle's compiled - * selector functions - * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile - * @param {Element} context - * @param {Array} [results] - * @param {Array} [seed] A set of elements to match against - */ -select = Sizzle.select = function( selector, context, results, seed ) { - var i, tokens, token, type, find, - compiled = typeof selector === "function" && selector, - match = !seed && tokenize( (selector = compiled.selector || selector) ); - - results = results || []; - - // Try to minimize operations if there is no seed and only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - support.getById && context.nodeType === 9 && documentIsHTML && - Expr.relative[ tokens[1].type ] ) { - - context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0]; - if ( !context ) { - return results; - - // Precompiled matchers will still verify ancestry, so step up a level - } else if ( compiled ) { - context = context.parentNode; - } - - selector = selector.slice( tokens.shift().value.length ); - } - - // Fetch a seed set for right-to-left matching - i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; - while ( i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( runescape, funescape ), - rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && toSelector( tokens ); - if ( !selector ) { - push.apply( results, seed ); - return results; - } - - break; - } - } - } - } - - // Compile and execute a filtering function if one is not provided - // Provide `match` to avoid retokenization if we modified the selector above - ( compiled || compile( selector, match ) )( - seed, - context, - !documentIsHTML, - results, - rsibling.test( selector ) && testContext( context.parentNode ) || context - ); - return results; -}; - -// One-time assignments - -// Sort stability -support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; - -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - -// Initialize against the default document -setDocument(); - -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) -// Detached nodes confoundingly follow *each other* -support.sortDetached = assert(function( div1 ) { - // Should return 1, but returns 4 (following) - return div1.compareDocumentPosition( document.createElement("div") ) & 1; -}); - -// Support: IE<8 -// Prevent attribute/property "interpolation" -// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert(function( div ) { - div.innerHTML = ""; - return div.firstChild.getAttribute("href") === "#" ; -}) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - }); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert(function( div ) { - div.innerHTML = ""; - div.firstChild.setAttribute( "value", "" ); - return div.firstChild.getAttribute( "value" ) === ""; -}) ) { - addHandle( "value", function( elem, name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - }); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert(function( div ) { - return div.getAttribute("disabled") == null; -}) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - (val = elem.getAttributeNode( name )) && val.specified ? - val.value : - null; - } - }); -} - -return Sizzle; - -})( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - - -var rneedsContext = jQuery.expr.match.needsContext; - -var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); - - - -var risSimple = /^.[^:#\[\.,]*$/; - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, not ) { - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep( elements, function( elem, i ) { - /* jshint -W018 */ - return !!qualifier.call( elem, i, elem ) !== not; - }); - - } - - if ( qualifier.nodeType ) { - return jQuery.grep( elements, function( elem ) { - return ( elem === qualifier ) !== not; - }); - - } - - if ( typeof qualifier === "string" ) { - if ( risSimple.test( qualifier ) ) { - return jQuery.filter( qualifier, elements, not ); - } - - qualifier = jQuery.filter( qualifier, elements ); - } - - return jQuery.grep( elements, function( elem ) { - return ( indexOf.call( qualifier, elem ) >= 0 ) !== not; - }); -} - -jQuery.filter = function( expr, elems, not ) { - var elem = elems[ 0 ]; - - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 && elem.nodeType === 1 ? - jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : - jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { - return elem.nodeType === 1; - })); -}; - -jQuery.fn.extend({ - find: function( selector ) { - var i, - len = this.length, - ret = [], - self = this; - - if ( typeof selector !== "string" ) { - return this.pushStack( jQuery( selector ).filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }) ); - } - - for ( i = 0; i < len; i++ ) { - jQuery.find( selector, self[ i ], ret ); - } - - // Needed because $( selector, context ) becomes $( context ).find( selector ) - ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); - ret.selector = this.selector ? this.selector + " " + selector : selector; - return ret; - }, - filter: function( selector ) { - return this.pushStack( winnow(this, selector || [], false) ); - }, - not: function( selector ) { - return this.pushStack( winnow(this, selector || [], true) ); - }, - is: function( selector ) { - return !!winnow( - this, - - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - typeof selector === "string" && rneedsContext.test( selector ) ? - jQuery( selector ) : - selector || [], - false - ).length; - } -}); - - -// Initialize a jQuery object - - -// A central reference to the root jQuery(document) -var rootjQuery, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) - rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - - init = jQuery.fn.init = function( selector, context ) { - var match, elem; - - // HANDLE: $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector[0] === "<" && selector[ selector.length - 1 ] === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - - // Option to run scripts is true for back-compat - // Intentionally let the error be thrown if parseHTML is not present - jQuery.merge( this, jQuery.parseHTML( - match[1], - context && context.nodeType ? context.ownerDocument || context : document, - true - ) ); - - // HANDLE: $(html, props) - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - for ( match in context ) { - // Properties of context are called as methods if possible - if ( jQuery.isFunction( this[ match ] ) ) { - this[ match ]( context[ match ] ); - - // ...and otherwise set as attributes - } else { - this.attr( match, context[ match ] ); - } - } - } - - return this; - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Support: Blackberry 4.6 - // gEBID returns nodes no longer in the document (#6963) - if ( elem && elem.parentNode ) { - // Inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(DOMElement) - } else if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return typeof rootjQuery.ready !== "undefined" ? - rootjQuery.ready( selector ) : - // Execute immediately if ready is not present - selector( jQuery ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }; - -// Give the init function the jQuery prototype for later instantiation -init.prototype = jQuery.fn; - -// Initialize central reference -rootjQuery = jQuery( document ); - - -var rparentsprev = /^(?:parents|prev(?:Until|All))/, - // Methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.extend({ - dir: function( elem, dir, until ) { - var matched = [], - truncate = until !== undefined; - - while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { - if ( elem.nodeType === 1 ) { - if ( truncate && jQuery( elem ).is( until ) ) { - break; - } - matched.push( elem ); - } - } - return matched; - }, - - sibling: function( n, elem ) { - var matched = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - matched.push( n ); - } - } - - return matched; - } -}); - -jQuery.fn.extend({ - has: function( target ) { - var targets = jQuery( target, this ), - l = targets.length; - - return this.filter(function() { - var i = 0; - for ( ; i < l; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - matched = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { - // Always skip document fragments - if ( cur.nodeType < 11 && (pos ? - pos.index(cur) > -1 : - - // Don't pass non-elements to Sizzle - cur.nodeType === 1 && - jQuery.find.matchesSelector(cur, selectors)) ) { - - matched.push( cur ); - break; - } - } - } - - return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); - }, - - // Determine the position of an element within the set - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; - } - - // Index in selector - if ( typeof elem === "string" ) { - return indexOf.call( jQuery( elem ), this[ 0 ] ); - } - - // Locate the position of the desired element - return indexOf.call( this, - - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[ 0 ] : elem - ); - }, - - add: function( selector, context ) { - return this.pushStack( - jQuery.unique( - jQuery.merge( this.get(), jQuery( selector, context ) ) - ) - ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } -}); - -function sibling( cur, dir ) { - while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} - return cur; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return elem.contentDocument || jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var matched = jQuery.map( this, fn, until ); - - if ( name.slice( -5 ) !== "Until" ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - matched = jQuery.filter( selector, matched ); - } - - if ( this.length > 1 ) { - // Remove duplicates - if ( !guaranteedUnique[ name ] ) { - jQuery.unique( matched ); - } - - // Reverse order for parents* and prev-derivatives - if ( rparentsprev.test( name ) ) { - matched.reverse(); - } - } - - return this.pushStack( matched ); - }; -}); -var rnotwhite = (/\S+/g); - - - -// String to Object options format cache -var optionsCache = {}; - -// Convert String-formatted options into Object-formatted ones and store in cache -function createOptions( options ) { - var object = optionsCache[ options ] = {}; - jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) { - object[ flag ] = true; - }); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : - jQuery.extend( {}, options ); - - var // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { - jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" ) { - if ( !options.unique || !self.has( arg ) ) { - list.push( arg ); - } - } else if ( arg && arg.length && type !== "string" ) { - // Inspect recursively - add( arg ); - } - }); - })( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if ( memory ) { - firingStart = start; - fire( memory ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; - } - } - } - }); - } - return this; - }, - // Check if a given callback is in the list. - // If no argument is given, return whether or not list has callbacks attached. - has: function( fn ) { - return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); - }, - // Remove all callbacks from the list - empty: function() { - list = []; - firingLength = 0; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - if ( list && ( !fired || stack ) ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - if ( firing ) { - stack.push( args ); - } else { - fire( args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; - - -jQuery.extend({ - - Deferred: function( func ) { - var tuples = [ - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred(function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ](function() { - var returned = fn && fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); - } - }); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; - - // Handle state - if ( stateString ) { - list.add(function() { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] - deferred[ tuple[0] ] = function() { - deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); - return this; - }; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value; - if ( values === progressValues ) { - deferred.notifyWith( contexts, values ); - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // Add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); - } else { - --remaining; - } - } - } - - // If we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } -}); - - -// The deferred used on DOM ready -var readyList; - -jQuery.fn.ready = function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); - - return this; -}; - -jQuery.extend({ - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.triggerHandler ) { - jQuery( document ).triggerHandler( "ready" ); - jQuery( document ).off( "ready" ); - } - } -}); - -/** - * The ready event handler and self cleanup method - */ -function completed() { - document.removeEventListener( "DOMContentLoaded", completed, false ); - window.removeEventListener( "load", completed, false ); - jQuery.ready(); -} - -jQuery.ready.promise = function( obj ) { - if ( !readyList ) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // We once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready ); - - } else { - - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", completed, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", completed, false ); - } - } - return readyList.promise( obj ); -}; - -// Kick off the DOM ready check even if the user does not -jQuery.ready.promise(); - - - - -// Multifunctional method to get and set values of a collection -// The value/s can optionally be executed if it's a function -var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) { - var i = 0, - len = elems.length, - bulk = key == null; - - // Sets many values - if ( jQuery.type( key ) === "object" ) { - chainable = true; - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); - } - - // Sets one value - } else if ( value !== undefined ) { - chainable = true; - - if ( !jQuery.isFunction( value ) ) { - raw = true; - } - - if ( bulk ) { - // Bulk operations run against the entire set - if ( raw ) { - fn.call( elems, value ); - fn = null; - - // ...except when executing function values - } else { - bulk = fn; - fn = function( elem, key, value ) { - return bulk.call( jQuery( elem ), value ); - }; - } - } - - if ( fn ) { - for ( ; i < len; i++ ) { - fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); - } - } - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - len ? fn( elems[0], key ) : emptyGet; -}; - - -/** - * Determines whether an object can have data - */ -jQuery.acceptData = function( owner ) { - // Accepts only: - // - Node - // - Node.ELEMENT_NODE - // - Node.DOCUMENT_NODE - // - Object - // - Any - /* jshint -W018 */ - return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType ); -}; - - -function Data() { - // Support: Android<4, - // Old WebKit does not have Object.preventExtensions/freeze method, - // return new empty object instead with no [[set]] accessor - Object.defineProperty( this.cache = {}, 0, { - get: function() { - return {}; - } - }); - - this.expando = jQuery.expando + Data.uid++; -} - -Data.uid = 1; -Data.accepts = jQuery.acceptData; - -Data.prototype = { - key: function( owner ) { - // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. - // Always return the key for a frozen object. - if ( !Data.accepts( owner ) ) { - return 0; - } - - var descriptor = {}, - // Check if the owner object already has a cache key - unlock = owner[ this.expando ]; - - // If not, create one - if ( !unlock ) { - unlock = Data.uid++; - - // Secure it in a non-enumerable, non-writable property - try { - descriptor[ this.expando ] = { value: unlock }; - Object.defineProperties( owner, descriptor ); - - // Support: Android<4 - // Fallback to a less secure definition - } catch ( e ) { - descriptor[ this.expando ] = unlock; - jQuery.extend( owner, descriptor ); - } - } - - // Ensure the cache object - if ( !this.cache[ unlock ] ) { - this.cache[ unlock ] = {}; - } - - return unlock; - }, - set: function( owner, data, value ) { - var prop, - // There may be an unlock assigned to this node, - // if there is no entry for this "owner", create one inline - // and set the unlock as though an owner entry had always existed - unlock = this.key( owner ), - cache = this.cache[ unlock ]; - - // Handle: [ owner, key, value ] args - if ( typeof data === "string" ) { - cache[ data ] = value; - - // Handle: [ owner, { properties } ] args - } else { - // Fresh assignments by object are shallow copied - if ( jQuery.isEmptyObject( cache ) ) { - jQuery.extend( this.cache[ unlock ], data ); - // Otherwise, copy the properties one-by-one to the cache object - } else { - for ( prop in data ) { - cache[ prop ] = data[ prop ]; - } - } - } - return cache; - }, - get: function( owner, key ) { - // Either a valid cache is found, or will be created. - // New caches will be created and the unlock returned, - // allowing direct access to the newly created - // empty data object. A valid owner object must be provided. - var cache = this.cache[ this.key( owner ) ]; - - return key === undefined ? - cache : cache[ key ]; - }, - access: function( owner, key, value ) { - var stored; - // In cases where either: - // - // 1. No key was specified - // 2. A string key was specified, but no value provided - // - // Take the "read" path and allow the get method to determine - // which value to return, respectively either: - // - // 1. The entire cache object - // 2. The data stored at the key - // - if ( key === undefined || - ((key && typeof key === "string") && value === undefined) ) { - - stored = this.get( owner, key ); - - return stored !== undefined ? - stored : this.get( owner, jQuery.camelCase(key) ); - } - - // [*]When the key is not a string, or both a key and value - // are specified, set or extend (existing objects) with either: - // - // 1. An object of properties - // 2. A key and value - // - this.set( owner, key, value ); - - // Since the "set" path can have two possible entry points - // return the expected data based on which path was taken[*] - return value !== undefined ? value : key; - }, - remove: function( owner, key ) { - var i, name, camel, - unlock = this.key( owner ), - cache = this.cache[ unlock ]; - - if ( key === undefined ) { - this.cache[ unlock ] = {}; - - } else { - // Support array or space separated string of keys - if ( jQuery.isArray( key ) ) { - // If "name" is an array of keys... - // When data is initially created, via ("key", "val") signature, - // keys will be converted to camelCase. - // Since there is no way to tell _how_ a key was added, remove - // both plain key and camelCase key. #12786 - // This will only penalize the array argument path. - name = key.concat( key.map( jQuery.camelCase ) ); - } else { - camel = jQuery.camelCase( key ); - // Try the string as a key before any manipulation - if ( key in cache ) { - name = [ key, camel ]; - } else { - // If a key with the spaces exists, use it. - // Otherwise, create an array by matching non-whitespace - name = camel; - name = name in cache ? - [ name ] : ( name.match( rnotwhite ) || [] ); - } - } - - i = name.length; - while ( i-- ) { - delete cache[ name[ i ] ]; - } - } - }, - hasData: function( owner ) { - return !jQuery.isEmptyObject( - this.cache[ owner[ this.expando ] ] || {} - ); - }, - discard: function( owner ) { - if ( owner[ this.expando ] ) { - delete this.cache[ owner[ this.expando ] ]; - } - } -}; -var data_priv = new Data(); - -var data_user = new Data(); - - - -// Implementation Summary -// -// 1. Enforce API surface and semantic compatibility with 1.9.x branch -// 2. Improve the module's maintainability by reducing the storage -// paths to a single mechanism. -// 3. Use the same single mechanism to support "private" and "user" data. -// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) -// 5. Avoid exposing implementation details on user objects (eg. expando properties) -// 6. Provide a clear path for implementation upgrade to WeakMap in 2014 - -var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, - rmultiDash = /([A-Z])/g; - -function dataAttr( elem, key, data ) { - var name; - - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - data_user.set( elem, key, data ); - } else { - data = undefined; - } - } - return data; -} - -jQuery.extend({ - hasData: function( elem ) { - return data_user.hasData( elem ) || data_priv.hasData( elem ); - }, - - data: function( elem, name, data ) { - return data_user.access( elem, name, data ); - }, - - removeData: function( elem, name ) { - data_user.remove( elem, name ); - }, - - // TODO: Now that all calls to _data and _removeData have been replaced - // with direct calls to data_priv methods, these can be deprecated. - _data: function( elem, name, data ) { - return data_priv.access( elem, name, data ); - }, - - _removeData: function( elem, name ) { - data_priv.remove( elem, name ); - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var i, name, data, - elem = this[ 0 ], - attrs = elem && elem.attributes; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = data_user.get( elem ); - - if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { - i = attrs.length; - while ( i-- ) { - - // Support: IE11+ - // The attrs elements can be null (#14894) - if ( attrs[ i ] ) { - name = attrs[ i ].name; - if ( name.indexOf( "data-" ) === 0 ) { - name = jQuery.camelCase( name.slice(5) ); - dataAttr( elem, name, data[ name ] ); - } - } - } - data_priv.set( elem, "hasDataAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - data_user.set( this, key ); - }); - } - - return access( this, function( value ) { - var data, - camelKey = jQuery.camelCase( key ); - - // The calling jQuery object (element matches) is not empty - // (and therefore has an element appears at this[ 0 ]) and the - // `value` parameter was not undefined. An empty jQuery object - // will result in `undefined` for elem = this[ 0 ] which will - // throw an exception if an attempt to read a data cache is made. - if ( elem && value === undefined ) { - // Attempt to get data from the cache - // with the key as-is - data = data_user.get( elem, key ); - if ( data !== undefined ) { - return data; - } - - // Attempt to get data from the cache - // with the key camelized - data = data_user.get( elem, camelKey ); - if ( data !== undefined ) { - return data; - } - - // Attempt to "discover" the data in - // HTML5 custom data-* attrs - data = dataAttr( elem, camelKey, undefined ); - if ( data !== undefined ) { - return data; - } - - // We tried really hard, but the data doesn't exist. - return; - } - - // Set the data... - this.each(function() { - // First, attempt to store a copy or reference of any - // data that might've been store with a camelCased key. - var data = data_user.get( this, camelKey ); - - // For HTML5 data-* attribute interop, we have to - // store property names with dashes in a camelCase form. - // This might not apply to all properties...* - data_user.set( this, camelKey, value ); - - // *... In the case of properties that might _actually_ - // have dashes, we need to also store a copy of that - // unchanged property. - if ( key.indexOf("-") !== -1 && data !== undefined ) { - data_user.set( this, key, value ); - } - }); - }, null, value, arguments.length > 1, null, true ); - }, - - removeData: function( key ) { - return this.each(function() { - data_user.remove( this, key ); - }); - } -}); - - -jQuery.extend({ - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = data_priv.get( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray( data ) ) { - queue = data_priv.access( elem, type, jQuery.makeArray(data) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // Clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // Not public - generate a queueHooks object, or return the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return data_priv.get( elem, key ) || data_priv.access( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - data_priv.remove( elem, [ type + "queue", key ] ); - }) - }); - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); - - // Ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while ( i-- ) { - tmp = data_priv.get( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -}); -var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source; - -var cssExpand = [ "Top", "Right", "Bottom", "Left" ]; - -var isHidden = function( elem, el ) { - // isHidden might be called from jQuery#filter function; - // in that case, element will be second argument - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); - }; - -var rcheckableType = (/^(?:checkbox|radio)$/i); - - - -(function() { - var fragment = document.createDocumentFragment(), - div = fragment.appendChild( document.createElement( "div" ) ), - input = document.createElement( "input" ); - - // Support: Safari<=5.1 - // Check state lost if the name is set (#11217) - // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) - input.setAttribute( "type", "radio" ); - input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - - // Support: Safari<=5.1, Android<4.2 - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE<=11+ - // Make sure textarea (and checkbox) defaultValue is properly cloned - div.innerHTML = ""; - support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; -})(); -var strundefined = typeof undefined; - - - -support.focusinBubbles = "onfocusin" in window; - - -var - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; - -function returnTrue() { - return true; -} - -function returnFalse() { - return false; -} - -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - global: {}, - - add: function( elem, types, handler, data, selector ) { - - var handleObjIn, eventHandle, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = data_priv.get( elem ); - - // Don't attach events to noData or text/comment nodes (but allow plain objects) - if ( !elemData ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - if ( !(events = elemData.events) ) { - events = elemData.events = {}; - } - if ( !(eventHandle = elemData.handle) ) { - eventHandle = elemData.handle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ? - jQuery.event.dispatch.apply( elem, arguments ) : undefined; - }; - } - - // Handle multiple events separated by a space - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // There *must* be a type, no attaching namespace-only handlers - if ( !type ) { - continue; - } - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: origType, - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - if ( !(handlers = events[ type ]) ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - }, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var j, origCount, tmp, - events, t, handleObj, - special, handlers, type, namespaces, origType, - elemData = data_priv.hasData( elem ) && data_priv.get( elem ); - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = ( types || "" ).match( rnotwhite ) || [ "" ]; - t = types.length; - while ( t-- ) { - tmp = rtypenamespace.exec( types[t] ) || []; - type = origType = tmp[1]; - namespaces = ( tmp[2] || "" ).split( "." ).sort(); - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector ? special.delegateType : special.bindType ) || type; - handlers = events[ type ] || []; - tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); - - // Remove matching events - origCount = j = handlers.length; - while ( j-- ) { - handleObj = handlers[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !tmp || tmp.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - handlers.splice( j, 1 ); - - if ( handleObj.selector ) { - handlers.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( origCount && !handlers.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - data_priv.remove( elem, "events" ); - } - }, - - trigger: function( event, data, elem, onlyHandlers ) { - - var i, cur, tmp, bubbleType, ontype, handle, special, - eventPath = [ elem || document ], - type = hasOwn.call( event, "type" ) ? event.type : event, - namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; - - cur = tmp = elem = elem || document; - - // Don't do events on text and comment nodes - if ( elem.nodeType === 3 || elem.nodeType === 8 ) { - return; - } - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf(".") >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - ontype = type.indexOf(":") < 0 && "on" + type; - - // Caller can pass in a jQuery.Event object, Object, or just an event type string - event = event[ jQuery.expando ] ? - event : - new jQuery.Event( type, typeof event === "object" && event ); - - // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) - event.isTrigger = onlyHandlers ? 2 : 3; - event.namespace = namespaces.join("."); - event.namespace_re = event.namespace ? - new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : - null; - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data == null ? - [ event ] : - jQuery.makeArray( data, [ event ] ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - if ( !rfocusMorph.test( bubbleType + type ) ) { - cur = cur.parentNode; - } - for ( ; cur; cur = cur.parentNode ) { - eventPath.push( cur ); - tmp = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( tmp === (elem.ownerDocument || document) ) { - eventPath.push( tmp.defaultView || tmp.parentWindow || window ); - } - } - - // Fire handlers on the event path - i = 0; - while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { - - event.type = i > 1 ? - bubbleType : - special.bindType || type; - - // jQuery handler - handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - - // Native handler - handle = ontype && cur[ ontype ]; - if ( handle && handle.apply && jQuery.acceptData( cur ) ) { - event.result = handle.apply( cur, data ); - if ( event.result === false ) { - event.preventDefault(); - } - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && - jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - tmp = elem[ ontype ]; - - if ( tmp ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - elem[ type ](); - jQuery.event.triggered = undefined; - - if ( tmp ) { - elem[ ontype ] = tmp; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event ); - - var i, j, ret, matched, handleObj, - handlerQueue = [], - args = slice.call( arguments ), - handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], - special = jQuery.event.special[ event.type ] || {}; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers - handlerQueue = jQuery.event.handlers.call( this, event, handlers ); - - // Run delegates first; they may want to stop propagation beneath us - i = 0; - while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { - event.currentTarget = matched.elem; - - j = 0; - while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { - - // Triggered event must either 1) have no namespace, or 2) have namespace(s) - // a subset or equal to those in the bound event (both can have no namespace). - if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { - - event.handleObj = handleObj; - event.data = handleObj.data; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - if ( (event.result = ret) === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - handlers: function( event, handlers ) { - var i, matches, sel, handleObj, - handlerQueue = [], - delegateCount = handlers.delegateCount, - cur = event.target; - - // Find delegate handlers - // Black-hole SVG instance trees (#13180) - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { - - for ( ; cur !== this; cur = cur.parentNode || this ) { - - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.disabled !== true || event.type !== "click" ) { - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - - // Don't conflict with Object.prototype properties (#13203) - sel = handleObj.selector + " "; - - if ( matches[ sel ] === undefined ) { - matches[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( matches[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, handlers: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( delegateCount < handlers.length ) { - handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); - } - - return handlerQueue; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, copy, - type = event.type, - originalEvent = event, - fixHook = this.fixHooks[ type ]; - - if ( !fixHook ) { - this.fixHooks[ type ] = fixHook = - rmouseEvent.test( type ) ? this.mouseHooks : - rkeyEvent.test( type ) ? this.keyHooks : - {}; - } - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = new jQuery.Event( originalEvent ); - - i = copy.length; - while ( i-- ) { - prop = copy[ i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Support: Cordova 2.5 (WebKit) (#13255) - // All events should have a target; Cordova deviceready doesn't - if ( !event.target ) { - event.target = document; - } - - // Support: Safari 6.0+, Chrome<28 - // Target should not be a text node (#504, #13143) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - focus: { - // Fire native event if possible so blur/focus sequence is correct - trigger: function() { - if ( this !== safeActiveElement() && this.focus ) { - this.focus(); - return false; - } - }, - delegateType: "focusin" - }, - blur: { - trigger: function() { - if ( this === safeActiveElement() && this.blur ) { - this.blur(); - return false; - } - }, - delegateType: "focusout" - }, - click: { - // For checkbox, fire native event so checked state will be right - trigger: function() { - if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { - this.click(); - return false; - } - }, - - // For cross-browser consistency, don't fire native .click() on links - _default: function( event ) { - return jQuery.nodeName( event.target, "a" ); - } - }, - - beforeunload: { - postDispatch: function( event ) { - - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. - if ( event.result !== undefined && event.originalEvent ) { - event.originalEvent.returnValue = event.result; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { - type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -jQuery.removeEvent = function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } -}; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - // Support: Android<4.0 - src.returnValue === false ? - returnTrue : - returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse, - - preventDefault: function() { - var e = this.originalEvent; - - this.isDefaultPrevented = returnTrue; - - if ( e && e.preventDefault ) { - e.preventDefault(); - } - }, - stopPropagation: function() { - var e = this.originalEvent; - - this.isPropagationStopped = returnTrue; - - if ( e && e.stopPropagation ) { - e.stopPropagation(); - } - }, - stopImmediatePropagation: function() { - var e = this.originalEvent; - - this.isImmediatePropagationStopped = returnTrue; - - if ( e && e.stopImmediatePropagation ) { - e.stopImmediatePropagation(); - } - - this.stopPropagation(); - } -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -// Support: Chrome 15+ -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout", - pointerenter: "pointerover", - pointerleave: "pointerout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// Support: Firefox, Chrome, Safari -// Create "bubbling" focus and blur events -if ( !support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - data_priv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this, - attaches = data_priv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - data_priv.remove( doc, fix ); - - } else { - data_priv.access( doc, fix, attaches ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - var elem = this[0]; - if ( elem ) { - return jQuery.event.trigger( type, data, elem, true ); - } - } -}); - - -var - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rhtml = /<|&#?\w+;/, - rnoInnerhtml = /<(?:script|style|link)/i, - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /^$|\/(?:java|ecma)script/i, - rscriptTypeMasked = /^true\/(.*)/, - rcleanScript = /^\s*\s*$/g, - - // We have to close these tags to support XHTML (#13200) - wrapMap = { - - // Support: IE9 - option: [ 1, "" ], - - thead: [ 1, "", "
" ], - col: [ 2, "", "
" ], - tr: [ 2, "", "
" ], - td: [ 3, "", "
" ], - - _default: [ 0, "", "" ] - }; - -// Support: IE9 -wrapMap.optgroup = wrapMap.option; - -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// Support: 1.x compatibility -// Manipulating tables requires a tbody -function manipulationTarget( elem, content ) { - return jQuery.nodeName( elem, "table" ) && - jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ? - - elem.getElementsByTagName("tbody")[0] || - elem.appendChild( elem.ownerDocument.createElement("tbody") ) : - elem; -} - -// Replace/restore the type attribute of script elements for safe DOM manipulation -function disableScript( elem ) { - elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; - return elem; -} -function restoreScript( elem ) { - var match = rscriptTypeMasked.exec( elem.type ); - - if ( match ) { - elem.type = match[ 1 ]; - } else { - elem.removeAttribute("type"); - } - - return elem; -} - -// Mark scripts as having already been evaluated -function setGlobalEval( elems, refElements ) { - var i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - data_priv.set( - elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) - ); - } -} - -function cloneCopyEvent( src, dest ) { - var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; - - if ( dest.nodeType !== 1 ) { - return; - } - - // 1. Copy private data: events, handlers, etc. - if ( data_priv.hasData( src ) ) { - pdataOld = data_priv.access( src ); - pdataCur = data_priv.set( dest, pdataOld ); - events = pdataOld.events; - - if ( events ) { - delete pdataCur.handle; - pdataCur.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - } - - // 2. Copy user data - if ( data_user.hasData( src ) ) { - udataOld = data_user.access( src ); - udataCur = jQuery.extend( {}, udataOld ); - - data_user.set( dest, udataCur ); - } -} - -function getAll( context, tag ) { - var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : - context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : - []; - - return tag === undefined || tag && jQuery.nodeName( context, tag ) ? - jQuery.merge( [ context ], ret ) : - ret; -} - -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var i, l, srcElements, destElements, - clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); - - // Fix IE cloning issues - if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && - !jQuery.isXMLDoc( elem ) ) { - - // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 - destElements = getAll( clone ); - srcElements = getAll( elem ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - if ( deepDataAndEvents ) { - srcElements = srcElements || getAll( elem ); - destElements = destElements || getAll( clone ); - - for ( i = 0, l = srcElements.length; i < l; i++ ) { - cloneCopyEvent( srcElements[ i ], destElements[ i ] ); - } - } else { - cloneCopyEvent( elem, clone ); - } - } - - // Preserve script evaluation history - destElements = getAll( clone, "script" ); - if ( destElements.length > 0 ) { - setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); - } - - // Return the cloned set - return clone; - }, - - buildFragment: function( elems, context, scripts, selection ) { - var elem, tmp, tag, wrap, contains, j, - fragment = context.createDocumentFragment(), - nodes = [], - i = 0, - l = elems.length; - - for ( ; i < l; i++ ) { - elem = elems[ i ]; - - if ( elem || elem === 0 ) { - - // Add nodes directly - if ( jQuery.type( elem ) === "object" ) { - // Support: QtWebKit, PhantomJS - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); - - // Convert non-html into a text node - } else if ( !rhtml.test( elem ) ) { - nodes.push( context.createTextNode( elem ) ); - - // Convert html into DOM nodes - } else { - tmp = tmp || fragment.appendChild( context.createElement("div") ); - - // Deserialize a standard representation - tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[ 2 ]; - - // Descend through wrappers to the right content - j = wrap[ 0 ]; - while ( j-- ) { - tmp = tmp.lastChild; - } - - // Support: QtWebKit, PhantomJS - // push.apply(_, arraylike) throws on ancient WebKit - jQuery.merge( nodes, tmp.childNodes ); - - // Remember the top-level container - tmp = fragment.firstChild; - - // Ensure the created nodes are orphaned (#12392) - tmp.textContent = ""; - } - } - } - - // Remove wrapper from fragment - fragment.textContent = ""; - - i = 0; - while ( (elem = nodes[ i++ ]) ) { - - // #4087 - If origin and destination elements are the same, and this is - // that element, do not do anything - if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { - continue; - } - - contains = jQuery.contains( elem.ownerDocument, elem ); - - // Append to fragment - tmp = getAll( fragment.appendChild( elem ), "script" ); - - // Preserve script evaluation history - if ( contains ) { - setGlobalEval( tmp ); - } - - // Capture executables - if ( scripts ) { - j = 0; - while ( (elem = tmp[ j++ ]) ) { - if ( rscriptType.test( elem.type || "" ) ) { - scripts.push( elem ); - } - } - } - } - - return fragment; - }, - - cleanData: function( elems ) { - var data, elem, type, key, - special = jQuery.event.special, - i = 0; - - for ( ; (elem = elems[ i ]) !== undefined; i++ ) { - if ( jQuery.acceptData( elem ) ) { - key = elem[ data_priv.expando ]; - - if ( key && (data = data_priv.cache[ key ]) ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - if ( data_priv.cache[ key ] ) { - // Discard any remaining `private` data - delete data_priv.cache[ key ]; - } - } - } - // Discard any remaining `user` data - delete data_user.cache[ elem[ data_user.expando ] ]; - } - } -}); - -jQuery.fn.extend({ - text: function( value ) { - return access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().each(function() { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - this.textContent = value; - } - }); - }, null, value, arguments.length ); - }, - - append: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.appendChild( elem ); - } - }); - }, - - prepend: function() { - return this.domManip( arguments, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { - var target = manipulationTarget( this, elem ); - target.insertBefore( elem, target.firstChild ); - } - }); - }, - - before: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this ); - } - }); - }, - - after: function() { - return this.domManip( arguments, function( elem ) { - if ( this.parentNode ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - } - }); - }, - - remove: function( selector, keepData /* Internal Use Only */ ) { - var elem, - elems = selector ? jQuery.filter( selector, this ) : this, - i = 0; - - for ( ; (elem = elems[i]) != null; i++ ) { - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem ) ); - } - - if ( elem.parentNode ) { - if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { - setGlobalEval( getAll( elem, "script" ) ); - } - elem.parentNode.removeChild( elem ); - } - } - - return this; - }, - - empty: function() { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - if ( elem.nodeType === 1 ) { - - // Prevent memory leaks - jQuery.cleanData( getAll( elem, false ) ); - - // Remove any remaining nodes - elem.textContent = ""; - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map(function() { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); - }, - - html: function( value ) { - return access( this, function( value ) { - var elem = this[ 0 ] || {}, - i = 0, - l = this.length; - - if ( value === undefined && elem.nodeType === 1 ) { - return elem.innerHTML; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { - - value = value.replace( rxhtmlTag, "<$1>" ); - - try { - for ( ; i < l; i++ ) { - elem = this[ i ] || {}; - - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( getAll( elem, false ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch( e ) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function() { - var arg = arguments[ 0 ]; - - // Make the changes, replacing each context element with the new content - this.domManip( arguments, function( elem ) { - arg = this.parentNode; - - jQuery.cleanData( getAll( this ) ); - - if ( arg ) { - arg.replaceChild( elem, this ); - } - }); - - // Force removal if there was no new content (e.g., from empty arguments) - return arg && (arg.length || arg.nodeType) ? this : this.remove(); - }, - - detach: function( selector ) { - return this.remove( selector, true ); - }, - - domManip: function( args, callback ) { - - // Flatten any nested arrays - args = concat.apply( [], args ); - - var fragment, first, scripts, hasScripts, node, doc, - i = 0, - l = this.length, - set = this, - iNoClone = l - 1, - value = args[ 0 ], - isFunction = jQuery.isFunction( value ); - - // We can't cloneNode fragments that contain checked, in WebKit - if ( isFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { - return this.each(function( index ) { - var self = set.eq( index ); - if ( isFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } - self.domManip( args, callback ); - }); - } - - if ( l ) { - fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - if ( first ) { - scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); - hasScripts = scripts.length; - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - for ( ; i < l; i++ ) { - node = fragment; - - if ( i !== iNoClone ) { - node = jQuery.clone( node, true, true ); - - // Keep references to cloned scripts for later restoration - if ( hasScripts ) { - // Support: QtWebKit - // jQuery.merge because push.apply(_, arraylike) throws - jQuery.merge( scripts, getAll( node, "script" ) ); - } - } - - callback.call( this[ i ], node, i ); - } - - if ( hasScripts ) { - doc = scripts[ scripts.length - 1 ].ownerDocument; - - // Reenable scripts - jQuery.map( scripts, restoreScript ); - - // Evaluate executable scripts on first document insertion - for ( i = 0; i < hasScripts; i++ ) { - node = scripts[ i ]; - if ( rscriptType.test( node.type || "" ) && - !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { - - if ( node.src ) { - // Optional AJAX dependency, but won't run scripts if not present - if ( jQuery._evalUrl ) { - jQuery._evalUrl( node.src ); - } - } else { - jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); - } - } - } - } - } - } - - return this; - } -}); - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - ret = [], - insert = jQuery( selector ), - last = insert.length - 1, - i = 0; - - for ( ; i <= last; i++ ) { - elems = i === last ? this : this.clone( true ); - jQuery( insert[ i ] )[ original ]( elems ); - - // Support: QtWebKit - // .get() because push.apply(_, arraylike) throws - push.apply( ret, elems.get() ); - } - - return this.pushStack( ret ); - }; -}); - - -var iframe, - elemdisplay = {}; - -/** - * Retrieve the actual display of a element - * @param {String} name nodeName of the element - * @param {Object} doc Document object - */ -// Called only from within defaultDisplay -function actualDisplay( name, doc ) { - var style, - elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), - - // getDefaultComputedStyle might be reliably used only on attached element - display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ? - - // Use of this method is a temporary fix (more like optimization) until something better comes along, - // since it was removed from specification and supported only in FF - style.display : jQuery.css( elem[ 0 ], "display" ); - - // We don't have any data stored on the element, - // so use "detach" method as fast way to get rid of the element - elem.detach(); - - return display; -} - -/** - * Try to determine the default display value of an element - * @param {String} nodeName - */ -function defaultDisplay( nodeName ) { - var doc = document, - display = elemdisplay[ nodeName ]; - - if ( !display ) { - display = actualDisplay( nodeName, doc ); - - // If the simple way fails, read from inside an iframe - if ( display === "none" || !display ) { - - // Use the already-created iframe if possible - iframe = (iframe || jQuery( "