From f1ede3df4f14ddee092ef0eeac7cc4d7268f366f Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Wed, 31 Mar 2021 13:31:46 +0200 Subject: [PATCH] Fix type resolution issues and add missing JTDs. Fix SQL trim parsing and some newly added tests --- .../internal/InferredBasicValueResolver.java | 50 +++++++++---------- .../mapping/EmbeddableMappingType.java | 2 +- .../entity/AbstractEntityPersister.java | 6 ++- .../sqm/sql/BaseSqmToSqlAstConverter.java | 2 +- .../main/java/org/hibernate/sql/Template.java | 45 +++++++++++++++-- .../sql/ast/spi/AbstractSqlAstTranslator.java | 4 +- .../java/spi/JavaTypeDescriptorBaseline.java | 7 ++- .../constraint/ForeignKeyConstraintTest.java | 3 +- .../mapping/formula/EntityOfFormulas.hbm.xml | 3 +- .../AggregateFunctionsWithSubSelectTest.java | 2 +- .../QueryParametersValidationArrayTest.java | 2 +- 11 files changed, 86 insertions(+), 40 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java index 1f0c1f13d9..b0422dee5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/model/process/internal/InferredBasicValueResolver.java @@ -102,35 +102,35 @@ else if ( reflectedJtd != null ) { legacyType = jdbcMapping; } else { - // here we have the legacy case - // - we mimic how this used to be done - final BasicType registeredType = typeConfiguration.getBasicTypeRegistry().getRegisteredType( reflectedJtd.getJavaType() ); + // Use JTD if we know it to apply any specialized resolutions - if ( registeredType != null ) { - // reuse the "legacy type" - legacyType = resolveSqlTypeIndicators( stdIndicators, registeredType ); - jdbcMapping = legacyType; + if ( reflectedJtd instanceof EnumJavaTypeDescriptor ) { + return fromEnum( + (EnumJavaTypeDescriptor) reflectedJtd, + explicitJavaTypeAccess.apply( typeConfiguration ), + explicitSqlTypeAccess.apply( typeConfiguration ), + stdIndicators, + typeConfiguration + ); + } + else if ( reflectedJtd instanceof TemporalJavaTypeDescriptor ) { + return fromTemporal( + (TemporalJavaTypeDescriptor) reflectedJtd, + explicitJavaTypeAccess, + explicitSqlTypeAccess, + stdIndicators, + typeConfiguration + ); } else { - // Use JTD if we know it to apply any specialized resolutions + // here we have the legacy case + // - we mimic how this used to be done + final BasicType registeredType = typeConfiguration.getBasicTypeRegistry().getRegisteredType( reflectedJtd.getJavaType() ); - if ( reflectedJtd instanceof EnumJavaTypeDescriptor ) { - return fromEnum( - (EnumJavaTypeDescriptor) reflectedJtd, - explicitJavaTypeAccess.apply( typeConfiguration ), - explicitSqlTypeAccess.apply( typeConfiguration ), - stdIndicators, - typeConfiguration - ); - } - else if ( reflectedJtd instanceof TemporalJavaTypeDescriptor ) { - return fromTemporal( - (TemporalJavaTypeDescriptor) reflectedJtd, - explicitJavaTypeAccess, - explicitSqlTypeAccess, - stdIndicators, - typeConfiguration - ); + if ( registeredType != null ) { + // reuse the "legacy type" + legacyType = resolveSqlTypeIndicators( stdIndicators, registeredType ); + jdbcMapping = legacyType; } else if ( reflectedJtd instanceof SerializableTypeDescriptor ) { legacyType = new SerializableType<>( reflectedJtd.getJavaTypeClass() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java index a43d2a96b5..92fc9726e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java @@ -225,7 +225,7 @@ private boolean finishInitialization( containingTableExpression, columnExpression, selectable.isFormula(), - selectable.getTemplate( dialect, sessionFactory.getQueryEngine().getSqmFunctionRegistry() ), + selectable.getCustomReadExpression(), selectable.getCustomWriteExpression(), representationStrategy.resolvePropertyAccess( bootPropertyDescriptor ), compositeType.getCascadeStyle( attributeIndex ), diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index f501190dcd..4037a024af 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -1512,7 +1512,11 @@ protected Predicate generateJoinPredicate( ), sqlAstProcessingState -> new ColumnReference( rootTableReference.getIdentificationVariable(), - selection, + rootPkColumnName, + false, + null, + null, + selection.getJdbcMapping(), getFactory() ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index 48e62d572a..d8cf8b3638 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -3733,7 +3733,7 @@ protected Expression createCorrelatedAggregateSubQuery( : mappingModelExpressable.getElementDescriptor(); final List arguments = new ArrayList<>( 1 ); - collectionPart.forEachSelection( + collectionPart.forEachSelectable( (selectionIndex, selectionMapping) -> { arguments.add( new ColumnReference( diff --git a/hibernate-core/src/main/java/org/hibernate/sql/Template.java b/hibernate-core/src/main/java/org/hibernate/sql/Template.java index 368296a493..d3bf4d8013 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/Template.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/Template.java @@ -219,7 +219,18 @@ else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) { boolean hasMoreOperands = true; String operandToken = tokens.nextToken(); + switch ( operandToken.toLowerCase( Locale.ROOT ) ) { + case "leading": + case "trailing": + case "both": + operands.add( operandToken ); + if ( hasMoreOperands = tokens.hasMoreTokens() ) { + operandToken = tokens.nextToken(); + } + break; + } boolean quotedOperand = false; + int parenthesis = 0; while ( hasMoreOperands ) { final boolean isQuote = "'".equals( operandToken ); if ( isQuote ) { @@ -235,14 +246,40 @@ else if ( quotedIdentifier && ( dialect.closeQuote()==token.charAt(0) ) ) { else if ( quotedOperand ) { builder.append( operandToken ); } - else if ( operandToken.length() == 1 && Character.isWhitespace( operandToken.charAt( 0 ) ) ) { - // do nothing + else if ( parenthesis != 0 ) { + builder.append( operandToken ); + switch ( operandToken ) { + case "(": + parenthesis++; + break; + case ")": + parenthesis--; + break; + } } else { - operands.add( operandToken ); + builder.append( operandToken ); + switch ( operandToken.toLowerCase( Locale.ROOT ) ) { + case "(": + parenthesis++; + break; + case ")": + parenthesis--; + break; + case "from": + if ( builder.length() != 0 ) { + operands.add( builder.substring( 0, builder.length() - 4 ) ); + builder.setLength( 0 ); + operands.add( operandToken ); + } + break; + } } operandToken = tokens.nextToken(); - hasMoreOperands = tokens.hasMoreTokens() && ! ")".equals( operandToken ); + hasMoreOperands = tokens.hasMoreTokens() && ( parenthesis != 0 || ! ")".equals( operandToken ) ); + } + if ( builder.length() != 0 ) { + operands.add( builder.toString() ); } TrimOperands trimOperands = new TrimOperands( operands ); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index 425fa636b8..d885d37bc4 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -2662,7 +2662,7 @@ else if ( modelPart instanceof PluralAttributeMapping ) { else if ( elementDescriptor instanceof EntityCollectionPart ) { final ForeignKeyDescriptor foreignKeyDescriptor = ( (EntityCollectionPart) elementDescriptor ).getForeignKeyDescriptor(); if ( foreignKeyDescriptor instanceof SimpleForeignKeyDescriptor ) { - foreignKeyDescriptor.visitTargetColumns( + foreignKeyDescriptor.visitTargetSelectables( (selectionIndex, selectionMapping) -> appendSql( selectionMapping.getSelectionExpression() ) ); } @@ -2671,7 +2671,7 @@ else if ( elementDescriptor instanceof EntityCollectionPart ) { else if ( modelPart instanceof ToOneAttributeMapping ) { final ForeignKeyDescriptor foreignKeyDescriptor = ( (ToOneAttributeMapping) modelPart ).getForeignKeyDescriptor(); if ( foreignKeyDescriptor instanceof SimpleForeignKeyDescriptor ) { - foreignKeyDescriptor.visitTargetColumns( + foreignKeyDescriptor.visitTargetSelectables( (selectionIndex, selectionMapping) -> appendSql( selectionMapping.getSelectionExpression() ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBaseline.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBaseline.java index bfbf98629d..b814c1f8ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBaseline.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/JavaTypeDescriptorBaseline.java @@ -51,9 +51,11 @@ import org.hibernate.type.descriptor.java.JavaObjectTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JdbcDateTypeDescriptor; +import org.hibernate.type.descriptor.java.JdbcTimeTypeDescriptor; import org.hibernate.type.descriptor.java.JdbcTimestampTypeDescriptor; import org.hibernate.type.descriptor.java.LocalDateJavaDescriptor; import org.hibernate.type.descriptor.java.LocalDateTimeJavaDescriptor; +import org.hibernate.type.descriptor.java.LocalTimeJavaDescriptor; import org.hibernate.type.descriptor.java.LocaleTypeDescriptor; import org.hibernate.type.descriptor.java.LongTypeDescriptor; import org.hibernate.type.descriptor.java.NClobTypeDescriptor; @@ -66,6 +68,7 @@ import org.hibernate.type.descriptor.java.TimeZoneTypeDescriptor; import org.hibernate.type.descriptor.java.UUIDTypeDescriptor; import org.hibernate.type.descriptor.java.UrlTypeDescriptor; +import org.hibernate.type.descriptor.java.ZoneOffsetJavaDescriptor; import org.hibernate.type.descriptor.java.ZonedDateTimeJavaDescriptor; /** @@ -109,6 +112,7 @@ public static void prime(BaselineTarget target) { target.addBaselineDescriptor( InstantJavaDescriptor.INSTANCE ); target.addBaselineDescriptor( LocalDateJavaDescriptor.INSTANCE ); target.addBaselineDescriptor( LocalDateTimeJavaDescriptor.INSTANCE ); + target.addBaselineDescriptor( LocalTimeJavaDescriptor.INSTANCE ); target.addBaselineDescriptor( OffsetDateTimeJavaDescriptor.INSTANCE ); target.addBaselineDescriptor( OffsetTimeJavaDescriptor.INSTANCE ); target.addBaselineDescriptor( ZonedDateTimeJavaDescriptor.INSTANCE ); @@ -116,9 +120,10 @@ public static void prime(BaselineTarget target) { target.addBaselineDescriptor( CalendarTypeDescriptor.INSTANCE ); target.addBaselineDescriptor( DateTypeDescriptor.INSTANCE ); target.addBaselineDescriptor( java.sql.Date.class, JdbcDateTypeDescriptor.INSTANCE ); - target.addBaselineDescriptor( java.sql.Time.class, JdbcTimestampTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( java.sql.Time.class, JdbcTimeTypeDescriptor.INSTANCE ); target.addBaselineDescriptor( java.sql.Timestamp.class, JdbcTimestampTypeDescriptor.INSTANCE ); target.addBaselineDescriptor( TimeZoneTypeDescriptor.INSTANCE ); + target.addBaselineDescriptor( ZoneOffsetJavaDescriptor.INSTANCE ); target.addBaselineDescriptor( ClassTypeDescriptor.INSTANCE ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/constraint/ForeignKeyConstraintTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/constraint/ForeignKeyConstraintTest.java index 78dec8a9c7..0ee7f15f88 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/constraint/ForeignKeyConstraintTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/constraint/ForeignKeyConstraintTest.java @@ -169,10 +169,9 @@ public void testSecondaryTable(DomainModelScope scope) { } @Test - @NotImplementedYet( strict = false, reason = "Problem with non-root-entity based FKs" ) public void testGet(SessionFactoryScope scope) { scope.inTransaction( - session -> session.get( Student.class, 1l ) + session -> session.get( Student.class, 1L ) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/formula/EntityOfFormulas.hbm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/formula/EntityOfFormulas.hbm.xml index 5e28fd41a6..7b56cc972a 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/formula/EntityOfFormulas.hbm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/formula/EntityOfFormulas.hbm.xml @@ -13,7 +13,8 @@ - + + diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/AggregateFunctionsWithSubSelectTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/AggregateFunctionsWithSubSelectTest.java index f2fb720f49..1adc27a2d8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/AggregateFunctionsWithSubSelectTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/AggregateFunctionsWithSubSelectTest.java @@ -19,9 +19,9 @@ import org.hibernate.dialect.H2Dialect; -import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.RequiresDialect; import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.junit.jupiter.api.AfterEach; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/QueryParametersValidationArrayTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/QueryParametersValidationArrayTest.java index 81ae52fad5..67d2b1832e 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/QueryParametersValidationArrayTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/QueryParametersValidationArrayTest.java @@ -31,10 +31,10 @@ import org.hibernate.type.descriptor.jdbc.BasicExtractor; import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor; -import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.TestForIssue; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; import org.hibernate.testing.orm.junit.Jpa; +import org.hibernate.testing.orm.junit.RequiresDialect; import org.junit.jupiter.api.Test; /**