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

Incorrect behaviour of logical not #64

Open
glyn opened this issue Jun 24, 2020 · 16 comments
Open

Incorrect behaviour of logical not #64

glyn opened this issue Jun 24, 2020 · 16 comments
Labels
Proposal A Anything discussing the advance of the Proposal A for a formal specification of JSONPath

Comments

@glyn
Copy link
Collaborator

glyn commented Jun 24, 2020

It seems that logical not (!) in filters in Proposal A doesn't work as expected. For example:

$ echo '[0]' | ./run.sh '$[?(true)]'
[0]
$ echo '[0]' | ./run.sh '$[?(!false)]'
[]
@glyn glyn added the Proposal A Anything discussing the advance of the Proposal A for a formal specification of JSONPath label Jun 24, 2020
@glyn
Copy link
Collaborator Author

glyn commented Jun 24, 2020

Or is it that boolean literals aren't evaluated as boolean expressions?

@cburgmer
Copy link
Owner

Not going to justify the implementation here, just to confirm your observation:

Proposal A here parses to the hasValue operator, which is implemented by this simple function (result) => result !== undefined. Anything representable in JSON is not undefined, so in this context any constant value would have the same effect as true. Negating a constant value then means nothing matches.

Now, what would we expect?

@glyn
Copy link
Collaborator Author

glyn commented Jun 25, 2020

@ and $ paths "on their own" (i.e. not involved in a comparison) in a filter denote an existence test, but I don't think that makes much sense for literals "on their own".

The syntax doesn't rule out literals "on their own", which I suppose would be one (perhaps rather draconian) option.

I don't think it makes sense to try to attach meaningful boolean values to string, numeric, and null literals as there isn't much intuition to guide the user there. If we continue to allow these syntactically, it's probably safest to make these equivalent to a false predicate so the user gets some kind of early feedback if, for example, they have missed out a comparison.

However, for boolean literals, there is an obvious intuition and I think we should support it. A boolean literal should denote the corresponding true or false predicate.

Apart from reducing the surprise factor, there may be a use case for this. Suppose someone is debugging a complex filter. They may wish to temporarily replace some of the predicates inside the filter with true or false to see what effect that has. The current behaviour would surely confuse matters.

@remorhaz remorhaz reopened this Jun 25, 2020
@remorhaz
Copy link
Collaborator

remorhaz commented Jun 25, 2020

Sorry, guys, just pressed wrong button.

I agree that true/false literals should have clear boolean semantics. What about other standalone literals - I've just forbid them on grammar level in my implementation, so the user can get the early feedback.

@cburgmer
Copy link
Owner

What do you think of https://cburgmer.github.io/json-path-comparison/results/filter_expression_with_equals_boolean_expression_value.html ? Is that comparable? For me what links the queries here is that true and false can actively be used in the logic, not only as valid JSON value.

@glyn
Copy link
Collaborator Author

glyn commented Jun 25, 2020

It's similar, but that is treating predicates as booleans rather than treating boolean literals as predicates, so we could make a distinction on that basis. It reminds me of certain languages which have predicates but no boolean type.

@cburgmer
Copy link
Owner

I agree that the constants currently are not helpful, borderline misleading. I created #66 to address that. Let me know what you think please.

We would have to make a slightly bigger change to support boolean values as part of the logic, I suggest we address this in a second change.

Let's talk more about what we want there. I'd like to understand the bigger picture.

@glyn
Copy link
Collaborator Author

glyn commented Jun 30, 2020

We would have to make a slightly bigger change to support boolean values as part of the logic, I suggest we address this in a second change.

I have yet to understand the real benefit of supporting this.

@cburgmer
Copy link
Owner

cburgmer commented Jul 1, 2020

I think I need to process a bit more what you initially wrote @glyn. Apologies that I didn't initial react to that, I think I need some quiet moment to reflect on the problem at hand.

However, for boolean literals, there is an obvious intuition and I think we should support it. A boolean literal should denote the corresponding true or false predicate.

I read this as [?(false)] to be valid and not to match anything, while [?(true)] matches everything?

Apart from reducing the surprise factor, there may be a use case for this. Suppose someone is debugging a complex filter. They may wish to temporarily replace some of the predicates inside the filter with true or false to see what effect that has. The current behaviour would surely confuse matters.

And here I understand you are calling for a more general predicate, so we can write something like [?(@.key=42 && true)]?

I don't think it makes sense to try to attach meaningful boolean values to string, numeric, and null literals as there isn't much intuition to guide the user there. If we continue to allow these syntactically, it's probably safest to make these equivalent to a false predicate so the user gets some kind of early feedback if, for example, they have missed out a comparison.

This is about whether to allow constants other than true or false in filter expressions, and what their impact is when combined with other predicates (or on their own) I understand.

And I understand this is a separate thing from trying to assign predicates a value that can be tested in the filter expression in a dedicated way (like $[?((@.key<44)==false)]).

I'll think a bit on that, and will add a few more queries to probe into support of the implementations.

@glyn
Copy link
Collaborator Author

glyn commented Jul 1, 2020

I think I need to process a bit more what you initially wrote @glyn. Apologies that I didn't initial react to that, I think I need some quiet moment to reflect on the problem at hand.

However, for boolean literals, there is an obvious intuition and I think we should support it. A boolean literal should denote the corresponding true or false predicate.

I read this as [?(false)] to be valid and not to match anything, while [?(true)] matches everything?

Yes, that's what I meant.

Apart from reducing the surprise factor, there may be a use case for this. Suppose someone is debugging a complex filter. They may wish to temporarily replace some of the predicates inside the filter with true or false to see what effect that has. The current behaviour would surely confuse matters.

And here I understand you are calling for a more general predicate, so we can write something like [?(@.key=42 && true)]?

Yes.

I don't think it makes sense to try to attach meaningful boolean values to string, numeric, and null literals as there isn't much intuition to guide the user there. If we continue to allow these syntactically, it's probably safest to make these equivalent to a false predicate so the user gets some kind of early feedback if, for example, they have missed out a comparison.

This is about whether to allow constants other than true or false in filter expressions, and what their impact is when combined with other predicates (or on their own) I understand.

And I understand this is a separate thing from trying to assign predicates a value that can be tested in the filter expression in a dedicated way (like $[?((@.key<44)==false)]).

Yes, and I don't yet understand the benefit of supporting $[?((@.key<44)==false)].

I'll think a bit on that, and will add a few more queries to probe into support of the implementations.

That will be useful, thanks.

cburgmer added a commit that referenced this issue Jul 1, 2020
@cburgmer
Copy link
Owner

cburgmer commented Jul 2, 2020

Looking at the queries added, there's spotty support for true/false in predicates, and some less intuitive responses as well ("looks buggy").

The more I think about it, the less reasons I see not support that.

I am probably mostly grappling with $[?(false)] vs. $[?(@.key)] for document [{"key": false}]. The former would return no matches, the latter would return {"key": false} (as @.key indeed has a value).
What we are saying is that false and true have no relationship to the JSON values false and true. Considering that we might want to support all JSON values (even arrays and objects) in comparisons, I wonder how much of a surprise this will be to our users.

@remorhaz
Copy link
Collaborator

remorhaz commented Jul 3, 2020

Alternatives are:

  • To fail syntax on any literal. No surprises at all.
  • To consider any literal an existing node and thus match them always. In this case, $[?(null)] and $[?(false)] that are matching look quite quite confusing to me.

We've been talking about the debugging mission of false/true to temporary switch filters in a complicated query. But we can invent something more consistent instead of that: for example, we can use something like $[?+(@.key)] to match everything and $[?-(@.key)] to match nothing.

@glyn
Copy link
Collaborator Author

glyn commented Jul 4, 2020

@remorhaz I'd prefer to avoid completely new constructs.

@cleidiano
Copy link
Collaborator

cleidiano commented Jul 4, 2020

I've been take a look at predicates like $[?(1 != 2)] and there is a consensus for that, could it solve the debugging goal discussed? It's common to use this approach on write some complex SQL to validate syntax etc.

@glyn
Copy link
Collaborator Author

glyn commented Jul 6, 2020

@cleidiano Yes, that approach works if people think of using 1 != 2 instead of false.

@remorhaz
Copy link
Collaborator

remorhaz commented Jul 6, 2020

I'd prefer to avoid completely new constructs

Me too, but I think we should keep in mind such possibility if existing syntax doesn't allow solution good enough.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Proposal A Anything discussing the advance of the Proposal A for a formal specification of JSONPath
Projects
None yet
Development

No branches or pull requests

4 participants