From 010eb5d3f90678c12b3853148bed8c24083da306 Mon Sep 17 00:00:00 2001 From: "UnHold (Alex)" Date: Sat, 10 Feb 2024 13:16:25 +0100 Subject: [PATCH 1/3] Excluded option values from query if they are `None` --- influxdb2-derive/src/expand_writable.rs | 47 ++++++++++++------------- src/writable.rs | 2 +- 2 files changed, 23 insertions(+), 26 deletions(-) diff --git a/influxdb2-derive/src/expand_writable.rs b/influxdb2-derive/src/expand_writable.rs index e037fa9..31d01b4 100644 --- a/influxdb2-derive/src/expand_writable.rs +++ b/influxdb2-derive/src/expand_writable.rs @@ -56,15 +56,20 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { let ident_str = ident.to_string(); let kind = f.kind.clone(); Some(quote! { - w.write_all(format!("{}", #ident_str).as_bytes())?; - w.write_all(b"=")?; - w.write_all(<#kind as #writable_krate::KeyWritable>::encode_key(&self.#ident).into_bytes().as_slice())?; + if <#kind as #writable_krate::KeyWritable>::encode_key(&self.#ident) != "None"{ + if first_tag_write == false { + w.write_all(b",")?; + } + w.write_all(format!("{}", #ident_str).as_bytes())?; + w.write_all(b"=")?; + w.write_all(<#kind as #writable_krate::KeyWritable>::encode_key(&self.#ident).into_bytes().as_slice())?; + first_tag_write = false; + } }) } _ => None, }) .collect(); - let fields_writes: Vec = fields .iter() .filter_map(|f| match f.field_type { @@ -73,9 +78,15 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { let ident_str = ident.to_string(); let kind = f.kind.clone(); Some(quote! { - w.write_all(format!("{}", #ident_str).as_bytes())?; - w.write_all(b"=")?; - w.write_all(<#kind as #writable_krate::ValueWritable>::encode_value(&self.#ident).into_bytes().as_slice())?; + if <#kind as #writable_krate::ValueWritable>::encode_value(&self.#ident) != "None" { + if first_field_write == false { + w.write_all(b",")?; + } + w.write_all(format!("{}", #ident_str).as_bytes())?; + w.write_all(b"=")?; + w.write_all(<#kind as #writable_krate::ValueWritable>::encode_value(&self.#ident).into_bytes().as_slice())?; + first_field_write = false; + } }) } _ => None, @@ -106,22 +117,6 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { panic!("You have to specify at least one #[field] field.") } - let mut combined_tag_writes = vec![]; - for (index, tag_write) in tag_writes.iter().enumerate() { - if index > 0 { - combined_tag_writes.push(quote!(w.write_all(b",")?;)); - } - combined_tag_writes.push(tag_write.clone()); - } - - let mut combined_fields_writes = vec![]; - for (index, fields_write) in fields_writes.iter().enumerate() { - if index > 0 { - combined_fields_writes.push(quote!(w.write_all(b",")?;)); - } - combined_fields_writes.push(fields_write.clone()); - } - let output = quote! { impl #generics #krate::models::WriteDataPoint for #ident #generics { @@ -130,12 +125,14 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { W: std::io::Write{ w.write_all(format!("{},", #measure).as_bytes())?; + let mut first_tag_write = true; #( - #combined_tag_writes + #tag_writes )* w.write_all(b" ")?; + let mut first_field_write = true; #( - #combined_fields_writes + #fields_writes )* w.write_all(b" ")?; #( diff --git a/src/writable.rs b/src/writable.rs index 236c177..cadabf2 100644 --- a/src/writable.rs +++ b/src/writable.rs @@ -77,7 +77,7 @@ impl ValueWritable for Option { fn encode_value(&self) -> String { match self { Some(v) => v.encode_value(), - None => "\"None\"".to_string(), + None => "None".to_string(), } } } From 4211ae2124b9bbb1caf82efa6497f5894375b860 Mon Sep 17 00:00:00 2001 From: "UnHold (Alex)" Date: Sun, 11 Feb 2024 23:32:28 +0100 Subject: [PATCH 2/3] added tests for the encoding of the option values --- influxdb2-derive/tests/writable.rs | 156 ++++++++++++++++++++++++++--- src/writable.rs | 12 +++ 2 files changed, 156 insertions(+), 12 deletions(-) diff --git a/influxdb2-derive/tests/writable.rs b/influxdb2-derive/tests/writable.rs index 4ab3ea7..d3e9e9b 100644 --- a/influxdb2-derive/tests/writable.rs +++ b/influxdb2-derive/tests/writable.rs @@ -9,7 +9,9 @@ struct Item { name2: String, #[influxdb(field)] field1: u64, + #[influxdb(field)] field2: i64, + #[influxdb(field)] field3: String, #[influxdb(timestamp)] time: u64, @@ -19,15 +21,83 @@ struct Item { #[measurement = "something"] struct Item2 { #[influxdb(tag)] - name: Option, + name: String, #[influxdb(tag)] - name2: Option, + name2: String, #[influxdb(field)] field1: Option, - field2: i64, + #[influxdb(field)] + field2: Option, + #[influxdb(timestamp)] + time: u64, +} + +#[derive(WriteDataPoint)] +#[measurement = "barfoo"] +struct Item3 { + #[influxdb(tag)] + name: String, + #[influxdb(field)] + field1: Option, + #[influxdb(field)] + field2: Option, + #[influxdb(field)] + field3: Option, + #[influxdb(field)] + field4: Option, + #[influxdb(field)] + field5: Option, #[influxdb(timestamp)] time: u64, } + +#[derive(WriteDataPoint)] +#[measurement = "barfoo2"] +struct Item4 { + #[influxdb(tag)] + tag1: Option, + #[influxdb(tag)] + tag2: Option, + #[influxdb(tag)] + tag3: Option, + #[influxdb(tag)] + tag4: Option, + #[influxdb(tag)] + tag5: Option, + #[influxdb(field)] + field1: String, + #[influxdb(timestamp)] + time: u64, +} + + +#[derive(WriteDataPoint)] +#[measurement = "foobar"] +struct Item5 { + #[influxdb(tag)] + tag1: Option, + #[influxdb(tag)] + tag2: Option, + #[influxdb(tag)] + tag3: Option, + #[influxdb(tag)] + tag4: Option, + #[influxdb(tag)] + tag5: Option, + #[influxdb(field)] + field1: Option, + #[influxdb(field)] + field2: Option, + #[influxdb(field)] + field3: Option, + #[influxdb(field)] + field4: Option, + #[influxdb(field)] + field5: Option, + #[influxdb(timestamp)] + time: u64, +} + fn main() { use influxdb2::models::WriteDataPoint; use std::io::Write; @@ -37,32 +107,94 @@ fn main() { field1: 32u64, field2: 33i64, field3: "hello".to_string(), - time: 222222u64, + time: 222233u64, }; let mut writer = Vec::new(); item.write_data_point_to(&mut writer).unwrap(); writer.flush().unwrap(); - println!("{}", std::str::from_utf8(&writer).unwrap()); + println!("Writer: {}", std::str::from_utf8(&writer).unwrap()); assert_eq!( &writer[..], - b"something,name=foo,name2=bar field1=32u,field2=33i,field3=\"hello\" 222222\n" + b"something,name=foo,name2=bar field1=32u,field2=33i,field3=\"hello\" 222233\n" ); let item = Item2 { - name: Some("foo".to_string()), - name2: None, + name: "foo".to_string(), + name2: "bar".to_string(), field1: None, - field2: 33i64, + field2: Some(33i64), + time: 222222u64, + }; + + let mut writer = Vec::new(); + item.write_data_point_to(&mut writer).unwrap(); + writer.flush().unwrap(); + println!("Writer: {}", std::str::from_utf8(&writer).unwrap()); + assert_eq!( + &writer[..], + b"something,name=foo,name2=bar field2=33i 222222\n" + ); + + let item = Item3 { + name: "foo".to_string(), + field1: None, + field2: None, + field3: Some(12.34), + field4: None, + field5: None, + time: 222222u64, + }; + + let mut writer = Vec::new(); + item.write_data_point_to(&mut writer).unwrap(); + writer.flush().unwrap(); + println!("Writer: {}", std::str::from_utf8(&writer).unwrap()); + assert_eq!( + &writer[..], + b"barfoo,name=foo field3=12.34 222222\n" + ); + + let item = Item4 { + tag1: None, + tag2: None, + tag3: Some("thisIsATag".to_string()), + tag4: None, + tag5: None, + field1: "asdf".to_string(), time: 222222u64, }; let mut writer = Vec::new(); item.write_data_point_to(&mut writer).unwrap(); writer.flush().unwrap(); - println!("{}", std::str::from_utf8(&writer).unwrap()); + println!("Writer: {}", std::str::from_utf8(&writer).unwrap()); assert_eq!( &writer[..], - b"something,name=foo,name2=None field1=\"None\",field2=33i 222222\n" - ) + b"barfoo2,tag3=thisIsATag field1=\"asdf\" 222222\n" + ); + + let item = Item5 { + tag1: None, + tag2: None, + tag3: Some("thisIsATag".to_string()), + tag4: None, + tag5: None, + field1: None, + field2: None, + field3: Some(12.34), + field4: None, + field5: None, + time: 222222u64, + }; + + let mut writer = Vec::new(); + item.write_data_point_to(&mut writer).unwrap(); + writer.flush().unwrap(); + println!("Writer: {}", std::str::from_utf8(&writer).unwrap()); + assert_eq!( + &writer[..], + b"foobar,tag3=thisIsATag field3=12.34 222222\n" + ); + } diff --git a/src/writable.rs b/src/writable.rs index cadabf2..d4cd813 100644 --- a/src/writable.rs +++ b/src/writable.rs @@ -197,6 +197,18 @@ mod tests { assert_eq!(a.encode_value(), "33i") } + #[test] + fn value_writable_option_f64_not_none() { + let a: Option = Some(78.4); + assert_eq!(a.encode_value(), "78.4"); + } + + #[test] + fn value_writable_option_f64_none() { + let a: Option = None; + assert_eq!(a.encode_value(), "None"); + } + #[test] fn tags_tuple() { let a: (&str, &str) = ("33", "str"); From 4d4d96364d4e128af9349a22d6e898d9a27aa945 Mon Sep 17 00:00:00 2001 From: "UnHold (Alex)" Date: Tue, 13 Feb 2024 11:32:43 +0100 Subject: [PATCH 3/3] made timestamps and tags optional --- influxdb2-derive/src/expand_writable.rs | 18 ++---- influxdb2-derive/tests/writable.rs | 74 +++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 12 deletions(-) diff --git a/influxdb2-derive/src/expand_writable.rs b/influxdb2-derive/src/expand_writable.rs index 31d01b4..3f6b00a 100644 --- a/influxdb2-derive/src/expand_writable.rs +++ b/influxdb2-derive/src/expand_writable.rs @@ -57,13 +57,10 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { let kind = f.kind.clone(); Some(quote! { if <#kind as #writable_krate::KeyWritable>::encode_key(&self.#ident) != "None"{ - if first_tag_write == false { - w.write_all(b",")?; - } + w.write_all(b",")?; w.write_all(format!("{}", #ident_str).as_bytes())?; w.write_all(b"=")?; w.write_all(<#kind as #writable_krate::KeyWritable>::encode_key(&self.#ident).into_bytes().as_slice())?; - first_tag_write = false; } }) } @@ -100,6 +97,7 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { let ident = f.ident.clone(); let kind = f.kind.clone(); Some(quote! { + w.write_all(b" ")?; w.write_all(<#kind as #writable_krate::TimestampWritable>::encode_timestamp(&self.#ident).into_bytes().as_slice())?; }) } @@ -107,11 +105,8 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { }) .collect(); - if tag_writes.len() < 1 { - panic!("You have to specify at least one #[tag] field.") - } - if timestamp_writes.len() != 1 { - panic!("You have to specify at exact one #[timestamp] field.") + if timestamp_writes.len() > 1 { + panic!("You have to specify at most one #[timestamp] field.") } if fields_writes.len() < 1 { panic!("You have to specify at least one #[field] field.") @@ -123,9 +118,8 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { fn write_data_point_to(&self,mut w: W) -> std::io::Result<()> where W: std::io::Write{ - w.write_all(format!("{},", #measure).as_bytes())?; + w.write_all(format!("{}", #measure).as_bytes())?; - let mut first_tag_write = true; #( #tag_writes )* @@ -134,7 +128,7 @@ pub fn impl_writeable(tokens: TokenStream) -> TokenStream { #( #fields_writes )* - w.write_all(b" ")?; + #( #timestamp_writes )* diff --git a/influxdb2-derive/tests/writable.rs b/influxdb2-derive/tests/writable.rs index d3e9e9b..5062f18 100644 --- a/influxdb2-derive/tests/writable.rs +++ b/influxdb2-derive/tests/writable.rs @@ -98,6 +98,37 @@ struct Item5 { time: u64, } +#[derive(WriteDataPoint)] +#[measurement = "allTagsNone"] +struct Item6 { + #[influxdb(tag)] + tag1: Option, + #[influxdb(tag)] + tag2: Option, + #[influxdb(field)] + field1: String, + #[influxdb(timestamp)] + time: u64, +} + +#[derive(WriteDataPoint)] +#[measurement = "noTags"] +struct Item7 { + #[influxdb(field)] + field1: String, + #[influxdb(timestamp)] + time: u64, +} + +#[derive(WriteDataPoint)] +#[measurement = "noTimestamp"] +struct Item8 { + #[influxdb(tag)] + tag1: String, + #[influxdb(field)] + field1: String, +} + fn main() { use influxdb2::models::WriteDataPoint; use std::io::Write; @@ -197,4 +228,47 @@ fn main() { b"foobar,tag3=thisIsATag field3=12.34 222222\n" ); + let item = Item6 { + tag1: None, + tag2: None, + field1: "abc".to_string(), + time: 122222u64 + }; + + let mut writer = Vec::new(); + item.write_data_point_to(&mut writer).unwrap(); + writer.flush().unwrap(); + println!("Writer: {}", std::str::from_utf8(&writer).unwrap()); + assert_eq!( + &writer[..], + b"allTagsNone field1=\"abc\" 122222\n" + ); + + let item = Item7 { + field1: "def".to_string(), + time: 122222u64, + }; + + let mut writer = Vec::new(); + item.write_data_point_to(&mut writer).unwrap(); + writer.flush().unwrap(); + println!("Writer: {}", std::str::from_utf8(&writer).unwrap()); + assert_eq!( + &writer[..], + b"noTags field1=\"def\" 122222\n" + ); + + let item = Item8 { + tag1: "abc".to_string(), + field1: "def".to_string(), + }; + + let mut writer = Vec::new(); + item.write_data_point_to(&mut writer).unwrap(); + writer.flush().unwrap(); + println!("Writer: {}", std::str::from_utf8(&writer).unwrap()); + assert_eq!( + &writer[..], + b"noTimestamp,tag1=abc field1=\"def\"\n" + ); }