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(types): add Fields trait and derive macro #13862

Merged
merged 9 commits into from
Dec 11, 2023
Merged

Conversation

TennyZhuang
Copy link
Contributor

@TennyZhuang TennyZhuang commented Dec 7, 2023

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

What's changed and what's your intention?

Resolve #13851

#[derive(Fields)]
struct Data {
v1: i16,
v2: std::primitive::i32,
v3: bool,
v4: f32,
v5: F32,
v6: Option<f64>,
v7: Vec<u8>,
v8: std::vec::Vec<i16>,
v9: Option<Vec<i64>>,
v10: std::option::Option<Vec<Option<f32>>>,
v11: Box<Timestamp>,
v14: Sub,
}
assert_eq!(
Data::fields(),
vec![
("v1", DataType::Int16),
("v2", DataType::Int32),
("v3", DataType::Boolean),
("v4", DataType::Float32),
("v5", DataType::Float32),
("v6", DataType::Float64),
("v7", DataType::Bytea),
("v8", DataType::List(Box::new(DataType::Int16))),
("v9", DataType::List(Box::new(DataType::Int64))),
("v10", DataType::List(Box::new(DataType::Float32))),
("v11", DataType::Timestamp),
(
"v14",
DataType::Struct(StructType::new(vec![
("v12", DataType::Timestamptz),
("v13", DataType::Bytea)
]))
)
]
)

Checklist

  • I have written necessary rustdoc comments
  • I have added necessary unit tests and integration tests
  • I have added test labels as necessary. See details.
  • I have added fuzzing tests or opened an issue to track them. (Optional, recommended for new SQL features Sqlsmith: Sql feature generation #7934).
  • My PR contains breaking changes. (If it deprecates some features, please create a tracking issue to remove them in the future).
  • All checks passed in ./risedev check (or alias, ./risedev c)
  • My PR changes performance-critical code. (Please run macro/micro-benchmarks and show the results.)
  • My PR contains critical fixes that are necessary to be merged into the latest release. (Please check out the details)

Documentation

  • My PR needs documentation updates. (Please use the Release note section below to summarize the impact on users)

Release note

If this PR includes changes that directly affect users or other significant modifications relevant to the community, kindly draft a release note to provide a concise summary of these changes. Please prioritize highlighting the impact these changes will have on users.

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

license-eye has totally checked 4559 files.

Valid Invalid Ignored Fixed
2006 1 2552 0
Click to see the invalid file list
  • src/common/src/types/with_data_type.rs

src/common/src/types/with_data_type.rs Show resolved Hide resolved
TennyZhuang and others added 3 commits December 8, 2023 01:10
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Signed-off-by: TennyZhuang <[email protected]>
Signed-off-by: TennyZhuang <[email protected]>
Comment on lines 17 to 20
use syn::Data;
use syn::DeriveInput;
use syn::Field;
use syn::Result;
Copy link
Contributor Author

@TennyZhuang TennyZhuang Dec 7, 2023

Choose a reason for hiding this comment

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

I'm unsure why cargo fmt can't help me to merge them here, but I don't like to fix it manually. I guess there are many similar fmt issues in the whole codebase. Let's investigate why cargo fmt doesn't work and fix them all later.

Copy link
Member

Choose a reason for hiding this comment

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

cargo fmt works on my machine 🤡

Copy link
Member

Choose a reason for hiding this comment

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

Maybe you are not in the root dir?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

brew uninstall rustfmt

Copy link
Member

@xxchan xxchan left a comment

Choose a reason for hiding this comment

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

Others LGTM

@@ -7,6 +7,7 @@ members = [
"src/cmd_all",
"src/common",
"src/common/common_service",
"src/common/fields-derive",
Copy link
Member

Choose a reason for hiding this comment

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

prefer underscore, to be consistent with others

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’s already inconsistent now, although most of them are underscores, there are still several crates using dash.

}

assert_eq!(
Data::fields(),
Copy link
Member

Choose a reason for hiding this comment

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

Just a hint. You can use expect_test::Expect::assert_debug_eq so you don’t have to manually write the RHS 🤪

Timestamp, Timestamptz, F32, F64,
};

pub trait WithDataType {
Copy link
Member

Choose a reason for hiding this comment

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

This is a little hard to understand why it’s needed. Add some comments?

Copy link
Member

Choose a reason for hiding this comment

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

Do we have something similar before? Or can we use this trait to simplify some existing manual matches?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can’t find similar thing that can be used, but I guess we may use it in somewhere. I’ll review it later.

Currently it’s just a macro helper.

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.

Rest LGTM

impl_with_data_type!(Timestamp, DataType::Timestamp);
impl_with_data_type!(Timestamptz, DataType::Timestamptz);
impl_with_data_type!(Interval, DataType::Interval);
impl_with_data_type!(Vec<u8>, DataType::Bytea);
Copy link
Member

Choose a reason for hiding this comment

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

Is this okay?

Suggested change
impl_with_data_type!(Vec<u8>, DataType::Bytea);
impl_with_data_type!([u8], DataType::Bytea);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We may need both lines?

Timestamp, Timestamptz, F32, F64,
};

pub trait WithDataType {
Copy link
Member

Choose a reason for hiding this comment

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

Do we have something similar before? Or can we use this trait to simplify some existing manual matches?

/// A struct can implements `Fields` when if can be represented as a relational Row.
pub trait Fields {
/// When the struct being converted to an [`Row`](crate::row::Row) or a [`DataChunk`](crate::array::DataChunk), it schema must be consistent with the `fields` call.
fn fields() -> Vec<(&'static str, DataType)>;
Copy link
Member

Choose a reason for hiding this comment

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

Should we return Cow here?

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for making the return value static. Maybe use lazy-static?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, but it increases the complexity. We can do it when it’s really used in critical path.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can use an attribute static to control whether make it lazy static.

Please note that static doesn't mean always more efficient.
If user only called once, and need the ownership, then we need to allocate once, return a static reference, and then allocate (clone) again.

And we can modify the signature to this:

fn fields() -> impl ToOwned<Owned = Vec<(&'static str, DataType)>> + AsRef<[(&'static str, DataType)]>;

Copy link
Contributor

@wangrunji0408 wangrunji0408 left a comment

Choose a reason for hiding this comment

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

Rest LGTM!

ty,
..
} = field_rs;
let name = name.map_or("".to_string(), |name| name.to_string());
Copy link
Contributor

Choose a reason for hiding this comment

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

Why a struct field may have no name? 🤔

Copy link
Member

Choose a reason for hiding this comment

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

tuple

Copy link
Contributor

Choose a reason for hiding this comment

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

In PostgreSQL the names would implicitly become f1, f2, ...

test=# select row(9, 18);
  row   
--------
 (9,18)
(1 row)

test=# select (row(9, 18)).f1;
 f1 
----
  9
(1 row)

test=# select to_jsonb(row(9, 18));
      to_jsonb       
---------------------
 {"f1": 9, "f2": 18}
(1 row)

But in RisingWave this has not been supported consistently yet. Some places are empty while some places have these implicit names. Have not thought about the impact on backward compatibility if it was fixed to be pg-compatible.

No opinion on what the behavior of this place should be.

/// A struct can implements `Fields` when if can be represented as a relational Row.
pub trait Fields {
/// When the struct being converted to an [`Row`](crate::row::Row) or a [`DataChunk`](crate::array::DataChunk), it schema must be consistent with the `fields` call.
fn fields() -> Vec<(&'static str, DataType)>;
Copy link
Contributor

Choose a reason for hiding this comment

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

+1 for making the return value static. Maybe use lazy-static?

Signed-off-by: TennyZhuang <[email protected]>
Signed-off-by: TennyZhuang <[email protected]>
Signed-off-by: TennyZhuang <[email protected]>
Signed-off-by: TennyZhuang <[email protected]>
Signed-off-by: TennyZhuang <[email protected]>
@TennyZhuang TennyZhuang added this pull request to the merge queue Dec 11, 2023
Copy link

codecov bot commented Dec 11, 2023

Codecov Report

Attention: 27 lines in your changes are missing coverage. Please review.

Comparison is base (ddfa85b) 68.30% compared to head (ae981e4) 68.25%.
Report is 29 commits behind head on main.

Files Patch % Lines
src/common/src/types/with_data_type.rs 41.66% 21 Missing ⚠️
src/common/fields-derive/src/lib.rs 87.50% 6 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #13862      +/-   ##
==========================================
- Coverage   68.30%   68.25%   -0.06%     
==========================================
  Files        1528     1531       +3     
  Lines      262603   262735     +132     
==========================================
- Hits       179375   179320      -55     
- Misses      83228    83415     +187     
Flag Coverage Δ
rust 68.25% <79.54%> (-0.06%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Merged via the queue into main with commit 92f3b58 Dec 11, 2023
7 of 8 checks passed
@TennyZhuang TennyZhuang deleted the feat/with-data-type branch December 11, 2023 10:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a new derive macro #[derive(Fields)]
5 participants