|
12 | 12 | // See the License for the specific language governing permissions and |
13 | 13 | // limitations under the License. |
14 | 14 |
|
15 | | -use std::fmt::Write; |
16 | 15 | use std::sync::Arc; |
17 | 16 |
|
18 | | -use common_exception::ErrorCode; |
19 | 17 | use common_exception::Result; |
20 | 18 | use common_io::prelude::FormatSettings; |
21 | 19 | use opensrv_clickhouse::types::column::ArrayColumnData; |
22 | 20 | use serde_json::Value; |
23 | 21 |
|
24 | 22 | use crate::prelude::*; |
25 | 23 |
|
26 | | -#[derive(Debug, Clone)] |
27 | | -pub struct ArraySerializer { |
28 | | - pub inner: Box<TypeSerializerImpl>, |
29 | | - pub typ: DataTypeImpl, |
| 24 | +#[derive(Clone)] |
| 25 | +pub struct ArraySerializer<'a> { |
| 26 | + offsets: &'a [i64], |
| 27 | + inner: Box<TypeSerializerImpl<'a>>, |
30 | 28 | } |
31 | 29 |
|
32 | | -impl TypeSerializer for ArraySerializer { |
33 | | - fn serialize_value(&self, value: &DataValue, format: &FormatSettings) -> Result<String> { |
34 | | - if let DataValue::Array(vals) = value { |
35 | | - let mut res = String::new(); |
36 | | - res.push('['); |
37 | | - let mut first = true; |
38 | | - let quoted = self.typ.data_type_id().is_quoted(); |
39 | | - for val in vals { |
40 | | - if !first { |
41 | | - res.push_str(", "); |
42 | | - } |
43 | | - first = false; |
| 30 | +impl<'a> ArraySerializer<'a> { |
| 31 | + pub fn try_create(column: &'a ColumnRef, inner_type: &DataTypeImpl) -> Result<Self> { |
| 32 | + let column: &ArrayColumn = Series::check_get(column)?; |
| 33 | + let inner = Box::new(inner_type.create_serializer(column.values())?); |
| 34 | + Ok(Self { |
| 35 | + offsets: column.offsets(), |
| 36 | + inner, |
| 37 | + }) |
| 38 | + } |
| 39 | +} |
44 | 40 |
|
45 | | - let s = self.inner.serialize_value(val, format)?; |
46 | | - if quoted { |
47 | | - write!(res, "'{s}'").expect("write to string must succeed"); |
48 | | - } else { |
49 | | - res.push_str(&s); |
50 | | - } |
| 41 | +impl<'a> TypeSerializer<'a> for ArraySerializer<'a> { |
| 42 | + fn write_field(&self, row_index: usize, buf: &mut Vec<u8>, format: &FormatSettings) { |
| 43 | + let start = self.offsets[row_index] as usize; |
| 44 | + let end = self.offsets[row_index + 1] as usize; |
| 45 | + buf.push(b'['); |
| 46 | + let inner = &self.inner; |
| 47 | + for i in start..end { |
| 48 | + if i != start { |
| 49 | + buf.extend_from_slice(b", "); |
51 | 50 | } |
52 | | - res.push(']'); |
53 | | - Ok(res) |
54 | | - } else { |
55 | | - Err(ErrorCode::BadBytes("Incorrect Array value")) |
| 51 | + inner.write_field_quoted(i, buf, format, b'\''); |
56 | 52 | } |
| 53 | + buf.push(b']'); |
57 | 54 | } |
58 | 55 |
|
59 | | - fn serialize_column(&self, column: &ColumnRef, format: &FormatSettings) -> Result<Vec<String>> { |
60 | | - let column: &ArrayColumn = Series::check_get(column)?; |
61 | | - let mut result = Vec::with_capacity(column.len()); |
62 | | - for i in 0..column.len() { |
63 | | - let val = column.get(i); |
64 | | - let s = self.serialize_value(&val, format)?; |
65 | | - result.push(s); |
| 56 | + fn serialize_clickhouse_const( |
| 57 | + &self, |
| 58 | + format: &FormatSettings, |
| 59 | + size: usize, |
| 60 | + ) -> Result<opensrv_clickhouse::types::column::ArcColumnData> { |
| 61 | + let len = self.offsets.len() - 1; |
| 62 | + let mut offsets = opensrv_clickhouse::types::column::List::with_capacity(size * len); |
| 63 | + let total = self.offsets[len]; |
| 64 | + let mut base = 0; |
| 65 | + for _ in 0..size { |
| 66 | + for offset in self.offsets.iter().skip(1) { |
| 67 | + offsets.push(((*offset) + base) as u64); |
| 68 | + } |
| 69 | + base += total; |
66 | 70 | } |
67 | | - Ok(result) |
68 | | - } |
69 | 71 |
|
70 | | - fn serialize_json(&self, column: &ColumnRef, _format: &FormatSettings) -> Result<Vec<Value>> { |
71 | | - let column: &ArrayColumn = Series::check_get(column)?; |
72 | | - let mut result = Vec::with_capacity(column.len()); |
73 | | - for i in 0..column.len() { |
74 | | - let val = column.get(i); |
75 | | - let s = serde_json::to_value(val)?; |
76 | | - result.push(s); |
77 | | - } |
78 | | - Ok(result) |
| 72 | + let inner_data = self.inner.serialize_clickhouse_const(format, size)?; |
| 73 | + Ok(Arc::new(ArrayColumnData::create(inner_data, offsets))) |
79 | 74 | } |
80 | 75 |
|
81 | | - fn serialize_clickhouse_format( |
| 76 | + fn serialize_clickhouse_column( |
82 | 77 | &self, |
83 | | - column: &ColumnRef, |
84 | 78 | format: &FormatSettings, |
85 | 79 | ) -> Result<opensrv_clickhouse::types::column::ArcColumnData> { |
86 | | - let column: &ArrayColumn = Series::check_get(column)?; |
87 | | - let mut offsets = opensrv_clickhouse::types::column::List::with_capacity(column.len()); |
88 | | - for offset in column.offsets().iter().skip(1) { |
| 80 | + let mut offsets = |
| 81 | + opensrv_clickhouse::types::column::List::with_capacity(self.offsets.len() - 1); |
| 82 | + for offset in self.offsets.iter().skip(1) { |
89 | 83 | offsets.push(*offset as u64); |
90 | 84 | } |
91 | 85 |
|
92 | | - let inner_data = self |
93 | | - .inner |
94 | | - .serialize_clickhouse_format(column.values(), format)?; |
| 86 | + let inner_data = self.inner.serialize_clickhouse_column(format)?; |
95 | 87 | Ok(Arc::new(ArrayColumnData::create(inner_data, offsets))) |
96 | 88 | } |
| 89 | + |
| 90 | + fn serialize_json(&self, format: &FormatSettings) -> Result<Vec<Value>> { |
| 91 | + let size = self.offsets.len() - 1; |
| 92 | + let mut result = Vec::with_capacity(size); |
| 93 | + let inner = self.inner.serialize_json(format)?; |
| 94 | + let mut iter = inner.into_iter(); |
| 95 | + for i in 0..size { |
| 96 | + let len = (self.offsets[i + 1] - self.offsets[i]) as usize; |
| 97 | + let chunk = iter.by_ref().take(len).collect(); |
| 98 | + result.push(Value::Array(chunk)) |
| 99 | + } |
| 100 | + Ok(result) |
| 101 | + } |
97 | 102 | } |
0 commit comments