datafusion_functions/core/
version.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
18//! [`VersionFunc`]: Implementation of the `version` function.
19
20use arrow::datatypes::DataType;
21use datafusion_common::{utils::take_function_args, Result, ScalarValue};
22use datafusion_expr::{
23    ColumnarValue, Documentation, ScalarFunctionArgs, ScalarUDFImpl, Signature,
24    Volatility,
25};
26use datafusion_macros::user_doc;
27use std::any::Any;
28
29#[user_doc(
30    doc_section(label = "Other Functions"),
31    description = "Returns the version of DataFusion.",
32    syntax_example = "version()",
33    sql_example = r#"```sql
34> select version();
35+--------------------------------------------+
36| version()                                  |
37+--------------------------------------------+
38| Apache DataFusion 42.0.0, aarch64 on macos |
39+--------------------------------------------+
40```"#
41)]
42#[derive(Debug)]
43pub struct VersionFunc {
44    signature: Signature,
45}
46
47impl Default for VersionFunc {
48    fn default() -> Self {
49        Self::new()
50    }
51}
52
53impl VersionFunc {
54    pub fn new() -> Self {
55        Self {
56            signature: Signature::exact(vec![], Volatility::Immutable),
57        }
58    }
59}
60
61impl ScalarUDFImpl for VersionFunc {
62    fn as_any(&self) -> &dyn Any {
63        self
64    }
65
66    fn name(&self) -> &str {
67        "version"
68    }
69
70    fn signature(&self) -> &Signature {
71        &self.signature
72    }
73
74    fn return_type(&self, args: &[DataType]) -> Result<DataType> {
75        let [] = take_function_args(self.name(), args)?;
76        Ok(DataType::Utf8)
77    }
78
79    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> Result<ColumnarValue> {
80        let [] = take_function_args(self.name(), args.args)?;
81        // TODO it would be great to add rust version and arrow version,
82        // but that requires a `build.rs` script and/or adding a version const to arrow-rs
83        let version = format!(
84            "Apache DataFusion {}, {} on {}",
85            env!("CARGO_PKG_VERSION"),
86            std::env::consts::ARCH,
87            std::env::consts::OS,
88        );
89        Ok(ColumnarValue::Scalar(ScalarValue::Utf8(Some(version))))
90    }
91
92    fn documentation(&self) -> Option<&Documentation> {
93        self.doc()
94    }
95}
96
97#[cfg(test)]
98mod test {
99    use super::*;
100    use datafusion_expr::ScalarUDF;
101
102    #[tokio::test]
103    async fn test_version_udf() {
104        let version_udf = ScalarUDF::from(VersionFunc::new());
105        let version = version_udf
106            .invoke_with_args(ScalarFunctionArgs {
107                args: vec![],
108                number_rows: 0,
109                return_type: &DataType::Utf8,
110            })
111            .unwrap();
112
113        if let ColumnarValue::Scalar(ScalarValue::Utf8(Some(version))) = version {
114            assert!(version.starts_with("Apache DataFusion"));
115        } else {
116            panic!("Expected version string");
117        }
118    }
119}