Skip to main content

dre_core/
rows.rs

1//! Typed, streaming JSON row export for integrations. Decimals retain their exact text;
2//! columns carry Arrow types so consumers need not infer types from values or CSV.
3
4use std::fs::File;
5use std::io::{BufWriter, Write};
6use std::path::Path;
7
8use arrow::ipc::reader::FileReader;
9use serde_json::json;
10
11pub fn write_spool(spool: &Path, output: &Path, row_count: u64) -> anyhow::Result<()> {
12    let reader = FileReader::try_new(File::open(spool)?, None)?;
13    let columns = column_types(&reader.schema());
14    let mut out = BufWriter::new(File::create(output)?);
15    write!(
16        out,
17        "{{\"schema_version\":\"dre/rows/v1\",\"columns\":{},\"row_count\":{},\"rows\":[",
18        serde_json::to_string(&columns)?,
19        row_count
20    )?;
21    let mut first = true;
22    for batch in reader {
23        for row in crate::values::batch_rows(&batch?) {
24            if !first {
25                out.write_all(b",")?;
26            }
27            first = false;
28            serde_json::to_writer(&mut out, &row)?;
29        }
30    }
31    out.write_all(b"]}\n")?;
32    out.flush()?;
33    Ok(())
34}
35
36/// Each column's name and Arrow type, as `dre/rows/v1` lists them.
37pub fn column_types(schema: &arrow::datatypes::Schema) -> Vec<serde_json::Value> {
38    schema
39        .fields()
40        .iter()
41        .map(|f| json!({"name": f.name(), "type": f.data_type().to_string()}))
42        .collect()
43}