laminar_connectors/schema/parquet/encoder/
mod.rs1use arrow_array::RecordBatch;
7use arrow_schema::SchemaRef;
8use parquet::arrow::ArrowWriter;
9use parquet::basic::Compression;
10use parquet::file::properties::WriterProperties;
11
12use crate::schema::error::{SchemaError, SchemaResult};
13use crate::schema::traits::FormatEncoder;
14
15#[derive(Debug, Clone)]
17pub struct ParquetEncoderConfig {
18 pub compression: Compression,
20
21 pub writer_version: i32,
23
24 pub max_row_group_size: usize,
26
27 pub write_statistics: bool,
29}
30
31impl Default for ParquetEncoderConfig {
32 fn default() -> Self {
33 Self {
34 compression: Compression::SNAPPY,
35 writer_version: 2,
36 max_row_group_size: 1_000_000,
37 write_statistics: true,
38 }
39 }
40}
41
42impl ParquetEncoderConfig {
43 #[must_use]
45 pub fn with_compression(mut self, compression: Compression) -> Self {
46 self.compression = compression;
47 self
48 }
49
50 #[must_use]
52 pub fn with_writer_version(mut self, version: i32) -> Self {
53 self.writer_version = version;
54 self
55 }
56
57 #[must_use]
59 pub fn with_max_row_group_size(mut self, size: usize) -> Self {
60 self.max_row_group_size = size;
61 self
62 }
63
64 #[must_use]
66 pub fn with_statistics(mut self, enabled: bool) -> Self {
67 self.write_statistics = enabled;
68 self
69 }
70}
71
72#[derive(Debug)]
78pub struct ParquetEncoder {
79 schema: SchemaRef,
80 config: ParquetEncoderConfig,
81}
82
83impl ParquetEncoder {
84 #[must_use]
86 pub fn new(schema: SchemaRef) -> Self {
87 Self::with_config(schema, ParquetEncoderConfig::default())
88 }
89
90 #[must_use]
92 pub fn with_config(schema: SchemaRef, config: ParquetEncoderConfig) -> Self {
93 Self { schema, config }
94 }
95}
96
97impl FormatEncoder for ParquetEncoder {
98 fn input_schema(&self) -> SchemaRef {
99 self.schema.clone()
100 }
101
102 fn encode_batch(&self, batch: &RecordBatch) -> SchemaResult<Vec<Vec<u8>>> {
103 if batch.num_rows() == 0 {
104 return Ok(vec![]);
105 }
106
107 let mut props_builder = WriterProperties::builder()
108 .set_compression(self.config.compression)
109 .set_max_row_group_row_count(Some(self.config.max_row_group_size));
110
111 if !self.config.write_statistics {
112 props_builder = props_builder
113 .set_statistics_enabled(parquet::file::properties::EnabledStatistics::None);
114 }
115
116 let props = props_builder.build();
117
118 let mut buf = Vec::new();
119 let mut writer = ArrowWriter::try_new(&mut buf, self.schema.clone(), Some(props))
120 .map_err(|e| SchemaError::DecodeError(format!("Parquet writer init: {e}")))?;
121
122 writer
123 .write(batch)
124 .map_err(|e| SchemaError::DecodeError(format!("Parquet write error: {e}")))?;
125
126 writer
127 .close()
128 .map_err(|e| SchemaError::DecodeError(format!("Parquet close error: {e}")))?;
129
130 Ok(vec![buf])
132 }
133
134 fn format_name(&self) -> &'static str {
135 "parquet"
136 }
137}
138
139#[cfg(test)]
140mod tests;