use arrow_array::RecordBatch;
use crate::Result;
use super::super::{
DirectEncoder, MeasuredDirectBatch, binding::BoundDirectBatch, checked_add, invalid_payload,
payload,
};
pub(crate) fn encode_measured_batch_range_into(
encoder: &DirectEncoder,
batch: &RecordBatch,
measured: &MeasuredDirectBatch,
start_row: usize,
row_count: usize,
buf: &mut tiberius::RawRowsAppendBuffer<'_>,
) -> Result<tiberius::RawRowsAppend> {
measured.check_range(start_row, row_count)?;
if measured.row_count() != batch.num_rows() {
return Err(invalid_payload(format!(
"measured row count {} does not match runtime batch row count {}",
measured.row_count(),
batch.num_rows()
)));
}
if measured.column_count() != encoder.plan.column_count() {
return Err(invalid_payload(format!(
"measured column count {} does not match direct plan column count {}",
measured.column_count(),
encoder.plan.column_count()
)));
}
let bound = BoundDirectBatch::new(encoder, batch)?;
let mut row_token_offsets = Vec::with_capacity(row_count);
let mut written = 0usize;
let end_row = start_row
.checked_add(row_count)
.ok_or_else(|| invalid_payload("direct row range end overflowed usize"))?;
for row_index in start_row..end_row {
row_token_offsets.push(written);
buf.put_u8(payload::TDS_ROW_TOKEN);
written = checked_add(written, 1)?;
for (column_index, column) in bound.columns().iter().enumerate() {
let measured_len = measured.cell_len(row_index, column_index)?;
column.append_cell(buf, row_index, measured_len)?;
written = checked_add(written, measured_len)?;
}
}
Ok(tiberius::RawRowsAppend::new(row_token_offsets))
}