#![cfg_attr(rustfmt, rustfmt_skip)]
#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_column {
(
table = $table:ident,
name = $column_name:ident,
sql_name = $sql_name:expr,
ty = ($($Type:tt)*),
meta = [$($meta:tt)*],
) => {
$($meta)*
#[allow(non_camel_case_types, dead_code)]
#[derive(Debug, Clone, Copy, QueryId, Default)]
pub struct $column_name;
impl $crate::expression::Expression for $column_name {
type SqlType = $($Type)*;
}
impl<DB> $crate::query_builder::QueryFragment<DB> for $column_name where
DB: $crate::backend::Backend,
<$table as QuerySource>::FromClause: QueryFragment<DB>,
{
fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> {
$table.from_clause().walk_ast(out.reborrow())?;
out.push_sql(".");
out.push_identifier($sql_name)
}
}
impl SelectableExpression<$table> for $column_name {
}
impl<QS> AppearsOnTable<QS> for $column_name where
QS: AppearsInFromClause<$table, Count=Once>,
{
}
impl<Left, Right> SelectableExpression<
Join<Left, Right, LeftOuter>,
> for $column_name where
$column_name: AppearsOnTable<Join<Left, Right, LeftOuter>>,
Left: AppearsInFromClause<$table, Count=Once>,
Right: AppearsInFromClause<$table, Count=Never>,
{
}
impl<Left, Right> SelectableExpression<
Join<Left, Right, Inner>,
> for $column_name where
$column_name: AppearsOnTable<Join<Left, Right, Inner>>,
Join<Left, Right, Inner>: AppearsInFromClause<$table, Count=Once>,
{
}
impl<Join, On> SelectableExpression<JoinOn<Join, On>> for $column_name where
$column_name: SelectableExpression<Join> + AppearsOnTable<JoinOn<Join, On>>,
{
}
impl<From> SelectableExpression<SelectStatement<From>> for $column_name where
$column_name: SelectableExpression<From> + AppearsOnTable<SelectStatement<From>>,
{
}
impl $crate::expression::NonAggregate for $column_name {}
impl $crate::query_source::Column for $column_name {
type Table = $table;
const NAME: &'static str = $sql_name;
}
impl<T> $crate::EqAll<T> for $column_name where
T: $crate::expression::AsExpression<$($Type)*>,
$crate::dsl::Eq<$column_name, T>: $crate::Expression<SqlType=$crate::sql_types::Bool>,
{
type Output = $crate::dsl::Eq<Self, T>;
fn eq_all(self, rhs: T) -> Self::Output {
$crate::expression::operators::Eq::new(self, rhs.as_expression())
}
}
__diesel_generate_ops_impls_if_numeric!($column_name, $($Type)*);
__diesel_generate_ops_impls_if_date_time!($column_name, $($Type)*);
}
}
#[macro_export]
macro_rules! table {
($($tokens:tt)*) => {
__diesel_parse_table! {
tokens = [$($tokens)*],
imports = [],
meta = [],
sql_name = unknown,
name = unknown,
schema = public,
primary_key = (id),
}
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_invalid_table_syntax {
() => {
compile_error!(
"Invalid `table!` syntax. Please see the `table!` macro docs for more info. \
`https://docs.diesel.rs/diesel/macro.table.html`"
);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_parse_table {
(
tokens = [use $($import:tt)::+; $($rest:tt)*],
imports = [$($imports:tt)*],
$($args:tt)*
) => {
__diesel_parse_table! {
tokens = [$($rest)*],
imports = [$($imports)* use $($import)::+;],
$($args)*
}
};
(
tokens = [#[sql_name = $sql_name:expr] $($rest:tt)*],
imports = $imports:tt,
meta = $meta:tt,
sql_name = $ignore:tt,
$($args:tt)*
) => {
__diesel_parse_table! {
tokens = [$($rest)*],
imports = $imports,
meta = $meta,
sql_name = $sql_name,
$($args)*
}
};
(
tokens = [#$new_meta:tt $($rest:tt)*],
imports = $imports:tt,
meta = [$($meta:tt)*],
$($args:tt)*
) => {
__diesel_parse_table! {
tokens = [$($rest)*],
imports = $imports,
meta = [$($meta)* #$new_meta],
$($args)*
}
};
(
tokens = [$schema:ident . $($rest:tt)*],
imports = $imports:tt,
meta = $meta:tt,
sql_name = $sql_name:tt,
name = $name:tt,
schema = $ignore:tt,
$($args:tt)*
) => {
__diesel_parse_table! {
tokens = [$($rest)*],
imports = $imports,
meta = $meta,
sql_name = $sql_name,
name = $name,
schema = $schema,
$($args)*
}
};
(
tokens = [$name:ident $($rest:tt)*],
imports = $imports:tt,
meta = $meta:tt,
sql_name = $sql_name:tt,
name = $ignore:tt,
$($args:tt)*
) => {
__diesel_parse_table! {
tokens = [$($rest)*],
imports = $imports,
meta = $meta,
sql_name = $sql_name,
name = $name,
$($args)*
}
};
(
tokens = [($($pk:ident),+ $(,)*) $($rest:tt)*],
imports = $imports:tt,
meta = $meta:tt,
sql_name = $sql_name:tt,
name = $name:tt,
schema = $schema:tt,
primary_key = $ignore:tt,
$($args:tt)*
) => {
__diesel_parse_table! {
tokens = [$($rest)*],
imports = $imports,
meta = $meta,
sql_name = $sql_name,
name = $name,
schema = $schema,
primary_key = ($($pk),+),
$($args)*
}
};
(
tokens = [{$($columns:tt)*}],
imports = [],
$($args:tt)*
) => {
__diesel_parse_table! {
tokens = [{$($columns)*}],
imports = [use $crate::sql_types::*;],
$($args)*
}
};
(
tokens = [{$($columns:tt)*}],
imports = $imports:tt,
meta = $meta:tt,
sql_name = unknown,
name = $name:tt,
$($args:tt)*
) => {
__diesel_parse_table! {
tokens = [{$($columns)*}],
imports = $imports,
meta = $meta,
sql_name = stringify!($name),
name = $name,
$($args)*
}
};
(
tokens = [{$($columns:tt)*}],
$($args:tt)*
) => {
__diesel_parse_columns! {
tokens = [$($columns)*],
table = { $($args)* },
columns = [],
}
};
($($tokens:tt)*) => {
__diesel_invalid_table_syntax!();
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_parse_columns {
(
tokens = [
$(#$meta:tt)*
$name:ident -> $($ty:tt)::* $(<$($ty_params:tt)::*>)*,
$($rest:tt)*
],
$($args:tt)*
) => {
__diesel_parse_columns! {
current_column = {
unchecked_meta = [$(#$meta)*],
name = $name,
sql_name = stringify!($name),
ty = ($($ty)::* $(<$($ty_params)::*>)*),
meta = [],
},
tokens = [$($rest)*],
$($args)*
}
};
(
tokens = [
$(#$meta:tt)*
$name:ident -> $ty:ty,
$($rest:tt)*
],
$($args:tt)*
) => {
__diesel_parse_columns! {
current_column = {
unchecked_meta = [$(#$meta)*],
name = $name,
sql_name = stringify!($name),
ty = ($ty),
meta = [],
},
tokens = [$($rest)*],
$($args)*
}
};
(
current_column = {
unchecked_meta = [#[sql_name = $sql_name:expr] $($meta:tt)*],
name = $name:tt,
sql_name = $ignore:expr,
$($current_column:tt)*
},
$($args:tt)*
) => {
__diesel_parse_columns! {
current_column = {
unchecked_meta = [$($meta)*],
name = $name,
sql_name = $sql_name,
$($current_column)*
},
$($args)*
}
};
(
current_column = {
unchecked_meta = [#$new_meta:tt $($unchecked_meta:tt)*],
name = $name:tt,
sql_name = $sql_name:expr,
ty = $ty:tt,
meta = [$($meta:tt)*],
$($current_column:tt)*
},
$($args:tt)*
) => {
__diesel_parse_columns! {
current_column = {
unchecked_meta = [$($unchecked_meta)*],
name = $name,
sql_name = $sql_name,
ty = $ty,
meta = [$($meta)* #$new_meta],
$($current_column)*
},
$($args)*
}
};
(
current_column = {
unchecked_meta = [],
$($current_column:tt)*
},
tokens = $tokens:tt,
table = $table:tt,
columns = [$($columns:tt,)*],
$($args:tt)*
) => {
__diesel_parse_columns! {
tokens = $tokens,
table = $table,
columns = [$($columns,)* { $($current_column)* },],
$($args)*
}
};
(
tokens = [],
$($args:tt)*
) => {
__diesel_table_impl!($($args)*);
};
($($tokens:tt)*) => {
__diesel_invalid_table_syntax!();
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_table_impl {
(
table = {
imports = [$($imports:tt)*],
meta = [$($meta:tt)*],
sql_name = $sql_name:expr,
name = $table_name:ident,
schema = $schema:ident,
primary_key = $primary_key:tt,
},
columns = [$({
name = $column_name:ident,
sql_name = $column_sql_name:expr,
ty = ($($column_ty:tt)*),
$($column:tt)*
},)+],
) => {
$($meta)*
pub mod $table_name {
#![allow(dead_code)]
use $crate::{
QuerySource,
Table,
JoinTo,
};
use $crate::associations::HasTable;
use $crate::insertable::Insertable;
use $crate::query_builder::*;
use $crate::query_builder::nodes::Identifier;
use $crate::query_source::{AppearsInFromClause, Once, Never};
use $crate::query_source::joins::{Join, JoinOn};
$($imports)*
pub use self::columns::*;
pub mod dsl {
$(static_cond! {
if $table_name == $column_name {
compile_error!(concat!(
"Column `",
stringify!($column_name),
"` cannot be named the same as its table.\n \
You may use `#[sql_name = \"",
stringify!($column_name),
"\"]` to reference the table's `",
stringify!($column_name),
"` column. \n \
Docs available at: `https://docs.diesel.rs/diesel/macro.table.html`\n"
));
} else {
pub use super::columns::{$column_name};
}
})+
pub use super::table as $table_name;
}
#[allow(non_upper_case_globals, dead_code)]
pub const all_columns: ($($column_name,)+) = ($($column_name,)+);
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, QueryId)]
pub struct table;
impl table {
#[allow(dead_code)]
pub fn star(&self) -> star {
star
}
}
pub type SqlType = ($($($column_ty)*,)+);
pub type BoxedQuery<'a, DB, ST = SqlType> = BoxedSelectStatement<'a, ST, table, DB>;
__diesel_table_query_source_impl!(table, $schema, $sql_name);
impl AsQuery for table {
type SqlType = SqlType;
type Query = SelectStatement<Self>;
fn as_query(self) -> Self::Query {
SelectStatement::simple(self)
}
}
impl Table for table {
type PrimaryKey = $primary_key;
type AllColumns = ($($column_name,)+);
fn primary_key(&self) -> Self::PrimaryKey {
$primary_key
}
fn all_columns() -> Self::AllColumns {
($($column_name,)+)
}
}
impl HasTable for table {
type Table = Self;
fn table() -> Self::Table {
table
}
}
impl IntoUpdateTarget for table {
type WhereClause = <<Self as AsQuery>::Query as IntoUpdateTarget>::WhereClause;
fn into_update_target(self) -> UpdateTarget<Self::Table, Self::WhereClause> {
self.as_query().into_update_target()
}
}
impl AppearsInFromClause<table> for table {
type Count = Once;
}
impl AppearsInFromClause<table> for () {
type Count = Never;
}
impl<Left, Right, Kind> JoinTo<Join<Left, Right, Kind>> for table where
Join<Left, Right, Kind>: JoinTo<table>,
{
type FromClause = Join<Left, Right, Kind>;
type OnClause = <Join<Left, Right, Kind> as JoinTo<table>>::OnClause;
fn join_target(rhs: Join<Left, Right, Kind>) -> (Self::FromClause, Self::OnClause) {
let (_, on_clause) = Join::join_target(table);
(rhs, on_clause)
}
}
impl<Join, On> JoinTo<JoinOn<Join, On>> for table where
JoinOn<Join, On>: JoinTo<table>,
{
type FromClause = JoinOn<Join, On>;
type OnClause = <JoinOn<Join, On> as JoinTo<table>>::OnClause;
fn join_target(rhs: JoinOn<Join, On>) -> (Self::FromClause, Self::OnClause) {
let (_, on_clause) = JoinOn::join_target(table);
(rhs, on_clause)
}
}
impl<F, S, D, W, O, L, Of, G> JoinTo<SelectStatement<F, S, D, W, O, L, Of, G>> for table where
SelectStatement<F, S, D, W, O, L, Of, G>: JoinTo<table>,
{
type FromClause = SelectStatement<F, S, D, W, O, L, Of, G>;
type OnClause = <SelectStatement<F, S, D, W, O, L, Of, G> as JoinTo<table>>::OnClause;
fn join_target(rhs: SelectStatement<F, S, D, W, O, L, Of, G>) -> (Self::FromClause, Self::OnClause) {
let (_, on_clause) = SelectStatement::join_target(table);
(rhs, on_clause)
}
}
impl<'a, QS, ST, DB> JoinTo<BoxedSelectStatement<'a, QS, ST, DB>> for table where
BoxedSelectStatement<'a, QS, ST, DB>: JoinTo<table>,
{
type FromClause = BoxedSelectStatement<'a, QS, ST, DB>;
type OnClause = <BoxedSelectStatement<'a, QS, ST, DB> as JoinTo<table>>::OnClause;
fn join_target(rhs: BoxedSelectStatement<'a, QS, ST, DB>) -> (Self::FromClause, Self::OnClause) {
let (_, on_clause) = BoxedSelectStatement::join_target(table);
(rhs, on_clause)
}
}
impl<T> Insertable<T> for table
where
<table as AsQuery>::Query: Insertable<T>,
{
type Values = <<table as AsQuery>::Query as Insertable<T>>::Values;
fn values(self) -> Self::Values {
self.as_query().values()
}
}
impl<'a, T> Insertable<T> for &'a table
where
table: Insertable<T>,
{
type Values = <table as Insertable<T>>::Values;
fn values(self) -> Self::Values {
(*self).values()
}
}
pub mod columns {
use super::table;
use $crate::{Expression, SelectableExpression, AppearsOnTable, QuerySource};
use $crate::backend::Backend;
use $crate::query_builder::{QueryFragment, AstPass, SelectStatement};
use $crate::query_source::joins::{Join, JoinOn, Inner, LeftOuter};
use $crate::query_source::{AppearsInFromClause, Once, Never};
use $crate::result::QueryResult;
$($imports)*
#[allow(non_camel_case_types, dead_code)]
#[derive(Debug, Clone, Copy)]
pub struct star;
impl Expression for star {
type SqlType = ();
}
impl<DB: Backend> QueryFragment<DB> for star where
<table as QuerySource>::FromClause: QueryFragment<DB>,
{
fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> {
table.from_clause().walk_ast(out.reborrow())?;
out.push_sql(".*");
Ok(())
}
}
impl SelectableExpression<table> for star {
}
impl AppearsOnTable<table> for star {
}
$(__diesel_column! {
table = table,
name = $column_name,
sql_name = $column_sql_name,
ty = ($($column_ty)*),
$($column)*
})+
}
}
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! __diesel_table_query_source_impl {
($table_struct:ident, public, $table_name:expr) => {
impl QuerySource for $table_struct {
type FromClause = Identifier<'static>;
type DefaultSelection = <Self as Table>::AllColumns;
fn from_clause(&self) -> Self::FromClause {
Identifier($table_name)
}
fn default_selection(&self) -> Self::DefaultSelection {
Self::all_columns()
}
}
};
($table_struct:ident, $schema_name:ident, $table_name:expr) => {
impl QuerySource for $table_struct {
type FromClause = $crate::query_builder::nodes::InfixNode<
'static,
Identifier<'static>,
Identifier<'static>,
>;
type DefaultSelection = <Self as Table>::AllColumns;
fn from_clause(&self) -> Self::FromClause {
$crate::query_builder::nodes::InfixNode::new(
Identifier(stringify!($schema_name)),
Identifier($table_name),
".",
)
}
fn default_selection(&self) -> Self::DefaultSelection {
Self::all_columns()
}
}
};
}
#[macro_export]
macro_rules! joinable {
($($child:ident)::* -> $($parent:ident)::* ($source:ident)) => {
joinable_inner!($($child)::* ::table => $($parent)::* ::table : ($($child)::* ::$source = $($parent)::* ::table));
joinable_inner!($($parent)::* ::table => $($child)::* ::table : ($($child)::* ::$source = $($parent)::* ::table));
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! joinable_inner {
($left_table:path => $right_table:path : ($foreign_key:path = $parent_table:path)) => {
joinable_inner!(
left_table_ty = $left_table,
right_table_ty = $right_table,
right_table_expr = $right_table,
foreign_key = $foreign_key,
primary_key_ty = <$parent_table as $crate::query_source::Table>::PrimaryKey,
primary_key_expr =
<$parent_table as $crate::query_source::Table>::primary_key(&$parent_table),
);
};
(
left_table_ty = $left_table_ty:ty,
right_table_ty = $right_table_ty:ty,
right_table_expr = $right_table_expr:expr,
foreign_key = $foreign_key:path,
primary_key_ty = $primary_key_ty:ty,
primary_key_expr = $primary_key_expr:expr,
) => {
impl $crate::JoinTo<$right_table_ty> for $left_table_ty {
type FromClause = $right_table_ty;
type OnClause = $crate::dsl::Eq<
$crate::expression::nullable::Nullable<$foreign_key>,
$crate::expression::nullable::Nullable<$primary_key_ty>,
>;
fn join_target(rhs: $right_table_ty) -> (Self::FromClause, Self::OnClause) {
use $crate::{ExpressionMethods, NullableExpressionMethods};
(
rhs,
$foreign_key.nullable().eq($primary_key_expr.nullable()),
)
}
}
};
}
#[macro_export]
macro_rules! allow_tables_to_appear_in_same_query {
($left_mod:ident, $($right_mod:ident),+ $(,)*) => {
$(
impl $crate::query_source::AppearsInFromClause<$left_mod::table>
for $right_mod::table
{
type Count = $crate::query_source::Never;
}
impl $crate::query_source::AppearsInFromClause<$right_mod::table>
for $left_mod::table
{
type Count = $crate::query_source::Never;
}
)+
allow_tables_to_appear_in_same_query!($($right_mod,)+);
};
($last_table:ident,) => {};
() => {};
}
#[macro_export]
macro_rules! not_none {
($bytes:expr) => {
match $bytes {
Some(bytes) => bytes,
None => return Err(Box::new($crate::result::UnexpectedNullError)),
}
};
}
#[macro_use]
mod internal;
#[macro_use]
mod query_id;
#[macro_use]
mod static_cond;
#[macro_use]
mod ops;
#[macro_use]
mod tuples;
#[cfg(test)]
mod tests {
use prelude::*;
table! {
foo.bars {
id -> Integer,
baz -> Text,
}
}
mod my_types {
#[derive(Debug, Clone, Copy)]
pub struct MyCustomType;
}
table! {
use sql_types::*;
use macros::tests::my_types::*;
table_with_custom_types {
id -> Integer,
my_type -> MyCustomType,
}
}
table! {
use sql_types::*;
use macros::tests::my_types::*;
table_with_custom_type_and_id (a) {
a -> Integer,
my_type -> MyCustomType,
}
}
#[test]
#[cfg(feature = "postgres")]
fn table_with_custom_schema() {
use pg::Pg;
let expected_sql = r#"SELECT "foo"."bars"."baz" FROM "foo"."bars" -- binds: []"#;
assert_eq!(
expected_sql,
&::debug_query::<Pg, _>(&bars::table.select(bars::baz)).to_string()
);
}
table! {
use sql_types;
use sql_types::*;
table_with_arbitrarily_complex_types {
id -> sql_types::Integer,
qualified_nullable -> sql_types::Nullable<sql_types::Integer>,
deeply_nested_type -> Option<Nullable<Integer>>,
random_tuple -> (Integer, Integer),
}
}
table!(
foo {
id -> Integer,
#[sql_name = "type"]
mytype -> Integer,
#[sql_name = "bleh"]
hey -> Integer,
}
);
#[test]
#[cfg(feature = "postgres")]
fn table_with_column_renaming_postgres() {
use pg::Pg;
let expected_sql =
r#"SELECT "foo"."id", "foo"."type", "foo"."bleh" FROM "foo" WHERE "foo"."type" = $1 -- binds: [1]"#;
assert_eq!(
expected_sql,
::debug_query::<Pg, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
);
}
#[test]
#[cfg(feature = "mysql")]
fn table_with_column_renaming_mysql() {
use mysql::Mysql;
let expected_sql =
r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE `foo`.`type` = ? -- binds: [1]"#;
assert_eq!(
expected_sql,
::debug_query::<Mysql, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
);
}
#[test]
#[cfg(feature = "sqlite")]
fn table_with_column_renaming_sqlite() {
use sqlite::Sqlite;
let expected_sql =
r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE `foo`.`type` = ? -- binds: [1]"#;
assert_eq!(
expected_sql,
::debug_query::<Sqlite, _>(&foo::table.filter(foo::mytype.eq(1))).to_string()
);
}
table!(
use sql_types::*;
#[sql_name="mod"]
bar {
id -> Integer,
}
);
#[test]
#[cfg(feature = "postgres")]
fn table_renaming_postgres() {
use pg::Pg;
let expected_sql = r#"SELECT "mod"."id" FROM "mod" -- binds: []"#;
assert_eq!(
expected_sql,
::debug_query::<Pg, _>(&bar::table.select(bar::id)).to_string()
);
}
#[test]
#[cfg(feature = "mysql")]
fn table_renaming_mysql() {
use mysql::Mysql;
let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
assert_eq!(
expected_sql,
::debug_query::<Mysql, _>(&bar::table.select(bar::id)).to_string()
);
}
#[test]
#[cfg(feature = "sqlite")]
fn table_renaming_sqlite() {
use sqlite::Sqlite;
let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#;
assert_eq!(
expected_sql,
::debug_query::<Sqlite, _>(&bar::table.select(bar::id)).to_string()
);
}
}