Skip to main content

reifydb_engine/bulk_insert/
coerce.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_core::{
5	interface::catalog::column::Column,
6	value::column::{buffer::ColumnBuffer, columns::Columns},
7};
8use reifydb_routine::routine::registry::Routines;
9use reifydb_runtime::context::{RuntimeContext, clock::Clock};
10use reifydb_type::{fragment::Fragment, params::Params, value::identity::IdentityId};
11
12use crate::{
13	Result,
14	expression::{cast::cast_column_data, context::EvalContext},
15	vm::stack::SymbolTable,
16};
17
18/// Coerce each column's data to the target type in batch.
19pub(super) fn coerce_columns(
20	column_data: &[ColumnBuffer],
21	columns: &[Column],
22	num_rows: usize,
23) -> Result<Vec<ColumnBuffer>> {
24	let runtime_ctx = RuntimeContext::with_clock(Clock::Real);
25	let routines = Routines::empty();
26	let ctx = EvalContext {
27		params: &Params::None,
28		symbols: &SymbolTable::new(),
29		routines: &routines,
30		runtime_context: &runtime_ctx,
31		arena: None,
32		identity: IdentityId::root(),
33		is_aggregate_context: false,
34		columns: Columns::empty(),
35		row_count: num_rows,
36		target: None,
37		take: None,
38	};
39
40	let mut coerced_columns: Vec<ColumnBuffer> = Vec::with_capacity(columns.len());
41
42	for (col_idx, col) in columns.iter().enumerate() {
43		let target = col.constraint.get_type();
44		// For Option(T) columns, cast to the inner type T; None values pass through unchanged
45		let cast_target = target.inner_type().clone();
46		let source_data = &column_data[col_idx];
47
48		let coerced = cast_column_data(&ctx, source_data, cast_target, || Fragment::internal(&col.name))?;
49		coerced_columns.push(coerced);
50	}
51
52	Ok(coerced_columns)
53}