1 #![cfg_attr(rustfmt, rustfmt_skip)] // https://github.com/rust-lang-nursery/rustfmt/issues/2755 2 3 #[macro_export] 4 #[doc(hidden)] 5 macro_rules! __diesel_column { 6 ( 7 table = $table:ident, 8 name = $column_name:ident, 9 sql_name = $sql_name:expr, 10 ty = ($($Type:tt)*), 11 meta = [$($meta:tt)*], 12 ) => { 13 $($meta)* 14 #[allow(non_camel_case_types, dead_code)] 15 #[derive(Debug, Clone, Copy, QueryId, Default)] 16 pub struct $column_name; 17 18 impl $crate::expression::Expression for $column_name { 19 type SqlType = $($Type)*; 20 } 21 22 impl<DB> $crate::query_builder::QueryFragment<DB> for $column_name where 23 DB: $crate::backend::Backend, 24 <$table as QuerySource>::FromClause: QueryFragment<DB>, 25 { 26 fn walk_ast(&self, mut out: $crate::query_builder::AstPass<DB>) -> $crate::result::QueryResult<()> { 27 $table.from_clause().walk_ast(out.reborrow())?; 28 out.push_sql("."); 29 out.push_identifier($sql_name) 30 } 31 } 32 33 impl SelectableExpression<$table> for $column_name { 34 } 35 36 impl<QS> AppearsOnTable<QS> for $column_name where 37 QS: AppearsInFromClause<$table, Count=Once>, 38 { 39 } 40 41 impl<Left, Right> SelectableExpression< 42 Join<Left, Right, LeftOuter>, 43 > for $column_name where 44 $column_name: AppearsOnTable<Join<Left, Right, LeftOuter>>, 45 Left: AppearsInFromClause<$table, Count=Once>, 46 Right: AppearsInFromClause<$table, Count=Never>, 47 { 48 } 49 50 impl<Left, Right> SelectableExpression< 51 Join<Left, Right, Inner>, 52 > for $column_name where 53 $column_name: AppearsOnTable<Join<Left, Right, Inner>>, 54 Join<Left, Right, Inner>: AppearsInFromClause<$table, Count=Once>, 55 { 56 } 57 58 // FIXME: Remove this when overlapping marker traits are stable 59 impl<Join, On> SelectableExpression<JoinOn<Join, On>> for $column_name where 60 $column_name: SelectableExpression<Join> + AppearsOnTable<JoinOn<Join, On>>, 61 { 62 } 63 64 // FIXME: Remove this when overlapping marker traits are stable 65 impl<From> SelectableExpression<SelectStatement<From>> for $column_name where 66 $column_name: SelectableExpression<From> + AppearsOnTable<SelectStatement<From>>, 67 { 68 } 69 70 impl $crate::expression::NonAggregate for $column_name {} 71 72 impl $crate::query_source::Column for $column_name { 73 type Table = $table; 74 75 const NAME: &'static str = $sql_name; 76 } 77 78 impl<T> $crate::EqAll<T> for $column_name where 79 T: $crate::expression::AsExpression<$($Type)*>, 80 $crate::dsl::Eq<$column_name, T>: $crate::Expression<SqlType=$crate::sql_types::Bool>, 81 { 82 type Output = $crate::dsl::Eq<Self, T>; 83 84 fn eq_all(self, rhs: T) -> Self::Output { 85 $crate::expression::operators::Eq::new(self, rhs.as_expression()) 86 } 87 } 88 89 __diesel_generate_ops_impls_if_numeric!($column_name, $($Type)*); 90 __diesel_generate_ops_impls_if_date_time!($column_name, $($Type)*); 91 } 92 } 93 94 /// Specifies that a table exists, and what columns it has. This will create a 95 /// new public module, with the same name, as the name of the table. In this 96 /// module, you'll find a unit struct named `table`, and a unit struct with the 97 /// names of each of the columns. 98 /// 99 /// By default this allows a maximum of 32 columns per table. 100 /// You can increase this limit to 64 by enabling the `64-column-tables` feature. 101 /// You can increase it to 128 by enabling the `128-column-tables` feature. 102 /// You can decrease it to 16 columns, 103 /// which improves compilation time, 104 /// by disabling the default features of Diesel. 105 /// Note that enabling 64 column tables or larger will substantially increase 106 /// the compile time of Diesel. 107 /// 108 /// Example usage 109 /// ------------- 110 /// 111 /// ```rust 112 /// # #[macro_use] extern crate diesel; 113 /// table! { 114 /// users { 115 /// id -> Integer, 116 /// name -> VarChar, 117 /// favorite_color -> Nullable<VarChar>, 118 /// } 119 /// } 120 /// # fn main() {} 121 /// ``` 122 /// 123 /// You may also specify a primary key if it's called something other than `id`. 124 /// Tables with no primary key are not supported. 125 /// 126 /// ```rust 127 /// # #[macro_use] extern crate diesel; 128 /// table! { 129 /// users (non_standard_primary_key) { 130 /// non_standard_primary_key -> Integer, 131 /// name -> VarChar, 132 /// favorite_color -> Nullable<VarChar>, 133 /// } 134 /// } 135 /// # fn main() {} 136 /// ``` 137 /// 138 /// For tables with composite primary keys, list all of the columns in the 139 /// primary key. 140 /// 141 /// ```rust 142 /// # #[macro_use] extern crate diesel; 143 /// table! { 144 /// followings (user_id, post_id) { 145 /// user_id -> Integer, 146 /// post_id -> Integer, 147 /// favorited -> Bool, 148 /// } 149 /// } 150 /// # fn main() { 151 /// # use diesel::prelude::*; 152 /// # use self::followings::dsl::*; 153 /// # // Poor man's assert_eq! -- since this is type level this would fail 154 /// # // to compile if the wrong primary key were generated 155 /// # let (user_id {}, post_id {}) = followings.primary_key(); 156 /// # } 157 /// ``` 158 /// 159 /// If you are using types that aren't from Diesel's core types, you can specify 160 /// which types to import. 161 /// 162 /// ``` 163 /// #[macro_use] extern crate diesel; 164 /// # /* 165 /// extern crate diesel_full_text_search; 166 /// # */ 167 /// # mod diesel_full_text_search { 168 /// # pub struct TsVector; 169 /// # } 170 /// 171 /// table! { 172 /// use diesel::sql_types::*; 173 /// use diesel_full_text_search::*; 174 /// 175 /// posts { 176 /// id -> Integer, 177 /// title -> Text, 178 /// keywords -> TsVector, 179 /// } 180 /// } 181 /// # fn main() {} 182 /// ``` 183 /// 184 /// If you want to add documentation to the generated code you can use the 185 /// following syntax: 186 /// 187 /// ``` 188 /// #[macro_use] extern crate diesel; 189 /// 190 /// table! { 191 /// 192 /// /// The table containing all blog posts 193 /// posts { 194 /// /// The post's unique id 195 /// id -> Integer, 196 /// /// The post's title 197 /// title -> Text, 198 /// } 199 /// } 200 /// # fn main() {} 201 /// ``` 202 /// 203 /// If you have a column with the same name as a Rust reserved keyword, you can use 204 /// the `sql_name` attribute like this: 205 /// 206 /// ``` 207 /// #[macro_use] extern crate diesel; 208 /// 209 /// table! { 210 /// posts { 211 /// id -> Integer, 212 /// /// This column is named `mytype` but references the table `type` column. 213 /// #[sql_name = "type"] 214 /// mytype -> Text, 215 /// } 216 /// } 217 /// # fn main() {} 218 /// ``` 219 /// 220 /// This module will also contain several helper types: 221 /// 222 /// dsl 223 /// --- 224 /// 225 /// This simply re-exports the table, renamed to the same name as the module, 226 /// and each of the columns. This is useful to glob import when you're dealing 227 /// primarily with one table, to allow writing `users.filter(name.eq("Sean"))` 228 /// instead of `users::table.filter(users::name.eq("Sean"))`. 229 /// 230 /// `all_columns` 231 /// ----------- 232 /// 233 /// A constant will be assigned called `all_columns`. This is what will be 234 /// selected if you don't otherwise specify a select clause. It's type will be 235 /// `table::AllColumns`. You can also get this value from the 236 /// `Table::all_columns` function. 237 /// 238 /// star 239 /// ---- 240 /// 241 /// This will be the qualified "star" expression for this table (e.g. 242 /// `users.*`). Internally, we read columns by index, not by name, so this 243 /// column is not safe to read data out of, and it has had it's SQL type set to 244 /// `()` to prevent accidentally using it as such. It is sometimes useful for 245 /// count statements however. It can also be accessed through the `Table.star()` 246 /// method. 247 /// 248 /// `SqlType` 249 /// ------- 250 /// 251 /// A type alias called `SqlType` will be created. It will be the SQL type of 252 /// `all_columns`. The SQL type is needed for things like [returning boxed 253 /// queries][boxed_queries]. 254 /// 255 /// [boxed_queries]: query_dsl/trait.QueryDsl.html#method.into_boxed 256 /// 257 /// `BoxedQuery` 258 /// ---------- 259 /// 260 /// ```ignore 261 /// pub type BoxedQuery<'a, DB, ST = SqlType> = BoxedSelectStatement<'a, ST, table, DB>; 262 /// ``` 263 #[macro_export] 264 macro_rules! table { 265 ($($tokens:tt)*) => { 266 __diesel_parse_table! { 267 tokens = [$($tokens)*], 268 imports = [], 269 meta = [], 270 sql_name = unknown, 271 name = unknown, 272 schema = public, 273 primary_key = (id), 274 } 275 } 276 } 277 278 #[macro_export] 279 #[doc(hidden)] 280 macro_rules! __diesel_invalid_table_syntax { 281 () => { 282 compile_error!( 283 "Invalid `table!` syntax. Please see the `table!` macro docs for more info." 284 ); 285 }; 286 } 287 288 #[macro_export] 289 #[doc(hidden)] 290 macro_rules! __diesel_parse_table { 291 // Found an import 292 ( 293 tokens = [use $($import:tt)::+; $($rest:tt)*], 294 imports = [$($imports:tt)*], 295 $($args:tt)* 296 ) => { 297 __diesel_parse_table! { 298 tokens = [$($rest)*], 299 imports = [$($imports)* use $($import)::+;], 300 $($args)* 301 } 302 }; 303 304 // Found sql_name attribute, override whatever we had before 305 ( 306 tokens = [#[sql_name = $sql_name:expr] $($rest:tt)*], 307 imports = $imports:tt, 308 meta = $meta:tt, 309 sql_name = $ignore:tt, 310 $($args:tt)* 311 ) => { 312 __diesel_parse_table! { 313 tokens = [$($rest)*], 314 imports = $imports, 315 meta = $meta, 316 sql_name = $sql_name, 317 $($args)* 318 } 319 }; 320 321 // Meta item other than sql_name, attach it to the table struct 322 ( 323 tokens = [#$new_meta:tt $($rest:tt)*], 324 imports = $imports:tt, 325 meta = [$($meta:tt)*], 326 $($args:tt)* 327 ) => { 328 __diesel_parse_table! { 329 tokens = [$($rest)*], 330 imports = $imports, 331 meta = [$($meta)* #$new_meta], 332 $($args)* 333 } 334 }; 335 336 // Found a schema name, override whatever we had before 337 ( 338 tokens = [$schema:ident . $($rest:tt)*], 339 imports = $imports:tt, 340 meta = $meta:tt, 341 sql_name = $sql_name:tt, 342 name = $name:tt, 343 schema = $ignore:tt, 344 $($args:tt)* 345 ) => { 346 __diesel_parse_table! { 347 tokens = [$($rest)*], 348 imports = $imports, 349 meta = $meta, 350 sql_name = $sql_name, 351 name = $name, 352 schema = $schema, 353 $($args)* 354 } 355 }; 356 357 // Found a table name, override whatever we had before 358 ( 359 tokens = [$name:ident $($rest:tt)*], 360 imports = $imports:tt, 361 meta = $meta:tt, 362 sql_name = $sql_name:tt, 363 name = $ignore:tt, 364 $($args:tt)* 365 ) => { 366 __diesel_parse_table! { 367 tokens = [$($rest)*], 368 imports = $imports, 369 meta = $meta, 370 sql_name = $sql_name, 371 name = $name, 372 $($args)* 373 } 374 }; 375 376 // Found a primary key, override whatever we had before 377 ( 378 tokens = [($($pk:ident),+ $(,)*) $($rest:tt)*], 379 imports = $imports:tt, 380 meta = $meta:tt, 381 sql_name = $sql_name:tt, 382 name = $name:tt, 383 schema = $schema:tt, 384 primary_key = $ignore:tt, 385 $($args:tt)* 386 ) => { 387 __diesel_parse_table! { 388 tokens = [$($rest)*], 389 imports = $imports, 390 meta = $meta, 391 sql_name = $sql_name, 392 name = $name, 393 schema = $schema, 394 primary_key = ($($pk),+), 395 $($args)* 396 } 397 }; 398 399 // Reached columns with no imports, set a default 400 ( 401 tokens = [{$($columns:tt)*}], 402 imports = [], 403 $($args:tt)* 404 ) => { 405 __diesel_parse_table! { 406 tokens = [{$($columns)*}], 407 imports = [use $crate::sql_types::*;], 408 $($args)* 409 } 410 }; 411 412 // Reached columns with no sql_name, set a default 413 ( 414 tokens = [{$($columns:tt)*}], 415 imports = $imports:tt, 416 meta = $meta:tt, 417 sql_name = unknown, 418 name = $name:tt, 419 $($args:tt)* 420 ) => { 421 __diesel_parse_table! { 422 tokens = [{$($columns)*}], 423 imports = $imports, 424 meta = $meta, 425 sql_name = stringify!($name), 426 name = $name, 427 $($args)* 428 } 429 }; 430 431 // Parse the columns 432 ( 433 tokens = [{$($columns:tt)*}], 434 $($args:tt)* 435 ) => { 436 __diesel_parse_columns! { 437 tokens = [$($columns)*], 438 table = { $($args)* }, 439 columns = [], 440 } 441 }; 442 443 // Invalid syntax 444 ($($tokens:tt)*) => { 445 __diesel_invalid_table_syntax!(); 446 } 447 } 448 449 #[macro_export] 450 #[doc(hidden)] 451 macro_rules! __diesel_parse_columns { 452 // No column being parsed, start a new one. 453 // Attempt to capture the type as separate tokens if at all possible. 454 ( 455 tokens = [ 456 $(#$meta:tt)* 457 $name:ident -> $($ty:tt)::* $(<$($ty_params:tt)::*>)*, 458 $($rest:tt)* 459 ], 460 $($args:tt)* 461 ) => { 462 __diesel_parse_columns! { 463 current_column = { 464 unchecked_meta = [$(#$meta)*], 465 name = $name, 466 sql_name = stringify!($name), 467 ty = ($($ty)::* $(<$($ty_params)::*>)*), 468 meta = [], 469 }, 470 tokens = [$($rest)*], 471 $($args)* 472 } 473 }; 474 475 // No column being parsed, start a new one. Couldn't keep the `ty` separate. 476 ( 477 tokens = [ 478 $(#$meta:tt)* 479 $name:ident -> $ty:ty, 480 $($rest:tt)* 481 ], 482 $($args:tt)* 483 ) => { 484 __diesel_parse_columns! { 485 current_column = { 486 unchecked_meta = [$(#$meta)*], 487 name = $name, 488 sql_name = stringify!($name), 489 ty = ($ty), 490 meta = [], 491 }, 492 tokens = [$($rest)*], 493 $($args)* 494 } 495 }; 496 497 498 // Found #[sql_name] 499 ( 500 current_column = { 501 unchecked_meta = [#[sql_name = $sql_name:expr] $($meta:tt)*], 502 name = $name:tt, 503 sql_name = $ignore:expr, 504 $($current_column:tt)* 505 }, 506 $($args:tt)* 507 ) => { 508 __diesel_parse_columns! { 509 current_column = { 510 unchecked_meta = [$($meta)*], 511 name = $name, 512 sql_name = $sql_name, 513 $($current_column)* 514 }, 515 $($args)* 516 } 517 }; 518 519 // Meta item other than #[sql_name] 520 ( 521 current_column = { 522 unchecked_meta = [#$new_meta:tt $($unchecked_meta:tt)*], 523 name = $name:tt, 524 sql_name = $sql_name:expr, 525 ty = $ty:tt, 526 meta = [$($meta:tt)*], 527 $($current_column:tt)* 528 }, 529 $($args:tt)* 530 ) => { 531 __diesel_parse_columns! { 532 current_column = { 533 unchecked_meta = [$($unchecked_meta)*], 534 name = $name, 535 sql_name = $sql_name, 536 ty = $ty, 537 meta = [$($meta)* #$new_meta], 538 $($current_column)* 539 }, 540 $($args)* 541 } 542 }; 543 544 // Done parsing this column 545 ( 546 current_column = { 547 unchecked_meta = [], 548 $($current_column:tt)* 549 }, 550 tokens = $tokens:tt, 551 table = $table:tt, 552 columns = [$($columns:tt,)*], 553 $($args:tt)* 554 ) => { 555 __diesel_parse_columns! { 556 tokens = $tokens, 557 table = $table, 558 columns = [$($columns,)* { $($current_column)* },], 559 $($args)* 560 } 561 }; 562 563 // Done parsing all columns 564 ( 565 tokens = [], 566 $($args:tt)* 567 ) => { 568 __diesel_table_impl!($($args)*); 569 }; 570 571 // Invalid syntax 572 ($($tokens:tt)*) => { 573 __diesel_invalid_table_syntax!(); 574 } 575 } 576 577 #[macro_export] 578 #[doc(hidden)] 579 macro_rules! __diesel_table_impl { 580 ( 581 table = { 582 imports = [$($imports:tt)*], 583 meta = [$($meta:tt)*], 584 sql_name = $sql_name:expr, 585 name = $table_name:ident, 586 schema = $schema:ident, 587 primary_key = $primary_key:tt, 588 }, 589 columns = [$({ 590 name = $column_name:ident, 591 sql_name = $column_sql_name:expr, 592 ty = ($($column_ty:tt)*), 593 $($column:tt)* 594 },)+], 595 ) => { 596 $($meta)* 597 pub mod $table_name { 598 #![allow(dead_code)] 599 use $crate::{ 600 QuerySource, 601 Table, 602 JoinTo, 603 }; 604 use $crate::associations::HasTable; 605 use $crate::insertable::Insertable; 606 use $crate::query_builder::*; 607 use $crate::query_builder::nodes::Identifier; 608 use $crate::query_source::{AppearsInFromClause, Once, Never}; 609 use $crate::query_source::joins::{Join, JoinOn}; 610 $($imports)* 611 pub use self::columns::*; 612 613 /// Re-exports all of the columns of this table, as well as the 614 /// table struct renamed to the module name. This is meant to be 615 /// glob imported for functions which only deal with one table. 616 pub mod dsl { 617 $(static_cond! { 618 if $table_name == $column_name { 619 compile_error!(concat!( 620 "Column `", 621 stringify!($column_name), 622 "` cannot be named the same as its table.\n \ 623 You may use `#[sql_name = \"", 624 stringify!($column_name), 625 "\"]` to reference the table's `", 626 stringify!($column_name), 627 "` column. \n \ 628 See the documentation of the `table!` macro for details`\n" 629 )); 630 } else { 631 pub use super::columns::{$column_name}; 632 } 633 })+ 634 pub use super::table as $table_name; 635 } 636 637 #[allow(non_upper_case_globals, dead_code)] 638 /// A tuple of all of the columns on this table 639 pub const all_columns: ($($column_name,)+) = ($($column_name,)+); 640 641 #[allow(non_camel_case_types)] 642 #[derive(Debug, Clone, Copy, QueryId)] 643 /// The actual table struct 644 /// 645 /// This is the type which provides the base methods of the query 646 /// builder, such as `.select` and `.filter`. 647 pub struct table; 648 649 impl table { 650 #[allow(dead_code)] 651 /// Represents `table_name.*`, which is sometimes necessary 652 /// for efficient count queries. It cannot be used in place of 653 /// `all_columns` 654 pub fn star(&self) -> star { 655 star 656 } 657 } 658 659 /// The SQL type of all of the columns on this table 660 pub type SqlType = ($($($column_ty)*,)+); 661 662 /// Helper type for representing a boxed query from this table 663 pub type BoxedQuery<'a, DB, ST = SqlType> = BoxedSelectStatement<'a, ST, table, DB>; 664 665 __diesel_table_query_source_impl!(table, $schema, $sql_name); 666 667 impl AsQuery for table { 668 type SqlType = SqlType; 669 type Query = SelectStatement<Self>; 670 671 fn as_query(self) -> Self::Query { 672 SelectStatement::simple(self) 673 } 674 } 675 676 impl Table for table { 677 type PrimaryKey = $primary_key; 678 type AllColumns = ($($column_name,)+); 679 680 fn primary_key(&self) -> Self::PrimaryKey { 681 $primary_key 682 } 683 684 fn all_columns() -> Self::AllColumns { 685 ($($column_name,)+) 686 } 687 } 688 689 impl HasTable for table { 690 type Table = Self; 691 692 fn table() -> Self::Table { 693 table 694 } 695 } 696 697 impl IntoUpdateTarget for table { 698 type WhereClause = <<Self as AsQuery>::Query as IntoUpdateTarget>::WhereClause; 699 700 fn into_update_target(self) -> UpdateTarget<Self::Table, Self::WhereClause> { 701 self.as_query().into_update_target() 702 } 703 } 704 705 impl AppearsInFromClause<table> for table { 706 type Count = Once; 707 } 708 709 impl AppearsInFromClause<table> for () { 710 type Count = Never; 711 } 712 713 impl<Left, Right, Kind> JoinTo<Join<Left, Right, Kind>> for table where 714 Join<Left, Right, Kind>: JoinTo<table>, 715 { 716 type FromClause = Join<Left, Right, Kind>; 717 type OnClause = <Join<Left, Right, Kind> as JoinTo<table>>::OnClause; 718 719 fn join_target(rhs: Join<Left, Right, Kind>) -> (Self::FromClause, Self::OnClause) { 720 let (_, on_clause) = Join::join_target(table); 721 (rhs, on_clause) 722 } 723 } 724 725 impl<Join, On> JoinTo<JoinOn<Join, On>> for table where 726 JoinOn<Join, On>: JoinTo<table>, 727 { 728 type FromClause = JoinOn<Join, On>; 729 type OnClause = <JoinOn<Join, On> as JoinTo<table>>::OnClause; 730 731 fn join_target(rhs: JoinOn<Join, On>) -> (Self::FromClause, Self::OnClause) { 732 let (_, on_clause) = JoinOn::join_target(table); 733 (rhs, on_clause) 734 } 735 } 736 737 impl<F, S, D, W, O, L, Of, G> JoinTo<SelectStatement<F, S, D, W, O, L, Of, G>> for table where 738 SelectStatement<F, S, D, W, O, L, Of, G>: JoinTo<table>, 739 { 740 type FromClause = SelectStatement<F, S, D, W, O, L, Of, G>; 741 type OnClause = <SelectStatement<F, S, D, W, O, L, Of, G> as JoinTo<table>>::OnClause; 742 743 fn join_target(rhs: SelectStatement<F, S, D, W, O, L, Of, G>) -> (Self::FromClause, Self::OnClause) { 744 let (_, on_clause) = SelectStatement::join_target(table); 745 (rhs, on_clause) 746 } 747 } 748 749 impl<'a, QS, ST, DB> JoinTo<BoxedSelectStatement<'a, QS, ST, DB>> for table where 750 BoxedSelectStatement<'a, QS, ST, DB>: JoinTo<table>, 751 { 752 type FromClause = BoxedSelectStatement<'a, QS, ST, DB>; 753 type OnClause = <BoxedSelectStatement<'a, QS, ST, DB> as JoinTo<table>>::OnClause; 754 fn join_target(rhs: BoxedSelectStatement<'a, QS, ST, DB>) -> (Self::FromClause, Self::OnClause) { 755 let (_, on_clause) = BoxedSelectStatement::join_target(table); 756 (rhs, on_clause) 757 } 758 } 759 760 // This impl should be able to live in Diesel, 761 // but Rust tries to recurse for no reason 762 impl<T> Insertable<T> for table 763 where 764 <table as AsQuery>::Query: Insertable<T>, 765 { 766 type Values = <<table as AsQuery>::Query as Insertable<T>>::Values; 767 768 fn values(self) -> Self::Values { 769 self.as_query().values() 770 } 771 } 772 773 impl<'a, T> Insertable<T> for &'a table 774 where 775 table: Insertable<T>, 776 { 777 type Values = <table as Insertable<T>>::Values; 778 779 fn values(self) -> Self::Values { 780 (*self).values() 781 } 782 } 783 784 /// Contains all of the columns of this table 785 pub mod columns { 786 use super::table; 787 use $crate::{Expression, SelectableExpression, AppearsOnTable, QuerySource}; 788 use $crate::backend::Backend; 789 use $crate::query_builder::{QueryFragment, AstPass, SelectStatement}; 790 use $crate::query_source::joins::{Join, JoinOn, Inner, LeftOuter}; 791 use $crate::query_source::{AppearsInFromClause, Once, Never}; 792 use $crate::result::QueryResult; 793 $($imports)* 794 795 #[allow(non_camel_case_types, dead_code)] 796 #[derive(Debug, Clone, Copy)] 797 /// Represents `table_name.*`, which is sometimes needed for 798 /// efficient count queries. It cannot be used in place of 799 /// `all_columns`, and has a `SqlType` of `()` to prevent it 800 /// being used that way 801 pub struct star; 802 803 impl Expression for star { 804 type SqlType = (); 805 } 806 807 impl<DB: Backend> QueryFragment<DB> for star where 808 <table as QuerySource>::FromClause: QueryFragment<DB>, 809 { 810 fn walk_ast(&self, mut out: AstPass<DB>) -> QueryResult<()> { 811 table.from_clause().walk_ast(out.reborrow())?; 812 out.push_sql(".*"); 813 Ok(()) 814 } 815 } 816 817 impl SelectableExpression<table> for star { 818 } 819 820 impl AppearsOnTable<table> for star { 821 } 822 823 $(__diesel_column! { 824 table = table, 825 name = $column_name, 826 sql_name = $column_sql_name, 827 ty = ($($column_ty)*), 828 $($column)* 829 })+ 830 } 831 } 832 } 833 } 834 835 #[macro_export] 836 #[doc(hidden)] 837 macro_rules! __diesel_table_query_source_impl { 838 ($table_struct:ident, public, $table_name:expr) => { 839 impl QuerySource for $table_struct { 840 type FromClause = Identifier<'static>; 841 type DefaultSelection = <Self as Table>::AllColumns; 842 843 fn from_clause(&self) -> Self::FromClause { 844 Identifier($table_name) 845 } 846 847 fn default_selection(&self) -> Self::DefaultSelection { 848 Self::all_columns() 849 } 850 } 851 }; 852 853 ($table_struct:ident, $schema_name:ident, $table_name:expr) => { 854 impl QuerySource for $table_struct { 855 type FromClause = $crate::query_builder::nodes::InfixNode< 856 'static, 857 Identifier<'static>, 858 Identifier<'static>, 859 >; 860 type DefaultSelection = <Self as Table>::AllColumns; 861 862 fn from_clause(&self) -> Self::FromClause { 863 $crate::query_builder::nodes::InfixNode::new( 864 Identifier(stringify!($schema_name)), 865 Identifier($table_name), 866 ".", 867 ) 868 } 869 870 fn default_selection(&self) -> Self::DefaultSelection { 871 Self::all_columns() 872 } 873 } 874 }; 875 } 876 877 /// Allow two tables to be referenced in a join query without providing an 878 /// explicit `ON` clause. 879 /// 880 /// The generated `ON` clause will always join to the primary key of the parent 881 /// table. This macro removes the need to call [`.on`] explicitly, you will 882 /// still need to invoke [`allow_tables_to_appear_in_same_query!`] for these two tables to 883 /// be able to use the resulting query, unless you are using `infer_schema!` or 884 /// `diesel print-schema` which will generate it for you. 885 /// 886 /// If you are using `infer_schema!` or `diesel print-schema`, an invocation of 887 /// this macro will be generated for every foreign key in your database unless 888 /// one of the following is true: 889 /// 890 /// - The foreign key references something other than the primary key 891 /// - The foreign key is composite 892 /// - There is more than one foreign key connecting two tables 893 /// - The foreign key is self-referential 894 /// 895 /// # Example 896 /// 897 /// ```rust 898 /// # #[macro_use] extern crate diesel; 899 /// # include!("../doctest_setup.rs"); 900 /// use schema::*; 901 /// 902 /// # /* 903 /// joinable!(posts -> users (user_id)); 904 /// allow_tables_to_appear_in_same_query!(posts, users); 905 /// # */ 906 /// 907 /// # fn main() { 908 /// let implicit_on_clause = users::table.inner_join(posts::table); 909 /// let implicit_on_clause_sql = diesel::debug_query::<DB, _>(&implicit_on_clause).to_string(); 910 /// 911 /// let explicit_on_clause = users::table 912 /// .inner_join(posts::table.on(posts::user_id.eq(users::id))); 913 /// let explicit_on_clause_sql = diesel::debug_query::<DB, _>(&explicit_on_clause).to_string(); 914 /// 915 /// assert_eq!(implicit_on_clause_sql, explicit_on_clause_sql); 916 /// # } 917 /// 918 /// ``` 919 /// 920 /// In the example above, the line `joinable!(posts -> users (user_id));` 921 /// 922 /// specifies the relation of the tables and the ON clause in the following way: 923 /// 924 /// `child_table -> parent_table (foreign_key)` 925 /// 926 /// * `parent_table` is the Table with the Primary key. 927 /// 928 /// * `child_table` is the Table with the Foreign key. 929 /// 930 /// So given the Table decaration from [Associations docs](/associations/index.html) 931 /// 932 /// * The parent table would be `User` 933 /// * The child table would be `Post` 934 /// * and the Foreign key would be `Post.user_id` 935 /// 936 /// For joins that do not explicitly use on clauses via [`JoinOnDsl`](/prelude/trait.JoinOnDsl.html) 937 /// the following on clause is generated implicitly: 938 /// ```sql 939 /// post JOIN users ON posts.user_id = users.id 940 /// ``` 941 #[macro_export] 942 macro_rules! joinable { 943 ($($child:ident)::* -> $($parent:ident)::* ($source:ident)) => { 944 joinable_inner!($($child)::* ::table => $($parent)::* ::table : ($($child)::* ::$source = $($parent)::* ::table)); 945 joinable_inner!($($parent)::* ::table => $($child)::* ::table : ($($child)::* ::$source = $($parent)::* ::table)); 946 } 947 } 948 949 #[macro_export] 950 #[doc(hidden)] 951 macro_rules! joinable_inner { 952 ($left_table:path => $right_table:path : ($foreign_key:path = $parent_table:path)) => { 953 joinable_inner!( 954 left_table_ty = $left_table, 955 right_table_ty = $right_table, 956 right_table_expr = $right_table, 957 foreign_key = $foreign_key, 958 primary_key_ty = <$parent_table as $crate::query_source::Table>::PrimaryKey, 959 primary_key_expr = 960 <$parent_table as $crate::query_source::Table>::primary_key(&$parent_table), 961 ); 962 }; 963 964 ( 965 left_table_ty = $left_table_ty:ty, 966 right_table_ty = $right_table_ty:ty, 967 right_table_expr = $right_table_expr:expr, 968 foreign_key = $foreign_key:path, 969 primary_key_ty = $primary_key_ty:ty, 970 primary_key_expr = $primary_key_expr:expr, 971 ) => { 972 impl $crate::JoinTo<$right_table_ty> for $left_table_ty { 973 type FromClause = $right_table_ty; 974 type OnClause = $crate::dsl::Eq< 975 $crate::expression::nullable::Nullable<$foreign_key>, 976 $crate::expression::nullable::Nullable<$primary_key_ty>, 977 >; 978 979 fn join_target(rhs: $right_table_ty) -> (Self::FromClause, Self::OnClause) { 980 use $crate::{ExpressionMethods, NullableExpressionMethods}; 981 982 ( 983 rhs, 984 $foreign_key.nullable().eq($primary_key_expr.nullable()), 985 ) 986 } 987 } 988 }; 989 } 990 991 /// Allow two or more tables which are otherwise unrelated to be used together 992 /// in a query. 993 /// 994 /// This macro must be invoked any time two tables need to appear in the same 995 /// query either because they are being joined together, or because one appears 996 /// in a subselect. When this macro is invoked with more than 2 tables, every 997 /// combination of those tables will be allowed to appear together. 998 /// 999 /// If you are using `infer_schema!` or `diesel print-schema`, an invocation of 1000 /// this macro will be generated for you for all tables in your schema. 1001 /// 1002 /// # Example 1003 /// 1004 /// ```ignore 1005 /// // This would be required to do `users.inner_join(posts.inner_join(comments))` 1006 /// allow_tables_to_appear_in_same_query!(comments, posts, users); 1007 /// ``` 1008 /// 1009 /// When more than two tables are passed, the relevant code is generated for 1010 /// every combination of those tables. This code would be equivalent to the 1011 /// previous example. 1012 /// 1013 /// ```ignore 1014 /// allow_tables_to_appear_in_same_query!(comments, posts); 1015 /// allow_tables_to_appear_in_same_query!(comments, users); 1016 /// allow_tables_to_appear_in_same_query!(posts, users); 1017 /// ``` 1018 #[macro_export] 1019 macro_rules! allow_tables_to_appear_in_same_query { 1020 ($left_mod:ident, $($right_mod:ident),+ $(,)*) => { 1021 $( 1022 impl $crate::query_source::AppearsInFromClause<$left_mod::table> 1023 for $right_mod::table 1024 { 1025 type Count = $crate::query_source::Never; 1026 } 1027 1028 impl $crate::query_source::AppearsInFromClause<$right_mod::table> 1029 for $left_mod::table 1030 { 1031 type Count = $crate::query_source::Never; 1032 } 1033 )+ 1034 allow_tables_to_appear_in_same_query!($($right_mod,)+); 1035 }; 1036 1037 ($last_table:ident,) => {}; 1038 1039 () => {}; 1040 } 1041 1042 /// Gets the value out of an option, or returns an error. 1043 /// 1044 /// This is used by `FromSql` implementations. 1045 #[macro_export] 1046 macro_rules! not_none { 1047 ($bytes:expr) => { 1048 match $bytes { 1049 Some(bytes) => bytes, 1050 None => return Err(Box::new($crate::result::UnexpectedNullError)), 1051 } 1052 }; 1053 } 1054 1055 // The order of these modules is important (at least for those which have tests). 1056 // Utility macros which don't call any others need to come first. 1057 #[macro_use] 1058 mod internal; 1059 #[macro_use] 1060 mod query_id; 1061 #[macro_use] 1062 mod static_cond; 1063 #[macro_use] 1064 mod ops; 1065 #[macro_use] 1066 mod tuples; 1067 1068 #[cfg(test)] 1069 mod tests { 1070 use prelude::*; 1071 1072 table! { 1073 foo.bars { 1074 id -> Integer, 1075 baz -> Text, 1076 } 1077 } 1078 1079 mod my_types { 1080 #[derive(Debug, Clone, Copy)] 1081 pub struct MyCustomType; 1082 } 1083 1084 table! { 1085 use sql_types::*; 1086 use macros::tests::my_types::*; 1087 1088 table_with_custom_types { 1089 id -> Integer, 1090 my_type -> MyCustomType, 1091 } 1092 } 1093 1094 table! { 1095 use sql_types::*; 1096 use macros::tests::my_types::*; 1097 1098 /// Table documentation 1099 /// 1100 /// some in detail documentation 1101 table_with_custom_type_and_id (a) { 1102 /// Column documentation 1103 /// 1104 /// some more details 1105 a -> Integer, 1106 my_type -> MyCustomType, 1107 } 1108 } 1109 1110 #[test] 1111 #[cfg(feature = "postgres")] table_with_custom_schema()1112 fn table_with_custom_schema() { 1113 use pg::Pg; 1114 let expected_sql = r#"SELECT "foo"."bars"."baz" FROM "foo"."bars" -- binds: []"#; 1115 assert_eq!( 1116 expected_sql, 1117 &::debug_query::<Pg, _>(&bars::table.select(bars::baz)).to_string() 1118 ); 1119 } 1120 1121 table! { 1122 use sql_types; 1123 use sql_types::*; 1124 1125 table_with_arbitrarily_complex_types { 1126 id -> sql_types::Integer, 1127 qualified_nullable -> sql_types::Nullable<sql_types::Integer>, 1128 deeply_nested_type -> Option<Nullable<Integer>>, 1129 // This actually should work, but there appears to be a rustc bug 1130 // on the `AsExpression` bound for `EqAll` when the ty param is a projection 1131 // projected_type -> <Nullable<Integer> as sql_types::IntoNullable>::Nullable, 1132 random_tuple -> (Integer, Integer), 1133 } 1134 } 1135 1136 table!( 1137 foo { 1138 /// Column doc 1139 id -> Integer, 1140 1141 #[sql_name = "type"] 1142 /// Also important to document this column 1143 mytype -> Integer, 1144 1145 /// And this one 1146 #[sql_name = "bleh"] 1147 hey -> Integer, 1148 } 1149 ); 1150 1151 #[test] 1152 #[cfg(feature = "postgres")] table_with_column_renaming_postgres()1153 fn table_with_column_renaming_postgres() { 1154 use pg::Pg; 1155 let expected_sql = 1156 r#"SELECT "foo"."id", "foo"."type", "foo"."bleh" FROM "foo" WHERE "foo"."type" = $1 -- binds: [1]"#; 1157 assert_eq!( 1158 expected_sql, 1159 ::debug_query::<Pg, _>(&foo::table.filter(foo::mytype.eq(1))).to_string() 1160 ); 1161 } 1162 1163 #[test] 1164 #[cfg(feature = "mysql")] table_with_column_renaming_mysql()1165 fn table_with_column_renaming_mysql() { 1166 use mysql::Mysql; 1167 let expected_sql = 1168 r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE `foo`.`type` = ? -- binds: [1]"#; 1169 assert_eq!( 1170 expected_sql, 1171 ::debug_query::<Mysql, _>(&foo::table.filter(foo::mytype.eq(1))).to_string() 1172 ); 1173 } 1174 1175 #[test] 1176 #[cfg(feature = "sqlite")] table_with_column_renaming_sqlite()1177 fn table_with_column_renaming_sqlite() { 1178 use sqlite::Sqlite; 1179 let expected_sql = 1180 r#"SELECT `foo`.`id`, `foo`.`type`, `foo`.`bleh` FROM `foo` WHERE `foo`.`type` = ? -- binds: [1]"#; 1181 assert_eq!( 1182 expected_sql, 1183 ::debug_query::<Sqlite, _>(&foo::table.filter(foo::mytype.eq(1))).to_string() 1184 ); 1185 } 1186 1187 table!( 1188 use sql_types::*; 1189 1190 /// Some documentation 1191 #[sql_name="mod"] 1192 /// Some more documentation 1193 bar { 1194 id -> Integer, 1195 } 1196 ); 1197 1198 #[test] 1199 #[cfg(feature = "postgres")] table_renaming_postgres()1200 fn table_renaming_postgres() { 1201 use pg::Pg; 1202 let expected_sql = r#"SELECT "mod"."id" FROM "mod" -- binds: []"#; 1203 assert_eq!( 1204 expected_sql, 1205 ::debug_query::<Pg, _>(&bar::table.select(bar::id)).to_string() 1206 ); 1207 } 1208 1209 #[test] 1210 #[cfg(feature = "mysql")] table_renaming_mysql()1211 fn table_renaming_mysql() { 1212 use mysql::Mysql; 1213 let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#; 1214 assert_eq!( 1215 expected_sql, 1216 ::debug_query::<Mysql, _>(&bar::table.select(bar::id)).to_string() 1217 ); 1218 } 1219 1220 #[test] 1221 #[cfg(feature = "sqlite")] table_renaming_sqlite()1222 fn table_renaming_sqlite() { 1223 use sqlite::Sqlite; 1224 let expected_sql = r#"SELECT `mod`.`id` FROM `mod` -- binds: []"#; 1225 assert_eq!( 1226 expected_sql, 1227 ::debug_query::<Sqlite, _>(&bar::table.select(bar::id)).to_string() 1228 ); 1229 } 1230 } 1231