Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smooth upgrade path from Prisma 1 to Prisma 2.0 #1937

Closed
4 tasks done
nikolasburk opened this issue Mar 26, 2020 · 11 comments
Closed
4 tasks done

Smooth upgrade path from Prisma 1 to Prisma 2.0 #1937

nikolasburk opened this issue Mar 26, 2020 · 11 comments

Comments

@nikolasburk
Copy link
Member

nikolasburk commented Mar 26, 2020

We're planning to have a smooth upgrade path for existing Prisma 1 users.

The plan is to have:

  • extensive documentation on the upgrade process
    • Upgrading a REST API
    • Upgrading a GraphQL API based on nexus-prisma
    • Upgrading a GraphQL API based on prisma-binding to Nexus
    • Upgrading a GraphQL API based on prisma-binding to SDL-first
  • additional tooling that help transforming a Prisma 1 project into a Prisma 2 project
@janpio janpio added this to the Foo 1 milestone Mar 26, 2020
@janpio janpio modified the milestones: Foo 1, Foo 2 Mar 30, 2020
@nikolasburk
Copy link
Member Author

nikolasburk commented Apr 8, 2020

I want to post an update in this issue with some information about the things we are currently working on and some broader context to explain what the friction points during the upgrade process are.

Example

Prisma 1 data model

Assume you have this Prisma 1 datamodel:

type User {
  id: ID! @id
  email: String! @unique
  name: String
  posts: [Post!]!
  profile: Profile
}

type Post {
  id: ID! @id
  createdAt: DateTime! @createdAt
  updatedAt: DateTime! @updatedAt
  published: Boolean! @default(value: false)
  title: String!
  content: String
  author: User!
  categories: [Category!]!
}

type Profile {
  id: ID! @id
  bio: String
  user: User! @relation(link: INLINE)
}

type Category {
  id: ID! @id
  name: String!
  posts: [Post!]!
}

Generated SQL in Prisma 1

When deploying this with prisma1 deploy to a PostgreSQL database, Prisma 1 runs the following SQL statements against the database:

CREATE TABLE default$default."User" (
    id character varying(25) PRIMARY KEY,
    email text NOT NULL,
    name text
);

CREATE UNIQUE INDEX "User_pkey" ON default$default."User"(id text_ops);
CREATE UNIQUE INDEX "default$default.User.email._UNIQUE" ON default$default."User"(email text_ops);

CREATE TABLE default$default."Post" (
    id character varying(25) PRIMARY KEY,
    "createdAt" timestamp(3) without time zone NOT NULL,
    "updatedAt" timestamp(3) without time zone NOT NULL,
    published boolean NOT NULL,
    title text NOT NULL,
    content text,
    author character varying(25) REFERENCES default$default."User"(id) ON DELETE SET NULL
);

CREATE UNIQUE INDEX "Post_pkey" ON default$default."Post"(id text_ops);

CREATE TABLE default$default."Profile" (
    id character varying(25) PRIMARY KEY,
    bio text,
    user character varying(25) REFERENCES default$default."User"(id) ON DELETE SET NULL
);

CREATE UNIQUE INDEX "Profile_pkey" ON default$default."Profile"(id text_ops);

CREATE TABLE default$default."Category" (
    id character varying(25) PRIMARY KEY,
    name text NOT NULL
);

CREATE UNIQUE INDEX "Category_pkey" ON default$default."Category"(id text_ops);

CREATE TABLE default$default."_CategoryToPost" (
    "A" character varying(25) NOT NULL REFERENCES default$default."Category"(id) ON DELETE CASCADE,
    "B" character varying(25) NOT NULL REFERENCES default$default."Post"(id) ON DELETE CASCADE
);

CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON default$default."_CategoryToPost"("A" text_ops,"B" text_ops);
CREATE INDEX "_CategoryToPost_B" ON default$default."_CategoryToPost"("B" text_ops);

Note that this data model has three relations:

  • 1-1: UserProfile
  • 1-n: UserPost
  • m-n: PostCategory

Prisma 2.0 schema after introspection

Now you can run Prisma's introspection against your database with the following command:

npx prisma introspect

For the above Prisma 1 datamodel, this results in the following Prisma 2.0 schema (note that the models and fields have been reorded to match the initial order of the Prisma 1 datamodel):

model User {
  id      String    @id
  email   String    @unique
  name    String?
  Post    Post[]
  Profile Profile[]
}

model Post {
  id        String     @id
  createdAt DateTime
  updatedAt DateTime
  published Boolean
  title     String
  content   String?
  author    String?
  User      User?      @relation(fields: [author], references: [id])
  Category  Category[] @relation(references: [id])
}

model Profile {
  id   String  @id
  bio  String?
  user String?
  User User?   @relation(fields: [user], references: [id])
}

model Category {
  id   String @id
  name String
  Post Post[] @relation(references: [id])
}

As you might notice, the Prisma schema is missing or has adjusted some information from the Prisma 1 datamodel:

  • On the User model:
    • The previous posts relation field has been renamed to Post
    • The previous profile relation field has been renamed to Profile
    • The previous 1-1 relation between User and Profile has been turned into a 1-n relation
  • On the Post model:
    • The createdAt field doesn't have an attribute (previously called directive in Prisma 1)
    • The updatedAt field doesn't have an attribute (previously called directive in Prisma 1)
    • The published field misses a @default attribute
    • The relation to User is now represented with two fields:
      • The type of author is now String and not User
      • The relation field User is now optional and uses the @relation attribute
    • The previous categories relation field has been renamed to Category and uses the @relation attribute
  • On the Profile model:
    • The relation to User is now represented with two fields:
      • The type of user is now String and not User
      • The relation field User is now optional and uses the @relation attribute
  • On the Category model:
    • The previous posts relation field has been renamed to Post and uses the @relation attribute

Also note that that with Prisma 2.0, you alway must explicitly specify @default attributes if you want Prisma to generate IDs for you by default. Since none of the @id fields have @default values at the moment, you would need to supply your own ID values when creating new records with the new Prisma Client!

Fixing the Prisma 2.0 schema

As pointed out above, the Prisma 2.0 schema that was generated from introspection has changed and even misses a lot of information from the previous Prisma 1 datamodel.

The main reason for this is that in Prisma 1, most of these features have been implemented by Prisma and did not actually manifest in the database. For example, @default directives in Prisma 1 were not mapped to DEFAULT constraints in SQL – instead the Prisma server would take care of generating these default values and inserting them into the database at runtime (if you took a look at the SQL schema that was shown in the expandable element above, you probably also noticed that).

Because much of the information from the Prisma 1 datamodel does not manifest in the database schema, it can't be recognized by Prisma's introspection (which is the reason why it doesn't appear in the new Prisma schema).

Note: One major goal of Prisma 2.0 is to provide a cleaner mapping from the Prisma schema to the database. With Prisma 2.0, most of the features from the Prisma schema do manifest in the database, with a few exceptions.

You generally have two ways to resolve many of the resulting issues:

  • Manually adjust your database schema using SQL and re-introspect
  • Adjust your Prisma schema to manually add the missing information

It has previusly been mentioned that we're building additional tooling that helps with the upgrade process. These tools will help you resolve the named issues automatically and will save lots of manual work.

@nikolasburk
Copy link
Member Author

We also just updated the upgrade guide that was previously in this repo to cover the migration path using introspection more extensively, you can find it here.

@windkomo
Copy link

windkomo commented Apr 29, 2020

The migration guide currently details how to migrate from a @relation(link: INLINE), but not a 1-n @relation(link: TABLE) ?

Take a Prisma 1 model that looks like this:

type Profile {
 id: ID! @id
 user: User @relation("UserProfiles")
}

type User {
 id: ID! @id
 profiles: [Profile!] @relation(name: "UserProfiles", link: TABLE)
}

In this case, there is no column in Profile that references User, so I can’t apply something like:

 user      User      @relation("UserProfiles", fields: [userId], references: [id])
 userId    String    @map("User")

Removing the User from Profile works, but then I can’t access a User from a Profile, only a Profile from a User.

This won't work either:

model User {
  id       Int       @default(autoincrement()) @id
  profiles Profile[]
}

model Profile {
  id      Int  @default(autoincrement()) @id
  user    User @relation(fields: [user_id], references: [id])
  user_id Int
}

Prisma 2 will complain Profile.user_id column is missing.

@LeonardoGentile
Copy link

@nikolasburk thanks for the update, we will wait for the migrations docs.
In the meanwhile, since it's not completely clear to me, I wanted to ask if in Prisma 2 prisma-binding and schema delegation would still be supported or will they be dropped?

@divyenduz divyenduz modified the milestones: Beta 4, Beta 5 May 4, 2020
@janpio janpio modified the milestones: Beta 5, Beta 6 May 12, 2020
@nikolasburk
Copy link
Member Author

nikolasburk commented May 12, 2020

Hey everyone, thanks a lot for staying patient 🙏 I want to share another quick update on the state of the upgrade path to Prisma 2.0.

We've just published a new docs page that has a lot of helpful information regarding the upgrade process.

Most importantly, it points out all relevant schema incompatibilies and different workarounds that can be applied. For most of the workarounds, you'll actually be able to use the Prisma schema upgrade CLI tool that we're also working on.

⚠️ The docs page as well as the Prisma schema upgrade CLI tool are still work in progress but we wanted to share an early version to give you an update on what we're working on and get your feedback for it! Please let me know if anything on the docs page needs clarification (feel free to ping me directly on Slack if you have any questions).

As next steps, we will start working on more detailed migration guides for upgrading GraphQL APIs with prisma-binding and nexus. (Side-note for @LeonardoGentile, Prisma 2.0 doesn't support prisma-binding any more. Alternatively you can use a plain SDL-first approach with graphql-tools or use GraphQL Nexus, this will be explained in the upcoming migration guides).

@nikolasburk
Copy link
Member Author

Hey folks 🙌 here comes another update regarding the upgrade process to Prisma 2.0!

First version of an upgrade guide for prisma-binding

We have started working on more upgrade guides, a first one that explains how to upgrade a prisma-binding app to Prisma 2.0 and Nexus is now available as a first version. While the guide already contains a lot of helpful information, it is still _work in progress (that's why it's not yet available in the main Prisma docs, but only as a preview URL).

I would love to get feedback for the prisma-binding guide and learn more about how helpful it is to you! If you're currently running a prisma-binding app and consider upgrading, please get in touch via email for ping me on Slack (I'm @nikolasburk there).

A new repository for dedicated upgrade feedback

I've also created a new repository that should serve as a central place to collect questions and issues about your upgrade process.

If you're currently running Prisma 1 and are planning to upgrade soon, please open an issue there and share some more details about your upgrade scenario.

If you have any other questions or issues, feel free to create a new GitHub issue to raise these.

@nikolasburk
Copy link
Member Author

Aaaand another quick update: There's another preliminary upgrade guide from prisma-binding to an SDL-first approach that you can find here.

@nikolasburk
Copy link
Member Author

Reminder to everyone, please share your upgrade scenario in our new feedback repo 🙏

@nikolasburk
Copy link
Member Author

Hi everyone 🙌 here comes another quick update:

The guides for upgrading prisma-binding apps to Nexus and SDL-first are now available in the docs 🙂 we also published the guide that explains how to upgrade just the "Prisma layer" (including the DB), and it uses the Prisma schema upgrade CLI to resolve a number of the schema incompatibilities.

Note that the upgrade CLI is still in the works. As a general best practice for the upgrade process, you should always ensure to have proper backups of production-data and ideally run the upgrade in development and staging environments first.

Also, a general reminder to everyone to please share your upgrade scenario in our new feedback repo 🙏

@nikolasburk
Copy link
Member Author

Hey Prisma friends 🙌 we just published the guide to upgrade from the "old" to the "new" Nexus.

I'd love to get feedback for these guides! If any of you is planning to upgrade any time soon, feel free to ping me! I'd love to jump on a call with you and learn more about your upgrade scenario and discuss whether the current guides cover it enough! 🙂

As usual, my general reminder to everyone to please share your upgrade scenario in our new feedback repo 🙏

@janpio janpio modified the milestones: Beta 7, Beta 8 May 29, 2020
@janpio janpio removed this from the Beta 10 milestone Sep 11, 2020
@nikolasburk
Copy link
Member Author

I'm closing this issue since we created the Upgrade CLI as well as a bunch of upgrade guides which help developers to smoothly upgrade from Prisma 1 to Prisma 2. If there are still open questions, you can post them in the upgrade feedback repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants