Skip to main content

datafusion_functions/string/
uuid.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::sync::Arc;
19
20use arrow::datatypes::DataType;
21use arrow::datatypes::DataType::Utf8;
22use rand::Rng;
23use uuid::Uuid;
24
25use crate::strings::GenericStringArrayBuilder;
26use datafusion_common::{Result, assert_or_internal_err};
27use datafusion_expr::{ColumnarValue, Documentation, Volatility};
28use datafusion_expr::{ScalarFunctionArgs, ScalarUDFImpl, Signature};
29use datafusion_macros::user_doc;
30
31#[user_doc(
32    doc_section(label = "String Functions"),
33    description = "Returns [`UUID v4`](https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_%28random%29) string value which is unique per row.",
34    syntax_example = "uuid()",
35    sql_example = r#"```sql
36> select uuid();
37+--------------------------------------+
38| uuid()                               |
39+--------------------------------------+
40| 6ec17ef8-1934-41cc-8d59-d0c8f9eea1f0 |
41+--------------------------------------+
42```"#
43)]
44#[derive(Debug, PartialEq, Eq, Hash)]
45pub struct UuidFunc {
46    signature: Signature,
47}
48
49impl Default for UuidFunc {
50    fn default() -> Self {
51        Self::new()
52    }
53}
54
55impl UuidFunc {
56    pub fn new() -> Self {
57        Self {
58            signature: Signature::nullary(Volatility::Volatile),
59        }
60    }
61}
62
63impl ScalarUDFImpl for UuidFunc {
64    fn name(&self) -> &str {
65        "uuid"
66    }
67
68    fn signature(&self) -> &Signature {
69        &self.signature
70    }
71
72    fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
73        Ok(Utf8)
74    }
75
76    /// Prints random (v4) uuid values per row
77    /// uuid() = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'
78    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
79        assert_or_internal_err!(
80            args.args.is_empty(),
81            "{} function does not accept arguments",
82            self.name()
83        );
84
85        // Generate random u128 values
86        let mut rng = rand::rng();
87        let mut randoms = vec![0u128; args.number_rows];
88        rng.fill(&mut randoms[..]);
89
90        let mut builder = GenericStringArrayBuilder::<i32>::with_capacity(
91            args.number_rows,
92            args.number_rows * 36,
93        );
94
95        let mut buffer = [0u8; 36];
96        for x in &mut randoms {
97            // From Uuid::new_v4(): Mask out the version and variant bits
98            *x = *x & 0xFFFFFFFFFFFF4FFFBFFFFFFFFFFFFFFF | 0x40008000000000000000;
99            let uuid = Uuid::from_u128(*x);
100            let fmt = uuid::fmt::Hyphenated::from_uuid(uuid);
101            builder.append_value(fmt.encode_lower(&mut buffer));
102        }
103
104        Ok(ColumnarValue::Array(Arc::new(builder.finish(None)?)))
105    }
106
107    fn documentation(&self) -> Option<&Documentation> {
108        self.doc()
109    }
110}