atmosphere_core/
bind.rs

1//! Bind Module for Atmosphere SQL Framework
2//!
3//! This module provides functionality to bind values to SQL queries in a type-safe and efficient
4//! manner. It includes traits and implementations that facilitate the binding of parameters to
5//! various SQL query types, ensuring that the queries are correctly formatted and executed against
6//! the database.
7//!
8//! Key components of this module include the `Bindable` trait, which abstracts over different
9//! types of queries, allowing for flexible and dynamic binding of values, and the `Bind` trait,
10//! which provides an interface for binding columns to SQL queries in the context of a specific
11//! table.
12//!
13//! # Types
14//!
15//! - `BindError`: An error related to binding operations, such as unknown column errors.
16//! - `Bindable`: A trait for abstracting over different query types, providing a method to dynamically bind values.
17//! - `Bind`: A trait for binding columns to SQL queries, specific to table entities.
18//!
19//! The module plays a crucial role in the framework, enabling developers to write database
20//! interactions that are both expressive and resilient to errors like incorrect parameter types or
21//! missing values.
22
23use crate::{Column, Result, Table};
24use miette::Diagnostic;
25use sqlx::database::Database;
26use sqlx::query::QueryAs;
27use sqlx::{Encode, QueryBuilder, Type};
28use thiserror::Error;
29
30/// Enumerates errors that can occur during the binding of values to SQL queries.
31///
32/// This enum covers various issues that might arise when binding parameters, such as referencing
33/// unknown columns.
34#[derive(Debug, Diagnostic, Error)]
35#[non_exhaustive]
36pub enum BindError {
37    /// Represents an error where a specified column is unknown or not found.
38    #[error("unknown column: {0}")]
39    #[diagnostic(code(atmosphere::bind::unknown))]
40    Unknown(&'static str),
41}
42
43type Query<'q, DB> = sqlx::query::Query<'q, DB, <DB as Database>::Arguments<'q>>;
44
45/// Trait for dynamic binding of values.
46///
47/// `Bindable` provides an abstraction over different types of SQL queries, such as
48/// `sqlx::query::Query` and `sqlx::query::QueryAs`, allowing for flexible and dynamic binding of
49/// values. It is designed to work with various query types and enables the binding of values with
50/// different types and constraints.
51pub trait Bindable<'q> {
52    /// Binds a value to the query. The value must be compatible with the `atmosphere::Driver`.
53    fn dyn_bind<T: 'q + Send + Encode<'q, crate::Driver> + Type<crate::Driver>>(
54        self,
55        value: T,
56    ) -> Self;
57}
58
59impl<'q> Bindable<'q> for Query<'q, crate::Driver> {
60    fn dyn_bind<T: 'q + Send + Encode<'q, crate::Driver> + Type<crate::Driver>>(
61        self,
62        value: T,
63    ) -> Self {
64        self.bind(value)
65    }
66}
67
68impl<'q, E> Bindable<'q>
69    for QueryAs<'q, crate::Driver, E, <crate::Driver as Database>::Arguments<'q>>
70{
71    fn dyn_bind<T: 'q + Send + Encode<'q, crate::Driver> + Type<crate::Driver>>(
72        self,
73        value: T,
74    ) -> Self {
75        self.bind(value)
76    }
77}
78
79impl<'q> Bindable<'q> for QueryBuilder<'q, crate::Driver> {
80    fn dyn_bind<T: 'q + Send + Encode<'q, crate::Driver> + Type<crate::Driver>>(
81        mut self,
82        value: T,
83    ) -> Self {
84        self.push_bind(value);
85        self
86    }
87}
88
89/// Trait for binding columns to SQL queries in the context of a specific table.
90///
91/// This trait should be implemented by table entities to enable the binding of their columns to
92/// SQL queries. It provides a method to bind a single column, ensuring that the query correctly
93/// reflects the structure and constraints of the table.
94pub trait Bind: Table {
95    /// Binds a single column of the implementing table entity to a given query.
96    fn bind<'q, Q: Bindable<'q>>(&'q self, c: &'q Column<Self>, query: Q) -> Result<Q>;
97}