Skip to content

Instantly share code, notes, and snippets.

@dehlen
Last active January 28, 2019 18:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dehlen/d31fa9cba65e026d338265e22c9576e9 to your computer and use it in GitHub Desktop.
Save dehlen/d31fa9cba65e026d338265e22c9576e9 to your computer and use it in GitHub Desktop.
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