From a15151add7bb947649a8debbf5716d09d3558e9f Mon Sep 17 00:00:00 2001 From: Dominic Date: Mon, 14 Dec 2020 22:34:33 +0100 Subject: [PATCH 01/42] create gh-pages branch From 084742bcb87fffdbd2416af6b1d23ae5226b2df5 Mon Sep 17 00:00:00 2001 From: Empty2k12 Date: Mon, 14 Dec 2020 22:14:11 +0000 Subject: [PATCH 02/42] GitHub Pages for f176db5ef3d08d63ee51e2c2c6c87f52d883b9e8 --- coverage.svg | 1 + tarpaulin-report.html | 660 ++++++++++++++++++++++++++++++++++++++++++ tarpaulin-report.json | 1 + 3 files changed, 662 insertions(+) create mode 100644 coverage.svg create mode 100644 tarpaulin-report.html create mode 100644 tarpaulin-report.json diff --git a/coverage.svg b/coverage.svg new file mode 100644 index 0000000..c08718d --- /dev/null +++ b/coverage.svg @@ -0,0 +1 @@ +coverage: 82.17%coverage82.17% \ No newline at end of file diff --git a/tarpaulin-report.html b/tarpaulin-report.html new file mode 100644 index 0000000..24dd223 --- /dev/null +++ b/tarpaulin-report.html @@ -0,0 +1,660 @@ + + + + + + + +
+ + + + + + \ No newline at end of file diff --git a/tarpaulin-report.json b/tarpaulin-report.json new file mode 100644 index 0000000..81f0d52 --- /dev/null +++ b/tarpaulin-report.json @@ -0,0 +1 @@ +{"files":[{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","benches","client.rs"],"content":"use chrono::{DateTime, Utc};\nuse influxdb::Error;\nuse influxdb::InfluxDbWriteable;\nuse influxdb::{Client, Query};\nuse std::sync::Arc;\nuse std::time::Instant;\nuse tokio::sync::mpsc::unbounded_channel;\nuse tokio::sync::Semaphore;\n\n#[derive(InfluxDbWriteable, Clone)]\nstruct WeatherReading {\n time: DateTime,\n humidity: i32,\n #[tag]\n wind_direction: String,\n}\n\n#[tokio::main]\nasync fn main() {\n let db_name = \"bench\";\n let url = \"http://localhost:8086\";\n let number_of_total_requests = 20000;\n let concurrent_requests = 1000;\n\n let client = Client::new(url, db_name);\n let concurrency_limit = Arc::new(Semaphore::new(concurrent_requests));\n\n prepare_influxdb(&client, db_name).await;\n let measurements = generate_measurements(number_of_total_requests);\n let (tx, mut rx) = unbounded_channel::>();\n\n let start = Instant::now();\n for m in measurements {\n let permit = concurrency_limit.clone().acquire_owned().await;\n let client_task = client.clone();\n let tx_task = tx.clone();\n tokio::spawn(async move {\n let res = client_task.query(&m.into_query(\"weather\")).await;\n let _ = tx_task.send(res);\n drop(permit);\n });\n }\n drop(tx);\n\n let mut successful_count = 0;\n let mut error_count = 0;\n while let Some(res) = rx.recv().await {\n if res.is_err() {\n error_count += 1;\n } else {\n successful_count += 1;\n }\n }\n\n let end = Instant::now();\n\n println!(\n \"Throughput: {:.1} request/s\",\n 1000000.0 * successful_count as f64 / (end - start).as_micros() as f64\n );\n println!(\n \"{} successful requests, {} errors\",\n successful_count, error_count\n );\n}\n\nasync fn prepare_influxdb(client: &Client, db_name: &str) {\n let create_db_stmt = format!(\"CREATE DATABASE {}\", db_name);\n client\n .query(&Query::raw_read_query(create_db_stmt))\n .await\n .expect(\"failed to create database\");\n}\n\nfn generate_measurements(n: u64) -> Vec {\n (0..n)\n .collect::>()\n .iter_mut()\n .map(|_| WeatherReading {\n time: Utc::now(),\n humidity: 30,\n wind_direction: String::from(\"north\"),\n })\n .collect()\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","client","mod.rs"],"content":"//! Client which can read and write data from InfluxDB.\n//!\n//! # Arguments\n//!\n//! * `url`: The URL where InfluxDB is running (ex. `http://localhost:8086`).\n//! * `database`: The Database against which queries and writes will be run.\n//!\n//! # Examples\n//!\n//! ```rust\n//! use influxdb::Client;\n//!\n//! let client = Client::new(\"http://localhost:8086\", \"test\");\n//!\n//! assert_eq!(client.database_name(), \"test\");\n//! ```\n\nuse futures::prelude::*;\nuse surf::{self, Client as SurfClient, StatusCode};\n\nuse crate::query::QueryTypes;\nuse crate::Error;\nuse crate::Query;\nuse std::collections::HashMap;\nuse std::sync::Arc;\n\n#[derive(Clone, Debug)]\n/// Internal Representation of a Client\npub struct Client {\n pub(crate) url: Arc,\n pub(crate) parameters: Arc>,\n pub(crate) client: SurfClient,\n}\n\nimpl Client {\n /// Instantiates a new [`Client`](crate::Client)\n ///\n /// # Arguments\n ///\n /// * `url`: The URL where InfluxDB is running (ex. `http://localhost:8086`).\n /// * `database`: The Database against which queries and writes will be run.\n ///\n /// # Examples\n ///\n /// ```rust\n /// use influxdb::Client;\n ///\n /// let _client = Client::new(\"http://localhost:8086\", \"test\");\n /// ```\n pub fn new(url: S1, database: S2) -> Self\n where\n S1: Into,\n S2: Into,\n {\n let mut parameters = HashMap::<&str, String>::new();\n parameters.insert(\"db\", database.into());\n Client {\n url: Arc::new(url.into()),\n parameters: Arc::new(parameters),\n client: SurfClient::new(),\n }\n }\n\n /// Add authentication/authorization information to [`Client`](crate::Client)\n ///\n /// # Arguments\n ///\n /// * username: The Username for InfluxDB.\n /// * password: The Password for the user.\n ///\n /// # Examples\n ///\n /// ```rust\n /// use influxdb::Client;\n ///\n /// let _client = Client::new(\"http://localhost:9086\", \"test\").with_auth(\"admin\", \"password\");\n /// ```\n pub fn with_auth(mut self, username: S1, password: S2) -> Self\n where\n S1: Into,\n S2: Into,\n {\n let mut with_auth = self.parameters.as_ref().clone();\n with_auth.insert(\"u\", username.into());\n with_auth.insert(\"p\", password.into());\n self.parameters = Arc::new(with_auth);\n self\n }\n\n /// Returns the name of the database the client is using\n pub fn database_name(&self) -> &str {\n // safe to unwrap: we always set the database name in `Self::new`\n self.parameters.get(\"db\").unwrap()\n }\n\n /// Returns the URL of the InfluxDB installation the client is using\n pub fn database_url(&self) -> &str {\n &self.url\n }\n\n /// Pings the InfluxDB Server\n ///\n /// Returns a tuple of build type and version number\n pub async fn ping(&self) -> Result<(String, String), Error> {\n let url = &format!(\"{}/ping\", self.url);\n let res = self\n .client\n .get(url)\n .send()\n .await\n .map_err(|err| Error::ProtocolError {\n error: format!(\"{}\", err),\n })?;\n\n let build = res.header(\"X-Influxdb-Build\").unwrap().as_str();\n let version = res.header(\"X-Influxdb-Version\").unwrap().as_str();\n\n Ok((build.to_owned(), version.to_owned()))\n }\n\n /// Sends a [`ReadQuery`](crate::ReadQuery) or [`WriteQuery`](crate::WriteQuery) to the InfluxDB Server.\n ///\n /// A version capable of parsing the returned string is available under the [serde_integration](crate::integrations::serde_integration)\n ///\n /// # Arguments\n ///\n /// * `q`: Query of type [`ReadQuery`](crate::ReadQuery) or [`WriteQuery`](crate::WriteQuery)\n ///\n /// # Examples\n ///\n /// ```rust,no_run\n /// use influxdb::{Client, Query, Timestamp};\n /// use influxdb::InfluxDbWriteable;\n /// use std::time::{SystemTime, UNIX_EPOCH};\n ///\n /// # #[async_std::main]\n /// # async fn main() -> Result<(), influxdb::Error> {\n /// let start = SystemTime::now();\n /// let since_the_epoch = start\n /// .duration_since(UNIX_EPOCH)\n /// .expect(\"Time went backwards\")\n /// .as_millis();\n ///\n /// let client = Client::new(\"http://localhost:8086\", \"test\");\n /// let query = Timestamp::Milliseconds(since_the_epoch)\n /// .into_query(\"weather\")\n /// .add_field(\"temperature\", 82);\n /// let results = client.query(&query).await?;\n ///\n /// # Ok(())\n /// # }\n /// ```\n /// # Errors\n ///\n /// If the function can not finish the query,\n /// a [`Error`] variant will be returned.\n ///\n /// [`Error`]: enum.Error.html\n pub async fn query<'q, Q>(&self, q: &'q Q) -> Result\n where\n Q: Query,\n &'q Q: Into>,\n {\n let query = q.build().map_err(|err| Error::InvalidQueryError {\n error: err.to_string(),\n })?;\n\n let request_builder = match q.into() {\n QueryTypes::Read(_) => {\n let read_query = query.get();\n let url = &format!(\"{}/query\", &self.url);\n let mut parameters = self.parameters.as_ref().clone();\n parameters.insert(\"q\", read_query.clone());\n\n if read_query.contains(\"SELECT\") || read_query.contains(\"SHOW\") {\n self.client.get(url).query(¶meters)\n } else {\n self.client.post(url).query(¶meters)\n }\n }\n QueryTypes::Write(write_query) => {\n let url = &format!(\"{}/write\", &self.url);\n let mut parameters = self.parameters.as_ref().clone();\n parameters.insert(\"precision\", write_query.get_precision());\n\n self.client.post(url).body(query.get()).query(¶meters)\n }\n }\n .map_err(|err| Error::UrlConstructionError {\n error: err.to_string(),\n })?;\n\n let request = request_builder.build();\n let mut res = self\n .client\n .send(request)\n .map_err(|err| Error::ConnectionError {\n error: err.to_string(),\n })\n .await?;\n\n match res.status() {\n StatusCode::Unauthorized => return Err(Error::AuthorizationError),\n StatusCode::Forbidden => return Err(Error::AuthenticationError),\n _ => {}\n }\n\n let s = res\n .body_string()\n .await\n .map_err(|_| Error::DeserializationError {\n error: \"response could not be converted to UTF-8\".to_string(),\n })?;\n\n // todo: improve error parsing without serde\n if s.contains(\"\\\"error\\\"\") {\n return Err(Error::DatabaseError {\n error: format!(\"influxdb error: \\\"{}\\\"\", s),\n });\n }\n\n Ok(s)\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::Client;\n\n #[test]\n fn test_fn_database() {\n let client = Client::new(\"http://localhost:8068\", \"database\");\n assert_eq!(client.database_name(), \"database\");\n assert_eq!(client.database_url(), \"http://localhost:8068\");\n }\n\n #[test]\n fn test_with_auth() {\n let client = Client::new(\"http://localhost:8068\", \"database\");\n assert_eq!(client.parameters.len(), 1);\n assert_eq!(client.parameters.get(\"db\").unwrap(), \"database\");\n\n let with_auth = client.with_auth(\"username\", \"password\");\n assert_eq!(with_auth.parameters.len(), 3);\n assert_eq!(with_auth.parameters.get(\"db\").unwrap(), \"database\");\n assert_eq!(with_auth.parameters.get(\"u\").unwrap(), \"username\");\n assert_eq!(with_auth.parameters.get(\"p\").unwrap(), \"password\");\n }\n}\n","traces":[{"line":50,"address":[4457936,4458042,4457359,4457232],"length":1,"stats":{"Line":6},"fn_name":"new<&str,&str>"},{"line":55,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":56,"address":[],"length":0,"stats":{"Line":12},"fn_name":null},{"line":58,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":59,"address":[],"length":0,"stats":{"Line":12},"fn_name":null},{"line":60,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":78,"address":[4511504,4511643],"length":1,"stats":{"Line":3},"fn_name":"with_auth<&str,&str>"},{"line":83,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":84,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":86,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":87,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":91,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":93,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":97,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":98,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":104,"address":[],"length":0,"stats":{"Line":7},"fn_name":null},{"line":105,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":106,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":107,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":108,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":110,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":111,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":112,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":115,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":116,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":118,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":159,"address":[4458656,4458943,4465967,4458736],"length":1,"stats":{"Line":8},"fn_name":"query"},{"line":164,"address":[],"length":0,"stats":{"Line":15},"fn_name":null},{"line":165,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":168,"address":[],"length":0,"stats":{"Line":18},"fn_name":null},{"line":169,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":170,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":171,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":172,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":173,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":175,"address":[],"length":0,"stats":{"Line":11},"fn_name":null},{"line":176,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":178,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":181,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":182,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":183,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":184,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":186,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":189,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":190,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":193,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":194,"address":[],"length":0,"stats":{"Line":38},"fn_name":null},{"line":195,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":196,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":197,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":198,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":200,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":202,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":203,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":204,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":205,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":208,"address":[],"length":0,"stats":{"Line":20},"fn_name":null},{"line":210,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":211,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":212,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":216,"address":[],"length":0,"stats":{"Line":12},"fn_name":null},{"line":217,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":218,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":222,"address":[],"length":0,"stats":{"Line":4},"fn_name":null}],"covered":50,"coverable":65},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","error.rs"],"content":"//! Errors that might happen in the crate\n\nuse thiserror::Error;\n\n#[derive(Debug, Error)]\npub enum Error {\n #[error(\"query is invalid: {error}\")]\n /// Error happens when a query is invalid\n InvalidQueryError { error: String },\n\n #[error(\"Failed to build URL: {error}\")]\n /// Error happens when a query is invalid\n UrlConstructionError { error: String },\n\n #[error(\"http protocol error: {error}\")]\n /// Error happens when a query is invalid\n ProtocolError { error: String },\n\n #[error(\"http protocol error: {error}\")]\n /// Error happens when Serde cannot deserialize the response\n DeserializationError { error: String },\n\n #[error(\"InfluxDB encountered the following error: {error}\")]\n /// Error which has happened inside InfluxDB\n DatabaseError { error: String },\n\n #[error(\"authentication error. No or incorrect credentials\")]\n /// Error happens when no or incorrect credentials are used. `HTTP 401 Unauthorized`\n AuthenticationError,\n\n #[error(\"authorization error. User not authorized\")]\n /// Error happens when the supplied user is not authorized. `HTTP 403 Forbidden`\n AuthorizationError,\n\n #[error(\"connection error: {error}\")]\n /// Error happens when HTTP request fails\n ConnectionError { error: String },\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","integrations","serde_integration","de.rs"],"content":"use super::{Series, TaggedSeries};\nuse serde::de::{\n value, DeserializeSeed, Deserializer, Error, IntoDeserializer, MapAccess, SeqAccess, Visitor,\n};\nuse serde::Deserialize;\nuse std::fmt;\nuse std::marker::PhantomData;\n\n// Based on https://serde.rs/deserialize-struct.html\nimpl<'de, T> Deserialize<'de> for Series\nwhere\n T: Deserialize<'de>,\n{\n fn deserialize(deserializer: D) -> Result\n where\n D: Deserializer<'de>,\n {\n // Field name deserializer\n #[derive(Deserialize)]\n #[serde(field_identifier, rename_all = \"lowercase\")]\n enum Field {\n Name,\n Columns,\n Values,\n };\n\n struct SeriesVisitor {\n _inner_type: PhantomData,\n };\n\n impl<'de, T> Visitor<'de> for SeriesVisitor\n where\n T: Deserialize<'de>,\n {\n type Value = Series;\n\n fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\n formatter.write_str(\"struct Series\")\n }\n\n fn visit_map(self, mut map: V) -> Result, V::Error>\n where\n V: MapAccess<'de>,\n {\n let mut name = None;\n let mut columns: Option> = None;\n let mut values: Option> = None;\n while let Some(key) = map.next_key()? {\n match key {\n Field::Name => {\n if name.is_some() {\n return Err(Error::duplicate_field(\"name\"));\n }\n name = Some(map.next_value()?);\n }\n Field::Columns => {\n if columns.is_some() {\n return Err(Error::duplicate_field(\"columns\"));\n }\n columns = Some(map.next_value()?);\n }\n Field::Values => {\n if values.is_some() {\n return Err(Error::duplicate_field(\"values\"));\n }\n // Error out if \"values\" is encountered before \"columns\"\n // Hopefully, InfluxDB never does this.\n if columns.is_none() {\n return Err(Error::custom(\n \"series values encountered before columns\",\n ));\n }\n // Deserialize using a HeaderVec deserializer\n // seeded with the headers from the \"columns\" field\n values = Some(map.next_value_seed(HeaderVec:: {\n header: columns.as_ref().unwrap(),\n _inner_type: PhantomData,\n })?);\n }\n }\n }\n let name = name.ok_or_else(|| Error::missing_field(\"name\"))?;\n let values = values.unwrap_or_default();\n\n Ok(Series { name, values })\n }\n }\n\n const FIELDS: &[&str] = &[\"name\", \"values\"];\n deserializer.deserialize_struct(\n \"Series\",\n FIELDS,\n SeriesVisitor:: {\n _inner_type: PhantomData,\n },\n )\n }\n}\n\n// Based on https://serde.rs/deserialize-struct.html\nimpl<'de, TAG, T> Deserialize<'de> for TaggedSeries\nwhere\n TAG: Deserialize<'de>,\n T: Deserialize<'de>,\n{\n fn deserialize(deserializer: D) -> Result\n where\n D: Deserializer<'de>,\n {\n // Field name deserializer\n #[derive(Deserialize)]\n #[serde(field_identifier, rename_all = \"lowercase\")]\n enum Field {\n Name,\n Tags,\n Columns,\n Values,\n };\n\n struct SeriesVisitor {\n _tag_type: PhantomData,\n _value_type: PhantomData,\n };\n\n impl<'de, TAG, T> Visitor<'de> for SeriesVisitor\n where\n TAG: Deserialize<'de>,\n T: Deserialize<'de>,\n {\n type Value = TaggedSeries;\n\n fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\n formatter.write_str(\"struct TaggedSeries\")\n }\n\n fn visit_map(self, mut map: V) -> Result, V::Error>\n where\n V: MapAccess<'de>,\n {\n let mut name = None;\n let mut tags: Option = None;\n let mut columns: Option> = None;\n let mut values: Option> = None;\n while let Some(key) = map.next_key()? {\n match key {\n Field::Name => {\n if name.is_some() {\n return Err(Error::duplicate_field(\"name\"));\n }\n name = Some(map.next_value()?);\n }\n Field::Tags => {\n if tags.is_some() {\n return Err(Error::duplicate_field(\"tags\"));\n }\n tags = Some(map.next_value()?);\n }\n Field::Columns => {\n if columns.is_some() {\n return Err(Error::duplicate_field(\"columns\"));\n }\n columns = Some(map.next_value()?);\n }\n Field::Values => {\n if values.is_some() {\n return Err(Error::duplicate_field(\"values\"));\n }\n // Error out if \"values\" is encountered before \"columns\"\n // Hopefully, InfluxDB never does this.\n if columns.is_none() {\n return Err(Error::custom(\n \"series values encountered before columns\",\n ));\n }\n // Deserialize using a HeaderVec deserializer\n // seeded with the headers from the \"columns\" field\n values = Some(map.next_value_seed(HeaderVec:: {\n header: columns.as_ref().unwrap(),\n _inner_type: PhantomData,\n })?);\n }\n }\n }\n let name = name.ok_or_else(|| Error::missing_field(\"name\"))?;\n let tags = tags.ok_or_else(|| Error::missing_field(\"tags\"))?;\n let values = values.ok_or_else(|| Error::missing_field(\"values\"))?;\n Ok(TaggedSeries { name, tags, values })\n }\n }\n\n const FIELDS: &[&str] = &[\"name\", \"tags\", \"values\"];\n deserializer.deserialize_struct(\n \"TaggedSeries\",\n FIELDS,\n SeriesVisitor:: {\n _tag_type: PhantomData,\n _value_type: PhantomData,\n },\n )\n }\n}\n\n// Deserializer that takes a header as a seed\n// and deserializes an array of arrays into a\n// Vec of map-like values using the header as\n// keys and the values as values.\nstruct HeaderVec<'h, T> {\n header: &'h [String],\n _inner_type: PhantomData,\n}\n\nimpl<'de, 'h, T> DeserializeSeed<'de> for HeaderVec<'h, T>\nwhere\n T: Deserialize<'de>,\n{\n type Value = Vec;\n\n fn deserialize(self, deserializer: D) -> Result\n where\n D: Deserializer<'de>,\n {\n struct HeaderVecVisitor<'h, T> {\n header: &'h [String],\n _inner_type: PhantomData,\n }\n impl<'de, 'h, T> Visitor<'de> for HeaderVecVisitor<'h, T>\n where\n T: Deserialize<'de>,\n {\n type Value = Vec;\n\n fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\n write!(formatter, \"an array of arrays\")\n }\n\n fn visit_seq(self, mut seq: A) -> Result, A::Error>\n where\n A: SeqAccess<'de>,\n {\n let mut vec = Vec::new();\n\n while let Some(v) = seq.next_element_seed(RowWithHeader {\n header: self.header,\n _inner_type: PhantomData,\n })? {\n vec.push(v);\n }\n\n Ok(vec)\n }\n }\n deserializer.deserialize_seq(HeaderVecVisitor {\n header: self.header,\n _inner_type: PhantomData,\n })\n }\n}\n\n// Deserializer that takes a header as a seed\n// and deserializes an array into a map-like\n// value using the header as keys and the values\n// as values.\nstruct RowWithHeader<'h, T> {\n header: &'h [String],\n _inner_type: PhantomData,\n}\n\nimpl<'de, 'h, T> DeserializeSeed<'de> for RowWithHeader<'h, T>\nwhere\n T: Deserialize<'de>,\n{\n type Value = T;\n\n fn deserialize(self, deserializer: D) -> Result\n where\n D: Deserializer<'de>,\n {\n struct RowWithHeaderVisitor<'h, T> {\n header: &'h [String],\n _inner: PhantomData T>,\n }\n\n impl<'de, 'h, T> Visitor<'de> for RowWithHeaderVisitor<'h, T>\n where\n T: Deserialize<'de>,\n {\n type Value = T;\n\n fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {\n formatter.write_str(\"array\")\n }\n\n fn visit_seq(self, seq: A) -> Result\n where\n A: SeqAccess<'de>,\n {\n // `MapAccessDeserializer` is a wrapper that turns a `MapAccess`\n // into a `Deserializer`, allowing it to be used as the input to T's\n // `Deserialize` implementation. T then deserializes itself using\n // the entries from the map visitor.\n Deserialize::deserialize(value::MapAccessDeserializer::new(HeaderMapAccess {\n header: self.header,\n field: 0,\n data: seq,\n }))\n }\n }\n\n deserializer.deserialize_seq(RowWithHeaderVisitor {\n header: self.header,\n _inner: PhantomData,\n })\n }\n}\n\n// MapAccess implementation that holds a reference to\n// the header for keys and a serde sequence for values.\n// When asked for a key, it returns the next header and\n// advances its header field index. When asked for a value,\n// it tries to deserialize the next element in the serde\n// sequence into the desired type, and returns an error\n// if no element is returned (the sequence is exhausted).\nstruct HeaderMapAccess<'h, A> {\n header: &'h [String],\n field: usize,\n data: A,\n}\n\nimpl<'de, 'h, A> MapAccess<'de> for HeaderMapAccess<'h, A>\nwhere\n A: SeqAccess<'de>,\n{\n type Error = >::Error;\n\n fn next_key_seed>(\n &mut self,\n seed: K,\n ) -> Result, Self::Error> {\n let field = match self.header.get(self.field) {\n None => return Ok(None),\n Some(field) => field,\n };\n self.field += 1;\n seed.deserialize(field.clone().into_deserializer())\n .map(Some)\n }\n\n fn next_value_seed>(\n &mut self,\n seed: K,\n ) -> Result {\n match self.data.next_element_seed(seed)? {\n Some(value) => Ok(value),\n None => Err(Error::custom(\"next_value_seed called but no value\")),\n }\n }\n}\n\n#[cfg(test)]\nmod tests {\n use super::Series;\n use std::borrow::Cow;\n use std::collections::HashMap;\n\n const TEST_DATA: &str = r#\"\n {\n \"name\": \"series_name\",\n \"columns\": [\"foo\", \"bar\"],\n \"values\": [\n [\"foo_a\", \"bar_a\"],\n [\"foo_b\", \"bar_b\"]\n ]\n }\n \"#;\n\n // we can derive all the impls we want here\n #[derive(Debug, PartialEq, Eq)]\n struct EqSeries {\n pub name: String,\n pub values: Vec,\n }\n\n impl From> for EqSeries {\n fn from(Series { name, values }: Series) -> Self {\n EqSeries { name, values }\n }\n }\n\n #[test]\n fn test_deserialize_cow() {\n // Unfortunately, Cow is not automatically borrowed,\n // so this is basically equivalent to String, String\n let result = serde_json::from_str::, Cow>>>(TEST_DATA);\n assert!(result.is_ok());\n assert_eq!(\n EqSeries::from(result.unwrap()),\n EqSeries {\n name: \"series_name\".into(),\n values: vec![\n {\n let mut h = std::collections::HashMap::new();\n h.insert(\"foo\".into(), \"foo_a\".into());\n h.insert(\"bar\".into(), \"bar_a\".into());\n h\n },\n {\n let mut h = std::collections::HashMap::new();\n h.insert(\"foo\".into(), \"foo_b\".into());\n h.insert(\"bar\".into(), \"bar_b\".into());\n h\n },\n ],\n },\n );\n }\n\n #[test]\n fn test_deserialize_borrowed() {\n use serde::Deserialize;\n\n // Deserializing a string that cannot be passed through\n // without escaping will result in an error like this:\n // `invalid type: string \"\\n\", expected a borrowed string at line 6 column 43`\n // but if it doesn't need escaping it's fine.\n #[derive(Deserialize, Debug, PartialEq, Eq)]\n struct BorrowingStruct<'a> {\n foo: &'a str,\n bar: &'a str,\n }\n\n let result = serde_json::from_str::>(TEST_DATA);\n assert!(result.is_ok(), \"{}\", result.unwrap_err());\n assert_eq!(\n EqSeries::from(result.unwrap()),\n EqSeries {\n name: \"series_name\".into(),\n values: vec![\n BorrowingStruct {\n foo: \"foo_a\",\n bar: \"bar_a\",\n },\n BorrowingStruct {\n foo: \"foo_b\",\n bar: \"bar_b\",\n },\n ],\n },\n );\n }\n}\n","traces":[{"line":14,"address":[4483520],"length":1,"stats":{"Line":8},"fn_name":"deserialize"},{"line":31,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":35,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":37,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":38,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":41,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":45,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":46,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":47,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":48,"address":[],"length":0,"stats":{"Line":48},"fn_name":null},{"line":49,"address":[],"length":0,"stats":{"Line":24},"fn_name":null},{"line":50,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":51,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":52,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":54,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":56,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":57,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":58,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":60,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":62,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":63,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":64,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":68,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":69,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":70,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":75,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":76,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":77,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":82,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":83,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":85,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":90,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":92,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":93,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":94,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":106,"address":[4360080],"length":1,"stats":{"Line":1},"fn_name":"deserialize"},{"line":125,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":130,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":132,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":133,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":136,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":140,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":141,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":142,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":143,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":144,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":145,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":146,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":147,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":148,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":150,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":152,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":153,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":154,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":156,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":158,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":159,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":160,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":162,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":164,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":165,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":166,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":170,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":171,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":172,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":177,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":178,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":179,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":184,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":185,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":186,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":187,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":192,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":194,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":195,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":196,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":197,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":218,"address":[4451520],"length":1,"stats":{"Line":9},"fn_name":"deserialize"},{"line":226,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":230,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":232,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":233,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":236,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":240,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":242,"address":[],"length":0,"stats":{"Line":54},"fn_name":null},{"line":243,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":244,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":246,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":249,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":252,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":253,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":254,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":274,"address":[4451616],"length":1,"stats":{"Line":9},"fn_name":"deserialize"},{"line":283,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":287,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":289,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":290,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":293,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":301,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":302,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":303,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":304,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":309,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":310,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":311,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":335,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":339,"address":[],"length":0,"stats":{"Line":18},"fn_name":null},{"line":340,"address":[],"length":0,"stats":{"Line":18},"fn_name":null},{"line":341,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":343,"address":[],"length":0,"stats":{"Line":18},"fn_name":null},{"line":344,"address":[],"length":0,"stats":{"Line":9},"fn_name":null},{"line":345,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":348,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":352,"address":[],"length":0,"stats":{"Line":24},"fn_name":null},{"line":353,"address":[],"length":0,"stats":{"Line":16},"fn_name":null},{"line":354,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":64,"coverable":116},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","integrations","serde_integration","mod.rs"],"content":"//! Serde Integration for InfluxDB. Provides deserialization of query returns.\n//!\n//! When querying multiple series in the same query (e.g. with a regex query), it might be desirable to flat map\n//! the resulting series into a single `Vec` like so. The example assumes, that there are weather readings in multiple\n//! series named `weather_` (e.g. `weather_berlin`, or `weather_london`). Since we're using a Regex query,\n//! we don't actually know which series will be returned. To assign the city name to the series, we can use the series\n//! `name`, InfluxDB provides alongside query results.\n//!\n//! ```rust,no_run\n//! use futures::prelude::*;\n//! use influxdb::{Client, Query};\n//! use serde::Deserialize;\n//!\n//! #[derive(Deserialize)]\n//! struct WeatherWithoutCityName {\n//! temperature: i32,\n//! }\n//!\n//! #[derive(Deserialize)]\n//! struct Weather {\n//! city_name: String,\n//! weather: WeatherWithoutCityName,\n//! }\n//!\n//! # #[async_std::main]\n//! # async fn main() -> Result<(), influxdb::Error> {\n//! let client = Client::new(\"http://localhost:8086\", \"test\");\n//! let query = Query::raw_read_query(\n//! \"SELECT temperature FROM /weather_[a-z]*$/ WHERE time > now() - 1m ORDER BY DESC\",\n//! );\n//! let mut db_result = client.json_query(query).await?;\n//! let _result = db_result\n//! .deserialize_next::()?\n//! .series\n//! .into_iter()\n//! .map(|mut city_series| {\n//! let city_name =\n//! city_series.name.split(\"_\").collect::>().remove(2);\n//! Weather {\n//! weather: city_series.values.remove(0),\n//! city_name: city_name.to_string(),\n//! }\n//! })\n//! .collect::>();\n//! # Ok(())\n//! # }\n//! ```\n\nmod de;\n\nuse surf::StatusCode;\n\nuse serde::{de::DeserializeOwned, Deserialize};\n\nuse crate::{Client, Error, Query, ReadQuery};\n\n#[derive(Deserialize)]\n#[doc(hidden)]\nstruct _DatabaseError {\n error: String,\n}\n\n#[derive(Deserialize, Debug)]\n#[doc(hidden)]\npub struct DatabaseQueryResult {\n pub results: Vec,\n}\n\nimpl DatabaseQueryResult {\n pub fn deserialize_next(&mut self) -> Result, Error>\n where\n T: DeserializeOwned + Send,\n {\n serde_json::from_value::>(self.results.remove(0)).map_err(|err| {\n Error::DeserializationError {\n error: format!(\"could not deserialize: {}\", err),\n }\n })\n }\n\n pub fn deserialize_next_tagged(\n &mut self,\n ) -> Result, Error>\n where\n TAG: DeserializeOwned + Send,\n T: DeserializeOwned + Send,\n {\n serde_json::from_value::>(self.results.remove(0)).map_err(|err| {\n Error::DeserializationError {\n error: format!(\"could not deserialize: {}\", err),\n }\n })\n }\n}\n\n#[derive(Deserialize, Debug)]\n#[doc(hidden)]\npub struct Return {\n #[serde(default = \"Vec::new\")]\n pub series: Vec>,\n}\n\n#[derive(Debug)]\n/// Represents a returned series from InfluxDB\npub struct Series {\n pub name: String,\n pub values: Vec,\n}\n\n#[derive(Deserialize, Debug)]\n#[doc(hidden)]\npub struct TaggedReturn {\n #[serde(default = \"Vec::new\")]\n pub series: Vec>,\n}\n\n#[derive(Debug)]\n/// Represents a returned series from InfluxDB\npub struct TaggedSeries {\n pub name: String,\n pub tags: TAG,\n pub values: Vec,\n}\n\nimpl Client {\n pub async fn json_query(&self, q: ReadQuery) -> Result {\n let query = q.build().map_err(|err| Error::InvalidQueryError {\n error: format!(\"{}\", err),\n })?;\n\n let read_query = query.get();\n\n if !read_query.contains(\"SELECT\") && !read_query.contains(\"SHOW\") {\n let error = Error::InvalidQueryError {\n error: String::from(\n \"Only SELECT and SHOW queries supported with JSON deserialization\",\n ),\n };\n return Err(error);\n }\n\n let url = &format!(\"{}/query\", &self.url);\n let mut parameters = self.parameters.as_ref().clone();\n parameters.insert(\"q\", read_query);\n let request = self\n .client\n .get(url)\n .query(¶meters)\n .map_err(|err| Error::UrlConstructionError {\n error: err.to_string(),\n })?\n .build();\n\n let mut res = self\n .client\n .send(request)\n .await\n .map_err(|err| Error::ConnectionError {\n error: err.to_string(),\n })?;\n\n match res.status() {\n StatusCode::Unauthorized => return Err(Error::AuthorizationError),\n StatusCode::Forbidden => return Err(Error::AuthenticationError),\n _ => {}\n }\n\n let body = res.body_bytes().await.map_err(|err| Error::ProtocolError {\n error: err.to_string(),\n })?;\n\n // Try parsing InfluxDBs { \"error\": \"error message here\" }\n if let Ok(error) = serde_json::from_slice::<_DatabaseError>(&body) {\n return Err(Error::DatabaseError { error: error.error });\n }\n\n // Json has another structure, let's try actually parsing it to the type we're deserializing\n serde_json::from_slice::(&body).map_err(|err| {\n Error::DeserializationError {\n error: format!(\"serde error: {}\", err),\n }\n })\n }\n}\n","traces":[{"line":70,"address":[4482896],"length":1,"stats":{"Line":6},"fn_name":"deserialize_next"},{"line":74,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":75,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":76,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":81,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":88,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":89,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":90,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":126,"address":[4572989,4573088,4572725,4572704,4572820,4572915],"length":1,"stats":{"Line":15},"fn_name":"drop_in_place"},{"line":127,"address":[4491120,4483806,4483972,4484003,4490896,4484150,4490975],"length":1,"stats":{"Line":6},"fn_name":"{{closure}}"},{"line":128,"address":[4491069,4490906,4490995],"length":1,"stats":{"Line":0},"fn_name":null},{"line":131,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":133,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":135,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":139,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":142,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":143,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":144,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":145,"address":[],"length":0,"stats":{"Line":10},"fn_name":null},{"line":146,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":147,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":148,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":149,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":150,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":154,"address":[],"length":0,"stats":{"Line":14},"fn_name":null},{"line":155,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":156,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":157,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":158,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":159,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":162,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":163,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":164,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":165,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":168,"address":[],"length":0,"stats":{"Line":10},"fn_name":null},{"line":169,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":173,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":174,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":178,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":179,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":180,"address":[],"length":0,"stats":{"Line":0},"fn_name":null}],"covered":22,"coverable":41},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","lib.rs"],"content":"//! This library is a work in progress. This means a feature you might need is not implemented\n//! yet or could be handled better.\n//!\n//! Pull requests are always welcome. See [Contributing](https://github.com/Empty2k12/influxdb-rust/blob/master/CONTRIBUTING.md) and [Code of Conduct](https://github.com/Empty2k12/influxdb-rust/blob/master/CODE_OF_CONDUCT.md).\n//!\n//! ## Currently Supported Features\n//!\n//! - Reading and Writing to InfluxDB\n//! - Optional Serde Support for Deserialization\n//! - Running multiple queries in one request (e.g. `SELECT * FROM weather_berlin; SELECT * FROM weather_london`)\n//! - Authenticated and Unauthenticated Connections\n//! - `async`/`await` support\n//! - `#[derive(InfluxDbWriteable)]` Derive Macro for Writing / Reading into Structs\n//! - `GROUP BY` support\n//! - Tokio and async-std support (see example below) or [available backends](https://github.com/Empty2k12/influxdb-rust/blob/master/influxdb/Cargo.toml)\n//!\n//! # Quickstart\n//!\n//! Add the following to your `Cargo.toml`\n//!\n//! ```toml\n//! influxdb = { version = \"0.3.0\", features = [\"derive\"] }\n//! ```\n//!\n//! For an example with using Serde deserialization, please refer to [serde_integration](crate::integrations::serde_integration)\n//!\n//! ```rust,no_run\n//! use influxdb::{Client, Query, Timestamp};\n//! use influxdb::InfluxDbWriteable;\n//! use chrono::{DateTime, Utc};\n//!\n//! #[async_std::main]\n//! // or #[tokio::main] if you prefer\n//! async fn main() {\n//! // Connect to db `test` on `http://localhost:8086`\n//! let client = Client::new(\"http://localhost:8086\", \"test\");\n//!\n//! #[derive(InfluxDbWriteable)]\n//! struct WeatherReading {\n//! time: DateTime,\n//! humidity: i32,\n//! #[tag] wind_direction: String,\n//! }\n//!\n//! // Let's write some data into a measurement called `weather`\n//! let weather_reading = WeatherReading {\n//! time: Timestamp::Hours(1).into(),\n//! humidity: 30,\n//! wind_direction: String::from(\"north\"),\n//! };\n//!\n//! let write_result = client\n//! .query(&weather_reading.into_query(\"weather\"))\n//! .await;\n//! assert!(write_result.is_ok(), \"Write result was not okay\");\n//!\n//! // Let's see if the data we wrote is there\n//! let read_query = Query::raw_read_query(\"SELECT * FROM weather\");\n//!\n//! let read_result = client.query(&read_query).await;\n//! assert!(read_result.is_ok(), \"Read result was not ok\");\n//! println!(\"{}\", read_result.unwrap());\n//! }\n//! ```\n//!\n//! For further examples, check out the Integration Tests in `tests/integration_tests.rs`\n//! in the repository.\n//!\n//! # License\n//!\n//! [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n#![allow(clippy::needless_doctest_main)]\n#![allow(clippy::needless_lifetimes)] // False positive in client/mod.rs query fn\n\nmod client;\nmod error;\nmod query;\n\npub use client::Client;\npub use error::Error;\npub use query::{\n read_query::ReadQuery,\n write_query::{Type, WriteQuery},\n InfluxDbWriteable, Query, QueryType, QueryTypes, Timestamp, ValidQuery,\n};\n\n#[cfg(feature = \"use-serde\")]\npub mod integrations {\n #[cfg(feature = \"use-serde\")]\n pub mod serde_integration;\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","query","consts.rs"],"content":"pub const MINUTES_PER_HOUR: u128 = 60;\npub const SECONDS_PER_MINUTE: u128 = 60;\npub const MILLIS_PER_SECOND: u128 = 1000;\npub const NANOS_PER_MILLI: u128 = 1_000_000;\n\n#[cfg(test)]\npub const MICROS_PER_NANO: u128 = 1000;\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","query","line_proto_term.rs"],"content":"/// InfluxDB Line Protocol escaping helper module.\n/// https://docs.influxdata.com/influxdb/v1.7/write_protocols/line_protocol_tutorial/\nuse crate::Type;\nuse lazy_static::lazy_static;\nuse regex::Regex;\n\nlazy_static! {\n pub static ref COMMAS_SPACES: Regex = Regex::new(\"[, ]\").unwrap();\n pub static ref COMMAS_SPACES_EQUALS: Regex = Regex::new(\"[, =]\").unwrap();\n pub static ref QUOTES_SLASHES: Regex = Regex::new(r#\"[\"\\\\]\"#).unwrap();\n pub static ref SLASHES: Regex = Regex::new(r#\"(\\\\|,| |=|\")\"#).unwrap();\n}\n\npub enum LineProtoTerm<'a> {\n Measurement(&'a str), // escape commas, spaces\n TagKey(&'a str), // escape commas, equals, spaces\n TagValue(&'a Type), // escape commas, equals, spaces\n FieldKey(&'a str), // escape commas, equals, spaces\n FieldValue(&'a Type), // escape quotes, backslashes + quote\n}\n\nimpl LineProtoTerm<'_> {\n pub fn escape(self) -> String {\n use LineProtoTerm::*;\n match self {\n Measurement(x) => Self::escape_any(x, &*COMMAS_SPACES),\n TagKey(x) | FieldKey(x) => Self::escape_any(x, &*COMMAS_SPACES_EQUALS),\n FieldValue(x) => Self::escape_field_value(x),\n TagValue(x) => Self::escape_tag_value(x),\n }\n }\n\n fn escape_field_value(v: &Type) -> String {\n use Type::*;\n match v {\n Boolean(v) => {\n if *v {\n \"true\"\n } else {\n \"false\"\n }\n }\n .to_string(),\n Float(v) => v.to_string(),\n SignedInteger(v) => format!(\"{}i\", v),\n UnsignedInteger(v) => format!(\"{}i\", v),\n Text(v) => format!(r#\"\"{}\"\"#, Self::escape_any(v, &*QUOTES_SLASHES)),\n }\n }\n\n fn escape_tag_value(v: &Type) -> String {\n use Type::*;\n match v {\n Boolean(v) => {\n if *v {\n \"true\"\n } else {\n \"false\"\n }\n }\n .to_string(),\n Float(v) => format!(r#\"{}\"#, v),\n SignedInteger(v) => format!(r#\"{}\"#, v),\n UnsignedInteger(v) => format!(r#\"{}\"#, v),\n Text(v) => Self::escape_any(v, &*SLASHES),\n }\n }\n\n fn escape_any(s: &str, re: &Regex) -> String {\n re.replace_all(s, r#\"\\$0\"#).to_string()\n }\n}\n\n#[cfg(test)]\nmod test {\n use crate::query::line_proto_term::LineProtoTerm::*;\n use crate::Type;\n\n #[test]\n fn test() {\n assert_eq!(TagValue(&Type::Boolean(true)).escape(), r#\"true\"#);\n assert_eq!(TagValue(&Type::Float(1.8324f64)).escape(), r#\"1.8324\"#);\n assert_eq!(TagValue(&Type::SignedInteger(-1i64)).escape(), r#\"-1\"#);\n assert_eq!(TagValue(&Type::UnsignedInteger(1u64)).escape(), r#\"1\"#);\n\n assert_eq!(\n TagValue(&Type::Text(\"this is my special string\".into())).escape(),\n r#\"this\\ is\\ my\\ special\\ string\"#\n );\n assert_eq!(\n TagValue(&Type::Text(\"a tag w=i th == tons of escapes\".into())).escape(),\n r#\"a\\ tag\\ w\\=i\\ th\\ \\=\\=\\ tons\\ of\\ escapes\"#\n );\n assert_eq!(\n TagValue(&Type::Text(\"no_escapes\".into())).escape(),\n r#\"no_escapes\"#\n );\n assert_eq!(\n TagValue(&Type::Text(\"some,commas,here\".into())).escape(),\n r#\"some\\,commas\\,here\"#\n );\n\n assert_eq!(Measurement(r#\"wea\", ther\"#).escape(), r#\"wea\"\\,\\ ther\"#);\n assert_eq!(TagKey(r#\"locat\\ ,=ion\"#).escape(), r#\"locat\\\\ \\,\\=ion\"#);\n\n assert_eq!(FieldValue(&Type::Boolean(true)).escape(), r#\"true\"#);\n assert_eq!(FieldValue(&Type::Boolean(false)).escape(), r#\"false\"#);\n\n assert_eq!(FieldValue(&Type::Float(0.0)).escape(), r#\"0\"#);\n assert_eq!(FieldValue(&Type::Float(-0.1)).escape(), r#\"-0.1\"#);\n\n assert_eq!(FieldValue(&Type::SignedInteger(0)).escape(), r#\"0i\"#);\n assert_eq!(FieldValue(&Type::SignedInteger(83)).escape(), r#\"83i\"#);\n\n assert_eq!(FieldValue(&Type::Text(\"\".into())).escape(), r#\"\"\"\"#);\n assert_eq!(FieldValue(&Type::Text(\"0\".into())).escape(), r#\"\"0\"\"#);\n assert_eq!(FieldValue(&Type::Text(\"\\\"\".into())).escape(), r#\"\"\\\"\"\"#);\n assert_eq!(\n FieldValue(&Type::Text(r#\"locat\"\\ ,=ion\"#.into())).escape(),\n r#\"\"locat\\\"\\\\ ,=ion\"\"#\n );\n }\n\n #[test]\n fn test_empty_tag_value() {\n // InfluxDB doesn't support empty tag values. But that's a job\n // of a calling site to validate an entire write request.\n assert_eq!(TagValue(&Type::Text(\"\".into())).escape(), r#\"\"#);\n }\n}\n","traces":[{"line":8,"address":[4874190],"length":1,"stats":{"Line":3},"fn_name":null},{"line":9,"address":[4873918],"length":1,"stats":{"Line":3},"fn_name":null},{"line":10,"address":[4873822],"length":1,"stats":{"Line":1},"fn_name":null},{"line":11,"address":[4874094],"length":1,"stats":{"Line":2},"fn_name":null},{"line":23,"address":[4904032],"length":1,"stats":{"Line":4},"fn_name":"escape"},{"line":25,"address":[4904202,4904273,4904298,4904325,4904118,4904354],"length":1,"stats":{"Line":15},"fn_name":null},{"line":26,"address":[4904042,4904132],"length":1,"stats":{"Line":7},"fn_name":null},{"line":27,"address":[4904280,4904214,4904320],"length":1,"stats":{"Line":9},"fn_name":null},{"line":28,"address":[4904332],"length":1,"stats":{"Line":3},"fn_name":null},{"line":29,"address":[4904091],"length":1,"stats":{"Line":4},"fn_name":null},{"line":33,"address":[4904384,4904448],"length":1,"stats":{"Line":3},"fn_name":"escape_field_value"},{"line":35,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":36,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":37,"address":[4904561,4904531,4904587],"length":1,"stats":{"Line":3},"fn_name":null},{"line":38,"address":[4904570],"length":1,"stats":{"Line":1},"fn_name":null},{"line":40,"address":[4904544],"length":1,"stats":{"Line":1},"fn_name":null},{"line":44,"address":[4904620],"length":1,"stats":{"Line":1},"fn_name":null},{"line":45,"address":[4904665],"length":1,"stats":{"Line":3},"fn_name":null},{"line":46,"address":[4904887],"length":1,"stats":{"Line":1},"fn_name":null},{"line":47,"address":[4904468,4905104],"length":1,"stats":{"Line":2},"fn_name":null},{"line":51,"address":[4905456],"length":1,"stats":{"Line":4},"fn_name":"escape_tag_value"},{"line":53,"address":[],"length":0,"stats":{"Line":7},"fn_name":null},{"line":54,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":55,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":56,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":58,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":62,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":63,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":64,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":65,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":69,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":70,"address":[],"length":0,"stats":{"Line":6},"fn_name":null}],"covered":31,"coverable":32},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","query","mod.rs"],"content":"//! Used to create queries of type [`ReadQuery`](crate::query::read_query::ReadQuery) or\n//! [`WriteQuery`](crate::query::write_query::WriteQuery) which can be executed in InfluxDB\n//!\n//! # Examples\n//!\n//! ```rust\n//! use influxdb::{Query, Timestamp};\n//! use influxdb::InfluxDbWriteable;\n//!\n//! let write_query = Timestamp::Nanoseconds(0).into_query(\"measurement\")\n//! .add_field(\"field1\", 5)\n//! .add_tag(\"author\", \"Gero\")\n//! .build();\n//!\n//! assert!(write_query.is_ok());\n//!\n//! let read_query = Query::raw_read_query(\"SELECT * FROM weather\")\n//! .build();\n//!\n//! assert!(read_query.is_ok());\n//! ```\n\nuse chrono::prelude::{DateTime, TimeZone, Utc};\nuse std::convert::TryInto;\n\npub mod consts;\nmod line_proto_term;\npub mod read_query;\npub mod write_query;\nuse std::fmt;\n\nuse crate::{Error, ReadQuery, WriteQuery};\nuse consts::{MILLIS_PER_SECOND, MINUTES_PER_HOUR, NANOS_PER_MILLI, SECONDS_PER_MINUTE};\n\n#[cfg(feature = \"derive\")]\npub use influxdb_derive::InfluxDbWriteable;\n\n#[derive(PartialEq, Debug, Copy, Clone)]\npub enum Timestamp {\n Nanoseconds(u128),\n Microseconds(u128),\n Milliseconds(u128),\n Seconds(u128),\n Minutes(u128),\n Hours(u128),\n}\n\nimpl fmt::Display for Timestamp {\n fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n use Timestamp::*;\n match self {\n Nanoseconds(ts) | Microseconds(ts) | Milliseconds(ts) | Seconds(ts) | Minutes(ts)\n | Hours(ts) => write!(f, \"{}\", ts),\n }\n }\n}\n\nimpl Into> for Timestamp {\n fn into(self) -> DateTime {\n match self {\n Timestamp::Hours(h) => {\n let nanos =\n h * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLIS_PER_SECOND * NANOS_PER_MILLI;\n Utc.timestamp_nanos(nanos.try_into().unwrap())\n }\n Timestamp::Minutes(m) => {\n let nanos = m * SECONDS_PER_MINUTE * MILLIS_PER_SECOND * NANOS_PER_MILLI;\n Utc.timestamp_nanos(nanos.try_into().unwrap())\n }\n Timestamp::Seconds(s) => {\n let nanos = s * MILLIS_PER_SECOND * NANOS_PER_MILLI;\n Utc.timestamp_nanos(nanos.try_into().unwrap())\n }\n Timestamp::Milliseconds(millis) => {\n let nanos = millis * NANOS_PER_MILLI;\n Utc.timestamp_nanos(nanos.try_into().unwrap())\n }\n Timestamp::Nanoseconds(nanos) => Utc.timestamp_nanos(nanos.try_into().unwrap()),\n Timestamp::Microseconds(mis) => {\n let nanos = mis / 10000;\n Utc.timestamp_nanos(nanos.try_into().unwrap())\n }\n }\n }\n}\n\nimpl From> for Timestamp\nwhere\n T: TimeZone,\n{\n fn from(date_time: DateTime) -> Self {\n Timestamp::Nanoseconds(date_time.timestamp_nanos() as u128)\n }\n}\n\n/// Internal enum used to represent either type of query.\npub enum QueryTypes<'a> {\n Read(&'a ReadQuery),\n Write(&'a WriteQuery),\n}\n\nimpl<'a> From<&'a ReadQuery> for QueryTypes<'a> {\n fn from(query: &'a ReadQuery) -> Self {\n Self::Read(query)\n }\n}\n\nimpl<'a> From<&'a WriteQuery> for QueryTypes<'a> {\n fn from(query: &'a WriteQuery) -> Self {\n Self::Write(query)\n }\n}\n\npub trait Query {\n /// Builds valid InfluxSQL which can be run against the Database.\n /// In case no fields have been specified, it will return an error,\n /// as that is invalid InfluxSQL syntax.\n ///\n /// # Examples\n ///\n /// ```rust\n /// use influxdb::{Query, Timestamp};\n /// use influxdb::InfluxDbWriteable;\n ///\n /// let invalid_query = Timestamp::Nanoseconds(0).into_query(\"measurement\").build();\n /// assert!(invalid_query.is_err());\n ///\n /// let valid_query = Timestamp::Nanoseconds(0).into_query(\"measurement\").add_field(\"myfield1\", 11).build();\n /// assert!(valid_query.is_ok());\n /// ```\n fn build(&self) -> Result;\n\n fn get_type(&self) -> QueryType;\n}\n\npub trait InfluxDbWriteable {\n fn into_query>(self, name: I) -> WriteQuery;\n}\n\nimpl InfluxDbWriteable for Timestamp {\n fn into_query>(self, name: I) -> WriteQuery {\n WriteQuery::new(self, name.into())\n }\n}\n\nimpl dyn Query {\n /// Returns a [`ReadQuery`](crate::ReadQuery) builder.\n ///\n /// # Examples\n ///\n /// ```rust\n /// use influxdb::Query;\n ///\n /// Query::raw_read_query(\"SELECT * FROM weather\"); // Is of type [`ReadQuery`](crate::ReadQuery)\n /// ```\n pub fn raw_read_query(read_query: S) -> ReadQuery\n where\n S: Into,\n {\n ReadQuery::new(read_query)\n }\n}\n\n#[derive(Debug)]\n#[doc(hidden)]\npub struct ValidQuery(String);\nimpl ValidQuery {\n pub fn get(self) -> String {\n self.0\n }\n}\nimpl From for ValidQuery\nwhere\n T: Into,\n{\n fn from(string: T) -> Self {\n Self(string.into())\n }\n}\nimpl PartialEq for ValidQuery {\n fn eq(&self, other: &String) -> bool {\n &self.0 == other\n }\n}\nimpl PartialEq<&str> for ValidQuery {\n fn eq(&self, other: &&str) -> bool {\n &self.0 == other\n }\n}\n\n/// Internal Enum used to decide if a `POST` or `GET` request should be sent to InfluxDB. See [InfluxDB Docs](https://docs.influxdata.com/influxdb/v1.7/tools/api/#query-http-endpoint).\n#[derive(PartialEq, Debug)]\npub enum QueryType {\n ReadQuery,\n WriteQuery,\n}\n\n#[cfg(test)]\nmod tests {\n use super::consts::{\n MICROS_PER_NANO, MILLIS_PER_SECOND, MINUTES_PER_HOUR, NANOS_PER_MILLI, SECONDS_PER_MINUTE,\n };\n use crate::query::{Timestamp, ValidQuery};\n use chrono::prelude::{DateTime, TimeZone, Utc};\n use std::convert::TryInto;\n #[test]\n fn test_equality_str() {\n assert_eq!(ValidQuery::from(\"hello\"), \"hello\");\n }\n #[test]\n fn test_equality_string() {\n assert_eq!(\n ValidQuery::from(String::from(\"hello\")),\n String::from(\"hello\")\n );\n }\n #[test]\n fn test_format_for_timestamp_else() {\n assert!(format!(\"{}\", Timestamp::Nanoseconds(100)) == \"100\");\n }\n #[test]\n fn test_chrono_datetime_from_timestamp_hours() {\n let datetime_from_timestamp: DateTime = Timestamp::Hours(2).into();\n assert_eq!(\n Utc.timestamp_nanos(\n (2 * MINUTES_PER_HOUR * SECONDS_PER_MINUTE * MILLIS_PER_SECOND * NANOS_PER_MILLI)\n .try_into()\n .unwrap()\n ),\n datetime_from_timestamp\n )\n }\n #[test]\n fn test_chrono_datetime_from_timestamp_minutes() {\n let datetime_from_timestamp: DateTime = Timestamp::Minutes(2).into();\n assert_eq!(\n Utc.timestamp_nanos(\n (2 * SECONDS_PER_MINUTE * MILLIS_PER_SECOND * NANOS_PER_MILLI)\n .try_into()\n .unwrap()\n ),\n datetime_from_timestamp\n )\n }\n #[test]\n fn test_chrono_datetime_from_timestamp_seconds() {\n let datetime_from_timestamp: DateTime = Timestamp::Seconds(2).into();\n assert_eq!(\n Utc.timestamp_nanos(\n (2 * MILLIS_PER_SECOND * NANOS_PER_MILLI)\n .try_into()\n .unwrap()\n ),\n datetime_from_timestamp\n )\n }\n #[test]\n fn test_chrono_datetime_from_timestamp_millis() {\n let datetime_from_timestamp: DateTime = Timestamp::Milliseconds(2).into();\n assert_eq!(\n Utc.timestamp_nanos((2 * NANOS_PER_MILLI).try_into().unwrap()),\n datetime_from_timestamp\n )\n }\n #[test]\n fn test_chrono_datetime_from_timestamp_nanos() {\n let datetime_from_timestamp: DateTime = Timestamp::Nanoseconds(1).into();\n assert_eq!(Utc.timestamp_nanos(1), datetime_from_timestamp)\n }\n #[test]\n fn test_chrono_datetime_from_timestamp_micros() {\n let datetime_from_timestamp: DateTime = Timestamp::Microseconds(1).into();\n assert_eq!(\n Utc.timestamp_nanos((1 / MICROS_PER_NANO).try_into().unwrap()),\n datetime_from_timestamp\n )\n }\n #[test]\n fn test_timestamp_from_chrono_date() {\n let timestamp_from_datetime: Timestamp = Utc.ymd(1970, 1, 1).and_hms(0, 0, 1).into();\n assert_eq!(\n Timestamp::Nanoseconds(MILLIS_PER_SECOND * NANOS_PER_MILLI),\n timestamp_from_datetime\n )\n }\n}\n","traces":[{"line":49,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":51,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":52,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":53,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":59,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":60,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":61,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":62,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":63,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":64,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":66,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":67,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":68,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":70,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":71,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":72,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":74,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":75,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":76,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":78,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":79,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":80,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":81,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":91,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":92,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":103,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":104,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":109,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":110,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":141,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":142,"address":[],"length":0,"stats":{"Line":5},"fn_name":null},{"line":156,"address":[4506928,4506864],"length":1,"stats":{"Line":6},"fn_name":"raw_read_query"},{"line":160,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":168,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":169,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":176,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":177,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":181,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":182,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":186,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":187,"address":[],"length":0,"stats":{"Line":1},"fn_name":null}],"covered":40,"coverable":41},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","query","read_query.rs"],"content":"//! Read Query Builder returned by Query::raw_read_query\n//!\n//! Can only be instantiated by using Query::raw_read_query\n\nuse crate::query::{QueryType, ValidQuery};\nuse crate::{Error, Query};\n\n#[derive(Debug, Clone)]\npub struct ReadQuery {\n queries: Vec,\n}\n\nimpl ReadQuery {\n /// Creates a new [`ReadQuery`]\n pub fn new(query: S) -> Self\n where\n S: Into,\n {\n ReadQuery {\n queries: vec![query.into()],\n }\n }\n\n /// Adds a query to the [`ReadQuery`]\n pub fn add_query(mut self, query: S) -> Self\n where\n S: Into,\n {\n self.queries.push(query.into());\n self\n }\n}\n\nimpl Query for ReadQuery {\n fn build(&self) -> Result {\n Ok(ValidQuery(self.queries.join(\";\")))\n }\n\n fn get_type(&self) -> QueryType {\n QueryType::ReadQuery\n }\n}\n\n#[cfg(test)]\nmod tests {\n use crate::query::{Query, QueryType};\n\n #[test]\n fn test_read_builder_single_query() {\n let query = Query::raw_read_query(\"SELECT * FROM aachen\").build();\n\n assert_eq!(query.unwrap(), \"SELECT * FROM aachen\");\n }\n\n #[test]\n fn test_read_builder_multi_query() {\n let query = Query::raw_read_query(\"SELECT * FROM aachen\")\n .add_query(\"SELECT * FROM cologne\")\n .build();\n\n assert_eq!(query.unwrap(), \"SELECT * FROM aachen;SELECT * FROM cologne\");\n }\n\n #[test]\n fn test_correct_query_type() {\n let query = Query::raw_read_query(\"SELECT * FROM aachen\");\n\n assert_eq!(query.get_type(), QueryType::ReadQuery);\n }\n}\n","traces":[{"line":15,"address":[4535936,4536160,4536083,4536306],"length":1,"stats":{"Line":6},"fn_name":"new"},{"line":20,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":25,"address":[4499313,4499248],"length":1,"stats":{"Line":2},"fn_name":"add_query<&str>"},{"line":29,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":30,"address":[4499362],"length":1,"stats":{"Line":2},"fn_name":null},{"line":35,"address":[5499808],"length":1,"stats":{"Line":4},"fn_name":"build"},{"line":36,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":39,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":40,"address":[],"length":0,"stats":{"Line":1},"fn_name":null}],"covered":9,"coverable":9},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","src","query","write_query.rs"],"content":"//! Write Query Builder returned by Query::write_query\n//!\n//! Can only be instantiated by using Query::write_query\n\nuse crate::query::line_proto_term::LineProtoTerm;\nuse crate::query::{QueryType, ValidQuery};\nuse crate::{Error, Query, Timestamp};\nuse std::fmt::{Display, Formatter};\n\npub trait WriteType {\n fn add_to(self, tag: String, fields_or_tags: &mut Vec<(String, Type)>);\n}\n\nimpl> WriteType for T {\n fn add_to(self, tag: String, fields_or_tags: &mut Vec<(String, Type)>) {\n let val: Type = self.into();\n fields_or_tags.push((tag, val));\n }\n}\n\nimpl> WriteType for Option {\n fn add_to(self, tag: String, fields_or_tags: &mut Vec<(String, Type)>) {\n if let Some(val) = self {\n val.add_to(tag, fields_or_tags);\n }\n }\n}\n\n/// Internal Representation of a Write query that has not yet been built\n#[derive(Debug, Clone)]\npub struct WriteQuery {\n fields: Vec<(String, Type)>,\n tags: Vec<(String, Type)>,\n measurement: String,\n timestamp: Timestamp,\n}\n\nimpl WriteQuery {\n /// Creates a new [`WriteQuery`](crate::query::write_query::WriteQuery)\n pub fn new(timestamp: Timestamp, measurement: S) -> Self\n where\n S: Into,\n {\n WriteQuery {\n fields: vec![],\n tags: vec![],\n measurement: measurement.into(),\n timestamp,\n }\n }\n\n /// Adds a field to the [`WriteQuery`](crate::WriteQuery)\n ///\n /// # Examples\n ///\n /// ```rust\n /// use influxdb::{Query, Timestamp};\n /// use influxdb::InfluxDbWriteable;\n ///\n /// Timestamp::Nanoseconds(0).into_query(\"measurement\").add_field(\"field1\", 5).build();\n /// ```\n pub fn add_field(mut self, field: S, value: F) -> Self\n where\n S: Into,\n F: WriteType,\n {\n value.add_to(field.into(), &mut self.fields);\n self\n }\n\n /// Adds a tag to the [`WriteQuery`](crate::WriteQuery)\n ///\n /// Please note that a [`WriteQuery`](crate::WriteQuery) requires at least one field. Composing a query with\n /// only tags will result in a failure building the query.\n ///\n /// # Examples\n ///\n /// ```rust\n /// use influxdb::{Query, Timestamp};\n /// use influxdb::InfluxDbWriteable;\n ///\n /// Timestamp::Nanoseconds(0)\n /// .into_query(\"measurement\")\n /// .add_tag(\"field1\", 5); // calling `.build()` now would result in a `Err(Error::InvalidQueryError)`\n /// ```\n pub fn add_tag(mut self, tag: S, value: I) -> Self\n where\n S: Into,\n I: WriteType,\n {\n value.add_to(tag.into(), &mut self.tags);\n self\n }\n\n pub fn get_precision(&self) -> String {\n let modifier = match self.timestamp {\n Timestamp::Nanoseconds(_) => \"ns\",\n Timestamp::Microseconds(_) => \"u\",\n Timestamp::Milliseconds(_) => \"ms\",\n Timestamp::Seconds(_) => \"s\",\n Timestamp::Minutes(_) => \"m\",\n Timestamp::Hours(_) => \"h\",\n };\n modifier.to_string()\n }\n}\n\n#[derive(Debug, Clone)]\npub enum Type {\n Boolean(bool),\n Float(f64),\n SignedInteger(i64),\n UnsignedInteger(u64),\n Text(String),\n}\n\nimpl Display for Type {\n fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {\n use Type::*;\n\n match self {\n Boolean(x) => write!(f, \"{}\", x),\n Float(x) => write!(f, \"{}\", x),\n SignedInteger(x) => write!(f, \"{}\", x),\n UnsignedInteger(x) => write!(f, \"{}\", x),\n Text(text) => write!(f, \"{text}\", text = text),\n }\n }\n}\n\nmacro_rules! from_impl {\n ( $variant:ident => $( $typ:ident ),+ ) => (\n $(\n impl From<$typ> for Type {\n fn from(b: $typ) -> Self {\n Type::$variant(b.into())\n }\n }\n )+\n )\n}\nfrom_impl! {Boolean => bool}\nfrom_impl! {Float => f32, f64}\nfrom_impl! {SignedInteger => i8, i16, i32, i64}\nfrom_impl! {UnsignedInteger => u8, u16, u32, u64}\nfrom_impl! {Text => String}\nimpl From<&str> for Type {\n fn from(b: &str) -> Self {\n Type::Text(b.into())\n }\n}\nimpl From<&T> for Type\nwhere\n T: Copy + Into,\n{\n fn from(t: &T) -> Self {\n (*t).into()\n }\n}\n\nimpl Query for WriteQuery {\n fn build(&self) -> Result {\n if self.fields.is_empty() {\n return Err(Error::InvalidQueryError {\n error: \"fields cannot be empty\".to_string(),\n });\n }\n\n let mut tags = self\n .tags\n .iter()\n .map(|(tag, value)| {\n format!(\n \"{tag}={value}\",\n tag = LineProtoTerm::TagKey(tag).escape(),\n value = LineProtoTerm::TagValue(value).escape(),\n )\n })\n .collect::>()\n .join(\",\");\n\n if !tags.is_empty() {\n tags.insert(0, ',');\n }\n let fields = self\n .fields\n .iter()\n .map(|(field, value)| {\n format!(\n \"{field}={value}\",\n field = LineProtoTerm::FieldKey(field).escape(),\n value = LineProtoTerm::FieldValue(value).escape(),\n )\n })\n .collect::>()\n .join(\",\");\n\n Ok(ValidQuery(format!(\n \"{measurement}{tags} {fields}{time}\",\n measurement = LineProtoTerm::Measurement(&self.measurement).escape(),\n tags = tags,\n fields = fields,\n time = format!(\" {}\", self.timestamp)\n )))\n }\n\n fn get_type(&self) -> QueryType {\n QueryType::WriteQuery\n }\n}\n\n#[cfg(test)]\nmod tests {\n use crate::query::{InfluxDbWriteable, Query, Timestamp};\n\n #[test]\n fn test_write_builder_empty_query() {\n let query = Timestamp::Hours(5)\n .into_query(\"marina_3\".to_string())\n .build();\n\n assert!(query.is_err(), \"Query was not empty\");\n }\n\n #[test]\n fn test_write_builder_single_field() {\n let query = Timestamp::Hours(11)\n .into_query(\"weather\".to_string())\n .add_field(\"temperature\", 82)\n .build();\n\n assert!(query.is_ok(), \"Query was empty\");\n assert_eq!(query.unwrap(), \"weather temperature=82i 11\");\n }\n\n #[test]\n fn test_write_builder_multiple_fields() {\n let query = Timestamp::Hours(11)\n .into_query(\"weather\".to_string())\n .add_field(\"temperature\", 82)\n .add_field(\"wind_strength\", 3.7)\n .build();\n\n assert!(query.is_ok(), \"Query was empty\");\n assert_eq!(\n query.unwrap(),\n \"weather temperature=82i,wind_strength=3.7 11\"\n );\n }\n\n #[test]\n fn test_write_builder_optional_fields() {\n let query = Timestamp::Hours(11)\n .into_query(\"weather\".to_string())\n .add_field(\"temperature\", 82u64)\n .add_tag(\"wind_strength\", >::None)\n .build();\n\n assert!(query.is_ok(), \"Query was empty\");\n assert_eq!(query.unwrap(), \"weather temperature=82i 11\");\n }\n\n #[test]\n fn test_write_builder_only_tags() {\n let query = Timestamp::Hours(11)\n .into_query(\"weather\".to_string())\n .add_tag(\"season\", \"summer\")\n .build();\n\n assert!(query.is_err(), \"Query missing one or more fields\");\n }\n\n #[test]\n fn test_write_builder_full_query() {\n let query = Timestamp::Hours(11)\n .into_query(\"weather\".to_string())\n .add_field(\"temperature\", 82)\n .add_tag(\"location\", \"us-midwest\")\n .add_tag(\"season\", \"summer\")\n .build();\n\n assert!(query.is_ok(), \"Query was empty\");\n assert_eq!(\n query.unwrap(),\n r#\"weather,location=us-midwest,season=summer temperature=82i 11\"#\n );\n }\n\n #[test]\n fn test_correct_query_type() {\n use crate::query::QueryType;\n\n let query = Timestamp::Hours(11)\n .into_query(\"weather\".to_string())\n .add_field(\"temperature\", 82)\n .add_tag(\"location\", \"us-midwest\")\n .add_tag(\"season\", \"summer\");\n\n assert_eq!(query.get_type(), QueryType::WriteQuery);\n }\n\n #[test]\n fn test_escaping() {\n let query = Timestamp::Hours(11)\n .into_query(\"wea, ther=\")\n .add_field(\"temperature\", 82)\n .add_field(\"\\\"temp=era,t ure\\\"\", r#\"too\"\\\\hot\"#)\n .add_field(\"float\", 82.0)\n .add_tag(\"location\", \"us-midwest\")\n .add_tag(\"loc, =\\\"ation\", r#\"us, \"mid=west\"#)\n .build();\n\n assert!(query.is_ok(), \"Query was empty\");\n let query_res = query.unwrap().get();\n #[allow(clippy::print_literal)]\n assert_eq!(\n query_res,\n r#\"wea\\,\\ ther=,location=us-midwest,loc\\,\\ \\=\"ation=us\\,\\ \\\"mid\\=west temperature=82i,\"temp\\=era\\,t\\ ure\"=\"too\\\"\\\\\\\\hot\",float=82 11\"#\n );\n }\n}\n","traces":[{"line":15,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":16,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":17,"address":[],"length":0,"stats":{"Line":8},"fn_name":null},{"line":22,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":23,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":24,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":40,"address":[4369616,4369711],"length":1,"stats":{"Line":3},"fn_name":"new"},{"line":45,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":46,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":47,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":62,"address":[4370256,4370333],"length":1,"stats":{"Line":7},"fn_name":"add_field<&str,i32>"},{"line":67,"address":[],"length":0,"stats":{"Line":21},"fn_name":null},{"line":68,"address":[],"length":0,"stats":{"Line":7},"fn_name":null},{"line":86,"address":[4370032,4370119],"length":1,"stats":{"Line":4},"fn_name":"add_tag<&str,core::option::Option>"},{"line":91,"address":[],"length":0,"stats":{"Line":12},"fn_name":null},{"line":92,"address":[],"length":0,"stats":{"Line":4},"fn_name":null},{"line":95,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":96,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":97,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":98,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":99,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":100,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":101,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":102,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":104,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":118,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":121,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":122,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":123,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":124,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":125,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":126,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":135,"address":[4872080,4871376,4871792,4871504,4871584,4871664,4871872,4872016,4871728,4871296,4871952,4871440],"length":1,"stats":{"Line":6},"fn_name":"from"},{"line":136,"address":[4871313,4871745,4871680,4871884,4871399,4871596,4871968,4872033,4871463,4871804,4871516,4872087],"length":1,"stats":{"Line":6},"fn_name":null},{"line":148,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":149,"address":[],"length":0,"stats":{"Line":2},"fn_name":null},{"line":156,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":157,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":162,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":163,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":164,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":165,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":169,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":170,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":172,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":173,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":174,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":175,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":176,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":182,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":183,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":185,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":186,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":188,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":189,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":190,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":191,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":192,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":198,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":199,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":200,"address":[],"length":0,"stats":{"Line":3},"fn_name":null},{"line":201,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":202,"address":[],"length":0,"stats":{"Line":0},"fn_name":null},{"line":203,"address":[],"length":0,"stats":{"Line":6},"fn_name":null},{"line":207,"address":[],"length":0,"stats":{"Line":1},"fn_name":null},{"line":208,"address":[],"length":0,"stats":{"Line":1},"fn_name":null}],"covered":46,"coverable":66},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","tests","derive_integration_tests.rs"],"content":"#[path = \"./utilities.rs\"]\nmod utilities;\n\n#[cfg(feature = \"derive\")]\nuse influxdb::InfluxDbWriteable;\n\nuse chrono::{DateTime, Utc};\nuse influxdb::{Query, Timestamp};\n\n#[cfg(feature = \"use-serde\")]\nuse serde::Deserialize;\n\nuse utilities::{assert_result_ok, create_client, create_db, delete_db, run_test};\n\n#[derive(Debug, PartialEq)]\n#[cfg_attr(feature = \"derive\", derive(InfluxDbWriteable))]\n#[cfg_attr(feature = \"use-serde\", derive(Deserialize))]\nstruct WeatherReading {\n time: DateTime,\n humidity: i32,\n #[tag]\n wind_strength: Option,\n}\n\n#[test]\nfn test_build_query() {\n let weather_reading = WeatherReading {\n time: Timestamp::Hours(1).into(),\n humidity: 30,\n wind_strength: Some(5),\n };\n let query = weather_reading\n .into_query(\"weather_reading\")\n .build()\n .unwrap();\n assert_eq!(\n query.get(),\n \"weather_reading,wind_strength=5 humidity=30i 3600000000000\"\n );\n}\n\n#[cfg(feature = \"derive\")]\n/// INTEGRATION TEST\n///\n/// This integration tests that writing data and retrieving the data again is working\n#[async_std::test]\nasync fn test_derive_simple_write() {\n const TEST_NAME: &str = \"test_derive_simple_write\";\n\n run_test(\n || async move {\n create_db(TEST_NAME).await.expect(\"could not setup db\");\n let client = create_client(TEST_NAME);\n let weather_reading = WeatherReading {\n time: Timestamp::Nanoseconds(0).into(),\n humidity: 30,\n wind_strength: Some(5),\n };\n let query = weather_reading.into_query(\"weather_reading\");\n let result = client.query(&query).await;\n assert!(result.is_ok(), \"unable to insert into db\");\n },\n || async move {\n delete_db(TEST_NAME).await.expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This integration tests that writing data and retrieving the data again is working\n#[cfg(feature = \"derive\")]\n#[cfg(feature = \"use-serde\")]\n#[async_std::test]\nasync fn test_write_and_read_option() {\n const TEST_NAME: &str = \"test_write_and_read_option\";\n\n run_test(\n || async move {\n create_db(TEST_NAME).await.expect(\"could not setup db\");\n let client = create_client(TEST_NAME);\n let weather_reading = WeatherReading {\n time: Timestamp::Hours(11).into(),\n humidity: 30,\n wind_strength: None,\n };\n let write_result = client\n .query(&weather_reading.into_query(\"weather_reading\".to_string()))\n .await;\n assert_result_ok(&write_result);\n let query =\n Query::raw_read_query(\"SELECT time, humidity, wind_strength FROM weather_reading\");\n let result = client.json_query(query).await.and_then(|mut db_result| {\n println!(\"{:?}\", db_result);\n db_result.deserialize_next::()\n });\n assert_result_ok(&result);\n let result = result.unwrap();\n assert_eq!(result.series[0].values[0].humidity, 30);\n assert_eq!(result.series[0].values[0].wind_strength, None);\n },\n || async move {\n delete_db(TEST_NAME).await.expect(\"could not clean up db\");\n },\n )\n .await;\n}\n","traces":[{"line":46,"address":[4571152,4571229,4571167],"length":1,"stats":{"Line":9},"fn_name":"drop_in_place"},{"line":51,"address":[4568960,4568805,4568709,4568688,4568812,4568935],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":52,"address":[4568791],"length":1,"stats":{"Line":4},"fn_name":null},{"line":53,"address":[4514462],"length":1,"stats":{"Line":1},"fn_name":null},{"line":54,"address":[4514650],"length":1,"stats":{"Line":1},"fn_name":null},{"line":55,"address":[4514488],"length":1,"stats":{"Line":1},"fn_name":null},{"line":57,"address":[4514626],"length":1,"stats":{"Line":1},"fn_name":null},{"line":59,"address":[4514723],"length":1,"stats":{"Line":1},"fn_name":null},{"line":60,"address":[4568871],"length":1,"stats":{"Line":5},"fn_name":null},{"line":61,"address":[4515262,4515242,4515302],"length":1,"stats":{"Line":2},"fn_name":null},{"line":63,"address":[4516698,4515959,4516080,4515936,4516489,4516688],"length":1,"stats":{"Line":6},"fn_name":"{{closure}}"},{"line":64,"address":[4516149,4516208,4516474,4516017],"length":1,"stats":{"Line":3},"fn_name":null},{"line":75,"address":[4569949,4569872,4569887],"length":1,"stats":{"Line":9},"fn_name":"drop_in_place"},{"line":80,"address":[4574707,4574368,4574685,4574483,4574586,4574604,4574389,4574490],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":81,"address":[4574467],"length":1,"stats":{"Line":4},"fn_name":null},{"line":82,"address":[4518158],"length":1,"stats":{"Line":1},"fn_name":null},{"line":83,"address":[4518347],"length":1,"stats":{"Line":1},"fn_name":null},{"line":84,"address":[4518185],"length":1,"stats":{"Line":1},"fn_name":null},{"line":86,"address":[4518335],"length":1,"stats":{"Line":1},"fn_name":null},{"line":88,"address":[4574545],"length":1,"stats":{"Line":4},"fn_name":null},{"line":89,"address":[4518593,4518428,4518549],"length":1,"stats":{"Line":3},"fn_name":null},{"line":90,"address":[4519025,4518637],"length":1,"stats":{"Line":1},"fn_name":null},{"line":91,"address":[4519082],"length":1,"stats":{"Line":1},"fn_name":null},{"line":93,"address":[4519096],"length":1,"stats":{"Line":1},"fn_name":null},{"line":94,"address":[4519125,4519205,4517312,4519314,4521037,4517385,4519388,4519264],"length":1,"stats":{"Line":6},"fn_name":"{{closure}}"},{"line":95,"address":[4517468,4517322,4517405],"length":1,"stats":{"Line":3},"fn_name":null},{"line":96,"address":[4517494],"length":1,"stats":{"Line":1},"fn_name":null},{"line":98,"address":[4519619],"length":1,"stats":{"Line":1},"fn_name":null},{"line":99,"address":[4519660],"length":1,"stats":{"Line":1},"fn_name":null},{"line":100,"address":[4520334,4519748,4519795,4520241,4519867,4520001],"length":1,"stats":{"Line":3},"fn_name":null},{"line":101,"address":[4520552,4520413,4520837,4520747,4519956,4520371],"length":1,"stats":{"Line":3},"fn_name":null},{"line":103,"address":[4521991,4522730,4522521,4522720,4521968,4522112],"length":1,"stats":{"Line":6},"fn_name":"{{closure}}"},{"line":104,"address":[4522049,4522181,4522506,4522240],"length":1,"stats":{"Line":3},"fn_name":null}],"covered":33,"coverable":33},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","tests","integration_tests.rs"],"content":"extern crate influxdb;\n\n#[path = \"./utilities.rs\"]\nmod utilities;\nuse utilities::{\n assert_result_err, assert_result_ok, create_client, create_db, delete_db, run_test,\n};\n\nuse influxdb::InfluxDbWriteable;\nuse influxdb::{Client, Error, Query, Timestamp};\n\n/// INTEGRATION TEST\n///\n/// This test case tests whether the InfluxDB server can be connected to and gathers info about it - tested with async_std\n#[async_std::test]\nasync fn test_ping_influx_db_async_std() {\n let client = create_client(\"notusedhere\");\n let result = client.ping().await;\n assert_result_ok(&result);\n\n let (build, version) = result.unwrap();\n assert!(!build.is_empty(), \"Build should not be empty\");\n assert!(!version.is_empty(), \"Build should not be empty\");\n\n println!(\"build: {} version: {}\", build, version);\n}\n\n/// INTEGRATION TEST\n///\n/// This test case tests whether the InfluxDB server can be connected to and gathers info about it * tested with tokio\n#[tokio::test]\nasync fn test_ping_influx_db_tokio() {\n let client = create_client(\"notusedhere\");\n let result = client.ping().await;\n assert_result_ok(&result);\n\n let (build, version) = result.unwrap();\n assert!(!build.is_empty(), \"Build should not be empty\");\n assert!(!version.is_empty(), \"Build should not be empty\");\n\n println!(\"build: {} version: {}\", build, version);\n}\n\n/// INTEGRATION TEST\n///\n/// This test case tests connection error\n#[async_std::test]\nasync fn test_connection_error() {\n let test_name = \"test_connection_error\";\n let client =\n Client::new(\"http://localhost:10086\", test_name).with_auth(\"nopriv_user\", \"password\");\n let read_query = Query::raw_read_query(\"SELECT * FROM weather\");\n let read_result = client.query(&read_query).await;\n assert_result_err(&read_result);\n match read_result {\n Err(Error::ConnectionError { .. }) => {}\n _ => panic!(format!(\n \"Should cause a ConnectionError: {}\",\n read_result.unwrap_err()\n )),\n }\n}\n\n/// INTEGRATION TEST\n///\n/// This test case tests the Authentication\n#[async_std::test]\nasync fn test_authed_write_and_read() {\n const TEST_NAME: &str = \"test_authed_write_and_read\";\n\n run_test(\n || async move {\n let client =\n Client::new(\"http://localhost:9086\", TEST_NAME).with_auth(\"admin\", \"password\");\n let query = format!(\"CREATE DATABASE {}\", TEST_NAME);\n client\n .query(&Query::raw_read_query(query))\n .await\n .expect(\"could not setup db\");\n\n let client =\n Client::new(\"http://localhost:9086\", TEST_NAME).with_auth(\"admin\", \"password\");\n let write_query = Timestamp::Hours(11)\n .into_query(\"weather\")\n .add_field(\"temperature\", 82);\n let write_result = client.query(&write_query).await;\n assert_result_ok(&write_result);\n\n let read_query = Query::raw_read_query(\"SELECT * FROM weather\");\n let read_result = client.query(&read_query).await;\n assert_result_ok(&read_result);\n assert!(\n !read_result.unwrap().contains(\"error\"),\n \"Data contained a database error\"\n );\n },\n || async move {\n let client =\n Client::new(\"http://localhost:9086\", TEST_NAME).with_auth(\"admin\", \"password\");\n let query = format!(\"DROP DATABASE {}\", TEST_NAME);\n\n client\n .query(&Query::raw_read_query(query))\n .await\n .expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This test case tests the Authentication\n#[async_std::test]\nasync fn test_wrong_authed_write_and_read() {\n const TEST_NAME: &str = \"test_wrong_authed_write_and_read\";\n\n run_test(\n || async move {\n let client =\n Client::new(\"http://localhost:9086\", TEST_NAME).with_auth(\"admin\", \"password\");\n let query = format!(\"CREATE DATABASE {}\", TEST_NAME);\n client\n .query(&Query::raw_read_query(query))\n .await\n .expect(\"could not setup db\");\n\n let client =\n Client::new(\"http://localhost:9086\", TEST_NAME).with_auth(\"wrong_user\", \"password\");\n let write_query = Timestamp::Hours(11)\n .into_query(\"weather\")\n .add_field(\"temperature\", 82);\n let write_result = client.query(&write_query).await;\n assert_result_err(&write_result);\n match write_result {\n Err(Error::AuthorizationError) => {}\n _ => panic!(format!(\n \"Should be an AuthorizationError: {}\",\n write_result.unwrap_err()\n )),\n }\n\n let read_query = Query::raw_read_query(\"SELECT * FROM weather\");\n let read_result = client.query(&read_query).await;\n assert_result_err(&read_result);\n match read_result {\n Err(Error::AuthorizationError) => {}\n _ => panic!(format!(\n \"Should be an AuthorizationError: {}\",\n read_result.unwrap_err()\n )),\n }\n\n let client = Client::new(\"http://localhost:9086\", TEST_NAME)\n .with_auth(\"nopriv_user\", \"password\");\n let read_query = Query::raw_read_query(\"SELECT * FROM weather\");\n let read_result = client.query(&read_query).await;\n assert_result_err(&read_result);\n match read_result {\n Err(Error::AuthenticationError) => {}\n _ => panic!(format!(\n \"Should be an AuthenticationError: {}\",\n read_result.unwrap_err()\n )),\n }\n },\n || async move {\n let client =\n Client::new(\"http://localhost:9086\", TEST_NAME).with_auth(\"admin\", \"password\");\n let query = format!(\"DROP DATABASE {}\", TEST_NAME);\n client\n .query(&Query::raw_read_query(query))\n .await\n .expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This test case tests the Authentication\n#[async_std::test]\nasync fn test_non_authed_write_and_read() {\n const TEST_NAME: &str = \"test_non_authed_write_and_read\";\n\n run_test(\n || async move {\n let client =\n Client::new(\"http://localhost:9086\", TEST_NAME).with_auth(\"admin\", \"password\");\n let query = format!(\"CREATE DATABASE {}\", TEST_NAME);\n client\n .query(&Query::raw_read_query(query))\n .await\n .expect(\"could not setup db\");\n let non_authed_client = Client::new(\"http://localhost:9086\", TEST_NAME);\n let write_query = Timestamp::Hours(11)\n .into_query(\"weather\")\n .add_field(\"temperature\", 82);\n let write_result = non_authed_client.query(&write_query).await;\n assert_result_err(&write_result);\n match write_result {\n Err(Error::AuthorizationError) => {}\n _ => panic!(format!(\n \"Should be an AuthorizationError: {}\",\n write_result.unwrap_err()\n )),\n }\n\n let read_query = Query::raw_read_query(\"SELECT * FROM weather\");\n let read_result = non_authed_client.query(&read_query).await;\n assert_result_err(&read_result);\n match read_result {\n Err(Error::AuthorizationError) => {}\n _ => panic!(format!(\n \"Should be an AuthorizationError: {}\",\n read_result.unwrap_err()\n )),\n }\n },\n || async move {\n let client =\n Client::new(\"http://localhost:9086\", TEST_NAME).with_auth(\"admin\", \"password\");\n let query = format!(\"DROP DATABASE {}\", TEST_NAME);\n client\n .query(&Query::raw_read_query(query))\n .await\n .expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This integration tests that writing data and retrieving the data again is working\n#[async_std::test]\nasync fn test_write_and_read_field() {\n const TEST_NAME: &str = \"test_write_field\";\n\n run_test(\n || async move {\n create_db(TEST_NAME).await.expect(\"could not setup db\");\n let client = create_client(TEST_NAME);\n let write_query = Timestamp::Hours(11)\n .into_query(\"weather\")\n .add_field(\"temperature\", 82);\n let write_result = client.query(&write_query).await;\n assert_result_ok(&write_result);\n\n let read_query = Query::raw_read_query(\"SELECT * FROM weather\");\n let read_result = client.query(&read_query).await;\n assert_result_ok(&read_result);\n assert!(\n !read_result.unwrap().contains(\"error\"),\n \"Data contained a database error\"\n );\n },\n || async move {\n delete_db(TEST_NAME).await.expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This integration tests that writing data and retrieving the data again is working\n#[async_std::test]\n#[cfg(feature = \"use-serde\")]\nasync fn test_write_and_read_option() {\n use serde::Deserialize;\n\n const TEST_NAME: &str = \"test_write_and_read_option\";\n\n run_test(\n || {\n async move {\n create_db(TEST_NAME).await.expect(\"could not setup db\");\n\n let client = create_client(TEST_NAME);\n // Todo: Convert this to derive based insert for easier comparison of structs\n let write_query = Timestamp::Hours(11)\n .into_query(\"weather\")\n .add_field(\"temperature\", 82)\n .add_field(\"wind_strength\", >::None);\n let write_result = client.query(&write_query).await;\n assert_result_ok(&write_result);\n\n #[derive(Deserialize, Debug, PartialEq)]\n struct Weather {\n time: String,\n // different order to verify field names\n // are being used instead of just order\n wind_strength: Option,\n temperature: i32,\n }\n\n let query =\n Query::raw_read_query(\"SELECT time, temperature, wind_strength FROM weather\");\n let result = client\n .json_query(query)\n .await\n .and_then(|mut db_result| db_result.deserialize_next::());\n assert_result_ok(&result);\n\n assert_eq!(\n result.unwrap().series[0].values[0],\n Weather {\n time: \"1970-01-01T11:00:00Z\".to_string(),\n temperature: 82,\n wind_strength: None,\n }\n );\n }\n },\n || async move {\n delete_db(\"test_write_and_read_option\")\n .await\n .expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This test case tests whether JSON can be decoded from a InfluxDB response and whether that JSON\n/// is equal to the data which was written to the database\n#[async_std::test]\n#[cfg(feature = \"use-serde\")]\nasync fn test_json_query() {\n use serde::Deserialize;\n\n const TEST_NAME: &str = \"test_json_query\";\n\n run_test(\n || async move {\n create_db(TEST_NAME).await.expect(\"could not setup db\");\n\n let client = create_client(TEST_NAME);\n\n let write_query = Timestamp::Hours(11)\n .into_query(\"weather\")\n .add_field(\"temperature\", 82);\n let write_result = client.query(&write_query).await;\n assert_result_ok(&write_result);\n\n #[derive(Deserialize, Debug, PartialEq)]\n struct Weather {\n time: String,\n temperature: i32,\n }\n\n let query = Query::raw_read_query(\"SELECT * FROM weather\");\n let result = client\n .json_query(query)\n .await\n .and_then(|mut db_result| db_result.deserialize_next::());\n assert_result_ok(&result);\n\n assert_eq!(\n result.unwrap().series[0].values[0],\n Weather {\n time: \"1970-01-01T11:00:00Z\".to_string(),\n temperature: 82\n }\n );\n },\n || async move {\n delete_db(TEST_NAME).await.expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This test case tests whether the response to a GROUP BY can be parsed by\n// deserialize_next_tagged into a tags struct\n#[async_std::test]\n#[cfg(feature = \"use-serde\")]\nasync fn test_json_query_tagged() {\n use serde::Deserialize;\n\n const TEST_NAME: &str = \"test_json_query_tagged\";\n\n run_test(\n || async move {\n create_db(TEST_NAME).await.expect(\"could not setup db\");\n\n let client = create_client(TEST_NAME);\n\n let write_query = Timestamp::Hours(11)\n .into_query(\"weather\")\n .add_tag(\"location\", \"London\")\n .add_field(\"temperature\", 82);\n let write_result = client.query(&write_query).await;\n assert_result_ok(&write_result);\n\n #[derive(Deserialize, Debug, PartialEq)]\n struct WeatherMeta {\n location: String,\n }\n\n #[derive(Deserialize, Debug, PartialEq)]\n struct Weather {\n time: String,\n temperature: i32,\n }\n\n let query = Query::raw_read_query(\"SELECT * FROM weather GROUP BY location\");\n let result = client.json_query(query).await.and_then(|mut db_result| {\n db_result.deserialize_next_tagged::()\n });\n assert_result_ok(&result);\n let result = result.unwrap();\n\n assert_eq!(\n result.series[0].tags,\n WeatherMeta {\n location: \"London\".to_string(),\n }\n );\n assert_eq!(\n result.series[0].values[0],\n Weather {\n time: \"1970-01-01T11:00:00Z\".to_string(),\n temperature: 82\n }\n );\n },\n || async move {\n delete_db(TEST_NAME).await.expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This test case tests whether JSON can be decoded from a InfluxDB response and wether that JSON\n/// is equal to the data which was written to the database\n/// (tested with tokio)\n#[tokio::test]\n#[cfg(feature = \"use-serde\")]\nasync fn test_json_query_vec() {\n use serde::Deserialize;\n\n const TEST_NAME: &str = \"test_json_query_vec\";\n\n run_test(\n || async move {\n create_db(TEST_NAME).await.expect(\"could not setup db\");\n\n let client = create_client(TEST_NAME);\n let write_query1 = Timestamp::Hours(11)\n .into_query(\"temperature_vec\")\n .add_field(\"temperature\", 16);\n let write_query2 = Timestamp::Hours(12)\n .into_query(\"temperature_vec\")\n .add_field(\"temperature\", 17);\n let write_query3 = Timestamp::Hours(13)\n .into_query(\"temperature_vec\")\n .add_field(\"temperature\", 18);\n\n let _write_result = client.query(&write_query1).await;\n let _write_result2 = client.query(&write_query2).await;\n let _write_result2 = client.query(&write_query3).await;\n\n #[derive(Deserialize, Debug, PartialEq)]\n struct Weather {\n time: String,\n temperature: i32,\n }\n\n let query = Query::raw_read_query(\"SELECT * FROM temperature_vec\");\n let result = client\n .json_query(query)\n .await\n .and_then(|mut db_result| db_result.deserialize_next::());\n assert_result_ok(&result);\n assert_eq!(result.unwrap().series[0].values.len(), 3);\n },\n || async move {\n delete_db(TEST_NAME).await.expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This integration test tests whether using the wrong query method fails building the query\n#[async_std::test]\n#[cfg(feature = \"use-serde\")]\nasync fn test_serde_multi_query() {\n use serde::Deserialize;\n\n const TEST_NAME: &str = \"test_serde_multi_query\";\n\n run_test(\n || async move {\n create_db(TEST_NAME).await.expect(\"could not setup db\");\n\n #[derive(Deserialize, Debug, PartialEq)]\n struct Temperature {\n time: String,\n temperature: i32,\n }\n\n #[derive(Deserialize, Debug, PartialEq)]\n struct Humidity {\n time: String,\n humidity: i32,\n }\n\n let client = create_client(TEST_NAME);\n let write_query = Timestamp::Hours(11)\n .into_query(\"temperature\")\n .add_field(\"temperature\", 16);\n let write_query2 = Timestamp::Hours(11)\n .into_query(\"humidity\")\n .add_field(\"humidity\", 69);\n\n let write_result = client.query(&write_query).await;\n let write_result2 = client.query(&write_query2).await;\n assert_result_ok(&write_result);\n assert_result_ok(&write_result2);\n\n let result = client\n .json_query(\n Query::raw_read_query(\"SELECT * FROM temperature\")\n .add_query(\"SELECT * FROM humidity\"),\n )\n .await\n .and_then(|mut db_result| {\n let temp = db_result.deserialize_next::()?;\n let humidity = db_result.deserialize_next::()?;\n\n Ok((temp, humidity))\n });\n assert_result_ok(&result);\n\n let (temp, humidity) = result.unwrap();\n assert_eq!(\n temp.series[0].values[0],\n Temperature {\n time: \"1970-01-01T11:00:00Z\".to_string(),\n temperature: 16\n },\n );\n assert_eq!(\n humidity.series[0].values[0],\n Humidity {\n time: \"1970-01-01T11:00:00Z\".to_string(),\n humidity: 69\n }\n );\n },\n || async move {\n delete_db(TEST_NAME).await.expect(\"could not clean up db\");\n },\n )\n .await;\n}\n\n/// INTEGRATION TEST\n///\n/// This integration test tests whether using the wrong query method fails building the query\n#[async_std::test]\n#[cfg(feature = \"use-serde\")]\nasync fn test_wrong_query_errors() {\n let client = create_client(\"test_name\");\n let result = client\n .json_query(Query::raw_read_query(\"CREATE DATABASE this_should_fail\"))\n .await;\n assert!(\n result.is_err(),\n \"Should only build SELECT and SHOW queries.\"\n );\n}\n","traces":[{"line":15,"address":[4723466,4723349,4723328],"length":1,"stats":{"Line":9},"fn_name":"drop_in_place"},{"line":17,"address":[5049953],"length":1,"stats":{"Line":1},"fn_name":null},{"line":18,"address":[4723428],"length":1,"stats":{"Line":4},"fn_name":null},{"line":19,"address":[5050411],"length":1,"stats":{"Line":1},"fn_name":null},{"line":21,"address":[5050447,5050548],"length":1,"stats":{"Line":2},"fn_name":null},{"line":25,"address":[5050911,5050771,5050969,5051058],"length":1,"stats":{"Line":4},"fn_name":null},{"line":31,"address":[4701205,4701322,4701184],"length":1,"stats":{"Line":9},"fn_name":"drop_in_place"},{"line":33,"address":[5051777],"length":1,"stats":{"Line":1},"fn_name":null},{"line":34,"address":[4701284],"length":1,"stats":{"Line":4},"fn_name":null},{"line":35,"address":[5052235],"length":1,"stats":{"Line":1},"fn_name":null},{"line":37,"address":[5052372,5052271],"length":1,"stats":{"Line":2},"fn_name":null},{"line":41,"address":[5052735,5052793,5052882,5052595],"length":1,"stats":{"Line":4},"fn_name":null},{"line":47,"address":[4701713,4701520,4701535],"length":1,"stats":{"Line":9},"fn_name":"drop_in_place"},{"line":49,"address":[5053601],"length":1,"stats":{"Line":1},"fn_name":null},{"line":50,"address":[5053636],"length":1,"stats":{"Line":1},"fn_name":null},{"line":52,"address":[5053742],"length":1,"stats":{"Line":1},"fn_name":null},{"line":53,"address":[4701650],"length":1,"stats":{"Line":5},"fn_name":null},{"line":54,"address":[5054199],"length":1,"stats":{"Line":1},"fn_name":null},{"line":56,"address":[5054336,5054235],"length":1,"stats":{"Line":2},"fn_name":null},{"line":67,"address":[4524032,4524039],"length":1,"stats":{"Line":9},"fn_name":"test_authed_write_and_read"},{"line":72,"address":[4737352,4737194,4737144,4736885,4737067,4737044,4736864,4737327],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":73,"address":[5055316],"length":1,"stats":{"Line":1},"fn_name":null},{"line":74,"address":[5055324],"length":1,"stats":{"Line":1},"fn_name":null},{"line":75,"address":[5055607,5055513,5055444],"length":1,"stats":{"Line":3},"fn_name":null},{"line":76,"address":[4737003],"length":1,"stats":{"Line":4},"fn_name":null},{"line":77,"address":[5055674],"length":1,"stats":{"Line":1},"fn_name":null},{"line":79,"address":[4736981,4737024],"length":1,"stats":{"Line":2},"fn_name":null},{"line":82,"address":[5056266],"length":1,"stats":{"Line":1},"fn_name":null},{"line":83,"address":[5056467,5056366],"length":1,"stats":{"Line":2},"fn_name":null},{"line":86,"address":[4737128],"length":1,"stats":{"Line":5},"fn_name":null},{"line":87,"address":[5056977],"length":1,"stats":{"Line":1},"fn_name":null},{"line":89,"address":[5057028],"length":1,"stats":{"Line":1},"fn_name":null},{"line":90,"address":[4737257],"length":1,"stats":{"Line":4},"fn_name":null},{"line":91,"address":[5057514],"length":1,"stats":{"Line":1},"fn_name":null},{"line":92,"address":[5057727,5057796,5057705],"length":1,"stats":{"Line":1},"fn_name":null},{"line":93,"address":[5057670,5057550,5057646],"length":1,"stats":{"Line":3},"fn_name":null},{"line":97,"address":[4724752,4724767,4724928,4724953],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":99,"address":[5058993],"length":1,"stats":{"Line":1},"fn_name":null},{"line":100,"address":[5059101,5059170,5059261],"length":1,"stats":{"Line":3},"fn_name":null},{"line":102,"address":[4724871],"length":1,"stats":{"Line":4},"fn_name":null},{"line":103,"address":[5059325],"length":1,"stats":{"Line":1},"fn_name":null},{"line":105,"address":[4724849,4724892],"length":1,"stats":{"Line":2},"fn_name":null},{"line":114,"address":[4524096,4524103],"length":1,"stats":{"Line":9},"fn_name":"test_wrong_authed_write_and_read"},{"line":119,"address":[4714998,4714814,4714665,4714642,4714464,4715219,4715244,4714485],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":120,"address":[5061030],"length":1,"stats":{"Line":1},"fn_name":null},{"line":121,"address":[5061060],"length":1,"stats":{"Line":1},"fn_name":null},{"line":122,"address":[5061180,5061258,5061361],"length":1,"stats":{"Line":3},"fn_name":null},{"line":123,"address":[4714601],"length":1,"stats":{"Line":4},"fn_name":null},{"line":124,"address":[5061428],"length":1,"stats":{"Line":1},"fn_name":null},{"line":126,"address":[4714622,4714579],"length":1,"stats":{"Line":2},"fn_name":null},{"line":129,"address":[5062038],"length":1,"stats":{"Line":1},"fn_name":null},{"line":130,"address":[5062239,5062138],"length":1,"stats":{"Line":2},"fn_name":null},{"line":133,"address":[4714738],"length":1,"stats":{"Line":5},"fn_name":null},{"line":134,"address":[5062772],"length":1,"stats":{"Line":1},"fn_name":null},{"line":136,"address":[5062951,5062839],"length":1,"stats":{"Line":2},"fn_name":null},{"line":137,"address":[5063072,5063214,5063163,5063008,5063095],"length":1,"stats":{"Line":0},"fn_name":null},{"line":139,"address":[5062861],"length":1,"stats":{"Line":0},"fn_name":null},{"line":143,"address":[5062969],"length":1,"stats":{"Line":1},"fn_name":null},{"line":144,"address":[4714905],"length":1,"stats":{"Line":4},"fn_name":null},{"line":145,"address":[5063751],"length":1,"stats":{"Line":1},"fn_name":null},{"line":147,"address":[5063818,5063930],"length":1,"stats":{"Line":2},"fn_name":null},{"line":148,"address":[5064197,5064055,5064146,5063991,5064078],"length":1,"stats":{"Line":0},"fn_name":null},{"line":150,"address":[5063840],"length":1,"stats":{"Line":0},"fn_name":null},{"line":154,"address":[5063940,5064283],"length":1,"stats":{"Line":2},"fn_name":null},{"line":156,"address":[5064345],"length":1,"stats":{"Line":1},"fn_name":null},{"line":157,"address":[4715105],"length":1,"stats":{"Line":5},"fn_name":null},{"line":158,"address":[5064861],"length":1,"stats":{"Line":1},"fn_name":null},{"line":160,"address":[5064897,5064998],"length":1,"stats":{"Line":2},"fn_name":null},{"line":161,"address":[5065043,5065196,5065105,5065247,5065128],"length":1,"stats":{"Line":0},"fn_name":null},{"line":163,"address":[5064912],"length":1,"stats":{"Line":0},"fn_name":null},{"line":167,"address":[4704240,4704064,4704265,4704079],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":169,"address":[5067201],"length":1,"stats":{"Line":1},"fn_name":null},{"line":170,"address":[5067378,5067309,5067469],"length":1,"stats":{"Line":3},"fn_name":null},{"line":171,"address":[4704183],"length":1,"stats":{"Line":4},"fn_name":null},{"line":172,"address":[5067533],"length":1,"stats":{"Line":1},"fn_name":null},{"line":174,"address":[4704204,4704161],"length":1,"stats":{"Line":2},"fn_name":null},{"line":183,"address":[4524167,4524160],"length":1,"stats":{"Line":9},"fn_name":"test_non_authed_write_and_read"},{"line":188,"address":[4733991,4733643,4733620,4733440,4733792,4733461,4733966],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":189,"address":[5069246],"length":1,"stats":{"Line":1},"fn_name":null},{"line":190,"address":[5069261],"length":1,"stats":{"Line":1},"fn_name":null},{"line":191,"address":[5069450,5069381,5069544],"length":1,"stats":{"Line":3},"fn_name":null},{"line":192,"address":[4733579],"length":1,"stats":{"Line":4},"fn_name":null},{"line":193,"address":[5069611],"length":1,"stats":{"Line":1},"fn_name":null},{"line":195,"address":[4733600,4733557],"length":1,"stats":{"Line":2},"fn_name":null},{"line":196,"address":[5070211],"length":1,"stats":{"Line":1},"fn_name":null},{"line":197,"address":[5070250],"length":1,"stats":{"Line":1},"fn_name":null},{"line":200,"address":[4733716],"length":1,"stats":{"Line":5},"fn_name":null},{"line":201,"address":[5070879],"length":1,"stats":{"Line":1},"fn_name":null},{"line":203,"address":[5070946,5071058],"length":1,"stats":{"Line":2},"fn_name":null},{"line":204,"address":[5071202,5071270,5071115,5071179,5071321],"length":1,"stats":{"Line":0},"fn_name":null},{"line":206,"address":[5070968],"length":1,"stats":{"Line":0},"fn_name":null},{"line":210,"address":[5071076],"length":1,"stats":{"Line":1},"fn_name":null},{"line":211,"address":[4733877],"length":1,"stats":{"Line":4},"fn_name":null},{"line":212,"address":[5071855],"length":1,"stats":{"Line":1},"fn_name":null},{"line":214,"address":[5071891,5071992],"length":1,"stats":{"Line":2},"fn_name":null},{"line":215,"address":[5072188,5072099,5072037,5072122,5072239],"length":1,"stats":{"Line":0},"fn_name":null},{"line":217,"address":[5071906],"length":1,"stats":{"Line":0},"fn_name":null},{"line":221,"address":[4707968,4707807,4707993,4707792],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":223,"address":[5073697],"length":1,"stats":{"Line":1},"fn_name":null},{"line":224,"address":[5073874,5073965,5073805],"length":1,"stats":{"Line":3},"fn_name":null},{"line":225,"address":[4707911],"length":1,"stats":{"Line":4},"fn_name":null},{"line":226,"address":[5074029],"length":1,"stats":{"Line":1},"fn_name":null},{"line":228,"address":[4707932,4707889],"length":1,"stats":{"Line":2},"fn_name":null},{"line":237,"address":[4524224,4524231],"length":1,"stats":{"Line":9},"fn_name":"test_write_and_read_field"},{"line":242,"address":[4726060,4725936,4726302,4726131,4725957,4726053,4726327,4726172],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":243,"address":[4726037],"length":1,"stats":{"Line":4},"fn_name":null},{"line":244,"address":[5076175],"length":1,"stats":{"Line":1},"fn_name":null},{"line":245,"address":[5076199],"length":1,"stats":{"Line":1},"fn_name":null},{"line":248,"address":[4726115],"length":1,"stats":{"Line":5},"fn_name":null},{"line":249,"address":[5076745],"length":1,"stats":{"Line":1},"fn_name":null},{"line":251,"address":[5076790],"length":1,"stats":{"Line":1},"fn_name":null},{"line":252,"address":[4726232],"length":1,"stats":{"Line":4},"fn_name":null},{"line":253,"address":[5077238],"length":1,"stats":{"Line":1},"fn_name":null},{"line":254,"address":[5077517,5077451,5077429],"length":1,"stats":{"Line":1},"fn_name":null},{"line":255,"address":[5077370,5077394,5077274],"length":1,"stats":{"Line":3},"fn_name":null},{"line":259,"address":[4740223,4740208,4740287,4740309],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":260,"address":[4740278],"length":1,"stats":{"Line":3},"fn_name":null},{"line":269,"address":[4524295,4524288],"length":1,"stats":{"Line":9},"fn_name":"test_write_and_read_option"},{"line":277,"address":[5083536],"length":1,"stats":{"Line":1},"fn_name":"{{closure}}"},{"line":278,"address":[4704682,4704469,4704765,4704563,4704787,4704641,4704570,4704448],"length":1,"stats":{"Line":5},"fn_name":"drop_in_place"},{"line":279,"address":[4704547],"length":1,"stats":{"Line":4},"fn_name":null},{"line":281,"address":[5080478],"length":1,"stats":{"Line":1},"fn_name":null},{"line":283,"address":[5080680,5080505],"length":1,"stats":{"Line":2},"fn_name":null},{"line":286,"address":[5080660],"length":1,"stats":{"Line":1},"fn_name":null},{"line":287,"address":[4704625],"length":1,"stats":{"Line":5},"fn_name":null},{"line":288,"address":[5081169],"length":1,"stats":{"Line":1},"fn_name":null},{"line":290,"address":[4529824,4529888,4529674,4529097,4529909,4529603,4529845,4529184,4529745,4529424,4529485,4528944,4529337],"length":1,"stats":{"Line":10},"fn_name":"eq"},{"line":292,"address":[4529447,4529033,4529273,4529593,4529198,4529233,4528993,4528958],"length":1,"stats":{"Line":3},"fn_name":null},{"line":295,"address":[4529458,4529241,4529206,4529111,4529399,4529664,4529001,4529160,4529351,4528966],"length":1,"stats":{"Line":4},"fn_name":null},{"line":296,"address":[4529065,4529016,4529256,4529147,4529473,4529735,4529305,4529386,4528981,4529221],"length":1,"stats":{"Line":4},"fn_name":null},{"line":300,"address":[5081212],"length":1,"stats":{"Line":1},"fn_name":null},{"line":301,"address":[4704720],"length":1,"stats":{"Line":5},"fn_name":null},{"line":302,"address":[5081241],"length":1,"stats":{"Line":1},"fn_name":null},{"line":304,"address":[5079776,5079792,5081704],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":305,"address":[5081720],"length":1,"stats":{"Line":1},"fn_name":null},{"line":307,"address":[5082402,5082491,5082160,5082193,5082063,5081890],"length":1,"stats":{"Line":3},"fn_name":null},{"line":308,"address":[5081849,5081761,5081914],"length":1,"stats":{"Line":3},"fn_name":null},{"line":309,"address":[5081983],"length":1,"stats":{"Line":1},"fn_name":null},{"line":310,"address":[5081944],"length":1,"stats":{"Line":1},"fn_name":null},{"line":312,"address":[5081971],"length":1,"stats":{"Line":1},"fn_name":null},{"line":317,"address":[4724160,4724239,4724261,4724175],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":318,"address":[4724230],"length":1,"stats":{"Line":3},"fn_name":null},{"line":320,"address":[5084054],"length":1,"stats":{"Line":1},"fn_name":null},{"line":330,"address":[4524352,4524359],"length":1,"stats":{"Line":9},"fn_name":"test_json_query"},{"line":338,"address":[4737957,4737936,4738058,4738051,4738253,4738129,4738170,4738275],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":339,"address":[4738035],"length":1,"stats":{"Line":4},"fn_name":null},{"line":341,"address":[5085662],"length":1,"stats":{"Line":1},"fn_name":null},{"line":343,"address":[5085689],"length":1,"stats":{"Line":1},"fn_name":null},{"line":346,"address":[4738113],"length":1,"stats":{"Line":5},"fn_name":null},{"line":347,"address":[5086283],"length":1,"stats":{"Line":1},"fn_name":null},{"line":349,"address":[4528837,4528224,4528816,4528549,4528481,4528512,4528337,4528368,4528880,4528901,4528671,4528742],"length":1,"stats":{"Line":10},"fn_name":"eq"},{"line":351,"address":[4528402,4528661,4528382,4528529,4528238,4528258,4528283,4528427],"length":1,"stats":{"Line":3},"fn_name":null},{"line":352,"address":[4528355,4528361,4528732,4528505,4528246,4528390,4528305,4528266,4528410,4528499,4528449,4528537],"length":1,"stats":{"Line":4},"fn_name":null},{"line":355,"address":[5086326],"length":1,"stats":{"Line":1},"fn_name":null},{"line":356,"address":[4738208],"length":1,"stats":{"Line":5},"fn_name":null},{"line":357,"address":[5086355],"length":1,"stats":{"Line":1},"fn_name":null},{"line":359,"address":[5084960,5084976,5086818],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":360,"address":[5086834],"length":1,"stats":{"Line":1},"fn_name":null},{"line":362,"address":[5087230,5087004,5087561,5087472,5087133,5087263],"length":1,"stats":{"Line":3},"fn_name":null},{"line":363,"address":[5086875,5087028,5086963],"length":1,"stats":{"Line":3},"fn_name":null},{"line":364,"address":[5087085],"length":1,"stats":{"Line":1},"fn_name":null},{"line":365,"address":[5087058],"length":1,"stats":{"Line":1},"fn_name":null},{"line":370,"address":[4702575,4702661,4702639,4702560],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":371,"address":[4702630],"length":1,"stats":{"Line":3},"fn_name":null},{"line":381,"address":[4524416,4524423],"length":1,"stats":{"Line":9},"fn_name":"test_json_query_tagged"},{"line":389,"address":[4738781,4738586,4738485,4738579,4738657,4738698,4738464,4738803],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":390,"address":[4738563],"length":1,"stats":{"Line":4},"fn_name":null},{"line":392,"address":[5090718],"length":1,"stats":{"Line":1},"fn_name":null},{"line":394,"address":[5090915,5090745],"length":1,"stats":{"Line":2},"fn_name":null},{"line":398,"address":[4738641],"length":1,"stats":{"Line":4},"fn_name":null},{"line":399,"address":[5091397],"length":1,"stats":{"Line":1},"fn_name":null},{"line":401,"address":[4527888,4527792,4527829,4528160,4528181,4527840,4527877,4528025,4527839,4527887,4527910,4528096,4528117],"length":1,"stats":{"Line":10},"fn_name":"eq"},{"line":403,"address":[4527806,4527902,4528015,4527854],"length":1,"stats":{"Line":1},"fn_name":null},{"line":406,"address":[4527185,4527728,4527749,4527072,4527664,4527397,4527519,4527685,4527216,4527360,4527329,4527590],"length":1,"stats":{"Line":10},"fn_name":"eq"},{"line":408,"address":[4527275,4527106,4527230,4527509,4527250,4527377,4527086,4527131],"length":1,"stats":{"Line":3},"fn_name":null},{"line":409,"address":[4527258,4527114,4527094,4527297,4527347,4527238,4527353,4527385,4527209,4527580,4527153,4527203],"length":1,"stats":{"Line":4},"fn_name":null},{"line":412,"address":[5091440],"length":1,"stats":{"Line":1},"fn_name":null},{"line":413,"address":[4738736],"length":1,"stats":{"Line":6},"fn_name":null},{"line":414,"address":[5090032],"length":1,"stats":{"Line":1},"fn_name":null},{"line":416,"address":[5091960],"length":1,"stats":{"Line":1},"fn_name":null},{"line":417,"address":[5092001],"length":1,"stats":{"Line":1},"fn_name":null},{"line":419,"address":[5092346,5092237,5092721,5092136,5092379,5092628],"length":1,"stats":{"Line":4},"fn_name":null},{"line":420,"address":[5092089],"length":1,"stats":{"Line":1},"fn_name":null},{"line":421,"address":[5092197],"length":1,"stats":{"Line":1},"fn_name":null},{"line":422,"address":[5092140],"length":1,"stats":{"Line":1},"fn_name":null},{"line":425,"address":[5092995,5092898,5093028,5093238,5093328],"length":1,"stats":{"Line":3},"fn_name":null},{"line":426,"address":[5092750],"length":1,"stats":{"Line":1},"fn_name":null},{"line":427,"address":[5092850],"length":1,"stats":{"Line":1},"fn_name":null},{"line":428,"address":[5092823],"length":1,"stats":{"Line":1},"fn_name":null},{"line":433,"address":[4729856,4729957,4729871,4729935],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":434,"address":[4729926],"length":1,"stats":{"Line":3},"fn_name":null},{"line":445,"address":[4524480,4524487],"length":1,"stats":{"Line":9},"fn_name":"test_json_query_vec"},{"line":453,"address":[4741498,4741292,4741575,4741626,4741732,4741754,4741407,4741552,4741285,4741189,4741649,4741168],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":454,"address":[4741269],"length":1,"stats":{"Line":4},"fn_name":null},{"line":456,"address":[5096654],"length":1,"stats":{"Line":1},"fn_name":null},{"line":457,"address":[5096681],"length":1,"stats":{"Line":1},"fn_name":null},{"line":460,"address":[5096939,5096841],"length":1,"stats":{"Line":2},"fn_name":null},{"line":463,"address":[5097109,5097011],"length":1,"stats":{"Line":2},"fn_name":null},{"line":467,"address":[4741391],"length":1,"stats":{"Line":5},"fn_name":null},{"line":468,"address":[4741536],"length":1,"stats":{"Line":5},"fn_name":null},{"line":469,"address":[4741610],"length":1,"stats":{"Line":5},"fn_name":null},{"line":471,"address":[4527029,4527008,4526944,4526965,4526870,4526352,4526799,4526465,4526640,4526609,4526496,4526677],"length":1,"stats":{"Line":8},"fn_name":"eq"},{"line":473,"address":[4526411,4526789,4526366,4526386,4526555,4526530,4526657,4526510],"length":1,"stats":{"Line":0},"fn_name":null},{"line":474,"address":[4526633,4526483,4526518,4526577,4526374,4526489,4526860,4526627,4526665,4526538,4526433,4526394],"length":1,"stats":{"Line":0},"fn_name":null},{"line":477,"address":[5098469],"length":1,"stats":{"Line":1},"fn_name":null},{"line":478,"address":[4741687],"length":1,"stats":{"Line":5},"fn_name":null},{"line":479,"address":[5098523],"length":1,"stats":{"Line":1},"fn_name":null},{"line":481,"address":[5098986,5095952,5095968],"length":1,"stats":{"Line":3},"fn_name":"{{closure}}"},{"line":482,"address":[5099002],"length":1,"stats":{"Line":1},"fn_name":null},{"line":483,"address":[5099131,5099172,5099043,5099548,5099638,5099196],"length":1,"stats":{"Line":3},"fn_name":null},{"line":485,"address":[4704976,4705077,4704991,4705055],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":486,"address":[4705046],"length":1,"stats":{"Line":3},"fn_name":null},{"line":495,"address":[4524784,4524791],"length":1,"stats":{"Line":9},"fn_name":"test_serde_multi_query"},{"line":503,"address":[4703211,4703125,4703102,4703051,4702892,4702789,4702885,4702985,4703233,4702768],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":504,"address":[4702869],"length":1,"stats":{"Line":4},"fn_name":null},{"line":506,"address":[4526224,4525745,4525920,4526079,4525889,4525776,4525632,4525957,4526150,4526245,4526309,4526288],"length":1,"stats":{"Line":10},"fn_name":"eq"},{"line":508,"address":[4525790,4525835,4525666,4526069,4525810,4525937,4525646,4525691],"length":1,"stats":{"Line":3},"fn_name":null},{"line":509,"address":[4525913,4525818,4526140,4525769,4525674,4525857,4525907,4525798,4525945,4525763,4525713,4525654],"length":1,"stats":{"Line":4},"fn_name":null},{"line":512,"address":[4525025,4525237,4524912,4525200,4525056,4525430,4525359,4525504,4525568,4525169,4525525,4525589],"length":1,"stats":{"Line":10},"fn_name":"eq"},{"line":514,"address":[4524971,4525349,4525217,4524946,4525070,4525115,4524926,4525090],"length":1,"stats":{"Line":3},"fn_name":null},{"line":515,"address":[4524934,4525225,4525137,4525098,4524993,4524954,4525049,4525078,4525420,4525187,4525193,4525043],"length":1,"stats":{"Line":4},"fn_name":null},{"line":518,"address":[5103998],"length":1,"stats":{"Line":1},"fn_name":null},{"line":519,"address":[5104025],"length":1,"stats":{"Line":1},"fn_name":null},{"line":522,"address":[5104185,5104283],"length":1,"stats":{"Line":2},"fn_name":null},{"line":526,"address":[4702969],"length":1,"stats":{"Line":5},"fn_name":null},{"line":527,"address":[4703086],"length":1,"stats":{"Line":5},"fn_name":null},{"line":528,"address":[5105226],"length":1,"stats":{"Line":1},"fn_name":null},{"line":529,"address":[5105277],"length":1,"stats":{"Line":1},"fn_name":null},{"line":531,"address":[4703166],"length":1,"stats":{"Line":5},"fn_name":null},{"line":533,"address":[5105340,5105303],"length":1,"stats":{"Line":2},"fn_name":null},{"line":537,"address":[5102504,5102464],"length":1,"stats":{"Line":1},"fn_name":"{{closure}}"},{"line":538,"address":[5102749,5102529,5102640,5102549,5102484],"length":1,"stats":{"Line":3},"fn_name":null},{"line":539,"address":[5102802,5103173,5102630,5103294],"length":1,"stats":{"Line":2},"fn_name":null},{"line":541,"address":[5102927],"length":1,"stats":{"Line":1},"fn_name":null},{"line":543,"address":[5105838],"length":1,"stats":{"Line":1},"fn_name":null},{"line":545,"address":[5105983,5105879],"length":1,"stats":{"Line":2},"fn_name":null},{"line":546,"address":[5106722,5106386,5106353,5106244,5106632],"length":1,"stats":{"Line":3},"fn_name":null},{"line":547,"address":[5106129,5106047],"length":1,"stats":{"Line":2},"fn_name":null},{"line":548,"address":[5106193],"length":1,"stats":{"Line":1},"fn_name":null},{"line":549,"address":[5106166],"length":1,"stats":{"Line":1},"fn_name":null},{"line":553,"address":[5106899,5107238,5106996,5107327,5107029],"length":1,"stats":{"Line":3},"fn_name":null},{"line":554,"address":[5106751],"length":1,"stats":{"Line":1},"fn_name":null},{"line":555,"address":[5106851],"length":1,"stats":{"Line":1},"fn_name":null},{"line":556,"address":[5106824],"length":1,"stats":{"Line":1},"fn_name":null},{"line":561,"address":[4740079,4740064,4740143,4740165],"length":1,"stats":{"Line":6},"fn_name":"drop_in_place"},{"line":562,"address":[4740134],"length":1,"stats":{"Line":3},"fn_name":null},{"line":571,"address":[4524855,4524848],"length":1,"stats":{"Line":9},"fn_name":"test_wrong_query_errors"},{"line":574,"address":[5110337],"length":1,"stats":{"Line":1},"fn_name":null},{"line":575,"address":[4727078],"length":1,"stats":{"Line":4},"fn_name":null},{"line":576,"address":[5110366],"length":1,"stats":{"Line":1},"fn_name":null}],"covered":238,"coverable":250},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb","tests","utilities.rs"],"content":"use futures::prelude::*;\nuse influxdb::{Client, Error, Query};\nuse std::panic::{AssertUnwindSafe, UnwindSafe};\n\n#[allow(dead_code)]\npub fn assert_result_err(result: &Result) {\n result.as_ref().expect_err(\"assert_result_err failed\");\n}\n\npub fn assert_result_ok(result: &Result) {\n result.as_ref().expect(\"assert_result_ok failed\");\n}\n\npub fn create_client(db_name: T) -> Client\nwhere\n T: Into,\n{\n Client::new(\"http://localhost:8086\", db_name)\n}\n\npub async fn create_db(name: T) -> Result\nwhere\n T: Into,\n{\n let test_name = name.into();\n let query = format!(\"CREATE DATABASE {}\", test_name);\n create_client(test_name)\n .query(&Query::raw_read_query(query))\n .await\n}\n\npub async fn delete_db(name: T) -> Result\nwhere\n T: Into,\n{\n let test_name = name.into();\n let query = format!(\"DROP DATABASE {}\", test_name);\n create_client(test_name)\n .query(&Query::raw_read_query(query))\n .await\n}\n\npub async fn run_test(test_fn: F, teardown: T)\nwhere\n F: FnOnce() -> Fut1 + UnwindSafe,\n T: FnOnce() -> Fut2,\n Fut1: Future,\n Fut2: Future,\n{\n let test_result = AssertUnwindSafe(test_fn()).catch_unwind().await;\n AssertUnwindSafe(teardown())\n .catch_unwind()\n .await\n .expect(\"failed teardown\");\n test_result.expect(\"failed test\");\n}\n","traces":[{"line":6,"address":[4270608],"length":1,"stats":{"Line":1},"fn_name":"assert_result_err"},{"line":7,"address":[4270617],"length":1,"stats":{"Line":1},"fn_name":null},{"line":10,"address":[4271088,4270928,4271168,4271008,4270848,4270688,4270768],"length":1,"stats":{"Line":9},"fn_name":"assert_result_ok,influxdb::error::Error>"},{"line":11,"address":[4270937,4270857,4270697,4271017,4270777,4271177,4271097],"length":1,"stats":{"Line":9},"fn_name":null},{"line":14,"address":[4530800,4530720],"length":1,"stats":{"Line":4},"fn_name":"create_client"},{"line":18,"address":[4271277,4271342],"length":1,"stats":{"Line":4},"fn_name":null},{"line":21,"address":[4530880,4531060],"length":1,"stats":{"Line":4},"fn_name":"create_db<&str>"},{"line":25,"address":[4271611],"length":1,"stats":{"Line":2},"fn_name":null},{"line":26,"address":[4531314,4531129,4531222],"length":1,"stats":{"Line":6},"fn_name":null},{"line":27,"address":[4531375,4531750,4532037,4531606,4531563,4531685],"length":1,"stats":{"Line":10},"fn_name":null},{"line":28,"address":[4531430,4531544],"length":1,"stats":{"Line":4},"fn_name":null},{"line":32,"address":[4532368,4532548],"length":1,"stats":{"Line":4},"fn_name":"delete_db<&str>"},{"line":36,"address":[4532571],"length":1,"stats":{"Line":2},"fn_name":null},{"line":37,"address":[4532617,4532710,4532802],"length":1,"stats":{"Line":6},"fn_name":null},{"line":38,"address":[4533051,4533525,4532863,4533094,4533238,4533173],"length":1,"stats":{"Line":10},"fn_name":null},{"line":39,"address":[4533032,4532918],"length":1,"stats":{"Line":4},"fn_name":null},{"line":43,"address":[4533904,4534041,4535465,4533856],"length":1,"stats":{"Line":22},"fn_name":"run_test,core::future::from_generator::GenFuture>"},{"line":50,"address":[4534336,4535619,4535695,4535760,4536436,4534195,4534271,4535485,4535012,4534061],"length":1,"stats":{"Line":44},"fn_name":null},{"line":51,"address":[4536150,4534726,4534661,4534454,4534578,4534617,4534532,4535878,4536002,4535030,4536085,4536454,4536041,4535956],"length":1,"stats":{"Line":66},"fn_name":null},{"line":55,"address":[4536308,4534884],"length":1,"stats":{"Line":11},"fn_name":null}],"covered":20,"coverable":20},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb_derive","src","lib.rs"],"content":"use proc_macro::TokenStream;\nuse proc_macro2::TokenStream as TokenStream2;\nuse quote::quote;\n\nmod writeable;\nuse writeable::expand_writeable;\n\nfn krate() -> TokenStream2 {\n quote!(::influxdb)\n}\n\n#[proc_macro_derive(InfluxDbWriteable, attributes(tag))]\npub fn derive_writeable(tokens: TokenStream) -> TokenStream {\n expand_writeable(tokens)\n}\n","traces":[],"covered":0,"coverable":0},{"path":["/","home","runner","work","influxdb-rust","influxdb-rust","influxdb_derive","src","writeable.rs"],"content":"use proc_macro::TokenStream;\nuse proc_macro2::TokenStream as TokenStream2;\nuse quote::{format_ident, quote};\nuse syn::{parse_macro_input, Field, Fields, Ident, ItemStruct};\n\nstruct WriteableField {\n ident: Ident,\n is_tag: bool,\n}\n\nimpl From for WriteableField {\n fn from(field: Field) -> WriteableField {\n let ident = field.ident.expect(\"fields without ident are not supported\");\n let is_tag = field.attrs.iter().any(|attr| {\n attr.path\n .segments\n .iter()\n .last()\n .map(|seg| seg.ident.to_string())\n .unwrap_or_default()\n == \"tag\"\n });\n WriteableField { ident, is_tag }\n }\n}\n\npub fn expand_writeable(tokens: TokenStream) -> TokenStream {\n let krate = super::krate();\n\n let input = parse_macro_input!(tokens as ItemStruct);\n let ident = input.ident;\n let generics = input.generics;\n\n let time_field = format_ident!(\"time\");\n #[allow(clippy::cmp_owned)] // that's not how idents work clippy\n let fields: Vec = match input.fields {\n Fields::Named(fields) => fields\n .named\n .into_iter()\n .map(WriteableField::from)\n .filter(|field| field.ident.to_string() != time_field.to_string())\n .map(|field| {\n let ident = field.ident;\n #[allow(clippy::match_bool)]\n match field.is_tag {\n true => quote!(query.add_tag(stringify!(#ident), self.#ident)),\n false => quote!(query.add_field(stringify!(#ident), self.#ident)),\n }\n })\n .collect(),\n _ => panic!(\"a struct without named fields is not supported\"),\n };\n\n let output = quote! {\n impl #generics #krate::InfluxDbWriteable for #ident #generics\n {\n fn into_query>(self, name : I) -> #krate::WriteQuery\n {\n let timestamp : #krate::Timestamp = self.#time_field.into();\n let mut query = timestamp.into_query(name);\n #(\n query = #fields;\n )*\n query\n }\n }\n };\n output.into()\n}\n","traces":[],"covered":0,"coverable":0}]} \ No newline at end of file From 20ad7e54294c432b541424202ce99fa1eb7ee4bf Mon Sep 17 00:00:00 2001 From: Empty2k12 Date: Tue, 15 Dec 2020 13:53:49 +0000 Subject: [PATCH 03/42] GitHub Pages for 5ed13476ca5e2dafb6f02c787a9bc30b05961dfd --- coverage.svg | 2 +- tarpaulin-report.html | 2 +- tarpaulin-report.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/coverage.svg b/coverage.svg index c08718d..b82026b 100644 --- a/coverage.svg +++ b/coverage.svg @@ -1 +1 @@ -coverage: 82.17%coverage82.17% \ No newline at end of file +coverage: 70.81%coverage70.81% \ No newline at end of file diff --git a/tarpaulin-report.html b/tarpaulin-report.html index 24dd223..02e7a3b 100644 --- a/tarpaulin-report.html +++ b/tarpaulin-report.html @@ -107,7 +107,7 @@