reifydb_routine/function/uuid/
v7.rs1use 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}