HHH-17982 Implement some JPA 3.2 methods
This commit is contained in:
parent
3e423ce900
commit
472d8eaa25
|
@ -276,39 +276,37 @@ import static org.hibernate.type.spi.TypeConfiguration.isJdbcTemporalType;
|
||||||
public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implements SqmCreationState {
|
public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implements SqmCreationState {
|
||||||
|
|
||||||
private static final Logger log = Logger.getLogger( SemanticQueryBuilder.class );
|
private static final Logger log = Logger.getLogger( SemanticQueryBuilder.class );
|
||||||
private static final Set<String> JPA_STANDARD_FUNCTIONS;
|
private static final Set<String> JPA_STANDARD_FUNCTIONS = Set.of(
|
||||||
|
"avg",
|
||||||
|
"max",
|
||||||
|
"min",
|
||||||
|
"sum",
|
||||||
|
"count",
|
||||||
|
"length",
|
||||||
|
"locate",
|
||||||
|
"abs",
|
||||||
|
"sqrt",
|
||||||
|
"mod",
|
||||||
|
"size",
|
||||||
|
"index",
|
||||||
|
"current_date",
|
||||||
|
"current_time",
|
||||||
|
"current_timestamp",
|
||||||
|
"concat",
|
||||||
|
"substring",
|
||||||
|
"trim",
|
||||||
|
"lower",
|
||||||
|
"upper",
|
||||||
|
"coalesce",
|
||||||
|
"nullif",
|
||||||
|
"left",
|
||||||
|
"right",
|
||||||
|
"replace"
|
||||||
|
);
|
||||||
|
|
||||||
private static final BasicTypeImpl<Object> OBJECT_BASIC_TYPE =
|
private static final BasicTypeImpl<Object> OBJECT_BASIC_TYPE =
|
||||||
new BasicTypeImpl<>( new UnknownBasicJavaType<>(Object.class), ObjectJdbcType.INSTANCE );
|
new BasicTypeImpl<>( new UnknownBasicJavaType<>(Object.class), ObjectJdbcType.INSTANCE );
|
||||||
|
|
||||||
static {
|
|
||||||
final Set<String> jpaStandardFunctions = new HashSet<>();
|
|
||||||
// Extracted from the BNF in JPA spec 4.14.
|
|
||||||
jpaStandardFunctions.add( "avg" );
|
|
||||||
jpaStandardFunctions.add( "max" );
|
|
||||||
jpaStandardFunctions.add( "min" );
|
|
||||||
jpaStandardFunctions.add( "sum" );
|
|
||||||
jpaStandardFunctions.add( "count" );
|
|
||||||
jpaStandardFunctions.add( "length" );
|
|
||||||
jpaStandardFunctions.add( "locate" );
|
|
||||||
jpaStandardFunctions.add( "abs" );
|
|
||||||
jpaStandardFunctions.add( "sqrt" );
|
|
||||||
jpaStandardFunctions.add( "mod" );
|
|
||||||
jpaStandardFunctions.add( "size" );
|
|
||||||
jpaStandardFunctions.add( "index" );
|
|
||||||
jpaStandardFunctions.add( "current_date" );
|
|
||||||
jpaStandardFunctions.add( "current_time" );
|
|
||||||
jpaStandardFunctions.add( "current_timestamp" );
|
|
||||||
jpaStandardFunctions.add( "concat" );
|
|
||||||
jpaStandardFunctions.add( "substring" );
|
|
||||||
jpaStandardFunctions.add( "trim" );
|
|
||||||
jpaStandardFunctions.add( "lower" );
|
|
||||||
jpaStandardFunctions.add( "upper" );
|
|
||||||
jpaStandardFunctions.add( "coalesce" );
|
|
||||||
jpaStandardFunctions.add( "nullif" );
|
|
||||||
JPA_STANDARD_FUNCTIONS = jpaStandardFunctions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main entry point into analysis of HQL/JPQL parse tree - producing
|
* Main entry point into analysis of HQL/JPQL parse tree - producing
|
||||||
* a semantic model of the query.
|
* a semantic model of the query.
|
||||||
|
@ -1073,11 +1071,6 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
||||||
else {
|
else {
|
||||||
firstIndex = 0;
|
firstIndex = 0;
|
||||||
}
|
}
|
||||||
if ( creationOptions.useStrictJpaCompliance() ) {
|
|
||||||
throw new StrictJpaComplianceViolation(
|
|
||||||
StrictJpaComplianceViolation.Type.SET_OPERATIONS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
final SqmQueryPart<?> firstQueryPart = (SqmQueryPart<?>) children.get( firstIndex ).accept( this );
|
final SqmQueryPart<?> firstQueryPart = (SqmQueryPart<?>) children.get( firstIndex ).accept( this );
|
||||||
SqmQueryGroup<?> queryGroup;
|
SqmQueryGroup<?> queryGroup;
|
||||||
if ( firstQueryPart instanceof SqmQueryGroup<?>) {
|
if ( firstQueryPart instanceof SqmQueryGroup<?>) {
|
||||||
|
|
|
@ -427,7 +427,13 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> CriteriaSelect<T> unionAll(CriteriaSelect<? extends T> left, CriteriaSelect<? extends T> right) {
|
public <T> CriteriaSelect<T> unionAll(CriteriaSelect<? extends T> left, CriteriaSelect<? extends T> right) {
|
||||||
return null;
|
if ( left instanceof Subquery<?> ) {
|
||||||
|
assert right instanceof Subquery<?>;
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.UNION_ALL, (Subquery<T>) left, (Subquery<T>) right );
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.UNION_ALL, (JpaCriteriaQuery<T>) left, (JpaCriteriaQuery<T>) right );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -437,12 +443,24 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> CriteriaSelect<T> except(CriteriaSelect<T> left, CriteriaSelect<?> right) {
|
public <T> CriteriaSelect<T> except(CriteriaSelect<T> left, CriteriaSelect<?> right) {
|
||||||
return null;
|
if ( left instanceof Subquery<?> ) {
|
||||||
|
assert right instanceof Subquery<?>;
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.EXCEPT, (Subquery<T>) left, (Subquery<T>) right );
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.EXCEPT, (JpaCriteriaQuery<T>) left, (JpaCriteriaQuery<T>) right );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> CriteriaSelect<T> exceptAll(CriteriaSelect<T> left, CriteriaSelect<?> right) {
|
public <T> CriteriaSelect<T> exceptAll(CriteriaSelect<T> left, CriteriaSelect<?> right) {
|
||||||
return null;
|
if ( left instanceof Subquery<?> ) {
|
||||||
|
assert right instanceof Subquery<?>;
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.EXCEPT_ALL, (Subquery<T>) left, (Subquery<T>) right );
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.EXCEPT_ALL, (JpaCriteriaQuery<T>) left, (JpaCriteriaQuery<T>) right );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -588,12 +606,24 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> CriteriaSelect<T> intersect(CriteriaSelect<? super T> left, CriteriaSelect<? super T> right) {
|
public <T> CriteriaSelect<T> intersect(CriteriaSelect<? super T> left, CriteriaSelect<? super T> right) {
|
||||||
return null;
|
if ( left instanceof Subquery<?> ) {
|
||||||
|
assert right instanceof Subquery<?>;
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.INTERSECT, (Subquery<T>) left, (Subquery<T>) right );
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.INTERSECT, (JpaCriteriaQuery<T>) left, (JpaCriteriaQuery<T>) right );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> CriteriaSelect<T> intersectAll(CriteriaSelect<? super T> left, CriteriaSelect<? super T> right) {
|
public <T> CriteriaSelect<T> intersectAll(CriteriaSelect<? super T> left, CriteriaSelect<? super T> right) {
|
||||||
return null;
|
if ( left instanceof Subquery<?> ) {
|
||||||
|
assert right instanceof Subquery<?>;
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.INTERSECT_ALL, (Subquery<T>) left, (Subquery<T>) right );
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return setOperation( SetOperator.INTERSECT_ALL, (JpaCriteriaQuery<T>) left, (JpaCriteriaQuery<T>) right );
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
@ -1614,6 +1644,16 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
return new JpaCriteriaParameter<>( name, parameterType, notBasic, this );
|
return new JpaCriteriaParameter<>( name, parameterType, notBasic, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SqmExpression<String> concat(List<Expression<String>> expressions) {
|
||||||
|
//noinspection unchecked
|
||||||
|
return getFunctionDescriptor( "concat" ).generateSqmExpression(
|
||||||
|
(List<? extends SqmTypedNode<?>>) (List<?>) expressions,
|
||||||
|
null,
|
||||||
|
getQueryEngine()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmExpression<String> concat(Expression<String> x, Expression<String> y) {
|
public SqmExpression<String> concat(Expression<String> x, Expression<String> y) {
|
||||||
final SqmExpression<String> xSqmExpression = (SqmExpression<String>) x;
|
final SqmExpression<String> xSqmExpression = (SqmExpression<String>) x;
|
||||||
|
@ -1918,11 +1958,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public <N, T extends Temporal> SqmExpression<N> extract(TemporalField<N, T> field, Expression<T> temporal) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> SqmFunction<T> function(String name, Class<T> type, Expression<?>[] args) {
|
public <T> SqmFunction<T> function(String name, Class<T> type, Expression<?>[] args) {
|
||||||
final BasicType<T> resultType = getTypeConfiguration().standardBasicTypeForJavaType( type );
|
final BasicType<T> resultType = getTypeConfiguration().standardBasicTypeForJavaType( type );
|
||||||
|
@ -2244,7 +2279,15 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPredicate and(List<Predicate> restrictions) {
|
public SqmPredicate and(List<Predicate> restrictions) {
|
||||||
return null;
|
if ( restrictions == null || restrictions.isEmpty() ) {
|
||||||
|
return conjunction();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<SqmPredicate> predicates = new ArrayList<>( restrictions.size() );
|
||||||
|
for ( Predicate expression : restrictions ) {
|
||||||
|
predicates.add( (SqmPredicate) expression );
|
||||||
|
}
|
||||||
|
return new SqmJunctionPredicate( Predicate.BooleanOperator.AND, predicates, this );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2805,11 +2848,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
return not( like( x, pattern, escapeChar ) );
|
return not( like( x, pattern, escapeChar ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public SqmExpression<String> concat(List<Expression<String>> expressions) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmPredicate notIlike(Expression<String> x, Expression<String> pattern) {
|
public SqmPredicate notIlike(Expression<String> x, Expression<String> pattern) {
|
||||||
return not( ilike( x, pattern ) );
|
return not( ilike( x, pattern ) );
|
||||||
|
@ -2957,6 +2995,51 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <N, T extends Temporal> SqmExpression<N> extract(TemporalField<N, T> field, Expression<T> temporal) {
|
||||||
|
Class<?> resultType = Integer.class;
|
||||||
|
final TemporalUnit temporalUnit;
|
||||||
|
switch ( field.toString() ) {
|
||||||
|
case "year":
|
||||||
|
temporalUnit = TemporalUnit.YEAR;
|
||||||
|
break;
|
||||||
|
case "quarter":
|
||||||
|
temporalUnit = TemporalUnit.QUARTER;
|
||||||
|
break;
|
||||||
|
case "month":
|
||||||
|
temporalUnit = TemporalUnit.MONTH;
|
||||||
|
break;
|
||||||
|
case "week":
|
||||||
|
temporalUnit = TemporalUnit.WEEK;
|
||||||
|
break;
|
||||||
|
case "day":
|
||||||
|
temporalUnit = TemporalUnit.DAY;
|
||||||
|
break;
|
||||||
|
case "hour":
|
||||||
|
temporalUnit = TemporalUnit.HOUR;
|
||||||
|
break;
|
||||||
|
case "minute":
|
||||||
|
temporalUnit = TemporalUnit.MINUTE;
|
||||||
|
break;
|
||||||
|
case "second":
|
||||||
|
temporalUnit = TemporalUnit.SECOND;
|
||||||
|
resultType = Double.class;
|
||||||
|
break;
|
||||||
|
case "date":
|
||||||
|
temporalUnit = TemporalUnit.DATE;
|
||||||
|
resultType = LocalDate.class;
|
||||||
|
break;
|
||||||
|
case "time":
|
||||||
|
temporalUnit = TemporalUnit.TIME;
|
||||||
|
resultType = LocalTime.class;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException( "Invalid temporal field [" + field + "]" );
|
||||||
|
}
|
||||||
|
//noinspection unchecked
|
||||||
|
return extract( temporal, temporalUnit, (Class<N>) resultType );
|
||||||
|
}
|
||||||
|
|
||||||
private <T> SqmFunction<T> extract(
|
private <T> SqmFunction<T> extract(
|
||||||
Expression<? extends TemporalAccessor> datetime,
|
Expression<? extends TemporalAccessor> datetime,
|
||||||
TemporalUnit temporalUnit,
|
TemporalUnit temporalUnit,
|
||||||
|
|
|
@ -355,11 +355,16 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmQuerySpec<T> setRestriction(Expression<Boolean> restriction) {
|
public SqmQuerySpec<T> setRestriction(Expression<Boolean> restriction) {
|
||||||
|
if ( restriction == null ) {
|
||||||
|
setWhereClause( null );
|
||||||
|
}
|
||||||
|
else {
|
||||||
SqmWhereClause whereClause = getWhereClause();
|
SqmWhereClause whereClause = getWhereClause();
|
||||||
if ( whereClause == null ) {
|
if ( whereClause == null ) {
|
||||||
setWhereClause( whereClause = new SqmWhereClause( nodeBuilder() ) );
|
setWhereClause( whereClause = new SqmWhereClause( nodeBuilder() ) );
|
||||||
}
|
}
|
||||||
whereClause.setPredicate( nodeBuilder().wrap( restriction ) );
|
whereClause.setPredicate( nodeBuilder().wrap( restriction ) );
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue