Skip to content

Commit ccc58e5

Browse files
committed
Implement support for jiff
1 parent 92926fd commit ccc58e5

File tree

7 files changed

+1084
-19
lines changed

7 files changed

+1084
-19
lines changed

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,15 @@ required-features = ["rustls-tls"]
7272

7373
[[example]]
7474
name = "data_types_derive_simple"
75-
required-features = ["time", "uuid", "chrono"]
75+
required-features = ["time", "uuid", "chrono", "jiff"]
7676

7777
[[example]]
7878
name = "data_types_variant"
7979
required-features = ["time"]
8080

8181
[[example]]
8282
name = "time_types_example"
83-
required-features = ["time", "chrono"]
83+
required-features = ["time", "chrono", "jiff"]
8484

8585
[profile.release]
8686
debug = true
@@ -94,6 +94,7 @@ uuid = ["dep:uuid"]
9494
time = ["dep:time"]
9595
lz4 = ["dep:lz4_flex", "dep:cityhash-rs"]
9696
chrono = ["dep:chrono"]
97+
jiff = ["dep:jiff"]
9798
futures03 = []
9899

99100
## TLS
@@ -148,6 +149,7 @@ cityhash-rs = { version = "=1.0.1", optional = true } # exact version for safety
148149
uuid = { version = "1", optional = true }
149150
time = { version = "0.3", optional = true }
150151
chrono = { version = "0.4", optional = true, features = ["serde"] }
152+
jiff = { version = "0.2", optional = true }
151153
bstr = { version = "1.11.0", default-features = false }
152154
quanta = { version = "0.12", optional = true }
153155
replace_with = { version = "0.1.7" }

README.md

Lines changed: 66 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ client.query("DROP TABLE IF EXISTS some").execute().await?;
208208
* `uuid` — adds `serde::uuid` to work with [uuid](https://docs.rs/uuid) crate.
209209
* `time` — adds `serde::time` to work with [time](https://docs.rs/time) crate.
210210
* `chrono` — adds `serde::chrono` to work with [chrono](https://docs.rs/chrono) crate.
211+
* `jiff` — adds `serde::jiff` to work with [jiff](https://docs.rs/jiff) crate.
211212

212213
### TLS
213214
By default, TLS is disabled and one or more following features must be enabled to use HTTPS urls:
@@ -316,6 +317,7 @@ How to choose between all these features? Here are some considerations:
316317
* `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:
317318
* [`time::Date`](https://docs.rs/time/latest/time/struct.Date.html) is supported by using `serde::time::date`, requiring the `time` feature.
318319
* [`chrono::NaiveDate`](https://docs.rs/chrono/latest/chrono/struct.NaiveDate.html) is supported by using `serde::chrono::date`, requiring the `chrono` feature.
320+
* [`jiff::civil::Date`](https://docs.rs/jiff/latest/jiff/civil/struct.Date.html) is supported by using `serde::jiff::date`, requiring the `jiff` feature.
319321
<details>
320322
<summary>Example</summary>
321323
@@ -324,17 +326,21 @@ How to choose between all these features? Here are some considerations:
324326
struct MyRow {
325327
days: u16,
326328
#[serde(with = "clickhouse::serde::time::date")]
327-
date: Date,
329+
date: time::Date,
328330
// if you prefer using chrono:
329331
#[serde(with = "clickhouse::serde::chrono::date")]
330332
date_chrono: NaiveDate,
333+
// if you prefer using jiff:
334+
#[serde(with = "clickhouse::serde::jiff::date")]
335+
date_jiff: jiff::civil::Date,
331336
}
332337
333338
```
334339
</details>
335340
* `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:
336341
* [`time::Date`](https://docs.rs/time/latest/time/struct.Date.html) is supported by using `serde::time::date32`, requiring the `time` feature.
337342
* [`chrono::NaiveDate`](https://docs.rs/chrono/latest/chrono/struct.NaiveDate.html) is supported by using `serde::chrono::date32`, requiring the `chrono` feature.
343+
* [`jiff::civil::Date`](https://docs.rs/jiff/latest/jiff/civil/struct.Date.html) is supported by using `serde::jiff::date32`, requiring the `jiff` feature.
338344
<details>
339345
<summary>Example</summary>
340346
@@ -343,18 +349,21 @@ How to choose between all these features? Here are some considerations:
343349
struct MyRow {
344350
days: i32,
345351
#[serde(with = "clickhouse::serde::time::date32")]
346-
date: Date,
352+
date: time::Date,
347353
// if you prefer using chrono:
348354
#[serde(with = "clickhouse::serde::chrono::date32")]
349355
date_chrono: NaiveDate,
350-
356+
// if you prefer using jiff:
357+
#[serde(with = "clickhouse::serde::jiff::date32")]
358+
date_jiff: jiff::civil::Date,
351359
}
352360
353361
```
354362
</details>
355363
* `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:
356364
* [`time::OffsetDateTime`](https://docs.rs/time/latest/time/struct.OffsetDateTime.html) is supported by using `serde::time::datetime`, requiring the `time` feature.
357365
* [`chrono::DateTime<Utc>`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) is supported by using `serde::chrono::datetime`, requiring the `chrono` feature.
366+
* [`jiff::Timestamp`](https://docs.rs/jiff/latest/jiff/struct.Timestamp.html) is supported by using `serde::jiff::datetime`, requiring the `jiff` feature.
358367
<details>
359368
<summary>Example</summary>
360369
@@ -366,13 +375,17 @@ How to choose between all these features? Here are some considerations:
366375
dt: OffsetDateTime,
367376
// if you prefer using chrono:
368377
#[serde(with = "clickhouse::serde::chrono::datetime")]
369-
dt_chrono: DateTime<Utc>,
378+
dt_chrono: DateTime<Utc>,
379+
// if you prefer using jiff:
380+
#[serde(with = "clickhouse::serde::jiff::datetime")]
381+
dt_jiff: Timestamp,
370382
}
371383
```
372384
</details>
373385
* `DateTime64(_)` maps to/from `i64` or a newtype around it and represents a time elapsed since UNIX epoch. The following external types are supported:
374386
* [`time::OffsetDateTime`](https://docs.rs/time/latest/time/struct.OffsetDateTime.html) is supported by using `serde::time::datetime64::*`, requiring the `time` feature.
375387
* [`chrono::DateTime<Utc>`](https://docs.rs/chrono/latest/chrono/struct.DateTime.html) is supported by using `serde::chrono::datetime64::*`, requiring the `chrono` feature.
388+
* [`jiff::Timestamp`](https://docs.rs/jiff/latest/jiff/struct.Timestamp.html) is supported by using `serde::jiff::datetime64::*`, requiring the `jiff` feature.
376389
<details>
377390
<summary>Example</summary>
378391
@@ -397,39 +410,78 @@ How to choose between all these features? Here are some considerations:
397410
dt64us_chrono: DateTime<Utc>, // `DateTime64(6)`
398411
#[serde(with = "clickhouse::serde::chrono::datetime64::nanos")]
399412
dt64ns_chrono: DateTime<Utc>, // `DateTime64(9)`
413+
// if you prefer using jiff:
414+
#[serde(with = "clickhouse::serde::jiff::datetime64::secs")]
415+
dt64s_jiff: Timestamp, // `DateTime64(0)`
416+
#[serde(with = "clickhouse::serde::jiff::datetime64::millis")]
417+
dt64ms_jiff: Timestamp, // `DateTime64(3)`
418+
#[serde(with = "clickhouse::serde::jiff::datetime64::micros")]
419+
dt64us_jiff: Timestamp, // `DateTime64(6)`
420+
#[serde(with = "clickhouse::serde::jiff::datetime64::nanos")]
421+
dt64ns_jiff: Timestamp, // `DateTime64(9)`
400422
}
401423
402424
403425
```
404426
</details>
405427
* `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.
406-
* [`time:Duration`](https://docs.rs/time/latest/time/struct.Duration.html) is is supported by using `serde::time::*`, requiring the `time` feature.
407-
* [`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
428+
* [`time::Duration`](https://docs.rs/time/latest/time/struct.Duration.html) is is supported by using `serde::time::time`, requiring the `time` feature.
429+
* [`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
430+
* [`jiff::SignedDuration`](https://docs.rs/jiff/latest/jiff/struct.SignedDuration.html) is is supported by using `serde::jiff::time`, requiring the `jiff` feature.
408431
<details>
409432
<summary>Example</summary>
410433
411434
```rust,ignore
412435
#[derive(Row, Serialize, Deserialize)]
413436
struct MyRow {
414-
#[serde(with = "clickhouse::serde::chrono::time64::secs")]
415-
t0: chrono::Duration,
416-
#[serde(with = "clickhouse::serde::chrono::time64::secs::option")]
417-
t0_opt: Option<chrono::Duration>,
437+
#[serde(with = "clickhouse::serde::time::time")]
438+
t: time::Duration,
439+
// if you prefer using chrono:
440+
#[serde(with = "clickhouse::serde::chrono::time")]
441+
t_chrono: chrono::Duration,
442+
// if you prefer using jiff:
443+
#[serde(with = "clickhouse::serde::jiff::time")]
444+
t_jiff: jiff::SignedDuration,
418445
}
419446
420447
```
421448
</details>
422449
* `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.
423-
* [`time:Duration`](https://docs.rs/time/latest/time/struct.Duration.html) is is supported by using `serde::time::*`, requiring the `time` feature.
424-
* [`chrono::Duration`](https://docs.rs/chrono/latest/chrono/type.Duration.html) is supported by using `serde::chrono::*`, requiring the `chrono` feature
450+
* [`time::Duration`](https://docs.rs/time/latest/time/struct.Duration.html) is is supported by using `serde::time::time64::*`, requiring the `time` feature.
451+
* [`chrono::Duration`](https://docs.rs/chrono/latest/chrono/type.Duration.html) is supported by using `serde::chrono::time64::*`, requiring the `chrono` feature
452+
* [`jiff::SignedDuration`](https://docs.rs/jiff/latest/jiff/struct.SignedDuration.html) is is supported by using `serde::jiff::time64::*`, requiring the `jiff` feature.
425453
<details>
426454
<summary>Example</summary>
427455
428456
```rust,ignore
429457
#[derive(Row, Serialize, Deserialize)]
430458
struct MyRow {
431-
#[serde(with = "clickhouse::serde::time::time")]
432-
t0: Time,
459+
#[serde(with = "clickhouse::serde::time::time64::secs")]
460+
t64s: time::Duration,
461+
#[serde(with = "clickhouse::serde::time::time64::millis")]
462+
t64ms: time::Duration,
463+
#[serde(with = "clickhouse::serde::time::time64::micros")]
464+
t64us: time::Duration,
465+
#[serde(with = "clickhouse::serde::time::time64::nanos")]
466+
t64ns: time::Duration,
467+
// if you prefer using chrono:
468+
#[serde(with = "clickhouse::serde::chrono::time64::secs")]
469+
t64s_chrono: chrono::Duration,
470+
#[serde(with = "clickhouse::serde::chrono::time64::millis")]
471+
t64ms_chrono: chrono::Duration,
472+
#[serde(with = "clickhouse::serde::chrono::time64::micros")]
473+
t64us_chrono: chrono::Duration,
474+
#[serde(with = "clickhouse::serde::chrono::time64::nanos")]
475+
t64ns_chrono: chrono::Duration,
476+
// if you prefer using jiff:
477+
#[serde(with = "clickhouse::serde::jiff::time64::secs")]
478+
t64s_jiff: jiff::SignedDuration,
479+
#[serde(with = "clickhouse::serde::jiff::time64::millis")]
480+
t64ms_jiff: jiff::SignedDuration,
481+
#[serde(with = "clickhouse::serde::jiff::time64::micros")]
482+
t64us_jiff: jiff::SignedDuration,
483+
#[serde(with = "clickhouse::serde::jiff::time64::nanos")]
484+
t64ns_jiff: jiff::SignedDuration,
433485
}
434486
435487
```

examples/data_types_derive_simple.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use fixnum::{
33
typenum::{U12, U4, U8},
44
FixedPoint,
55
};
6+
use jiff::{civil::Date as JiffDate, Timestamp};
67
use rand::prelude::IndexedRandom;
78
use rand::{distr::Alphanumeric, Rng};
89
use std::str::FromStr;
@@ -73,6 +74,16 @@ async fn main() -> Result<()> {
7374
chrono_datetime64_6 DateTime64(6),
7475
chrono_datetime64_9 DateTime64(9),
7576
chrono_datetime64_9_tz DateTime64(9, 'UTC'),
77+
78+
jiff_date Date,
79+
jiff_date32 Date32,
80+
jiff_datetime DateTime,
81+
jiff_datetime_tz DateTime('UTC'),
82+
jiff_datetime64_0 DateTime64(0),
83+
jiff_datetime64_3 DateTime64(3),
84+
jiff_datetime64_6 DateTime64(6),
85+
jiff_datetime64_9 DateTime64(9),
86+
jiff_datetime64_9_tz DateTime64(9, 'UTC'),
7687
) ENGINE MergeTree ORDER BY ();
7788
",
7889
)
@@ -168,6 +179,25 @@ pub struct Row {
168179
pub chrono_datetime64_9: DateTime<Utc>,
169180
#[serde(with = "clickhouse::serde::chrono::datetime64::nanos")]
170181
pub chrono_datetime64_9_tz: DateTime<Utc>,
182+
183+
#[serde(with = "clickhouse::serde::jiff::date")]
184+
pub jiff_date: JiffDate,
185+
#[serde(with = "clickhouse::serde::jiff::date32")]
186+
pub jiff_date32: JiffDate,
187+
#[serde(with = "clickhouse::serde::jiff::datetime")]
188+
pub jiff_datetime: Timestamp,
189+
#[serde(with = "clickhouse::serde::jiff::datetime")]
190+
pub jiff_datetime_tz: Timestamp,
191+
#[serde(with = "clickhouse::serde::jiff::datetime64::secs")]
192+
pub jiff_datetime64_0: Timestamp,
193+
#[serde(with = "clickhouse::serde::jiff::datetime64::millis")]
194+
pub jiff_datetime64_3: Timestamp,
195+
#[serde(with = "clickhouse::serde::jiff::datetime64::micros")]
196+
pub jiff_datetime64_6: Timestamp,
197+
#[serde(with = "clickhouse::serde::jiff::datetime64::nanos")]
198+
pub jiff_datetime64_9: Timestamp,
199+
#[serde(with = "clickhouse::serde::jiff::datetime64::nanos")]
200+
pub jiff_datetime64_9_tz: Timestamp,
171201
}
172202

173203
// See ClickHouse decimal sizes: https://clickhouse.com/docs/en/sql-reference/data-types/decimal
@@ -255,6 +285,16 @@ impl Row {
255285
chrono_datetime64_6: Utc::now(),
256286
chrono_datetime64_9: Utc::now(),
257287
chrono_datetime64_9_tz: Utc::now(),
288+
289+
jiff_date: JiffDate::constant(2149, 6, 6),
290+
jiff_date32: JiffDate::constant(2299, 12, 31),
291+
jiff_datetime: Timestamp::now(),
292+
jiff_datetime_tz: Timestamp::now(),
293+
jiff_datetime64_0: Timestamp::now(),
294+
jiff_datetime64_3: Timestamp::now(),
295+
jiff_datetime64_6: Timestamp::now(),
296+
jiff_datetime64_9: Timestamp::now(),
297+
jiff_datetime64_9_tz: Timestamp::now(),
258298
}
259299
}
260300
}

examples/time_types_example.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use chrono::Duration;
22
use clickhouse::Client;
3+
use jiff::SignedDuration;
34
use serde::{Deserialize, Serialize};
45

56
#[derive(Debug, Serialize, Deserialize, clickhouse::Row)]
@@ -44,9 +45,30 @@ struct TimeExampleChrono {
4445
time64_nanos: Duration,
4546
}
4647

48+
#[derive(Debug, Serialize, Deserialize, clickhouse::Row)]
49+
struct TimeExampleJiff {
50+
#[serde(with = "clickhouse::serde::jiff::time")]
51+
time_field: SignedDuration,
52+
53+
#[serde(with = "clickhouse::serde::jiff::time::option")]
54+
time_optional: Option<SignedDuration>,
55+
56+
#[serde(with = "clickhouse::serde::jiff::time64::secs")]
57+
time64_seconds: SignedDuration,
58+
59+
#[serde(with = "clickhouse::serde::jiff::time64::millis")]
60+
time64_millis: SignedDuration,
61+
62+
#[serde(with = "clickhouse::serde::jiff::time64::micros")]
63+
time64_micros: SignedDuration,
64+
65+
#[serde(with = "clickhouse::serde::jiff::time64::nanos")]
66+
time64_nanos: SignedDuration,
67+
}
68+
4769
#[tokio::main]
4870
async fn main() -> Result<(), Box<dyn std::error::Error>> {
49-
let client = Client::default();
71+
let client = Client::default().with_url("http://localhost:8123");
5072

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

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

142+
// Insert data using jiff crate
143+
let time_example = TimeExampleJiff {
144+
time_field: SignedDuration::new(23 * 3600 + 56 * 60, 0),
145+
time_optional: Some(SignedDuration::new(3600 + 2 * 60 + 2, 0)),
146+
time64_seconds: SignedDuration::new(3 * 3600 + 4 * 60 + 5, 0),
147+
time64_millis: SignedDuration::new(6 * 3600 + 7 * 60 + 8, 123_000_000),
148+
time64_micros: SignedDuration::new(9 * 3600 + 10 * 60 + 11, 456_789_000),
149+
time64_nanos: SignedDuration::new(12 * 3600 + 13 * 60 + 14, 123_456_789),
150+
};
151+
152+
let mut insert = client.insert::<TimeExampleJiff>("time_example")?;
153+
insert.write(&time_example).await?;
154+
insert.end().await?;
155+
119156
// Query the data
120157
let rows: Vec<TimeExample> = client
121158
.query("SELECT * FROM time_example ORDER BY time_field")

0 commit comments

Comments
 (0)