メインコンテンツにスキップ

Prisma ORM レイヤーのアップグレード

概要

このページでは、アップグレードプロセスの最初のステップである、Prisma 1 の構成を Prisma ORM 2 にアップグレードする方法について説明します。具体的には、以下の方法を学びます。

  1. Prisma ORM 2 CLI を開発依存関係として追加する
  2. Prisma ORM 2 スキーマを作成する
  3. 接続 URL を特定し、データベースに接続する
  4. データベース (これまで Prisma 1 で管理していたもの) をイントロスペクトする
  5. Prisma 1 Upgrade CLI を使用して、新しい Prisma ORM 2 データモデルの スキーマの非互換性 を解決する
  6. Prisma Client をインストールして生成する

これらの手順が完了したら、アプリケーションレイヤーをアップグレードしてデータベースクエリに Prisma Client を使用する方法を説明する次のガイドに進むことができます。

注記: アップグレードプロセス中、データベースのグラフィカルビューを取得すると役立つ場合があります。そのため、TablePlusPostico などのグラフィカルデータベースクライアントを使用してデータベースに接続することをお勧めします。

1. Prisma ORM 2 CLI をインストールする

Prisma ORM 2 CLI は、npm の prisma パッケージとして利用でき、prisma コマンドで呼び出されます。

Prisma 1 の以前の prisma コマンドは prisma1 に名前が変更されたことに注意してください。詳細については、こちら を参照してください。

Node.js プロジェクトに Prisma ORM 2 CLI をインストールするには、次のようにします (package.json があるディレクトリでこのコマンドを呼び出すようにしてください)。

npm install prisma --save-dev

注記: Prisma 1 では、CLI をグローバルにインストールすることが通常推奨されていました。現在では、バージョン競合を防ぐために Prisma CLI をローカルにインストールする ことをお勧めします。

npx をプレフィックスとして付けることで、prisma CLI のローカルインストールを使用できるようになりました。

npx prisma

プロジェクト全体を 一度にすべて アップグレードする場合は、Prisma 1 CLI をアンインストールすることもできます (それ以外の場合は下記を展開してください)。

# remove global installation
npm uninstall -g prisma1

# remove local installation
npm uninstall prisma1

Prisma 1 CLI をサイドバイサイドで使用し続けたい場合は展開してください

Prisma 1 CLI を使用し続けたい場合は、グローバルインストールを削除し、prisma1 CLI を開発依存関係として追加することをお勧めします。

# installs v1.34 of the Prisma 1 CLI
npm uninstall -g prisma
npm install prisma1 --save-dev

次のようにして呼び出すことができます。

npx prisma1

1.34 より小さい CLI バージョン (例: 1.30) が必要な場合は、次のようにインストールできます。

# installs v1.30 of the Prisma 1 CLI
npm uninstall -g prisma@1.30
npm install prisma@1.30 --save-dev

次のようにして呼び出すことができます。

npx prisma

2. Prisma ORM 2 スキーマを作成する

このガイドでは、まず prisma init コマンドを使用して新しい Prisma スキーマを作成し、イントロスペクション を使用してデータモデルを「入力」します。

次のコマンドを実行して Prisma スキーマを作成します (prisma という名前のフォルダーが既に存在する場合はエラーがスローされることに注意してください)。

npx prisma init

次のエラーが表示される場合は、現在の prisma ディレクトリの名前を変更する必要があります。

ERROR  A folder called prisma already exists in your project.
Please try again in a project that is not yet using Prisma.

現在の prisma ディレクトリの名前を prisma1 に変更して、これが以前の Prisma 1 構成を保持していることを明確にすることができます。

mv prisma prisma1

これで init を実行すると成功します。

npx prisma init

次の出力が表示されるはずです。

✔ Your Prisma schema was created at prisma/schema.prisma.
You can now open it in your favorite editor.

Next steps:
1. Set the `DATABASE_URL` in the `.env` file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started
2. Set the `provider` of your `datasource` block in `schema.prisma` to match your database: `postgresql`, `mysql` or `sqlite`.
3. Run `prisma db pull` to turn your database schema into a Prisma data model.
4. Run `prisma generate` to install Prisma Client. You can then start querying your database.

More information in our documentation:
https://pris.ly/d/getting-started

コマンドは prisma という名前の新しいフォルダーと 2 つのファイルを作成しました。

初期 Prisma スキーマは次のようになります。

schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

generator client {
provider = "prisma-client-js"
}

Prisma 1 では、prisma.yml で使用する Prisma Client の言語バリアントを指定します。Prisma ORM 2 では、この情報は Prisma スキーマ内の generator ブロックで指定されるようになりました。

注記: Prisma 1 とは異なり、Prisma Client 2.0 の TypeScript および JavaScript バリアントは、prisma-client-js という同じ ジェネレーターを使用します。index.d.ts で生成された型は、プレーンな JavaScript プロジェクトでも常に 含まれています。これにより、TypeScript を使用していない場合でも、VS Code でのオートコンプリートのような機能が有効になります。

3. 接続 URL を特定し、データベースに接続する

Prisma 1 では、データベース接続は、Prisma ORM サーバーを起動するために使用される Docker Compose ファイルで構成されます。次に、Prisma ORM サーバーは、Prisma Client アプリケーションコードからのすべてのデータベースリクエストをプロキシする GraphQL エンドポイント (HTTP 経由) を公開します。その HTTP エンドポイントは prisma.yml で指定されます。

Prisma ORM 2 では、HTTP レイヤーはもう公開されず、Prisma Client 2.0 はデータベースに対して「直接」リクエストを実行するように構成されています (つまり、リクエストは Prisma ORM の クエリエンジン によってプロキシされますが、追加のサーバーはもうありません)。

したがって、次のステップとして、使用するデータベースの種類 (MySQL または PostgreSQL) とその場所を Prisma ORM 2 に伝える必要があります。

まず、schema.prisma 内の datasource ブロックの provider フィールドが正しいデータベースを使用するように構成されていることを確認する必要があります。

  • PostgreSQL を使用している場合は、provider フィールドに値 "postgresql" を定義する必要があります。
  • MySQL を使用している場合は、provider フィールドに値 "mysql" を定義する必要があります。

コードブロックのタブを切り替えて、両方の例を確認してください。

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

provider フィールドを設定したら、.env ファイル内で接続 URL を構成できます。

Prisma ORM サーバーのデプロイに使用した Docker Compose ファイルのデータベース構成が次のようになっていると仮定します。

docker-compose.yml
PRISMA_CONFIG: |
port: 4466
databases:
default:
connector: postgres
host: postgres
port: 5432
user: prisma
password: prisma

また、prisma.ymlendpoint が次のように構成されていると仮定します。

prisma.yml
endpoint: http://#:4466/myproject/dev

これらの接続の詳細に基づいて、.env ファイル内の DATABASE_URL 環境変数を次のように構成する必要があります。

.env
DATABASE_URL="postgresql://janedoe:randompassword@localhost:5432/prisma?schema=myproject$dev"

schema 引数は通常、サービス名サービスステージ (prisma.ymlendpoint の一部) で構成され、$ 文字で区切られていることに注意してください。

サービス名とステージが prisma.yml で指定されていない場合があります。

prisma.yml
endpoint: http://#:4466/

その場合、schema は次のように指定する必要があります。

.env
DATABASE_URL="postgresql://janedoe:randompassword@localhost:5432/prisma?schema=default$default"

詳細については、接続 URL ページを参照してください。

4. データベースをイントロスペクトする

このガイドの目的のために、次の Prisma 1 データモデルを使用します (SQL タブを選択して、データモデルが SQL でどのようにマップされるかを確認してください)。

type User {
id: ID! @id
email: String @unique
name: String!
role: Role! @default(value: CUSTOMER)
jsonData: Json
profile: Profile
posts: [Post!]!
}

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

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

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

enum Role {
ADMIN
CUSTOMER
}

このデータモデルには 3 つの リレーション があることに注意してください。

  • 1-1: UserProfile
  • 1-n: UserPost (_PostToUser リレーションテーブルを介して維持)
  • m-n: PostCategory (_CategoryToPost リレーションテーブルを介して維持)

これで、次のコマンドを使用して Prisma ORM のイントロスペクションをデータベースに対して実行できます。

npx prisma db pull

db pull が呼び出されたときに何が起こるかのグラフィカルな図を次に示します。

Introspect your database

上記の Prisma 1 データモデルの場合、これは次の Prisma ORM 2 スキーマになります (モデルは Prisma 1 データモデルの最初の順序に一致するように再配置されていることに注意してください)。

schema.prisma
model User {
id String @id @default(cuid())
email String? @unique
name String
role String
jsonData String?
Profile Profile[]
Post Post[]
}

model Post {
id String @id @default(cuid())
createdAt DateTime
updatedAt DateTime
title String
content String?
published Boolean
Category Category[]
User User[]
}

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

model Category {
id String @id @default(cuid())
name String
Post Post[]
}

これはすでに有効な Prisma ORM 2 スキーマですが、Prisma 1 と同等の機能 がいくつか欠けています。

  • PostcreatedAt および updatedAt フィールドの自動生成の日付値がない
  • Userrole フィールドのデフォルト値がない
  • Postpublished フィールドのデフォルト値がない

さらに、あまり慣用的ではない/人間工学に基づかない Prisma Client API になるいくつかの矛盾があります。

  • UserProfile は 1-1 リレーションではなく 1-n リレーション
  • UserPost は 1-n リレーションではなく m-n リレーション
  • リレーションフィールドが大文字 (例: UserProfile および Post)
  • UserjsonData フィールドの型が Json ではなく String
  • Userrole フィールドの型が Role ではなく String、role の enum 定義が完全に欠落している

これらの矛盾は、Prisma Client API で使用できる「機能セット」に実際には影響しませんが、以前に存在していた特定の制約/保証を失うことになります。

たとえば、テーブル間のリレーションがイントロスペクション中に 1-n として認識されたため、Prisma ORM は、User最大 1 つの Profile に接続されていることを保証しなくなりました。そのため、1 つの User レコードが複数の Profile レコードに接続される可能性があります。

もう 1 つの問題は、jsonData および role フィールドに、有効な JSON であるか、Role 列挙型の値を表しているかに関係なく、任意のテキストを格納できることです。

これらの矛盾の詳細については、スキーマの非互換性 ページを確認してください。

以下では、これらの非互換性について順に説明し、Prisma スキーマアップグレード CLI を使用して 1 つずつ修正します。

5. Prisma スキーマアップグレード CLI を使用してスキーマの非互換性を解決する

Prisma 1 Upgrade CLI は、Prisma スキーマのアップグレードと、上記の非互換性のほとんどを解消するのに役立つインタラクティブツールです。

Prisma 1 Upgrade CLI は、主に 2 つのフェーズで動作します。

  1. プレーン SQL を使用してデータベーススキーマを修正する
  2. Prisma ORM 2 スキーマに欠落している属性とその他のスキーマ修正を追加する

最初のフェーズでは、データベーススキーマを調整するためにデータベースに対して実行する必要がある SQL ステートメントの数を生成して出力します。すべてのステートメントを実行するか、それらの一部を実行してから、2 番目のフェーズに進むことができます。

2 番目のフェーズでは、手動で何も行う必要はありません。Upgrade CLI は、特定の Prisma ORM レベルの属性 (@default(cuid))@updatedAt など) を追加したり、Prisma 1 データモデルのリレーションフィールドの名前を一致するように調整したり、Prisma 1 データモデルの両側で必須だった 1-1 リレーションが Prisma ORM 2 スキーマでも必須になるようにしたりすることで、Prisma スキーマに変更を加えます。

プロセス中はいつでもやり直すことができます。また、2 番目のフェーズから最初のフェーズに戻ることができます。

この図では、緑色の領域は最初のフェーズ、青色の領域は 2 番目のフェーズを示しています。フェーズの間に prisma db pull をオプションで実行して Prisma ORM データモデルを更新できることに注意してください。

Fixing the schema incompatibilities

Upgrade CLI を使用するには、プロジェクトにローカルにインストールするか、ここで実行されているように npx を使用してインストールせずに一度呼び出すことができます。

npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma

CLI は次のメッセージで挨拶します。

◮ Welcome to the interactive Prisma Upgrade CLI that helps with the
upgrade process from Prisma 1 to Prisma ORM 2.

Please read the docs to learn more about the upgrade process:
https://pris.ly/d/how-to-upgrade

➤ Goal
The Upgrade CLI helps you resolve the schema incompatibilities
between Prisma 1 and Prisma ORM 2. Learn more in the docs:
https://pris.ly/d/schema-incompatibilities

➤ How it works
Throughout the process, you'll need to adjust your database schema by sending
SQL statements to it. The SQL statements are provided by the Upgrade CLI.

Note that the Upgrade CLI never makes changes to your database,
you are in full control over any operations that are executed against it.

You can stop and re-run the Upgrade CLI at any time.

These are the different steps of the upgrade process:

1. The Upgrade CLI generates SQL commands for you to run on your database.
2. You run the SQL commands against your database.
3. You run the `npx prisma db pull` command again.
4. You run the `npx prisma-upgrade` command again.
5. The Upgrade CLI adjusts the Prisma ORM 2 schema by adding missing attributes.

➤ Note
It is recommended that you make a full backup of your existing data before starting
the upgrade process. If possible, the migration should be performed in a staging
environment before executed against a production environment.

➤ Help
If you have any questions or run into any problems along the way,
please create an issue at:
https://github.com/prisma/prisma1-upgrade/issues

Are you ready? [Y/n]

Y ボタンを押し、RETURN キーを押して続行します。

確認すると、CLI はデータベースに対して実行する必要がある SQL ステートメントを出力します。

➤ Adjust your database schema
Run the following SQL statements against your database:

Fix columns with ENUM data types
https://pris.ly/d/schema-incompatibilities#enums-are-represented-as-text-in-database

CREATE TYPE "default$default"."Role" AS ENUM ('ADMIN', 'CUSTOMER');
ALTER TABLE "default$default"."User" ALTER COLUMN "role" SET DATA TYPE "default$default"."Role" using "role"::"default$default"."Role";


Add missing `DEFAULT` constraints to the database
https://pris.ly/d/schema-incompatibilities#default-values-arent-represented-in-database

ALTER TABLE "default$default"."User" ALTER COLUMN "role" SET DEFAULT 'CUSTOMER';
ALTER TABLE "default$default"."Post" ALTER COLUMN "published" SET DEFAULT false;


Fix columns with JSON data types
https://pris.ly/d/schema-incompatibilities#json-type-is-represented-as-text-in-database

ALTER TABLE "default$default"."User" ALTER COLUMN "jsonData" SET DATA TYPE JSONB USING "jsonData"::TEXT::JSONB;


Replicate `@createdAt` behavior in Prisma ORM 2
https://pris.ly/d/schema-incompatibilities#createdat-isnt-represented-in-database

ALTER TABLE "default$default"."Post" ALTER COLUMN "createdAt" SET DEFAULT CURRENT_TIMESTAMP;


Fix 1-1 relations by adding `UNIQUE` constraints
https://pris.ly/d/schema-incompatibilities#inline-1-1-relations-are-recognized-as-1-n-missing-unique-constraint

ALTER TABLE "default$default"."Profile" ADD UNIQUE ("user");


Migrate IDs from varchar(25) to varchar(30)
https://pris.ly/d/schema-incompatibilities#mismatching-cuid-length

ALTER TABLE "default$default"."Category" ALTER COLUMN "id" SET DATA TYPE character varying(30);
ALTER TABLE "default$default"."Post" ALTER COLUMN "id" SET DATA TYPE character varying(30);
ALTER TABLE "default$default"."Profile" ALTER COLUMN "id" SET DATA TYPE character varying(30);
ALTER TABLE "default$default"."Profile" ALTER COLUMN "user" SET DATA TYPE character varying(30);
ALTER TABLE "default$default"."User" ALTER COLUMN "id" SET DATA TYPE character varying(30);

➤ Breaking changes detected

In order to fully optimize your database schema, you'll need to run a few SQL
statements that can break your Prisma 1 setup. Note that these changes are optional
and if you are upgrading gradually and running Prisma 1 and Prisma ORM 2 side-by-side,
you should not perform these changes yet. Instead, you can perform them whenever
you are ready to completely remove Prisma 1 from your project.
If you are upgrading all at once, you can safely perform these changes now.

Learn more in the docs:
https://pris.ly/d/how-to-upgrade'

注記: 破壊的変更に関する注記が表示されている場合は、今のところ無視してもかまいません。これについては後で説明します。

表示されている SQL ステートメントは、特定の スキーマの非互換性 を解決することを目的とした、多数の「バケット」に分類されています。

  • ENUM データ型の列を修正する
  • データベースに欠落している DEFAULT 制約を追加する
  • JSON データ型の列を修正する
  • Prisma 2 で @createdAt の動作をレプリケートする
  • UNIQUE 制約を追加して 1-1 リレーションを修正する

次のステップとして、SQL ステートメントをデータベースに送信できます。これらの変更はすべて非破壊的であり、Prisma ORM 2 とサイドバイサイドで Prisma 1 を引き続き使用できることに注意してください。

次のセクションでは、データベースに送信されるさまざまな種類の SQL ステートメントについて個別に説明します。

5.1. プレーン SQL を使用してデータベーススキーマを修正する (非破壊的)

このセクションでは、出力された SQL ステートメントについて順に説明し、データベースに対して 1 つずつ実行します。

5.1.1. ENUM データ型の列を修正する

ツールが最初に行うことは、Prisma 1 データモデルの enum 定義が、基になるデータベースの実際の ENUM 型として表されるようにすることです。現在、これらはプレーンな文字列 (例: MySQL の MEDIUMTEXT) として表されています。

CLI は現在、次の出力を表示しています。

Fix columns with ENUM data types
https://pris.ly/d/schema-incompatibilities#enums-are-represented-as-text-in-database

CREATE TYPE "default$default"."Role" AS ENUM ('ADMIN', 'CUSTOMER');
ALTER TABLE "default$default"."User" ALTER COLUMN "role" SET DATA TYPE "default$default"."Role" using "role"::"default$default"."Role";

⚠️ 警告: Prisma 1 と Prisma ORM 2 を サイドバイサイド で実行している場合、これらの SQL ステートメントは Prisma 1 セットアップを破壊します。ドキュメントはまもなく更新されてこれを反映します。

これらのステートメントをデータベースに対して今すぐ実行してください。

Altering columns to use ENUM with SQL

5.1.2. データベースに欠落している DEFAULT 制約を追加する

次に、Upgrade CLI は、デフォルト値がデータベースで表現されていない という問題を解決するのに役立ちます。これを行うために、それぞれの DEFAULT 制約をデータベースに直接追加する SQL ステートメントを生成します。

この場合、ツールによって提案された 2 つの DEFAULT 制約が欠落しています。

Add missing `DEFAULT` constraints to the database
https://pris.ly/d/schema-incompatibilities#default-values-arent-represented-in-database

ALTER TABLE "default$default"."User" ALTER COLUMN "role" SET DEFAULT 'CUSTOMER';
ALTER TABLE "default$default"."Post" ALTER COLUMN "published" SET DEFAULT false;

コマンドラインクライアントまたは Postico などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できるようになりました。

Adding missing DEFAULT constraints to columns

5.1.3. JSON データ型の列を修正する

次に、ツールは、Prisma 1 データモデルの Json フィールドが、基になるデータベースの JSON 列として表されるようにするのに役立ちます。現在、これらはプレーンな文字列 (例: MySQL の MEDIUMTEXT) として表されています。

列の型を JSON に変更すると、Prisma ORM 2 イントロスペクション中にフィールドが Json として適切に認識されるようになります。

CLI は現在、次の出力を表示しています。

Fix columns with JSON data types
https://pris.ly/d/schema-incompatibilities#json-type-is-represented-as-text-in-database

ALTER TABLE "default$default"."User" ALTER COLUMN "jsonData" TYPE JSON USING "jsonData"::json;

⚠️ 警告: Prisma 1 と Prisma ORM 2 を サイドバイサイド で実行している場合、これらの SQL ステートメントは Prisma 1 セットアップを破壊します。ドキュメントはまもなく更新されてこれを反映します。

コマンドラインクライアントまたは Postico などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できるようになりました。

Adding missing DEFAULT constraints to columns

5.1.4. Prisma ORM 2 で @createdAt の動作をレプリケートする

ツールが次に行うことは、@createdAt の動作がデータベースで表現されていない という問題を解決するのに役立ちます。

CLI は現在、次の出力を表示しています。

Replicate `@createdAt` behavior in Prisma ORM 2.0
https://pris.ly/d/schema-incompatibilities#createdat-isnt-represented-in-database

ALTER TABLE "default$default"."Post" ALTER COLUMN "createdAt" SET DEFAULT CURRENT_TIMESTAMP;

コマンドラインクライアントまたは Postico などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できるようになりました。

Running an SQL command to alter a column

5.1.5. UNIQUE 制約を追加して 1-1 リレーションを修正する

次に、ツールは、データベース内の user (Prisma 1 データモデルのリレーションフィールドにちなんで命名) という名前の外部キー列に UNIQUE 制約を追加することで、UserProfile 間の現在の 1-n リレーションを 1-1 リレーションに戻す のに役立ちます。

CLI は現在、次の出力を表示しています。

Fix 1-1 relations by adding `UNIQUE` constraints
https://pris.ly/d/schema-incompatibilities#inline-1-1-relations-are-recognized-as-1-n-missing-unique-constraint

ALTER TABLE "default$default"."Profile" ADD UNIQUE ("user");

コマンドラインクライアントまたは Postico などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できるようになりました。

Running an SQL command to alter a column

5.1.6. CUID 長さの不一致を修正する

注記: これらの SQL ステートメントは、基になるデータベースで列の型を変更した後でも、Upgrade CLI に引き続き表示されます。これは、Upgrade CLI の現在の制限事項です。

最後に、ツールは、データベース内の user (Prisma 1 データモデルのリレーションフィールドにちなんで命名) という名前の外部キー列に UNIQUE 制約を追加することで、現在の型 VARCHAR(25) の ID 列を VARCHAR(30) に変更する のに役立ちます。

CLI は現在、次の出力を表示しています。

Migrate IDs from varchar(25) to varchar(30)
https://pris.ly/d/schema-incompatibilities#mismatching-cuid-length

ALTER TABLE "default$default"."Category" ALTER COLUMN "id" SET DATA TYPE character varying(30);
ALTER TABLE "default$default"."Post" ALTER COLUMN "id" SET DATA TYPE character varying(30);
ALTER TABLE "default$default"."Profile" ALTER COLUMN "id" SET DATA TYPE character varying(30);
ALTER TABLE "default$default"."Profile" ALTER COLUMN "user" SET DATA TYPE character varying(30);
ALTER TABLE "default$default"."User" ALTER COLUMN "id" SET DATA TYPE character varying(30);

コマンドラインクライアントまたは Postico などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できるようになりました。

Running an SQL command to alter a column

5.1.7. 破壊的変更が検出されました

Upgrade CLI が破壊的変更に関する注記を出力した場合、データベーススキーマには、完全に最適化するために Prisma 1 の互換性を損なういくつかの調整が必要です。

破壊的変更が検出されなかった場合は、セクション 5.2 にスキップしてください

アップグレード戦略 に応じて、これらの変更を今すぐ実行するか、Upgrade CLI の次のフェーズにスキップすることができます。

  • 段階的なサイドバイサイドアップグレード戦略に従っている場合は、これらの変更は Prisma 1 セットアップを破壊するため、まだ実行しないでください。その場合は、n と入力し、RETURN を押して Upgrade CLI の次のフェーズに進むことができます。
  • 一度にすべてアップグレードする戦略に従っている場合は、これらの変更を今すぐ実行できます。その場合は、Y と入力し、RETURN を押して続行します。

5.2. プレーン SQL を使用してデータベーススキーマを修正する (破壊的)

このセクションでは、Prisma 1 セットアップを破壊するスキーマの非互換性を解決します。プロジェクトで Prisma 1 をまだ実行している場合は、これらの変更を実行しないでください。

5.2.1. 正しくない m-n リレーションを修正する

次に、Upgrade CLI は、Prisma 1 がリレーションテーブルで表し、新しい Prisma ORM 2 スキーマでは 現在 m-n リレーションとしてのみ存在する すべての 1-1 および 1-n リレーションを修正するのに役立ちます。具体的には、現在 m-n として定義されていますが、実際には 1-n リレーションである必要がある UserPost リレーションの場合です。

これを修正するには、次の移行を実行する必要があります。

  1. Post に新しい外部キー列を作成して、User テーブルに直接リンクします。
  2. リレーションテーブルから新しい外部キー列 Post に外部キー値を移行します。
  3. リレーションテーブルを削除します。

これらの手順は、CLI によって出力されます。

➤ Adjust your database schema
Run the following SQL statements against your database:

Fix one-to-many table relations
https://pris.ly/d/schema-incompatibilities#all-non-inline-relations-are-recognized-as-m-n

ALTER TABLE "default$default"."Post" ADD COLUMN "authorId" character varying(25) ;
ALTER TABLE "default$default"."Post" ADD CONSTRAINT "author" FOREIGN KEY ("authorId") REFERENCES "default$default"."User"("id");
UPDATE "default$default"."Post" SET "authorId" = "default$default"."_PostToUser"."B" FROM "default$default"."_PostToUser" WHERE "default$default"."_PostToUser"."A" = "default$default"."Post"."id";
DROP TABLE "default$default"."_PostToUser";


➤ Next Steps

After you executed one or more of the previous SQL statements against your database,
please run the following two commands to refresh your Prisma ORM 2 schema and check
the changes.

1. Run `npx prisma db pull` again to refresh your Prisma ORM 2 schema.
2. Run `npx prisma-upgrade` again.

If you can't or don't want to execute the remaining SQL statements right now, you can
skip to the last step where the Upgrade CLI adds missing attributes to your Prisma ORM 2
schema that are not picked up by introspection.

Skip to the last step? [Y/n]?

この修正には、3 つの SQL ステートメントを実行する必要があります。

  1. Post テーブルに新しい列 authorId を作成します。この列は、User テーブルの id フィールドを参照する外部キー である必要があります。
    ALTER TABLE `Post` ADD COLUMN `authorId` VARCHAR(25);
    ALTER TABLE `Post` ADD FOREIGN KEY (`authorId`) REFERENCES `User` (`id`);
  2. _PostToUser リレーションテーブルからすべての行を読み取り、各行に対して SQL クエリを記述します。
    1. A の値を参照して、それぞれの Post レコードを見つけます。
    2. B の値を authorId の値としてその Post レコードに挿入します。
    UPDATE Post, _PostToUser
    SET Post.authorId = _PostToUser.B
    WHERE Post.id = _PostToUser.A
  3. _PostToUser リレーションテーブルを削除します。
    DROP TABLE `_PostToUser`;

Fixing incorrect m-n relations with SQL

これらのコマンドの後、リレーションテーブルの列 B のレコードのユーザー ID 値が新しい authorId 列に移行されます。

5.2. Prisma スキーマを更新するためにデータベースを再度イントロスペクトする

この時点で、Upgrade CLI を使用してスキーマの非互換性を解決しました。n と入力し、RETURN を押して、Upgrade CLI を終了できます。

このセクションでは、別のイントロスペクションラウンドで Prisma スキーマを更新します。今回は、データベーススキーマが調整されたため、Prisma スキーマの以前の欠陥が解決されます。

npx prisma db pull

今回は、結果の Prisma スキーマは次のようになります。

schema.prisma
model User {
id String @id
name String
email String? @unique
jsonData Json?
role Role @default(CUSTOMER)
Post Post[]
Profile Profile?
}

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

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

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

enum Role {
ADMIN
CUSTOMER
}

このスキーマではほとんどの問題が解決されていますが、まだ次のものが欠けています。

5.2. Prisma 2 スキーマに欠落している属性とその他のスキーマ修正を追加する

CLI は次の出力を表示します。

➤ What happens next
As a last step, some final adjustments will be made to your Prisma ORM 2 schema
to carry over some Prisma ORM-level attributes that aren't picked up by introspection.

As a last step, some final adjustments will be made to your Prisma ORM 2.0
schema to carry over some Prisma ORM-level attributes that aren't picked
up by introspection.

Warning
Your current Prisma ORM 2.0 schema will be overwritten, so please
make sure you have a backup!

Are you ready? [Y/n]

この時点で、CLI によって出力されたすべての SQL ステートメントを実行したか、一部をスキップしました。いずれにせよ、最後のステップに進み、Upgrade CLI に欠落している Prisma ORM 2 属性を追加させることができます。通常、これらは次のとおりです。

  • @id フィールドの @default(cuid())
  • Prisma 1 でこの属性を使用していたフィールドの @updatedAt
  • Prisma 1 の @db および @@db の代替としての @map および @@map

そのステップで、Upgrade CLI は Prisma ORM 2 への移行で発生した他の問題も修正します。

  • Prisma 1 で両側で必須だった 1-1 リレーションが、Prisma ORM 2 スキーマでも必須になるようにします。
  • リレーションフィールドの名前を Prisma 1 データモデル (近日公開予定) と同じ名前に変更します。

これらの変更を適用するには、Upgrade CLI を再実行できます。

npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma

すべてのスキーマの非互換性を解決しなかった場合、Upgrade CLI は残りの SQL ステートメント (および ID を移行するためのステートメント) を出力します。この時点でそれらを無視して、プロンプトが表示されたら Y と入力して RETURN を押し続けることで、最後のステップに進むことができます。

すべてのスキーマの非互換性を解決した場合、SQL ステートメントは出力されず、Upgrade CLI は次の出力のみを出力します。

$ npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma

➤ Next Steps

After you executed one or more of the previous SQL statements against your database,
please run the following two commands to refresh your Prisma ORM 2 schema and check
the changes.

1. Run `npx prisma db pull` again to refresh your Prisma ORM 2 schema.
2. Run `npx prisma-upgrade` again.

If you can't or don't want to execute the remaining SQL statements right now, you can
skip to the last step where the Upgrade CLI adds missing attributes to your Prisma ORM 2
schema that are not picked up by introspection.

Skip to the last step? [Y/n]?

もう一度 Y と入力し、RETURN を押して確認します。

Upgrade CLI の最後のプロンプトで、Prisma スキーマに対して行う上記変更を確認するように求められます。

➤ What happens next
As a last step, some final adjustments will be made to your Prisma ORM 2 schema
to carry over some Prisma ORM-level attributes that aren't picked up by introspection.

As a last step, some final adjustments will be made to your Prisma ORM 2.0
schema to carry over some Prisma ORM-level attributes that aren't picked
up by introspection.

Warning
Your current Prisma ORM 2.0 schema will be overwritten, so please
make sure you have a backup!

Are you ready? [Y/n]

最後にもう一度 Y と入力し、RETURN を押して確認します。

これが Upgrade CLI の最終出力です。

Updating prisma/schema.prisma...
Done updating prisma/schema.prisma!

✔ Congratulations, you're all set!

➤ Note
If you didn't execute all generated SQL commands against your database,
you can re-run the Upgrade CLI at any time.

Note that the Upgrade CLI doesn't resolve all of the schema incompatibilities
between Prisma 1 and Prisma ORM 2. If you want to resolve the remaining ones,
you can do so manually by following this guide:
https://pris.ly/d/upgrading-the-prisma-layer

➤ Next steps
Otherwise you can continue your upgrade process by installing Prisma Client 2:
npm install @prisma/client

You can find guides for different upgrade scenarios in the docs:
https://pris.ly/d/upgrade-from-prisma-1

5.3. 最終結果

Prisma スキーマの最終バージョンは次のようになります。

schema.prisma
model User {
id String @id @default(cuid())
name String
email String? @unique
jsonData Json?
role Role @default(CUSTOMER)
Post Post[]
Profile Profile?
}

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

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

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

enum Role {
ADMIN
CUSTOMER
}

5.4. リレーションフィールドの名前を変更する

このバージョンの Prisma ORM 2 スキーマで気付くことの 1 つは、すべての リレーションフィールド がそれぞれのモデルにちなんで命名されていることです。例:

schema.prisma
model User {
Post Post[]
Profile Profile?
}

model Post {
User User? @relation(fields: [authorId], references: [id])
Category Category[] @relation(references: [id])
}

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

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

これは理想的ではありません。実際には、それらすべてを以前のバージョンに手動で名前変更できます。

すべてのリレーションフィールドは仮想 であり、データベースにマニフェスト されないため、好きなように名前を付けることができます。この場合、すべてのリレーションフィールドは小文字で、場合によっては複数形になっています。

名前変更後の外観を次に示します。

schema.prisma
model User {
posts Post[]
profile Profile?
}

model Post {
author User? @relation(fields: [authorId], references: [id])
categories Category[] @relation(references: [id])
}

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

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

注記: UserProfile 間の 1-1 リレーションの場合、リレーションフィールドに古い名前 user を設定することはできませんでした。これは、外部キーを保持する既存の リレーションスカラー フィールドとの名前の衝突が発生するためです。その場合は、別の名前を選択するか、SQL を介してデータベースで外部キー列の名前を直接変更することができます。

5.5. 残りのスキーマの非互換性を解決する

Upgrade CLI ではまだ解決されていないスキーマの非互換性がいくつかあります。この時点では、まだ スカラーリスト を修正していません。これらおよびその他の推奨される回避策については、スキーマの非互換性 ページを参照してください。

6. Prisma Client をインストールして生成する

Prisma ORM 2 スキーマの準備ができたので、次のコマンドで Prisma Client をインストールできます。

npm install @prisma/client

7. 次のステップ

おめでとうございます。Prisma ORM レイヤーを Prisma ORM 2 にアップグレードしました。ここからは、次のいずれかのガイドを使用してアプリケーションコードを更新できます。

  • 古い Nexus から新しい Nexus へ: 現在 GraphQL Nexus で Prisma 1 を実行している場合は、このガイドを選択してください。
  • prisma-binding から Nexus へ: 現在 prisma-binding で Prisma 1 を実行しており、Nexus (および TypeScript) にアップグレードする場合は、このガイドを選択してください。
  • prisma-binding から SDL-first へ: 現在 prisma-binding で Prisma 1 を実行しており、SDL-first GraphQL サーバーにアップグレードする場合は、このガイドを選択してください。
  • REST API: Prisma Client 1 を使用して Prisma 1 を現在実行しており、REST API を構築している場合は、このガイドを選択してください。

ボーナス: Prisma Client API の比較

このセクションでは、Prisma 1 と Prisma ORM 2 の Prisma Client API の概要と並列比較を示します。新しい Prisma Client API の詳細については、Prisma Client ドキュメントをご覧ください。

単一レコードの読み取り

Prisma Client (v1)
const user = await prisma.user({ id: 1 })
Prisma Client (v2)
await prisma.user.findUnique({
where: { id: 1 },
})

レコードリストの読み取り

Prisma Client (v1)
const user = await prisma.users()
Prisma Client (v2)
await prisma.user.findMany()

リストのフィルタリング

Prisma Client (v1)
const users = await prisma.users({
where: {
name: 'Alice',
},
})
Prisma Client (v2)
await prisma.user.findMany({
where: {
name: 'Alice',
},
})

リストのページネーション

Prisma Client (v1)
const posts = await prisma.posts({
skip: 5,
first: 10,
})
Prisma Client (v2)
await prisma.user.findMany({
skip: 5,
take: 10,
})

: 新しいページネーション API の詳細については、それぞれのリリースノート またはドキュメントのページネーションページをご覧ください。

リストのソート

Prisma Client (v1)
await prisma.posts({
orderBy: 'title_ASC',
})
Prisma Client (v2)
await prisma.posts({
orderBy: {
title: 'asc',
},
})

レコードの作成

Prisma Client (v1)
await prisma.createUser({
name: 'Alice',
})
Prisma Client (v2)
await prisma.user.create({
data: {
name: 'Alice',
},
})

レコードの更新

Prisma Client (v1)
await prisma.updateUser({
where: { id: 1 },
data: {
name: 'James',
email: 'james@prisma.io',
},
})
Prisma Client (v2)
await prisma.user.update({
where: { id: 1 },
data: {
name: 'James',
email: 'james@prisma.io',
},
})

レコードの削除

Prisma Client (v1)
await prisma.deleteUser({ id: 1 })
Prisma Client (v2)
await prisma.user.delete({
where: { id: 1 },
})

フィールドの選択とリレーションのロード

Prisma 1 では、特定のフィールドを選択したり、オブジェクトのリレーションをロードしたりする唯一の方法は、文字列ベースの $fragment 関数と $graphql 関数を使用することでした。Prisma ORM 2 では、selectinclude を使用して、クリーンでタイプセーフな方法でこれが行われるようになりました。

このアプローチのもう 1 つの利点は、selectincludefindUnique()findManycreateupdatedelete などの任意の Prisma Client クエリで使用できることです。

Prisma Client (v1)
await prisma.user({ id: 1 }).$fragment(`
fragment NameAndEmail on User { id email }`
`)
Prisma Client (v2)
await prisma.user.findUnique({
where: { id: 1 },
select: {
id: true,
email: true,
},
})

例として、新しいレコードを作成し、返されたオブジェクトで id のみを取得することは、Prisma 1 では不可能でした。Prisma ORM 2 では、次のようにしてこれを実現できます

await prisma.user.create({
data: {
name: 'Alice',
},
select: {
id: true,
},
})