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 {
|
||||
|
||||
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 =
|
||||
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
|
||||
* a semantic model of the query.
|
||||
|
@ -1073,11 +1071,6 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
else {
|
||||
firstIndex = 0;
|
||||
}
|
||||
if ( creationOptions.useStrictJpaCompliance() ) {
|
||||
throw new StrictJpaComplianceViolation(
|
||||
StrictJpaComplianceViolation.Type.SET_OPERATIONS
|
||||
);
|
||||
}
|
||||
final SqmQueryPart<?> firstQueryPart = (SqmQueryPart<?>) children.get( firstIndex ).accept( this );
|
||||
SqmQueryGroup<?> queryGroup;
|
||||
if ( firstQueryPart instanceof SqmQueryGroup<?>) {
|
||||
|
|
|
@ -427,7 +427,13 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
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
|
||||
|
@ -437,12 +443,24 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
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
|
||||
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
|
||||
|
@ -588,12 +606,24 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
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
|
||||
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" })
|
||||
|
@ -1614,6 +1644,16 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
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
|
||||
public SqmExpression<String> concat(Expression<String> x, Expression<String> y) {
|
||||
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
|
||||
public <T> SqmFunction<T> function(String name, Class<T> type, Expression<?>[] args) {
|
||||
final BasicType<T> resultType = getTypeConfiguration().standardBasicTypeForJavaType( type );
|
||||
|
@ -2244,7 +2279,15 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
|
||||
@Override
|
||||
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
|
||||
|
@ -2805,11 +2848,6 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
|
|||
return not( like( x, pattern, escapeChar ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<String> concat(List<Expression<String>> expressions) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notIlike(Expression<String> x, Expression<String> 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(
|
||||
Expression<? extends TemporalAccessor> datetime,
|
||||
TemporalUnit temporalUnit,
|
||||
|
|
|
@ -355,11 +355,16 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
|
|||
|
||||
@Override
|
||||
public SqmQuerySpec<T> setRestriction(Expression<Boolean> restriction) {
|
||||
if ( restriction == null ) {
|
||||
setWhereClause( null );
|
||||
}
|
||||
else {
|
||||
SqmWhereClause whereClause = getWhereClause();
|
||||
if ( whereClause == null ) {
|
||||
setWhereClause( whereClause = new SqmWhereClause( nodeBuilder() ) );
|
||||
}
|
||||
whereClause.setPredicate( nodeBuilder().wrap( restriction ) );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue