aragog 0.17.1

A simple lightweight object-document mapper for ArangoDB
Documentation
use crate::db::database_record_dto::DatabaseRecordDto;
use crate::error::ArangoHttpError;
use crate::query::{Query, QueryCursor, QueryResult};
use crate::{DatabaseAccess, DatabaseRecord, Error, OperationOptions, Record};
use arangors_lite::{AqlOptions, AqlQuery};
use std::convert::TryInto;

#[maybe_async::maybe_async]
pub async fn update_record<T, D>(
    obj: DatabaseRecord<T>,
    key: &str,
    db_accessor: &D,
    collection_name: &str,
    options: OperationOptions,
) -> Result<DatabaseRecord<T>, Error>
where
    T: Record,
    D: DatabaseAccess + ?Sized,
{
    log::debug!("Updating document {} {}", collection_name, key);
    let collection = db_accessor.get_collection(collection_name)?;
    let response = match collection.update_document(key, obj, options.into()).await {
        Ok(resp) => resp,
        Err(error) => return Err(Error::from(error)),
    };
    response.try_into()
}

#[maybe_async::maybe_async]
pub async fn create_record<T, D>(
    obj: T,
    key: Option<String>,
    db_accessor: &D,
    collection_name: &str,
    options: OperationOptions,
) -> Result<DatabaseRecord<T>, Error>
where
    T: Record,
    D: DatabaseAccess + ?Sized,
{
    let collection = db_accessor.get_collection(collection_name)?;
    log::debug!("Creating new {} document", collection.name());
    let dto = DatabaseRecordDto::new(obj, key);
    let response = match collection.create_document(dto, options.into()).await {
        Ok(resp) => resp,
        Err(error) => return Err(Error::from(error)),
    };
    response.try_into()
}

#[maybe_async::maybe_async]
pub async fn retrieve_record<T, D>(
    key: &str,
    db_accessor: &D,
    collection_name: &str,
) -> Result<DatabaseRecord<T>, Error>
where
    T: Record,
    D: DatabaseAccess + ?Sized,
{
    log::debug!("Retrieving {} {} from database", collection_name, key);
    let collection = db_accessor.get_collection(collection_name)?;
    let record = match collection.document(key).await {
        Ok(doc) => doc,
        Err(error) => {
            println!("{}", error);
            let err = Error::from(error);
            if let Error::ArangoError(ref db_error) = err {
                if ArangoHttpError::NotFound == db_error.http_error {
                    return Err(Error::NotFound {
                        item: collection_name.to_string(),
                        id: key.to_string(),
                        source: Some(db_error.clone()),
                    });
                }
            }
            return Err(err);
        }
    };
    Ok(DatabaseRecord::from(record))
}

#[maybe_async::maybe_async]
pub async fn remove_record<T, D>(
    key: &str,
    db_accessor: &D,
    collection_name: &str,
    options: OperationOptions,
) -> Result<(), Error>
where
    T: Record,
    D: DatabaseAccess + ?Sized,
{
    log::debug!("Removing {} {} from database", collection_name, key);
    let collection = db_accessor.get_collection(collection_name)?;
    match collection
        .remove_document::<T>(key, options.into(), None)
        .await
    {
        Ok(_result) => Ok(()),
        Err(error) => Err(Error::from(error)),
    }
}

#[maybe_async::maybe_async]
pub async fn raw_query_records<T, D>(db_accessor: &D, aql: &str) -> Result<QueryResult<T>, Error>
where
    T: Record,
    D: DatabaseAccess + ?Sized,
{
    log::debug!(
        "Querying {} records through AQL: `{}`",
        T::COLLECTION_NAME,
        aql
    );
    let query_result = match db_accessor.database().aql_str(aql).await {
        Ok(value) => value,
        Err(error) => return Err(Error::from(error)),
    };
    Ok(query_result.into())
}

#[maybe_async::maybe_async]
pub async fn query_records<T, D>(db_accessor: &D, query: &Query) -> Result<QueryResult<T>, Error>
where
    T: Record,
    D: DatabaseAccess + ?Sized,
{
    let aql = query.aql_str();
    log::debug!(
        "Querying {} records through AQL: `{}`",
        T::COLLECTION_NAME,
        aql
    );
    let mut aql_query = AqlQuery::new(&aql);
    for (var, val) in &query.bind_vars {
        aql_query = aql_query.bind_var(var, val.clone());
    }
    let query_result = match db_accessor.database().aql_query(aql_query).await {
        Ok(value) => value,
        Err(error) => return Err(Error::from(error)),
    };
    Ok(query_result.into())
}

#[maybe_async::maybe_async]
pub async fn query_records_in_batches<T, D>(
    db_accessor: &D,
    query: &Query,
    batch_size: u32,
) -> Result<QueryCursor<T>, Error>
where
    T: Record,
    D: DatabaseAccess + ?Sized,
{
    let aql = query.aql_str();
    log::debug!(
        "Querying {} records through AQL with {} batch size: `{}`",
        T::COLLECTION_NAME,
        batch_size,
        aql
    );
    let mut aql_query = AqlQuery::new(&aql)
        .batch_size(batch_size)
        .options(AqlOptions::builder().full_count(true).build());
    for (var, val) in &query.bind_vars {
        aql_query = aql_query.bind_var(var, val.clone());
    }
    let cursor = match db_accessor.database().aql_query_batch(aql_query).await {
        Ok(value) => value,
        Err(error) => return Err(Error::from(error)),
    };
    Ok(QueryCursor::new(cursor, db_accessor.database().clone()))
}