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

add option to skip missing map keys #36

Closed
wants to merge 1 commit into from
Closed

Conversation

schmichael
Copy link
Member

@schmichael schmichael commented Apr 17, 2023

Fixes #35 (option 2)

This adds a SkipMissingMapKey option which treats comparisons against missing maps keys as unequal.

For example with this option the expressions Map["x"] == "y" and Map["x"] != "something else" will both match when Map["x"] = "y". If Map["x"] is unset then the != operation will match since a missing key does not match any values.

I'll try to get reviews from someone on hashicorp/nomad, hashicorp/consul, and hashicorp/boundary to make sure we're all aligned.

As noted in the parent issue my preference is for hardcoding this change and dropping the Option. This PR implements the Option path to demonstrate the most complicated option. Hardcoding it means removing code and collapsing tests.

Fixes #35 (option 2)

This adds a SkipMissingMapKey option which treats comparisons against
missing maps keys as unequal.

For example with this option the expressions `Map["x"] == "y"` and
`Map["x"] != "something else"` will both match when `Map["x"] =
"y"`. If `Map["x"]` is unset then the `!=` operation will match since
a missing key does not match any values.
@schmichael schmichael requested review from a team, shore and alvin-huang and removed request for a team April 17, 2023 23:19
// For comparison results with missing keys: missing means not equal.
if evaluateSkipMissing(ptr, datum) {
switch expression.Operator {
case grammar.MatchEqual:
Copy link
Member

Choose a reason for hiding this comment

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

I think we should probably handle the other operators too:

  • MatchIn - false
  • MatchNotIn - true
  • MatchEmpty - true (sort of like how len(slice) == 0 works for a nil slice and an allocated slice that is currently empty)
  • MatchNotEmpty - false
  • MatchMatches - false
  • MatchNotMatches - true

I would also recommend adding a func to grammar/ast.go (possibly called NotPresentMatchDisposition) to do the big switch statement over all operators and return the bool, error that you are returning in these cases. That way the big switch is colocated with other functions with similar needs and next to the const definitions so that when we add more operators in the future we don't accidentally miss adding them to this block of code.

Copy link
Member Author

Choose a reason for hiding this comment

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

Any opinion on using an Option vs hardcoding the behavior? I think all HashiCorp products should have matching behavior, so I have a preference for hardcoding (or dropping this entirely and documenting the "x" in m approach if we can't get consensus).

@jefferai
Copy link
Member

I don't love the idea of hardcoding this change; the library coalesces to strings and generally treats unset as an empty string so the current behavior is IMHO correct.

I'd be more into the idea of a way to check existence of a key so that you can be explicit -- if X is not set, or X is set but != Y, then...

@jefferai
Copy link
Member

I think I may have gotten turned around a bit by the description. I thought given the option name that you were suggesting that the hardcoded behavior should be that it does not treat missing keys as unequal. I think you're suggesting that the behavior should be to treat missing keys as unequal instead of erroring...I'm into that. (Naming is hard, but something like "WithSkipErrorOnMissingKeys" might be a bit more descriptive.)

I took a look at the linked issue and it says that "The major downside of [the hardcoded] approach is bexpr users" and stops there. Don't leave us hanging :-)

Also I think that the comparisons to WithUnknownValue are misleading. Although in some cases you could use them interchangeably one is used to set a default value, which is different from how comparisons are treated, and I think the commenting on the new option that talks about how the two differ creates some confusion instead of resolves it. But if this becomes hardcoded then it won't be an issue anyways. You'd just have to ensure that using the unknown value doesn't stop working for those that want a default.

schmichael added a commit that referenced this pull request Apr 21, 2023
Implements MatchOperator.NotPresentDisposition to determine an
operator's behavior when a map key in the selector is not found.

Fixes #35
Replaces #36
@schmichael
Copy link
Member Author

I went for a clean start to implement the suggestions: #38

@schmichael schmichael closed this Apr 21, 2023
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.

Comparisons against missing map keys return an error unless preceded by an "in" check
3 participants