jamesfredley commented on code in PR #16816:
URL: https://github.com/apache/grails-core/pull/16816#discussion_r4475314067
##########
grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java:
##########
@@ -961,4 +1031,29 @@ else if (criterion instanceof AssociationCriteria) {
return position;
}
+
+ private static String functionOperator(Query.PropertyCriterion wrapped) {
+ if (wrapped instanceof Query.Equals) {
+ return " = ";
+ }
+ if (wrapped instanceof Query.NotEquals) {
+ return " != ";
+ }
+ if (wrapped instanceof Query.GreaterThan) {
+ return " > ";
+ }
+ if (wrapped instanceof Query.GreaterThanEquals) {
+ return " >= ";
+ }
+ if (wrapped instanceof Query.LessThan) {
+ return " < ";
+ }
+ if (wrapped instanceof Query.LessThanEquals) {
+ return " <= ";
+ }
+ if (wrapped instanceof Query.Like) {
Review Comment:
A function around an rlike comparison, then deleteAll(), deletes nothing
when the name matches the regular expression. RLike is a Like, so this branch
emits LIKE. Handle the regular expression before this branch. A read of the
same criterion already uses the regular expression.
##########
grails-datastore-core/src/main/groovy/org/grails/datastore/mapping/query/jpa/JpaQueryBuilder.java:
##########
@@ -605,6 +606,73 @@ public int handle(PersistentEntity entity, Query.Criterion
criterion, StringBuil
}
});
+ queryHandlers.put(FunctionCallingCriterion.class, new QueryHandler() {
+ public int handle(PersistentEntity entity, Query.Criterion
criterion, StringBuilder q, StringBuilder whereClause, String logicalName, int
position, List parameters, ConversionService conversionService, boolean
allowJoins, boolean hibernateCompatible) {
+ FunctionCallingCriterion functionCriterion =
(FunctionCallingCriterion) criterion;
+ String name = functionCriterion.getProperty();
+ validateProperty(entity, name, FunctionCallingCriterion.class);
+ if (functionCriterion.isOnValue()) {
+ throw new InvalidDataAccessResourceUsageException("A
function on the value of a comparison is not supported: " +
functionCriterion.getFunctionName());
+ }
+ Query.PropertyCriterion wrapped =
functionCriterion.getPropertyCriterion();
+ if (wrapped instanceof Query.ILike) {
+ whereClause.append("lower(")
+ .append(functionCriterion.getFunctionName())
+ .append(OPEN_BRACKET)
+ .append(logicalName)
+ .append(DOT)
+ .append(name)
+ .append(CLOSE_BRACKET)
+ .append(") like lower(")
+ .append(PARAMETER_PREFIX)
+ .append(++position)
+ .append(CLOSE_BRACKET);
+ parameters.add(wrapped.getValue());
+ return position;
+ }
+ whereClause.append(functionCriterion.getFunctionName())
+ .append(OPEN_BRACKET)
+ .append(logicalName)
+ .append(DOT)
+ .append(name)
+ .append(CLOSE_BRACKET);
+ if (wrapped instanceof Query.In in) {
+ whereClause.append(" IN (");
+ QueryableCriteria subquery = in.getSubquery();
+ if (subquery != null) {
+ buildSubQuery(q, whereClause, position, parameters,
conversionService, allowJoins, hibernateCompatible, subquery);
+ position = parameters.size();
+ }
+ else {
+ for (Iterator i = in.getValues().iterator();
i.hasNext();) {
+ Object val = i.next();
+
whereClause.append(PARAMETER_PREFIX).append(++position);
+ if (i.hasNext()) {
+ whereClause.append(COMMA);
+ }
+ parameters.add(val);
+ }
+ }
+ whereClause.append(CLOSE_BRACKET);
+ }
+ else if (wrapped instanceof Query.Equals && wrapped.getValue()
== null) {
+ whereClause.append(" IS NULL");
+ }
+ else if (wrapped instanceof Query.NotEquals &&
wrapped.getValue() == null) {
+ whereClause.append(" IS NOT NULL");
+ }
+ else {
+ String operator = functionOperator(wrapped);
+ if (operator == null) {
+ throw new
InvalidDataAccessResourceUsageException("Unsupported criterion in a function
call: " + wrapped.getClass().getSimpleName());
+ }
+
whereClause.append(operator).append(PARAMETER_PREFIX).append(++position);
+ parameters.add(wrapped.getValue());
Review Comment:
A function around an equality whose value is a one-row detached criteria,
then deleteAll(), binds the criteria object as the parameter and the update
fails. Render that value as a subquery, as the read path does.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]