Skip to content

Commit 5ccae0b

Browse files
authored
docs: note about Geo and add container-like data types examples (#147)
1 parent f78cf31 commit 5ccae0b

File tree

3 files changed

+159
-1
lines changed

3 files changed

+159
-1
lines changed

README.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,11 +398,36 @@ See [examples](https://github.com/ClickHouse/clickhouse-rs/tree/main/examples).
398398
}
399399
```
400400
</details>
401-
* `JSON` and `Geo` aren't supported for now.
401+
* `Geo` types are supported. `Point` behaves like a tuple `(f64, f64)`, and the rest of the types are just slices of points.
402+
<details>
403+
<summary>Example</summary>
404+
405+
```rust,ignore
406+
type Point = (f64, f64);
407+
type Ring = Vec<Point>;
408+
type Polygon = Vec<Ring>;
409+
type MultiPolygon = Vec<Polygon>;
410+
type LineString = Vec<Point>;
411+
type MultiLineString = Vec<LineString>;
412+
413+
#[derive(Row, Serialize, Deserialize)]
414+
struct MyRow {
415+
point: Point,
416+
ring: Ring,
417+
polygon: Polygon,
418+
multi_polygon: MultiPolygon,
419+
line_string: LineString,
420+
multi_line_string: MultiLineString,
421+
}
422+
```
423+
</details>
424+
425+
* `JSON`, `Variant`, `Dynamic` types are not supported for now.
402426
403427
See also the additional examples:
404428
405429
* [Simpler ClickHouse data types](examples/data_types_derive_simple.rs)
430+
* [Container-like ClickHouse data types](examples/data_types_derive_containers.rs)
406431
407432
## Mocking
408433
The crate provides utils for mocking CH server and testing DDL, `SELECT`, `INSERT` and `WATCH` queries.

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ If something is missing, or you found a mistake in one of these examples, please
1717
### Data types
1818

1919
- [data_types_derive_simple.rs](data_types_derive_simple.rs) - deriving simpler ClickHouse data types in a struct. Required cargo features: `time`, `uuid`.
20+
- [data_types_derive_containers.rs](data_types_derive_containers.rs) - deriving container-like (Array, Tuple, Map, Nested, Geo) ClickHouse data types in a struct.
2021

2122
### Special cases
2223

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
use rand::distributions::Alphanumeric;
2+
use rand::Rng;
3+
4+
use clickhouse::sql::Identifier;
5+
use clickhouse::{error::Result, Client};
6+
7+
// This example covers derivation of container-like ClickHouse data types.
8+
// See also:
9+
// - https://clickhouse.com/docs/en/sql-reference/data-types
10+
// - data_types_derive_simple.rs
11+
12+
#[tokio::main]
13+
async fn main() -> Result<()> {
14+
let table_name = "chrs_data_types_derive_containers";
15+
let client = Client::default().with_url("http://localhost:8123");
16+
17+
client
18+
.query(
19+
"
20+
CREATE OR REPLACE TABLE ?
21+
(
22+
arr Array(String),
23+
arr2 Array(Array(String)),
24+
map Map(String, UInt32),
25+
tuple Tuple(String, UInt32),
26+
nested Nested(name String, count UInt32),
27+
point Point,
28+
ring Ring,
29+
polygon Polygon,
30+
multi_polygon MultiPolygon,
31+
line_string LineString,
32+
multi_line_string MultiLineString
33+
) ENGINE MergeTree ORDER BY ();
34+
",
35+
)
36+
.bind(Identifier(table_name))
37+
.execute()
38+
.await?;
39+
40+
let mut insert = client.insert(table_name)?;
41+
insert.write(&Row::new()).await?;
42+
insert.end().await?;
43+
44+
let rows = client
45+
.query("SELECT ?fields FROM ?")
46+
.bind(Identifier(table_name))
47+
.fetch_all::<Row>()
48+
.await?;
49+
50+
println!("{rows:#?}");
51+
Ok(())
52+
}
53+
54+
// See https://clickhouse.com/docs/en/sql-reference/data-types/geo
55+
type Point = (f64, f64);
56+
type Ring = Vec<Point>;
57+
type Polygon = Vec<Ring>;
58+
type MultiPolygon = Vec<Polygon>;
59+
type LineString = Vec<Point>;
60+
type MultiLineString = Vec<LineString>;
61+
62+
#[derive(Clone, Debug, PartialEq)]
63+
#[derive(clickhouse::Row, serde::Serialize, serde::Deserialize)]
64+
pub struct Row {
65+
arr: Vec<String>,
66+
arr2: Vec<Vec<String>>,
67+
map: Vec<(String, u32)>,
68+
tuple: (String, u32),
69+
// Nested columns are internally represented as arrays of the same length
70+
// https://clickhouse.com/docs/en/sql-reference/data-types/nested-data-structures/nested
71+
#[serde(rename = "nested.name")]
72+
nested_name: Vec<String>,
73+
#[serde(rename = "nested.count")]
74+
nested_count: Vec<u32>,
75+
// Geo types
76+
point: Point,
77+
ring: Ring,
78+
polygon: Polygon,
79+
multi_polygon: MultiPolygon,
80+
line_string: LineString,
81+
multi_line_string: MultiLineString,
82+
}
83+
84+
impl Row {
85+
pub fn new() -> Self {
86+
let mut rng = rand::thread_rng();
87+
Row {
88+
arr: vec![random_str()],
89+
arr2: vec![vec![random_str()]],
90+
map: vec![(random_str(), 42)],
91+
tuple: (random_str(), 144),
92+
// Nested
93+
// NB: the length of all vectors/slices representing Nested columns must be the same
94+
nested_name: vec![random_str(), random_str()],
95+
nested_count: vec![rng.gen(), rng.gen()],
96+
// Geo
97+
point: random_point(),
98+
ring: random_ring(),
99+
polygon: random_polygon(),
100+
multi_polygon: vec![random_polygon()],
101+
line_string: random_ring(), // on the type level, the same as the Ring
102+
multi_line_string: random_polygon(), // on the type level, the same as the Polygon
103+
}
104+
}
105+
}
106+
107+
impl Default for Row {
108+
fn default() -> Self {
109+
Self::new()
110+
}
111+
}
112+
113+
fn random_str() -> String {
114+
rand::thread_rng()
115+
.sample_iter(&Alphanumeric)
116+
.take(3)
117+
.map(char::from)
118+
.collect()
119+
}
120+
121+
fn random_point() -> Point {
122+
let mut rng = rand::thread_rng();
123+
(rng.gen(), rng.gen())
124+
}
125+
126+
fn random_ring() -> Ring {
127+
vec![random_point(), random_point()]
128+
}
129+
130+
fn random_polygon() -> Polygon {
131+
vec![random_ring(), random_ring()]
132+
}

0 commit comments

Comments
 (0)