Skip to main content

reifydb_routine/function/uuid/
v7.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_core::value::column::{ColumnWithName, buffer::ColumnBuffer, columns::Columns};
5use reifydb_type::value::{r#type::Type, uuid::Uuid7};
6use uuid::Uuid;
7
8use crate::routine::{Function, FunctionKind, Routine, RoutineInfo, context::FunctionContext, error::RoutineError};
9
10pub struct UuidV7 {
11	info: RoutineInfo,
12}
13
14impl Default for UuidV7 {
15	fn default() -> Self {
16		Self::new()
17	}
18}
19
20impl UuidV7 {
21	pub fn new() -> Self {
22		Self {
23			info: RoutineInfo::new("uuid::v7"),
24		}
25	}
26}
27
28impl<'a> Routine<FunctionContext<'a>> for UuidV7 {
29	fn info(&self) -> &RoutineInfo {
30		&self.info
31	}
32
33	fn return_type(&self, _input_types: &[Type]) -> Type {
34		Type::Uuid7
35	}
36
37	fn execute(&self, ctx: &mut FunctionContext<'a>, args: &Columns) -> Result<Columns, RoutineError> {
38		if args.len() > 1 {
39			return Err(RoutineError::FunctionArityMismatch {
40				function: ctx.fragment.clone(),
41				expected: 0,
42				actual: args.len(),
43			});
44		}
45
46		if args.is_empty() {
47			let uuid = Uuid7::generate(&ctx.runtime_context.clock, &ctx.runtime_context.rng);
48			let result_data = ColumnBuffer::uuid7(vec![uuid]);
49			return Ok(Columns::new(vec![ColumnWithName::new(ctx.fragment.clone(), result_data)]));
50		}
51
52		let column = &args[0];
53		let (data, bitvec) = column.unwrap_option();
54		let row_count = data.len();
55
56		match data {
57			ColumnBuffer::Utf8 {
58				container,
59				..
60			} => {
61				let mut result = Vec::with_capacity(row_count);
62				for i in 0..row_count {
63					let s = container.get(i).unwrap();
64					let parsed = Uuid::parse_str(s).map_err(|e| {
65						RoutineError::FunctionExecutionFailed {
66							function: ctx.fragment.clone(),
67							reason: format!("invalid UUID string '{}': {}", s, e),
68						}
69					})?;
70					if parsed.get_version_num() != 7 {
71						return Err(RoutineError::FunctionExecutionFailed {
72							function: ctx.fragment.clone(),
73							reason: format!(
74								"expected UUID v7, got v{}",
75								parsed.get_version_num()
76							),
77						});
78					}
79					result.push(Uuid7::from(parsed));
80				}
81				let result_data = ColumnBuffer::uuid7(result);
82				let final_data = match bitvec {
83					Some(bv) => ColumnBuffer::Option {
84						inner: Box::new(result_data),
85						bitvec: bv.clone(),
86					},
87					None => result_data,
88				};
89				Ok(Columns::new(vec![ColumnWithName::new(ctx.fragment.clone(), final_data)]))
90			}
91			other => Err(RoutineError::FunctionInvalidArgumentType {
92				function: ctx.fragment.clone(),
93				argument_index: 0,
94				expected: vec![Type::Utf8],
95				actual: other.get_type(),
96			}),
97		}
98	}
99}
100
101impl Function for UuidV7 {
102	fn kinds(&self) -> &[FunctionKind] {
103		&[FunctionKind::Scalar]
104	}
105}