Skip to main content

reifydb_core/value/column/data/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4pub mod canonical;
5
6use std::{any::Any, sync::Arc};
7
8use canonical::Canonical;
9use reifydb_value::{
10	Result,
11	util::bitvec::BitVec,
12	value::{Value, value_type::ValueType},
13};
14
15use crate::value::column::{
16	buffer::ColumnBuffer, encoding::EncodingId, mask::RowMask, nones::NoneBitmap, stats::StatsSet,
17};
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20pub enum CompareOp {
21	Eq,
22	Ne,
23	Lt,
24	LtEq,
25	Gt,
26	GtEq,
27}
28
29#[derive(Clone, Copy, Debug, PartialEq, Eq)]
30pub enum SearchResult {
31	Found(usize),
32	NotFound(usize),
33}
34
35pub trait ColumnData: Send + Sync + 'static {
36	fn ty(&self) -> ValueType;
37	fn len(&self) -> usize;
38	fn is_empty(&self) -> bool {
39		self.len() == 0
40	}
41	fn encoding(&self) -> EncodingId;
42
43	fn is_nullable(&self) -> bool;
44	fn nones(&self) -> Option<&NoneBitmap>;
45	fn is_defined(&self, idx: usize) -> bool {
46		!self.nones().map(|n| n.is_none(idx)).unwrap_or(false)
47	}
48
49	fn stats(&self) -> &StatsSet;
50
51	fn get_value(&self, idx: usize) -> Value;
52	fn iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
53		Box::new((0..self.len()).map(move |i| self.get_value(i)))
54	}
55	fn as_string(&self, idx: usize) -> String;
56
57	fn as_any(&self) -> &dyn Any;
58	fn as_any_mut(&mut self) -> &mut dyn Any;
59
60	fn children(&self) -> &[Column];
61	fn metadata(&self) -> &dyn Any;
62
63	fn to_canonical(&self) -> Result<Arc<Canonical>>;
64
65	fn filter(&self, mask: &RowMask) -> Result<Column> {
66		let canon = self.to_canonical()?;
67		Ok(Column::from_canonical(canonical_filter(&canon, mask)?))
68	}
69
70	fn take(&self, indices: &Column) -> Result<Column> {
71		let canon = self.to_canonical()?;
72		let idx = canon_indices(indices)?;
73		Ok(Column::from_canonical(canonical_take(&canon, &idx)?))
74	}
75
76	fn slice(&self, start: usize, end: usize) -> Result<Column> {
77		let canon = self.to_canonical()?;
78		Ok(Column::from_canonical(canonical_slice(&canon, start, end)?))
79	}
80}
81
82#[derive(Clone)]
83pub struct Column(Arc<dyn ColumnData>);
84
85impl Column {
86	pub fn from_data(data: Arc<dyn ColumnData>) -> Self {
87		Self(data)
88	}
89
90	pub fn from_canonical(canon: Canonical) -> Self {
91		Self(Arc::new(canon))
92	}
93
94	pub fn from_column_buffer(buffer: ColumnBuffer) -> Self {
95		Self::from_canonical(Canonical::from_buffer(buffer))
96	}
97
98	pub fn data(&self) -> &dyn ColumnData {
99		&*self.0
100	}
101
102	pub fn ty(&self) -> ValueType {
103		self.0.ty()
104	}
105
106	pub fn is_nullable(&self) -> bool {
107		self.0.is_nullable()
108	}
109
110	pub fn len(&self) -> usize {
111		self.0.len()
112	}
113
114	pub fn is_empty(&self) -> bool {
115		self.0.is_empty()
116	}
117
118	pub fn encoding(&self) -> EncodingId {
119		self.0.encoding()
120	}
121
122	pub fn stats(&self) -> &StatsSet {
123		self.0.stats()
124	}
125
126	pub fn nones(&self) -> Option<&NoneBitmap> {
127		self.0.nones()
128	}
129
130	pub fn is_defined(&self, idx: usize) -> bool {
131		self.0.is_defined(idx)
132	}
133
134	pub fn get_value(&self, idx: usize) -> Value {
135		self.0.get_value(idx)
136	}
137
138	pub fn iter(&self) -> Box<dyn Iterator<Item = Value> + '_> {
139		self.0.iter()
140	}
141
142	pub fn as_string(&self, idx: usize) -> String {
143		self.0.as_string(idx)
144	}
145
146	pub fn children(&self) -> &[Column] {
147		self.0.children()
148	}
149
150	pub fn metadata(&self) -> &dyn Any {
151		self.0.metadata()
152	}
153
154	pub fn to_canonical(&self) -> Result<Arc<Canonical>> {
155		self.0.to_canonical()
156	}
157
158	pub fn filter(&self, mask: &RowMask) -> Result<Column> {
159		self.0.filter(mask)
160	}
161
162	pub fn take(&self, indices: &Column) -> Result<Column> {
163		self.0.take(indices)
164	}
165
166	pub fn slice(&self, start: usize, end: usize) -> Result<Column> {
167		self.0.slice(start, end)
168	}
169
170	pub fn materialize(&mut self) -> Result<&mut Canonical> {
171		if Arc::get_mut(&mut self.0).map(|d| d.as_any().is::<Canonical>()).unwrap_or(false) {
172			let d = Arc::get_mut(&mut self.0).unwrap();
173			return Ok(d.as_any_mut().downcast_mut::<Canonical>().unwrap());
174		}
175		let canonical_arc = self.0.to_canonical()?;
176		let owned = Arc::try_unwrap(canonical_arc).unwrap_or_else(|arc| (*arc).clone());
177		self.0 = Arc::new(owned);
178		let d = Arc::get_mut(&mut self.0).unwrap();
179		Ok(d.as_any_mut().downcast_mut::<Canonical>().unwrap())
180	}
181}
182
183fn canonical_filter(canon: &Canonical, mask: &RowMask) -> Result<Canonical> {
184	assert_eq!(canon.len(), mask.len(), "filter: length mismatch");
185	let kept = mask.popcount();
186
187	let new_nones = canon.nones.as_ref().map(|n| {
188		let mut out = NoneBitmap::all_present(kept);
189		let mut j = 0usize;
190		for i in 0..n.len() {
191			if mask.get(i) {
192				if n.is_none(i) {
193					out.set_none(j);
194				}
195				j += 1;
196			}
197		}
198		out
199	});
200
201	let mut new_buffer = canon.buffer.clone();
202	new_buffer.filter(&row_mask_to_bitvec(mask))?;
203
204	Ok(Canonical::new(canon.ty.clone(), canon.nullable, new_nones, new_buffer))
205}
206
207fn canonical_take(canon: &Canonical, indices: &[usize]) -> Result<Canonical> {
208	let new_nones = canon.nones.as_ref().map(|n| {
209		let mut out = NoneBitmap::all_present(indices.len());
210		for (j, &i) in indices.iter().enumerate() {
211			if n.is_none(i) {
212				out.set_none(j);
213			}
214		}
215		out
216	});
217	let new_buffer = canon.buffer.gather(indices);
218	Ok(Canonical::new(canon.ty.clone(), canon.nullable, new_nones, new_buffer))
219}
220
221fn canonical_slice(canon: &Canonical, start: usize, end: usize) -> Result<Canonical> {
222	assert!(start <= end);
223	assert!(end <= canon.len());
224	let new_nones = canon.nones.as_ref().map(|n| {
225		let count = end - start;
226		let mut out = NoneBitmap::all_present(count);
227		for i in 0..count {
228			if n.is_none(start + i) {
229				out.set_none(i);
230			}
231		}
232		out
233	});
234	let new_buffer = canon.buffer.slice(start, end);
235	Ok(Canonical::new(canon.ty.clone(), canon.nullable, new_nones, new_buffer))
236}
237
238fn row_mask_to_bitvec(mask: &RowMask) -> BitVec {
239	let mut bits = Vec::with_capacity(mask.len());
240	for i in 0..mask.len() {
241		bits.push(mask.get(i));
242	}
243	BitVec::from(bits)
244}
245
246fn canon_indices(indices: &Column) -> Result<Vec<usize>> {
247	let canon = indices.to_canonical()?;
248	let len = canon.len();
249	let mut out = Vec::with_capacity(len);
250	for i in 0..len {
251		let v = canon.buffer.get_value(i);
252		let n: usize = match v {
253			Value::Uint1(n) => n as usize,
254			Value::Uint2(n) => n as usize,
255			Value::Uint4(n) => n as usize,
256			Value::Uint8(n) => n as usize,
257			Value::Int4(n) => n as usize,
258			Value::Int8(n) => n as usize,
259			_ => panic!("take: indices must be fixed-width unsigned/signed int"),
260		};
261		out.push(n);
262	}
263	Ok(out)
264}