diff --git a/Sources/ZeeQL/Access/AccessDataSource.swift b/Sources/ZeeQL/Access/AccessDataSource.swift index 40ea937..29b70c0 100644 --- a/Sources/ZeeQL/Access/AccessDataSource.swift +++ b/Sources/ZeeQL/Access/AccessDataSource.swift @@ -146,6 +146,48 @@ open class AccessDataSource : DataSource, public extension AccessDataSourceType { + /** + * This method takes the name of a fetch specification. It looks up the fetch + * spec in the ``Entity`` associated with the datasource and then binds the + * spec with the given key/value pairs. + * + * Example: + * ```swift + * try ds.fetchObjects(myFetchSpec, ["contactId": 12345]) { contact in + * print("Contact:", contact) + * } + * ``` + * + * This calls ``FetchSpecification/fetchSpecificiationWith(bindings:)-585ip`` + * and passes in the given key/value pair (contactId=12345). + * + * Finally the fetch will be performed using + * ``_primaryFetchObjects``. + * + * - Parameters: + * - fetchSpecification: The ``FetchSpecification`` to use. + * - keysAndValues: The key/value pairs to apply as bindings. + */ + @inlinable + func fetchObjects(_ fetchSpecification: FetchSpecification, + _ binds: [ String : Any ] = [:], + yield: ( Object ) throws -> Void) throws + { + if !binds.isEmpty { + guard let fs = try fetchSpecification + .fetchSpecificiationWith(bindings: binds) else + { + throw AccessDataSourceError + .CouldNotResolveBindings(fetchSpecification: fetchSpecification, + bindings: binds) + } + try _primaryFetchObjects(fs) { try yield($0) } + } + else { + try _primaryFetchObjects(fetchSpecification) { try yield($0) } + } + } + /** * This method takes the name of a fetch specification. It looks up the fetch * spec in the `Entity` associated with the datasource and then binds the @@ -153,12 +195,14 @@ public extension AccessDataSourceType { * * Example: * ```swift - * let persons = try ds.fetchObjects("myContacts", ["contactId": 12345]) + * try ds.fetchObjects("myContacts", ["contactId": 12345]) { contact in + * print("Contact:", contact) + * } * ``` * * This will lookup the `FetchSpecification` named "myContacts" in * the `Entity` of the datasource. It then calls - * `fetchSpecificationWithQualifierBindings()` + * ``FetchSpecification/fetchSpecificiationWith(bindings:)-585ip`` * and passes in the given key/value pair (contactId=12345). * * Finally the fetch will be performed using @@ -167,15 +211,16 @@ public extension AccessDataSourceType { * - Parameters: * - fetchSpecificationName: The name of the fetch specification to use. * - keysAndValues: The key/value pairs to apply as bindings. - * - Returns: The fetched objects. */ @inlinable func fetchObjects(_ fetchSpecificationName: String, - _ binds: [ String : Any ] = [:]) throws -> [ Object ] + _ binds: [ String : Any ] = [:], + yield: ( Object ) throws -> Void) throws { guard let findEntity = entity else { // TBD: improve exception - log.error("did not find entity, cannot construct fetchspec"); + log.error("did not find entity, cannot construct fetchspec:", + fetchSpecificationName) throw AccessDataSourceError.MissingEntity } @@ -184,21 +229,41 @@ public extension AccessDataSourceType { .DidNotFindFetchSpecification(name: fetchSpecificationName, entity: findEntity) } - + return try fetchObjects(fs, binds, yield: yield) + } + + /** + * This method takes the name of a fetch specification. It looks up the fetch + * spec in the `Entity` associated with the datasource and then binds the + * spec with the given key/value pairs. + * + * Example: + * ```swift + * let persons = try ds.fetchObjects("myContacts", ["contactId": 12345]) + * ``` + * + * This will lookup the `FetchSpecification` named "myContacts" in + * the `Entity` of the datasource. It then calls + * `fetchSpecificationWithQualifierBindings()` + * and passes in the given key/value pair (contactId=12345). + * + * Finally the fetch will be performed using + * ``_primaryFetchObjects``. + * + * - Parameters: + * - fetchSpecificationName: The name of the fetch specification to use. + * - keysAndValues: The key/value pairs to apply as bindings. + * - Returns: The fetched objects. + */ + @inlinable + func fetchObjects(_ fetchSpecificationName: String, + _ binds: [ String : Any ] = [:]) throws -> [ Object ] + { var results = [ Object ]() - if !binds.isEmpty { - guard let fs = try fs.fetchSpecificiationWith(bindings: binds) else { - throw AccessDataSourceError - .CouldNotResolveBindings(fetchSpecification: fs, bindings: binds) - } - try _primaryFetchObjects(fs) { results.append($0) } - } - else { - try _primaryFetchObjects(fs) { results.append($0) } - } + try fetchObjects(fetchSpecificationName, binds) { results.append($0) } return results } - + /** * This method takes the name of a fetch specification. It looks up the fetch * spec in the `Entity` associated with the datasource and then binds the diff --git a/Sources/ZeeQL/Access/AccessDataSourceError.swift b/Sources/ZeeQL/Access/AccessDataSourceError.swift index 39f41f8..8e9ca41 100644 --- a/Sources/ZeeQL/Access/AccessDataSourceError.swift +++ b/Sources/ZeeQL/Access/AccessDataSourceError.swift @@ -24,5 +24,5 @@ public enum AccessDataSourceError: Swift.Error { case DidNotFindFetchSpecification(name: String, entity: Entity) case CouldNotResolveBindings(fetchSpecification: FetchSpecification, - bindings: [ String : Any]) + bindings: Any) }