Skip to content

Commit a4b7a02

Browse files
fix(ser): fix i128/u128 SQL bind serialization
Integer types larger than 64 bits cannot be written as literals without casting, or they end up `Float64`. See ClickHouse/ClickHouse#38480 This commit fixes #208
1 parent 72b3729 commit a4b7a02

File tree

3 files changed

+127
-2
lines changed

3 files changed

+127
-2
lines changed

src/sql/ser.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,10 @@ impl<'a, W: Write> Serializer for SqlSerializer<'a, W> {
9595
serialize_i16(i16),
9696
serialize_i32(i32),
9797
serialize_i64(i64),
98-
serialize_i128(i128),
9998
serialize_u8(u8),
10099
serialize_u16(u16),
101100
serialize_u32(u32),
102101
serialize_u64(u64),
103-
serialize_u128(u128),
104102
serialize_f32(f32),
105103
serialize_f64(f64),
106104
serialize_bool(bool),
@@ -112,6 +110,18 @@ impl<'a, W: Write> Serializer for SqlSerializer<'a, W> {
112110
self.serialize_str(value.encode_utf8(&mut tmp))
113111
}
114112

113+
#[inline]
114+
fn serialize_i128(self, value: i128) -> Result {
115+
write!(self.writer, "{}::Int128", value)?;
116+
Ok(())
117+
}
118+
119+
#[inline]
120+
fn serialize_u128(self, value: u128) -> Result {
121+
write!(self.writer, "{}::UInt128", value)?;
122+
Ok(())
123+
}
124+
115125
#[inline]
116126
fn serialize_str(self, value: &str) -> Result {
117127
escape::string(value, self.writer)?;

tests/it/int128.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
use rand::random;
2+
use serde::{Deserialize, Serialize};
3+
4+
use clickhouse::Row;
5+
6+
#[tokio::test]
7+
async fn u128() {
8+
let client = prepare_database!();
9+
10+
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Row)]
11+
struct MyRow {
12+
id: u128,
13+
value: String,
14+
}
15+
16+
client
17+
.query(
18+
"
19+
CREATE TABLE test(
20+
id UInt128,
21+
value String,
22+
) ENGINE = MergeTree ORDER BY id
23+
",
24+
)
25+
.execute()
26+
.await
27+
.unwrap();
28+
29+
let (id0, id1, id2) = (random(), random(), random());
30+
println!("ids: {id0}, {id1}, {id2}");
31+
32+
let original_rows = vec![MyRow {
33+
id: id0,
34+
value: "test_0".to_string(),
35+
}, MyRow {
36+
id: id1,
37+
value: "test_1".to_string(),
38+
}, MyRow {
39+
id: id2,
40+
value: "test_2".to_string(),
41+
}];
42+
43+
let mut insert = client.insert("test").unwrap();
44+
for row in &original_rows {
45+
insert.write(row).await.unwrap();
46+
}
47+
insert.end().await.unwrap();
48+
49+
let rows = client
50+
.query("SELECT ?fields FROM test WHERE id IN ? ORDER BY value")
51+
.bind(vec![id0, id2])
52+
.fetch_all::<MyRow>()
53+
.await
54+
.unwrap();
55+
56+
assert_eq!(rows.len(), 2);
57+
assert_eq!(rows[0], original_rows[0]);
58+
assert_eq!(rows[1], original_rows[2]);
59+
}
60+
61+
#[tokio::test]
62+
async fn i128() {
63+
let client = prepare_database!();
64+
65+
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Row)]
66+
struct MyRow {
67+
id: i128,
68+
value: String,
69+
}
70+
71+
client
72+
.query(
73+
"
74+
CREATE TABLE test(
75+
id Int128,
76+
value String,
77+
) ENGINE = MergeTree ORDER BY id
78+
",
79+
)
80+
.execute()
81+
.await
82+
.unwrap();
83+
84+
let (id0, id1, id2) = (random(), random(), random());
85+
println!("ids: {id0}, {id1}, {id2}");
86+
87+
let original_rows = vec![MyRow {
88+
id: id0,
89+
value: "test_0".to_string(),
90+
}, MyRow {
91+
id: id1,
92+
value: "test_1".to_string(),
93+
}, MyRow {
94+
id: id2,
95+
value: "test_2".to_string(),
96+
}];
97+
98+
let mut insert = client.insert("test").unwrap();
99+
for row in &original_rows {
100+
insert.write(row).await.unwrap();
101+
}
102+
insert.end().await.unwrap();
103+
104+
let rows = client
105+
.query("SELECT ?fields FROM test WHERE id IN ? ORDER BY value")
106+
.bind(vec![id0, id2])
107+
.fetch_all::<MyRow>()
108+
.await
109+
.unwrap();
110+
111+
assert_eq!(rows.len(), 2);
112+
assert_eq!(rows[0], original_rows[0]);
113+
assert_eq!(rows[1], original_rows[2]);
114+
}

tests/it/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ mod cursor_stats;
6161
mod fetch_bytes;
6262
mod insert;
6363
mod inserter;
64+
mod int128;
6465
mod ip;
6566
mod mock;
6667
mod nested;

0 commit comments

Comments
 (0)