From da0e327d09b12dee73b4a8db428bfe50401e0069 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Wed, 7 Feb 2024 13:20:23 +0100 Subject: [PATCH] validate parameters of @SQL query --- .../annotation/AnnotationMetaEntity.java | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java index 039beac2da..3a8b4210d9 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/jpamodelgen/annotation/AnnotationMetaEntity.java @@ -44,6 +44,8 @@ import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.criteria.JpaEntityJoin; import org.hibernate.query.criteria.JpaRoot; import org.hibernate.query.criteria.JpaSelection; +import org.hibernate.query.sql.internal.ParameterParser; +import org.hibernate.query.sql.spi.ParameterRecognizer; import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.expression.SqmParameter; @@ -995,10 +997,12 @@ public class AnnotationMetaEntity extends AnnotationMeta { ); putMember( attribute.getPropertyName() + paramTypes, attribute ); - if ( !isNative ) { + if ( isNative ) { + validateSql( method, mirror, hql, paramNames, value ); + } + else { validateHql( method, returnType, mirror, value, hql, paramNames, paramTypes ); } - //TODO: for SQL queries check that there is a method parameter for every query parameter // now check that the query has a parameter for every method parameter checkParameters( method, paramNames, paramTypes, mirror, value, hql ); @@ -1111,6 +1115,52 @@ public class AnnotationMetaEntity extends AnnotationMeta { } } + private void validateSql( + ExecutableElement method, + AnnotationMirror mirror, + String hql, + List paramNames, + AnnotationValue value) { + // for SQL queries check that there is a method parameter for every query parameter + ParameterParser.parse(hql, new ParameterRecognizer() { + int ordinalCount = 0; + @Override + public void ordinalParameter(int sourcePosition) { + ordinalCount++; + if ( ordinalCount > paramNames.size() ) { + context.message(method, mirror, value, + "missing method parameter for query parameter " + ordinalCount + + " (add a parameter to '" + method.getSimpleName() + "')", + Diagnostic.Kind.ERROR ); + } + } + + @Override + public void namedParameter(String name, int sourcePosition) { + if ( !paramNames.contains(name) ) { + context.message(method, mirror, value, + "missing method parameter for query parameter :" + name + + " (add a parameter '" + name + "' to '" + method.getSimpleName() + "')", + Diagnostic.Kind.ERROR ); + } + } + + @Override + public void jpaPositionalParameter(int label, int sourcePosition) { + if ( label > paramNames.size() ) { + context.message(method, mirror, value, + "missing method parameter for query parameter ?" + label + + " (add a parameter to '" + method.getSimpleName() + "')", + Diagnostic.Kind.ERROR ); + } + } + + @Override + public void other(char character) { + } + }); + } + private static boolean checkConstructorReturn(DeclaredType returnType, JpaSelection selection) { final List> selectionItems = selection.getSelectionItems(); if ( selectionItems == null ) {