Skip to main content

reifydb_core/value/column/buffer/
extend.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::mem;
5
6use reifydb_type::{Result, storage::DataBitVec, util::bitvec::BitVec};
7
8use crate::{
9	return_internal_error,
10	value::column::{ColumnBuffer, buffer::with_container},
11};
12
13impl ColumnBuffer {
14	pub fn extend(&mut self, other: ColumnBuffer) -> Result<()> {
15		match (&mut *self, other) {
16			(ColumnBuffer::Bool(l), ColumnBuffer::Bool(r)) => l.extend(&r)?,
17			(ColumnBuffer::Float4(l), ColumnBuffer::Float4(r)) => l.extend(&r)?,
18			(ColumnBuffer::Float8(l), ColumnBuffer::Float8(r)) => l.extend(&r)?,
19			(ColumnBuffer::Int1(l), ColumnBuffer::Int1(r)) => l.extend(&r)?,
20			(ColumnBuffer::Int2(l), ColumnBuffer::Int2(r)) => l.extend(&r)?,
21			(ColumnBuffer::Int4(l), ColumnBuffer::Int4(r)) => l.extend(&r)?,
22			(ColumnBuffer::Int8(l), ColumnBuffer::Int8(r)) => l.extend(&r)?,
23			(ColumnBuffer::Int16(l), ColumnBuffer::Int16(r)) => l.extend(&r)?,
24			(ColumnBuffer::Uint1(l), ColumnBuffer::Uint1(r)) => l.extend(&r)?,
25			(ColumnBuffer::Uint2(l), ColumnBuffer::Uint2(r)) => l.extend(&r)?,
26			(ColumnBuffer::Uint4(l), ColumnBuffer::Uint4(r)) => l.extend(&r)?,
27			(ColumnBuffer::Uint8(l), ColumnBuffer::Uint8(r)) => l.extend(&r)?,
28			(ColumnBuffer::Uint16(l), ColumnBuffer::Uint16(r)) => l.extend(&r)?,
29			(
30				ColumnBuffer::Utf8 {
31					container: l,
32					..
33				},
34				ColumnBuffer::Utf8 {
35					container: r,
36					..
37				},
38			) => l.extend(&r)?,
39			(ColumnBuffer::Date(l), ColumnBuffer::Date(r)) => l.extend(&r)?,
40			(ColumnBuffer::DateTime(l), ColumnBuffer::DateTime(r)) => l.extend(&r)?,
41			(ColumnBuffer::Time(l), ColumnBuffer::Time(r)) => l.extend(&r)?,
42			(ColumnBuffer::Duration(l), ColumnBuffer::Duration(r)) => l.extend(&r)?,
43			(ColumnBuffer::IdentityId(l), ColumnBuffer::IdentityId(r)) => l.extend(&r)?,
44			(ColumnBuffer::Uuid4(l), ColumnBuffer::Uuid4(r)) => l.extend(&r)?,
45			(ColumnBuffer::Uuid7(l), ColumnBuffer::Uuid7(r)) => l.extend(&r)?,
46			(
47				ColumnBuffer::Blob {
48					container: l,
49					..
50				},
51				ColumnBuffer::Blob {
52					container: r,
53					..
54				},
55			) => l.extend(&r)?,
56			(
57				ColumnBuffer::Int {
58					container: l,
59					..
60				},
61				ColumnBuffer::Int {
62					container: r,
63					..
64				},
65			) => l.extend(&r)?,
66			(
67				ColumnBuffer::Uint {
68					container: l,
69					..
70				},
71				ColumnBuffer::Uint {
72					container: r,
73					..
74				},
75			) => l.extend(&r)?,
76			(
77				ColumnBuffer::Decimal {
78					container: l,
79					..
80				},
81				ColumnBuffer::Decimal {
82					container: r,
83					..
84				},
85			) => l.extend(&r)?,
86			(ColumnBuffer::DictionaryId(l), ColumnBuffer::DictionaryId(r)) => l.extend(&r)?,
87			(ColumnBuffer::Any(l), ColumnBuffer::Any(r)) => l.extend(&r)?,
88
89			(
90				ColumnBuffer::Option {
91					inner: l_inner,
92					bitvec: l_bitvec,
93				},
94				ColumnBuffer::Option {
95					inner: r_inner,
96					bitvec: r_bitvec,
97				},
98			) => {
99				if l_inner.get_type() == r_inner.get_type() {
100					l_inner.extend(*r_inner)?;
101				} else if DataBitVec::count_ones(&r_bitvec) == 0 {
102					let r_len = r_inner.len();
103					with_container!(l_inner.as_mut(), |c| {
104						for _ in 0..r_len {
105							c.push_default();
106						}
107					});
108				} else if DataBitVec::count_ones(l_bitvec) == 0 {
109					let l_len = l_inner.len();
110					let r_type = r_inner.get_type();
111					let (mut new_inner, _) =
112						ColumnBuffer::none_typed(r_type, l_len).into_unwrap_option();
113					new_inner.extend(*r_inner)?;
114					**l_inner = new_inner;
115				} else {
116					return_internal_error!("column type mismatch in Option extend");
117				}
118				DataBitVec::extend_from(l_bitvec, &r_bitvec);
119			}
120
121			(
122				ColumnBuffer::Option {
123					inner,
124					bitvec,
125				},
126				other,
127			) => {
128				let other_len = other.len();
129				if inner.get_type() != other.get_type() && DataBitVec::count_ones(bitvec) == 0 {
130					let l_len = inner.len();
131					let r_type = other.get_type();
132					let (mut new_inner, _) =
133						ColumnBuffer::none_typed(r_type, l_len).into_unwrap_option();
134					new_inner.extend(other)?;
135					**inner = new_inner;
136				} else {
137					inner.extend(other)?;
138				}
139				for _ in 0..other_len {
140					DataBitVec::push(bitvec, true);
141				}
142			}
143
144			(
145				_,
146				ColumnBuffer::Option {
147					inner: r_inner,
148					bitvec: r_bitvec,
149				},
150			) => {
151				let l_len = self.len();
152				let r_len = r_inner.len();
153				let mut l_bitvec = BitVec::repeat(l_len, true);
154				DataBitVec::extend_from(&mut l_bitvec, &r_bitvec);
155				let inner = mem::replace(self, ColumnBuffer::bool(vec![]));
156				let mut boxed_inner = Box::new(inner);
157
158				if boxed_inner.get_type() != r_inner.get_type()
159					&& DataBitVec::count_ones(&r_bitvec) == 0
160				{
161					with_container!(boxed_inner.as_mut(), |c| {
162						for _ in 0..r_len {
163							c.push_default();
164						}
165					});
166				} else {
167					boxed_inner.extend(*r_inner)?;
168				}
169
170				*self = ColumnBuffer::Option {
171					inner: boxed_inner,
172					bitvec: l_bitvec,
173				};
174			}
175
176			(_, _) => {
177				return_internal_error!("column type mismatch");
178			}
179		}
180
181		Ok(())
182	}
183}