Skip to content

Commit

Permalink
Internal API experiment: KeyPathRefining
Browse files Browse the repository at this point in the history
  • Loading branch information
groue committed Jan 21, 2020
1 parent 66bce33 commit 349e34b
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 171 deletions.
10 changes: 10 additions & 0 deletions GRDB.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,10 @@
56DF001C228DDBA300D611F3 /* AssociationPrefetchingRowTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56DF0019228DDBA200D611F3 /* AssociationPrefetchingRowTests.swift */; };
56DF001D228DDBA300D611F3 /* AssociationPrefetchingCodableRecordTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56DF001A228DDBA300D611F3 /* AssociationPrefetchingCodableRecordTests.swift */; };
56DF001E228DDBA300D611F3 /* AssociationPrefetchingCodableRecordTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56DF001A228DDBA300D611F3 /* AssociationPrefetchingCodableRecordTests.swift */; };
56DF37AB23D77AB4009AAA05 /* KeyPathRefining.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56DF37AA23D77AB4009AAA05 /* KeyPathRefining.swift */; };
56DF37AC23D77AB4009AAA05 /* KeyPathRefining.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56DF37AA23D77AB4009AAA05 /* KeyPathRefining.swift */; };
56DF37AD23D77AB4009AAA05 /* KeyPathRefining.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56DF37AA23D77AB4009AAA05 /* KeyPathRefining.swift */; };
56DF37AE23D77AB4009AAA05 /* KeyPathRefining.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56DF37AA23D77AB4009AAA05 /* KeyPathRefining.swift */; };
56E4F7EE2392E2D000A611F6 /* DatabaseAbortedTransactionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56E4F7ED2392E2D000A611F6 /* DatabaseAbortedTransactionTests.swift */; };
56E4F7EF2392E2D000A611F6 /* DatabaseAbortedTransactionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56E4F7ED2392E2D000A611F6 /* DatabaseAbortedTransactionTests.swift */; };
56E4F7F02392E2D000A611F6 /* DatabaseAbortedTransactionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56E4F7ED2392E2D000A611F6 /* DatabaseAbortedTransactionTests.swift */; };
Expand Down Expand Up @@ -1502,6 +1506,7 @@
56DE7B101C3D93ED00861EB8 /* StatementArgumentsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StatementArgumentsTests.swift; sourceTree = "<group>"; };
56DF0019228DDBA200D611F3 /* AssociationPrefetchingRowTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssociationPrefetchingRowTests.swift; sourceTree = "<group>"; };
56DF001A228DDBA300D611F3 /* AssociationPrefetchingCodableRecordTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AssociationPrefetchingCodableRecordTests.swift; sourceTree = "<group>"; };
56DF37AA23D77AB4009AAA05 /* KeyPathRefining.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyPathRefining.swift; sourceTree = "<group>"; };
56E4F7ED2392E2D000A611F6 /* DatabaseAbortedTransactionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseAbortedTransactionTests.swift; sourceTree = "<group>"; };
56E5D7CA1B4D3FED00430942 /* GRDB.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GRDB.framework; sourceTree = BUILT_PRODUCTS_DIR; };
56E5D7D31B4D3FEE00430942 /* GRDBiOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GRDBiOSTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -1951,6 +1956,7 @@
5659F49F1EA8D997004A4992 /* DatabaseResult.swift */,
563EF4492161F179007DAACD /* Inflections.swift */,
569BBA482291707D00478429 /* Inflections+English.swift */,
56DF37AA23D77AB4009AAA05 /* KeyPathRefining.swift */,
566BE7172342542F00A8254B /* LockedBox.swift */,
563EF414215F87EB007DAACD /* OrderedDictionary.swift */,
5659F4971EA8D989004A4992 /* Pool.swift */,
Expand Down Expand Up @@ -2762,6 +2768,7 @@
56CEB5671EAA359A00BFAF62 /* SQLSelectable.swift in Sources */,
5653EB272094A14400F46237 /* QueryInterfaceRequest+Association.swift in Sources */,
565490B91D5AE236005622CB /* DatabasePool.swift in Sources */,
56DF37AD23D77AB4009AAA05 /* KeyPathRefining.swift in Sources */,
563B06AD217EF0CC00B38F35 /* ValueObservation.swift in Sources */,
5674A6EF1F307F0E0095F066 /* DatabaseValueConvertible+Encodable.swift in Sources */,
565490D81D5AE252005622CB /* DatabaseMigrator.swift in Sources */,
Expand Down Expand Up @@ -2941,6 +2948,7 @@
56A2387C1B9C75030082EB20 /* Configuration.swift in Sources */,
56DAA2DE1DE9C827006E10C8 /* Cursor.swift in Sources */,
560A37A51C8F625000949E71 /* DatabasePool.swift in Sources */,
56DF37AC23D77AB4009AAA05 /* KeyPathRefining.swift in Sources */,
5674A7081F307FCD0095F066 /* DatabaseValueConvertible+ReferenceConvertible.swift in Sources */,
56AE64132229A53700AD1B0B /* HasOneThroughAssociation.swift in Sources */,
56A2388C1B9C75030082EB20 /* Statement.swift in Sources */,
Expand Down Expand Up @@ -3488,6 +3496,7 @@
AAA4DCB0230F1E0600C74B15 /* Configuration.swift in Sources */,
AAA4DCB1230F1E0600C74B15 /* Cursor.swift in Sources */,
AAA4DCB2230F1E0600C74B15 /* DatabasePool.swift in Sources */,
56DF37AE23D77AB4009AAA05 /* KeyPathRefining.swift in Sources */,
AAA4DCB3230F1E0600C74B15 /* DatabaseValueConvertible+ReferenceConvertible.swift in Sources */,
AAA4DCB4230F1E0600C74B15 /* HasOneThroughAssociation.swift in Sources */,
AAA4DCB5230F1E0600C74B15 /* Statement.swift in Sources */,
Expand Down Expand Up @@ -3828,6 +3837,7 @@
560D92401C672C3E00F4F92B /* DatabaseValueConvertible.swift in Sources */,
564CE4D621B2DEB600652B19 /* CompactMap.swift in Sources */,
56A8C2301D1914540096E9D4 /* UUID.swift in Sources */,
56DF37AB23D77AB4009AAA05 /* KeyPathRefining.swift in Sources */,
56CEB5011EAA2F4D00BFAF62 /* FTS4.swift in Sources */,
56AE64122229A53700AD1B0B /* HasOneThroughAssociation.swift in Sources */,
56CEB55A1EAA359A00BFAF62 /* SQLOrdering.swift in Sources */,
Expand Down
10 changes: 3 additions & 7 deletions GRDB/Core/DatabaseValueConversion.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SQLite3
// MARK: - Conversion Context and Errors

/// A type that helps the user understanding value conversion errors
struct ValueConversionContext {
struct ValueConversionContext: KeyPathRefining {
private enum Column {
case columnIndex(Int)
case columnName(String)
Expand All @@ -21,15 +21,11 @@ struct ValueConversionContext {
private var column: Column?

func atColumn(_ columnIndex: Int) -> ValueConversionContext {
var result = self
result.column = .columnIndex(columnIndex)
return result
return with(\.column, .columnIndex(columnIndex))
}

func atColumn(_ columnName: String) -> ValueConversionContext {
var result = self
result.column = .columnName(columnName)
return result
return with(\.column, .columnName(columnName))
}

var columnIndex: Int? {
Expand Down
6 changes: 3 additions & 3 deletions GRDB/Core/SQLLiteral.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ public struct SQLLiteral {

/// Returns a literal whose SQL is transformed by the given closure.
public func mapSQL(_ transform: (String) throws -> String) rethrows -> SQLLiteral {
var result = self
result.sql = try transform(sql)
return result
return try map(\.sql, transform)
}
}

extension SQLLiteral: KeyPathRefining { }

extension SQLLiteral {
/// Returns the SQLLiteral produced by the concatenation of two literals.
///
Expand Down
2 changes: 1 addition & 1 deletion GRDB/QueryInterface/Request/Association/Association.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ extension Association {

extension Association {
private func mapDestinationRelation(_ transform: (SQLRelation) -> SQLRelation) -> Self {
return .init(sqlAssociation: sqlAssociation.mapDestinationRelation(transform))
return .init(sqlAssociation: sqlAssociation.map(\.destination.relation, transform))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public struct AssociationAggregate<RowDecoder> {
}
}

extension AssociationAggregate {
extension AssociationAggregate: KeyPathRefining {
/// Returns an aggregate that is selected in a column with the given name.
///
/// For example:
Expand All @@ -95,9 +95,7 @@ extension AssociationAggregate {
/// let numberOfBooks: Int = row["numberOfBooks"]
/// }
public func forKey(_ key: String) -> AssociationAggregate<RowDecoder> {
var aggregate = self
aggregate.key = key
return aggregate
return with(\.key, key)
}

/// Returns an aggregate that is selected in a column named like the given
Expand Down
49 changes: 21 additions & 28 deletions GRDB/QueryInterface/Request/QueryInterfaceRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ extension QueryInterfaceRequest: FetchRequest {
let pivotColumns = pivotMappings.map { $0.right }
let pivotAlias = TableAlias()
let prefetchedRelation = association
.mapPivotRelation { $0.qualified(with: pivotAlias) }
.map(\.pivot.relation, { $0.qualified(with: pivotAlias) })
.destinationRelation(fromOriginRows: { _ in [] /* no origin row */ })
.annotated(with: pivotColumns.map { pivotAlias[Column($0)].forKey("grdb_\($0)") })
let prefetchedQuery = SQLQuery(relation: prefetchedRelation)
Expand Down Expand Up @@ -132,7 +132,7 @@ extension QueryInterfaceRequest: SelectionRequest {
/// .select([Column("id")])
/// .select([Column("email")])
public func select(_ selection: [SQLSelectable]) -> QueryInterfaceRequest {
return mapQuery { $0.select(selection) }
return map(\.query, { $0.select(selection) })
}

/// Creates a request which selects *selection*, and fetches values of
Expand All @@ -146,7 +146,7 @@ extension QueryInterfaceRequest: SelectionRequest {
public func select<RowDecoder>(_ selection: [SQLSelectable], as type: RowDecoder.Type = RowDecoder.self)
-> QueryInterfaceRequest<RowDecoder>
{
return mapQuery { $0.select(selection) }.asRequest(of: RowDecoder.self)
return map(\.query, { $0.select(selection) }).asRequest(of: RowDecoder.self)
}

/// Creates a request which selects *selection*, and fetches values of
Expand Down Expand Up @@ -223,7 +223,7 @@ extension QueryInterfaceRequest: SelectionRequest {
/// .select([Column("id"), Column("email")])
/// .annotated(with: [Column("name")])
public func annotated(with selection: [SQLSelectable]) -> QueryInterfaceRequest {
return mapQuery { $0.annotated(with: selection) }
return map(\.query, { $0.annotated(with: selection) })
}
}

Expand All @@ -237,7 +237,7 @@ extension QueryInterfaceRequest: FilteredRequest {
/// var request = Player.all()
/// request = request.filter { db in true }
public func filter(_ predicate: @escaping (Database) throws -> SQLExpressible) -> QueryInterfaceRequest {
return mapQuery { $0.filter(predicate) }
return map(\.query, { $0.filter(predicate) })
}
}

Expand All @@ -258,7 +258,7 @@ extension QueryInterfaceRequest: OrderedRequest {
/// .reversed()
/// .order{ _ in [Column("name")] }
public func order(_ orderings: @escaping (Database) throws -> [SQLOrderingTerm]) -> QueryInterfaceRequest {
return mapQuery { $0.order(orderings) }
return map(\.query, { $0.order(orderings) })
}

/// Creates a request that reverses applied orderings.
Expand All @@ -273,7 +273,7 @@ extension QueryInterfaceRequest: OrderedRequest {
/// var request = Player.all()
/// request = request.reversed()
public func reversed() -> QueryInterfaceRequest {
return mapQuery { $0.reversed() }
return map(\.query, { $0.reversed() })
}

/// Creates a request without any ordering.
Expand All @@ -282,7 +282,7 @@ extension QueryInterfaceRequest: OrderedRequest {
/// var request = Player.all().order(Column("name"))
/// request = request.unordered()
public func unordered() -> QueryInterfaceRequest {
return mapQuery { $0.unordered() }
return map(\.query, { $0.unordered() })
}
}

Expand All @@ -291,46 +291,46 @@ extension QueryInterfaceRequest: AggregatingRequest {

/// Creates a request grouped according to *expressions promise*.
public func group(_ expressions: @escaping (Database) throws -> [SQLExpressible]) -> QueryInterfaceRequest {
return mapQuery { $0.group(expressions) }
return map(\.query, { $0.group(expressions) })
}

/// Creates a request with the provided *predicate* added to the
/// eventual set of already applied predicates.
public func having(_ predicate: SQLExpressible) -> QueryInterfaceRequest {
return mapQuery { $0.having(predicate) }
return map(\.query, { $0.having(predicate) })
}
}

extension QueryInterfaceRequest: _JoinableRequest {
/// :nodoc:
public func _including(all association: SQLAssociation) -> QueryInterfaceRequest {
return mapQuery { $0._including(all: association) }
return map(\.query, { $0._including(all: association) })
}

/// :nodoc:
public func _including(optional association: SQLAssociation) -> QueryInterfaceRequest {
return mapQuery { $0._including(optional: association) }
return map(\.query, { $0._including(optional: association) })
}

/// :nodoc:
public func _including(required association: SQLAssociation) -> QueryInterfaceRequest {
return mapQuery { $0._including(required: association) }
return map(\.query, { $0._including(required: association) })
}

/// :nodoc:
public func _joining(optional association: SQLAssociation) -> QueryInterfaceRequest {
return mapQuery { $0._joining(optional: association) }
return map(\.query, { $0._joining(optional: association) })
}

/// :nodoc:
public func _joining(required association: SQLAssociation) -> QueryInterfaceRequest {
return mapQuery { $0._joining(required: association) }
return map(\.query, { $0._joining(required: association) })
}
}

extension QueryInterfaceRequest: JoinableRequest where T: TableRecord { }

extension QueryInterfaceRequest {
extension QueryInterfaceRequest: KeyPathRefining {

// MARK: Request Derivation

Expand All @@ -344,7 +344,7 @@ extension QueryInterfaceRequest {
/// var request = Player.select(Column("name"))
/// request = request.distinct()
public func distinct() -> QueryInterfaceRequest {
return mapQuery { $0.distinct() }
return map(\.query, { $0.distinct() })
}

/// Creates a request which expects a single result.
Expand All @@ -355,7 +355,7 @@ extension QueryInterfaceRequest {
///
/// :nodoc:
public func expectingSingleResult() -> QueryInterfaceRequest {
return mapQuery { $0.expectingSingleResult() }
return map(\.query, { $0.expectingSingleResult() })
}


Expand All @@ -367,7 +367,7 @@ extension QueryInterfaceRequest {
///
/// Any previous limit is replaced.
public func limit(_ limit: Int, offset: Int? = nil) -> QueryInterfaceRequest {
return mapQuery { $0.limit(limit, offset: offset) }
return map(\.query, { $0.limit(limit, offset: offset) })
}

/// Creates a request that allows you to define expressions that target
Expand All @@ -388,7 +388,7 @@ extension QueryInterfaceRequest {
/// .aliased(playerAlias)
/// .including(required: Player.team.filter(Column("avgScore") < playerAlias[Column("score")])
public func aliased(_ alias: TableAlias) -> QueryInterfaceRequest {
return mapQuery { $0.qualified(with: alias) }
return map(\.query, { $0.qualified(with: alias) })
}

/// Creates a request bound to type Target.
Expand All @@ -407,13 +407,6 @@ extension QueryInterfaceRequest {
public func asRequest<RowDecoder>(of type: RowDecoder.Type) -> QueryInterfaceRequest<RowDecoder> {
return QueryInterfaceRequest<RowDecoder>(query: query)
}

/// Returns a request whose query is transformed by the given closure.
func mapQuery(_ transform: (SQLQuery) -> SQLQuery) -> QueryInterfaceRequest {
var request = self
request.query = transform(query)
return request
}
}

extension QueryInterfaceRequest {
Expand Down Expand Up @@ -585,7 +578,7 @@ private func prefetch(_ db: Database, associations: [SQLAssociation], in rows: [
let pivotColumns = pivotMappings.map { $0.right }
let pivotAlias = TableAlias()
let prefetchedRelation = association
.mapPivotRelation { $0.qualified(with: pivotAlias) }
.map(\.pivot.relation, { $0.qualified(with: pivotAlias) })
.destinationRelation(fromOriginRows: { _ in rows })
.annotated(with: pivotColumns.map { pivotAlias[Column($0)].forKey("grdb_\($0)") })
prefetchedRows = try QueryInterfaceRequest(relation: prefetchedRelation)
Expand Down
Loading

0 comments on commit 349e34b

Please sign in to comment.