1mod errors;
4mod typesystem;
5
6pub use self::errors::ClickHouseSourceError;
7pub use self::typesystem::{ClickHouseTypeSystem, TypeMetadata};
8
9use crate::{
10 data_order::DataOrder,
11 errors::ConnectorXError,
12 sources::{
13 clickhouse::typesystem::DataType, PartitionParser, Produce, Source, SourcePartition,
14 },
15 sql::{count_query, limit0_query, CXQuery},
16};
17use anyhow::anyhow;
18use chrono::{DateTime, Duration, NaiveDate, NaiveTime, Utc};
19use chrono_tz::Tz;
20use clickhouse::Client;
21use fehler::{throw, throws};
22use rust_decimal::Decimal;
23use serde::Deserialize;
24use serde_json::Value as JsonValue;
25use sqlparser::dialect::{ClickHouseDialect, GenericDialect};
26use std::io::{Cursor, Read};
27use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
28use std::sync::Arc;
29use tokio::runtime::Runtime;
30use uuid::Uuid;
31
32pub struct ClickHouseSource {
34 rt: Arc<Runtime>,
35 pub client: Client,
36 origin_query: Option<String>,
37 queries: Vec<CXQuery<String>>,
38 names: Vec<String>,
39 schema: Vec<ClickHouseTypeSystem>,
40 metadata: Vec<TypeMetadata>,
41}
42
43impl ClickHouseSource {
44 #[throws(ClickHouseSourceError)]
45 pub fn new(rt: Arc<Runtime>, conn: &str) -> Self {
46 let url = url::Url::parse(conn)?;
47
48 let use_https = url
49 .query_pairs()
50 .find(|(k, v)| k == "protocol" && v == "https")
51 .is_some();
52
53 let base_url = format!(
54 "{}://{}:{}",
55 if use_https { "https" } else { "http" },
56 url.host_str().unwrap_or("localhost"),
57 url.port().unwrap_or(8123)
58 );
59
60 let mut client = Client::default()
63 .with_url(&base_url)
64 .with_setting("network_compression_method", "lz4");
65
66 let database = url.path().trim_start_matches('/');
67 if !database.is_empty() {
68 client = client.with_database(database);
69 }
70
71 let username = url.username();
72 if !username.is_empty() {
73 client = client.with_user(username);
74 }
75
76 let password = url.password().unwrap_or("");
77 if !password.is_empty() {
78 client = client.with_password(password);
79 }
80
81 Self {
82 rt,
83 client,
84 origin_query: None,
85 queries: vec![],
86 names: vec![],
87 schema: vec![],
88 metadata: vec![],
89 }
90 }
91}
92
93impl Source for ClickHouseSource
94where
95 ClickHouseSourcePartition:
96 SourcePartition<TypeSystem = ClickHouseTypeSystem, Error = ClickHouseSourceError>,
97{
98 const DATA_ORDERS: &'static [DataOrder] = &[DataOrder::RowMajor];
99 type Partition = ClickHouseSourcePartition;
100 type TypeSystem = ClickHouseTypeSystem;
101 type Error = ClickHouseSourceError;
102
103 #[throws(ClickHouseSourceError)]
104 fn set_data_order(&mut self, data_order: DataOrder) {
105 if !matches!(data_order, DataOrder::RowMajor) {
106 throw!(ConnectorXError::UnsupportedDataOrder(data_order));
107 }
108 }
109
110 fn set_queries<Q: ToString>(&mut self, queries: &[CXQuery<Q>]) {
111 self.queries = queries.iter().map(|q| q.map(Q::to_string)).collect();
112 }
113
114 fn set_origin_query(&mut self, query: Option<String>) {
115 self.origin_query = query;
116 }
117
118 #[throws(ClickHouseSourceError)]
119 fn fetch_metadata(&mut self) {
120 assert!(!self.queries.is_empty());
121
122 let first_query = &self.queries[0];
123 let l1query = limit0_query(first_query, &ClickHouseDialect {})?;
124
125 let describe_query = format!("DESCRIBE ({})", l1query.as_str());
126
127 let response = self.rt.block_on(async {
128 let mut cursor = self
129 .client
130 .query(&describe_query)
131 .fetch_bytes("JSONCompact")
132 .map_err(|e| anyhow!("ClickHouse error: {}", e))?;
133 let bytes = cursor
134 .collect()
135 .await
136 .map_err(|e| anyhow!("ClickHouse error: {}", e))?;
137 Ok::<_, ClickHouseSourceError>(bytes)
138 })?;
139
140 #[derive(Debug, Deserialize)]
141 struct DescribeResponse {
142 data: Vec<Vec<JsonValue>>,
143 }
144
145 let parsed: DescribeResponse = serde_json::from_slice(&response)
146 .map_err(|e| anyhow!("Failed to parse DESCRIBE response: {}", e))?;
147
148 let mut names = Vec::new();
149 let mut types = Vec::new();
150 let mut metadata = Vec::new();
151
152 for row in parsed.data {
153 if row.len() >= 2 {
154 let name = row[0].as_str().unwrap_or("").to_string();
155 let type_str = row[1].as_str().unwrap_or("String");
156 let (ts, meta) = ClickHouseTypeSystem::from_type_str_with_metadata(type_str);
157 names.push(name);
158 types.push(ts);
159 metadata.push(meta);
160 }
161 }
162
163 self.names = names;
164 self.schema = types;
165 self.metadata = metadata;
166 }
167
168 #[throws(ClickHouseSourceError)]
169 fn result_rows(&mut self) -> Option<usize> {
170 match &self.origin_query {
171 Some(q) => {
172 let cxq = CXQuery::Naked(q.clone());
173 let cquery = count_query(&cxq, &ClickHouseDialect {})?;
174
175 let response = self.rt.block_on(async {
176 let mut cursor = self
177 .client
178 .query(cquery.as_str())
179 .fetch_bytes("JSONCompact")
180 .map_err(|e| anyhow!("ClickHouse error: {}", e))?;
181 let bytes = cursor
182 .collect()
183 .await
184 .map_err(|e| anyhow!("ClickHouse error: {}", e))?;
185 Ok::<_, ClickHouseSourceError>(bytes)
186 })?;
187
188 #[derive(Debug, Deserialize)]
189 struct CountResponse {
190 data: Vec<Vec<JsonValue>>,
191 }
192
193 let parsed: CountResponse = serde_json::from_slice(&response)
194 .map_err(|e| anyhow!("Failed to parse count response: {}", e))?;
195
196 if let Some(row) = parsed.data.first() {
197 if let Some(count_val) = row.first() {
198 let count = match count_val {
199 JsonValue::Number(n) => n.as_u64().unwrap_or(0),
200 JsonValue::String(s) => s.parse().unwrap_or(0),
201 _ => 0,
202 };
203 return Some(count as usize);
204 }
205 }
206 None
207 }
208 None => None,
209 }
210 }
211
212 fn names(&self) -> Vec<String> {
213 self.names.clone()
214 }
215
216 fn schema(&self) -> Vec<Self::TypeSystem> {
217 self.schema.clone()
218 }
219
220 #[throws(ClickHouseSourceError)]
221 fn partition(self) -> Vec<Self::Partition> {
222 let mut ret = vec![];
223 for query in self.queries {
224 ret.push(ClickHouseSourcePartition::new(
225 self.rt.clone(),
226 self.client.clone(),
227 &query,
228 &self.schema,
229 &self.metadata,
230 ));
231 }
232 ret
233 }
234}
235
236pub struct ClickHouseSourcePartition {
237 rt: Arc<Runtime>,
238 client: Client,
239 query: CXQuery<String>,
240 schema: Vec<ClickHouseTypeSystem>,
241 metadata: Vec<TypeMetadata>,
242 nrows: usize,
243 ncols: usize,
244}
245
246impl ClickHouseSourcePartition {
247 pub fn new(
248 rt: Arc<Runtime>,
249 client: Client,
250 query: &CXQuery<String>,
251 schema: &[ClickHouseTypeSystem],
252 metadata: &[TypeMetadata],
253 ) -> Self {
254 Self {
255 rt,
256 client,
257 query: query.clone(),
258 schema: schema.to_vec(),
259 metadata: metadata.to_vec(),
260 nrows: 0,
261 ncols: schema.len(),
262 }
263 }
264}
265
266impl SourcePartition for ClickHouseSourcePartition {
267 type TypeSystem = ClickHouseTypeSystem;
268 type Parser<'a> = ClickHouseSourceParser<'a>;
269 type Error = ClickHouseSourceError;
270
271 #[throws(ClickHouseSourceError)]
272 fn result_rows(&mut self) {
273 let cquery = count_query(&self.query, &GenericDialect {})?;
274
275 let response = self.rt.block_on(async {
276 let mut cursor = self
277 .client
278 .query(cquery.as_str())
279 .fetch_bytes("JSONCompact")
280 .map_err(|e| anyhow!("ClickHouse error: {}", e))?;
281 let bytes = cursor
282 .collect()
283 .await
284 .map_err(|e| anyhow!("ClickHouse error: {}", e))?;
285 Ok::<_, ClickHouseSourceError>(bytes)
286 })?;
287
288 #[derive(Debug, Deserialize)]
289 struct CountResponse {
290 data: Vec<Vec<JsonValue>>,
291 }
292
293 let parsed: CountResponse = serde_json::from_slice(&response)
294 .map_err(|e| anyhow!("Failed to parse count response: {}", e))?;
295
296 if let Some(row) = parsed.data.first() {
297 if let Some(count_val) = row.first() {
298 let count = match count_val {
299 JsonValue::Number(n) => n.as_u64().unwrap_or(0),
300 JsonValue::String(s) => s.parse().unwrap_or(0),
301 _ => 0,
302 };
303 self.nrows = count as usize;
304 }
305 }
306 }
307
308 #[throws(ClickHouseSourceError)]
309 fn parser(&mut self) -> Self::Parser<'_> {
310 ClickHouseSourceParser::new(
311 self.rt.clone(),
312 self.client.clone(),
313 self.query.clone(),
314 &self.schema,
315 &self.metadata,
316 )?
317 }
318
319 fn nrows(&self) -> usize {
320 self.nrows
321 }
322
323 fn ncols(&self) -> usize {
324 self.ncols
325 }
326}
327
328struct BinaryReader<'a> {
329 cursor: Cursor<&'a [u8]>,
330}
331
332impl<'a> BinaryReader<'a> {
333 fn new(data: &'a [u8]) -> Self {
334 Self {
335 cursor: Cursor::new(data),
336 }
337 }
338
339 fn read_bytes<const N: usize>(&mut self) -> Result<[u8; N], ClickHouseSourceError> {
340 let mut buf = [0u8; N];
341 self.cursor
342 .read_exact(&mut buf)
343 .map_err(|e| anyhow!("Failed to read {} bytes: {}", N, e))?;
344 Ok(buf)
345 }
346
347 fn read_u8(&mut self) -> Result<u8, ClickHouseSourceError> {
348 Ok(self.read_bytes::<1>()?[0])
349 }
350
351 fn read_i8(&mut self) -> Result<i8, ClickHouseSourceError> {
352 Ok(self.read_u8()? as i8)
353 }
354
355 fn read_u16(&mut self) -> Result<u16, ClickHouseSourceError> {
356 Ok(u16::from_le_bytes(self.read_bytes()?))
357 }
358
359 fn read_i16(&mut self) -> Result<i16, ClickHouseSourceError> {
360 Ok(i16::from_le_bytes(self.read_bytes()?))
361 }
362
363 fn read_u32(&mut self) -> Result<u32, ClickHouseSourceError> {
364 Ok(u32::from_le_bytes(self.read_bytes()?))
365 }
366
367 fn read_i32(&mut self) -> Result<i32, ClickHouseSourceError> {
368 Ok(i32::from_le_bytes(self.read_bytes()?))
369 }
370
371 fn read_u64(&mut self) -> Result<u64, ClickHouseSourceError> {
372 Ok(u64::from_le_bytes(self.read_bytes()?))
373 }
374
375 fn read_i64(&mut self) -> Result<i64, ClickHouseSourceError> {
376 Ok(i64::from_le_bytes(self.read_bytes()?))
377 }
378
379 fn read_f32(&mut self) -> Result<f32, ClickHouseSourceError> {
380 Ok(f32::from_le_bytes(self.read_bytes()?))
381 }
382
383 fn read_f64(&mut self) -> Result<f64, ClickHouseSourceError> {
384 Ok(f64::from_le_bytes(self.read_bytes()?))
385 }
386
387 fn read_varint(&mut self) -> Result<u64, ClickHouseSourceError> {
388 let mut result: u64 = 0;
389 let mut shift = 0;
390 loop {
391 let byte = self.read_u8()?;
392 result |= ((byte & 0x7f) as u64) << shift;
393 if byte & 0x80 == 0 {
394 break;
395 }
396 shift += 7;
397 if shift >= 64 {
398 return Err(anyhow!("Varint too long").into());
399 }
400 }
401 Ok(result)
402 }
403
404 fn read_fixed_string(&mut self, len: usize) -> Result<Vec<u8>, ClickHouseSourceError> {
405 let mut buf = vec![0u8; len];
406 self.cursor
407 .read_exact(&mut buf)
408 .map_err(|e| anyhow!("Failed to read FixedString: {}", e))?;
409 Ok(buf)
410 }
411
412 fn read_string(&mut self) -> Result<String, ClickHouseSourceError> {
413 let len = self.read_varint()? as usize;
414 let mut buf = vec![0u8; len];
415 self.cursor
416 .read_exact(&mut buf)
417 .map_err(|e| anyhow!("Failed to read string: {}", e))?;
418 String::from_utf8(buf).map_err(|e| anyhow!("Invalid UTF-8: {}", e).into())
419 }
420
421 fn read_uuid(&mut self) -> Result<Uuid, ClickHouseSourceError> {
422 let high = self.read_u64()?;
424 let low = self.read_u64()?;
425
426 Ok(Uuid::from_u64_pair(high, low))
427 }
428
429 fn read_bool(&mut self) -> Result<bool, ClickHouseSourceError> {
430 Ok(self.read_u8()? != 0)
431 }
432
433 fn read_date(&mut self) -> Result<NaiveDate, ClickHouseSourceError> {
434 let days = self.read_u16()? as i64;
436 let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
437 epoch
438 .checked_add_signed(Duration::days(days))
439 .ok_or_else(|| anyhow!("Invalid date value: {} days since epoch", days).into())
440 }
441
442 fn read_date32(&mut self) -> Result<NaiveDate, ClickHouseSourceError> {
443 let days = self.read_i32()? as i64;
446 let epoch = NaiveDate::from_ymd_opt(1970, 1, 1).unwrap();
447 epoch
448 .checked_add_signed(Duration::days(days))
449 .ok_or_else(|| anyhow!("Invalid date32 value: {} days since epoch", days).into())
450 }
451
452 fn read_datetime(&mut self, tz: Option<&Tz>) -> Result<DateTime<Utc>, ClickHouseSourceError> {
453 let seconds = self.read_u32()? as i64;
454 chrono::DateTime::from_timestamp(seconds, 0)
455 .map(|dt| dt.with_timezone(tz.unwrap_or(&Tz::UTC)).to_utc())
456 .ok_or_else(|| {
457 anyhow!("Invalid datetime value: {} seconds since epoch", seconds).into()
458 })
459 }
460
461 fn read_datetime64(
462 &mut self,
463 precision: u8,
464 tz: Option<&Tz>,
465 ) -> Result<DateTime<Utc>, ClickHouseSourceError> {
466 if precision > 9 {
467 return Err(anyhow!("Unsupported DateTime64 precision: {}", precision).into());
468 }
469 let ticks = self.read_i64()?;
470 let scale = 10_i64.pow(precision as u32);
471 let seconds = ticks.div_euclid(scale);
472 let fractional_ticks = ticks.rem_euclid(scale) as u32;
473 let nanos = fractional_ticks * 10_u32.pow(9 - precision as u32);
474
475 DateTime::from_timestamp(seconds, nanos)
476 .map(|dt| dt.with_timezone(tz.unwrap_or(&Tz::UTC)).to_utc())
477 .ok_or_else(|| anyhow!("Invalid datetime64 value: {} ticks", ticks).into())
478 }
479
480 fn read_decimal(&mut self, precision: u8, scale: u8) -> Result<Decimal, ClickHouseSourceError> {
481 match precision {
482 1..=9 => {
483 let value = self.read_i32()?;
484 Ok(Decimal::new(value as i64, scale as u32))
485 }
486 10..=18 => {
487 let value = self.read_i64()?;
488 Ok(Decimal::new(value, scale as u32))
489 }
490 _ => Err(anyhow!("Unsupported Decimal precision: {}", precision).into()),
491 }
492 }
493
494 fn read_time(&mut self) -> Result<NaiveTime, ClickHouseSourceError> {
495 let seconds = self.read_u32()? as i64;
496 Ok(
497 NaiveTime::from_num_seconds_from_midnight_opt(seconds as u32, 0)
498 .ok_or_else(|| anyhow!("Invalid time value: {} seconds since midnight", seconds))?,
499 )
500 }
501
502 fn read_time64(&mut self, precision: u8) -> Result<NaiveTime, ClickHouseSourceError> {
503 if precision > 9 {
504 return Err(anyhow!("Unsupported Time64 precision: {}", precision).into());
505 }
506 let ticks = self.read_i64()?;
507 let nanos = ticks * 10_i64.pow(9 - precision as u32);
508 Ok(NaiveTime::from_num_seconds_from_midnight_opt(
509 (nanos / 1_000_000_000) as u32,
510 (nanos % 1_000_000_000) as u32,
511 )
512 .ok_or_else(|| anyhow!("Invalid time64 value: {} ticks since midnight", ticks))?)
513 }
514
515 fn read_ipv4(&mut self) -> Result<IpAddr, ClickHouseSourceError> {
516 let bytes = self.read_u32()?;
517
518 Ok(IpAddr::V4(Ipv4Addr::from_bits(bytes)))
519 }
520
521 fn read_ipv6(&mut self) -> Result<IpAddr, ClickHouseSourceError> {
522 let seg1 = u16::from_be(self.read_u16()?);
523 let seg2 = u16::from_be(self.read_u16()?);
524 let seg3 = u16::from_be(self.read_u16()?);
525 let seg4 = u16::from_be(self.read_u16()?);
526 let seg5 = u16::from_be(self.read_u16()?);
527 let seg6 = u16::from_be(self.read_u16()?);
528 let seg7 = u16::from_be(self.read_u16()?);
529 let seg8 = u16::from_be(self.read_u16()?);
530
531 Ok(IpAddr::V6(Ipv6Addr::from_segments([
532 seg1, seg2, seg3, seg4, seg5, seg6, seg7, seg8,
533 ])))
534 }
535
536 fn read_enum8(&mut self) -> Result<i8, ClickHouseSourceError> {
537 self.read_i8()
538 }
539
540 fn read_enum16(&mut self) -> Result<i16, ClickHouseSourceError> {
541 self.read_i16()
542 }
543
544 fn read_array<T, F>(&mut self, read_elem: F) -> Result<Vec<Option<T>>, ClickHouseSourceError>
545 where
546 F: Fn(&mut Self) -> Result<T, ClickHouseSourceError>,
547 {
548 let len = self.read_varint()? as usize;
549 let mut result = Vec::with_capacity(len);
550 for _ in 0..len {
551 result.push(Some(read_elem(self)?));
552 }
553 Ok(result)
554 }
555
556 fn is_empty(&self) -> bool {
557 self.cursor.position() as usize >= self.cursor.get_ref().len()
558 }
559}
560
561pub struct ClickHouseSourceParser<'a> {
562 rt: Arc<Runtime>,
563 client: Client,
564 query: CXQuery<String>,
565 schema: Vec<ClickHouseTypeSystem>,
566 metadata: Vec<TypeMetadata>,
567 rowbuf: Vec<Vec<DataType>>,
568 ncols: usize,
569 current_row: usize,
570 current_col: usize,
571 is_finished: bool,
572 _phantom: std::marker::PhantomData<&'a ()>,
573}
574
575impl<'a> ClickHouseSourceParser<'a> {
576 #[throws(ClickHouseSourceError)]
577 pub fn new(
578 rt: Arc<Runtime>,
579 client: Client,
580 query: CXQuery<String>,
581 schema: &[ClickHouseTypeSystem],
582 metadata: &[TypeMetadata],
583 ) -> Self {
584 Self {
585 rt,
586 client,
587 query,
588 schema: schema.to_vec(),
589 metadata: metadata.to_vec(),
590 rowbuf: Vec::new(),
591 ncols: schema.len(),
592 current_row: 0,
593 current_col: 0,
594 is_finished: false,
595 _phantom: std::marker::PhantomData,
596 }
597 }
598
599 fn parse_row_binary(
600 &self,
601 reader: &mut BinaryReader,
602 ) -> Result<Vec<DataType>, ClickHouseSourceError> {
603 let mut row = Vec::with_capacity(self.ncols);
604
605 for (col_idx, col_type) in self.schema.iter().enumerate() {
606 let is_nullable = col_type.is_nullable();
607 let meta = &self.metadata[col_idx];
608
609 if is_nullable {
610 let null_flag = reader.read_u8()?;
611 if null_flag == 1 {
612 row.push(DataType::Null);
613 continue;
614 }
615 }
616
617 let value = match col_type {
618 ClickHouseTypeSystem::Int8(_) => DataType::Int8(reader.read_i8()?),
619 ClickHouseTypeSystem::Int16(_) => DataType::Int16(reader.read_i16()?),
620 ClickHouseTypeSystem::Int32(_) => DataType::Int32(reader.read_i32()?),
621 ClickHouseTypeSystem::Int64(_) => DataType::Int64(reader.read_i64()?),
622 ClickHouseTypeSystem::UInt8(_) => DataType::UInt8(reader.read_u8()?),
623 ClickHouseTypeSystem::UInt16(_) => DataType::UInt16(reader.read_u16()?),
624 ClickHouseTypeSystem::UInt32(_) => DataType::UInt32(reader.read_u32()?),
625 ClickHouseTypeSystem::UInt64(_) => DataType::UInt64(reader.read_u64()?),
626
627 ClickHouseTypeSystem::Float32(_) => DataType::Float32(reader.read_f32()?),
628 ClickHouseTypeSystem::Float64(_) => DataType::Float64(reader.read_f64()?),
629
630 ClickHouseTypeSystem::Decimal(_) => {
631 DataType::Decimal(reader.read_decimal(meta.precision, meta.scale)?)
632 }
633
634 ClickHouseTypeSystem::String(_) => DataType::String(reader.read_string()?),
635
636 ClickHouseTypeSystem::FixedString(_) => {
637 DataType::FixedString(reader.read_fixed_string(meta.length)?)
638 }
639
640 ClickHouseTypeSystem::Date(_) => DataType::Date(reader.read_date()?),
641 ClickHouseTypeSystem::Date32(_) => DataType::Date32(reader.read_date32()?),
642
643 ClickHouseTypeSystem::DateTime(_) => {
644 DataType::DateTime(reader.read_datetime(meta.timezone.as_ref())?)
645 }
646 ClickHouseTypeSystem::DateTime64(_) => DataType::DateTime64(
647 reader.read_datetime64(meta.precision, meta.timezone.as_ref())?,
648 ),
649
650 ClickHouseTypeSystem::Time(_) => DataType::Time(reader.read_time()?),
651 ClickHouseTypeSystem::Time64(_) => {
652 DataType::Time64(reader.read_time64(meta.precision)?)
653 }
654
655 ClickHouseTypeSystem::Enum8(_) => {
656 let enum_value = reader.read_enum8()?;
657 let enum_str = meta
658 .named_values
659 .as_ref()
660 .and_then(|h| h.get(&(enum_value as i16)));
661 DataType::Enum8(enum_str.cloned().unwrap_or_default())
662 }
663 ClickHouseTypeSystem::Enum16(_) => {
664 let enum_value = reader.read_enum16()?;
665 let enum_str = meta.named_values.as_ref().and_then(|h| h.get(&enum_value));
666 DataType::Enum16(enum_str.cloned().unwrap_or_default())
667 }
668
669 ClickHouseTypeSystem::UUID(_) => DataType::UUID(reader.read_uuid()?),
670
671 ClickHouseTypeSystem::IPv4(_) => DataType::IPv4(reader.read_ipv4()?),
672 ClickHouseTypeSystem::IPv6(_) => DataType::IPv6(reader.read_ipv6()?),
673
674 ClickHouseTypeSystem::Bool(_) => DataType::Bool(reader.read_bool()?),
675
676 ClickHouseTypeSystem::ArrayBool(_) => {
677 DataType::ArrayBool(reader.read_array(BinaryReader::read_bool)?)
678 }
679 ClickHouseTypeSystem::ArrayString(_) => {
680 DataType::ArrayString(reader.read_array(BinaryReader::read_string)?)
681 }
682 ClickHouseTypeSystem::ArrayInt8(_) => {
683 DataType::ArrayInt8(reader.read_array(BinaryReader::read_i8)?)
684 }
685 ClickHouseTypeSystem::ArrayInt16(_) => {
686 DataType::ArrayInt16(reader.read_array(BinaryReader::read_i16)?)
687 }
688 ClickHouseTypeSystem::ArrayInt32(_) => {
689 DataType::ArrayInt32(reader.read_array(BinaryReader::read_i32)?)
690 }
691 ClickHouseTypeSystem::ArrayInt64(_) => {
692 DataType::ArrayInt64(reader.read_array(BinaryReader::read_i64)?)
693 }
694 ClickHouseTypeSystem::ArrayUInt8(_) => {
695 DataType::ArrayUInt8(reader.read_array(BinaryReader::read_u8)?)
696 }
697 ClickHouseTypeSystem::ArrayUInt16(_) => {
698 DataType::ArrayUInt16(reader.read_array(BinaryReader::read_u16)?)
699 }
700 ClickHouseTypeSystem::ArrayUInt32(_) => {
701 DataType::ArrayUInt32(reader.read_array(BinaryReader::read_u32)?)
702 }
703 ClickHouseTypeSystem::ArrayUInt64(_) => {
704 DataType::ArrayUInt64(reader.read_array(BinaryReader::read_u64)?)
705 }
706 ClickHouseTypeSystem::ArrayFloat32(_) => {
707 DataType::ArrayFloat32(reader.read_array(BinaryReader::read_f32)?)
708 }
709 ClickHouseTypeSystem::ArrayFloat64(_) => {
710 DataType::ArrayFloat64(reader.read_array(BinaryReader::read_f64)?)
711 }
712 ClickHouseTypeSystem::ArrayDecimal(_) => {
713 let precision = meta.precision;
714 let scale = meta.scale;
715 DataType::ArrayDecimal(reader.read_array(|r| r.read_decimal(precision, scale))?)
716 }
717 };
718
719 row.push(value);
720 }
721
722 Ok(row)
723 }
724
725 #[throws(ClickHouseSourceError)]
726 fn next_loc(&mut self) -> (usize, usize) {
727 let ret = (self.current_row, self.current_col);
728 self.current_row += (self.current_col + 1) / self.ncols;
729 self.current_col = (self.current_col + 1) % self.ncols;
730 ret
731 }
732}
733
734impl<'a> PartitionParser<'a> for ClickHouseSourceParser<'a> {
735 type TypeSystem = ClickHouseTypeSystem;
736 type Error = ClickHouseSourceError;
737
738 #[throws(ClickHouseSourceError)]
739 fn fetch_next(&mut self) -> (usize, bool) {
740 assert!(self.current_col == 0);
741
742 if self.is_finished {
743 return (0, true);
744 }
745
746 let response = self.rt.block_on(async {
747 let mut cursor = self
748 .client
749 .query(self.query.as_str())
750 .fetch_bytes("RowBinary")
751 .map_err(|e| anyhow!("ClickHouse error: {}", e))?;
752 let bytes = cursor
753 .collect()
754 .await
755 .map_err(|e| anyhow!("ClickHouse error: {}", e))?;
756 Ok::<_, ClickHouseSourceError>(bytes)
757 })?;
758 let mut reader = BinaryReader::new(&response);
759 let mut rows = Vec::new();
760
761 while !reader.is_empty() {
762 match self.parse_row_binary(&mut reader) {
763 Ok(row) => rows.push(row),
764 Err(_) => break,
765 }
766 }
767
768 self.rowbuf = rows;
769 self.current_row = 0;
770 self.is_finished = true;
771
772 (self.rowbuf.len(), true)
773 }
774}
775
776macro_rules! impl_produce {
777 ($rust_type:ty, [$($variant:ident),+]) => {
778 impl<'r, 'a> Produce<'r, $rust_type> for ClickHouseSourceParser<'a> {
779 type Error = ClickHouseSourceError;
780
781 #[throws(ClickHouseSourceError)]
782 fn produce(&'r mut self) -> $rust_type {
783 let (ridx, cidx) = self.next_loc()?;
784 let value = &self.rowbuf[ridx][cidx];
785
786 match value {
787 $(DataType::$variant(v) => *v as $rust_type,)+
788 _ => throw!(ConnectorXError::cannot_produce::<$rust_type>(Some(
789 format!("{:?}", value)
790 ))),
791 }
792 }
793 }
794
795 impl<'r, 'a> Produce<'r, Option<$rust_type>> for ClickHouseSourceParser<'a> {
796 type Error = ClickHouseSourceError;
797
798 #[throws(ClickHouseSourceError)]
799 fn produce(&'r mut self) -> Option<$rust_type> {
800 let (ridx, cidx) = self.next_loc()?;
801 let value = &self.rowbuf[ridx][cidx];
802
803 match value {
804 DataType::Null => None,
805 $(DataType::$variant(v) => Some(*v as $rust_type),)+
806 _ => throw!(ConnectorXError::cannot_produce::<$rust_type>(Some(
807 format!("{:?}", value)
808 ))),
809 }
810 }
811 }
812 };
813}
814
815macro_rules! impl_produce_with_clone {
816 ($rust_type:ty, [$($variant:ident),+]) => {
817 impl<'r, 'a> Produce<'r, $rust_type> for ClickHouseSourceParser<'a> {
818 type Error = ClickHouseSourceError;
819
820 #[throws(ClickHouseSourceError)]
821 fn produce(&'r mut self) -> $rust_type {
822 let (ridx, cidx) = self.next_loc()?;
823 let value = &self.rowbuf[ridx][cidx];
824
825 match value {
826 $(DataType::$variant(v) => v.clone() as $rust_type,)+
827 _ => throw!(ConnectorXError::cannot_produce::<$rust_type>(Some(
828 format!("{:?}", value)
829 ))),
830 }
831 }
832 }
833
834 impl<'r, 'a> Produce<'r, Option<$rust_type>> for ClickHouseSourceParser<'a> {
835 type Error = ClickHouseSourceError;
836
837 #[throws(ClickHouseSourceError)]
838 fn produce(&'r mut self) -> Option<$rust_type> {
839 let (ridx, cidx) = self.next_loc()?;
840 let value = &self.rowbuf[ridx][cidx];
841
842 match value {
843 DataType::Null => None,
844 $(DataType::$variant(v) => Some(v.clone() as $rust_type),)+
845 _ => throw!(ConnectorXError::cannot_produce::<$rust_type>(Some(
846 format!("{:?}", value)
847 ))),
848 }
849 }
850 }
851 };
852}
853
854macro_rules! impl_produce_vec {
855 ($rust_type:ty, [$($variant:ident),+]) => {
856 impl<'r, 'a> Produce<'r, Vec<Option<$rust_type>>> for ClickHouseSourceParser<'a> {
857 type Error = ClickHouseSourceError;
858
859 #[throws(ClickHouseSourceError)]
860 fn produce(&'r mut self) -> Vec<Option<$rust_type>> {
861 let (ridx, cidx) = self.next_loc()?;
862 let value = &self.rowbuf[ridx][cidx];
863
864 match value {
865 $(DataType::$variant(v) => v.clone(),)+
866 _ => throw!(ConnectorXError::cannot_produce::<Vec<Option<$rust_type>>>(Some(
867 format!("{:?}", value)
868 ))),
869 }
870 }
871 }
872
873 impl<'r, 'a> Produce<'r, Option<Vec<Option<$rust_type>>>> for ClickHouseSourceParser<'a> {
874 type Error = ClickHouseSourceError;
875
876 #[throws(ClickHouseSourceError)]
877 fn produce(&'r mut self) -> Option<Vec<Option<$rust_type>>> {
878 let (ridx, cidx) = self.next_loc()?;
879 let value = &self.rowbuf[ridx][cidx];
880
881 match value {
882 DataType::Null => None,
883 $(DataType::$variant(v) => Some(v.clone()),)+
884 _ => throw!(ConnectorXError::cannot_produce::<Option<Vec<Option<$rust_type>>>>(Some(
885 format!("{:?}", value)
886 ))),
887 }
888 }
889 }
890 };
891}
892
893impl_produce!(i8, [Int8]);
894impl_produce!(i16, [Int16]);
895impl_produce!(i32, [Int32]);
896impl_produce!(i64, [Int64]);
897impl_produce!(u8, [UInt8]);
898impl_produce!(u16, [UInt16]);
899impl_produce!(u32, [UInt32]);
900impl_produce!(u64, [UInt64]);
901impl_produce!(f32, [Float32]);
902impl_produce!(f64, [Float64]);
903impl_produce!(Decimal, [Decimal]);
904impl_produce_with_clone!(String, [String, Enum8, Enum16]);
905impl_produce_with_clone!(Vec<u8>, [FixedString]);
906impl_produce!(NaiveDate, [Date, Date32]);
907impl_produce!(DateTime<Utc>, [DateTime, DateTime64]);
908impl_produce!(NaiveTime, [Time, Time64]);
909impl_produce!(Uuid, [UUID]);
910impl_produce!(IpAddr, [IPv4, IPv6]);
911impl_produce!(bool, [Bool]);
912impl_produce_vec!(bool, [ArrayBool]);
913impl_produce_vec!(String, [ArrayString]);
914impl_produce_vec!(i8, [ArrayInt8]);
915impl_produce_vec!(i16, [ArrayInt16]);
916impl_produce_vec!(i32, [ArrayInt32]);
917impl_produce_vec!(i64, [ArrayInt64]);
918impl_produce_vec!(u8, [ArrayUInt8]);
919impl_produce_vec!(u16, [ArrayUInt16]);
920impl_produce_vec!(u32, [ArrayUInt32]);
921impl_produce_vec!(u64, [ArrayUInt64]);
922impl_produce_vec!(f32, [ArrayFloat32]);
923impl_produce_vec!(f64, [ArrayFloat64]);
924impl_produce_vec!(Decimal, [ArrayDecimal]);