diesel: Add support for currently unsupported JSON/JSONB operators
Diesel currently supports the postgres json and jsonb types. We do not provide built-in support for various operators available for these types. This is a tracking issue for adding support for these operators.
The general strategy for adding support for new operators is as following:
- Define the operator via
infix_operator!(). The contains operator would be defined as following:infix_operator!(KeyExists, " ? ", backend: Pg);These operators can be defined here. If there is already an existing definition, this step could be skipped. - Define a new helper type here. Helper types are a tool for diesel users to simplify type definitions. Again if there is already a matching type definition this could be skipped.
- Add a new
ExpressionMethodsextension trait for the corresponding types. This only needs to happen once forjsonband once forjsonb+json. See thePgRangeExpressionMethodstrait here as example. - Add a new method to the corresponding
ExpressionMethodstrait. See here for an example for a different operator/type. This definition should:- Use the previously defined helper type
- Contain a documentation with an example
- Check if compile test output is up to date by running
TRYBUILD=overwrite cargo testinside ofdiesel_compile_tests. (This is required if you’ve added a new operator based oninfix_operator! - Submit a PR with the change
Operator list:
-
json/jsonb -> integer(indexing by index, returnsjson/jsonb) ** -
json/jsonb -> text(indexing by key name, returnsjson/jsonb) ** -
json/jsonb ->> integer(indexing by index, returns field astext) ** -
json/jsonb ->> text(indexing by key name, returns field astext) ** -
json/jsonb #> text[](indexing by path, returns field asjson/jsonb) * -
json/jsonb #>> text[](indexing by path, returns field astext) * -
jsonb @> jsonb(checks if the second value is contained by the first value, returns aboolean) * -
jsonb <@ jsonb(checks if the first value is contained by the second value, returns aboolean) * -
jsonb ? text(checks if a string exists as top level key in the given json, returns aboolean) * -
jsonb ?| text[](checks if any of the strings exists as top level key in the given json, returns aboolean) * -
jsonb ?& text[](checks if all of the strings exist as top level key in the given json, returns aboolean) * -
jsonb || jsonb(concats two json values, returnsjsonb) * -
jsonb - text(remove the key given as string from the json, returnsjsonb) ** -
jsonb - text[](removes all keys given as string from the json, returnsjsonb) ** -
jsonb - integer(removes the field with the given index from the json, returnsjsonb) ** -
jsonb #- text[](removes the given path from the json, returnsjsonb) * -
jsonb @? jsonpath(Does JSON path return any item for the specified JSON value?, returns aboolean) *** -
jsonb @@ jsonpath (Returns the result of a JSON path predicate check for the specified JSON value. Only the first item of the result is taken into account. If the result is not Boolean, then NULL is returned., returns aboolean`) ***
Items marked with one * can follow the instructions directly, items marked with ** require additional work to unify the different input types behind a common operator/function call (See here for a general example on how to abstract over expressions of different types), items marked with *** likely require additional design work.
Please add a comment to this issue if you plan to work on a specific operator.
If there is anything unclear about how to add a support for a specific operator just ask and we will try to answer your questions.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Comments: 26 (26 by maintainers)
@mrbuzz @gamesbrainiac @czotomo Sorry for being away so long. I’ve pushed #3092 which contains all of your work + some fixes to the operators. Additionally it adds the missing operators. Feel free to leave comments about potential improvements on that PR. Thanks again for your work ❤️
@zaneduffield Yes those would need marker traits for json/jsonb. So basically this thing here: https://github.com/diesel-rs/diesel/blob/b479e8352f6712bbc2f6bdcd734c8e32a934e6b9/diesel/src/pg/expression/expression_methods.rs#L1554-L1564
but so that the helper trait (
JsonbOrNullableJsonb) is implemented forJsonandNullable<Json>as well.I’ll try these operators next.
json/jsonb #> text[]json/jsonb #>> text[]Edit: they aren’t marked as
**like the others above them which also operate onjson/jsonb. Won’t they also require a marker trait forjson/jsonb?@mrbuzz I’m happy to answer any question that comes up. Just ask .
I’d like to take these three operators as my next task:
jsonb - textjsonb - text[]jsonb - integerI might need some guidance as I’m relatively new to Rust, I’ll start by looking at the example codeHi, I’d like to try adding support for these two operators.
jsonb @> jsonbjsonb <@ jsonbHey, I’d like to get my hands dirty with these two operators if that’s ok…
jsonb ?| text[]jsonb ?& text[]Alright, let’s continue with the trivial ones. I’m going to implement
jsonb ? textEdit: PR https://github.com/diesel-rs/diesel/pull/3036
Jsonb concat PR: https://github.com/diesel-rs/diesel/pull/3035
@czotomo Any new feature should target the master branch.
Believe it or not, I was considering suggesting this some time last week! I will gladly take this task up for the
one asteriskoperators and maybe this work will evolve into discussion on other operators.Edit: on the second thought, this probably shouldn’t all be done by one person. First operator I will work on:
jsonb || jsonb@weiznich what version do we add this in, current or master?