Last active
January 28, 2019 18:59
-
-
Save dehlen/d31fa9cba65e026d338265e22c9576e9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vapor | |
import Fluent | |
import FluentPostgreSQL | |
extension QueryBuilder | |
where Result: PostgreSQLModel, Result.Database == Database { | |
/// Creates the model or updates it depending on whether a model | |
/// with the same ID already exists. | |
internal func upsert(_ model: Result, | |
columns: [PostgreSQLColumnIdentifier]) -> Future<Result> { | |
var row = SQLQueryEncoder(PostgreSQLExpression.self).encode(model) | |
/// remove id from row if not available | |
/// otherwise the not-null constraint will break | |
row = row.filter { (key, value) -> Bool in | |
if key == "id" && value.isNull { return false } | |
return true | |
} | |
let values = row | |
.map { row -> (PostgreSQLIdentifier, PostgreSQLExpression) in | |
return (.identifier(row.key), row.value) | |
} | |
self.query.upsert = .upsert(columns, values) | |
return create(model) | |
} | |
} | |
extension PostgreSQLModel { | |
/// Creates the model or updates it depending on whether a model | |
/// with the same ID already exists. | |
internal func upsert(on connection: DatabaseConnectable) -> Future<Self> { | |
return Self | |
.query(on: connection) | |
.upsert(self, columns: [.keyPath(Self.idKey)]) | |
} | |
internal func upsert<U>(on connection: DatabaseConnectable, | |
onConflict keyPath: KeyPath<Self, U>) -> Future<Self> { | |
return Self | |
.query(on: connection) | |
.upsert(self, columns: [.keyPath(keyPath)]) | |
} | |
internal func upsert<U, V>(on connection: DatabaseConnectable, | |
onConflict keyPath1: KeyPath<Self, U>, | |
_ keyPath2: KeyPath<Self, V>) -> Future<Self> { | |
return Self | |
.query(on: connection) | |
.upsert(self, columns: [.keyPath(keyPath1), .keyPath(keyPath2)]) | |
} | |
} | |
// Usage: | |
model.upsert(on: req, onConflict: \.someProperty) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment