Skip to content

Commit

Permalink
Beauty and comments
Browse files Browse the repository at this point in the history
...
  • Loading branch information
helje5 committed Nov 30, 2024
1 parent e375e14 commit 25f01a2
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 46 deletions.
18 changes: 11 additions & 7 deletions Sources/ZeeQL/Access/DatabaseChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -509,15 +509,15 @@ open class DatabaseChannelBase {
*/
let helper = DatabaseChannelFetchHelper(baseObjects: baseObjects)

for ( relName, value ) in leveledPrefetches {
for ( relName, values ) in leveledPrefetches {
/* The relName is never a path, its a level-1 key. the value in
* leveledPrefetches contains 'subpathes'.
*/
do {
try fetchRelationship(entity, relName, baseObjects, value, helper, ec)
try fetchRelationship(entity, relName, baseObjects, values, helper, ec)
}
catch {
log.error("Could not fetch relationship", relName, value, error)
log.error("Could not fetch relationship", relName, values, error)
throw error
}
}
Expand Down Expand Up @@ -586,8 +586,9 @@ open class DatabaseChannelBase {

/* extract values of source object list for IN query on target */

guard let srcName = join.source?.name ?? join.sourceName
else { throw Error.IncompleteJoin(join) }
guard let srcName = join.source?.name ?? join.sourceName else {
throw Error.IncompleteJoin(join)
}

let srcValues = helper.getSourceValues(srcName)

Expand Down Expand Up @@ -623,10 +624,13 @@ open class DatabaseChannelBase {
}
let targetName = targetAttr.name

// This does things like:
// `companyId in [ 1, 2, 3, 4 ]`
let joinQualifier = KeyValueQualifier(targetName, .Contains, srcValues)

guard let destEntity = rel.destinationEntity else {
// TODO: what error
assertionFailure("Missing destination Entity for relationship \(rel)")
return
}

Expand Down Expand Up @@ -1183,8 +1187,8 @@ open class TypedDatabaseChannel<ObjectType> : DatabaseChannelBase,
) throws
{
guard let prefetchRelPathes = fs.prefetchingRelationshipKeyPathes,
!prefetchRelPathes.isEmpty
else {
!prefetchRelPathes.isEmpty else
{
/* simple case, no prefetches */
return try primarySelectObjectsWithFetchSpecification(fs, ec)
}
Expand Down
6 changes: 5 additions & 1 deletion Sources/ZeeQL/Access/Entity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,12 @@ public extension Entity { // default imp
ms += " #attrs=\(attributes.count)"

if relationships.count > 0 { ms += " #rel=\(relationships.count)" }

if let rq = restrictingQualifier {
ms += " restrict=\(rq)"
}

// TODO: restrictingQualifier, fetchspecs
// TODO: fetchspecs
}
}

Expand Down
59 changes: 26 additions & 33 deletions Sources/ZeeQL/Control/ComparisonOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@

// TODO: Update to modern Swift API standards (e.g. lowercase)

public enum ComparisonOperation : Equatable, SmartDescription {
public enum ComparisonOperation: Equatable {
// Cannot nest in Qualifier protocol in Swift 3.0, maybe later
// TODO: lowercase cases (can use static vars for compat)

case Unknown(String)

Expand All @@ -22,8 +23,9 @@ public enum ComparisonOperation : Equatable, SmartDescription {
* operator when run against the database, e.g. `%` in most SQL databases).
*
* Example:
*
* name LIKE 'Zee*'
* ```sql
* name LIKE 'Zee*'
* ```
*
* Note: `.Like` coalesces nil values with the empty string. This
* can have performance implications in SQL databases. You may choose
Expand All @@ -36,8 +38,9 @@ public enum ComparisonOperation : Equatable, SmartDescription {
* is used as the pattern character, see `.Like` for details.
*
* Example:
*
* name ILIKE 'zee*'
* ```sql
* name ILIKE 'zee*'
* ```
*
* Not all databases support a SQL case insensitive like. The adaptor may
* rewrite such queries to `LOWER(name) LIKE 'zee*'`.
Expand All @@ -50,9 +53,10 @@ public enum ComparisonOperation : Equatable, SmartDescription {
* In SQL databases a LIKE against a NULL column may have unexpected
* behaviour. If the column `street` is NULL, *neither* of the two queries
* match the row:
*
* SELECT * FROM address WHERE street LIKE '%way%'
* SELECT * FROM address WHERE NOT street LIKE '%way%'
* ```sql
* SELECT * FROM address WHERE street LIKE '%way%'
* SELECT * FROM address WHERE NOT street LIKE '%way%'
* ```
*
* Using `.SQLLike` can be faster than `.Like` as the database is more likely
* able to use an index. Regular `.Like` has the additional processing step
Expand All @@ -62,9 +66,12 @@ public enum ComparisonOperation : Equatable, SmartDescription {

/// Check `.SQLLike` for a discussion and the difference to `.Like`.
case SQLCaseInsensitiveLike
}

public extension ComparisonOperation {


public init(string: String) {
@inlinable
init(string: String) {
switch string {
case "=", "==": self = .EqualTo
case ">": self = .GreaterThan
Expand All @@ -82,8 +89,8 @@ public enum ComparisonOperation : Equatable, SmartDescription {
self = .Unknown(string)
}
}

public var stringRepresentation : String {
@inlinable
var stringRepresentation : String {
switch self {
case .Unknown(let s): return s
case .EqualTo: return "="
Expand All @@ -99,32 +106,18 @@ public enum ComparisonOperation : Equatable, SmartDescription {
case .SQLCaseInsensitiveLike: return "SQLILIKE"
}
}
}

extension ComparisonOperation: SmartDescription {

@inlinable
public var description: String { return stringRepresentation }

@inlinable
public func appendToDescription(_ ms: inout String) {
ms += " "
ms += stringRepresentation
}

@inlinable
public static func ==(lhs: ComparisonOperation, rhs: ComparisonOperation)
-> Bool
{
switch ( lhs, rhs ) {
case ( EqualTo, EqualTo ): return true
case ( NotEqualTo, NotEqualTo ): return true
case ( GreaterThan, GreaterThan ): return true
case ( GreaterThanOrEqual, GreaterThanOrEqual ): return true
case ( LessThan, LessThan ): return true
case ( LessThanOrEqual, LessThanOrEqual ): return true
case ( Contains, Contains ): return true
case ( Like, Like ): return true
case ( CaseInsensitiveLike, CaseInsensitiveLike ): return true
case ( SQLLike, SQLLike ): return true
case ( SQLCaseInsensitiveLike, SQLCaseInsensitiveLike ): return true
case ( Unknown(let lhsV), Unknown(let rhsV) ): return lhsV == rhsV
default: return false
}
}
}

public extension ComparisonOperation {
Expand Down
7 changes: 6 additions & 1 deletion Sources/ZeeQL/Control/KeyValueQualifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,12 @@ public struct KeyValueQualifier : Qualifier, Equatable {
@inlinable
public func appendToDescription(_ ms: inout String) {
// TODO: improve
ms += " \(keyExpr) \(operation) \(value as Optional)"
if let key = keyExpr as? StringKey {
ms += " \(key.key) \(operation) \(value as Optional)"
}
else {
ms += " \(keyExpr) \(operation) \(value as Optional)"
}
}

public func appendToStringRepresentation(_ ms: inout String) {
Expand Down
11 changes: 7 additions & 4 deletions Sources/ZeeQL/Control/Qualifier.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,24 @@ public extension Qualifier { // default imp

// MARK: - Convenience

@inlinable
var not : Qualifier { return NotQualifier(qualifier: self) }

@inlinable
func or(_ q: Qualifier?) -> Qualifier {
guard let q = q else { return self }
if let bq = q as? BooleanQualifier {
return bq.value ? BooleanQualifier.trueQualifier : self
}
return CompoundQualifier(qualifiers: [ self, q ], op: .Or)
}
func and(_ q: Qualifier?) -> Qualifier {
guard let q = q else { return self }
if let bq = q as? BooleanQualifier {
@inlinable
func and(_ other: Qualifier?) -> Qualifier {
guard let other = other else { return self }
if let bq = other as? BooleanQualifier {
return bq.value ? self : BooleanQualifier.falseQualifier
}
return CompoundQualifier(qualifiers: [ self, q ], op: .And)
return CompoundQualifier(qualifiers: [ self, other ], op: .And)
}

}
Expand Down

0 comments on commit 25f01a2

Please sign in to comment.