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::data::ColumnData;
5use reifydb_type::value::{r#type::Type, uuid::Uuid7};
6use uuid::{Builder, Uuid};
7
8use crate::function::{
9	ScalarFunction, ScalarFunctionContext,
10	error::{ScalarFunctionError, ScalarFunctionResult},
11	propagate_options,
12};
13
14pub struct UuidV7;
15
16impl UuidV7 {
17	pub fn new() -> Self {
18		Self
19	}
20}
21
22impl ScalarFunction for UuidV7 {
23	fn scalar(&self, ctx: ScalarFunctionContext) -> ScalarFunctionResult<ColumnData> {
24		if let Some(result) = propagate_options(self, &ctx) {
25			return result;
26		}
27
28		let row_count = ctx.row_count;
29
30		if ctx.columns.len() > 1 {
31			return Err(ScalarFunctionError::ArityMismatch {
32				function: ctx.fragment.clone(),
33				expected: 0,
34				actual: ctx.columns.len(),
35			});
36		}
37
38		if ctx.columns.is_empty() {
39			let mut data = Vec::with_capacity(row_count);
40			for _ in 0..row_count {
41				let millis = ctx.runtime_context.clock.now_millis();
42				let random_bytes = ctx.runtime_context.rng.bytes_10();
43				let uuid = Uuid7::from(
44					Builder::from_unix_timestamp_millis(millis, &random_bytes).into_uuid(),
45				);
46				data.push(uuid);
47			}
48			return Ok(ColumnData::uuid7(data));
49		}
50
51		let column = ctx.columns.get(0).unwrap();
52		match &column.data() {
53			ColumnData::Utf8 {
54				container,
55				..
56			} => {
57				let mut data = Vec::with_capacity(row_count);
58				for i in 0..row_count {
59					let s = &container[i];
60					let parsed = Uuid::parse_str(s).map_err(|e| {
61						ScalarFunctionError::ExecutionFailed {
62							function: ctx.fragment.clone(),
63							reason: format!("invalid UUID string '{}': {}", s, e),
64						}
65					})?;
66					if parsed.get_version_num() != 7 {
67						return Err(ScalarFunctionError::ExecutionFailed {
68							function: ctx.fragment.clone(),
69							reason: format!(
70								"expected UUID v7, got v{}",
71								parsed.get_version_num()
72							),
73						});
74					}
75					data.push(Uuid7::from(parsed));
76				}
77				Ok(ColumnData::uuid7(data))
78			}
79			other => Err(ScalarFunctionError::InvalidArgumentType {
80				function: ctx.fragment.clone(),
81				argument_index: 0,
82				expected: vec![Type::Utf8],
83				actual: other.get_type(),
84			}),
85		}
86	}
87
88	fn return_type(&self, _input_types: &[Type]) -> Type {
89		Type::Uuid7
90	}
91}