         }
     }
 
-    // Create a new query build with the same connection.
-    internal func copy() -> QueryBuilder<Model, Result> {
-        return QueryBuilder<Model, Result>(query: query, on: connection, resultTransformer: resultTransformer)
-    }
-
-    /// Replaces the query result handler with the supplied closure.
-    static func make(
-        on connection: Future<Model.Database.Connection>,
-        with transformer: @escaping ([QueryField: Model.Database.QueryData], Model.Database.Connection) -> Future<Result>
-    ) -> QueryBuilder<Model, Result> {
-        return QueryBuilder(query: DatabaseQuery(entity: Model.entity), on: connection, resultTransformer: { row, conn in
-            return transformer(row, conn)
-        })
-    }
-
-    /// Replaces the query result handler with the supplied closure.
-    func changeResult<NewResult>(
-        with transformer: @escaping ([QueryField: Model.Database.QueryData], Model.Database.Connection) -> Future<NewResult>
-    ) -> QueryBuilder<Model, NewResult> {
-        return QueryBuilder<Model, NewResult>(query: self.query, on: self.connection, resultTransformer: { row, conn in
-            return transformer(row, conn)
-        })
-    }
-
-    /// Transforms the previous query result to a new result using the supplied closure.
-    func transformResult<NewResult>(
-        with transformer: @escaping ([QueryField: Model.Database.QueryData], Model.Database.Connection, Result) -> Future<NewResult>
-    ) -> QueryBuilder<Model, NewResult> {
-        return QueryBuilder<Model, NewResult>(query: self.query, on: self.connection, resultTransformer: { row, conn in
-            return self.resultTransformer(row, conn).flatMap(to: NewResult.self) { result in
-                return transformer(row, conn, result)
-            }
-        })
-    }
-
-    /// Sets the query to decode type `D` when run.
-    public func decode<D>(_ type: D.Type, entity: String = Model.entity) -> QueryBuilder<Model, D> where D: Decodable {
-        let decoder = QueryDataDecoder(Model.Database.self, entity: entity)
-        return changeResult { row, conn in
-            let row = row.onlyValues(forEntity: entity)
-            return Future.map(on: conn) {
-                return try decoder.decode(D.self, from: row)
-            }
-        }
-    }
+    // MARK: Decode
 
     /// Adds an additional type `D` to be decoded when run.
     /// The new result for this query will be a tuple containing the previous result and this new result.
+    ///
+    ///     let joined = try User.query(on: req)
+    ///         .join(Pet.self, field: \.userID, to: \.id)
+    ///         .alsoDecode(Pet.self)
+    ///         .all()
+    ///     print(joined) // Future<[(User, Pet)]>
+    ///
+    /// - parameters:
+    ///     - type: New model type `D` to also decode.
+    /// - returns: `QueryBuilder` decoding type `(Result, D)`.
+    public func alsoDecode<M>(_ type: M.Type) -> QueryBuilder<Model, (Result, M)> where M: Fluent.Model {
+        return alsoDecode(M.self, entity: M.entity)
+    }
+
+    /// Adds an additional type `D` to be decoded when run.
+    /// The new result for this query will be a tuple containing the previous result and this new result.
+    ///
+    ///     let joined = try User.query(on: req)
+    ///         .join(Pet.self, field: \.userID, to: \.id)
+    ///         .alsoDecode(PetDetail.self, entity: "pets")
+    ///         .all()
+    ///     print(joined) // Future<[(User, PetDetail)]>
+    ///
+    /// - parameters:
+    ///     - type: New decodable type `D` to also decode.
+    ///     - entity: Entity name of this decodable type.
+    /// - returns: `QueryBuilder` decoding type `(Result, D)`.
     public func alsoDecode<D>(_ type: D.Type, entity: String) -> QueryBuilder<Model, (Result, D)> where D: Decodable {
         let decoder = QueryDataDecoder(Model.Database.self, entity: entity)
         return transformResult { row, conn, result in

        }
    }

    /// Adds an additional type `D` to be decoded when run.
    /// The new result for this query will be a tuple containing the previous result and this new result.
    public func alsoDecode<M>(_ type: M.Type) -> QueryBuilder<Model, (Result, M)> where M: Fluent.Model {
        return alsoDecode(M.self, entity: M.entity)
    }
}


        self.resultTransformer = resultTransformer
    }

    // MARK: Run

    /// Runs the `QueryBuilder's query, decoding results into the handler.
    ///
    ///     User.query(on: req).run { user in
    ///         print(user)
    ///     }
    ///
    /// - parameters:
    ///     - handler: Optional closure to handle results.
    /// - returns: A `Future` that will be completed when the query has finished.
    public func run(into handler: @escaping (Result) throws -> () = { _ in }) -> Future<Void> {
        /// if the model is soft deletable, and soft deleted
        /// models were not requested, then exclude them
