diff options
| author | Tobias Wiese <tobias@tobiaswiese.com> | 2025-12-03 19:10:02 +0100 |
|---|---|---|
| committer | Tobias Wiese <tobias@tobiaswiese.com> | 2025-12-03 21:08:16 +0100 |
| commit | a464bec09a922d7f9040e512b9ed04794a28d174 (patch) | |
| tree | ceff760ba1b79b4200704cf76c2de4921cc9c2fa /src/db.rs | |
Initial commit1.0.0
Signed-off-by: Tobias Wiese <tobias@tobiaswiese.com>
Diffstat (limited to 'src/db.rs')
| -rw-r--r-- | src/db.rs | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/src/db.rs b/src/db.rs new file mode 100644 index 0000000..6b4240b --- /dev/null +++ b/src/db.rs @@ -0,0 +1,151 @@ +#![allow(non_camel_case_types, non_upper_case_globals)] +#![allow(unused)] // remove this (?) + +use diesel::backend::Backend; +use diesel::expression::{ + IsContainedInGroupBy, ValidGrouping, is_aggregate, is_contained_in_group_by, +}; +use diesel::internal::table_macro::{FromClause, SelectStatement}; +use diesel::prelude::*; +use diesel::prelude::*; +use diesel::query_builder::{AsQuery, AstPass, Query, QueryFragment, QueryId}; +use diesel::query_source::{AppearsInFromClause, Once, Table as TableTrait}; +use diesel::sql_types::{Text, Uuid}; + +pub use self::columns::*; + +pub mod columns { + use super::*; + + macro_rules! col { + ($col:ident, $sql_type:ty) => { + pub struct $col; + + impl Expression for $col { + type SqlType = $sql_type; + } + + impl<'a, QS> AppearsOnTable<QS> for $col where + QS: AppearsInFromClause<super::Table<'a>, Count = Once> + { + } + + impl<'a> SelectableExpression<super::Table<'a>> for $col {} + + impl ValidGrouping<()> for $col { + type IsAggregate = is_aggregate::No; + } + + impl<GB> ValidGrouping<GB> for $col + where + GB: IsContainedInGroupBy<$col, Output = is_contained_in_group_by::Yes>, + { + type IsAggregate = is_aggregate::Yes; + } + + impl<'a> Column for $col { + type Table = Table<'static>; + + const NAME: &'static str = stringify!($col); + } + + impl<DB> QueryFragment<DB> for $col + where + DB: Backend, + { + fn walk_ast<'b>(&'b self, mut pass: AstPass<'_, 'b, DB>) -> QueryResult<()> { + pass.push_identifier(<$col as Column>::NAME)?; + Ok(()) + } + } + + impl QueryId for $col { + type QueryId = $col; + + const HAS_STATIC_QUERY_ID: bool = true; + } + }; + } + + col!(id, Uuid); + col!(username, Text); + col!(token, Text); +} + +//pub const all_columns: <Table<'static> as TableTrait>::AllColumns = (id, username, token); + +pub type SqlType = (Uuid, Text, Text); + +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +pub struct Table<'a> { + name: &'a str, + schema: Option<&'a str>, +} + +impl<'a> Table<'a> { + pub fn new(name: &'a str, schema: Option<&'a str>) -> Self { + Self { name, schema } + } +} + +impl QuerySource for Table<'_> { + type FromClause = Self; + type DefaultSelection = <Self as TableTrait>::AllColumns; + + fn from_clause(&self) -> Self::FromClause { + self.clone() + } + + fn default_selection(&self) -> Self::DefaultSelection { + <Self as TableTrait>::all_columns() + } +} + +impl AsQuery for Table<'_> { + type SqlType = SqlType; + type Query = SelectStatement<FromClause<Self>>; + + fn as_query(self) -> Self::Query { + SelectStatement::simple(self) + } +} + +impl TableTrait for Table<'_> +where + Self: QuerySource + AsQuery, +{ + type PrimaryKey = id; + type AllColumns = (id, username, token); + + fn primary_key(&self) -> Self::PrimaryKey { + id + } + + fn all_columns() -> Self::AllColumns { + (id, username, token) + } +} + +impl<DB> QueryFragment<DB> for Table<'_> +where + DB: Backend, +{ + fn walk_ast<'b>(&'b self, mut pass: AstPass<'_, 'b, DB>) -> QueryResult<()> { + if let Some(ref schema) = self.schema { + pass.push_identifier(schema)?; + pass.push_sql("."); + } + pass.push_identifier(self.name)?; + Ok(()) + } +} + +impl QueryId for Table<'_> { + type QueryId = (); + + const HAS_STATIC_QUERY_ID: bool = false; +} + +impl AppearsInFromClause<Table<'_>> for Table<'_> { + type Count = Once; +} |
