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