22//!
33//! Can only be instantiated by using Query::write_query
44
5+ use crate :: query:: line_proto_term:: LineProtoTerm ;
56use crate :: query:: { QueryType , ValidQuery } ;
67use crate :: { Error , Query , Timestamp } ;
78use std:: fmt:: { Display , Formatter } ;
89
910// todo: batch write queries
1011
1112pub trait WriteField {
12- fn add_to_fields ( self , tag : String , fields : & mut Vec < ( String , String ) > ) ;
13+ fn add_to_fields ( self , tag : String , fields : & mut Vec < ( String , Type ) > ) ;
1314}
1415
1516impl < T : Into < Type > > WriteField for T {
16- fn add_to_fields ( self , tag : String , fields : & mut Vec < ( String , String ) > ) {
17+ fn add_to_fields ( self , tag : String , fields : & mut Vec < ( String , Type ) > ) {
1718 let val: Type = self . into ( ) ;
18- fields. push ( ( tag, val. to_string ( ) ) ) ;
19+ fields. push ( ( tag, val) ) ;
1920 }
2021}
2122
2223impl < T : Into < Type > > WriteField for Option < T > {
23- fn add_to_fields ( self , tag : String , fields : & mut Vec < ( String , String ) > ) {
24+ fn add_to_fields ( self , tag : String , fields : & mut Vec < ( String , Type ) > ) {
2425 if let Some ( val) = self {
2526 val. add_to_fields ( tag, fields) ;
2627 }
@@ -29,7 +30,7 @@ impl<T: Into<Type>> WriteField for Option<T> {
2930
3031/// Internal Representation of a Write query that has not yet been built
3132pub struct WriteQuery {
32- fields : Vec < ( String , String ) > ,
33+ fields : Vec < ( String , Type ) > ,
3334 tags : Vec < ( String , String ) > ,
3435 measurement : String ,
3536 timestamp : Timestamp ,
@@ -121,7 +122,7 @@ impl Display for Type {
121122 Float ( x) => write ! ( f, "{}" , x) ,
122123 SignedInteger ( x) => write ! ( f, "{}" , x) ,
123124 UnsignedInteger ( x) => write ! ( f, "{}" , x) ,
124- Text ( text) => write ! ( f, "\" {text}\" " , text = text) ,
125+ Text ( text) => write ! ( f, "{text}" , text = text) ,
125126 }
126127 }
127128}
@@ -159,22 +160,35 @@ impl Query for WriteQuery {
159160 let mut tags = self
160161 . tags
161162 . iter ( )
162- . map ( |( tag, value) | format ! ( "{tag}={value}" , tag = tag, value = value) )
163+ . map ( |( tag, value) | {
164+ format ! (
165+ "{tag}={value}" ,
166+ tag = LineProtoTerm :: TagKey ( tag) . escape( ) ,
167+ value = LineProtoTerm :: TagValue ( value) . escape( ) ,
168+ )
169+ } )
163170 . collect :: < Vec < String > > ( )
164171 . join ( "," ) ;
172+
165173 if !tags. is_empty ( ) {
166174 tags. insert_str ( 0 , "," ) ;
167175 }
168176 let fields = self
169177 . fields
170178 . iter ( )
171- . map ( |( field, value) | format ! ( "{field}={value}" , field = field, value = value) )
179+ . map ( |( field, value) | {
180+ format ! (
181+ "{field}={value}" ,
182+ field = LineProtoTerm :: FieldKey ( field) . escape( ) ,
183+ value = LineProtoTerm :: FieldValue ( value) . escape( ) ,
184+ )
185+ } )
172186 . collect :: < Vec < String > > ( )
173187 . join ( "," ) ;
174188
175189 Ok ( ValidQuery ( format ! (
176190 "{measurement}{tags} {fields}{time}" ,
177- measurement = self . measurement,
191+ measurement = LineProtoTerm :: Measurement ( & self . measurement) . escape ( ) ,
178192 tags = tags,
179193 fields = fields,
180194 time = match self . timestamp {
@@ -207,7 +221,7 @@ mod tests {
207221 . build ( ) ;
208222
209223 assert ! ( query. is_ok( ) , "Query was empty" ) ;
210- assert_eq ! ( query. unwrap( ) , "weather temperature=82 11" ) ;
224+ assert_eq ! ( query. unwrap( ) , "weather temperature=82i 11" ) ;
211225 }
212226
213227 #[ test]
@@ -220,7 +234,7 @@ mod tests {
220234 assert ! ( query. is_ok( ) , "Query was empty" ) ;
221235 assert_eq ! (
222236 query. unwrap( ) ,
223- "weather temperature=82 ,wind_strength=3.7 11"
237+ "weather temperature=82i ,wind_strength=3.7 11"
224238 ) ;
225239 }
226240
@@ -232,7 +246,7 @@ mod tests {
232246 . build ( ) ;
233247
234248 assert ! ( query. is_ok( ) , "Query was empty" ) ;
235- assert_eq ! ( query. unwrap( ) , "weather temperature=82 11" ) ;
249+ assert_eq ! ( query. unwrap( ) , "weather temperature=82i 11" ) ;
236250 }
237251
238252 #[ test]
@@ -255,7 +269,7 @@ mod tests {
255269 assert ! ( query. is_ok( ) , "Query was empty" ) ;
256270 assert_eq ! (
257271 query. unwrap( ) ,
258- "weather,location=\" us-midwest\" ,season=\" summer\" temperature=82 11"
272+ "weather,location=us-midwest,season=summer temperature=82i 11"
259273 ) ;
260274 }
261275
@@ -270,4 +284,21 @@ mod tests {
270284
271285 assert_eq ! ( query. get_type( ) , QueryType :: WriteQuery ) ;
272286 }
287+
288+ #[ test]
289+ fn test_escaping ( ) {
290+ let query = Query :: write_query ( Timestamp :: Hours ( 11 ) , "wea, ther=" )
291+ . add_field ( "temperature" , 82 )
292+ . add_field ( "\" temp=era,t ure\" " , r#"too"\\hot"# )
293+ . add_field ( "float" , 82.0 )
294+ . add_tag ( "location" , "us-midwest" )
295+ . add_tag ( "loc, =\" ation" , "us, \" mid=west\" " )
296+ . build ( ) ;
297+
298+ assert ! ( query. is_ok( ) , "Query was empty" ) ;
299+ assert_eq ! (
300+ query. unwrap( ) . get( ) ,
301+ r#"wea\,\ ther=,location=us-midwest,loc\,\ \="ation=us\,\ "mid\=west" temperature=82i,"temp\=era\,t\ ure"="too\"\\\\hot",float=82 11"#
302+ ) ;
303+ }
273304}
0 commit comments