restrict offset/fetch to be a Number in the Jpa/Sqm tree types

This commit is contained in:
Gavin 2023-07-06 09:48:08 +02:00 committed by Gavin King
parent 98a83a082c
commit 980bf4d8ab
7 changed files with 65 additions and 53 deletions

View File

@ -31,12 +31,12 @@ public interface JpaQueryGroup<T> extends JpaQueryPart<T> {
JpaQueryGroup<T> setSortSpecifications(List<? extends JpaOrder> sortSpecifications);
@Override
JpaQueryGroup<T> setOffset(JpaExpression<?> offset);
JpaQueryGroup<T> setOffset(JpaExpression<? extends Number> offset);
@Override
JpaQueryGroup<T> setFetch(JpaExpression<?> fetch);
JpaQueryGroup<T> setFetch(JpaExpression<? extends Number> fetch);
@Override
JpaQueryGroup<T> setFetch(JpaExpression<?> fetch, FetchClauseType fetchClauseType);
JpaQueryGroup<T> setFetch(JpaExpression<? extends Number> fetch, FetchClauseType fetchClauseType);
}

View File

@ -31,15 +31,17 @@ public interface JpaQueryPart<T> extends JpaCriteriaNode {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Limit/Offset/Fetch clause
JpaExpression<?> getOffset();
//TODO: these operations should only accept integer literals or parameters
JpaQueryPart<T> setOffset(JpaExpression<?> offset);
JpaExpression<? extends Number> getOffset();
JpaExpression<?> getFetch();
JpaQueryPart<T> setOffset(JpaExpression<? extends Number> offset);
JpaQueryPart<T> setFetch(JpaExpression<?> fetch);
JpaExpression<? extends Number> getFetch();
JpaQueryPart<T> setFetch(JpaExpression<?> fetch, FetchClauseType fetchClauseType);
JpaQueryPart<T> setFetch(JpaExpression<? extends Number> fetch);
JpaQueryPart<T> setFetch(JpaExpression<? extends Number> fetch, FetchClauseType fetchClauseType);
FetchClauseType getFetchClauseType();
}

View File

@ -87,11 +87,11 @@ public interface JpaQueryStructure<T> extends JpaQueryPart<T> {
JpaQueryStructure<T> setSortSpecifications(List<? extends JpaOrder> sortSpecifications);
@Override
JpaQueryStructure<T> setOffset(JpaExpression<?> offset);
JpaQueryStructure<T> setOffset(JpaExpression<? extends Number> offset);
@Override
JpaQueryStructure<T> setFetch(JpaExpression<?> fetch);
JpaQueryStructure<T> setFetch(JpaExpression<? extends Number> fetch);
@Override
JpaQueryStructure<T> setFetch(JpaExpression<?> fetch, FetchClauseType fetchClauseType);
JpaQueryStructure<T> setFetch(JpaExpression<? extends Number> fetch, FetchClauseType fetchClauseType);
}

View File

@ -1089,19 +1089,25 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
);
}
sqmQueryPart.setOffsetExpression( visitOffsetClause( offsetClauseContext ) );
if ( limitClauseContext == null ) {
sqmQueryPart.setFetchExpression(
visitFetchClause( fetchClauseContext ),
visitFetchClauseType( fetchClauseContext )
);
}
else if ( fetchClauseContext == null ) {
sqmQueryPart.setFetchExpression( visitLimitClause( limitClauseContext ) );
}
else {
throw new SemanticException("The 'limit' and 'fetch' clauses may not be used together" );
}
setOffsetFetchLimit(sqmQueryPart, limitClauseContext, offsetClauseContext, fetchClauseContext);
}
}
@SuppressWarnings("unchecked")
private void setOffsetFetchLimit(SqmQueryPart<?> sqmQueryPart, HqlParser.LimitClauseContext limitClauseContext, HqlParser.OffsetClauseContext offsetClauseContext, HqlParser.FetchClauseContext fetchClauseContext) {
// these casts are all fine because the parser only accepts literals and parameters
sqmQueryPart.setOffsetExpression((SqmExpression<? extends Number>) visitOffsetClause(offsetClauseContext));
if ( limitClauseContext == null ) {
sqmQueryPart.setFetchExpression(
(SqmExpression<? extends Number>) visitFetchClause(fetchClauseContext),
visitFetchClauseType(fetchClauseContext)
);
}
else if ( fetchClauseContext == null ) {
sqmQueryPart.setFetchExpression( (SqmExpression<? extends Number>) visitLimitClause(limitClauseContext) );
}
else {
throw new SemanticException("The 'limit' and 'fetch' clauses may not be used together" );
}
}

View File

@ -117,22 +117,26 @@ public class SqmQueryGroup<T> extends SqmQueryPart<T> implements JpaQueryGroup<T
@Override
public SqmQueryGroup<T> setSortSpecifications(List<? extends JpaOrder> sortSpecifications) {
return (SqmQueryGroup<T>) super.setSortSpecifications( sortSpecifications );
super.setSortSpecifications( sortSpecifications );
return this;
}
@Override
public SqmQueryGroup<T> setOffset(JpaExpression<?> offset) {
return (SqmQueryGroup<T>) super.setOffset( offset );
public SqmQueryGroup<T> setOffset(JpaExpression<? extends Number> offset) {
super.setOffset( offset );
return this;
}
@Override
public SqmQueryGroup<T> setFetch(JpaExpression<?> fetch) {
return (SqmQueryGroup<T>) super.setFetch( fetch );
public SqmQueryGroup<T> setFetch(JpaExpression<? extends Number> fetch) {
super.setFetch( fetch );
return this;
}
@Override
public SqmQueryGroup<T> setFetch(JpaExpression<?> fetch, FetchClauseType fetchClauseType) {
return (SqmQueryGroup<T>) super.setFetch( fetch, fetchClauseType );
public SqmQueryGroup<T> setFetch(JpaExpression<? extends Number> fetch, FetchClauseType fetchClauseType) {
super.setFetch( fetch, fetchClauseType );
return this;
}
@Override
@ -155,7 +159,7 @@ public class SqmQueryGroup<T> extends SqmQueryPart<T> implements JpaQueryGroup<T
for ( int i = 0; i < queryParts.size(); i++ ) {
final SqmQueryPart<T> queryPart = queryParts.get( i );
if ( queryPart instanceof SqmQueryGroup<?> ) {
( (SqmQueryGroup<Object>) queryPart ).validateQueryGroupFetchStructure( typedNodes );
( (SqmQueryGroup<?>) queryPart ).validateQueryGroupFetchStructure( typedNodes );
}
else {
final SqmQuerySpec<?> querySpec = (SqmQuerySpec<?>) queryPart;

View File

@ -28,8 +28,8 @@ public abstract class SqmQueryPart<T> implements SqmVisitableNode, JpaQueryPart<
private SqmOrderByClause orderByClause;
private SqmExpression<?> offsetExpression;
private SqmExpression<?> fetchExpression;
private SqmExpression<? extends Number> offsetExpression;
private SqmExpression<? extends Number> fetchExpression;
private FetchClauseType fetchClauseType = FetchClauseType.ROWS_ONLY;
public SqmQueryPart(NodeBuilder nodeBuilder) {
@ -85,26 +85,26 @@ public abstract class SqmQueryPart<T> implements SqmVisitableNode, JpaQueryPart<
this.orderByClause = orderByClause;
}
public SqmExpression<?> getFetchExpression() {
public SqmExpression<? extends Number> getFetchExpression() {
return fetchExpression;
}
public SqmExpression<?> getOffsetExpression() {
public SqmExpression<? extends Number> getOffsetExpression() {
return offsetExpression;
}
public void setOffsetExpression(SqmExpression<?> offsetExpression) {
public void setOffsetExpression(SqmExpression<? extends Number> offsetExpression) {
if ( offsetExpression != null ) {
offsetExpression.applyInferableType( nodeBuilder.getIntegerType() );
}
this.offsetExpression = offsetExpression;
}
public void setFetchExpression(SqmExpression<?> fetchExpression) {
public void setFetchExpression(SqmExpression<? extends Number> fetchExpression) {
setFetchExpression( fetchExpression, FetchClauseType.ROWS_ONLY );
}
public void setFetchExpression(SqmExpression<?> fetchExpression, FetchClauseType fetchClauseType) {
public void setFetchExpression(SqmExpression<? extends Number> fetchExpression, FetchClauseType fetchClauseType) {
if ( fetchExpression == null ) {
this.fetchExpression = null;
this.fetchClauseType = null;
@ -149,30 +149,30 @@ public abstract class SqmQueryPart<T> implements SqmVisitableNode, JpaQueryPart<
}
@Override
public SqmExpression<?> getOffset() {
public JpaExpression<? extends Number> getOffset() {
return getOffsetExpression();
}
@Override
public SqmQueryPart<T> setOffset(JpaExpression<?> offset) {
setOffsetExpression( (SqmExpression<?>) offset );
public SqmQueryPart<T> setOffset(JpaExpression<? extends Number> offset) {
setOffsetExpression( (SqmExpression<? extends Number>) offset );
return this;
}
@Override
public SqmExpression<?> getFetch() {
public JpaExpression<? extends Number> getFetch() {
return getFetchExpression();
}
@Override
public SqmQueryPart<T> setFetch(JpaExpression<?> fetch) {
setFetchExpression( (SqmExpression<?>) fetch );
public SqmQueryPart<T> setFetch(JpaExpression<? extends Number> fetch) {
setFetchExpression( (SqmExpression<? extends Number>) fetch );
return this;
}
@Override
public JpaQueryPart<T> setFetch(JpaExpression<?> fetch, FetchClauseType fetchClauseType) {
setFetchExpression( (SqmExpression<?>) fetch, fetchClauseType );
public JpaQueryPart<T> setFetch(JpaExpression<? extends Number> fetch, FetchClauseType fetchClauseType) {
setFetchExpression( (SqmExpression<? extends Number>) fetch, fetchClauseType );
return this;
}

View File

@ -445,20 +445,20 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
}
@Override
public SqmQuerySpec<T> setOffset(JpaExpression<?> offset) {
setOffsetExpression( (SqmExpression<?>) offset );
public SqmQuerySpec<T> setOffset(JpaExpression<? extends Number> offset) {
setOffsetExpression( (SqmExpression<? extends Number>) offset );
return this;
}
@Override
public SqmQuerySpec<T> setFetch(JpaExpression<?> fetch) {
setFetchExpression( (SqmExpression<?>) fetch );
public SqmQuerySpec<T> setFetch(JpaExpression<? extends Number> fetch) {
setFetchExpression( (SqmExpression<? extends Number>) fetch );
return this;
}
@Override
public SqmQuerySpec<T> setFetch(JpaExpression<?> fetch, FetchClauseType fetchClauseType) {
setFetchExpression( (SqmExpression<?>) fetch, fetchClauseType );
public SqmQuerySpec<T> setFetch(JpaExpression<? extends Number> fetch, FetchClauseType fetchClauseType) {
setFetchExpression( (SqmExpression<? extends Number>) fetch, fetchClauseType );
return this;
}