Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
helje5 committed Dec 8, 2024
2 parents ba9fb44 + 66cadff commit 6e9fbbc
Show file tree
Hide file tree
Showing 14 changed files with 206 additions and 145 deletions.
26 changes: 6 additions & 20 deletions Sources/ZeeQL/Access/AccessDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ public extension AccessDataSourceType {
* }
* ```
*
* This calls ``FetchSpecification/fetchSpecificiationWith(bindings:)-585ip``
* and passes in the given key/value pair (contactId=12345).
* This calls ``FetchSpecification/resolvingBindings(_:)`` and passes in the
* given key/value pair (contactId=12345).
*
* Finally the fetch will be performed using
* ``_primaryFetchObjects``.
Expand All @@ -174,13 +174,7 @@ public extension AccessDataSourceType {
yield: ( Object ) throws -> Void) throws
{
if !binds.isEmpty {
guard let fs = try fetchSpecification
.fetchSpecificiationWith(bindings: binds) else
{
throw AccessDataSourceError
.CouldNotResolveBindings(fetchSpecification: fetchSpecification,
bindings: binds)
}
let fs = try fetchSpecification.resolvingBindings(binds)
try _primaryFetchObjects(fs) { try yield($0) }
}
else {
Expand All @@ -202,8 +196,8 @@ public extension AccessDataSourceType {
*
* This will lookup the `FetchSpecification` named "myContacts" in
* the `Entity` of the datasource. It then calls
* ``FetchSpecification/fetchSpecificiationWith(bindings:)-585ip``
* and passes in the given key/value pair (contactId=12345).
* ``FetchSpecification/resolvingBindings(_:)`` and passes in the given
* key/value pair (contactId=12345).
*
* Finally the fetch will be performed using
* ``_primaryFetchObjects``.
Expand Down Expand Up @@ -351,15 +345,7 @@ public extension AccessDataSourceType {
}

/* apply bindings */
if let qb = qb {
guard let fs = try fs.fetchSpecificiationWith(bindings: qb) else {
throw AccessDataSourceError
.CannotConstructFetchSpecification(.bindingFailed)
}
return fs
}

return fs
return try fs.resolvingBindings(qb)
}

}
11 changes: 2 additions & 9 deletions Sources/ZeeQL/Access/AccessDataSourceFinders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public extension AccessDataSource { // Finders
*
* Example:
* ```swift
* let a = personDataSource.find("firstCustomer")
* let a = personDataSource.find("firstCustomer") // fetchspec
* ```
* or:
* ```swift
Expand All @@ -260,14 +260,7 @@ public extension AccessDataSource { // Finders
func find(_ name: String, _ bindings: Any? = nil) throws -> Object? {
guard let entity = entity else { return nil }
guard var fs = entity[fetchSpecification: name] else { return nil }

if let bindings = bindings {
guard let cfs = try fs.fetchSpecificiationWith(bindings: bindings) else {
return nil
}
fs = cfs
}

fs = try fs.resolvingBindings(bindings)
return try find(fs)
}
/**
Expand Down
5 changes: 4 additions & 1 deletion Sources/ZeeQL/Access/Attribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -418,20 +418,23 @@ open class ModelAttribute : Attribute, Equatable {

public extension Attribute {

@inlinable
func eq(_ attr: Attribute) -> KeyComparisonQualifier {
let key = AttributeKey(self)
let otherKey = AttributeKey(attr)
return KeyComparisonQualifier(key, .EqualTo, otherKey)
}

@inlinable
func eq(_ value : Any?) -> KeyValueQualifier {
let key = AttributeKey(self)
return KeyValueQualifier(key, .EqualTo, value)
}
}

public extension Attribute {


@inlinable
func like(_ pattern : String) -> KeyValueQualifier {
let key = AttributeKey(self)
return KeyValueQualifier(key, .Like, pattern)
Expand Down
1 change: 1 addition & 0 deletions Sources/ZeeQL/Access/AttributeKey.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
*/
public struct AttributeKey : Key, Equatable {

@inlinable
public var key : String { return attribute.name }

public let entity : Entity?
Expand Down
2 changes: 1 addition & 1 deletion Sources/ZeeQL/Access/CodeAttribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* Their primary feature over `ModelAttribute`s is that such are generic over
* the value type.
*/
open class CodeAttribute<T: AttributeValue> : ModelAttribute {
open class CodeAttribute<T: AttributeValue> : ModelAttribute, TypedProperty {

// Note: we remove the keyword
@inlinable
Expand Down
5 changes: 4 additions & 1 deletion Sources/ZeeQL/Access/CodeRelationship.swift
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,11 @@ open class CodeRelationshipBase<Target: SwiftObject>
}

open class CodeRelationship<Target: DatabaseObject>
: CodeRelationshipBase<Target>, CodeRelationshipType
: CodeRelationshipBase<Target>, CodeRelationshipType,
TypedProperty
{
public typealias T = Target

public var codeEntity : Entity? = nil
override open var entity : Entity {
set {
Expand Down
12 changes: 10 additions & 2 deletions Sources/ZeeQL/Access/Property.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
// ZeeQL
//
// Created by Helge Heß on 18.02.17.
// Copyright © 2017-2021 ZeeZide GmbH. All rights reserved.
// Copyright © 2017-2024 ZeeZide GmbH. All rights reserved.
//

/**
* A property of an `Entity`: Either an `Attribute` or a `Relationship`.
* A property of an ``Entity``: Either an ``Attribute`` or a ``Relationship``.
*/
public protocol Property : AnyObject, EquatableType {
// `class` because we use identity in some places
Expand All @@ -16,3 +16,11 @@ public protocol Property : AnyObject, EquatableType {
var relationshipPath : String? { get }

}

/**
* A property of an ``Entity``: Either an ``Attribute`` or a ``Relationship``,
* that knows the static type of the property.
*/
public protocol TypedProperty<T>: Property {
associatedtype T
}
45 changes: 21 additions & 24 deletions Sources/ZeeQL/Control/EntityType+Builder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,53 +113,50 @@ public extension TypedEntityObject {
public extension TypedEntityType where FullEntity: CodeEntity<Self> {

// TODO: select w/ pack iteration

// Maybe the `where` should work on typed keys!

@inlinable
static func `where`<V>(
_ key: Swift.KeyPath<FullEntity, CodeAttribute<V>>,
_ operation: ComparisonOperation,
_ value: V
static func `where`<A: TypedProperty>(
_ key : Swift.KeyPath<FullEntity, A>,
_ operation : ComparisonOperation,
_ value : A.T
) -> TypedFetchSpecification<Self>
where V: AttributeValue
{
// if we need no attributes
var fs = TypedFetchSpecification<Self>(entity: Self.entity)
let attribute = Self.e[keyPath: key]
fs.qualifier = KeyValueQualifier(AttributeKey(attribute), operation, value)
let property = Self.e[keyPath: key]
fs.qualifier = KeyValueQualifier(StringKey(property.name), operation, value)
return fs
}

@inlinable
static func `where`<V>(
_ key: Swift.KeyPath<FullEntity, CodeAttribute<V>>,
_ value: V
) -> TypedFetchSpecification<Self>
where V: AttributeValue
static func `where`<A>(_ key: Swift.KeyPath<FullEntity, A>,
_ value: A.T) -> TypedFetchSpecification<Self>
where A: TypedProperty
{
return `where`(key, .EqualTo, value)
}

@inlinable
static func `where`<V>(
_ key: Swift.KeyPath<FullEntity, CodeAttribute<V?>>,
_ operation: ComparisonOperation,
_ value: V?
static func `where`<A>(
_ key : Swift.KeyPath<FullEntity, A>,
_ operation : ComparisonOperation = .EqualTo,
_ value : A.T
) -> TypedFetchSpecification<Self>
where V: AttributeValue
where A: TypedProperty, A.T: AnyOptional
{
// if we need no attributes
var fs = TypedFetchSpecification<Self>(entity: Self.entity)
let attribute = Self.e[keyPath: key]
fs.qualifier = KeyValueQualifier(AttributeKey(attribute), operation, value)
let property = Self.e[keyPath: key]
fs.qualifier = KeyValueQualifier(StringKey(property.name), operation, value)
return fs
}

@inlinable
static func `where`<V>(
_ key: Swift.KeyPath<FullEntity, CodeAttribute<V?>>,
_ value: V?
) -> TypedFetchSpecification<Self>
where V: AttributeValue
static func `where`<A>(_ key: Swift.KeyPath<FullEntity, A>,
_ value: A.T) -> TypedFetchSpecification<Self>
where A: TypedProperty, A.T: AnyOptional
{
return `where`(key, .EqualTo, value)
}
Expand Down
79 changes: 26 additions & 53 deletions Sources/ZeeQL/Control/FetchSpecification+Builder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -195,39 +195,39 @@ public extension DatabaseFetchSpecification
// TODO: select w/ pack iteration

// MARK: - Qualifier


// Maybe the `where` should work on typed keys!

@inlinable
func `where`<V>(_ key: Swift.KeyPath<Object.FullEntity, CodeAttribute<V>>,
_ operation: ComparisonOperation,
_ value: V) -> Self
where V: AttributeValue
func `where`<A: TypedProperty>(_ key: Swift.KeyPath<Object.FullEntity, A>,
_ operation: ComparisonOperation,
_ value: A.T) -> Self
{
let attribute = Object.e[keyPath: key]
return `where`(KeyValueQualifier(AttributeKey(attribute), operation, value))
let property = Object.e[keyPath: key]
return `where`(KeyValueQualifier(StringKey(property.name), operation,value))
}

@inlinable
func `where`<V>(_ key: Swift.KeyPath<Object.FullEntity, CodeAttribute<V>>,
_ value: V) -> Self
where V: AttributeValue
func `where`<A: TypedProperty>(_ key: Swift.KeyPath<Object.FullEntity, A>,
_ value: A.T) -> Self
{
return `where`(key, .EqualTo, value)
}

@inlinable
func `where`<V>(_ key: Swift.KeyPath<Object.FullEntity, CodeAttribute<V?>>,
_ operation: ComparisonOperation,
_ value: V?) -> Self
where V: AttributeValue
func `where`<A: TypedProperty>(_ key: Swift.KeyPath<Object.FullEntity, A>,
_ operation: ComparisonOperation,
_ value: A.T) -> Self
where A: TypedProperty, A.T: AnyOptional
{
let attribute = Object.e[keyPath: key]
return `where`(KeyValueQualifier(AttributeKey(attribute), operation, value))
let property = Object.e[keyPath: key]
return `where`(KeyValueQualifier(StringKey(property.name), operation,value))
}

@inlinable
func `where`<V>(_ key: Swift.KeyPath<Object.FullEntity, CodeAttribute<V?>>,
_ value: V?) -> Self
where V: AttributeValue
func `where`<A: TypedProperty>(_ key: Swift.KeyPath<Object.FullEntity, A>,
_ value: A.T) -> Self
where A: TypedProperty, A.T: AnyOptional
{
return `where`(key, .EqualTo, value)
}
Expand All @@ -236,8 +236,9 @@ public extension DatabaseFetchSpecification
// MARK: - Ordering

#if compiler(>=6)
func order<each V: AttributeValue>(
by key: repeat Swift.KeyPath<Object.FullEntity, CodeAttribute<each V>>,
@inlinable
func order<each A: Attribute>(
by key: repeat Swift.KeyPath<Object.FullEntity, each A>,
using selector: SortOrdering.Selector = .CompareAscending
) -> Self
{
Expand Down Expand Up @@ -266,39 +267,10 @@ public extension DatabaseFetchSpecification
// MARK: - Prefetch

#if compiler(>=6)
// TODO: can we do both toOne and toMany in one?
// a KeyPath that has the parent class (CodeRelationship) doesn't work?
func prefetch<each O: DatabaseObject>(
_ relationship:
repeat Swift.KeyPath<Object.FullEntity, ToOneRelationship<each O>>,
clear: Bool = false
) -> Self
{
transform {
if clear { $0.prefetchingRelationshipKeyPathes = [] }
for relationship in repeat each relationship {
let relationship = Object.e[keyPath: relationship]
$0.prefetchingRelationshipKeyPathes.append(relationship.name)
}
}
}
func prefetch<each O: DatabaseObject>(
_ relationship:
repeat Swift.KeyPath<Object.FullEntity, ToManyRelationship<each O>>,
clear: Bool = false
) -> Self
{
transform {
if clear { $0.prefetchingRelationshipKeyPathes = [] }
for relationship in repeat each relationship {
let relationship = Object.e[keyPath: relationship]
$0.prefetchingRelationshipKeyPathes.append(relationship.name)
}
}
}
func prefetch<each O: DatabaseObject>(
@inlinable
func prefetch<each O: CodeRelationshipType>(
_ relationship:
repeat Swift.KeyPath<Object.FullEntity, CodeRelationship<each O>>,
repeat Swift.KeyPath<Object.FullEntity, each O>,
clear: Bool = false
) -> Self
{
Expand All @@ -310,5 +282,6 @@ public extension DatabaseFetchSpecification
}
}
}

#endif // compiler(>=6)
}
Loading

0 comments on commit 6e9fbbc

Please sign in to comment.