prisma1-upgrade icon indicating copy to clipboard operation
prisma1-upgrade copied to clipboard

Prisma upgrade CLI produces invalid schema

Open henryson opened this issue 4 years ago • 10 comments

First, there are duplicate fields inserted to the schema:

image

When I remove or comment one of the duplicates, I get an error like below:

image

These errors appear all over my pretty big schema. Should I remove each @map that was added?

I also get errors on the index that looks wrong:

image

The application field seems to exist, and even if I remove the map (that causes error) the problem remains.

henryson avatar Oct 20 '20 15:10 henryson

I can only comment on a tiny part here: application in the last screenshot is not a scalar field, but a relation field and thus can not be used in an index. You should be able to use applicationId in the index (after removing the @maps).

That of course should not happen really.

Can you share (part of) your schema so we can try to understand what is happening here?

janpio avatar Oct 20 '20 17:10 janpio

When I first run introspect the schema looks fine without errors.

image

Then I run prisma upgrade and after executing the first SQL statements I proceed with breaking changes. It gives me no SQL statements to run. See image.

image

Then I proceed to the last step and see this:

image

When I run it and comment out duplicates the whole schema get heaps of errors like this:

image

I guess that after adding 'applicationId' the upgrade tool should update the index with applicationId instead of application? Here are the errors for the Document model:

  • Error validating model "Document": The index definition refers to the relation fields application. Index definitions must reference only scalar fields. Did you mean @@index([application])?
  • Error validating model "Document": The index definition refers to the unknown fields company.
  • Error validating model "Document": The index definition refers to the relation fields file. Index definitions must reference only scalar fields. Did you mean @@index([file])?
  • Error validating model "Document": The index definition refers to the relation fields recruitment. Index definitions must reference only scalar fields. Did you mean @@index([recruitment])?

@janpio Is that enough part of the schema? Do you want me to add more models?

Note that these changes are all made by the upgrade tool, not by me (except from removing 3 duplicate fields)

henryson avatar Oct 21 '20 09:10 henryson

This seems to be a bug with the Upgrade CLI indeed.

I believe you should be ab le to fix it by manually adjusting the indices from @@index([application]) to @@index([applicationId]), from @@index([company]) to @@index([companyId]), etc

Can you try this manual fix and lets us know if that solves the issue?

nikolasburk avatar Oct 22 '20 09:10 nikolasburk

I did go through the entire file, and it looked good until I fixed the last one, then the whole schema went red again. Now it looks like this:

image

Should the relation fields also be updated with Id?

henryson avatar Oct 22 '20 09:10 henryson

Ah, you probably need to go through a similar process with the fields: [] argument inside the @relation attribute, i.e. change @relation(fields: [application]), references: [id]) to @relation(fields: [applicationId]), references: [id]), @relation(fields: [company]), references: [id]) to @relation(fields: [companyId]), references: [id]), etc.

Sorry for the inconvenience here! 🙏 If you want to understand more about what is actually going on, I'd recommend reading the section about "relation fields" and "relation scalar fields" in the docs here: https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-schema/relations#terminology

nikolasburk avatar Oct 22 '20 11:10 nikolasburk

I have now updated those files and corrected som relation names etc. I get no more validation errors which is fine. But I don't trust the schema to be complete or correct, nor the database. Since I got no more SQL statements from the upgrade tool, there might be more things that needs to be altered. For example, no json fields where updated in the schema. I guess I have to read through the upgrade tutorial thoroughly and apply each step manually. Please let me know if/when there will be a new release of the tool. Thank you for your support!

henryson avatar Oct 22 '20 12:10 henryson

@nikolasburk any news on this? Has this been fixed in the latest Upgrade CLI?

henryson avatar Jan 04 '21 08:01 henryson

Hey @henryson, there's no additional plans to make the upgrade process fully-automated. It's just too hard to cover all the edge cases. For many real-world schemas you'll need to make some tweaks by hand.

If there are no more SQL statements to apply, you should be upgraded. Is there a specific problem you've run into recently?

matthewmueller avatar Jan 04 '21 08:01 matthewmueller

@matthewmueller thank you for a quick response! I had a look on migration a while back when I had no other projects to work on. I got stuck after my post above (Oct 22) but I can't really recall exactly what the problem was. I posted again to check if there was a new version that could help me out when I dive into this again. But then I know that I have to solve it by hand.

henryson avatar Jan 04 '21 09:01 henryson

It's a bit of a cop-out to call this an edge case, I think. I notice in the code

  // Lastly, we'll try to rename relationships
  for (let p1Model of models) {
    // find the corresponding p2 model
    for (let p2Model of prisma2.models) {
      if (p2Model.name !== p1Model.dbname) {
        continue
      }
      for (let p2Field of p2Model.fields) {
        if (!p2Field.type.isReference()) {
          continue
        }
        for (let p1Field of p1Model.fields) {
          if (!p1Field.type.isReference()) {
            continue
          }
          if (p2Field.type.innermost().toString() === p1Field.type.named()) {
            // look for any conflicts
            for (let p2Field of p2Model.fields) {
              if (p1Field.name === p2Field.name) {
                p2Field.rename(p2Field.name + "Id");
                break
              }
            }
            p2Field.setName(p1Field.name);
            break;
          }
        }
      }
    }
  }

It seems pretty clear that p2Field.setName(p1Field.name); will always select the first field in the Prisma 1 model with the same type as the Prisma 2 field in question. This is a pretty weak heuristic when there are other reasonable checks that could be made:

  • Select the field with the same type only if there is one matching, otherwise
  • Look at the @relation for fields. If there is one and it matches a Prisma 1 field, pick that one
  • Since introspection often generates fields of the form [Prisma1FieldType]_[Prisma1Model]_[Prisma1FieldName], check if the name of the Prisma 2 field matches this pattern and if the ending matches a Prisma 1 field. Similar approach for the @relation name

Lastly... don't rename fields for which you can't find matches.

mattkindy avatar May 26 '22 00:05 mattkindy