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 5, 2024
2 parents dc9060c + af3f209 commit ba9fb44
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 186 deletions.
6 changes: 3 additions & 3 deletions Sources/ZeeQL/Access/AccessDataSourceFinders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// ZeeQL
//
// Created by Helge Heß on 22.08.19.
// Copyright © 2019 ZeeZide GmbH. All rights reserved.
// Copyright © 2019-2024 ZeeZide GmbH. All rights reserved.
//

public extension AccessDataSource {
Expand Down Expand Up @@ -206,8 +206,8 @@ public extension AccessDataSource { // Finders

var fs = try fetchSpecificationForFetch()
fs.qualifier = and(q, auxiliaryQualifier)
fs.sortOrderings = nil /* no sorting, makes DB faster */
fs.fetchLimit = 1 /* we just want to find one record */
fs.sortOrderings = [] /* no sorting, makes DB faster */
fs.fetchLimit = 1 /* we just want to find one record */
return fs
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/ZeeQL/Access/ActiveDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ open class ActiveDataSource<Object: ActiveRecordType>: AccessDataSource<Object>,
var cfs = fs
cfs.fetchesReadOnly = true
cfs.fetchAttributeNames = pkeys
cfs.prefetchingRelationshipKeyPathes = nil
cfs.prefetchingRelationshipKeyPathes = []

let pkeyAttrs = pkeys.compactMap { entity[attribute: $0] }
assert(pkeyAttrs.count == pkeys.count, "could not lookup all pkeys!")
Expand Down Expand Up @@ -177,7 +177,7 @@ open class ActiveDataSource<Object: ActiveRecordType>: AccessDataSource<Object>,
// The idea is that this preserves the WHERE part of the query, including
// relationships.
var cfs = fs
cfs.sortOrderings = nil // no need to sort
cfs.sortOrderings = [] // no need to sort

// hm, well, OK.
cfs.fetchLimit = 1 // TBD: could use '2' to detect query issues
Expand Down
4 changes: 2 additions & 2 deletions Sources/ZeeQL/Access/AdaptorChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,8 @@ public extension AdaptorChannel { // MARK: - Operations
attributes = attrs
}
else if let entity = e {
if let fs = fs, let an = fs.fetchAttributeNames {
attributes = entity.attributesWithNames(an)
if let fs = fs, !fs.fetchAttributeNames.isEmpty {
attributes = entity.attributesWithNames(fs.fetchAttributeNames)
}
else {
attributes = entity.attributes
Expand Down
10 changes: 5 additions & 5 deletions Sources/ZeeQL/Access/CodeAttribute.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// ZeeQL
//
// Created by Helge Hess on 01/03/2017.
// Copyright © 2017 ZeeZide GmbH. All rights reserved.
// Copyright © 2017-2024 ZeeZide GmbH. All rights reserved.
//

/**
Expand All @@ -17,6 +17,7 @@
open class CodeAttribute<T: AttributeValue> : ModelAttribute {

// Note: we remove the keyword
@inlinable
public init(_ name : String? = nil,
column : String? = nil,
externalType : String? = nil,
Expand All @@ -40,16 +41,15 @@ open class CodeAttribute<T: AttributeValue> : ModelAttribute {

public protocol SQLLikeType {}
extension String : SQLLikeType {}
extension Optional : SQLLikeType {} // sigh: to support Optional<String>
// needs: conditional conformance, maybe Swift 4
extension Optional : SQLLikeType where Wrapped: SQLLikeType {}

public extension CodeAttribute where T : SQLLikeType {

@inlinable
func like(_ pattern : String) -> KeyValueQualifier {
let key = AttributeKey(self)
return KeyValueQualifier(key, .Like, pattern)
}

}
}


Expand Down
14 changes: 6 additions & 8 deletions Sources/ZeeQL/Access/DatabaseChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1186,9 +1186,7 @@ open class TypedDatabaseChannel<ObjectType> : DatabaseChannelBase,
_ ec: ObjectTrackingContext? = nil
) throws
{
guard let prefetchRelPathes = fs.prefetchingRelationshipKeyPathes,
!prefetchRelPathes.isEmpty else
{
guard !fs.prefetchingRelationshipKeyPathes.isEmpty else {
/* simple case, no prefetches */
return try primarySelectObjectsWithFetchSpecification(fs, ec)
}
Expand Down Expand Up @@ -1273,7 +1271,8 @@ open class TypedDatabaseChannel<ObjectType> : DatabaseChannelBase,

do {
try fetchRelationships(fs.entity, entityName,
prefetchRelPathes, baseObjects, ec)
fs.prefetchingRelationshipKeyPathes,
baseObjects, ec)
}
catch {
cancelFetch()
Expand Down Expand Up @@ -1347,9 +1346,7 @@ open class DatabaseChannel : DatabaseChannelBase, IteratorProtocol {
= nil)
throws
{
guard let prefetchRelPathes = fs.prefetchingRelationshipKeyPathes,
!prefetchRelPathes.isEmpty
else {
guard !fs.prefetchingRelationshipKeyPathes.isEmpty else {
/* simple case, no prefetches */
return try primarySelectObjectsWithFetchSpecification(fs, ec)
}
Expand Down Expand Up @@ -1425,7 +1422,8 @@ open class DatabaseChannel : DatabaseChannelBase, IteratorProtocol {

do {
try fetchRelationships(fs.entity, entityName,
prefetchRelPathes, baseObjects, ec)
fs.prefetchingRelationshipKeyPathes,
baseObjects, ec)
}
catch {
cancelFetch()
Expand Down
20 changes: 4 additions & 16 deletions Sources/ZeeQL/Access/ModelLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,8 @@ open class CoreDataModelLoader : ModelLoader {
}
else { limit = nil }

let sos : [ SortOrdering ]? = nil
var fs = ModelFetchSpecification(entity: entity, qualifier: q,
sortOrderings: sos, limit: limit)
sortOrderings: [], limit: limit)

fs.usesDistinct = boolValue(attrs["returnDistinctResults"])

Expand Down Expand Up @@ -356,30 +355,19 @@ open class CoreDataModelLoader : ModelLoader {
for xml in xml.childElementsWithName("ordering") {
// `<ordering key="name" />` (multiple are possible!)
guard let ordering = loadSortOrdering(from: xml) else { continue }
if fs.sortOrderings == nil { fs.sortOrderings = [] }
fs.sortOrderings?.append(ordering)
fs.sortOrderings.append(ordering)
}

if let v = attrs["attributes"]?.split(separator: ","), !v.isEmpty {
if fs.fetchAttributeNames == nil {
fs.fetchAttributeNames = v.map(String.init)
}
else {
fs.fetchAttributeNames?.append(contentsOf: v.map(String.init))
}
fs.fetchAttributeNames.append(contentsOf: v.map(String.init))
}
for xml in xml.childElementsWithName("attributes") {
// <attributes>objectId,permissions</attributes>
guard let v = xml.textContent?.split(separator: ","), !v.isEmpty else {
assertionFailure("<attributes> tag w/o content?")
continue
}
if fs.fetchAttributeNames == nil {
fs.fetchAttributeNames = v.map(String.init)
}
else {
fs.fetchAttributeNames?.append(contentsOf: v.map(String.init))
}
fs.fetchAttributeNames.append(contentsOf: v.map(String.init))
}
if let xml = xml.firstChildElementWithName("qualifier") {
// <qualifier>(principalId IN $authIds) AND (objectId IN $ids)</qualifier>
Expand Down
68 changes: 53 additions & 15 deletions Sources/ZeeQL/Access/TypedFetchSpecification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ public struct TypedFetchSpecification<Object: DatabaseObject>
return nil
}

public var fetchAttributeNames : [ String ]?
public var fetchAttributeNames = [ String ]()
public var qualifier : Qualifier?
public var sortOrderings : [ SortOrdering ]?
public var sortOrderings = [ SortOrdering ]()
public var fetchLimit : Int?
public var fetchOffset : Int?
public var hints = [ String : Any ]()
Expand All @@ -55,14 +55,14 @@ public struct TypedFetchSpecification<Object: DatabaseObject>
public var fetchesRawRows = false
public var fetchesReadOnly = false
public var requiresAllQualifierBindingVariables = false
public var prefetchingRelationshipKeyPathes : [ String ]?
public var prefetchingRelationshipKeyPathes = [ String ]()

@inlinable
public init(entityName : String? = nil,
qualifier : Qualifier? = nil,
sortOrderings : [ SortOrdering ]? = nil,
limit : Int? = nil,
prefetch : [ String ]? = nil,
public init(entityName : String? = nil,
qualifier : Qualifier? = nil,
sortOrderings : [ SortOrdering ] = [],
limit : Int? = nil,
prefetch : [ String ] = [],
requiresAllQualifierBindingVariables: Bool = false)
{
self._entityName = entityName
Expand All @@ -76,10 +76,10 @@ public struct TypedFetchSpecification<Object: DatabaseObject>

@inlinable
public init(entity : Entity,
qualifier : Qualifier? = nil,
sortOrderings : [ SortOrdering ]? = nil,
limit : Int? = nil,
prefetch : [ String ]? = nil,
qualifier : Qualifier? = nil,
sortOrderings : [ SortOrdering ] = [],
limit : Int? = nil,
prefetch : [ String ] = [],
requiresAllQualifierBindingVariables: Bool = false)
{
self._entity = entity
Expand All @@ -94,9 +94,9 @@ public struct TypedFetchSpecification<Object: DatabaseObject>
/// Initialize w/ a qualifier string.
public init(entity : Entity,
_ q : String,
sortOrderings : [ SortOrdering ]? = nil,
limit : Int? = nil,
prefetch : [ String ]? = nil)
sortOrderings : [ SortOrdering ] = [],
limit : Int? = nil,
prefetch : [ String ] = [])
{
self._entity = entity
self.qualifier = qualifierWith(format: q)
Expand All @@ -106,3 +106,41 @@ public struct TypedFetchSpecification<Object: DatabaseObject>
}

}

extension TypedFetchSpecification: Equatable {

public static func ==(lhs: Self, rhs: Self) -> Bool {
guard lhs.usesDistinct == rhs.usesDistinct,
lhs.locksObjects == rhs.locksObjects,
lhs.deep == rhs.deep,
lhs.requiresAllQualifierBindingVariables ==
rhs.requiresAllQualifierBindingVariables,
lhs.prefetchingRelationshipKeyPathes ==
rhs.prefetchingRelationshipKeyPathes,
lhs.fetchesRawRows == rhs.fetchesRawRows,
lhs.fetchesReadOnly == rhs.fetchesReadOnly,
lhs.fetchAttributeNames == rhs.fetchAttributeNames,
lhs.sortOrderings == rhs.sortOrderings,
lhs.fetchLimit == rhs.fetchLimit,
lhs.fetchOffset == rhs.fetchOffset else { return false }

if let lhs = lhs.qualifier { return lhs.isEqual(to: rhs.qualifier) }
else if rhs.qualifier != nil { return false }

guard lhs.entityName == rhs.entityName else { return false }
if let lhs = lhs.entity { return lhs.isEqual(to: rhs.entity) }
else if rhs.entity != nil { return false }

if lhs.hints.count != rhs.hints.count { return false }
return eq(lhs.hints, rhs.hints)
}
}
extension TypedFetchSpecification: EquatableType {

public func isEqual(to object: Any?) -> Bool {
// TBD: Would we want to allow comparison to ModelFS and such? That *might*
// make sense?
guard let typed = object as? Self else { return false }
return self == typed
}
}
4 changes: 2 additions & 2 deletions Sources/ZeeQL/Control/ArrayDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ open class ArrayDataSource<Object: SwiftObject> : DataSource<Object>,
}


if let sos = fs.sortOrderings, !sos.isEmpty {
if !fs.sortOrderings.isEmpty {
// TODO: sort
log.warn("not applying sort orderings", self, sos)
log.warn("not applying sort orderings", self, fs.sortOrderings)
}

let count = filtered.count
Expand Down
31 changes: 25 additions & 6 deletions Sources/ZeeQL/Control/EntityType+Builder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ public extension EntityType {
// TBD: maybe rename, 'select' should run the actual select, right?

@inlinable
static func select(_ attributes: String...)
-> FetchSpecification
{
static func select(_ attributes: String...) -> FetchSpecification {
var fs = ModelFetchSpecification(entity: Self.entity)
fs.fetchAttributeNames = attributes.isEmpty ? nil : attributes
fs.fetchAttributeNames = attributes
return fs
}

Expand Down Expand Up @@ -57,7 +55,7 @@ public extension TypedEntityType where Self: DatabaseObject {
-> TypedFetchSpecification<Self>
{
var fs = TypedFetchSpecification<Self>(entity: Self.entity)
fs.fetchAttributeNames = attributes.isEmpty ? nil : attributes
fs.fetchAttributeNames = attributes
return fs
}

Expand Down Expand Up @@ -137,11 +135,32 @@ public extension TypedEntityType where FullEntity: CodeEntity<Self> {
_ value: V
) -> TypedFetchSpecification<Self>
where V: AttributeValue
{
return `where`(key, .EqualTo, value)
}

@inlinable
static func `where`<V>(
_ key: Swift.KeyPath<FullEntity, CodeAttribute<V?>>,
_ operation: ComparisonOperation,
_ value: V?
) -> 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), .EqualTo, value)
fs.qualifier = KeyValueQualifier(AttributeKey(attribute), operation, value)
return fs
}

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

0 comments on commit ba9fb44

Please sign in to comment.