elephantry 5.2.0

Object model manager for PostgreSQL
Documentation
#[derive(Debug)]
pub struct Event<T: elephantry::FromSql + elephantry::ToSql> {
    #[cfg(feature = "uuid")]
    pub uuid: Option<uuid::Uuid>,
    #[cfg(not(feature = "uuid"))]
    pub uuid: Option<String>,
    pub name: String,
    pub visitor_id: Option<i32>,
    #[cfg(feature = "json")]
    pub properties: serde_json::Value,
    #[cfg(not(feature = "json"))]
    pub properties: String,
    #[cfg(feature = "json")]
    pub browser: serde_json::Value,
    #[cfg(not(feature = "json"))]
    pub browser: String,
    pub generic: Option<T>,
}

impl<T: elephantry::FromSql + elephantry::ToSql> elephantry::Entity for Event<T> {
    fn from(tuple: &elephantry::Tuple) -> Self {
        Self {
            uuid: tuple.get("uuid"),
            name: tuple.get("name"),
            visitor_id: tuple.get("visitor_id"),
            properties: tuple.get("properties"),
            browser: tuple.get("browser"),
            generic: tuple.get("generic"),
        }
    }

    fn get(&self, field: &str) -> Option<&dyn elephantry::ToSql> {
        match field {
            "uuid" => self.uuid.as_ref().map(|x| x as _),
            "name" => Some(&self.name),
            "visitor_id" => self.visitor_id.as_ref().map(|x| x as _),
            "properties" => Some(&self.properties),
            "browser" => Some(&self.browser),
            "generic" => self.generic.as_ref().map(|x| x as _),
            _ => None,
        }
    }
}

pub struct EventModel {
    #[allow(dead_code)]
    connection: elephantry::Connection,
}

impl elephantry::Model for EventModel {
    type Entity = Event<String>;
    type Structure = EventStructure;

    fn new(connection: &elephantry::Connection) -> Self {
        Self {
            connection: connection.clone(),
        }
    }
}

impl EventModel {
    pub fn count_uniq_visitor(&self) -> elephantry::Result<u32> {
        self.connection
            .execute("select count(distinct visitor_id) as count from event")
            .map(|x| x.get(0).get("count"))
    }
}

#[derive(Debug)]
pub struct EventExtra<T: elephantry::Entity + elephantry::ToSql> {
    #[cfg(feature = "uuid")]
    pub uuid: Option<uuid::Uuid>,
    #[cfg(not(feature = "uuid"))]
    pub uuid: Option<String>,
    pub name: String,
    pub visitor_id: Option<i32>,
    #[cfg(feature = "json")]
    pub properties: serde_json::Value,
    #[cfg(not(feature = "json"))]
    pub properties: String,
    #[cfg(feature = "json")]
    pub browser: serde_json::Value,
    pub generic: Option<T>,
    #[cfg(not(feature = "json"))]
    pub browser: String,
    pub os: Option<String>,
}

impl<T: elephantry::Entity + elephantry::ToSql> elephantry::Entity for EventExtra<T> {
    fn from(tuple: &elephantry::Tuple) -> Self {
        let event = <Event<String> as elephantry::Entity>::from(tuple);

        Self {
            uuid: event.uuid,
            name: event.name,
            visitor_id: event.visitor_id,
            properties: event.properties,
            browser: event.browser,
            generic: None,
            os: tuple.get("os"),
        }
    }

    fn get(&self, field: &str) -> Option<&dyn elephantry::ToSql> {
        match field {
            "uuid" => self.uuid.as_ref().map(|x| x as _),
            "name" => Some(&self.name),
            "visitor_id" => self.visitor_id.as_ref().map(|x| x as _),
            "properties" => Some(&self.properties),
            "browser" => Some(&self.browser),
            "generic" => self.generic.as_ref().map(|x| x as _),
            "os" => self.os.as_ref().map(|x| x as _),
            _ => None,
        }
    }
}

pub struct EventExtraModel;

impl elephantry::Model for EventExtraModel {
    type Entity = EventExtra<String>;
    type Structure = EventStructure;

    fn new(_: &elephantry::Connection) -> Self {
        Self
    }

    fn create_projection() -> elephantry::Projection {
        Self::default_projection().add_field("os", "%:browser:% ->> 'os'")
    }
}

pub struct EventStructure;

impl elephantry::Structure for EventStructure {
    fn primary_key() -> &'static [&'static str] {
        &["uuid"]
    }
}

impl elephantry::Projectable for EventStructure {
    fn relation() -> &'static str {
        "public.event"
    }

    fn columns() -> &'static [&'static str] {
        &["uuid", "name", "visitor_id", "properties", "browser"]
    }
}