-
-
Notifications
You must be signed in to change notification settings - Fork 338
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
RPC Records list filtering #3700
Conversation
Also, add some type information for documentation
I've only read the PR description, but I wanted to chime in with some thoughts... This looks nice! The JSON is basically an AST for a limited set of SQL expressions. Very cool! The way you're using the I have one minor nitpick that very well may not be worth addressing. I'm just mentioning this as food for thought, on the off chance that it might tip your mental calculus into making an adjustment. Instead of: {
"type": "lesser",
"args": [
{
"type": "attnum",
"value": 1
},
{
"type": "literal",
"value": 3
}
]
} I'd rather see something like: {
"type": "lesser",
"lhs": {
"type": "attnum",
"value": 1
},
"rhs": {
"type": "literal",
"value": 3
}
} Why? Because a "less-than" expression always requires exactly two arguments. Structuring the JSON fields statically as To be clear: I don't mean to suggest that we'd have Here's an example of a comparison that we might want to add in the future which would be structured differently: {
"type": "in",
"value": {
"type": "attnum",
"value": 1
},
"values": [
{
"type": "literal",
"value": 3
},
{
"type": "literal",
"value": 4
}
]
} Overall this is minor though. Not worth slowing things down unless you happen to see other good reasons for making such a change too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mathemancer The syntax looks great to me! I do not see any concerns.
Adding some thoughts towards @seancolsen's comment:
I still prefer the syntax in the PR description because it follows a uniform structure (with each node containing a type
and args/value
) which is much easier to parse and work with.
In this example:
{
"type": "lesser",
"lhs": {
"type": "attnum",
"value": 1
},
"rhs": {
"type": "literal",
"value": 3
}
}
I'd prefer finding the lhs
and rhs
using the type
key instead of having them as additional keys.
In the scenario on the PR description, one is a column and the other is a literal, so we can deduct that easily using attnum
and literal
, and it works great.
However there are scenarios where it might be required, say both arguments are columns, I'd prefer something like this instead:
{
"type": "lesser",
"args": [
{
"type": "lhs",
"value": {
"operand_type": "attnum",
"operand": 4
}
},
{
"type": "rhs",
"value": {
"operand_type": "attnum",
"operand": 3
}
}
]
}
This allows maximum flexibility w.r.t structure and even for us to nest the expressions if we ever want to, eg., comparing the output of one filter with another.
@seancolsen @pavish A couple of quick notes regarding your well-received commentary.
Finally, I should point out that the form, and the underlying parser, is flexible enough to allow for writing a whole bunch of arbitrary SQL. It doesn't actually know it's writing a "filter". I intend to use it for more general function calls in the future. As a quick example, the
to the {
"type": "or",
"args": [
{
"type": "lesser",
"args": [
{
"type": "json_array_length",
"args": [
{"type": "attnum", "value": 2}
]
},
{"type": "literal", "value": 3}
]
},
{
"type": "equal",
"args": [
{
"type": "json_array_length",
"args": [
{"type": "attnum", "value": 2}
]
},
{"type": "literal", "value": 3}
]
}
]
} would produce the SQL WHERE (jsonb_array_length(col1::jsonb) < '3') OR (jsonb_array_length(col1::jsonb) = '3') This filter will give the exact same output as You may notice that many of our current filter functions could actually just be compositions or argument-swaps of other functions. In the long run, I think we should lean on that feature. |
use composition rather than prewrapped functions add more parentheses to avoid ambiguity avoid ILIKE, stopping bugs due to inadvertent wildcards
@seancolsen Please take a look at the decomposed functions when/if you have time or interest. I ended up keeping the I also went ahead and made separate versions of Finally, I realized once I got into the docs that there's a If you find that you don't want to use any of the functions (e.g., the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wonderful!
db/sql/00_msar.sql
Outdated
('json_array_length', 'jsonb_array_length((%s)::jsonb)'), | ||
('json_array_contains', '(%s) @> (%s)'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know if we should be explicitly typecasting to jsonb
here, as this would allow columns storing a json blob in a text column to be typecasted and return a result. However, if that is the intended behavior, it would be good to add typecasting to json_array_contains
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main goal was to allow this to be used on both json
and jsonb
. But, your point stands. I'll add typecasting to json_array_contains
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good now @mathemancer, Thanks!
Related to #3690
Adds filtering to the
records.list
RPC function.Technical details
The filters implemented are derived from the current Front End code.
The
Filter
spec is documented, but some changes warrant extra attention.First,
and
andor
are now just filters like the rest. Each takes two operands. So, to get the SQLyou submit
In reality, this produces the SQL:
The reason for this change is that it lets the recursive function that parses the filter spec be memoryless. It's also much more flexible moving forward.
Another change is that the filter type is no longer a key, but is instead a value corresponding to the key
"type"
in each filter. This is much more typical, and (again) allows the parser to be memoryless.Finally, and less importantly, we've changed
column_id
toattnum
to conform with the other RPC functions.Checklist
Update index.md
).develop
branch of the repositoryvisible errors.
Developer Certificate of Origin
Developer Certificate of Origin