Prisma1: Nested mutations inside UpdateMany are not applied

Created on 3 Mar 2018  ·  19Comments  ·  Source: prisma/prisma1

Bug Report

Current behavior

Using connect inside an UpdateMany mutation call returns the error:
"message": "Whoops. Looks like an internal server error. Search your cluster logs for request ID: api:api:cjeb19t3f00310150uqe2ihuo",

from cluster logs:

{"key":"error/unhandled","requestId":"api:api:cjeb19t3f00310150uqe2ihuo","clientId":"blaze-service@dev","payload":{"exception":"java.lang.IllegalArgumentException: Unsupported scalar value in SlickExtensions: Some(ListMap(connect -> Some(ListMap(username -> Some(ragzor)))))","query":"mutation updateManyTasks {\n updateManyTasks(where: {id_in: [\"cjead1ixy00x40150yejblrai\", \"cjeadhukt00xz0150zxrbcq7f\"]}, data: {status: RECCE, recceUser: {connect: {username: \"ragzor\"}}}) {\n count\n }\n}\n","variables":"{}","code":"0",

Reproduction
Run the following mutation

mutation updateManyTasks {
updateManyTasks(
where: {
  id_in: ["cjead1ixy00x40150yejblrai","cjeadhukt00xz0150zxrbcq7f"]
},
data: {
  user: {
    connect: {
      username: "ragzor"
    }
  }
    },
  ) {
count
  }
}

Schema defined as:

type User {
  createdAt: DateTime!
  id: ID! @unique
  username: String! @unique
  password: String!
  name: String!
  role: Role! @default(value: "UNREGISTERED")
  tasks: [Task!]!
}
type Task {
  id: ID! @unique
  store: Store!
  status: Status!
  user: User
  createdAt: DateTime! # Start/Receive Date
}

It works perfectly while running a single mutation like so:

mutation updateTask {
  updateTask(
where: {
  id: "cjead1ixy00x40150yejblrai"
},
data: {
   user: {
    connect: {
      username: "ragzor"
    }
  }
    },
  ) {
id
  }
}

Expected behavior?

All items should be updated and connected to the user as expected

bu2-confirmed areengine

Most helpful comment

In my case, update mutation run successfully. No error thrown. Number of nodes affected is valid. But data not updated.

All 19 comments

Hey, thanks for reporting this. This should not throw an internal. But the initial implementation of updateMany is also not supposed to support nested mutations as per https://github.com/graphcool/prisma/issues/81.

We'll have a look at the thrown error.

Just ran aground of this as well, is there an intent to show these routes as inaccessible in the playground as well? currently it shows nested mutations as possible (which, given the programmatic nature of the docs generation, may point to the root of the issue)

I don't exactly understand your comment @Aubron, could you elaborate? :slightly_smiling_face:

screen shot 2018-03-08 at 5 49 21 pm

The updateMany system still shows nested operations as valid in the playground, leading to frustration for those who don't know about #81's spec.

After thinking about it for a bit, I'm fairly certain that programmatically hiding this is not an easy possibility, since that's just the descriptor of the generic {Thing}UpdateOneWithoutChildrenInput, which can be used properly when not nested.

Adjacent thought, while there are still a lot of quirks in the system, maybe some notices on the data types in playground that point to these kinds of issues?

If you're following, a lot of frustration this afternoon would have been avoided if either {Thing}UpdateOneWithoutChildrenInput or (probably more appropriately) updateMany{Thing}s's auto-generated playground page had footnotes linking to issues like #81 that document the quirks.

Nested mutations of updateMany mutations are not currently supported. See the spec for more information.

Those kinds of notes as footnotes in the playground would probably defer a lot of the incoming issues.

I just wanted to toss my vote behind this issue because it makes updating databases difficult to manage, especially when types change. For instance, I just changed a tag name type and needed to recreate tags for 200 entries, but it looks like I'll need to make a script to do it one at a time.

Bumping this thread - I just wasted 30 minutes trying to figure this out - would love it if the server could throw an exception for anything like this that's not implemented instead of returning successful result.

In my case, update mutation run successfully. No error thrown. Number of nodes affected is valid. But data not updated.

@chitswe experiencing the same issue with nested create mutation inside an updateMany batch mutation

@chitswe Same.

@troysandal I spent like three hours 🤣.

This at least has to throw an exception.

I agree wholeheartedly with @cesaraaron, the fact that no error is thrown and the publicly-exposed API makes it look like nested mutations would work is both frustrating and confusing. My team assumed that functionality worked, and when we realized it didn't, it was multiple hours of debugging to figure out the issue was with Prisma.

Any updates on this issue?

Same result using prisma bindings, appears successful but no data is updated/upserted in the database:

        const updatedPlayers = await ctx.db.mutation.updateManyPlayers(
          {
            where: { lastName: 'Brady' },
            data: {
              stats: {
                upsert: {
                  create: {
                    gamesPlayed: 8,
                    passing: {
                      create: {
                        passAttempts: 0,
                        passCompletions: 0,
                        passPct: 0.0,
                      },
                    },
                  },
                  update: { gamesPlayed: 8 },
                },
              },
            },
          },
          `{ count }`
        );
        console.log(`Updated ${updatedPlayers.count} player(s)`);

Hey,
since we did some refactoring to the way we handle nested mutations I think there is no more technical reason preventing us from nested mutations in updateMany. But this is a change that can have heavy performance impacts. Additionally we would like to make sure that we do not run into deadlock issues with it.

Unfortunately we do not have the capacity to look into these potential problems at the moment. We'll therefore remove these from the API until we have the time to implement them to avoid confusion.

I could hack this :) I'm not sure if you'd like my solution but I'll post here anyway.

async updateTasks(parent, { tasks }, ctx, info) {
  // tasks is an array ["task_id_1", "task_id_2"]
  const updatedTasks = await Promise.all(
    tasks.map(async taskId => {
      return await ctx.db.mutation.updateTask({
        where: {
          id: taskId
        },
        data: {
          connect: {
            username: "your_username"
          }
        }
      }, info);
    });
  )

  console.log("Update: ", updatedTasks.length, " tasks");
}

And this behavior is not even documented anywhere ... To the contrary, the auto generated graphQL types for the mutation make you believe this is supposed to work (otherwise why would they be in the API?!) 🤦‍♂️

After having discovered lots of inconsistencies in the "batch" APIs, which most of the time are not even documented, I am starting to regret our decision to migrate our entire data layer to Prisma.

In this case the documentation should have a full page warning with red text of the largest font size available.

Ah! now it all makes sense :D I agree that the API call should at the very least throw if the requested mutation is not performed ‼️

I will highjack this issue to ask: given this problem with the bindings, should I add IDs to types that don't necessarily need to be uniquely identified or is there another workaround for this issue at the moment?

Thanks!

We removed the nested mutations from the generated schema in the case of updateMany to avoid confusion. Details can be found here: https://github.com/prisma/prisma/pull/3374

Where is the progress on allowing nested mutations in updateMany being tracked?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

akoenig picture akoenig  ·  3Comments

schickling picture schickling  ·  3Comments

sorenbs picture sorenbs  ·  3Comments

sedubois picture sedubois  ·  3Comments

nikolasburk picture nikolasburk  ·  3Comments