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