-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Add support for optional predicates in Panache #2303
Comments
I like this. This also lets us use |
yes |
I do like how this looks, but I like the separation of predicates more. Separated predicates could still be checked too I believe? Just need to make sure that the root type is made explicit. The weak aspects of this solution:
But don't take this as a blocker; just mentioning the limitations so that we're on the same page on why I prefer the separation of predicates. |
What's your alternative syntax or API look like for the examples I gave @Sanne ? |
I do think it's a good addition to Panache, but I don't think it removes the need to have a A When you test everything with mocks, your test didn't hit the database and the query are never rendered. Having a query that is mechanically generated from an object allows to be sure that this query will be semantically exact. But I'm not 100% fan of some query by example implementation that allows a user to specify any type as long as long as the type have the same attributes as the Entity (this will not longuer by compile checked and type safe) . I can see some advantages (when you have DTO with not all the fields) but I prefere a query by example that uses the same type as the Entity directly. Something like this could be added to Panache:
An other more complex solution should be to provide a Criteria API to provides pragramatically query generation so one could write something like :
This will cover more use cases but add some more complexity in the implementation sides. To conclude, I think that if we want to keep Panache simple, we should add a |
What if PanacheQL was compile time checked. It looks like it would alleviate all the concerns you have. CC @gavinking |
Compile checking PanacheQL queries will be a good thing, but it assume it will not really be compile check but build time check (by the deployment module). So there will be no such check via my IDE ... Anyway, I still support an additional querying facility (example or criteria or something else) than via a simple String, because some people will prefere it. I think that at some point we may add it to Panache, maybe it's not the time now :) |
No we do have annotation processor driven HQL validation we can repurpose for PanacheQL, it will show up in your IDE |
I reviewed this issue and my proposal is to implement this and see how much the other approaches are still sorely missed. I understand the limitations:
Note that falling back to plain JPA is really easy. I can even see us offering CC @FroMage |
So, the proposal is to auto-remove AST nodes of the
The "only" issue is that we'll need to use the HQL parser, which is probably a bit more expensive than what we do ATM. And we can't use it because it will reject identifiers with It's possible we'll want to start expansing those PanacheQL fragments at build-time to cut run-time costs, though probably they are actually moot since Hibernate will parse them anyway later on. |
I think the parser you describe is what @loicmathieu has done for MongoDB right? At least I see the panacheql module with a grammar. While I'm no grammar guy, I think supporting the |
While discussing with @gavinking, he advised to come with a formal set of rules for how the feature should operate. GoalConstruct query structures depending of the presence or absence of a parameter. Examples
you can mix optional predicates and non optional ones.
Formal rulesI explored a few options but in the end Stephane had it the most right with his AST proposal. An optional predicate including a parameter value which is null is removed from the AST node and it's parent Said differently, replace AND and OR nodes with the non optional node. If the AST of the where clause ends up being empty, there are two options:
I haven't made up my mind, I am concerned about the fact that a query could mistakenly return more things than expected in this extreme condition but that's an arbitrary rule. NOTE: it's the whole predicate, not just A few tree pruning examples:
assuming the parameter for L is null, is equivalent to
assuming also that the parameter for F is null, is equivalent to
Another example
assuming the parameter for S is null, is equivalent to
I did not formally prove it but I am pretty sure that regardless of the tree walking algorithm, the pruning algorithm converges to the same results. Failed attemptsI did try another approach which was to replace the optional predicate with
Question on the syntaxI am not super happy about the syntax Here is a verbose but maybe more accurate syntax: Alternative syntaxes
8 and 1 are the most accurate as they select the whole predicate. There you go, we can discuss the semantic now. |
I like the conciseness of I initially thought we could write So, it would feel less ambiguous to mark specially the parameter that can be null, perhaps by changing the |
I do like the proposal of @FromMage to put the optional caracteristic of a predicate on the operator and not the field path, this better describe what is an optional predicate: a variant of an existing predicate. The issue is on the implementation side. Ideally we should be able to work on the AST level to prune nodes that should disapear due to the optionality. That is what @emmanuelbernard describe in his comment (by the way, thanks for it, it adds a lot of clarity for what needs to be done). If you look at my implementation for MongoDB you can see that it's not what I did. In fact, the current PanacheQL implementation inside MongoDB with Panache uses an Antlr visitor, the visitor is not capable or pruning an AST node (it can only replace it, not remove it), and not capable of updatong the parent node. So, the implementation is harder that what it seems first, if we cannot simply replace a node by something else (empty document for MongoDB, 1=1 where clause for Hibernate) the implementation will be very much complex ... |
What about
It is more verbose but very clear. |
I'd like to ask for @gavinking's opinion about syntax. He's pretty good at throwing ideas in and out. |
Hrm. I've been tagged so many times in this issue, but somehow I never got a proper notification until Stef sent me a message today. Need to check my filters. |
Alright, so my first reactions are:
So I guess I like the look of:
I find this very readable. However, there is one thing that's wrong with that: the logical connectives should really also go inside the brackets, yielding:
However, I'm not sure I like that better. OTOH, consider the extension to multiple predicates within a single optional condition:
WDYT? |
(P.S. I know I was the one advocating that we treat this as some sort of pseudo "function" in HQL, and I can see I'm sorta walking back from that now, at least with respect to the syntax.) |
Potential objection of using brackets is that it hammers the natural syntax for list literals. But I highly doubt we'll ever want list literals in HQL. |
Well, in my mind, this is a two-actor team:
So the semantics really belong mostly on the operator, because it's that operator which changes semantics if we opt in or not:
|
@FroMage Yeah, I originally tried to go down that path when I chatted with Emmanuel, but I think we decided that no, that would be adding a new sort of ternary logic that collided with the ternary logic of SQL and was broken in novel and different ways to SQL's ternary logic. So after a bit of a think about it I decided it would probably be a mistake. |
So, with that in mind, I guess I'd favour the following variants:
The Perl user in me finds |
To be clear, I think either of those options are perfectly acceptable outcomes. They're very readable. OTOH, the option of putting the operator inside the brackets does have the advantage that we don't have to come up with strange and half-convincing backsplanations as to what is the meaning of a dangling |
(The issue being that |
Rrrrm the more I stare at this example, the more I think it's telling us that the logical operator should go inside:
|
Not even, see this loooong post #2303 (comment) |
So I considered the Gavin bracket syntax and was scared it would conflict with HQL but if it does not, I think that's the winner.
|
Any progress of this? I would like to use Typesafe APIs such as JPA Creteria(Specification in Spring Data JPA) or QueryDSL to assemble the Query logic by pure Java codes instead of literal strings. |
I came here after posting this |
Any updates on this ? |
@antssilva96 no update on it, you can see #8136 that tries to sum up all the ideas around dynamic query support in Panache. I open a discussion on Zulip as I think we need to move forward or decide to close all these issues: https://quarkusio.zulipchat.com/#narrow/stream/187038-dev/topic/Panache.20dynamic.20query |
Any update ? |
What people use the example API for is for generic "search" screens that need to accept between 1 to n predicates depending on what the user as filled in. And the example API does allow to do such matching assuming the search fields are all in one entity as properties and by adding side metadata on what property needs to be ignored, ignored if null, have a trailing % in like etc.
The following Panache model would scale better. I call it the destructured example API
The trailing
?
per property expresses that the predicate on the property should be ignored if the property is null.The advantages I see to this approach are:
Thoughts @gavinking @Sanne @gsmet @FroMage ?
The text was updated successfully, but these errors were encountered: