//! Traits that construct SELECT statements
//!
//! Traits in this module have methods that generally map to the keyword for the corresponding clause in SQL,
//! unless it conflicts with a Rust keyword (such as `WHERE`/`where`).
//!
//! Methods for constructing queries lives on the [`QueryDsl`] trait.
//! Methods for executing queries live on [`RunQueryDsl`].
//!
//! See also [`expression_methods`][expression_methods] and [`dsl`][dsl].
//!
//! [expression_methods]: super::expression_methods
//! [dsl]: super::dsl

use crate::backend::Backend;
use crate::connection::Connection;
use crate::expression::count::CountStar;
use crate::expression::Expression;
use crate::helper_types::*;
use crate::query_builder::locking_clause as lock;
use crate::query_source::{joins, Table};
use crate::result::QueryResult;

mod belonging_to_dsl;
#[doc(hidden)]
pub mod boxed_dsl;
mod combine_dsl;
mod distinct_dsl;
#[doc(hidden)]
pub mod filter_dsl;
mod group_by_dsl;
mod having_dsl;
mod join_dsl;
#[doc(hidden)]
pub mod limit_dsl;
#[doc(hidden)]
pub mod load_dsl;
mod locking_dsl;
mod nullable_select_dsl;
mod offset_dsl;
pub(crate) mod order_dsl;
#[doc(hidden)]
pub mod positional_order_dsl;
mod save_changes_dsl;
#[doc(hidden)]
pub mod select_dsl;
mod single_value_dsl;

pub use self::belonging_to_dsl::BelongingToDsl;
pub use self::combine_dsl::CombineDsl;
pub use self::join_dsl::{InternalJoinDsl, JoinOnDsl, JoinWithImplicitOnClause};
#[cfg(feature = "i-implement-a-third-party-backend-and-opt-into-breaking-changes")]
pub use self::load_dsl::CompatibleType;
#[doc(hidden)]
pub use self::load_dsl::LoadQuery;
pub use self::save_changes_dsl::{SaveChangesDsl, UpdateAndFetchResults};

/// The traits used by `QueryDsl`.
///
/// Each trait in this module represents exactly one method from `QueryDsl`.
/// Apps should general rely on `QueryDsl` directly, rather than these traits.
/// However, generic code may need to include a where clause that references
/// these traits.
pub mod methods {
    pub use super::boxed_dsl::BoxedDsl;
    pub use super::distinct_dsl::*;
    #[doc(inline)]
    pub use super::filter_dsl::*;
    pub use super::group_by_dsl::GroupByDsl;
    pub use super::having_dsl::HavingDsl;
    pub use super::limit_dsl::LimitDsl;
    pub use super::load_dsl::{ExecuteDsl, LoadQuery};
    pub use super::locking_dsl::{LockingDsl, ModifyLockDsl};
    pub use super::nullable_select_dsl::SelectNullableDsl;
    pub use super::offset_dsl::OffsetDsl;
    pub use super::order_dsl::{OrderDsl, ThenOrderDsl};
    pub use super::select_dsl::SelectDsl;
    pub use super::single_value_dsl::SingleValueDsl;

    #[cfg(all(feature = "with-deprecated", not(feature = "without-deprecated")))]
    #[doc(hidden)]
    #[allow(deprecated)]
    #[deprecated(note = "Use `LoadQuery::RowIter` directly")]
    pub use super::load_dsl::LoadRet;
}

/// Methods used to construct select statements.
pub trait QueryDsl: Sized {
    /// Adds the `DISTINCT` keyword to a query.
    ///
    /// This method will override any previous distinct clause that was present.
    /// For example, on PostgreSQL, `foo.distinct_on(bar).distinct()` will
    /// create the same query as `foo.distinct()`.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     diesel::sql_query("DELETE FROM users").execute(connection).unwrap();
    /// diesel::insert_into(users)
    ///     .values(&vec![name.eq("Sean"); 3])
    ///     .execute(connection)?;
    /// let names = users.select(name).load::<String>(connection)?;
    /// let distinct_names = users.select(name).distinct().load::<String>(connection)?;
    ///
    /// assert_eq!(vec!["Sean"; 3], names);
    /// assert_eq!(vec!["Sean"; 1], distinct_names);
    /// #     Ok(())
    /// # }
    /// ```
    fn distinct(self) -> Distinct<Self>
    where
        Self: methods::DistinctDsl,
    {
        methods::DistinctDsl::distinct(self)
    }

    /// Adds the `DISTINCT ON` clause to a query.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::animals;
    /// #
    /// # #[derive(Queryable, Debug, PartialEq)]
    /// # struct Animal {
    /// #     species: String,
    /// #     name: Option<String>,
    /// #     legs: i32,
    /// # }
    /// #
    /// # impl Animal {
    /// #     fn new<S: Into<String>>(species: S, name: Option<&str>, legs: i32) -> Self {
    /// #         Animal {
    /// #             species: species.into(),
    /// #             name: name.map(Into::into),
    /// #             legs
    /// #         }
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     use self::animals::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     diesel::sql_query("DELETE FROM animals").execute(connection).unwrap();
    /// diesel::insert_into(animals)
    ///     .values(&vec![
    ///         (species.eq("dog"), name.eq(Some("Jack")), legs.eq(4)),
    ///         (species.eq("dog"), name.eq(None), legs.eq(4)),
    ///         (species.eq("spider"), name.eq(None), legs.eq(8)),
    ///     ])
    ///     .execute(connection)
    ///     .unwrap();
    /// let all_animals = animals.select((species, name, legs)).load(connection);
    /// let distinct_animals = animals
    ///     .select((species, name, legs))
    ///     .order_by((species, legs))
    ///     .distinct_on(species)
    ///     .load(connection);
    ///
    /// assert_eq!(Ok(vec![Animal::new("dog", Some("Jack"), 4),
    ///                    Animal::new("dog", None, 4),
    ///                    Animal::new("spider", None, 8)]), all_animals);
    /// assert_eq!(Ok(vec![Animal::new("dog", Some("Jack"), 4),
    ///                    Animal::new("spider", None, 8)]), distinct_animals);
    /// # }
    /// ```
    #[cfg(feature = "postgres_backend")]
    fn distinct_on<Expr>(self, expr: Expr) -> DistinctOn<Self, Expr>
    where
        Self: methods::DistinctOnDsl<Expr>,
    {
        methods::DistinctOnDsl::distinct_on(self, expr)
    }

    // FIXME: Needs usage example and doc rewrite
    /// Adds a `SELECT` clause to the query.
    ///
    /// If there was already a select clause present, it will be overridden.
    /// For example, `foo.select(bar).select(baz)` will produce the same
    /// query as `foo.select(baz)`.
    ///
    /// By default, the select clause will be roughly equivalent to `SELECT *`
    /// (however, Diesel will list all columns to ensure that they are in the
    /// order we expect).
    ///
    /// `select` has slightly stricter bounds on its arguments than other
    /// methods. In particular, when used with a left outer join, `.nullable`
    /// must be called on columns that come from the right side of a join. It
    /// can be called on the column itself, or on an expression containing that
    /// column. `title.nullable()`, `lower(title).nullable()`, and `(id,
    /// title).nullable()` would all be valid.
    ///
    /// In order to use this method with columns from different tables
    /// a method like [`.inner_join`] or [`.left_join`] needs to be called before
    /// calling [`.select`] (See examples below).
    /// This is because you can only access columns from tables
    /// that appear in your query before that function call.
    ///
    /// [`.inner_join`]: QueryDsl::inner_join()
    /// [`.left_join`]: QueryDsl::left_join()
    /// [`.select`]: QueryDsl::select()
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::users;
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use self::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// // By default, all columns will be selected
    /// let all_users = users.load::<(i32, String)>(connection)?;
    /// assert_eq!(vec![(1, String::from("Sean")), (2, String::from("Tess"))], all_users);
    ///
    /// let all_names = users.select(name).load::<String>(connection)?;
    /// assert_eq!(vec!["Sean", "Tess"], all_names);
    /// #     Ok(())
    /// # }
    /// ```
    ///
    /// ### When used with a left join
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::{users, posts};
    /// #
    /// # #[derive(Queryable, PartialEq, Eq, Debug)]
    /// # struct User {
    /// #     id: i32,
    /// #     name: String,
    /// # }
    /// #
    /// # impl User {
    /// #     fn new(id: i32, name: &str) -> Self {
    /// #         User {
    /// #             id,
    /// #             name: name.into(),
    /// #         }
    /// #     }
    /// # }
    /// #
    /// # #[derive(Queryable, PartialEq, Eq, Debug)]
    /// # struct Post {
    /// #     id: i32,
    /// #     user_id: i32,
    /// #     title: String,
    /// # }
    /// #
    /// # impl Post {
    /// #     fn new(id: i32, user_id: i32, title: &str) -> Self {
    /// #         Post {
    /// #             id,
    /// #             user_id,
    /// #             title: title.into(),
    /// #         }
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     let connection = &mut establish_connection();
    /// #     diesel::sql_query("DELETE FROM posts").execute(connection)?;
    /// #     diesel::insert_into(posts::table)
    /// #         .values((posts::user_id.eq(1), posts::title.eq("Sean's Post")))
    /// #         .execute(connection)?;
    /// #     let post_id = posts::table.select(posts::id)
    /// #         .first::<i32>(connection)?;
    /// let join = users::table.left_join(posts::table);
    ///
    /// // By default, all columns from both tables are selected.
    /// // If no explicit select clause is used this means that the result
    /// // type of this query must contain all fields from the original schema in order.
    /// let all_data = join.load::<(User, Option<Post>)>(connection)?;
    /// let expected_data = vec![
    ///     (User::new(1, "Sean"), Some(Post::new(post_id, 1, "Sean's Post"))),
    ///     (User::new(2, "Tess"), None),
    /// ];
    /// assert_eq!(expected_data, all_data);
    ///
    /// // Since `posts` is on the right side of a left join, `.nullable` is
    /// // needed.
    /// let names_and_titles = join.select((users::name, posts::title.nullable()))
    ///     .load::<(String, Option<String>)>(connection)?;
    /// let expected_data = vec![
    ///     (String::from("Sean"), Some(String::from("Sean's Post"))),
    ///     (String::from("Tess"), None),
    /// ];
    /// assert_eq!(expected_data, names_and_titles);
    /// #     Ok(())
    /// # }
    /// ```
    fn select<Selection>(self, selection: Selection) -> Select<Self, Selection>
    where
        Selection: Expression,
        Self: methods::SelectDsl<Selection>,
    {
        methods::SelectDsl::select(self, selection)
    }

    /// Get the count of a query. This is equivalent to `.select(count_star())`
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let count = users.count().get_result(connection);
    /// assert_eq!(Ok(2), count);
    /// # }
    /// ```
    fn count(self) -> Select<Self, CountStar>
    where
        Self: methods::SelectDsl<CountStar>,
    {
        use crate::dsl::count_star;

        QueryDsl::select(self, count_star())
    }

    /// Join two tables using a SQL `INNER JOIN`.
    ///
    /// If you have invoked [`joinable!`] for the two tables, you can pass that
    /// table directly.  Otherwise you will need to use [`.on`] to specify the `ON`
    /// clause.
    ///
    /// [`joinable!`]: crate::joinable!
    /// [`.on`]: JoinOnDsl::on()
    ///
    /// You can join to as many tables as you'd like in a query, with the
    /// restriction that no table can appear in the query more than once. For
    /// tables that appear more than once in a single query the usage of [`alias!`](crate::alias!)
    /// is required.
    ///
    /// You will also need to call [`allow_tables_to_appear_in_same_query!`].
    /// If you are using `diesel print-schema`, this will
    /// have been generated for you.
    /// See the documentation for [`allow_tables_to_appear_in_same_query!`] for
    /// details.
    ///
    /// Diesel expects multi-table joins to be semantically grouped based on the
    /// relationships. For example, `users.inner_join(posts.inner_join(comments))`
    /// is not the same as `users.inner_join(posts).inner_join(comments)`. The first
    /// would deserialize into `(User, (Post, Comment))` and generate the following
    /// SQL:
    ///
    /// ```sql
    /// SELECT * FROM users
    ///     INNER JOIN (
    ///         posts
    ///         INNER JOIN comments ON comments.post_id = posts.id
    ///     ) ON posts.user_id = users.id
    ///
    /// ```
    ///
    /// While the second query would deserialize into `(User, Post, Comment)` and
    /// generate the following SQL:
    ///
    /// ```sql
    /// SELECT * FROM users
    ///     INNER JOIN posts ON posts.user_id = users.id
    ///     INNER JOIN comments ON comments.user_id = users.id
    /// ```
    ///
    /// The exact generated SQL may change in future diesel version as long as the
    /// generated query continues to produce same results. The currently generated
    /// SQL is referred as ["explicit join"](https://www.postgresql.org/docs/current/explicit-joins.html)
    /// by the PostgreSQL documentation and may have implications on the chosen query plan
    /// for large numbers of joins in the same query. Checkout the documentation of the
    /// [`join_collapse_limit` parameter](https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-JOIN-COLLAPSE-LIMIT)
    /// to control this behaviour.
    ///
    /// [associations]: crate::associations
    /// [`allow_tables_to_appear_in_same_query!`]: crate::allow_tables_to_appear_in_same_query!
    ///
    /// Note that in order to use this method with [`.select`], you will need to use it before calling
    /// [`.select`] (See examples below). This is because you can only access columns from tables
    /// that appear in your query before the call to [`.select`].
    ///
    /// [`.select`]: QueryDsl::select()
    ///
    /// # Examples
    ///
    /// ### With implicit `ON` clause
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::{users, posts};
    /// # /*
    /// joinable!(posts -> users (user_id));
    /// allow_tables_to_appear_in_same_query!(users, posts);
    /// # */
    ///
    /// # fn main() {
    /// #     use self::users::dsl::{users, name};
    /// #     use self::posts::dsl::{posts, user_id, title};
    /// #     let connection = &mut establish_connection();
    /// let data = users.inner_join(posts)
    ///     .select((name, title))
    ///     .load(connection);
    ///
    /// let expected_data = vec![
    ///     (String::from("Sean"), String::from("My first post")),
    ///     (String::from("Sean"), String::from("About Rust")),
    ///     (String::from("Tess"), String::from("My first post too")),
    /// ];
    /// assert_eq!(Ok(expected_data), data);
    /// # }
    /// ```
    ///
    /// ### With explicit `ON` clause
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::{users, posts};
    /// #
    /// # /*
    /// allow_tables_to_appear_in_same_query!(users, posts);
    /// # */
    ///
    /// # fn main() {
    /// #     use self::users::dsl::{users, name};
    /// #     use self::posts::dsl::{posts, user_id, title};
    /// #     let connection = &mut establish_connection();
    /// diesel::insert_into(posts)
    ///     .values(&vec![
    ///         (user_id.eq(1), title.eq("Sean's post")),
    ///         (user_id.eq(2), title.eq("Sean is a jerk")),
    ///     ])
    ///     .execute(connection)
    ///     .unwrap();
    ///
    /// let data = users
    ///     .inner_join(posts.on(title.like(name.concat("%"))))
    ///     .select((name, title))
    ///     .load(connection);
    /// let expected_data = vec![
    ///     (String::from("Sean"), String::from("Sean's post")),
    ///     (String::from("Sean"), String::from("Sean is a jerk")),
    /// ];
    /// assert_eq!(Ok(expected_data), data);
    /// # }
    /// ```
    ///
    /// ### With explicit `ON` clause (struct)
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::{users, posts};
    /// #
    /// # /*
    /// allow_tables_to_appear_in_same_query!(users, posts);
    /// # */
    ///
    /// # fn main() {
    /// #     use self::users::dsl::{users, name};
    /// #     use self::posts::dsl::{posts, user_id, title};
    /// #     let connection = &mut establish_connection();
    /// #[derive(Debug, PartialEq, Queryable)]
    /// struct User {
    ///     id: i32,
    ///     name: String,
    /// }
    ///
    /// #[derive(Debug, PartialEq, Queryable)]
    /// struct Post {
    ///     id: i32,
    ///     user_id: i32,
    ///     title: String,
    /// }
    ///
    /// diesel::insert_into(posts)
    ///     .values(&vec![
    ///         (user_id.eq(1), title.eq("Sean's post")),
    ///         (user_id.eq(2), title.eq("Sean is a jerk")),
    ///     ])
    ///     .execute(connection)
    ///     .unwrap();
    ///
    /// // By default, all columns from both tables are selected.
    /// // If no explicit select clause is used this means that the
    /// // result type of this query must contain all fields from the
    /// // original schema in order.
    /// let data = users
    ///     .inner_join(posts.on(title.like(name.concat("%"))))
    ///     .load::<(User, Post)>(connection); // type could be elided
    /// let expected_data = vec![
    ///     (
    ///         User { id: 1, name: String::from("Sean") },
    ///         Post { id: 4, user_id: 1, title: String::from("Sean's post") },
    ///     ),
    ///     (
    ///         User { id: 1, name: String::from("Sean") },
    ///         Post { id: 5, user_id: 2, title: String::from("Sean is a jerk") },
    ///     ),
    /// ];
    /// assert_eq!(Ok(expected_data), data);
    /// # }
    /// ```
    fn inner_join<Rhs>(self, rhs: Rhs) -> InnerJoin<Self, Rhs>
    where
        Self: JoinWithImplicitOnClause<Rhs, joins::Inner>,
    {
        self.join_with_implicit_on_clause(rhs, joins::Inner)
    }

    /// Join two tables using a SQL `LEFT OUTER JOIN`.
    ///
    /// Behaves similarly to [`inner_join`], but will produce a left join
    /// instead. See [`inner_join`] for usage examples.
    ///
    /// [`inner_join`]: QueryDsl::inner_join()
    ///
    /// Columns in the right hand table will become `Nullable` which means
    /// you must call `nullable()` on the corresponding fields in the select
    /// clause:
    ///
    /// ### Selecting after a left join
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::{users, posts};
    /// #
    /// # #[derive(Queryable, PartialEq, Eq, Debug)]
    /// # struct User {
    /// #     id: i32,
    /// #     name: String,
    /// # }
    /// #
    /// # impl User {
    /// #     fn new(id: i32, name: &str) -> Self {
    /// #         User {
    /// #             id,
    /// #             name: name.into(),
    /// #         }
    /// #     }
    /// # }
    /// #
    /// # #[derive(Queryable, PartialEq, Eq, Debug)]
    /// # struct Post {
    /// #     id: i32,
    /// #     user_id: i32,
    /// #     title: String,
    /// # }
    /// #
    /// # impl Post {
    /// #     fn new(id: i32, user_id: i32, title: &str) -> Self {
    /// #         Post {
    /// #             id,
    /// #             user_id,
    /// #             title: title.into(),
    /// #         }
    /// #     }
    /// # }
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     let connection = &mut establish_connection();
    /// #     diesel::sql_query("DELETE FROM posts").execute(connection)?;
    /// #     diesel::insert_into(posts::table)
    /// #         .values((posts::user_id.eq(1), posts::title.eq("Sean's Post")))
    /// #         .execute(connection)?;
    /// #     let post_id = posts::table.select(posts::id)
    /// #         .first::<i32>(connection)?;
    /// let join = users::table.left_join(posts::table);
    ///
    /// // Since `posts` is on the right side of a left join, `.nullable` is
    /// // needed.
    /// let names_and_titles = join.select((users::name, posts::title.nullable()))
    ///     .load::<(String, Option<String>)>(connection)?;
    /// let expected_data = vec![
    ///     (String::from("Sean"), Some(String::from("Sean's Post"))),
    ///     (String::from("Tess"), None),
    /// ];
    /// assert_eq!(expected_data, names_and_titles);
    /// #     Ok(())
    /// # }
    /// ```
    fn left_outer_join<Rhs>(self, rhs: Rhs) -> LeftJoin<Self, Rhs>
    where
        Self: JoinWithImplicitOnClause<Rhs, joins::LeftOuter>,
    {
        self.join_with_implicit_on_clause(rhs, joins::LeftOuter)
    }

    /// Alias for [`left_outer_join`].
    ///
    /// [`left_outer_join`]: QueryDsl::left_outer_join()
    fn left_join<Rhs>(self, rhs: Rhs) -> LeftJoin<Self, Rhs>
    where
        Self: JoinWithImplicitOnClause<Rhs, joins::LeftOuter>,
    {
        self.left_outer_join(rhs)
    }

    /// Adds to the `WHERE` clause of a query.
    ///
    /// If there is already a `WHERE` clause, the result will be `old AND new`.
    ///
    /// Note that in order to use this method with columns from different tables, you need to call
    ///  [`.inner_join`] or [`.left_join`] beforehand.
    /// This is because you can only access columns from tables
    /// that appear in your query before the call to [`.filter`].
    ///
    /// [`.inner_join`]: QueryDsl::inner_join()
    /// [`.left_join`]: QueryDsl::left_join()
    /// [`.filter`]: QueryDsl::filter()
    ///
    /// # Example:
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let seans_id = users.filter(name.eq("Sean")).select(id)
    ///     .first(connection);
    /// assert_eq!(Ok(1), seans_id);
    /// let tess_id = users.filter(name.eq("Tess")).select(id)
    ///     .first(connection);
    /// assert_eq!(Ok(2), tess_id);
    /// # }
    /// ```
    #[doc(alias = "where")]
    fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
    where
        Self: methods::FilterDsl<Predicate>,
    {
        methods::FilterDsl::filter(self, predicate)
    }

    /// Adds to the `WHERE` clause of a query using `OR`
    ///
    /// If there is already a `WHERE` clause, the result will be `(old OR new)`.
    /// Calling `foo.filter(bar).or_filter(baz)`
    /// is identical to `foo.filter(bar.or(baz))`.
    /// However, the second form is much harder to do dynamically.
    ///
    /// # Example:
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use schema::animals::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     diesel::delete(animals).execute(connection)?;
    /// diesel::insert_into(animals)
    ///     .values(&vec![
    ///         (species.eq("cat"), legs.eq(4), name.eq("Sinatra")),
    ///         (species.eq("dog"), legs.eq(3), name.eq("Fido")),
    ///         (species.eq("spider"), legs.eq(8), name.eq("Charlotte")),
    ///     ])
    ///     .execute(connection)?;
    ///
    /// let good_animals = animals
    ///     .filter(name.eq("Fido"))
    ///     .or_filter(legs.eq(4))
    ///     .select(name)
    ///     .get_results::<Option<String>>(connection)?;
    /// let expected = vec![
    ///     Some(String::from("Sinatra")),
    ///     Some(String::from("Fido")),
    /// ];
    /// assert_eq!(expected, good_animals);
    /// #     Ok(())
    /// # }
    /// ```
    #[doc(alias = "where")]
    fn or_filter<Predicate>(self, predicate: Predicate) -> OrFilter<Self, Predicate>
    where
        Self: methods::OrFilterDsl<Predicate>,
    {
        methods::OrFilterDsl::or_filter(self, predicate)
    }

    /// Attempts to find a single record from the given table by primary key.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     use schema::users::dsl::*;
    /// #     use diesel::result::Error::NotFound;
    /// #     let connection = &mut establish_connection();
    /// let sean = (1, "Sean".to_string());
    /// let tess = (2, "Tess".to_string());
    /// assert_eq!(Ok(sean), users.find(1).first(connection));
    /// assert_eq!(Ok(tess), users.find(2).first(connection));
    /// assert_eq!(Err::<(i32, String), _>(NotFound), users.find(3).first(connection));
    /// # }
    /// ```
    fn find<PK>(self, id: PK) -> Find<Self, PK>
    where
        Self: methods::FindDsl<PK>,
    {
        methods::FindDsl::find(self, id)
    }

    /// Sets the order clause of a query.
    ///
    /// If there was already an order clause, it will be overridden. See
    /// also:
    /// [`.desc()`](crate::expression_methods::ExpressionMethods::desc())
    /// and
    /// [`.asc()`](crate::expression_methods::ExpressionMethods::asc())
    ///
    /// Ordering by multiple columns can be achieved by passing a tuple of those
    /// columns.
    /// To construct an order clause of an unknown number of columns,
    /// see [`QueryDsl::then_order_by`](QueryDsl::then_order_by())
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     diesel::sql_query("DELETE FROM users").execute(connection)?;
    /// diesel::insert_into(users)
    ///     .values(&vec![
    ///         name.eq("Saul"),
    ///         name.eq("Steve"),
    ///         name.eq("Stan"),
    ///     ])
    ///     .execute(connection)?;
    ///
    /// let ordered_names = users.select(name)
    ///     .order(name.desc())
    ///     .load::<String>(connection)?;
    /// assert_eq!(vec!["Steve", "Stan", "Saul"], ordered_names);
    ///
    /// diesel::insert_into(users).values(name.eq("Stan")).execute(connection)?;
    ///
    /// let data = users.select((name, id))
    ///     .order((name.asc(), id.desc()))
    ///     .load(connection)?;
    /// let expected_data = vec![
    ///     (String::from("Saul"), 3),
    ///     (String::from("Stan"), 6),
    ///     (String::from("Stan"), 5),
    ///     (String::from("Steve"), 4),
    /// ];
    /// assert_eq!(expected_data, data);
    /// #    Ok(())
    /// # }
    /// ```
    fn order<Expr>(self, expr: Expr) -> Order<Self, Expr>
    where
        Expr: Expression,
        Self: methods::OrderDsl<Expr>,
    {
        methods::OrderDsl::order(self, expr)
    }

    /// Alias for `order`
    fn order_by<Expr>(self, expr: Expr) -> Order<Self, Expr>
    where
        Expr: Expression,
        Self: methods::OrderDsl<Expr>,
    {
        QueryDsl::order(self, expr)
    }

    /// Appends to the `ORDER BY` clause of this SQL query.
    ///
    /// Unlike `.order`, this method will append rather than replace.
    /// In other words,
    /// `.order_by(foo).order_by(bar)` is equivalent to `.order_by(bar)`.
    /// In contrast,
    /// `.order_by(foo).then_order_by(bar)` is equivalent to `.order((foo, bar))`.
    /// This method is only present on boxed queries.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     diesel::sql_query("DELETE FROM users").execute(connection)?;
    /// diesel::insert_into(users)
    ///     .values(&vec![
    ///         name.eq("Saul"),
    ///         name.eq("Steve"),
    ///         name.eq("Stan"),
    ///         name.eq("Stan"),
    ///     ])
    ///     .execute(connection)?;
    ///
    /// let data = users.select((name, id))
    ///     .order_by(name.asc())
    ///     .then_order_by(id.desc())
    ///     .load(connection)?;
    /// let expected_data = vec![
    ///     (String::from("Saul"), 3),
    ///     (String::from("Stan"), 6),
    ///     (String::from("Stan"), 5),
    ///     (String::from("Steve"), 4),
    /// ];
    /// assert_eq!(expected_data, data);
    /// #    Ok(())
    /// # }
    /// ```
    fn then_order_by<Order>(self, order: Order) -> ThenOrderBy<Self, Order>
    where
        Self: methods::ThenOrderDsl<Order>,
    {
        methods::ThenOrderDsl::then_order_by(self, order)
    }

    /// Sets the limit clause of the query.
    ///
    /// If there was already a limit clause, it will be overridden.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::users;
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use self::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     diesel::delete(users).execute(connection)?;
    /// #     diesel::insert_into(users)
    /// #        .values(&vec![
    /// #            name.eq("Sean"),
    /// #            name.eq("Bastien"),
    /// #            name.eq("Pascal"),
    /// #        ])
    /// #        .execute(connection)?;
    /// #
    /// // Using a limit
    /// let limited = users.select(name)
    ///     .order(id)
    ///     .limit(1)
    ///     .load::<String>(connection)?;
    ///
    /// // Without a limit
    /// let no_limit = users.select(name)
    ///     .order(id)
    ///     .load::<String>(connection)?;
    ///
    /// assert_eq!(vec!["Sean"], limited);
    /// assert_eq!(vec!["Sean", "Bastien", "Pascal"], no_limit);
    /// #    Ok(())
    /// # }
    /// ```
    fn limit(self, limit: i64) -> Limit<Self>
    where
        Self: methods::LimitDsl,
    {
        methods::LimitDsl::limit(self, limit)
    }

    /// Sets the offset clause of the query.
    ///
    /// If there was already a offset clause, it will be overridden.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::users;
    /// #
    /// # fn main() {
    /// #     run_test().unwrap();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use self::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// #     diesel::delete(users).execute(connection)?;
    /// #     diesel::insert_into(users)
    /// #        .values(&vec![
    /// #            name.eq("Sean"),
    /// #            name.eq("Bastien"),
    /// #            name.eq("Pascal"),
    /// #        ])
    /// #        .execute(connection)?;
    /// #
    /// // Using an offset
    /// let offset = users.select(name)
    ///     .order(id)
    ///     .limit(2)
    ///     .offset(1)
    ///     .load::<String>(connection)?;
    ///
    /// // No Offset
    /// let no_offset = users.select(name)
    ///     .order(id)
    ///     .limit(2)
    ///     .load::<String>(connection)?;
    ///
    /// assert_eq!(vec!["Bastien", "Pascal"], offset);
    /// assert_eq!(vec!["Sean", "Bastien"], no_offset);
    /// #     Ok(())
    /// # }
    /// ```
    fn offset(self, offset: i64) -> Offset<Self>
    where
        Self: methods::OffsetDsl,
    {
        methods::OffsetDsl::offset(self, offset)
    }

    /// Sets the `group by` clause of a query.
    ///
    /// **Note:** Queries having a `group by` clause require a custom select clause.
    /// Use [`QueryDsl::select()`] to specify one.
    ///
    /// If there was already a group by clause, it will be overridden.
    /// Grouping by multiple columns can be achieved by passing a tuple of those
    /// columns.
    ///
    /// Diesel follows postgresql's group by semantic, this means any column
    /// appearing in a group by clause is considered to be aggregated. If a
    /// primary key is part of the group by clause every column from the
    /// corresponding table is considered to be aggregated. Select clauses
    /// cannot mix aggregated and non aggregated expressions.
    ///
    /// For group by clauses containing columns from more than one table it
    /// is required to call [`allow_columns_to_appear_in_same_group_by_clause!`]
    ///
    /// [`allow_columns_to_appear_in_same_group_by_clause!`]: crate::allow_columns_to_appear_in_same_group_by_clause!
    ///
    /// # Examples
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use crate::schema::{users, posts};
    /// #     use diesel::dsl::count;
    /// #     let connection = &mut establish_connection();
    /// let data = users::table.inner_join(posts::table)
    ///     .group_by(users::id)
    ///     .select((users::name, count(posts::id)))
    /// #   .order_by(users::id.asc())
    ///     .load::<(String, i64)>(connection)?;
    ///
    /// assert_eq!(vec![(String::from("Sean"), 2), (String::from("Tess"), 1)], data);
    /// # Ok(())
    /// # }
    /// ```
    fn group_by<GB>(self, group_by: GB) -> GroupBy<Self, GB>
    where
        GB: Expression,
        Self: methods::GroupByDsl<GB>,
    {
        methods::GroupByDsl::group_by(self, group_by)
    }

    /// Adds to the `HAVING` clause of a query.
    ///
    /// # Examples
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use crate::schema::{users, posts};
    /// #     use diesel::dsl::count;
    /// #     let connection = &mut establish_connection();
    /// let data = users::table.inner_join(posts::table)
    ///     .group_by(users::id)
    ///     .having(count(posts::id).gt(1))
    ///     .select((users::name, count(posts::id)))
    ///     .load::<(String, i64)>(connection)?;
    ///
    /// assert_eq!(vec![(String::from("Sean"), 2)], data);
    /// # Ok(())
    /// # }
    /// ```
    fn having<Predicate>(self, predicate: Predicate) -> Having<Self, Predicate>
    where
        Self: methods::HavingDsl<Predicate>,
    {
        methods::HavingDsl::having(self, predicate)
    }

    /// Adds `FOR UPDATE` to the end of the select statement.
    ///
    /// This method is only available for MySQL and PostgreSQL. SQLite does not
    /// provide any form of row locking.
    ///
    /// Additionally, `.for_update` cannot be used on queries with a distinct
    /// clause, group by clause, having clause, or any unions. Queries with
    /// a `FOR UPDATE` clause cannot be boxed.
    ///
    /// # Example
    ///
    /// ```
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # #[cfg(any(feature = "mysql", feature = "postgres"))]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use crate::schema::users;
    /// #     let connection = &mut establish_connection();
    /// // Executes `SELECT * FROM users FOR UPDATE`
    /// let users_for_update = users::table.for_update().load(connection)?;
    /// # let u: Vec<(i32, String)> = users_for_update;
    /// # Ok(())
    /// # }
    /// # #[cfg(feature = "sqlite")]
    /// # fn run_test() -> QueryResult<()> { Ok(()) }
    /// ```
    fn for_update(self) -> ForUpdate<Self>
    where
        Self: methods::LockingDsl<lock::ForUpdate>,
    {
        methods::LockingDsl::with_lock(self, lock::ForUpdate)
    }

    /// Adds `FOR NO KEY UPDATE` to the end of the select statement.
    ///
    /// This method is only available for PostgreSQL. SQLite does not
    /// provide any form of row locking, and MySQL does not support anything
    /// finer than row-level locking.
    ///
    /// Additionally, `.for_no_key_update` cannot be used on queries with a distinct
    /// clause, group by clause, having clause, or any unions. Queries with
    /// a `FOR NO KEY UPDATE` clause cannot be boxed.
    ///
    /// # Example
    ///
    /// ```
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # #[cfg(feature = "postgres")]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use crate::schema::users;
    /// #     let connection = &mut establish_connection();
    /// // Executes `SELECT * FROM users FOR NO KEY UPDATE`
    /// let users_for_no_key_update = users::table.for_no_key_update().load(connection)?;
    /// # let u: Vec<(i32, String)> = users_for_no_key_update;
    /// # Ok(())
    /// # }
    /// # #[cfg(not(feature = "postgres"))]
    /// # fn run_test() -> QueryResult<()> { Ok(()) }
    /// ```
    fn for_no_key_update(self) -> ForNoKeyUpdate<Self>
    where
        Self: methods::LockingDsl<lock::ForNoKeyUpdate>,
    {
        methods::LockingDsl::with_lock(self, lock::ForNoKeyUpdate)
    }

    /// Adds `FOR SHARE` to the end of the select statement.
    ///
    /// This method is only available for MySQL and PostgreSQL. SQLite does not
    /// provide any form of row locking.
    ///
    /// Additionally, `.for_share` cannot be used on queries with a distinct
    /// clause, group by clause, having clause, or any unions. Queries with
    /// a `FOR SHARE` clause cannot be boxed.
    ///
    /// # Example
    ///
    /// ```
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # #[cfg(any(feature = "mysql", feature = "postgres"))]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use crate::schema::users;
    /// #     let connection = &mut establish_connection();
    /// // Executes `SELECT * FROM users FOR SHARE`
    /// let users_for_share = users::table.for_share().load(connection)?;
    /// # let u: Vec<(i32, String)> = users_for_share;
    /// # Ok(())
    /// # }
    /// # #[cfg(feature = "sqlite")]
    /// # fn run_test() -> QueryResult<()> { Ok(()) }
    /// ```
    fn for_share(self) -> ForShare<Self>
    where
        Self: methods::LockingDsl<lock::ForShare>,
    {
        methods::LockingDsl::with_lock(self, lock::ForShare)
    }

    /// Adds `FOR KEY SHARE` to the end of the select statement.
    ///
    /// This method is only available for PostgreSQL. SQLite does not
    /// provide any form of row locking, and MySQL does not support anything
    /// finer than row-level locking.
    ///
    /// Additionally, `.for_key_share` cannot be used on queries with a distinct
    /// clause, group by clause, having clause, or any unions. Queries with
    /// a `FOR KEY SHARE` clause cannot be boxed.
    ///
    /// # Example
    ///
    /// ```
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    ///
    /// # #[cfg(feature = "postgres")]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use crate::schema::users;
    /// #     let connection = &mut establish_connection();
    /// // Executes `SELECT * FROM users FOR KEY SHARE`
    /// let users_for_key_share = users::table.for_key_share().load(connection)?;
    /// # let u: Vec<(i32, String)> = users_for_key_share;
    /// # Ok(())
    /// # }
    /// # #[cfg(not(feature = "postgres"))]
    /// # fn run_test() -> QueryResult<()> { Ok(()) }
    /// ```
    fn for_key_share(self) -> ForKeyShare<Self>
    where
        Self: methods::LockingDsl<lock::ForKeyShare>,
    {
        methods::LockingDsl::with_lock(self, lock::ForKeyShare)
    }

    /// Adds `SKIP LOCKED` to the end of a `FOR UPDATE` clause.
    ///
    /// This modifier is only supported in PostgreSQL 9.5+ and MySQL 8+.
    ///
    /// # Example
    ///
    /// ```
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # #[cfg(any(feature = "postgres", feature = "mysql"))]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use crate::schema::users;
    /// #     let connection = &mut establish_connection();
    /// // Executes `SELECT * FROM users FOR UPDATE SKIP LOCKED`
    /// let user_skipped_locked = users::table.for_update().skip_locked().load(connection)?;
    /// # let u: Vec<(i32, String)> = user_skipped_locked;
    /// # Ok(())
    /// # }
    /// # #[cfg(feature = "sqlite")]
    /// # fn run_test() -> QueryResult<()> { Ok(()) }
    /// ```
    fn skip_locked(self) -> SkipLocked<Self>
    where
        Self: methods::ModifyLockDsl<lock::SkipLocked>,
    {
        methods::ModifyLockDsl::modify_lock(self, lock::SkipLocked)
    }

    /// Adds `NOWAIT` to the end of a `FOR UPDATE` clause.
    ///
    /// This modifier is only supported in PostgreSQL 9.5+ and MySQL 8+.
    ///
    /// # Example
    ///
    /// ```
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # #[cfg(any(feature = "mysql", feature = "postgres"))]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use crate::schema::users;
    /// #     let connection = &mut establish_connection();
    /// // Executes `SELECT * FROM users FOR UPDATE NOWAIT`
    /// let users_no_wait = users::table.for_update().no_wait().load(connection)?;
    /// # let u: Vec<(i32, String)> = users_no_wait;
    /// # Ok(())
    /// # }
    /// # #[cfg(feature = "sqlite")]
    /// # fn run_test() -> QueryResult<()> { Ok(()) }
    /// ```
    fn no_wait(self) -> NoWait<Self>
    where
        Self: methods::ModifyLockDsl<lock::NoWait>,
    {
        methods::ModifyLockDsl::modify_lock(self, lock::NoWait)
    }

    /// Boxes the pieces of a query into a single type.
    ///
    /// This is useful for cases where you want to conditionally modify a query,
    /// but need the type to remain the same. The backend must be specified as
    /// part of this. It is not possible to box a query and have it be useable
    /// on multiple backends.
    ///
    /// A boxed query will incur a minor performance penalty, as the query builder
    /// can no longer be inlined by the compiler. For most applications this cost
    /// will be minimal.
    ///
    /// ### Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::users;
    /// #
    /// # fn main() {
    /// #     use std::collections::HashMap;
    /// #     let connection = &mut establish_connection();
    /// #     let mut params = HashMap::new();
    /// #     params.insert("name", "Sean");
    /// let mut query = users::table.into_boxed();
    /// if let Some(name) = params.get("name") {
    ///     query = query.filter(users::name.eq(name));
    /// }
    /// let users = query.load(connection);
    /// #     let expected = vec![(1, String::from("Sean"))];
    /// #     assert_eq!(Ok(expected), users);
    /// # }
    /// ```
    ///
    /// Diesel queries also have a similar problem to [`Iterator`], where
    /// returning them from a function requires exposing the implementation of that
    /// function. The [`helper_types`][helper_types] module exists to help with this,
    /// but you might want to hide the return type or have it conditionally change.
    /// Boxing can achieve both.
    ///
    /// [helper_types]: crate::helper_types
    ///
    /// ### Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # use schema::users;
    /// #
    /// # fn main() {
    /// #     let connection = &mut establish_connection();
    /// fn users_by_name(name: &str) -> users::BoxedQuery<DB> {
    ///     users::table.filter(users::name.eq(name)).into_boxed()
    /// }
    ///
    /// assert_eq!(Ok(1), users_by_name("Sean").select(users::id).first(connection));
    /// assert_eq!(Ok(2), users_by_name("Tess").select(users::id).first(connection));
    /// # }
    /// ```
    fn into_boxed<'a, DB>(self) -> IntoBoxed<'a, Self, DB>
    where
        DB: Backend,
        Self: methods::BoxedDsl<'a, DB>,
    {
        methods::BoxedDsl::internal_into_boxed(self)
    }

    /// Wraps this select statement in parenthesis, allowing it to be used
    /// as an expression.
    ///
    /// SQL allows queries such as `foo = (SELECT ...)`, as long as the
    /// subselect returns only a single column, and 0 or 1 rows. This method
    /// indicates that you expect the query to only return a single value (this
    /// will be enforced by adding `LIMIT 1`).
    ///
    /// The SQL type of this will always be `Nullable`, as the query returns
    /// `NULL` if the table is empty or it otherwise returns 0 rows.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::insert_into;
    /// #     use schema::users::dsl::*;
    /// #     use schema::posts;
    /// #     let connection = &mut establish_connection();
    /// insert_into(posts::table)
    ///     .values(posts::user_id.eq(1))
    ///     .execute(connection)?;
    /// let last_post = posts::table
    ///     .order(posts::id.desc());
    /// let most_recently_active_user = users.select(name)
    ///     .filter(id.nullable().eq(last_post.select(posts::user_id).single_value()))
    ///     .first::<String>(connection)?;
    /// assert_eq!("Sean", most_recently_active_user);
    /// #     Ok(())
    /// # }
    /// ```
    fn single_value(self) -> SingleValue<Self>
    where
        Self: methods::SingleValueDsl,
    {
        methods::SingleValueDsl::single_value(self)
    }

    /// Coerce the SQL type of the select clause to it's nullable equivalent.
    ///
    /// This is useful for writing queries that contain subselects on non null
    /// fields comparing them to nullable fields.
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #    run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     let connection = &mut establish_connection();
    /// table! {
    ///     users {
    ///         id -> Integer,
    ///         name -> Text,
    ///     }
    /// }
    ///
    /// table! {
    ///     posts {
    ///         id -> Integer,
    ///         by_user -> Nullable<Text>,
    ///     }
    /// }
    ///
    /// allow_tables_to_appear_in_same_query!(users, posts);
    ///
    /// # let _: Vec<(i32, Option<String>)> =
    /// posts::table.filter(
    ///    posts::by_user.eq_any(users::table.select(users::name).nullable())
    /// ).load(connection)?;
    /// #     Ok(())
    /// # }
    fn nullable(self) -> NullableSelect<Self>
    where
        Self: methods::SelectNullableDsl,
    {
        methods::SelectNullableDsl::nullable(self)
    }
}

impl<T: Table> QueryDsl for T {}

/// Methods used to execute queries.
pub trait RunQueryDsl<Conn>: Sized {
    /// Executes the given command, returning the number of rows affected.
    ///
    /// `execute` is usually used in conjunction with [`insert_into`](crate::insert_into()),
    /// [`update`](crate::update()) and [`delete`](crate::delete()) where the number of
    /// affected rows is often enough information.
    ///
    /// When asking the database to return data from a query, [`load`](crate::query_dsl::RunQueryDsl::load()) should
    /// probably be used instead.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::insert_into;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let inserted_rows = insert_into(users)
    ///     .values(name.eq("Ruby"))
    ///     .execute(connection)?;
    /// assert_eq!(1, inserted_rows);
    ///
    /// let inserted_rows = insert_into(users)
    ///     .values(&vec![name.eq("Jim"), name.eq("James")])
    ///     .execute(connection)?;
    /// assert_eq!(2, inserted_rows);
    /// #     Ok(())
    /// # }
    /// ```
    fn execute(self, conn: &mut Conn) -> QueryResult<usize>
    where
        Conn: Connection,
        Self: methods::ExecuteDsl<Conn>,
    {
        methods::ExecuteDsl::execute(self, conn)
    }

    /// Executes the given query, returning a [`Vec`] with the returned rows.
    ///
    /// When using the query builder, the return type can be
    /// a tuple of the values, or a struct which implements [`Queryable`].
    ///
    /// When this method is called on [`sql_query`],
    /// the return type can only be a struct which implements [`QueryableByName`]
    ///
    /// For insert, update, and delete operations where only a count of affected is needed,
    /// [`execute`] should be used instead.
    ///
    /// [`Queryable`]: crate::deserialize::Queryable
    /// [`QueryableByName`]: crate::deserialize::QueryableByName
    /// [`execute`]: crate::query_dsl::RunQueryDsl::execute()
    /// [`sql_query`]: crate::sql_query()
    ///
    /// ## How to resolve compiler errors while loading data from the database
    ///
    /// In case you getting uncomprehensable compiler errors while loading data
    /// from the database into a type using [`#[derive(Queryable)]`](derive@crate::prelude::Queryable)
    /// you might want to consider
    /// using  [`#[derive(Selectable)]`](derive@crate::prelude::Selectable) +
    /// `#[diesel(check_for_backend(YourBackendType))]`
    /// to check for mismatching fields at compile time. This drastically improves
    /// the quality of the generated error messages by pointing to concrete type mismatches at
    /// field level.You need to specify the concrete database backend
    /// this specific struct is indented to be used with, as otherwise rustc cannot correctly
    /// identify the required deserialization implementation.
    ///
    /// # Examples
    ///
    /// ## Returning a single field
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::insert_into;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let data = users.select(name)
    ///     .load::<String>(connection)?;
    /// assert_eq!(vec!["Sean", "Tess"], data);
    /// #     Ok(())
    /// # }
    /// ```
    ///
    /// ## Returning a tuple
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::insert_into;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let data = users
    ///     .load::<(i32, String)>(connection)?;
    /// let expected_data = vec![
    ///     (1, String::from("Sean")),
    ///     (2, String::from("Tess")),
    /// ];
    /// assert_eq!(expected_data, data);
    /// #     Ok(())
    /// # }
    /// ```
    ///
    /// ## Returning a struct
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// #[derive(Queryable, PartialEq, Debug)]
    /// struct User {
    ///     id: i32,
    ///     name: String,
    /// }
    ///
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::insert_into;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let data = users
    ///     .load::<User>(connection)?;
    /// let expected_data = vec![
    ///     User { id: 1, name: String::from("Sean") },
    ///     User { id: 2, name: String::from("Tess") },
    /// ];
    /// assert_eq!(expected_data, data);
    /// #     Ok(())
    /// # }
    /// ```
    fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
    where
        Self: LoadQuery<'query, Conn, U>,
    {
        self.internal_load(conn)?.collect()
    }

    /// Executes the given query, returning an [`Iterator`] with the returned rows.
    ///
    /// The iterator's item is [`QueryResult<U>`](crate::result::QueryResult).
    ///
    /// You should normally prefer to use [`RunQueryDsl::load`] instead. This method
    /// is provided for situations where the result needs to be collected into a different
    /// container than a [`Vec`]
    ///
    /// When using the query builder, the return type can be
    /// a tuple of the values, or a struct which implements [`Queryable`].
    /// This type is specified by the first generic type of this function.
    ///
    /// The second generic type parameter specifies the so called loading mode,
    /// which describes how the connection implementation loads data from the database.
    /// All connections should provide a implementation for
    /// [`DefaultLoadingMode`](crate::connection::DefaultLoadingMode).
    ///
    /// They may provide additional modes. Checkout the documentation of the concrete
    /// connection types for details. For connection implementations that provide
    /// more than one loading mode it is **required** to specify this generic paramater.
    /// This is currently true for `PgConnection`.
    ///
    /// When this method is called on [`sql_query`],
    /// the return type can only be a struct which implements [`QueryableByName`]
    ///
    /// For insert, update, and delete operations where only a count of affected is needed,
    /// [`execute`] should be used instead.
    ///
    /// [`Queryable`]: crate::deserialize::Queryable
    /// [`QueryableByName`]: crate::deserialize::QueryableByName
    /// [`execute`]: crate::query_dsl::RunQueryDsl::execute()
    /// [`sql_query`]: crate::sql_query()
    ///
    /// # Examples
    ///
    /// ## Returning a single field
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::insert_into;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// use diesel::connection::DefaultLoadingMode;
    ///
    /// let data = users.select(name)
    ///     .load_iter::<String, DefaultLoadingMode>(connection)?
    ///     .collect::<QueryResult<Vec<_>>>()?;
    /// assert_eq!(vec!["Sean", "Tess"], data);
    /// #     Ok(())
    /// # }
    /// ```
    ///
    /// ## Returning a tuple
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::insert_into;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// use diesel::connection::DefaultLoadingMode;
    ///
    /// let data = users
    ///     .load_iter::<(i32, String), DefaultLoadingMode>(connection)?
    ///     .collect::<QueryResult<Vec<_>>>()?;
    /// let expected_data = vec![
    ///     (1, String::from("Sean")),
    ///     (2, String::from("Tess")),
    /// ];
    /// assert_eq!(expected_data, data);
    /// #     Ok(())
    /// # }
    /// ```
    ///
    /// ## Returning a struct
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// #[derive(Queryable, PartialEq, Debug)]
    /// struct User {
    ///     id: i32,
    ///     name: String,
    /// }
    ///
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::insert_into;
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// use diesel::connection::DefaultLoadingMode;
    ///
    /// let data = users
    ///     .load_iter::<User, DefaultLoadingMode>(connection)?
    ///     .collect::<QueryResult<Vec<_>>>()?;
    /// let expected_data = vec![
    ///     User { id: 1, name: String::from("Sean") },
    ///     User { id: 2, name: String::from("Tess") },
    /// ];
    /// assert_eq!(expected_data, data);
    /// #     Ok(())
    /// # }
    /// ```
    fn load_iter<'conn, 'query: 'conn, U, B>(
        self,
        conn: &'conn mut Conn,
    ) -> QueryResult<Self::RowIter<'conn>>
    where
        U: 'conn,
        Self: LoadQuery<'query, Conn, U, B> + 'conn,
    {
        self.internal_load(conn)
    }

    /// Runs the command, and returns the affected row.
    ///
    /// `Err(NotFound)` will be returned if the query affected 0 rows. You can
    /// call `.optional()` on the result of this if the command was optional to
    /// get back a `Result<Option<U>>`
    ///
    /// When this method is called on an insert, update, or delete statement,
    /// it will implicitly add a `RETURNING *` to the query,
    /// unless a returning clause was already specified.
    ///
    /// This method only returns the first row that was affected, even if more
    /// rows are affected.
    ///
    /// # Example
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// #
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # #[cfg(feature = "postgres")]
    /// # fn run_test() -> QueryResult<()> {
    /// #     use diesel::{insert_into, update};
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// let inserted_row = insert_into(users)
    ///     .values(name.eq("Ruby"))
    ///     .get_result(connection)?;
    /// assert_eq!((3, String::from("Ruby")), inserted_row);
    ///
    /// // This will return `NotFound`, as there is no user with ID 4
    /// let update_result = update(users.find(4))
    ///     .set(name.eq("Jim"))
    ///     .get_result::<(i32, String)>(connection);
    /// assert_eq!(Err(diesel::NotFound), update_result);
    /// #     Ok(())
    /// # }
    /// #
    /// # #[cfg(not(feature = "postgres"))]
    /// # fn run_test() -> QueryResult<()> {
    /// #     Ok(())
    /// # }
    /// ```
    fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
    where
        Self: LoadQuery<'query, Conn, U>,
    {
        match self.internal_load(conn)?.next() {
            Some(v) => v,
            None => Err(crate::result::Error::NotFound),
        }
    }

    /// Runs the command, returning an `Vec` with the affected rows.
    ///
    /// This method is an alias for [`load`], but with a name that makes more
    /// sense for insert, update, and delete statements.
    ///
    /// [`load`]: crate::query_dsl::RunQueryDsl::load()
    fn get_results<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
    where
        Self: LoadQuery<'query, Conn, U>,
    {
        self.load(conn)
    }

    /// Attempts to load a single record.
    ///
    /// This method is equivalent to `.limit(1).get_result()`
    ///
    /// Returns `Ok(record)` if found, and `Err(NotFound)` if no results are
    /// returned. If the query truly is optional, you can call `.optional()` on
    /// the result of this to get a `Result<Option<U>>`.
    ///
    /// # Example:
    ///
    /// ```rust
    /// # include!("../doctest_setup.rs");
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use schema::users::dsl::*;
    /// #     let connection = &mut establish_connection();
    /// diesel::insert_into(users)
    ///     .values(&vec![name.eq("Sean"), name.eq("Pascal")])
    ///     .execute(connection)?;
    ///
    /// let first_name = users.order(id).select(name).first(connection);
    /// assert_eq!(Ok(String::from("Sean")), first_name);
    ///
    /// let not_found = users
    ///     .filter(name.eq("Foo"))
    ///     .first::<(i32, String)>(connection);
    /// assert_eq!(Err(diesel::NotFound), not_found);
    /// #     Ok(())
    /// # }
    /// ```
    fn first<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
    where
        Self: methods::LimitDsl,
        Limit<Self>: LoadQuery<'query, Conn, U>,
    {
        methods::LimitDsl::limit(self, 1).get_result(conn)
    }
}

// Note: We could have a blanket `AsQuery` impl here, which would apply to
// everything we want it to. However, when a query is invalid, we specifically
// want the error to happen on the where clause of the method instead of trait
// resolution. Otherwise our users will get an error saying `<3 page long type>:
// ExecuteDsl is not satisfied` instead of a specific error telling them what
// part of their query is wrong.
impl<T, Conn> RunQueryDsl<Conn> for T where T: Table {}
