rdf_fusion_functions/scalar/terms/
str.rs1use crate::scalar::dispatch::dispatch_unary_owned_typed_value;
2use crate::scalar::sparql_op_impl::{
3 ScalarSparqlOpImpl, create_plain_term_sparql_op_impl,
4 create_typed_value_sparql_op_impl,
5};
6use crate::scalar::{ScalarSparqlOp, ScalarSparqlOpSignature, SparqlOpArity};
7use datafusion::arrow::array::{Array, StringArray, UInt8Array};
8use datafusion::logical_expr::ColumnarValue;
9use itertools::repeat_n;
10use rdf_fusion_encoding::plain_term::{
11 PlainTermArray, PlainTermArrayBuilder, PlainTermEncoding, PlainTermEncodingField,
12 PlainTermType,
13};
14use rdf_fusion_encoding::typed_value::TypedValueEncoding;
15use rdf_fusion_encoding::{EncodingArray, EncodingDatum, EncodingScalar};
16use rdf_fusion_extensions::functions::BuiltinName;
17use rdf_fusion_extensions::functions::FunctionName;
18use rdf_fusion_model::ThinError;
19use rdf_fusion_model::vocab::xsd;
20use rdf_fusion_model::{SimpleLiteral, TypedValue, TypedValueRef};
21use std::sync::Arc;
22
23#[derive(Debug, Hash, PartialEq, Eq)]
24pub struct StrSparqlOp;
25
26impl Default for StrSparqlOp {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32impl StrSparqlOp {
33 const NAME: FunctionName = FunctionName::Builtin(BuiltinName::Str);
34
35 pub fn new() -> Self {
36 Self {}
37 }
38}
39
40impl ScalarSparqlOp for StrSparqlOp {
41 fn name(&self) -> &FunctionName {
42 &Self::NAME
43 }
44
45 fn signature(&self) -> ScalarSparqlOpSignature {
46 ScalarSparqlOpSignature::default_with_arity(SparqlOpArity::Fixed(1))
47 }
48
49 fn typed_value_encoding_op(
50 &self,
51 ) -> Option<Box<dyn ScalarSparqlOpImpl<TypedValueEncoding>>> {
52 Some(create_typed_value_sparql_op_impl(|args| {
53 dispatch_unary_owned_typed_value(
54 &args.args[0],
55 |value| {
56 let converted = match value {
57 TypedValueRef::NamedNode(value) => value.as_str().to_owned(),
58 TypedValueRef::BlankNode(value) => value.as_str().to_owned(),
59 TypedValueRef::BooleanLiteral(value) => value.to_string(),
60 TypedValueRef::NumericLiteral(value) => value.format_value(),
61 TypedValueRef::SimpleLiteral(value) => value.value.to_owned(),
62 TypedValueRef::LanguageStringLiteral(value) => {
63 value.value.to_owned()
64 }
65 TypedValueRef::DateTimeLiteral(value) => value.to_string(),
66 TypedValueRef::TimeLiteral(value) => value.to_string(),
67 TypedValueRef::DateLiteral(value) => value.to_string(),
68 TypedValueRef::DurationLiteral(value) => value.to_string(),
69 TypedValueRef::YearMonthDurationLiteral(value) => {
70 value.to_string()
71 }
72 TypedValueRef::DayTimeDurationLiteral(value) => value.to_string(),
73 TypedValueRef::OtherLiteral(value) => value.value().to_owned(),
74 };
75 Ok(TypedValue::SimpleLiteral(SimpleLiteral {
76 value: converted,
77 }))
78 },
79 ThinError::expected,
80 )
81 }))
82 }
83
84 fn plain_term_encoding_op(
85 &self,
86 ) -> Option<Box<dyn ScalarSparqlOpImpl<PlainTermEncoding>>> {
87 Some(create_plain_term_sparql_op_impl(|args| {
88 match &args.args[0] {
89 EncodingDatum::Array(array) => Ok(ColumnarValue::Array(
90 impl_str_plain_term(array).into_array(),
91 )),
92 EncodingDatum::Scalar(scalar, _) => {
93 let array = scalar.to_array(1)?;
94 impl_str_plain_term(&array)
95 .try_as_scalar(0)
96 .map(|scalar| ColumnarValue::Scalar(scalar.into_scalar_value()))
97 }
98 }
99 }))
100 }
101}
102
103fn impl_str_plain_term(array: &PlainTermArray) -> PlainTermArray {
104 let parts = array.as_parts();
105
106 let value = Arc::clone(
107 parts
108 .struct_array
109 .column(PlainTermEncodingField::Value.index()),
110 );
111
112 let term_types_data =
113 UInt8Array::from_iter(repeat_n(u8::from(PlainTermType::Literal), value.len()))
114 .to_data()
115 .into_builder()
116 .nulls(value.nulls().cloned())
117 .build()
118 .unwrap();
119 let term_types = UInt8Array::from(term_types_data);
120
121 let data_types_data =
122 StringArray::from_iter_values(repeat_n(xsd::STRING.as_str(), value.len()))
123 .to_data()
124 .into_builder()
125 .nulls(value.nulls().cloned())
126 .build()
127 .unwrap();
128 let data_types = StringArray::from(data_types_data);
129
130 PlainTermArrayBuilder::new(Arc::new(term_types), value)
131 .with_data_types(Arc::new(data_types))
132 .finish()
133}