Skip to content
This repository has been archived by the owner on Sep 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #4793 from prisma/MongoDeleteManyBug
Browse files Browse the repository at this point in the history
Mongo Delete Many Bug
  • Loading branch information
do4gr authored Aug 8, 2019
2 parents cdb8ca6 + 8297d1b commit 9adefc9
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import collection.JavaConverters._

case class CombinedPullDefinition(keys: Vector[String], value: BsonValue)

//Mongo will just silently ignore it if more than one pull is defined for the same field
object CustomUpdateCombiner {

def customCombine(updates: Vector[conversions.Bson]): conversions.Bson = {
Expand All @@ -17,14 +18,19 @@ object CustomUpdateCombiner {
val pulls = rawUpdates.filter(_._1.getFirstKey == "$pull")
val others = rawUpdates.filter(_._1.getFirstKey != "$pull")

val convertedPulls = pulls.map(x => documentToCombinedPullDefinition(x._1))
val groupedPulls: Map[Vector[String], Vector[CombinedPullDefinition]] = convertedPulls.groupBy(_.keys)
if (pulls.length > 1) {

val changedPulls = groupedPulls.map { group =>
bsonDocumentFilter(group._1.toList, BsonArray(group._2.map(_.value)))
}
val convertedPulls: Vector[CombinedPullDefinition] = pulls.map(x => documentToCombinedPullDefinition(x._1))
val groupedPulls: Map[Vector[String], Vector[CombinedPullDefinition]] = convertedPulls.groupBy(_.keys)

val changedPulls = groupedPulls.map { group =>
bsonDocumentFilter(group._1.toList, BsonArray(group._2.map(_.value)))
}

combine(others.map(_._2) ++ changedPulls: _*)
combine(others.map(_._2) ++ changedPulls: _*)
} else {
combine(others.map(_._2) ++ pulls.map(_._2): _*)
}
}

private def removeDuplicates(elements: List[(BsonDocument, Bson)]): List[(BsonDocument, Bson)] = elements match {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,8 @@ trait NodeActions extends NodeSingleQueries {
parent: NodeAddress): (Vector[Bson], Vector[Bson], Vector[DatabaseMutactionResult]) = {
val actionsArrayFiltersAndResults = mutactions.collect {
case deleteNodes @ NestedDeleteNodes(_, _, rf, whereFilter) if rf.relatedModel_!.isEmbedded =>
val deletes = pull(parent.path.stringForField(rf.dbName), buildConditionForScalarFilter("", whereFilter))
val condition = buildConditionForScalarFilter("", whereFilter)
val deletes = pull(parent.path.stringForField(rf.dbName), condition)
val thisResult = ManyNodesResult(deleteNodes, 0)

(Vector(deletes), Vector.empty, Vector(thisResult))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.prisma.api.mutations.embedded

import com.prisma.api.ApiSpecBase
import com.prisma.shared.models.ConnectorCapability.EmbeddedTypesCapability
import com.prisma.shared.models.Project
import com.prisma.shared.schema_dsl.SchemaDsl
import org.scalatest.{FlatSpec, Matchers}

class DeleteManyBugSpec extends FlatSpec with Matchers with ApiSpecBase {
override def runOnlyForCapabilities = Set(EmbeddedTypesCapability)

val schema =
"""type User {
| id: ID! @id
| name: String! @unique
| balances: [Balance!]!
|}
|
|type Balance @embedded {
| currency: String!
| platform: String!
| amount: Float!
|}"""

lazy val project: Project = SchemaDsl.fromStringV11() { schema }

override protected def beforeAll(): Unit = {
super.beforeAll()
database.setup(project)
}

override def beforeEach(): Unit = database.truncateProjectTables(project)

"The delete many Mutation" should "delete the items matching the where relation filter" in {

server.query(
s"""mutation {
| createUser(
| data: {
| name: "user"
| balances: {
| create: [
| {platform: "OnlineWallet", currency: "BTC", amount: 1}
| {platform: "PaperWallet", currency: "BTC", amount: 1}
| {platform: "OnlineWallet", currency: "ETH", amount: 1}
| ]
| }
| }
| ) {
| id
| }
|}
""",
project
)

val res = server.query(
s"""mutation {
| updateUser(
| data: { balances: { deleteMany: { platform: "PaperWallet", currency: "BTC" } } }
| where: { name: "user" }
| ) {
| name
| balances {
| platform
| currency
| }
| }
|}
""",
project
)

res.toString should be(
"""{"data":{"updateUser":{"name":"user","balances":[{"platform":"OnlineWallet","currency":"BTC"},{"platform":"OnlineWallet","currency":"ETH"}]}}}""")

}

}

0 comments on commit 9adefc9

Please sign in to comment.