Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix binding embeded id parameter #3131

Closed
wants to merge 1 commit into from
Closed

Conversation

radovanradic
Copy link
Contributor

Fix for issue #3125

@@ -48,6 +51,13 @@ public QueryParameterBinding bind(BindingContext bindingContext) {
if (outgoingQueryParameterProperty == null) {
return new SimpleParameterBinding(name, DataType.forType(paramClass), bindingContext.isExpandable(), value);
}
return new PropertyPathParameterBinding(name, outgoingQueryParameterProperty, bindingContext.isExpandable(), value);
Object parameterValue = value;
if (value != null && outgoingQueryParameterProperty.getProperty().getOwner().isEmbeddable()) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dstepanov So here is the case that DefaultParameterExpression gets value as embeded id but binding parameters should be each field of embedded id. So, we need to extract value for the param if field belongs to embedded id and passed value is embedded id. Not sure if this is safe enough and if there is some better approach to extract correct value for embedded id part(s).

Copy link
Contributor

@dstepanov dstepanov Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be expanded in the equals operator, similar to the composite identity:

public void visitEquals(Expression<?> leftExpression, Expression<?> rightExpression, boolean ignoreCase) {
if (leftExpression instanceof io.micronaut.data.model.jpa.criteria.PersistentPropertyPath<?> persistentPropertyPath) {
PersistentPropertyPath propertyPath = persistentPropertyPath.getPropertyPath();
PersistentProperty property = propertyPath.getProperty();
if (computePropertyPaths() && property instanceof Association) {
List<IPredicate> predicates = new ArrayList<>();
PersistentEntityUtils.traverse(propertyPath, pp ->
predicates.add(new BinaryPredicate(
new DefaultPersistentPropertyPath<>(pp, null),
rightExpression,
ignoreCase ? PredicateBinaryOp.EQUALS_IGNORE_CASE : PredicateBinaryOp.EQUALS
))
);
if (predicates.size() == 1) {

Copy link
Contributor Author

@radovanradic radovanradic Sep 16, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Predicate and criteria is ok, association is expanded and query generated is

UPDATE `Shipment1` SET `field`=? WHERE (`sp_country` = ? AND `sp_city` = ?)

but each of these 2 bindings for WHERE criteria is ShipmentId instead of each property of the embedded id getting from here

@NotNull
    @NextMajorVersion("Require non null y")
    private Predicate predicate(Expression<?> x, Object y, PredicateBinaryOp op) {
        if (x instanceof IdExpression) {
            return new ExpressionBinaryPredicate(x, literal(y), op);
        }
        return new PersistentPropertyBinaryPredicate<>(requireProperty(x), literal(y), op);
    }

This is why we need to get actual embedded id field value in the bind method above.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should be done a bit differently:

  • We need to add PersistentPropertyPath parameterPropertyPath to DefaultParameterExpression like it's in SourceParameterExpressionImpl
  • When the property is expanded, we should try to recognize DefaultParameterExpression and clone it to a new parameter with parameterPropertyPath set the left property path
  • DefaultParameterExpression should use the same logic as in the source one to calculate parameterBindingPath
  • DefaultBindableParametersStoredQuery should support using getParameterBindingPath for cases when the value set

Copy link

sonarcloud bot commented Sep 16, 2024

@radovanradic radovanradic marked this pull request as ready for review September 16, 2024 12:55
@radovanradic radovanradic marked this pull request as draft September 16, 2024 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants