From 8d0dc799f82c7ec433e73c183dbbc8d3797a296e Mon Sep 17 00:00:00 2001 From: Daniel Leping Date: Sun, 26 Mar 2017 17:10:51 +0300 Subject: [PATCH] upsert --- Sources/Demo/main.swift | 16 ++++++++++++--- Sources/Swirl/Query.swift | 6 +++--- Sources/Swirl/SwirlOperation.swift | 32 +++++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/Sources/Demo/main.swift b/Sources/Demo/main.swift index 69adafd..d0b7dff 100644 --- a/Sources/Demo/main.swift +++ b/Sources/Demo/main.swift @@ -173,9 +173,19 @@ let comments = Comments() print("Inserted shit:", ressult) }*/ -comments.filter { c in - c.comment == "WTF" -}.delete.execute(in: swirl).onComplete { res in +let q = comments.map { c in + (c.personId, c.comment) +} + +let ins = q.filter { pid, comment in + comment == "WTF" +} ?+= (5, "OK") + +let upd = q.filter { pid, comment in + comment == "WTF1" +} ?+= (5, "WTF-MOD") + +swirl.execute([ins, upd]).onComplete { res in print(res) } diff --git a/Sources/Swirl/Query.swift b/Sources/Swirl/Query.swift index 271088e..d8b330b 100644 --- a/Sources/Swirl/Query.swift +++ b/Sources/Swirl/Query.swift @@ -38,7 +38,7 @@ extension QueryLike { } extension QueryLike where Ret.Value : EntityLike, DS : Table { - func insert(item: Ret.Value.Bind) -> Renderlet { + func insertlet(item: Ret.Value.Bind) -> Renderlet { let q = self.query let rep = Ret.Value.unbind(bound: item).rep() return { dialect in @@ -46,7 +46,7 @@ extension QueryLike where Ret.Value : EntityLike, DS : Table { } } - func insert(items: [Ret.Value.Bind]) -> Renderlet { + func insertlet(items: [Ret.Value.Bind]) -> Renderlet { let q = self.query let reps = items.map(Ret.Value.unbind).map{$0.rep()} return { dialect in @@ -54,7 +54,7 @@ extension QueryLike where Ret.Value : EntityLike, DS : Table { } } - func update(with values: Ret.Value.Bind) -> Renderlet { + func updatelet(with values: Ret.Value.Bind) -> Renderlet { let q = self.query let rep = Ret.Value.unbind(bound: values).rep() return { dialect in diff --git a/Sources/Swirl/SwirlOperation.swift b/Sources/Swirl/SwirlOperation.swift index e716e28..a9b348e 100644 --- a/Sources/Swirl/SwirlOperation.swift +++ b/Sources/Swirl/SwirlOperation.swift @@ -105,6 +105,11 @@ public extension QueryLike where Ret.Value : EntityLike { infix operator ++= : AssignmentPrecedence infix operator ?= : AssignmentPrecedence +infix operator ?+= : AssignmentPrecedence + +private enum UpsertException : Error { + case notUpdated +} public extension QueryLike where Ret.Value : EntityLike, DS : Table { private static func count(from: F, swirl: Swirl) -> Future where F.Value == ResultSet? { @@ -133,15 +138,15 @@ public extension QueryLike where Ret.Value : EntityLike, DS : Table { } public func insert(item: Ret.Value.Bind) -> SwirlOperation { - return insert(renderlet: self.insert(item: item)) + return insert(renderlet: insertlet(item: item)) } public func insert(items: [Ret.Value.Bind]) -> SwirlOperation { - return insert(renderlet: self.insert(items: items)) + return insert(renderlet: insertlet(items: items)) } public func update(with values: Ret.Value.Bind) -> SwirlOperation { - let renderlet: Renderlet = self.update(with: values) + let renderlet = updatelet(with: values) return SwirlOperation { swirl in Self.count(from: swirl.execute(renderlet: renderlet), swirl: swirl) } @@ -154,6 +159,23 @@ public extension QueryLike where Ret.Value : EntityLike, DS : Table { } } + public func upsert(item: Ret.Value.Bind) -> SwirlOperation { + let updatelet = self.updatelet(with: item) + + return SwirlOperation { swirl in + swirl.sequencial.flatMap { swirl in + Self.count(from: swirl.execute(renderlet: updatelet), swirl: swirl).map { count in + if count > 0 { + return count + } + throw UpsertException.notUpdated + }.recoverWith { (e:UpsertException) in + self.insert(item: item).execute(in: swirl) + } + } + } + } + public static func +=(q:Self, item: Ret.Value.Bind) -> SwirlOperation { return q.insert(item: item) } @@ -166,4 +188,8 @@ public extension QueryLike where Ret.Value : EntityLike, DS : Table { public static func ?=(q:Self, item: Ret.Value.Bind) -> SwirlOperation { return q.update(with: item) } + + public static func ?+=(q:Self, item: Ret.Value.Bind) -> SwirlOperation { + return q.upsert(item: item) + } }