#![allow(non_camel_case_types)] 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::query_builder::{AsQuery, AstPass, 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 for $col where QS: AppearsInFromClause, Count = Once> { } impl<'a> SelectableExpression> for $col {} impl ValidGrouping<()> for $col { type IsAggregate = is_aggregate::No; } impl ValidGrouping 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 QueryFragment 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: 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 = ::AllColumns; fn from_clause(&self) -> Self::FromClause { self.clone() } fn default_selection(&self) -> Self::DefaultSelection { ::all_columns() } } impl AsQuery for Table<'_> { type SqlType = SqlType; type Query = SelectStatement>; 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 QueryFragment 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> for Table<'_> { type Count = Once; }