Skip to content

Commit

Permalink
Merge pull request #162 from vapor/tn-beta-5
Browse files Browse the repository at this point in the history
FluentKit Beta 5
  • Loading branch information
tanner0101 authored Feb 25, 2020
2 parents 16a462c + eb5ce7b commit c70bdc6
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 202 deletions.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ let package = Package(
.library(name: "FluentMySQLDriver", targets: ["FluentMySQLDriver"]),
],
dependencies: [
.package(url: "https://github.com/vapor/fluent-kit.git", from: "1.0.0-beta.2"),
.package(url: "https://github.com/vapor/fluent-kit.git", from: "1.0.0-beta.5"),
.package(url: "https://github.com/vapor/mysql-kit.git", from: "4.0.0-beta.2"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
],
Expand Down
46 changes: 33 additions & 13 deletions Sources/FluentMySQLDriver/FluentMySQLDatabase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,29 @@ struct _FluentMySQLDatabase {
}

extension _FluentMySQLDatabase: Database {
func execute(query: DatabaseQuery, onRow: @escaping (DatabaseRow) -> ()) -> EventLoopFuture<Void> {
func execute(
query: DatabaseQuery,
onOutput: @escaping (DatabaseOutput) -> ()
) -> EventLoopFuture<Void> {
let expression = SQLQueryConverter(delegate: MySQLConverterDelegate())
.convert(query)
let (sql, binds) = self.serialize(expression)
do {
return try self.query(sql, binds.map { try MySQLDataEncoder().encode($0) }, onRow: onRow, onMetadata: { metadata in
switch query.action {
case .create:
onRow(LastInsertRow(idKey: query.idKey, metadata: metadata))
default:
break
return try self.query(
sql, binds.map { try MySQLDataEncoder().encode($0) },
onRow: { row in
onOutput(row.databaseOutput())
},
onMetadata: { metadata in
switch query.action {
case .create:
let row = LastInsertRow(
metadata: metadata,
customIDKey: query.customIDKey
)
onOutput(row)
default:
break
}
})
} catch {
Expand All @@ -39,6 +51,10 @@ extension _FluentMySQLDatabase: Database {
}
}

func execute(enum: DatabaseEnum) -> EventLoopFuture<Void> {
self.eventLoop.makeSucceededFuture(())
}

func transaction<T>(_ closure: @escaping (Database) -> EventLoopFuture<T>) -> EventLoopFuture<T> {
self.database.withConnection { conn in
conn.simpleQuery("START TRANSACTION").flatMap { _ in
Expand Down Expand Up @@ -86,22 +102,26 @@ extension _FluentMySQLDatabase: MySQLDatabase {
}
}

private struct LastInsertRow: DatabaseRow {
private struct LastInsertRow: DatabaseOutput {
var description: String {
"\(self.metadata)"
}

let idKey: String
let metadata: MySQLQueryMetadata
let customIDKey: FieldKey?

func schema(_ schema: String) -> DatabaseOutput {
self
}

func contains(field: String) -> Bool {
field == self.idKey
func contains(_ field: FieldKey) -> Bool {
field == .id || field == self.customIDKey
}

func decode<T>(field: String, as type: T.Type, for database: Database) throws -> T
func decode<T>(_ field: FieldKey, as type: T.Type) throws -> T
where T: Decodable
{
guard field == self.idKey else {
guard field == .id || field == self.customIDKey else {
fatalError("Cannot decode field from last insert row: \(field).")
}
if let lastInsertIDInitializable = T.self as? LastInsertIDInitializable.Type {
Expand Down
38 changes: 26 additions & 12 deletions Sources/FluentMySQLDriver/FluentMySQLDriver.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import AsyncKit

extension DatabaseDriverFactory {
extension DatabaseConfigurationFactory {
public static func mysql(
url: URL,
maxConnectionsPerEventLoop: Int = 1
) throws -> DatabaseDriverFactory {
) throws -> Self {
guard let configuration = MySQLConfiguration(url: url) else {
throw FluentMySQLError.invalidURL(url)
}
Expand All @@ -22,7 +22,7 @@ extension DatabaseDriverFactory {
database: String? = nil,
tlsConfiguration: TLSConfiguration? = .forClient(),
maxConnectionsPerEventLoop: Int = 1
) -> DatabaseDriverFactory {
) -> Self {
return .mysql(
configuration: .init(
hostname: hostname,
Expand All @@ -39,21 +39,35 @@ extension DatabaseDriverFactory {
public static func mysql(
configuration: MySQLConfiguration,
maxConnectionsPerEventLoop: Int = 1
) -> DatabaseDriverFactory {
return DatabaseDriverFactory { databases in
let db = MySQLConnectionSource(
configuration: configuration
)
let pool = EventLoopGroupConnectionPool(
source: db,
) -> Self {
return Self {
FluentMySQLConfiguration(
configuration: configuration,
maxConnectionsPerEventLoop: maxConnectionsPerEventLoop,
on: databases.eventLoopGroup
middleware: []
)
return _FluentMySQLDriver(pool: pool)
}
}
}

struct FluentMySQLConfiguration: DatabaseConfiguration {
let configuration: MySQLConfiguration
let maxConnectionsPerEventLoop: Int
var middleware: [AnyModelMiddleware]

func makeDriver(for databases: Databases) -> DatabaseDriver {
let db = MySQLConnectionSource(
configuration: configuration
)
let pool = EventLoopGroupConnectionPool(
source: db,
maxConnectionsPerEventLoop: maxConnectionsPerEventLoop,
on: databases.eventLoopGroup
)
return _FluentMySQLDriver(pool: pool)
}
}

enum FluentMySQLError: Error {
case invalidURL(URL)
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/FluentMySQLDriver/MySQLConverterDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ struct MySQLConverterDelegate: SQLConverterDelegate {
}

func nestedFieldExpression(_ column: String, _ path: [String]) -> SQLExpression {
return SQLRaw("JSON_EXTRACT(\(column), '$.\(path[0])')")
let path = path.joined(separator: ".")
return SQLRaw("JSON_EXTRACT(\(column), '$.\(path)')")
}
}
41 changes: 36 additions & 5 deletions Sources/FluentMySQLDriver/MySQLRow+Database.swift
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
extension MySQLRow: DatabaseRow {
public func contains(field: String) -> Bool {
return self.column(field) != nil
extension MySQLRow {
internal func databaseOutput() -> DatabaseOutput {
_MySQLDatabaseOutput(row: self, schema: nil)
}
}

private struct _MySQLDatabaseOutput: DatabaseOutput {
let row: MySQLRow
let schema: String?

var description: String {
self.row.description
}

func contains(_ field: FieldKey) -> Bool {
return self.row.column(self.column(field)) != nil
}

func schema(_ schema: String) -> DatabaseOutput {
_MySQLDatabaseOutput(
row: self.row,
schema: schema
)
}

func decode<T>(
_ field: FieldKey,
as type: T.Type
) throws -> T where T : Decodable {
try self.row.decode(column: self.column(field), as: T.self)
}

public func decode<T>(field: String, as type: T.Type, for database: Database) throws -> T where T : Decodable {
return try self.decode(column: field, as: T.self)
private func column(_ field: FieldKey) -> String {
if let schema = self.schema {
return schema + "_" + field.description
} else {
return field.description
}
}
}
Loading

0 comments on commit c70bdc6

Please sign in to comment.