reifydb_routine/function/uuid/
v4.rs1use reifydb_core::value::column::{Column, columns::Columns, data::ColumnData};
5use reifydb_type::value::{r#type::Type, uuid::Uuid4};
6use uuid::{Builder, Uuid};
7
8use crate::function::{Function, FunctionCapability, FunctionContext, FunctionInfo, error::FunctionError};
9
10pub struct UuidV4 {
11 info: FunctionInfo,
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: FunctionInfo::new("uuid::v4"),
24 }
25 }
26}
27
28impl Function for UuidV4 {
29 fn info(&self) -> &FunctionInfo {
30 &self.info
31 }
32
33 fn capabilities(&self) -> &[FunctionCapability] {
34 &[FunctionCapability::Scalar]
35 }
36
37 fn return_type(&self, _input_types: &[Type]) -> Type {
38 Type::Uuid4
39 }
40
41 fn execute(&self, ctx: &FunctionContext, args: &Columns) -> Result<Columns, FunctionError> {
42 if args.len() > 1 {
43 return Err(FunctionError::ArityMismatch {
44 function: ctx.fragment.clone(),
45 expected: 0,
46 actual: args.len(),
47 });
48 }
49
50 if args.is_empty() {
51 let bytes = ctx.runtime_context.rng.bytes_16();
52 let uuid = Uuid4::from(Builder::from_random_bytes(bytes).into_uuid());
53 let result_data = ColumnData::uuid4(vec![uuid]);
54 return Ok(Columns::new(vec![Column::new(ctx.fragment.clone(), result_data)]));
55 }
56
57 let column = &args[0];
58 let (data, bitvec) = column.data().unwrap_option();
59 let row_count = data.len();
60
61 match data {
62 ColumnData::Utf8 {
63 container,
64 ..
65 } => {
66 let mut result = Vec::with_capacity(row_count);
67 for i in 0..row_count {
68 let s = &container[i];
69 let parsed =
70 Uuid::parse_str(s).map_err(|e| FunctionError::ExecutionFailed {
71 function: ctx.fragment.clone(),
72 reason: format!("invalid UUID string '{}': {}", s, e),
73 })?;
74 if parsed.get_version_num() != 4 {
75 return Err(FunctionError::ExecutionFailed {
76 function: ctx.fragment.clone(),
77 reason: format!(
78 "expected UUID v4, got v{}",
79 parsed.get_version_num()
80 ),
81 });
82 }
83 result.push(Uuid4::from(parsed));
84 }
85 let result_data = ColumnData::uuid4(result);
86 let final_data = match bitvec {
87 Some(bv) => ColumnData::Option {
88 inner: Box::new(result_data),
89 bitvec: bv.clone(),
90 },
91 None => result_data,
92 };
93 Ok(Columns::new(vec![Column::new(ctx.fragment.clone(), final_data)]))
94 }
95 other => Err(FunctionError::InvalidArgumentType {
96 function: ctx.fragment.clone(),
97 argument_index: 0,
98 expected: vec![Type::Utf8],
99 actual: other.get_type(),
100 }),
101 }
102 }
103}