drizzle-core 0.3.0

A type-safe SQL query builder for Rust
Documentation
//! Traits for schema items (tables, columns, indexes, views, ...) and SQL
//! rendering.
//!
//! The table, index, view and schema macros implement almost all of these.
//! Users mostly call their methods, or meet them in error messages.

use crate::TableRef;
use crate::prelude::*;
use core::any::Any;

#[macro_use]
mod tuple;

mod column;
mod constraint;
mod foreign_key;
mod index;
mod param;
mod policy;
mod table;
mod to_sql;
mod type_set;
mod view;

pub use column::*;
pub use constraint::*;
pub use foreign_key::*;
pub use index::*;
pub use param::*;
pub use policy::*;
pub use table::*;
pub use to_sql::*;
pub use type_set::*;
pub use view::*;

/// A schema item (table, column, index, view, enum) with a name and its
/// `CREATE` SQL.
///
/// Generated by the schema macros. `'a` is the lifetime of borrowed
/// parameter values in the SQL it renders.
#[diagnostic::on_unimplemented(
    message = "`{Self}` is not a SQL schema element",
    label = "this type was not derived with a drizzle schema macro"
)]
pub trait SQLSchema<'a, T, V: SQLParam + 'a>: ToSQL<'a, V> {
    /// The item's SQL name.
    const NAME: &'static str;
    /// The kind of item (a dialect-specific enum, or the column's SQL type
    /// name for columns).
    const TYPE: T;
    /// The statement that creates the item (`CREATE TABLE ...`), or an
    /// empty string when it has none.
    const SQL: &'static str;
}

impl<'a, S, T, V> SQLSchema<'a, T, V> for &S
where
    S: SQLSchema<'a, T, V>,
    V: SQLParam + 'a,
{
    const NAME: &'static str = <S as SQLSchema<'a, T, V>>::NAME;
    const TYPE: T = <S as SQLSchema<'a, T, V>>::TYPE;
    const SQL: &'static str = <S as SQLSchema<'a, T, V>>::SQL;
}

/// The tables a schema item adds to its schema, as a type-level list.
///
/// A table adds itself (`Cons<Table, Nil>`); indexes, views and enums add
/// nothing (`Nil`).
#[diagnostic::on_unimplemented(
    message = "`{Self}` is not a recognized schema item",
    label = "schema items must be tables, views, indexes, or enums derived with drizzle macros"
)]
pub trait SchemaItemTables {
    /// `Cons<Table, Nil>` for a table, `Nil` otherwise.
    type Tables: TypeSet;
    /// The table's metadata, or `None` for an item that is not a table.
    const TABLE_REF_CONST: Option<&'static TableRef> = None;
}

/// Dialect marker for schema items: `SQLiteSchemaType`,
/// `PostgresSchemaType` or `MySQLSchemaType`.
///
/// Keeps a SQLite table from being used with a PostgreSQL schema, and so on.
#[diagnostic::on_unimplemented(
    message = "`{Self}` is not a SQL schema type marker",
    label = "expected a dialect marker like SQLiteSchemaType, PostgresSchemaType, or MySQLSchemaType"
)]
pub trait SQLSchemaType: core::fmt::Debug + Any + Send + Sync {}

/// A schema struct (generated by `#[SQLiteSchema]`, `#[PostgresSchema]`,
/// ...) that can list its tables and render its `CREATE` statements.
pub trait SQLSchemaImpl: Any + Send + Sync {
    /// Metadata of every table in the schema.
    fn table_refs(&self) -> &'static [&'static TableRef];
    /// Returns the `CREATE` statements for the schema's items.
    ///
    /// # Errors
    ///
    /// Returns an error if SQL generation for any table fails.
    fn create_statements(&self) -> crate::error::Result<impl Iterator<Item = String>>;
}