From 52632ae065921fd9219d9a15f8a11e03f69e42c0 Mon Sep 17 00:00:00 2001 From: TennyZhuang Date: Tue, 12 Dec 2023 03:33:56 +0800 Subject: [PATCH] fix(types): fix Serial in Fields derive and add tests (#13926) Signed-off-by: TennyZhuang --- Cargo.lock | 48 +++++------------- src/common/fields-derive/Cargo.toml | 5 ++ .../fields-derive/src/gen/test_output.rs | 12 +++++ src/common/fields-derive/src/lib.rs | 49 +++++++++++++++++-- src/common/src/types/with_data_type.rs | 9 ++-- 5 files changed, 76 insertions(+), 47 deletions(-) create mode 100644 src/common/fields-derive/src/gen/test_output.rs diff --git a/Cargo.lock b/Cargo.lock index 90149113a272c..ee4fa96be12bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4097,7 +4097,7 @@ dependencies = [ "log", "murmur3", "once_cell", - "opendal 0.41.0", + "opendal", "ordered-float 3.9.1", "parquet", "prometheus", @@ -4172,6 +4172,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "indoc" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8" + [[package]] name = "inferno" version = "0.11.16" @@ -5529,40 +5535,6 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -[[package]] -name = "opendal" -version = "0.41.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e31b48f0af6de5b3b344c1acc1e06c4581dca3e13cd5ba05269927fc2abf953a" -dependencies = [ - "anyhow", - "async-compat", - "async-trait", - "backon", - "base64 0.21.4", - "bytes", - "chrono", - "flagset", - "futures", - "http 0.2.9", - "hyper", - "log", - "md-5", - "once_cell", - "parking_lot 0.12.1", - "percent-encoding", - "pin-project", - "prometheus", - "quick-xml 0.30.0", - "reqsign", - "reqwest", - "serde", - "serde_json", - "sha2", - "tokio", - "uuid", -] - [[package]] name = "opendal" version = "0.43.0" @@ -5585,6 +5557,7 @@ dependencies = [ "parking_lot 0.12.1", "percent-encoding", "pin-project", + "prometheus", "quick-xml 0.30.0", "reqsign", "reqwest", @@ -7311,6 +7284,9 @@ dependencies = [ name = "risingwave-fields-derive" version = "1.3.0-alpha" dependencies = [ + "expect-test", + "indoc", + "prettyplease 0.2.15", "proc-macro2", "quote", "syn 2.0.37", @@ -8321,7 +8297,7 @@ dependencies = [ "itertools 0.12.0", "madsim-aws-sdk-s3", "madsim-tokio", - "opendal 0.43.0", + "opendal", "prometheus", "risingwave_common", "rustls", diff --git a/src/common/fields-derive/Cargo.toml b/src/common/fields-derive/Cargo.toml index e5b78786244d6..5bd03de647183 100644 --- a/src/common/fields-derive/Cargo.toml +++ b/src/common/fields-derive/Cargo.toml @@ -14,3 +14,8 @@ proc-macro = true proc-macro2 = "1" quote = "1" syn = { version = "2", features = ["full", "extra-traits"] } + +[dev-dependencies] +expect-test = "1" +indoc = "2" +prettyplease = "0.2" diff --git a/src/common/fields-derive/src/gen/test_output.rs b/src/common/fields-derive/src/gen/test_output.rs new file mode 100644 index 0000000000000..d8e7274b4c2ee --- /dev/null +++ b/src/common/fields-derive/src/gen/test_output.rs @@ -0,0 +1,12 @@ +impl ::risingwave_common::types::Fields for Data { + fn fields() -> Vec<(&'static str, ::risingwave_common::types::DataType)> { + vec![ + ("v1", < i16 as ::risingwave_common::types::WithDataType > + ::default_data_type()), ("v2", < std::primitive::i32 as + ::risingwave_common::types::WithDataType > ::default_data_type()), ("v3", < + bool as ::risingwave_common::types::WithDataType > ::default_data_type()), + ("v4", < Serial as ::risingwave_common::types::WithDataType > + ::default_data_type()) + ] + } +} diff --git a/src/common/fields-derive/src/lib.rs b/src/common/fields-derive/src/lib.rs index 2f988f7e5bb2c..cae4f1c820c4c 100644 --- a/src/common/fields-derive/src/lib.rs +++ b/src/common/fields-derive/src/lib.rs @@ -18,15 +18,19 @@ use syn::{Data, DeriveInput, Field, Result}; #[proc_macro_derive(Fields)] pub fn fields(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { - let input: DeriveInput = syn::parse_macro_input! {tokens}; + inner(tokens.into()).into() +} - match gen(input) { - Ok(tokens) => tokens.into(), - Err(err) => err.to_compile_error().into(), +fn inner(tokens: TokenStream) -> TokenStream { + match gen(tokens) { + Ok(tokens) => tokens, + Err(err) => err.to_compile_error(), } } -fn gen(input: DeriveInput) -> Result { +fn gen(tokens: TokenStream) -> Result { + let input: DeriveInput = syn::parse2(tokens)?; + let DeriveInput { attrs: _attrs, vis: _vis, @@ -71,3 +75,38 @@ fn gen(input: DeriveInput) -> Result { } }) } + +#[cfg(test)] +mod tests { + use indoc::indoc; + use proc_macro2::TokenStream; + use syn::File; + + fn pretty_print(output: TokenStream) -> String { + let output: File = syn::parse2(output).unwrap(); + prettyplease::unparse(&output) + } + + #[test] + fn test_gen() { + let code = indoc! {r#" + #[derive(Fields)] + struct Data { + v1: i16, + v2: std::primitive::i32, + v3: bool, + v4: Serial, + } + "#}; + + let input: TokenStream = str::parse(code).unwrap(); + + let output = super::gen(input).unwrap(); + + let output = pretty_print(output); + + let expected = expect_test::expect_file!["gen/test_output.rs"]; + + expected.assert_eq(&output); + } +} diff --git a/src/common/src/types/with_data_type.rs b/src/common/src/types/with_data_type.rs index c91dae8aceb61..df271cff133d9 100644 --- a/src/common/src/types/with_data_type.rs +++ b/src/common/src/types/with_data_type.rs @@ -18,8 +18,8 @@ use std::sync::Arc; use bytes::Bytes; use super::{ - DataType, Date, Decimal, Fields, Int256, Interval, JsonbRef, JsonbVal, StructType, Time, - Timestamp, Timestamptz, F32, F64, + DataType, Date, Decimal, Fields, Int256, Interval, JsonbRef, JsonbVal, Serial, StructType, + Time, Timestamp, Timestamptz, F32, F64, }; /// A trait for all physical types that can be associated with a [`DataType`]. @@ -27,10 +27,6 @@ use super::{ /// This is also a helper for [`Fields`](derive@crate::types::Fields) derive macro. pub trait WithDataType { /// Returns the most obvious [`DataType`] for the rust type. - /// - /// There may be more than one [`DataType`] corresponding to the same rust type, - /// for example, [`Int64`](DataType::Int64) and [`Serial`](DataType::Serial) are - /// both expressed as i64. This method will return [`Int64`](DataType::Int64). fn default_data_type() -> DataType; } @@ -94,6 +90,7 @@ impl_with_data_type!(f64, DataType::Float64); impl_with_data_type!(F64, DataType::Float64); impl_with_data_type!(rust_decimal::Decimal, DataType::Decimal); impl_with_data_type!(Decimal, DataType::Decimal); +impl_with_data_type!(Serial, DataType::Serial); impl<'a> WithDataType for &'a str { fn default_data_type() -> DataType {