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

feat(expr): add jsonb table functions #9977

Merged
merged 13 commits into from
Jun 1, 2023
Merged

Conversation

wangrunji0408
Copy link
Contributor

@wangrunji0408 wangrunji0408 commented May 24, 2023

I hereby agree to the terms of the RisingWave Labs, Inc. Contributor License Agreement.

What's changed and what's your intention?

Based on #9949, this PR adds the following jsonb table functions:

jsonb_array_elements ( jsonb ) → setof jsonb
jsonb_array_elements_text ( jsonb ) → setof text
jsonb_each ( jsonb ) → setof record ( key text, value jsonb )
jsonb_each_text ( jsonb ) → setof record ( key text, value text )
jsonb_object_keys ( jsonb ) → setof text

Checklist For Contributors

  • I have written necessary rustdoc comments (will update docs after doc(expr): add docs for #[function] macro #10010)
  • I have added necessary unit tests and integration tests
  • I have added fuzzing tests or opened an issue to track them. (Optional, recommended for new SQL features Sqlsmith: Sql feature generation #7934).
  • I have demonstrated that backward compatibility is not broken by breaking changes and created issues to track deprecated features to be removed in the future. (Please refer to the issue)
  • All checks passed in ./risedev check (or alias, ./risedev c)

Checklist For Reviewers

  • I have requested macro/micro-benchmarks as this PR can affect performance substantially, and the results are shown.

Documentation

Click here for Documentation

Types of user-facing changes

Please keep the types that apply to your changes, and remove the others.

  • SQL commands, functions, and operators

Release note

Add jsonb table functions:

jsonb_array_elements ( jsonb ) → setof jsonb
jsonb_array_elements_text ( jsonb ) → setof text
jsonb_each ( jsonb ) → setof record ( key text, value jsonb )
jsonb_each_text ( jsonb ) → setof record ( key text, value text )
jsonb_object_keys ( jsonb ) → setof text

https://www.postgresql.org/docs/15/functions-json.html

@github-actions github-actions bot added type/feature user-facing-changes Contains changes that are visible to users labels May 24, 2023
@wangrunji0408 wangrunji0408 mentioned this pull request May 24, 2023
23 tasks
Base automatically changed from wrj/set-returning-function-macro to main May 25, 2023 11:49
Signed-off-by: Runji Wang <wangrunji0408@163.com>
Signed-off-by: Runji Wang <wangrunji0408@163.com>
Signed-off-by: Runji Wang <wangrunji0408@163.com>
Signed-off-by: Runji Wang <wangrunji0408@163.com>
Signed-off-by: Runji Wang <wangrunji0408@163.com>
Signed-off-by: Runji Wang <wangrunji0408@163.com>
Signed-off-by: Runji Wang <wangrunji0408@163.com>
Comment on lines 221 to 225
query T
select jsonb_each('{"a":"foo", "b":"bar"}'::jsonb);
----
(a,"""foo""")
(b,"""bar""")
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Found a problem in string formatting in struct. cc @xiangjinwu

    [Diff] (-expected|+actual)
    -   (a,"""foo""")
    -   (b,"""bar""")
    +   (a,"foo")
    +   (b,"bar")

The quote " is escaped to \" in array, but "" in record.

postgres=# select row(1, '"str"');
      row      
---------------
 (1,"""str""")
postgres=# select array['"str"'];
    array    
-------------
 {"\"str\""}

Is there any documents for this behavior? How should we handle it?

Copy link
Contributor

@xiangjinwu xiangjinwu May 26, 2023

Choose a reason for hiding this comment

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

Yes it is buggy right now: #4769

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes it is buggy right now: #4967

Seems not related. Wrong issue number?

Copy link
Contributor

Choose a reason for hiding this comment

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

My bad. Updated to #4769

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! Then I'd like to change the test result to fit the current format and leave this issue for the future.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, that works. Alternatively, we can write the tests without relying on the display of struct:

select (st).key, (st).value from (select jsonb_each('{"a":"foo", "b":"bar"}'::jsonb)) as t(st);
----
a "foo"
b "bar"

@wangrunji0408 wangrunji0408 marked this pull request as ready for review May 26, 2023 03:55
@codecov
Copy link

codecov bot commented May 26, 2023

Codecov Report

Merging #9977 (46860fb) into main (71729ac) will decrease coverage by 0.03%.
The diff coverage is 52.88%.

@@            Coverage Diff             @@
##             main    #9977      +/-   ##
==========================================
- Coverage   70.93%   70.91%   -0.03%     
==========================================
  Files        1233     1234       +1     
  Lines      210884   210990     +106     
==========================================
+ Hits       149600   149625      +25     
- Misses      61284    61365      +81     
Flag Coverage Δ
rust 70.91% <52.88%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/common/src/array/arrow.rs 65.84% <0.00%> (-0.55%) ⬇️
src/common/src/array/data_chunk.rs 87.83% <0.00%> (+0.12%) ⬆️
src/common/src/types/jsonb.rs 43.22% <0.00%> (-5.82%) ⬇️
src/common/src/types/mod.rs 63.23% <0.00%> (-0.95%) ⬇️
src/common/src/types/struct_type.rs 62.00% <0.00%> (-38.00%) ⬇️
src/expr/src/table_function/mod.rs 72.72% <ø> (ø)
src/expr/src/table_function/unnest.rs 57.14% <0.00%> (ø)
src/expr/src/table_function/jsonb.rs 22.72% <22.72%> (ø)
src/expr/src/table_function/generate_series.rs 92.00% <50.00%> (-0.08%) ⬇️
src/frontend/src/expr/table_function.rs 40.96% <71.42%> (-8.10%) ⬇️
... and 8 more

... and 3 files with indirect coverage changes

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

Copy link
Member

@BugenZhao BugenZhao left a comment

Choose a reason for hiding this comment

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

Generally LGTM!

Comment on lines +632 to +635
/// To make sure there is `as_scalar_ref` for all scalar ref types.
pub trait SelfAsScalarRef {
fn as_scalar_ref(&self) -> Self;
}
Copy link
Member

Choose a reason for hiding this comment

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

Why we need this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The purpose is to allow both owned type and reference type as function return value. (e.g. -> &str and -> Box<str>). So we want both types have a method .as_scalar_ref() -> &str so that we can call it to convert owned type into reference and keep reference type unchanged in the macro. Currently this method exists in the Scalar trait. At first I added this method to the ScalarRef trait, but it leads to conflicts for those types that share both traits (e.g. primitive types: i32, i64...). Therefore I created this trait to add as_scalar_ref for types which impl ScalarRef but not impl Scalar. Maybe a better solution is to extract an AsScalarRef trait. But it's too hard for me to do type exercise. 🤪

Copy link
Member

Choose a reason for hiding this comment

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

Cool

Comment on lines +78 to +79
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "record" {
Copy link
Member

Choose a reason for hiding this comment

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

What format is the str in? Is it SQL representation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is almost auto-generated by Copilot from the above Display code. 😄

@wangrunji0408 wangrunji0408 added this pull request to the merge queue Jun 1, 2023
Merged via the queue into main with commit 1ac7732 Jun 1, 2023
@wangrunji0408 wangrunji0408 deleted the wrj/json-table-functions branch June 1, 2023 12:02
kwannoel pushed a commit that referenced this pull request Jun 6, 2023
Signed-off-by: Runji Wang <wangrunji0408@163.com>
Co-authored-by: xxchan <xxchan22f@gmail.com>
@hengm3467 hengm3467 added the 📖✓ Covered or will be covered in the user docs. label Jun 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type/feature user-facing-changes Contains changes that are visible to users 📖✓ Covered or will be covered in the user docs.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants