Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ required-features = ["rustls-tls"]

[[example]]
name = "data_types_derive_simple"
required-features = ["time", "uuid", "chrono"]
required-features = ["time", "uuid", "chrono", "jiff"]

[[example]]
name = "data_types_variant"
required-features = ["time"]

[[example]]
name = "time_types_example"
required-features = ["time", "chrono"]
required-features = ["time", "chrono", "jiff"]

[profile.release]
debug = true
Expand All @@ -94,6 +94,7 @@ uuid = ["dep:uuid"]
time = ["dep:time"]
lz4 = ["dep:lz4_flex", "dep:cityhash-rs"]
chrono = ["dep:chrono"]
jiff = ["dep:jiff"]
futures03 = []

## TLS
Expand Down Expand Up @@ -148,6 +149,7 @@ cityhash-rs = { version = "=1.0.1", optional = true } # exact version for safety
uuid = { version = "1", optional = true }
time = { version = "0.3", optional = true }
chrono = { version = "0.4", optional = true, features = ["serde"] }
jiff = { version = "0.2", optional = true }
bstr = { version = "1.11.0", default-features = false }
quanta = { version = "0.12", optional = true }
replace_with = { version = "0.1.7" }
Expand Down
80 changes: 66 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ client.query("DROP TABLE IF EXISTS some").execute().await?;
* `uuid` — adds `serde::uuid` to work with [uuid](https://docs.rs/uuid) crate.
* `time` — adds `serde::time` to work with [time](https://docs.rs/time) crate.
* `chrono` — adds `serde::chrono` to work with [chrono](https://docs.rs/chrono) crate.
* `jiff` — adds `serde::jiff` to work with [jiff](https://docs.rs/jiff) crate.

### TLS
By default, TLS is disabled and one or more following features must be enabled to use HTTPS urls:
Expand Down Expand Up @@ -316,6 +317,7 @@ How to choose between all these features? Here are some considerations:
* `Date` maps to/from `u16` or a newtype around it and represents a number of days elapsed since `1970-01-01`. The following external types are supported:
* [`time::Date`](https://docs.rs/time/latest/time/struct.Date.html) is supported by using `serde::time::date`, requiring the `time` feature.
* [`chrono::NaiveDate`](https://docs.rs/chrono/latest/chrono/struct.NaiveDate.html) is supported by using `serde::chrono::date`, requiring the `chrono` feature.
* [`jiff::civil::Date`](https://docs.rs/jiff/latest/jiff/civil/struct.Date.html) is supported by using `serde::jiff::date`, requiring the `jiff` feature.
<details>
<summary>Example</summary>

Expand All @@ -324,17 +326,21 @@ How to choose between all these features? Here are some considerations:
struct MyRow {
days: u16,
#[serde(with = "clickhouse::serde::time::date")]
date: Date,
date: time::Date,
// if you prefer using chrono:
#[serde(with = "clickhouse::serde::chrono::date")]
date_chrono: NaiveDate,
// if you prefer using jiff:
#[serde(with = "clickhouse::serde::jiff::date")]
date_jiff: jiff::civil::Date,
}

```
</details>
* `Date32` maps to/from `i32` or a newtype around it and represents a number of days elapsed since `1970-01-01`. The following external types are supported:
* [`time::Date`](https://docs.rs/time/latest/time/struct.Date.html) is supported by using `serde::time::date32`, requiring the `time` feature.
* [`chrono::NaiveDate`](https://docs.rs/chrono/latest/chrono/struct.NaiveDate.html) is supported by using `serde::chrono::date32`, requiring the `chrono` feature.
* [`jiff::civil::Date`](https://docs.rs/jiff/latest/jiff/civil/struct.Date.html) is supported by using `serde::jiff::date32`, requiring the `jiff` feature.
<details>
<summary>Example</summary>

Expand All @@ -343,18 +349,21 @@ How to choose between all these features? Here are some considerations:
struct MyRow {
days: i32,
#[serde(with = "clickhouse::serde::time::date32")]
date: Date,
date: time::Date,
// if you prefer using chrono:
#[serde(with = "clickhouse::serde::chrono::date32")]
date_chrono: NaiveDate,

// if you prefer using jiff:
#[serde(with = "clickhouse::serde::jiff::date32")]
date_jiff: jiff::civil::Date,
}

```
</details>
* `DateTime` maps to/from `u32` or a newtype around it and represents a number of seconds elapsed since UNIX epoch. The following external types are supported:
* [`time::OffsetDateTime`](https://docs.rs/time/latest/time/struct.OffsetDateTime.html) is supported by using `serde::time::datetime`, requiring the `time` feature.
* [`chrono::DateTime<Utc>`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) is supported by using `serde::chrono::datetime`, requiring the `chrono` feature.
* [`jiff::Timestamp`](https://docs.rs/jiff/latest/jiff/struct.Timestamp.html) is supported by using `serde::jiff::datetime`, requiring the `jiff` feature.
<details>
<summary>Example</summary>

Expand All @@ -366,13 +375,17 @@ How to choose between all these features? Here are some considerations:
dt: OffsetDateTime,
// if you prefer using chrono:
#[serde(with = "clickhouse::serde::chrono::datetime")]
dt_chrono: DateTime<Utc>,
dt_chrono: DateTime<Utc>,
// if you prefer using jiff:
#[serde(with = "clickhouse::serde::jiff::datetime")]
dt_jiff: Timestamp,
}
```
</details>
* `DateTime64(_)` maps to/from `i64` or a newtype around it and represents a time elapsed since UNIX epoch. The following external types are supported:
* [`time::OffsetDateTime`](https://docs.rs/time/latest/time/struct.OffsetDateTime.html) is supported by using `serde::time::datetime64::*`, requiring the `time` feature.
* [`chrono::DateTime<Utc>`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) is supported by using `serde::chrono::datetime64::*`, requiring the `chrono` feature.
* [`jiff::Timestamp`](https://docs.rs/jiff/latest/jiff/struct.Timestamp.html) is supported by using `serde::jiff::datetime64::*`, requiring the `jiff` feature.
<details>
<summary>Example</summary>

Expand All @@ -397,39 +410,78 @@ How to choose between all these features? Here are some considerations:
dt64us_chrono: DateTime<Utc>, // `DateTime64(6)`
#[serde(with = "clickhouse::serde::chrono::datetime64::nanos")]
dt64ns_chrono: DateTime<Utc>, // `DateTime64(9)`
// if you prefer using jiff:
#[serde(with = "clickhouse::serde::jiff::datetime64::secs")]
dt64s_jiff: Timestamp, // `DateTime64(0)`
#[serde(with = "clickhouse::serde::jiff::datetime64::millis")]
dt64ms_jiff: Timestamp, // `DateTime64(3)`
#[serde(with = "clickhouse::serde::jiff::datetime64::micros")]
dt64us_jiff: Timestamp, // `DateTime64(6)`
#[serde(with = "clickhouse::serde::jiff::datetime64::nanos")]
dt64ns_jiff: Timestamp, // `DateTime64(9)`
}


```
</details>
* `Time` maps to/from i32 or a newtype around it. The Time data type is used to store a time value independent of any calendar date. It is ideal for representing daily schedules, event times, or any situation where only the time component (hours, minutes, seconds) is important.
* [`time:Duration`](https://docs.rs/time/latest/time/struct.Duration.html) is is supported by using `serde::time::*`, requiring the `time` feature.
* [`chrono::Duration`](https://docs.rs/chrono/latest/chrono/type.Duration.html) is supported by using `serde::chrono::*`, which is an alias to `TimeDelta`, requiring the `chrono` feature
* [`time::Duration`](https://docs.rs/time/latest/time/struct.Duration.html) is is supported by using `serde::time::time`, requiring the `time` feature.
* [`chrono::Duration`](https://docs.rs/chrono/latest/chrono/type.Duration.html) is supported by using `serde::chrono::time`, which is an alias to `TimeDelta`, requiring the `chrono` feature
* [`jiff::SignedDuration`](https://docs.rs/jiff/latest/jiff/struct.SignedDuration.html) is is supported by using `serde::jiff::time`, requiring the `jiff` feature.
<details>
<summary>Example</summary>

```rust,ignore
#[derive(Row, Serialize, Deserialize)]
struct MyRow {
#[serde(with = "clickhouse::serde::chrono::time64::secs")]
t0: chrono::Duration,
#[serde(with = "clickhouse::serde::chrono::time64::secs::option")]
t0_opt: Option<chrono::Duration>,
#[serde(with = "clickhouse::serde::time::time")]
t: time::Duration,
// if you prefer using chrono:
#[serde(with = "clickhouse::serde::chrono::time")]
t_chrono: chrono::Duration,
// if you prefer using jiff:
#[serde(with = "clickhouse::serde::jiff::time")]
t_jiff: jiff::SignedDuration,
}

```
</details>
* `Time64(_)` maps to/from i64 or a newtype around it. The Time data type is used to store a time value independent of any calendar date. It is ideal for representing daily schedules, event times, or any situation where only the time component (hours, minutes, seconds) is important.
* [`time:Duration`](https://docs.rs/time/latest/time/struct.Duration.html) is is supported by using `serde::time::*`, requiring the `time` feature.
* [`chrono::Duration`](https://docs.rs/chrono/latest/chrono/type.Duration.html) is supported by using `serde::chrono::*`, requiring the `chrono` feature
* [`time::Duration`](https://docs.rs/time/latest/time/struct.Duration.html) is is supported by using `serde::time::time64::*`, requiring the `time` feature.
* [`chrono::Duration`](https://docs.rs/chrono/latest/chrono/type.Duration.html) is supported by using `serde::chrono::time64::*`, requiring the `chrono` feature
* [`jiff::SignedDuration`](https://docs.rs/jiff/latest/jiff/struct.SignedDuration.html) is is supported by using `serde::jiff::time64::*`, requiring the `jiff` feature.
<details>
<summary>Example</summary>

```rust,ignore
#[derive(Row, Serialize, Deserialize)]
struct MyRow {
#[serde(with = "clickhouse::serde::time::time")]
t0: Time,
#[serde(with = "clickhouse::serde::time::time64::secs")]
t64s: time::Duration,
#[serde(with = "clickhouse::serde::time::time64::millis")]
t64ms: time::Duration,
#[serde(with = "clickhouse::serde::time::time64::micros")]
t64us: time::Duration,
#[serde(with = "clickhouse::serde::time::time64::nanos")]
t64ns: time::Duration,
// if you prefer using chrono:
#[serde(with = "clickhouse::serde::chrono::time64::secs")]
t64s_chrono: chrono::Duration,
#[serde(with = "clickhouse::serde::chrono::time64::millis")]
t64ms_chrono: chrono::Duration,
#[serde(with = "clickhouse::serde::chrono::time64::micros")]
t64us_chrono: chrono::Duration,
#[serde(with = "clickhouse::serde::chrono::time64::nanos")]
t64ns_chrono: chrono::Duration,
// if you prefer using jiff:
#[serde(with = "clickhouse::serde::jiff::time64::secs")]
t64s_jiff: jiff::SignedDuration,
#[serde(with = "clickhouse::serde::jiff::time64::millis")]
t64ms_jiff: jiff::SignedDuration,
#[serde(with = "clickhouse::serde::jiff::time64::micros")]
t64us_jiff: jiff::SignedDuration,
#[serde(with = "clickhouse::serde::jiff::time64::nanos")]
t64ns_jiff: jiff::SignedDuration,
}

```
Expand Down
40 changes: 40 additions & 0 deletions examples/data_types_derive_simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use fixnum::{
typenum::{U12, U4, U8},
FixedPoint,
};
use jiff::{civil::Date as JiffDate, Timestamp};
use rand::prelude::IndexedRandom;
use rand::{distr::Alphanumeric, Rng};
use std::str::FromStr;
Expand Down Expand Up @@ -73,6 +74,16 @@ async fn main() -> Result<()> {
chrono_datetime64_6 DateTime64(6),
chrono_datetime64_9 DateTime64(9),
chrono_datetime64_9_tz DateTime64(9, 'UTC'),

jiff_date Date,
jiff_date32 Date32,
jiff_datetime DateTime,
jiff_datetime_tz DateTime('UTC'),
jiff_datetime64_0 DateTime64(0),
jiff_datetime64_3 DateTime64(3),
jiff_datetime64_6 DateTime64(6),
jiff_datetime64_9 DateTime64(9),
jiff_datetime64_9_tz DateTime64(9, 'UTC'),
) ENGINE MergeTree ORDER BY ();
",
)
Expand Down Expand Up @@ -168,6 +179,25 @@ pub struct Row {
pub chrono_datetime64_9: DateTime<Utc>,
#[serde(with = "clickhouse::serde::chrono::datetime64::nanos")]
pub chrono_datetime64_9_tz: DateTime<Utc>,

#[serde(with = "clickhouse::serde::jiff::date")]
pub jiff_date: JiffDate,
#[serde(with = "clickhouse::serde::jiff::date32")]
pub jiff_date32: JiffDate,
#[serde(with = "clickhouse::serde::jiff::datetime")]
pub jiff_datetime: Timestamp,
#[serde(with = "clickhouse::serde::jiff::datetime")]
pub jiff_datetime_tz: Timestamp,
#[serde(with = "clickhouse::serde::jiff::datetime64::secs")]
pub jiff_datetime64_0: Timestamp,
#[serde(with = "clickhouse::serde::jiff::datetime64::millis")]
pub jiff_datetime64_3: Timestamp,
#[serde(with = "clickhouse::serde::jiff::datetime64::micros")]
pub jiff_datetime64_6: Timestamp,
#[serde(with = "clickhouse::serde::jiff::datetime64::nanos")]
pub jiff_datetime64_9: Timestamp,
#[serde(with = "clickhouse::serde::jiff::datetime64::nanos")]
pub jiff_datetime64_9_tz: Timestamp,
}

// See ClickHouse decimal sizes: https://clickhouse.com/docs/en/sql-reference/data-types/decimal
Expand Down Expand Up @@ -255,6 +285,16 @@ impl Row {
chrono_datetime64_6: Utc::now(),
chrono_datetime64_9: Utc::now(),
chrono_datetime64_9_tz: Utc::now(),

jiff_date: JiffDate::constant(2149, 6, 6),
jiff_date32: JiffDate::constant(2299, 12, 31),
jiff_datetime: Timestamp::now(),
jiff_datetime_tz: Timestamp::now(),
jiff_datetime64_0: Timestamp::now(),
jiff_datetime64_3: Timestamp::now(),
jiff_datetime64_6: Timestamp::now(),
jiff_datetime64_9: Timestamp::now(),
jiff_datetime64_9_tz: Timestamp::now(),
}
}
}
Expand Down
39 changes: 38 additions & 1 deletion examples/time_types_example.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use chrono::Duration;
use clickhouse::Client;
use jiff::SignedDuration;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, clickhouse::Row)]
Expand Down Expand Up @@ -44,9 +45,30 @@ struct TimeExampleChrono {
time64_nanos: Duration,
}

#[derive(Debug, Serialize, Deserialize, clickhouse::Row)]
struct TimeExampleJiff {
#[serde(with = "clickhouse::serde::jiff::time")]
time_field: SignedDuration,

#[serde(with = "clickhouse::serde::jiff::time::option")]
time_optional: Option<SignedDuration>,

#[serde(with = "clickhouse::serde::jiff::time64::secs")]
time64_seconds: SignedDuration,

#[serde(with = "clickhouse::serde::jiff::time64::millis")]
time64_millis: SignedDuration,

#[serde(with = "clickhouse::serde::jiff::time64::micros")]
time64_micros: SignedDuration,

#[serde(with = "clickhouse::serde::jiff::time64::nanos")]
time64_nanos: SignedDuration,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::default();
let client = Client::default().with_url("http://localhost:8123");

let create_table_sql = r#"
CREATE TABLE IF NOT EXISTS time_example (
Expand All @@ -58,6 +80,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
time64_nanos Time64(9)
) ENGINE = MergeTree()
ORDER BY time_field
SETTINGS enable_time_time64_type = 1
"#;

client.query(create_table_sql).execute().await?;
Expand Down Expand Up @@ -116,6 +139,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("Inserted edge case #{i}: {edge:?}");
}

// Insert data using jiff crate
let time_example = TimeExampleJiff {
time_field: SignedDuration::new(23 * 3600 + 56 * 60, 0),
time_optional: Some(SignedDuration::new(3600 + 2 * 60 + 2, 0)),
time64_seconds: SignedDuration::new(3 * 3600 + 4 * 60 + 5, 0),
time64_millis: SignedDuration::new(6 * 3600 + 7 * 60 + 8, 123_000_000),
time64_micros: SignedDuration::new(9 * 3600 + 10 * 60 + 11, 456_789_000),
time64_nanos: SignedDuration::new(12 * 3600 + 13 * 60 + 14, 123_456_789),
};

let mut insert = client.insert::<TimeExampleJiff>("time_example")?;
insert.write(&time_example).await?;
insert.end().await?;

// Query the data
let rows: Vec<TimeExample> = client
.query("SELECT * FROM time_example ORDER BY time_field")
Expand Down
Loading