reifydb_function/is/
type.rs1use reifydb_core::value::column::data::ColumnData;
5use reifydb_type::value::{Value, r#type::Type};
6
7use crate::{
8 ScalarFunction, ScalarFunctionContext,
9 error::{ScalarFunctionError, ScalarFunctionResult},
10};
11
12pub struct IsType;
13
14impl IsType {
15 pub fn new() -> Self {
16 Self
17 }
18}
19
20impl ScalarFunction for IsType {
21 fn scalar(&self, ctx: ScalarFunctionContext) -> ScalarFunctionResult<ColumnData> {
22 let columns = ctx.columns;
23 let row_count = ctx.row_count;
24
25 if columns.len() != 2 {
26 return Err(ScalarFunctionError::ArityMismatch {
27 function: ctx.fragment.clone(),
28 expected: 2,
29 actual: columns.len(),
30 });
31 }
32
33 let value_column = columns.get(0).unwrap();
34 let type_column = columns.get(1).unwrap();
35
36 let target_type = match type_column.data().get_value(0) {
40 Value::Any(boxed) => match boxed.as_ref() {
41 Value::Type(t) => t.clone(),
42 _ => {
43 return Err(ScalarFunctionError::InvalidArgumentType {
44 function: ctx.fragment.clone(),
45 argument_index: 1,
46 expected: vec![Type::Any],
47 actual: boxed.get_type(),
48 });
49 }
50 },
51 Value::None {
52 ..
53 } => Type::Option(Box::new(Type::Any)),
54 other => {
55 return Err(ScalarFunctionError::InvalidArgumentType {
56 function: ctx.fragment.clone(),
57 argument_index: 1,
58 expected: vec![Type::Any],
59 actual: other.get_type(),
60 });
61 }
62 };
63
64 let data: Vec<bool> = (0..row_count)
66 .map(|i| {
67 let vtype = value_column.data().get_value(i).get_type();
68 if target_type == Type::Option(Box::new(Type::Any)) {
69 vtype.is_option()
70 } else {
71 !vtype.is_option() && vtype.inner_type() == target_type.inner_type()
72 }
73 })
74 .collect();
75
76 Ok(ColumnData::bool(data))
77 }
78
79 fn return_type(&self, _input_types: &[Type]) -> Type {
80 Type::Boolean
81 }
82}