Skip to main content

reifydb_core/
partition.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use reifydb_value::{
5	error::{Diagnostic, Error, IntoDiagnostic},
6	fragment::Fragment,
7};
8
9use crate::interface::catalog::{column::Column, object::ObjectId};
10
11pub fn partition_col_indices(columns: &[Column], partition_by: &[String]) -> Vec<usize> {
12	partition_by
13		.iter()
14		.map(|pb| {
15			columns.iter()
16				.position(|c| c.name == *pb)
17				.expect("partition column must exist (validated during planning)")
18		})
19		.collect()
20}
21
22#[derive(Debug, thiserror::Error)]
23pub enum PartitionError {
24	#[error("cannot change partition column via UPDATE on object {object}: partition columns are immutable")]
25	ImmutablePartitionColumn {
26		object: ObjectId,
27	},
28
29	#[error(
30		"partition hash collision on object {object}: hash {hash:032x} maps to two distinct partition value tuples"
31	)]
32	PartitionHashCollision {
33		object: ObjectId,
34		hash: u128,
35	},
36}
37
38impl IntoDiagnostic for PartitionError {
39	fn into_diagnostic(self) -> Diagnostic {
40		match self {
41			PartitionError::ImmutablePartitionColumn {
42				object,
43			} => Diagnostic {
44				code: "PART_002".to_string(),
45				rql: None,
46				message: format!(
47					"cannot change partition column via UPDATE on object {}: partition columns are immutable",
48					object
49				),
50				column: None,
51				fragment: Fragment::None,
52				label: Some("partition column change rejected".to_string()),
53				help: Some(
54					"partition columns determine a row's physical location and cannot be updated; delete and re-insert the row instead"
55						.to_string(),
56				),
57				notes: vec![],
58				cause: None,
59				operator_chain: None,
60			},
61
62			PartitionError::PartitionHashCollision {
63				object,
64				hash,
65			} => Diagnostic {
66				code: "PART_003".to_string(),
67				rql: None,
68				message: format!(
69					"partition hash collision on object {}: hash {:032x} maps to two distinct partition value tuples",
70					object, hash
71				),
72				column: None,
73				fragment: Fragment::None,
74				label: Some("128-bit hash collision".to_string()),
75				help: Some(
76					"two distinct partition value tuples produced the same 128-bit hash; this is astronomically unlikely and points to a hashing bug or data corruption, report it as a bug"
77						.to_string(),
78				),
79				notes: vec![],
80				cause: None,
81				operator_chain: None,
82			},
83		}
84	}
85}
86
87impl From<PartitionError> for Error {
88	fn from(err: PartitionError) -> Self {
89		Error(Box::new(err.into_diagnostic()))
90	}
91}