-
Notifications
You must be signed in to change notification settings - Fork 598
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
feat(expr): add json path functions #13568
Conversation
|
||
#[function( | ||
"jsonb_path_exists(jsonb, varchar) -> boolean", | ||
prebuild = "JsonPath::new($1).map_err(parse_error)?" |
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.
Great!
I have fixed regression tests as much as possible. # wrong silent handling
select jsonb_path_query('[1,"2",3]', '+$', '{}', true);
jsonb_path_query
------------------
- 1
-(1 row)
+(0 rows)
# wrong silent handling
select jsonb '["1",2,0,3]' @? '-$[*]';
?column?
----------
- t
+
(1 row)
# double precision problem
select jsonb_path_query('{"a": 2.5}', '-($.a * $.a).floor() % 4.3');
- jsonb_path_query
-------------------
- -1.7
+ jsonb_path_query
+---------------------
+ -1.7000000000000002
(1 row)
# I think both results are valid according to the specification. It depends on implementation.
select jsonb_path_query('[[null, 1, "abc", "abcabc"]]', 'lax $ ? (@[*] starts with "abc")');
- jsonb_path_query
-----------------------------
- [null, 1, "abc", "abcabc"]
-(1 row)
+ jsonb_path_query
+------------------
+(0 rows)
# wrong regexp matching
select jsonb_path_query('[null, 1, "a\b", "a\\b", "^a\\b$"]', 'lax $[*] ? (@ like_regex "a\\b" flag "")');
jsonb_path_query
------------------
+ "^a\\b$"
+ "a\\b"
"a\b"
-(1 row)
+(3 rows)
# wrong regexp matching
select jsonb_path_query('[null, 1, "a\b", "a\\b", "^a\\b$"]', 'lax $[*] ? (@ like_regex "^a\\b$" flag "")');
jsonb_path_query
------------------
- "a\b"
-(1 row)
+(0 rows)
# wrong silent handling
SELECT jsonb_path_query_first('[{"a": 1}, {"a": 2}, {}]', 'strict $[*].a', '{}', true);
jsonb_path_query_first
------------------------
- 1
+
(1 row) As these are mostly corner cases, I think we can move on and leave them to be fixed later. |
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]>
f032ed1
to
a9f393b
Compare
Codecov ReportAttention:
Additional details and impacted files@@ Coverage Diff @@
## main #13568 +/- ##
==========================================
- Coverage 68.19% 68.15% -0.04%
==========================================
Files 1524 1525 +1
Lines 262232 262454 +222
==========================================
+ Hits 178829 178879 +50
- Misses 83403 83575 +172
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
Signed-off-by: Runji Wang <[email protected]>
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.
Cool!
let matched = path | ||
.query::<ValueRef<'_>>(target.into()) | ||
.map_err(eval_error)?; | ||
Ok(matched.into_iter().map(|json| json.into_owned().into())) |
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.
Is it possible to return an iterator for query
?
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.
It is hard in stable Rust as all query functions need to be written as generator.
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.
What about those 3rd party libraries available under stable
🥵? Like https://github.com/Wolvereness/remit/
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.
Interesting! Will have a try later.
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 PR and test suite LGTM. Although not all corner cases were covered, I think it’s still good enough to merge.
Signed-off-by: Runji Wang <[email protected]>
Signed-off-by: Runji Wang <[email protected]> Co-authored-by: Runji Wang <[email protected]>
I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.
What's changed and what's your intention?
resolve #11372
This PR implements all jsonpath operators and functions:
This PR doesn't introduce the
jsonpath
data type. However, this does not affect the normal use of the above functions. Alljsonpath
arguments in the signature are actually varchar. If we havejsonpath
type, there will be only one parsing during'literal' :: jsonpath
. Currently, parsing happens every time theeval
is called (not every time evaluating a row). I think it's not a big problem.The jsonpath parsing and query logic is separated into an independent crate: sql-json-path. Please also review it if you are interested. (After investigation, I found no existing crate that can meet our requirements. Most of them follow the IETF standard and only support serde-json.)
Almost all jsonpath syntax is supported, except
.datetime()
and some escaped string literal. I use Postgres regression testjsonb_jsonpath.sql
to ensure correctness. Please check this file to see what is (not) supported yet. Detailed explanation: #13568 (comment)This PR is based on #13545, which is needed to run regression test. After it merged, I will rebase this PR onto main.
References:
Checklist
./risedev check
(or alias,./risedev c
)Documentation
Support jsonpath operators and functions:
See postgres docs and search "jsonpath" for more details. Note that we don't support
jsonpath
data type for now. Alljsonpath
arguments in the signature are actually varchar.For the syntax of
jsonpath
, see 9.16.2. The SQL/JSON Path Language. Almost all features in the docs have been supported, except that:.datetime()
and. datetime(template)
method is not supported.silent
argument may be incorrect.