sift-query-sqlx 0.1.0

PostgreSQL renderer and sqlx executor for SiftQuery
Documentation
use super::typed;
use sift_query_core::{CustomOperator, ValueType};

#[cfg(feature = "ltree")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TreeQuery {
    Ancestor,
    Descendant,
}
#[cfg(feature = "ltree")]
pub fn ltree(mode: TreeQuery) -> CustomOperator {
    match mode {
        TreeQuery::Ancestor => typed(
            "tree_ancestor",
            "{field} @> {0}::ltree",
            ValueType::Text,
            ValueType::Text,
        ),
        TreeQuery::Descendant => typed(
            "tree_descendant",
            "{field} <@ {0}::ltree",
            ValueType::Text,
            ValueType::Text,
        ),
    }
}
#[cfg(feature = "ltree")]
#[derive(Debug, Clone, Copy)]
pub struct LtreeCodec {
    field: &'static str,
}
#[cfg(feature = "ltree")]
impl LtreeCodec {
    pub const fn new(field: &'static str) -> Self {
        Self { field }
    }
}
#[cfg(feature = "ltree")]
impl sift_query_core::Codec for LtreeCodec {
    fn name(&self) -> &'static str {
        "ltree"
    }
    fn fingerprint(&self) -> u64 {
        let mut hash = sift_query_algorithm::StableHasher64::default();
        hash.write_delimited(self.name());
        hash.write_delimited(self.field);
        hash.finish()
    }
    fn supports(&self, field: &sift_query_core::FieldMeta) -> bool {
        field.value_type == ValueType::Text && field.public_name == self.field
    }
    fn parse(
        &self,
        _field: &sift_query_core::FieldMeta,
        input: &str,
    ) -> Result<sift_query_core::ScalarValue, String> {
        if !input.is_empty()
            && input.split('.').any(|label| {
                label.is_empty()
                    || label.chars().count() > 255
                    || !label.chars().all(|ch| ch.is_alphanumeric() || ch == '_')
            })
        {
            return Err("expected a dot separated ltree path".to_owned());
        }
        Ok(sift_query_core::ScalarValue::Text(input.to_owned()))
    }
}