rdf_fusion_functions/builtin/native/
boolean_as_rdf_term.rs

1use datafusion::arrow::array::{Array, as_boolean_array};
2use datafusion::arrow::datatypes::DataType;
3use datafusion::common::exec_err;
4use datafusion::logical_expr::{
5    ColumnarValue, ScalarFunctionArgs, ScalarUDF, ScalarUDFImpl, Signature,
6    TypeSignature, Volatility,
7};
8use rdf_fusion_encoding::typed_value::{TYPED_VALUE_ENCODING, TypedValueArrayBuilder};
9use rdf_fusion_encoding::{EncodingArray, TermEncoding};
10use rdf_fusion_extensions::functions::BuiltinName;
11use rdf_fusion_model::DFResult;
12use std::any::Any;
13use std::hash::{Hash, Hasher};
14
15pub fn native_boolean_as_term() -> ScalarUDF {
16    let udf_impl = NativeBooleanAsTerm::new();
17    ScalarUDF::new_from_impl(udf_impl)
18}
19
20#[derive(Debug, Eq)]
21struct NativeBooleanAsTerm {
22    name: String,
23    signature: Signature,
24}
25
26impl NativeBooleanAsTerm {
27    pub fn new() -> Self {
28        Self {
29            name: BuiltinName::NativeBooleanAsTerm.to_string(),
30            signature: Signature::new(
31                TypeSignature::Exact(vec![DataType::Boolean]),
32                Volatility::Immutable,
33            ),
34        }
35    }
36}
37
38impl ScalarUDFImpl for NativeBooleanAsTerm {
39    fn as_any(&self) -> &dyn Any {
40        self
41    }
42
43    fn name(&self) -> &str {
44        &self.name
45    }
46
47    fn signature(&self) -> &Signature {
48        &self.signature
49    }
50
51    fn return_type(&self, _arg_types: &[DataType]) -> DFResult<DataType> {
52        Ok(TYPED_VALUE_ENCODING.data_type())
53    }
54
55    fn invoke_with_args(&self, args: ScalarFunctionArgs) -> DFResult<ColumnarValue> {
56        if args.args.len() != 1 {
57            return exec_err!("Unexpected number of arguments");
58        }
59
60        let arg = &args.args[0];
61        if arg.data_type() != DataType::Boolean {
62            return exec_err!("Unexpected argument type: {:?}", arg.data_type());
63        }
64
65        // Performance could be optimized here
66        let arg = arg.to_array(args.number_rows)?;
67        let arg = as_boolean_array(&arg);
68        let mut builder = TypedValueArrayBuilder::default();
69        for i in 0..args.number_rows {
70            if arg.is_null(i) {
71                builder.append_null()?;
72            } else {
73                builder.append_boolean(arg.value(i).into())?;
74            }
75        }
76
77        Ok(ColumnarValue::Array(builder.finish().into_array()))
78    }
79}
80
81impl Hash for NativeBooleanAsTerm {
82    fn hash<H: Hasher>(&self, state: &mut H) {
83        self.as_any().type_id().hash(state);
84    }
85}
86
87impl PartialEq for NativeBooleanAsTerm {
88    fn eq(&self, other: &Self) -> bool {
89        self.as_any().type_id() == other.as_any().type_id()
90    }
91}