radixdb-executor 1.1.0

SQL binding, planning, and execution engine for RadixDB
Documentation
use radixdb_core::{DataType, Error, Result, Value};

use crate::Executor;

use super::transaction_visible_catalog;

pub(super) fn equal(executor: &Executor, left: &Value, right: &Value) -> Result<bool> {
    executor
        .plugin_registry
        .external_equal(left, right)
        .map_err(|error| Error::invalid_argument(error.to_string()))
}

pub(super) fn compare(
    executor: &Executor,
    left: &Value,
    right: &Value,
) -> Result<std::cmp::Ordering> {
    executor
        .plugin_registry
        .external_compare(left, right)
        .map_err(|error| Error::invalid_argument(error.to_string()))
}

pub(super) fn input(executor: &Executor, type_name: &str, input: &Value) -> Result<Value> {
    if input.is_null() {
        return Ok(Value::null_unknown());
    }
    let (catalog, _) = transaction_visible_catalog(executor)?;
    let catalog_type =
        crate::catalog::bind_catalog_type_in_generation(type_name, catalog.as_ref())?;
    let type_ref = catalog_type.external_type_ref().ok_or_else(|| {
        Error::invalid_argument(format!("type '{type_name}' is not an external type"))
    })?;
    if let Some(external) = input.as_external() {
        if external.type_ref() != type_ref {
            return Err(Error::Type(format!(
                "cannot cast external value to unrelated type '{type_name}'"
            )));
        }
        executor
            .plugin_registry
            .validate_external_value(input)
            .map_err(|error| Error::invalid_argument(error.to_string()))?;
        return Ok(input.clone());
    }
    if let Some(text) = input.as_str() {
        return executor
            .plugin_registry
            .parse_external_text(type_ref, text)
            .map_err(|error| Error::invalid_argument(error.to_string()));
    }
    if let Some(bytes) = input.as_bytes_value() {
        return executor
            .plugin_registry
            .parse_external_binary(type_ref, bytes)
            .map_err(|error| Error::invalid_argument(error.to_string()));
    }
    Err(Error::Type(format!(
        "external type '{type_name}' accepts TEXT or BYTES input"
    )))
}

pub(super) fn output(executor: &Executor, value: &Value, target_type: DataType) -> Result<Value> {
    match target_type {
        DataType::Text => executor
            .plugin_registry
            .format_external_text(value)
            .map(|value| Value::Text(value.into()))
            .map_err(|error| Error::invalid_argument(error.to_string())),
        DataType::Bytes => executor
            .plugin_registry
            .format_external_binary(value)
            .map(Value::bytes)
            .map_err(|error| Error::invalid_argument(error.to_string())),
        _ => Err(Error::Type(format!(
            "external values can only be cast to TEXT or BYTES, not {target_type}"
        ))),
    }
}