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); JpaQueryGroup<T> setSortSpecifications(List<? extends JpaOrder> sortSpecifications);
@Override @Override
JpaQueryGroup<T> setOffset(JpaExpression<?> offset); JpaQueryGroup<T> setOffset(JpaExpression<? extends Number> offset);
@Override @Override
JpaQueryGroup<T> setFetch(JpaExpression<?> fetch); JpaQueryGroup<T> setFetch(JpaExpression<? extends Number> fetch);
@Override @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 // 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(); FetchClauseType getFetchClauseType();
} }

View File

@ -87,11 +87,11 @@ public interface JpaQueryStructure<T> extends JpaQueryPart<T> {
JpaQueryStructure<T> setSortSpecifications(List<? extends JpaOrder> sortSpecifications); JpaQueryStructure<T> setSortSpecifications(List<? extends JpaOrder> sortSpecifications);
@Override @Override
JpaQueryStructure<T> setOffset(JpaExpression<?> offset); JpaQueryStructure<T> setOffset(JpaExpression<? extends Number> offset);
@Override @Override
JpaQueryStructure<T> setFetch(JpaExpression<?> fetch); JpaQueryStructure<T> setFetch(JpaExpression<? extends Number> fetch);
@Override @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 ) ); setOffsetFetchLimit(sqmQueryPart, limitClauseContext, offsetClauseContext, fetchClauseContext);
if ( limitClauseContext == null ) { }
sqmQueryPart.setFetchExpression( }
visitFetchClause( fetchClauseContext ),
visitFetchClauseType( 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
else if ( fetchClauseContext == null ) { sqmQueryPart.setOffsetExpression((SqmExpression<? extends Number>) visitOffsetClause(offsetClauseContext));
sqmQueryPart.setFetchExpression( visitLimitClause( limitClauseContext ) ); if ( limitClauseContext == null ) {
} sqmQueryPart.setFetchExpression(
else { (SqmExpression<? extends Number>) visitFetchClause(fetchClauseContext),
throw new SemanticException("The 'limit' and 'fetch' clauses may not be used together" ); 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 @Override
public SqmQueryGroup<T> setSortSpecifications(List<? extends JpaOrder> sortSpecifications) { public SqmQueryGroup<T> setSortSpecifications(List<? extends JpaOrder> sortSpecifications) {
return (SqmQueryGroup<T>) super.setSortSpecifications( sortSpecifications ); super.setSortSpecifications( sortSpecifications );
return this;
} }
@Override @Override
public SqmQueryGroup<T> setOffset(JpaExpression<?> offset) { public SqmQueryGroup<T> setOffset(JpaExpression<? extends Number> offset) {
return (SqmQueryGroup<T>) super.setOffset( offset ); super.setOffset( offset );
return this;
} }
@Override @Override
public SqmQueryGroup<T> setFetch(JpaExpression<?> fetch) { public SqmQueryGroup<T> setFetch(JpaExpression<? extends Number> fetch) {
return (SqmQueryGroup<T>) super.setFetch( fetch ); super.setFetch( fetch );
return this;
} }
@Override @Override
public SqmQueryGroup<T> setFetch(JpaExpression<?> fetch, FetchClauseType fetchClauseType) { public SqmQueryGroup<T> setFetch(JpaExpression<? extends Number> fetch, FetchClauseType fetchClauseType) {
return (SqmQueryGroup<T>) super.setFetch( fetch, fetchClauseType ); super.setFetch( fetch, fetchClauseType );
return this;
} }
@Override @Override
@ -155,7 +159,7 @@ public class SqmQueryGroup<T> extends SqmQueryPart<T> implements JpaQueryGroup<T
for ( int i = 0; i < queryParts.size(); i++ ) { for ( int i = 0; i < queryParts.size(); i++ ) {
final SqmQueryPart<T> queryPart = queryParts.get( i ); final SqmQueryPart<T> queryPart = queryParts.get( i );
if ( queryPart instanceof SqmQueryGroup<?> ) { if ( queryPart instanceof SqmQueryGroup<?> ) {
( (SqmQueryGroup<Object>) queryPart ).validateQueryGroupFetchStructure( typedNodes ); ( (SqmQueryGroup<?>) queryPart ).validateQueryGroupFetchStructure( typedNodes );
} }
else { else {
final SqmQuerySpec<?> querySpec = (SqmQuerySpec<?>) queryPart; final SqmQuerySpec<?> querySpec = (SqmQuerySpec<?>) queryPart;

View File

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

View File

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