hamelin_lib 0.9.4

Core library for Hamelin query language
Documentation
//! JSON functions

use std::any::TypeId;

use crate::func::def::{FunctionDef, ParameterBindingProvider, Parameters};
use crate::types::array::Array;
use crate::types::matcher::{AnyMatcher, ArrayMatcher, ExactMatcher};
use crate::types::struct_type::Struct;
use crate::types::{Type, STRING, VARIANT};

/// parse_json(json_string) - Parse JSON string to variant.
#[derive(Default, Clone)]
pub struct ParseJsonString;

impl FunctionDef for ParseJsonString {
    fn name(&self) -> &'static str {
        "parse_json"
    }

    fn parameters(&self) -> Parameters {
        Parameters::new().with("json", ExactMatcher::of(STRING))
    }

    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
        Ok(VARIANT)
    }

    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

/// parse_json(variant) - Pass-through for already-parsed JSON.
#[derive(Default, Clone)]
pub struct ParseJsonVariant;

impl FunctionDef for ParseJsonVariant {
    fn name(&self) -> &'static str {
        "parse_json"
    }

    fn parameters(&self) -> Parameters {
        Parameters::new().with("json", ExactMatcher::of(VARIANT))
    }

    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
        Ok(VARIANT)
    }

    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

/// to_json_string(variant) - Convert variant to JSON string.
#[derive(Default, Clone)]
pub struct ToJsonString;

impl FunctionDef for ToJsonString {
    fn name(&self) -> &'static str {
        "to_json_string"
    }

    fn parameters(&self) -> Parameters {
        Parameters::new().with("json", ExactMatcher::of(VARIANT))
    }

    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
        Ok(STRING)
    }

    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

/// array_variant_to_json(array) - Convert every variant element of an array to its JSON string.
///
/// Internal function used by transform lowering. Applies `to_json_string` element-wise
/// to an array of variants, avoiding the explode/reaggregate pipeline.
#[derive(Default, Clone)]
pub struct ArrayVariantToJson;

impl FunctionDef for ArrayVariantToJson {
    fn name(&self) -> &'static str {
        "array_variant_to_json"
    }

    fn parameters(&self) -> Parameters {
        Parameters::new().with("array", ArrayMatcher::of(ExactMatcher::of(VARIANT)))
    }

    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
        Ok(Array::new(STRING).into())
    }

    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}

/// typeof(x) - Get the type of any expression.
#[derive(Default, Clone)]
pub struct Typeof;

impl FunctionDef for Typeof {
    fn name(&self) -> &'static str {
        "typeof"
    }

    fn parameters(&self) -> Parameters {
        Parameters::new().with("x", AnyMatcher::default())
    }

    fn return_type(&self, _bindings: &dyn ParameterBindingProvider) -> anyhow::Result<Type> {
        Ok(Struct::default()
            .with_str("hamelin_type", STRING.into())
            .with_str("sql_type", STRING.into())
            .into())
    }

    fn type_id(&self) -> TypeId {
        TypeId::of::<Self>()
    }
}