Skip to content

Commit

Permalink
Docs docs, and more docs.
Browse files Browse the repository at this point in the history
  • Loading branch information
mara-schulke committed Nov 25, 2023
1 parent 64e0389 commit c608b10
Show file tree
Hide file tree
Showing 16 changed files with 438 additions and 62 deletions.
36 changes: 34 additions & 2 deletions atmosphere-core/src/bind.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,53 @@
//! Bind Module for Atmosphere SQL Framework
//!
//! This module provides functionality to bind values to SQL queries in a type-safe and efficient
//! manner. It includes traits and implementations that facilitate the binding of parameters to
//! various SQL query types, ensuring that the queries are correctly formatted and executed against
//! the database.
//!
//! Key components of this module include the `Bindable` trait, which abstracts over different
//! types of queries, allowing for flexible and dynamic binding of values, and the `Bind` trait,
//! which provides an interface for binding columns to SQL queries in the context of a specific
//! table.
//!
//! # Types
//!
//! - `BindError`: An error related to binding operations, such as unknown column errors.
//! - `Bindable`: A trait for abstracting over different query types, providing a method to dynamically bind values.
//! - `Bind`: A trait for binding columns to SQL queries, specific to table entities.
//!
//! The module plays a crucial role in the framework, enabling developers to write database
//! interactions that are both expressive and resilient to errors like incorrect parameter types or
//! missing values.
use crate::{Column, Result, Table};
use sqlx::database::HasArguments;
use sqlx::query::QueryAs;
use sqlx::{Encode, QueryBuilder, Type};
use thiserror::Error;

/// An error that occured while binding values
/// Enumerates errors that can occur during the binding of values to SQL queries.
///
/// This enum covers various issues that might arise when binding parameters, such as referencing
/// unknown columns.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum BindError {
/// Represents an error where a specified column is unknown or not found.
#[error("unknown column: {0}")]
Unknown(&'static str),
}

type Query<'q, DB> = sqlx::query::Query<'q, DB, <DB as HasArguments<'q>>::Arguments>;

/// Bindable query abstraction. Implementors are [`sqlx::query::Query`] & [`sqlx::query::QueryAs`];
/// Trait for dynamic binding of values.
///
/// `Bindable` provides an abstraction over different types of SQL queries, such as
/// `sqlx::query::Query` and `sqlx::query::QueryAs`, allowing for flexible and dynamic binding of
/// values. It is designed to work with various query types and enables the binding of values with
/// different types and constraints.
pub trait Bindable<'q> {
/// Binds a value to the query. The value must be compatible with the `atmosphere::Driver`.
fn dyn_bind<T: 'q + Send + Encode<'q, crate::Driver> + Type<crate::Driver>>(
self,
value: T,
Expand Down
22 changes: 21 additions & 1 deletion atmosphere-core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
//! Error Handling Module for Atmosphere
//!
//! This module defines the error handling mechanisms used throughout the Atmosphere framework. It
//! provides a comprehensive `Error` type that encapsulates various kinds of errors that may occur
//! during database operations, file IO, and other framework-related activities.
//!
//! The module simplifies error management by categorizing common error types and providing a
//! unified interface for handling them. This approach enhances code readability and
//! maintainability, especially in scenarios involving complex database interactions and
//! operations.
use thiserror::Error;

use crate::{query::QueryError, BindError};

/// Errors that can occur within Atmosphere.
///
/// This enum encapsulates a range of errors including IO errors, query-related errors, binding
/// errors, and others. It is designed to provide a unified error handling mechanism across
/// different components of the framework.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
Expand All @@ -21,5 +37,9 @@ pub enum Error {
Internal,
}

/// A result type for atmosphere code
/// A specialized `Result` type for use throughout the Atmosphere framework.
///
/// This type alias simplifies error handling by using the `Error` enum as the default error type.
/// It is used as the return type for functions and methods within the framework, where errors are
/// expected to be one of the variants defined in the `Error` enum.
pub type Result<T> = std::result::Result<T, Error>;
52 changes: 44 additions & 8 deletions atmosphere-core/src/hooks/mod.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
//! Atmosphere Hook System
//!
//! This module provides a system for defining and applying hooks at various stages of query
//! execution. Hooks allow for custom logic to be executed at predetermined points in the query
//! lifecycle, such as before binding, before execution, and after execution. This functionality is
//! essential for implementing side effects, validations, or augmentations to the standard query
//! process.
//!
//! # Concepts
//!
//! - `HookStage`: An enum representing different stages in the query lifecycle where hooks can be applied.
//! - `HookInput`: An enum representing different types of input that can be provided to hooks.
//! - `Hook`: A trait defining a hook with a specific stage and an application method.
//! - `Hooks`: A trait for associating a set of hooks with a table entity.
//! - `execute`: A function to execute the appropriate hooks for a given stage and context.
//!
//! The hooks system is a powerful tool for extending and customizing the behavior of database operations,
//! enabling developers to embed additional logic seamlessly within the query execution flow.
use async_trait::async_trait;

use crate::{
query::{Query, QueryResult},
Bind, Result, Table,
};

/// Enumerates different stages in the query lifecycle for hook application.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum HookStage {
/// Represents the stage before query parameters are bound.
PreBind,
/// Indicates the stage before query execution.
PreExec,
/// Denotes the stage after the query has been executed.
PostExec,
}

/// Represents different types of input that can be provided to hooks.
pub enum HookInput<'t, T: Table + Bind> {
/// No input is provided to the hook.
None,
/// A mutable reference to a table row entity.
Row(&'t mut T),
/// A reference to the primary key of a table entity.
PrimaryKey(&'t T::PrimaryKey),
/// The result of a query operation.
QueryResult(QueryResult<'t, T>),
}

Expand All @@ -25,23 +53,31 @@ impl<'t, T: Table + Bind> From<QueryResult<'t, T>> for HookInput<'t, T> {
}
}

/// A trait defining a hook for query execution.
///
/// Implementors of this trait can define custom logic to be executed at a specific stage of the
/// query lifecycle. The trait provides a method to specify the stage at which the hook should be
/// applied and another method to implement the hook's logic.
#[async_trait]
pub trait Hook<T: Table + Bind + Sync>: Sync + Send {
/// Stage
/// Returns the stage at which the hook should be applied.
fn stage(&self) -> HookStage;

///
async fn apply(
&self,
#[allow(unused)] ctx: &Query<T>,
#[allow(unused)] input: &mut HookInput<'_, T>,
) -> Result<()> {
println!("{}", ctx.sql());
/// Asynchronously applies the hook logic to a given query context and input.
async fn apply(&self, ctx: &Query<T>, input: &mut HookInput<'_, T>) -> Result<()> {
let _ = ctx;
let _ = input;
Ok(())
}
}

/// A trait for associating a set of hooks with a table entity.
///
/// Implementors can define a static array of hooks that are associated with a table entity. These
/// hooks are invoked at their respective stages during the query execution process, enabling
/// custom behaviors or validations.
pub trait Hooks: Table + Bind {
/// A static array of references to hooks associated with the implementing table entity.
const HOOKS: &'static [&'static dyn Hook<Self>];
}

Expand Down
46 changes: 38 additions & 8 deletions atmosphere-core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,48 @@
/// Bind entities to queries
//! # `🌍 Atmosphere`
//!
//! **A lightweight sql framework for sustainable database reliant systems**
//!
//! ## Overview
//!
//! Atmosphere is a lightweight SQL framework designed for sustainable, database-reliant systems.
//! It leverages Rust's powerful type and macro systems to derive SQL schemas from your rust struct
//! definitions into an advanced trait system.
//!
//! Atmosphere provides a suite of modules and types that abstract and facilitate various aspects
//! of database operations, from query construction and execution to error handling and schema
//! management.
//!
//! ## Key Features
//!
//! - SQL schema derivation from Rust structs.
//! - Advanced trait system for query generation.
//! - Automated database code testing with `atmosphere::testing`
//! - ORM-like CRUD traits.
//! - Code reusability across API layers using generics.
//! - Compile-time introspection for type-safe schema generation.
/// Facilitates binding entities to queries, ensuring type safety and ease of use in query construction.
pub mod bind;
/// High level database error types

/// Defines high-level database error types, offering a structured approach to error handling.
pub mod error;
/// Hook system
/// Implements a hook system, allowing custom logic to be executed at different stages of database
/// interactions.
pub mod hooks;
/// Query abstraction
/// Offers an abstraction layer for building and executing SQL queries, simplifying complex query
/// logic.
pub mod query;
/// Abstraction to model sql relationships
/// Models SQL relationships, providing tools to define and manipulate relationships between
/// database entities.
pub mod rel;
/// Runtime environment
/// Manages the runtime environment for database operations, encompassing execution contexts and
/// configurations.
pub mod runtime;
/// Compile time generated SQL schema traits
/// Contains compile-time generated SQL schema traits, enabling a declarative approach to schema
/// definition.
pub mod schema;
/// Automated testing of SQL interactions
/// Provides utilities for automated testing of SQL interactions, ensuring reliability and
/// correctness of database operations.
pub mod testing;

/// Atmosphere Database Driver
Expand Down
30 changes: 25 additions & 5 deletions atmosphere-core/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
//! Provides structures and enums for handling and executing SQL queries, along with error
//! handling.
//!
//! This module includes custom error types for different database-related errors, enums for query
//! operations and cardinality, and a struct for building and managing queries for database tables.
use sqlx::QueryBuilder;
use thiserror::Error;

use crate::{runtime::sql::Bindings, Bind, Result, Table};

/// An error that occured while executing the query
/// Errors that can occur while executing a database query.
///
/// This enum includes variants for IO errors, row not found errors, SQLSTATE errors, violation
/// errors, and others, allowing for detailed categorization and handling of different database
/// errors.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum QueryError {
Expand Down Expand Up @@ -32,6 +42,11 @@ pub enum QueryError {
InternalError(#[source] sqlx::Error),
}

/// Represents errors related to constraint violations in the database.
///
/// Includes uniqueness violations, foreign key violations, and integrity check errors,
/// encapsulating different types of constraint-related issues that can occur during database
/// operations.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum ViolationError {
Expand All @@ -43,7 +58,10 @@ pub enum ViolationError {
Check(#[source] sqlx::Error),
}

/// SQLSTATE derived errors
/// Encapsulates errors derived from SQLSTATE codes.
///
/// This enum categorizes various SQL errors such as data exceptions, integrity constraints, syntax
/// errors, and others, based on their SQLSTATE classification.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum SqlError {
Expand Down Expand Up @@ -113,15 +131,15 @@ impl From<sqlx::Error> for QueryError {
}
}

/// Cardinality information on the affected rows
/// Describes the cardinality of the rows affected by a query.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Cardinality {
None,
One,
Many,
}

/// The operation that the query contains
/// Describes the types of operations that a query performs.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Operation {
Select,
Expand All @@ -132,7 +150,7 @@ pub enum Operation {
Other,
}

/// A generated atmosphere query over a given table
/// Represents a atmosphere query over a database table.
pub struct Query<T: Bind> {
pub op: Operation,
pub cardinality: Cardinality,
Expand Down Expand Up @@ -160,11 +178,13 @@ impl<T: Bind> Query<T> {
self.builder.sql()
}

/// Access the column bindings
pub const fn bindings(&self) -> &Bindings<T> {
&self.bindings
}
}

/// Describes possible results of executing a query.
pub enum QueryResult<'t, T: Table + Bind> {
Execution(&'t Result<<crate::Driver as sqlx::Database>::QueryResult>),
Optional(&'t Result<Option<T>>),
Expand Down
22 changes: 20 additions & 2 deletions atmosphere-core/src/rel.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
//! Provides traits for managing relationships between database entities.
//!
//! This module contains traits and their implementations for handling relationships such as
//! 'RefersTo' and 'ReferredBy'. These traits facilitate operations like resolving and deleting
//! relationships in a database using SQLx.
use async_trait::async_trait;
use sqlx::database::HasArguments;
use sqlx::{Executor, IntoArguments};
Expand All @@ -8,7 +14,10 @@ use crate::runtime::sql;
use crate::schema::Table;
use crate::{Error, ForeignKey, Result};

/// A relationship where `Self` referrs to `Other`
/// Defines a relationship where `Self` refers to `Other`.
///
/// Implements functionality to resolve this relationship, fetching the `Other` entity that `Self`
/// refers to.
#[async_trait]
pub trait RefersTo<Other>
where
Expand All @@ -17,6 +26,8 @@ where
{
const FOREIGN_KEY: ForeignKey<Self>;

/// Asynchronously resolves and retrieves the `Other` entity that `Self` refers to from the
/// database.
async fn resolve<'e, E>(&self, executor: E) -> Result<Other>
where
E: Executor<'e, Database = crate::Driver>,
Expand All @@ -39,13 +50,18 @@ where
}
}

/// A relationship where `Self` is referred to by many `Other`
/// Defines a relationship where `Self` is referred to by many `Other`.
///
/// This trait provides methods to resolve these relationships, including fetching all `Other`
/// entities referring to `Self`, resolving by primary key, and deleting all such referring
/// entities.
#[async_trait]
pub trait ReferedBy<Other>
where
Self: Table + Bind + Unpin + Sync,
Other: Table + Bind + RefersTo<Self> + Unpin + Sync,
{
/// Asynchronously fetches all `Other` entities referring to `Self`.
async fn resolve<'e, E>(&self, executor: E) -> Result<Vec<Other>>
where
E: Executor<'e, Database = crate::Driver>,
Expand All @@ -67,6 +83,7 @@ where
.map_err(Error::Query)
}

/// Resolves the referring entities based on the primary key of `Self`.
async fn resolve_by<'e, E>(pk: &Self::PrimaryKey, executor: E) -> Result<Vec<Other>>
where
E: Executor<'e, Database = crate::Driver>,
Expand All @@ -84,6 +101,7 @@ where
.map_err(Error::Query)
}

/// Deletes all `Other` entities referring to `Self`.
async fn delete_all<'e, E>(
&self,
executor: E,
Expand Down
Loading

0 comments on commit c608b10

Please sign in to comment.