<commit_before>public protocol QueryRepresentable {
    associatedtype E: Entity
    func makeQuery(_ executor: Executor) throws -> Query<E>
}

public protocol ExecutorRepresentable {
    func makeExecutor() throws -> Executor
}


extension QueryRepresentable where Self: ExecutorRepresentable {
    public func makeQuery() throws -> Query<E> {
        return try makeQuery(makeExecutor())
    }
}

// MARK: Fetch
extension QueryRepresentable where Self: ExecutorRepresentable {    
    /// Returns all entities retrieved by the query.
    public func all(_ computedFields: [RawOr<ComputedField>] = []) throws -> [E] {
        let query = try makeQuery()
        query.action = .fetch(computedFields + E.computedFields)

        guard let array = try query.raw().array else {
            throw QueryError.invalidDriverResponse("Array required.")
        }
        
        var models: [E] = []

        for result in array {
            let row = Row(node: result)
            let model = try E(row: row)
            model.id = try row.get(E.idKey)
            model.exists = true

            // timestampable
            if
                let T = E.self as? Timestampable.Type,
                let t = model as? Timestampable
            {
                t.createdAt = try row.get(T.createdAtKey)
                t.updatedAt = try row.get(T.updatedAtKey)
            }

            // soft deletable
            if
                let S = E.self as? SoftDeletable.Type,
                let s = model as? SoftDeletable
            {
                s.deletedAt = try row.get(S.deletedAtKey)
            }

            models.append(model)
        }

        return models
    }

    /// Returns the first entity retrieved by the query.
    public func first(_ computedFields: [RawOr<ComputedField>] = []) throws -> E? {
        let query = try makeQuery()
        query.action = .fetch(computedFields + E.computedFields)
        try query.limit(1)

        let model = try query.all().first

        return model
    }

    /// Returns the first entity with the given `id`.
    public func find(_ id: NodeRepresentable?) throws -> E? {
        return try makeQuery()
            .filter(E.idKey, id)
            .first()
    }
}

// MARK: Create
extension QueryRepresentable where Self: ExecutorRepresentable {
    /// Attempts the create action for the supplied
    /// serialized data.
    /// Returns the new entity's identifier.
    public func create(_ row: Row?) throws -> Identifier {
        let query = try makeQuery()

        query.action = .create
        row?.makeNode(in: query.context).rawOrObject?.forEach { (key, value) in
            query.data[key] = value
        }

        let raw = try query.raw()
        return Identifier(raw)
    }
    
    public func save() throws {
        let query = try makeQuery()
        guard let entity = query.entity else {
            throw QueryError.entityRequired
        }
        try save(entity)
    }

    /// Attempts to save a supplied entity
    /// and updates its identifier if successful.
    public func save(_ entity: E) throws {
        let query = try makeQuery()

        if let _ = entity.id, entity.exists {
            // update
            try entity.willUpdate()
            var row = try entity.makeDirtyRow()
            try row.set(E.idKey, entity.id)

            // timestampable
            if
                let T = E.self as? Timestampable.Type,
                let t = entity as? Timestampable
            {
                let now = Date()
                try row.set(T.updatedAtKey, now)
                t.updatedAt = now
            }

            // soft deletable
            if
                let S = E.self as? SoftDeletable.Type,
                let s = entity as? SoftDeletable
            {
                if let deletedAt = s.deletedAt {
                    try row.set(S.deletedAtKey, deletedAt)
                } else {
                    try row.set(S.deletedAtKey, Node.null)
                }
            }

            try modify(row)
            entity.didUpdate()
        } else {
            // create
            if entity.id == nil, case .uuid = E.idType {
                // automatically generates uuids
                // for models without them
                entity.id = Identifier(UUID.random())
            }
            try entity.willCreate()
            var row = try entity.makeRow()
            try row.set(E.idKey, entity.id)

            // timestampable
            if
                let T = E.self as? Timestampable.Type,
                let t = entity as? Timestampable
            {
                let now = Date()
                try row.set(T.createdAtKey, now)
                try row.set(T.updatedAtKey, now)
                t.createdAt = now
                t.updatedAt = now
            }

            let id = try query.create(row)
            if id != nil, id != .null, id != 0 {
                entity.id = id
            }

            entity.didCreate()
        }
        entity.exists = true
    }
}

// MARK: Delete
extension QueryRepresentable where Self: ExecutorRepresentable {
    /// Attempts to delete all entities
    /// in the model's collection.
    public func delete(shouldForceDelete: Bool = true) throws {
        let query = try makeQuery()
        if let entity = query.entity {
            if let softDeletbleEntity = entity as? SoftDeletable {
                softDeletbleEntity.shouldForceDelete = shouldForceDelete
            }
            try query.delete(entity)
        } else if let softDeletableEntityType = E.self as? SoftDeletable, shouldForceDelete == false {
            let deletedAtKey = type(of: softDeletableEntityType).deletedAtKey
            var row = Row()
            try row.set(deletedAtKey, Date())
            try query.modify(row)
        } else {
            query.action = .delete
            try query.raw()
        }
    }

    /// Attempts to delete the supplied entity
    /// if its identifier is set.
    public func delete(_ entity: E) throws {
        let id = try entity.assertExists()
        let query = try makeQuery()

        // if the model is soft deletable and
        // does not have the force delete flag set,
        // then soft delete it.<commit_msg>Improves naming following the current codebase<commit_after>public protocol QueryRepresentable {
    associatedtype E: Entity
    func makeQuery(_ executor: Executor) throws -> Query<E>
}

public protocol ExecutorRepresentable {
    func makeExecutor() throws -> Executor
}


extension QueryRepresentable where Self: ExecutorRepresentable {
    public func makeQuery() throws -> Query<E> {
        return try makeQuery(makeExecutor())
    }
}

// MARK: Fetch
extension QueryRepresentable where Self: ExecutorRepresentable {    
    /// Returns all entities retrieved by the query.
    public func all(_ computedFields: [RawOr<ComputedField>] = []) throws -> [E] {
        let query = try makeQuery()
        query.action = .fetch(computedFields + E.computedFields)

        guard let array = try query.raw().array else {
            throw QueryError.invalidDriverResponse("Array required.")
        }
        
        var models: [E] = []

        for result in array {
            let row = Row(node: result)
            let model = try E(row: row)
            model.id = try row.get(E.idKey)
            model.exists = true

            // timestampable
            if
                let T = E.self as? Timestampable.Type,
                let t = model as? Timestampable
            {
                t.createdAt = try row.get(T.createdAtKey)
                t.updatedAt = try row.get(T.updatedAtKey)
            }

            // soft deletable
            if
                let S = E.self as? SoftDeletable.Type,
                let s = model as? SoftDeletable
            {
                s.deletedAt = try row.get(S.deletedAtKey)
            }

            models.append(model)
        }

        return models
    }

    /// Returns the first entity retrieved by the query.
    public func first(_ computedFields: [RawOr<ComputedField>] = []) throws -> E? {
        let query = try makeQuery()
        query.action = .fetch(computedFields + E.computedFields)
        try query.limit(1)

        let model = try query.all().first

        return model
    }

    /// Returns the first entity with the given `id`.
    public func find(_ id: NodeRepresentable?) throws -> E? {
        return try makeQuery()
            .filter(E.idKey, id)
            .first()
    }
}

// MARK: Create
extension QueryRepresentable where Self: ExecutorRepresentable {
    /// Attempts the create action for the supplied
    /// serialized data.
    /// Returns the new entity's identifier.
    public func create(_ row: Row?) throws -> Identifier {
        let query = try makeQuery()

        query.action = .create
        row?.makeNode(in: query.context).rawOrObject?.forEach { (key, value) in
            query.data[key] = value
        }

        let raw = try query.raw()
        return Identifier(raw)
    }
    
    public func save() throws {
        let query = try makeQuery()
        guard let entity = query.entity else {
            throw QueryError.entityRequired
        }
        try save(entity)
    }

    /// Attempts to save a supplied entity
    /// and updates its identifier if successful.
    public func save(_ entity: E) throws {
        let query = try makeQuery()

        if let _ = entity.id, entity.exists {
            // update
            try entity.willUpdate()
            var row = try entity.makeDirtyRow()
            try row.set(E.idKey, entity.id)

            // timestampable
            if
                let T = E.self as? Timestampable.Type,
                let t = entity as? Timestampable
            {
                let now = Date()
                try row.set(T.updatedAtKey, now)
                t.updatedAt = now
            }

            // soft deletable
            if
                let S = E.self as? SoftDeletable.Type,
                let s = entity as? SoftDeletable
            {
                if let deletedAt = s.deletedAt {
                    try row.set(S.deletedAtKey, deletedAt)
                } else {
                    try row.set(S.deletedAtKey, Node.null)
                }
            }

            try modify(row)
            entity.didUpdate()
        } else {
            // create
            if entity.id == nil, case .uuid = E.idType {
                // automatically generates uuids
                // for models without them
                entity.id = Identifier(UUID.random())
            }
            try entity.willCreate()
            var row = try entity.makeRow()
            try row.set(E.idKey, entity.id)

            // timestampable
            if
                let T = E.self as? Timestampable.Type,
                let t = entity as? Timestampable
            {
                let now = Date()
                try row.set(T.createdAtKey, now)
                try row.set(T.updatedAtKey, now)
                t.createdAt = now
                t.updatedAt = now
            }

            let id = try query.create(row)
            if id != nil, id != .null, id != 0 {
                entity.id = id
            }

            entity.didCreate()
        }
        entity.exists = true
    }
}

// MARK: Delete
extension QueryRepresentable where Self: ExecutorRepresentable {
    /// Attempts to delete all entities
    /// in the model's collection.
    public func delete(shouldForceDelete: Bool = true) throws {
        let query = try makeQuery()
        if let entity = query.entity {
            if let softDeletbleEntity = entity as? SoftDeletable {
                softDeletbleEntity.shouldForceDelete = shouldForceDelete
            }
            try query.delete(entity)
        } else if let S = E.self as? SoftDeletable.Type, shouldForceDelete == false {
            let deletedAtKey = S.deletedAtKey
            var row = Row()
            try row.set(deletedAtKey, Date())
            try query.modify(row)
        } else {
            query.action = .delete
            try query.raw()
        }
    }

    /// Attempts to delete the supplied entity
    /// if its identifier is set.
    public func delete(_ entity: E) throws {
        let id = try entity.assertExists()
        let query = try makeQuery()

        // if the model is soft deletable and
        // does not have the force delete flag set,
        // then soft delete it.
{'fraction_non_alphanumeric': 0.0881648298993771, 'fraction_numerical': 0.00031943778949049674, 'mean_word_length': 1.4926353503184713, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2357924', 'n_tokens_mistral': 3381, 'n_tokens_neox': 3235, 'n_words': 1007}