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

[pkg/telemetryquerylanguage] Add ordering inequalities to comparisons #12491

Closed
kentquirk opened this issue Jul 15, 2022 · 8 comments · Fixed by #13320
Closed

[pkg/telemetryquerylanguage] Add ordering inequalities to comparisons #12491

kentquirk opened this issue Jul 15, 2022 · 8 comments · Fixed by #13320
Assignees

Comments

@kentquirk
Copy link
Member

kentquirk commented Jul 15, 2022

Is your feature request related to a problem? Please describe.
Currently, TQL supports strict equality ('==') and inequality ('!='). It would be useful to support ordering comparisons as well -- specifically, ('<'), ('>'), ('<='), and ('>=').

Adding them to the grammar is pretty simple, but it's slightly trickier to extend the expression evaluators.

Describe the solution you'd like
We need to define the semantics appropriately for comparing two values that may potentially be different base types. The semantics should be symmetric (a < b should give the identical result to b > a). Also, there really can't be the concept of an error -- the condition just has to return a boolean result.

We propose that comparisons between different types always evaluate to false. Anything else can be fixed with type coercion functions.

The details:

base type bool int float string Bytes nil
bool normal, T>F false false false false false
int false normal int coerced to float false false false
float false int coerced to float normal false false false
string false false false normal (compared as utf8 strings) false false
Bytes false false false false byte-for-byte comparison false
nil false false false false false true for equality only

Describe alternatives you've considered
Alternatives are:

  • Don't do it at all -- but people need this.
  • Don't extend the grammar, provide functions that can compare values. This would look something like Compare(http.return, 400, ">") == true. I think this is unnecessarily wordy.

Within this proposal, we could try harder to coerce things into compatible types. For example, when comparing a string to a numeric value, we could try to parse the string as a numeric value. This would allow, say, comparing an http return of "500" to 500. Personally, I'd rather fix this with explicit type conversion functions like int("500"). Similarly, bools could be coerced to numeric values (0 and 1, or 0 and -1) with int() or float() functions.

@kentquirk
Copy link
Member Author

@TylerHelmuth ^ thoughts?

@TylerHelmuth
Copy link
Member

We definitely need this. I think your idea about returning false is correct for mismatching types. Maybe we could write out a log when that happens?

Personally, I'd rather fix this with explicit type conversion functions

Agreed, that's what Factory functions are good for.

Can you add the "nil" and "Bytes" literals to your table?

@TylerHelmuth
Copy link
Member

TylerHelmuth commented Jul 15, 2022

Also, I think "Missing" is the same as the literal "nil" case. If a Getter returns nil it should be treated the same as nil. I don't think we should assume 0, 0.0, or "" for instance, I think comparison with nil would be false always.

@kentquirk
Copy link
Member Author

@TylerHelmuth updated. If this seems OK, feel free to assign it to me. I should be able to do it early next week.

@TylerHelmuth
Copy link
Member

@kentquirk assigned.

For int to float and float to int, we may not be able to do that coercion. Sometimes comparison is done between 2 Getters and we don't actually know the type returned by the Getter until data is processing. We might want to enforce the use of Factories instead of doing type checking and conversion during the hot path. Interested to see what you come up with.

@github-actions
Copy link
Contributor

Pinging code owners: @TylerHelmuth @kentquirk

@kentquirk
Copy link
Member Author

kentquirk commented Aug 12, 2022

@TylerHelmuth I have been implementing this, and I've made a few decisions in the details

  • I've dropped the idea that all comparisons return false for noncomparable types. I implemented it so that != (Not Equals) has the inverted sense -- 3 != "hello" should be true (but 3 < "hello" and 3 > "hello" are both false). I have implemented this.
  • A nil []byte (Bytes) object is treated like an empty Bytes object -- zero length.
  • Pointers to nil base types are treated like a typeless nil and compare in the same way. Thus an implementation that returns a nil pointer to (say) float for a float will have it treated like nil, not like a zero value.

Please see the draft PR in progress linked below.

@TylerHelmuth
Copy link
Member

I've dropped the idea that all comparisons return false for noncomparable types. I implemented it so that != (Not Equals) has the inverted sense -- 3 != "hello" should be true (but 3 < "hello" and 3 > "hello" are both false). I have implemented this.

I think this makes sense.

When the PR is ready let me know and I'll take an in-depth look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants