re-enable tests

re-organize some tests
continuing with o.h.test.hql
improve cast-target handling

https://github.com/hibernate/hibernate-orm/discussions/3889
This commit is contained in:
Steve Ebersole 2021-04-09 17:34:50 -05:00
parent e0bbb02c99
commit 4917d7c6bd
28 changed files with 310 additions and 164 deletions

View File

@ -769,7 +769,15 @@ castFunction
;
castTarget
: identifier (LEFT_PAREN INTEGER_LITERAL (COMMA INTEGER_LITERAL)? RIGHT_PAREN)?
: castTargetType (LEFT_PAREN INTEGER_LITERAL (COMMA INTEGER_LITERAL)? RIGHT_PAREN)?
;
/**
* Like the `entityName` rule, we have a specialized dotIdentifierSequence rule
*/
castTargetType
returns [String fullTargetName]
: (i=identifier { $fullTargetName = _localctx.i.getText(); }) (DOT c=identifier { $fullTargetName += ("." + _localctx.c.getText() ); })*
;
concatFunction

View File

@ -11,31 +11,28 @@ import java.util.List;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.ast.tree.expression.CastTarget;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.FunctionExpression;
import org.hibernate.sql.ast.tree.expression.JdbcLiteral;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.sql.ast.tree.expression.NullnessLiteral;
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.expression.Literal;
import org.hibernate.sql.ast.tree.expression.NullnessLiteral;
import org.hibernate.sql.ast.tree.expression.SqlTuple;
import org.hibernate.sql.ast.tree.expression.Summarization;
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
import org.hibernate.sql.ast.tree.select.QueryGroup;
import org.hibernate.sql.ast.tree.select.QueryPart;
import org.hibernate.sql.ast.tree.select.QuerySpec;
@ -247,7 +244,7 @@ public class FirebirdSqlAstTranslator<T extends JdbcOperation> extends AbstractS
final JdbcMapping jdbcMapping = jdbcParameter.getExpressionType().getJdbcMappings().get( 0 );
final List<SqlAstNode> arguments = new ArrayList<>( 2 );
arguments.add( jdbcParameter );
arguments.add( new CastTarget( (BasicValuedMapping) jdbcMapping ) );
arguments.add( new CastTarget( jdbcMapping ) );
castFunction().render( this, arguments, this );
}
finally {

View File

@ -11,7 +11,6 @@ import java.util.List;
import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.query.CastType;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
@ -54,11 +53,11 @@ public class CastFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
@Override
public void render(SqlAppender sqlAppender, List<SqlAstNode> arguments, SqlAstTranslator<?> walker) {
final Expression source = (Expression) arguments.get( 0 );
final JdbcMapping sourceMapping = ( (SqlExpressable) source.getExpressionType() ).getJdbcMapping();
final JdbcMapping sourceMapping = source.getExpressionType().getJdbcMappings().get( 0 );
final CastType sourceType = getCastType( sourceMapping );
final CastTarget castTarget = (CastTarget) arguments.get( 1 );
final JdbcMapping targetJdbcMapping = castTarget.getExpressionType().getJdbcMapping();
final JdbcMapping targetJdbcMapping = castTarget.getExpressionType().getJdbcMappings().get( 0 );
final CastType targetType = getCastType( targetJdbcMapping );
String cast = dialect.castPattern( sourceType, targetType );

View File

@ -12,6 +12,7 @@ import java.util.List;
import org.hibernate.Incubating;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.MutableInteger;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.sql.ast.Clause;
@ -24,7 +25,7 @@ import org.hibernate.sql.ast.Clause;
* @author Steve Ebersole
*/
@Incubating
public interface Bindable {
public interface Bindable extends JdbcMappingContainer {
/*
* todo (6.0) : much of this contract uses Clause which (1) kludgy and (2) not always necessary
* - e.g. see the note below wrt "2 forms of JDBC-type visiting"

View File

@ -6,6 +6,10 @@
*/
package org.hibernate.metamodel.mapping;
import java.util.Collections;
import java.util.List;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.query.CastType;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
@ -17,7 +21,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
*
* @author Steve Ebersole
*/
public interface JdbcMapping extends MappingType {
public interface JdbcMapping extends MappingType, JdbcMappingContainer {
/**
* The descriptor for the Java type represented by this
* expressable type
@ -50,4 +54,26 @@ public interface JdbcMapping extends MappingType {
default JavaTypeDescriptor getMappedJavaTypeDescriptor() {
return getJavaTypeDescriptor();
}
@Override
default int getJdbcTypeCount() {
return 1;
}
@Override
default List<JdbcMapping> getJdbcMappings() {
return Collections.singletonList( this );
}
@Override
default int forEachJdbcType(IndexedConsumer<JdbcMapping> action) {
action.accept( 0, this );
return 1;
}
@Override
default int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
action.accept( 0, this );
return 1;
}
}

View File

@ -0,0 +1,50 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.metamodel.mapping;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.mapping.IndexedConsumer;
/**
* Container for one-or-more JdbcMappings
*/
public interface JdbcMappingContainer {
/**
* The number of JDBC mappings
*/
default int getJdbcTypeCount() {
return forEachJdbcType( (index, jdbcMapping) -> {} );
}
/**
* The list of JDBC mappings
*/
default List<JdbcMapping> getJdbcMappings() {
final List<JdbcMapping> results = new ArrayList<>();
forEachJdbcType( (index, jdbcMapping) -> results.add( jdbcMapping ) );
return results;
}
/**
* Visit each of JdbcMapping
*
* @apiNote Same as {@link #forEachJdbcType(int, IndexedConsumer)} starting from `0`
*/
default int forEachJdbcType(IndexedConsumer<JdbcMapping> action) {
return forEachJdbcType( 0, action );
}
/**
* Visit each JdbcMapping starting from the given offset
*/
default int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
throw new NotYetImplementedFor6Exception( getClass() );
}
}

View File

@ -14,7 +14,7 @@ package org.hibernate.metamodel.mapping;
*
* @author Steve Ebersole
*/
public interface SqlExpressable {
public interface SqlExpressable extends JdbcMappingContainer {
/**
* Any thing that is expressable at the SQL AST level
* would be of basic type.

View File

@ -3388,7 +3388,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
@Override
public SqmCastTarget<?> visitCastTarget(HqlParser.CastTargetContext castTargetContext) {
String targetName = castTargetContext.identifier().getText();
final String targetName = castTargetContext.castTargetType().fullTargetName;
List<TerminalNode> args = castTargetContext.INTEGER_LITERAL();
Long length = args.size() == 1 ? Long.valueOf( args.get(0).getText() ) : null;

View File

@ -6,12 +6,14 @@
*/
package org.hibernate.query.sqm.function;
import java.util.List;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Table;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.SemanticException;
@ -32,8 +34,6 @@ import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
import java.util.List;
/**
* Representation of a function call in the SQL AST for impls that know how to
* render themselves.
@ -46,14 +46,14 @@ public class SelfRenderingFunctionSqlAstExpression
private final FunctionRenderingSupport renderer;
private final List<SqlAstNode> sqlAstArguments;
private final AllowableFunctionReturnType<?> type;
private final MappingModelExpressable<?> expressable;
private final JdbcMappingContainer expressable;
public SelfRenderingFunctionSqlAstExpression(
String functionName,
FunctionRenderingSupport renderer,
List<SqlAstNode> sqlAstArguments,
AllowableFunctionReturnType<?> type,
MappingModelExpressable<?> expressable) {
JdbcMappingContainer expressable) {
this.functionName = functionName;
this.renderer = renderer;
this.sqlAstArguments = sqlAstArguments;
@ -73,7 +73,7 @@ public class SelfRenderingFunctionSqlAstExpression
}
@Override
public MappingModelExpressable getExpressionType() {
public JdbcMappingContainer getExpressionType() {
return expressable;
}

View File

@ -6,9 +6,14 @@
*/
package org.hibernate.query.sqm.produce.function;
import java.sql.Types;
import java.util.List;
import java.util.Locale;
import java.util.function.Supplier;
import org.hibernate.QueryException;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
import org.hibernate.query.sqm.SqmExpressable;
import org.hibernate.query.sqm.tree.SqmTypedNode;
@ -17,11 +22,6 @@ import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.BasicType;
import org.hibernate.type.spi.TypeConfiguration;
import java.sql.Types;
import java.util.List;
import java.util.Locale;
import java.util.function.Supplier;
/**
* @author Steve Ebersole
*/
@ -90,7 +90,7 @@ public class StandardFunctionReturnTypeResolvers {
continue;
}
final MappingModelExpressable<?> nodeType = ( (Expression) arg ).getExpressionType();
final JdbcMappingContainer nodeType = ( (Expression) arg ).getExpressionType();
if ( nodeType instanceof BasicValuedMapping ) {
final BasicValuedMapping argType = (BasicValuedMapping) nodeType;
return useImpliedTypeIfPossible( argType, impliedTypeAccess.get() );
@ -220,7 +220,7 @@ public class StandardFunctionReturnTypeResolvers {
public static BasicValuedMapping extractArgumentValuedMapping(List<? extends SqlAstNode> arguments, int position) {
final SqlAstNode specifiedArgument = arguments.get( position-1 );
final MappingModelExpressable<?> specifiedArgType = specifiedArgument instanceof Expression
final JdbcMappingContainer specifiedArgType = specifiedArgument instanceof Expression
? ( (Expression) specifiedArgument ).getExpressionType()
: null;

View File

@ -54,6 +54,7 @@ import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer;
@ -2231,7 +2232,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
// we must convert this duration from
// nanoseconds to the given unit
MappingModelExpressable durationType = scaledExpression.getExpressionType();
JdbcMappingContainer durationType = scaledExpression.getExpressionType();
Duration duration = new Duration( scaledExpression, NANOSECOND, (BasicValuedMapping) durationType );
TemporalUnit appliedUnit = appliedByUnit.getUnit().getUnit();
@ -2349,12 +2350,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
);
}
private MappingModelExpressable<?> getKeyExpressable(MappingModelExpressable<?> mappingModelExpressable) {
private MappingModelExpressable<?> getKeyExpressable(JdbcMappingContainer mappingModelExpressable) {
if ( mappingModelExpressable instanceof EntityAssociationMapping ) {
return ( (EntityAssociationMapping) mappingModelExpressable ).getKeyTargetMatchPart();
}
else {
return mappingModelExpressable;
return (MappingModelExpressable<?>) mappingModelExpressable;
}
}
@ -2749,7 +2750,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
targetType = InferredBasicValueResolver.resolveSqlTypeIndicators( this, (BasicType<?>) targetType );
}
return new CastTarget(
targetType,
targetType.getJdbcMapping(),
target.getLength(),
target.getPrecision(),
target.getScale()
@ -3264,7 +3265,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
Expression timestamp = adjustedTimestamp;
SqmExpressable<?> timestampType = adjustedTimestampType;
adjustedTimestamp = toSqlExpression( expression.getLeftHandOperand().accept( this ) );
MappingModelExpressable type = adjustedTimestamp.getExpressionType();
JdbcMappingContainer type = adjustedTimestamp.getExpressionType();
if ( type instanceof SqmExpressable ) {
adjustedTimestampType = (SqmExpressable) type;
}

View File

@ -19,12 +19,8 @@ import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import org.hibernate.sql.ast.tree.cte.CteSearchClauseKind;
import org.hibernate.query.FetchClauseType;
import org.hibernate.LockOptions;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.SortOrder;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.AbstractDelegatingWrapperOptions;
@ -36,12 +32,12 @@ import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.collections.Stack;
import org.hibernate.internal.util.collections.StandardStack;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.metamodel.mapping.internal.BasicValuedCollectionPart;
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
import org.hibernate.metamodel.mapping.internal.SimpleForeignKeyDescriptor;
@ -49,13 +45,14 @@ import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.AbstractEntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.Limit;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.SortOrder;
import org.hibernate.query.UnaryArithmeticOperator;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.NonAggregatedCompositeValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
import org.hibernate.query.sqm.tree.expression.Conversion;
import org.hibernate.sql.ast.Clause;
@ -68,6 +65,7 @@ import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.cte.CteColumn;
import org.hibernate.sql.ast.tree.cte.CteContainer;
import org.hibernate.sql.ast.tree.cte.CteSearchClauseKind;
import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.ast.tree.cte.SearchClauseSpecification;
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
@ -2500,7 +2498,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
protected void renderCasted(Expression expression) {
final List<SqlAstNode> arguments = new ArrayList<>( 2 );
arguments.add( expression );
arguments.add( new CastTarget( (BasicValuedMapping) expression.getExpressionType() ) );
arguments.add( new CastTarget( expression.getExpressionType().getJdbcMappings().get( 0 ) ) );
castFunction().render( this, arguments, this );
}
@ -2521,7 +2519,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
if ( castParameter ) {
final List<SqlAstNode> arguments = new ArrayList<>( 2 );
arguments.add( jdbcParameter );
arguments.add( new CastTarget( (BasicValuedMapping) jdbcMapping ) );
arguments.add( new CastTarget( jdbcMapping ) );
castFunction().render( this, arguments, this );
}
else {
@ -2818,7 +2816,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
public void visitCastTarget(CastTarget castTarget) {
appendSql(
getDialect().getCastTypeName(
castTarget.getExpressionType(),
(SqlExpressable) castTarget.getExpressionType(),
castTarget.getLength(),
castTarget.getPrecision(),
castTarget.getScale()
@ -2878,7 +2876,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
final List<SqlAstNode> arguments = new ArrayList<>( 2 );
arguments.add( jdbcParameter );
arguments.add( new CastTarget( (BasicValuedMapping) jdbcMapping ) );
arguments.add( new CastTarget( jdbcMapping ) );
castFunction().render( this, arguments, this );
}
else {

View File

@ -7,6 +7,7 @@
package org.hibernate.sql.ast.spi;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -56,7 +57,7 @@ public interface SqlSelection extends SqlAstNode {
/**
* Get the type of the expression
*/
MappingModelExpressable getExpressionType();
JdbcMappingContainer getExpressionType();
void accept(SqlAstWalker sqlAstWalker);

View File

@ -7,6 +7,8 @@
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -14,16 +16,16 @@ import org.hibernate.sql.ast.tree.SqlAstNode;
* @author Gavin King
*/
public class CastTarget implements Expression, SqlAstNode {
private final BasicValuedMapping type;
private final JdbcMapping type;
private final Long length;
private final Integer precision;
private final Integer scale;
public CastTarget(BasicValuedMapping type) {
public CastTarget(JdbcMapping type) {
this( type, null, null, null );
}
public CastTarget(BasicValuedMapping type, Long length, Integer precision, Integer scale) {
public CastTarget(JdbcMapping type, Long length, Integer precision, Integer scale) {
this.type = type;
this.length = length;
this.precision = precision;
@ -43,7 +45,7 @@ public class CastTarget implements Expression, SqlAstNode {
}
@Override
public BasicValuedMapping getExpressionType() {
public JdbcMappingContainer getExpressionType() {
return type;
}

View File

@ -7,7 +7,7 @@
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -43,11 +43,17 @@ public class Collate implements Expression, SqlExpressable, SqlAstNode {
return ( (SqlExpressable) getExpressionType() ).getJdbcMapping();
}
if ( getExpressionType() != null ) {
final JdbcMappingContainer mappingContainer = getExpressionType();
assert mappingContainer.getJdbcTypeCount() == 1;
return mappingContainer.getJdbcMappings().get( 0 );
}
return null;
}
@Override
public MappingModelExpressable getExpressionType() {
public JdbcMappingContainer getExpressionType() {
return expression.getExpressionType();
}

View File

@ -7,7 +7,7 @@
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -36,11 +36,16 @@ public class Distinct implements Expression, SqlExpressable, SqlAstNode {
return ( (SqlExpressable) getExpressionType() ).getJdbcMapping();
}
if ( getExpressionType() != null ) {
assert getExpressionType().getJdbcTypeCount() == 1;
return getExpressionType().getJdbcMappings().get( 0 );
}
return null;
}
@Override
public MappingModelExpressable getExpressionType() {
public JdbcMappingContainer getExpressionType() {
return expression.getExpressionType();
}

View File

@ -6,7 +6,7 @@
*/
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.spi.SqlSelectionProducer;
import org.hibernate.sql.ast.tree.SqlAstNode;
@ -23,7 +23,7 @@ public interface Expression extends SqlAstNode, SqlSelectionProducer {
/**
* The type for this expression
*/
MappingModelExpressable getExpressionType();
JdbcMappingContainer getExpressionType();
default <T> T unwrap(Class<T> target) {
return (T) this;

View File

@ -7,7 +7,7 @@
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
@ -32,7 +32,7 @@ public class LiteralAsParameter<T> implements SelfRenderingExpression {
}
@Override
public MappingModelExpressable getExpressionType() {
public JdbcMappingContainer getExpressionType() {
return literal.getExpressionType();
}

View File

@ -6,9 +6,9 @@
*/
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlSelection;
/**
* Represents a selection that is "re-used" in certain parts of the query
@ -57,7 +57,7 @@ public class SqlSelectionExpression implements Expression {
}
@Override
public MappingModelExpressable getExpressionType() {
public JdbcMappingContainer getExpressionType() {
return theSelection.getExpressionType();
}
}

View File

@ -9,8 +9,8 @@ package org.hibernate.sql.ast.tree.select;
import java.util.List;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.SetOperator;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -62,7 +62,7 @@ public class QueryGroup extends QueryPart {
// Expression
@Override
public MappingModelExpressable getExpressionType() {
public JdbcMappingContainer getExpressionType() {
return queryParts.get( 0 ).getExpressionType();
}

View File

@ -10,7 +10,7 @@ import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
import org.hibernate.sql.ast.SqlAstWalker;
@ -121,7 +121,7 @@ public class QuerySpec extends QueryPart implements SqlAstNode, PredicateContain
// Expression
@Override
public MappingModelExpressable getExpressionType() {
public JdbcMappingContainer getExpressionType() {
if ( selectClause.getSqlSelections().size() == 1 ) {
SqlSelection first = selectClause.getSqlSelections().get( 0 );
return first.getExpressionType();

View File

@ -6,7 +6,9 @@
*/
package org.hibernate.sql.results.internal;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import java.util.Objects;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlExpressionAccess;
@ -14,8 +16,6 @@ import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.descriptor.ValueExtractor;
import java.util.Objects;
/**
* @asciidoc
*
@ -69,7 +69,7 @@ public class SqlSelectionImpl implements SqlSelection, SqlExpressionAccess {
}
@Override
public MappingModelExpressable getExpressionType() {
public JdbcMappingContainer getExpressionType() {
return getExpression().getExpressionType();
}

View File

@ -6,6 +6,9 @@
*/
package org.hibernate.type;
import java.util.Collections;
import java.util.List;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
@ -45,11 +48,27 @@ public interface BasicType<T> extends Type, BasicDomainType<T>, MappingType, Bas
return getJavaTypeDescriptor();
}
@Override
default int forEachJdbcType(IndexedConsumer<JdbcMapping> action) {
action.accept( 0, this );
return 1;
}
@Override
default JdbcMapping getJdbcMapping() {
return this;
}
@Override
default int getJdbcTypeCount() {
return 1;
}
@Override
default List<JdbcMapping> getJdbcMappings() {
return Collections.singletonList( this );
}
@Override
default JavaTypeDescriptor<T> getMappedJavaTypeDescriptor() {
return getJavaTypeDescriptor();

View File

@ -16,6 +16,7 @@ import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
import org.hibernate.type.descriptor.java.FloatTypeDescriptor;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.internal.JdbcLiteralFormatterNumericData;
import org.hibernate.type.spi.TypeConfiguration;

View File

@ -31,6 +31,7 @@ import org.hibernate.Incubating;
import org.hibernate.SessionFactory;
import org.hibernate.SessionFactoryObserver;
import org.hibernate.boot.cfgxml.spi.CfgXmlAccessService;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.spi.BasicTypeRegistration;
import org.hibernate.boot.spi.MetadataBuildingContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -38,6 +39,8 @@ import org.hibernate.id.uuid.LocalObjectUuidHelper;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.SessionFactoryRegistry;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.model.domain.internal.MappingMetamodelImpl;
import org.hibernate.query.BinaryArithmeticOperator;
@ -288,7 +291,25 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
case "truefalse": return StandardBasicTypes.TRUE_FALSE;
case "yesno": return StandardBasicTypes.YES_NO;
case "numericboolean": return StandardBasicTypes.NUMERIC_BOOLEAN;
default: throw new HibernateException( "unrecognized cast target type: " + name );
default: {
final BasicType<Object> registeredBasicType = basicTypeRegistry.getRegisteredType( name );
if ( registeredBasicType != null ) {
return registeredBasicType;
}
try {
final ClassLoaderService cls = getServiceRegistry().getService( ClassLoaderService.class );
final Class<?> javaTypeClass = cls.classForName( name );
final JavaTypeDescriptor<?> jtd = javaTypeDescriptorRegistry.resolveDescriptor( javaTypeClass );
final JdbcTypeDescriptor jdbcType = jtd.getRecommendedJdbcType( getCurrentBaseSqlTypeIndicators() );
return basicTypeRegistry.resolve( jtd, jdbcType );
}
catch (Exception ignore) {
}
throw new HibernateException( "unrecognized cast target type: " + name );
}
}
}
@ -610,6 +631,15 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
return getSqlTemporalType( type.getExpressableJavaTypeDescriptor().getRecommendedJdbcType( getCurrentBaseSqlTypeIndicators() ) );
}
public static TemporalType getSqlTemporalType(JdbcMapping jdbcMapping) {
return getSqlTemporalType( jdbcMapping.getJdbcTypeDescriptor() );
}
public static TemporalType getSqlTemporalType(JdbcMappingContainer jdbcMappings) {
assert jdbcMappings.getJdbcTypeCount() == 1;
return getSqlTemporalType( jdbcMappings.getJdbcMappings().get( 0 ).getJdbcTypeDescriptor() );
}
public static TemporalType getSqlTemporalType(MappingModelExpressable<?> type) {
if ( type instanceof BasicValuedMapping ) {
return getSqlTemporalType( ( (BasicValuedMapping) type ).getJdbcMapping().getJdbcTypeDescriptor() );

View File

@ -9,96 +9,16 @@ package org.hibernate.orm.test.query.hql;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.Session;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.FailureExpected;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
/**
* @author Steve Ebersole
*/
@DomainModel( annotatedClasses = CastFunctionTest.MyEntity.class )
@SessionFactory
@FailureExpected( reason = "requires https://github.com/hibernate/hibernate-orm/pull/3912" )
public class CastFunctionTest {
@Test
public void testStringCasting(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
final Dialect dialect = session.getFactory().getJdbcServices().getDialect();
if ( DerbyDialect.class.isInstance( dialect ) ) {
// the conversion from DOUBLE to VARCHAR is not supported by Derby,
// using the short name
session.createQuery( "select cast(char(e.theLostNumber) as string) from MyEntity e" ).list();
// using the java class name
session.createQuery( "select cast(char(e.theLostNumber) as java.lang.String) from MyEntity e" ).list();
// using the fqn Hibernate Type name
session.createQuery( "select cast(char(e.theLostNumber) as org.hibernate.type.StringType) from MyEntity e" )
.list();
}
else {
// using the short name
session.createQuery( "select cast(e.theLostNumber as string) from MyEntity e" ).list();
// using the java class name
session.createQuery( "select cast(e.theLostNumber as java.lang.String) from MyEntity e" ).list();
// using the fqn Hibernate Type name
session.createQuery( "select cast(e.theLostNumber as org.hibernate.type.StringType) from MyEntity e" )
.list();
}
}
);
}
@Test
public void testIntegerCasting(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// using the short name
session.createQuery( "select cast(e.theLostNumber as integer) from MyEntity e" ).list();
// using the java class name (primitive)
session.createQuery( "select cast(e.theLostNumber as int) from MyEntity e" ).list();
// using the java class name
session.createQuery( "select cast(e.theLostNumber as java.lang.Integer) from MyEntity e" ).list();
// using the fqn Hibernate Type name
session.createQuery( "select cast(e.theLostNumber as org.hibernate.type.IntegerType) from MyEntity e" ).list();
}
);
}
@Test
public void testLongCasting(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// using the short name (also the primitive name)
session.createQuery( "select cast(e.theLostNumber as long) from MyEntity e" ).list();
// using the java class name
session.createQuery( "select cast(e.theLostNumber as java.lang.Long) from MyEntity e" ).list();
// using the fqn Hibernate Type name
session.createQuery( "select cast(e.theLostNumber as org.hibernate.type.LongType) from MyEntity e" ).list();
}
);
}
@Test
public void testFloatCasting(SessionFactoryScope scope) {
scope.inTransaction(
(session) -> {
// using the short name (also the primitive name)
session.createQuery( "select cast(e.theLostNumber as float) from MyEntity e" ).list();
// using the java class name
session.createQuery( "select cast(e.theLostNumber as java.lang.Float) from MyEntity e" ).list();
// using the fqn Hibernate Type name
session.createQuery( "select cast(e.theLostNumber as org.hibernate.type.FloatType) from MyEntity e" ).list();
}
);
}
public class CastFunctionTest extends BaseCoreFunctionalTestCase {
@Entity( name="MyEntity" )
public static class MyEntity {
@Id
@ -107,4 +27,87 @@ public class CastFunctionTest {
private Double theLostNumber;
}
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { MyEntity.class };
}
@Test
public void testStringCasting() {
Session s = openSession();
s.beginTransaction();
if ( getDialect() instanceof DerbyDialect ) {
// the conversion from DOUBLE to VARCHAR is not supported by Derby,
// using the short name
s.createQuery( "select cast(char(e.theLostNumber) as string) from MyEntity e" ).list();
// using the java class name
s.createQuery( "select cast(char(e.theLostNumber) as java.lang.String) from MyEntity e" ).list();
// using the fqn Hibernate Type name
s.createQuery( "select cast(char(e.theLostNumber) as org.hibernate.type.StringType) from MyEntity e" )
.list();
}
else {
// using the short name
s.createQuery( "select cast(e.theLostNumber as string) from MyEntity e" ).list();
// using the java class name
s.createQuery( "select cast(e.theLostNumber as java.lang.String) from MyEntity e" ).list();
// using the fqn Hibernate Type name
s.createQuery( "select cast(e.theLostNumber as org.hibernate.type.StringType) from MyEntity e" )
.list();
}
s.getTransaction().commit();
s.close();
}
@Test
public void testIntegerCasting() {
Session s = openSession();
s.beginTransaction();
// using the short name
s.createQuery( "select cast(e.theLostNumber as integer) from MyEntity e" ).list();
// using the java class name (primitive)
s.createQuery( "select cast(e.theLostNumber as int) from MyEntity e" ).list();
// using the java class name
s.createQuery( "select cast(e.theLostNumber as java.lang.Integer) from MyEntity e" ).list();
// using the fqn Hibernate Type name
s.createQuery( "select cast(e.theLostNumber as org.hibernate.type.IntegerType) from MyEntity e" ).list();
s.getTransaction().commit();
s.close();
}
@Test
public void testLongCasting() {
Session s = openSession();
s.beginTransaction();
// using the short name (also the primitive name)
s.createQuery( "select cast(e.theLostNumber as long) from MyEntity e" ).list();
// using the java class name
s.createQuery( "select cast(e.theLostNumber as java.lang.Long) from MyEntity e" ).list();
// using the fqn Hibernate Type name
s.createQuery( "select cast(e.theLostNumber as org.hibernate.type.LongType) from MyEntity e" ).list();
s.getTransaction().commit();
s.close();
}
@Test
public void testFloatCasting() {
Session s = openSession();
s.beginTransaction();
// using the short name (also the primitive name)
s.createQuery( "select cast(e.theLostNumber as float) from MyEntity e" ).list();
// using the java class name
s.createQuery( "select cast(e.theLostNumber as java.lang.Float) from MyEntity e" ).list();
// using the fqn Hibernate Type name
s.createQuery( "select cast(e.theLostNumber as org.hibernate.type.FloatType) from MyEntity e" ).list();
s.getTransaction().commit();
s.close();
}
}

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.test.hql;
package org.hibernate.orm.test.query.hql;
import java.util.HashMap;
import java.util.List;

View File

@ -9,7 +9,7 @@ package org.hibernate.orm.test.sql.ast;
import java.sql.Types;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.metamodel.model.convert.internal.OrdinalEnumValueConverter;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.orm.test.mapping.SmokeTests.Gender;
@ -31,11 +31,11 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.exec.spi.JdbcSelect;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.graph.basic.BasicResultAssembler;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.graph.basic.BasicResultAssembler;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.type.internal.StandardBasicTypeImpl;
import org.hibernate.testing.hamcrest.AssignableMatcher;
@ -50,7 +50,6 @@ import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
/**
@ -181,7 +180,7 @@ public class SmokeTests {
final ColumnReference columnReference = (ColumnReference) selectedExpression;
assertThat( columnReference.renderSqlFragment( scope.getSessionFactory() ), is( "s1_0.gender" ) );
final MappingModelExpressable selectedExpressable = selectedExpression.getExpressionType();
final JdbcMappingContainer selectedExpressable = selectedExpression.getExpressionType();
assertThat( selectedExpressable, instanceOf( StandardBasicTypeImpl.class ) );
final StandardBasicTypeImpl basicType = (StandardBasicTypeImpl) selectedExpressable;
assertThat( basicType.getJavaTypeDescriptor().getJavaTypeClass(), AssignableMatcher.assignableTo( Integer.class ) );