Prisma ORM レイヤーのアップグレード
概要
このページでは、アップグレードプロセスの最初のステップについて説明します。Prisma 1 の構成を Prisma ORM 2 にアップグレードします。具体的には、以下の方法を学びます。
- Prisma ORM 2 CLI を開発依存関係として追加する
- Prisma ORM 2 スキーマを作成する
- 接続 URL を決定し、データベースに接続する
- (これまで Prisma 1 で管理されていた)データベースをイントロスペクトする
- Prisma 1 Upgrade CLI を使用して、新しい Prisma ORM 2 データモデルの スキーマの非互換性 を解決する
- Prisma Client をインストールして生成する
これらの手順が完了したら、アプリケーションレイヤーをアップグレードして Prisma Client をデータベースクエリに使用する方法について説明する次のガイドに進むことができます。
注記: アップグレードプロセス中、データベースのグラフィカルビューを取得すると役立つ場合があります。そのため、TablePlus や Postico などのグラフィカルデータベースクライアントを使用してデータベースに接続することをお勧めします。
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
: データソース、ジェネレーター、および データモデル を指定する Prisma スキーマ (データモデルはまだ存在しないことに注意してください。イントロスペクションによって生成されます)。.env
: データベースの 接続 URL を構成するための dotenv ファイル。
最初の Prisma スキーマは次のようになります。
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
Prisma 1 では、使用する Prisma Client の言語バリアントを prisma.yml
で指定していました。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 の クエリエンジン によってプロキシされますが、追加のサーバーはもうありません)。
したがって、次のステップとして、Prisma ORM 2 に使用するデータベースの種類 (MySQL または PostgreSQL) と場所を伝える必要があります。
まず、schema.prisma
内の datasource
ブロックの provider
フィールドが正しいデータベースを使用するように構成されていることを確認する必要があります。
- PostgreSQL を使用している場合は、
provider
フィールドに値"postgresql"
を定義する必要があります。 - MySQL を使用している場合は、
provider
フィールドに値"mysql"
を定義する必要があります。
コードブロックのタブを切り替えて、両方の例を確認してください
- PostgreSQL
- MySQL
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
provider
フィールドを設定したら、.env
ファイル内で接続 URL を構成できます。
Prisma ORM サーバーのデプロイに使用した Docker Compose ファイルのデータベース構成が次のようになっていると仮定します。
PRISMA_CONFIG: |
port: 4466
databases:
default:
connector: mysql
host: mysql
port: 3306
user: root
password: randompassword
また、prisma.yml
の endpoint
が次のように構成されていると仮定します。
endpoint: http://#:4466/myproject/dev
これらの接続の詳細に基づいて、.env
ファイル内の DATABASE_URL
環境変数を次のように構成する必要があります。
DATABASE_URL="mysql://root:randompassword@localhost:3306/myproject@dev"
接続 URL の データベース名 は通常、サービス名 と サービスステージ (prisma.yml
の endpoint
の一部) で構成され、@
文字で区切られていることに注意してください。
サービス名とステージが prisma.yml
で指定されていない場合もあります。
endpoint: http://#:4466/
その場合、データベース名は次のように指定する必要があります。
DATABASE_URL="mysql://root:randompassword@localhost:3306/default@default"
詳細については、接続 URL ページをご覧ください。
4. データベースのイントロスペクト
このガイドの目的のために、次の Prisma 1 データモデルを使用します (SQL でのデータモデルのマッピングを確認するには、以下の SQL タブを選択してください)。
- Prisma 1 データモデル
- 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
}
CREATE TABLE"User" (
id character varying(25) PRIMARY KEY,
email text,
name text NOT NULL,
role text NOT NULL,
"jsonData" text
);
CREATE UNIQUE INDEX "User_pkey" ON"User"(id text_ops);
CREATE UNIQUE INDEX "default$default.User.email._UNIQUE" ON"User"(email text_ops);
CREATE TABLE"Post" (
id character varying(25) PRIMARY KEY,
title text NOT NULL,
published boolean NOT NULL,
"createdAt" timestamp(3) without time zone NOT NULL,
"updatedAt" timestamp(3) without time zone NOT NULL,
content text
);
CREATE UNIQUE INDEX "Post_pkey" ON"Post"(id text_ops);
CREATE TABLE"Profile" (
id character varying(25) PRIMARY KEY,
bio text,
user character varying(25) REFERENCES"User"(id) ON DELETE SET NULL
);
CREATE UNIQUE INDEX "Profile_pkey" ON"Profile"(id text_ops);
CREATE TABLE"Category" (
id character varying(25) PRIMARY KEY,
name text NOT NULL
);
CREATE UNIQUE INDEX "Category_pkey" ON"Category"(id text_ops);
CREATE TABLE"_PostToUser" (
"A" character varying(25) NOT NULL REFERENCES"Post"(id) ON DELETE CASCADE,
"B" character varying(25) NOT NULL REFERENCES"User"(id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX "_PostToUser_AB_unique" ON"_PostToUser"("A" text_ops,"B" text_ops);
CREATE INDEX "_PostToUser_B" ON"_PostToUser"("B" text_ops);
CREATE TABLE"_CategoryToPost" (
"A" character varying(25) NOT NULL REFERENCES"Category"(id) ON DELETE CASCADE,
"B" character varying(25) NOT NULL REFERENCES"Post"(id) ON DELETE CASCADE
);
CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON"_CategoryToPost"("A" text_ops,"B" text_ops);
CREATE INDEX "_CategoryToPost_B" ON"_CategoryToPost"("B" text_ops);
このデータモデルには 3 つの リレーション があることに注意してください。
- 1-1:
User
↔Profile
- 1-n:
User
↔Post
(_PostToUser
リレーションテーブルを介して維持) - m-n:
Post
↔Category
(_CategoryToPost
リレーションテーブルを介して維持)
次のコマンドを使用して、Prisma ORM のイントロスペクションをデータベースに対して実行できます。
npx prisma db pull
db pull
が呼び出されたときに何が起こるかをグラフィカルに説明した図を次に示します。
上記の Prisma 1 データモデルの場合、これは次の Prisma ORM 2 スキーマになります (モデルは Prisma 1 データモデルの最初の順序と一致するように再配置されていることに注意してください)。
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 の同等のスキーマの一部であった多くの 機能 が欠落しています。
Post
のcreatedAt
およびupdatedAt
フィールドの自動生成された日付値がないUser
のrole
フィールドのデフォルト値がないPost
のpublished
フィールドのデフォルト値がない
さらに、よりイディオム的/人間工学的な Prisma Client API を得られない多くの一貫性のない点があります。
User
↔Profile
は 1-1 リレーションではなく 1-n リレーションであるUser
↔Post
は 1-n リレーションではなく m-n リレーションである- リレーションフィールドが大文字で始まる (例:
User
のProfile
およびPost
) User
のjsonData
フィールドの型がJson
ではなくString
であるUser
のrole
フィールドの型がRole
ではなくString
である。ロールの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 つのフェーズで動作します。
- プレーン SQL を介してデータベーススキーマを修正する
- Prisma ORM 2 スキーマに欠落している属性とその他のスキーマ修正を追加する
最初のフェーズでは、データベーススキーマを調整するためにデータベースに対して実行する必要がある SQL ステートメントの数を生成して出力します。すべてのステートメントまたはそのサブセットを実行してから、第 2 フェーズに進むことができます。
第 2 フェーズでは、手動で何もする必要はありません。Upgrade CLI は、特定の Prisma ORM レベルの属性 (@default(cuid))
や @updatedAt
など) を追加したり、Prisma 1 データモデルのフィールドと一致するようにリレーションフィールドの名前を調整したり、Prisma 1 データモデルの両側で必須だった 1-1 リレーションが Prisma ORM 2 スキーマでも必須になるようにしたりすることで、Prisma スキーマに変更を加えます。
プロセス中はいつでもやり直して、第 2 フェーズから第 1 フェーズに戻ることができることに注意してください。
この図では、緑色の領域が第 1 フェーズ、青色の領域が第 2 フェーズを示しています。フェーズ間にオプションで prisma db pull
を実行して、Prisma ORM データモデルを更新できることに注意してください。
Upgrade CLI を使用するには、プロジェクトにローカルにインストールするか、ここで実行しているように npx
を使用してインストールせずに 1 回呼び出すことができます。
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/new
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
ALTER TABLE `User` CHANGE `role` `role` ENUM('ADMIN', 'CUSTOMER') NOT NULL;
Add missing `DEFAULT` constraints to the database
https://pris.ly/d/schema-incompatibilities#default-values-arent-represented-in-database
ALTER TABLE `User` CHANGE `role` `role` ENUM('ADMIN', 'CUSTOMER') NOT NULL DEFAULT 'CUSTOMER';
ALTER TABLE `Post` CHANGE `published` `published` TINYINT(1) NOT NULL DEFAULT 0;
Fix columns with JSON data types
https://pris.ly/d/schema-incompatibilities#json-type-is-represented-as-text-in-database
ALTER TABLE `User` CHANGE `jsonData` `jsonData` JSON ;
Replicate `@createdAt` behavior in Prisma ORM 2.0
https://pris.ly/d/schema-incompatibilities#createdat-isnt-represented-in-database
ALTER TABLE `Post` CHANGE `createdAt` `createdAt` DATETIME NOT NULL 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 `Profile` ADD UNIQUE (`user`);
Migrate IDs from varchar(25) to varchar(30)
https://pris.ly/d/schema-incompatibilities#mismatching-cuid-length
SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE `Category` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL;
ALTER TABLE `Post` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL;
ALTER TABLE `Profile` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL;
ALTER TABLE `Profile` CHANGE `user` `user` char(30) CHARACTER SET utf8 ;
ALTER TABLE `User` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL;
SET FOREIGN_KEY_CHECKS=1;
➤ 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
ALTER TABLE `User` CHANGE `role` `role` ENUM('ADMIN', 'CUSTOMER') NOT NULL;
これらのステートメントをデータベースに対して実行してください。
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 `User` CHANGE `role` `role` ENUM('ADMIN', 'CUSTOMER') NOT NULL DEFAULT 'CUSTOMER';
ALTER TABLE `Post` CHANGE `published` `published` TINYINT(1) NOT NULL DEFAULT 0;
コマンドラインクライアントまたは TablePlus などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できます。
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 `User` CHANGE `jsonData` `jsonData` JSON ;
コマンドラインクライアントまたは TablePlus などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できます。
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 `Post` CHANGE `createdAt` `createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP;
コマンドラインクライアントまたは TablePlus などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できます。
5.1.5. UNIQUE
制約を追加して 1-1 リレーションを修正する
次に、ツールは、データベース内の user
(Prisma 1 データモデルのリレーションフィールドにちなんで名付けられた) という外部キー列に UNIQUE
制約を追加することにより、User
↔ Profile
間の現在の 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 `Profile` ADD UNIQUE (`user`);
コマンドラインクライアントまたは TablePlus などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できます。
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
SET FOREIGN_KEY_CHECKS=0;
ALTER TABLE `Category` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL;
ALTER TABLE `Post` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL;
ALTER TABLE `Profile` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL;
ALTER TABLE `Profile` CHANGE `user` `user` char(30) CHARACTER SET utf8 ;
ALTER TABLE `User` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL;
SET FOREIGN_KEY_CHECKS=1;
コマンドラインクライアントまたは TablePlus などの GUI を使用して、これらの SQL ステートメントをデータベースに対して実行できます。
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 リレーションである User
↔ Post
リレーションの場合です。
これを修正するには、次の移行を実行する必要があります。
Post
に新しい外部キー列を作成して、User
テーブルに直接リンクします。- リレーションテーブルから外部キー値を移行して、
Post
の新しい外部キー列に格納します。 - リレーションテーブルを削除します。
これらの手順は、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 `Post` ADD COLUMN `authorId` char(25) CHARACTER SET utf8 ;
ALTER TABLE `Post` ADD CONSTRAINT author FOREIGN KEY (`authorId`) REFERENCES `User`(`id`);
UPDATE `Post`, `_PostToUser` SET `Post`.`authorId` = `_PostToUser`.B where `_PostToUser`.A = `Post`.`id`;
DROP TABLE `_PostToUser`;
➤ Next Steps
After you executed one or more of the above 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 ステートメントを実行する必要があります。
Post
テーブルに新しい列authorId
を作成します。この列は、User
テーブルのid
フィールドを参照する 外部キー である必要があります。ALTER TABLE `Post` ADD COLUMN `authorId` char(25) CHARACTER SET utf8 ;
ALTER TABLE `Post` ADD CONSTRAINT author FOREIGN KEY (`authorId`) REFERENCES `User`(`id`);_PostToUser
リレーションテーブルからすべての行を読み取る SQL クエリを記述し、各行に対して- 列
A
の値を参照して、それぞれのPost
レコードを見つけます。 - 列
B
の値をauthorId
の値としてそのPost
レコードに挿入します。
UPDATE `Post`, `_PostToUser` SET `Post`.`authorId` = `_PostToUser`.B where `_PostToUser`.A = `Post`.`id`;
- 列
_PostToUser
リレーションテーブルを削除します。DROP TABLE `_PostToUser`;
これらのコマンドの後、リレーションテーブルの列 B
のレコードのユーザー ID 値が、新しい authorId
列に移行されます。
5.2. データベースを再イントロスペクトして Prisma スキーマを更新する
この時点で、Upgrade CLI を使用してスキーマの非互換性を解決しました。n
と入力して RETURN を押して、Upgrade CLI をいったん終了できます。
このセクションでは、別のイントロスペクションラウンドで Prisma スキーマを更新します。今回は、データベーススキーマが調整されたため、Prisma スキーマの以前の欠陥が解決されます。
npx prisma db pull
今回、結果として得られる 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 スキーマの最終バージョンは、次のようになります。
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 つは、すべての リレーションフィールド がそれぞれのモデルにちなんで名付けられていることです。例:
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])
}
これは理想的ではありません。実際には、それらのすべてを以前のバージョンに手動で名前変更できます!
すべてのリレーションフィールドは 仮想 であり、データベースに 現れない ため、好きなように名前を付けることができます。この場合、すべてのリレーションフィールドは小文字で始まり、場合によっては複数形になります。
名前を変更した後の外観は次のとおりです。
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])
}
注記:
User
とProfile
の間の 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 のドキュメントを参照してください。
単一レコードの読み取り
const user = await prisma.user({ id: 1 })
await prisma.user.findUnique({
where: { id: 1 },
})
レコードリストの読み取り
const user = await prisma.users()
await prisma.user.findMany()
リストのフィルタリング
const users = await prisma.users({
where: {
name: 'Alice',
},
})
await prisma.user.findMany({
where: {
name: 'Alice',
},
})
リストのページネーション
const posts = await prisma.posts({
skip: 5,
first: 10,
})
await prisma.user.findMany({
skip: 5,
take: 10,
})
注記: 新しいページネーション API の詳細については、それぞれのリリースノートまたはドキュメントのページネーションのページを参照してください。
リストのソート
await prisma.posts({
orderBy: 'title_ASC',
})
await prisma.posts({
orderBy: {
title: 'asc',
},
})
レコードの作成
await prisma.createUser({
name: 'Alice',
})
await prisma.user.create({
data: {
name: 'Alice',
},
})
レコードの更新
await prisma.updateUser({
where: { id: 1 },
data: {
name: 'James',
email: 'james@prisma.io',
},
})
await prisma.user.update({
where: { id: 1 },
data: {
name: 'James',
email: 'james@prisma.io',
},
})
レコードの削除
await prisma.deleteUser({ id: 1 })
await prisma.user.delete({
where: { id: 1 },
})
フィールドの選択とリレーションのロード
Prisma 1 では、特定のフィールドを選択したり、オブジェクトのリレーションをロードしたりする唯一の方法は、文字列ベースの $fragment
および $graphql
関数を使用することでした。Prisma ORM 2 では、select
と include
を使用して、クリーンでタイプセーフな方法でこれを行うことができます。
このアプローチのもう 1 つの利点は、select
と include
を findUnique
、findMany
、create
、update
、delete
などの任意の Prisma Client クエリで使用できることです。
await prisma.user({ id: 1 }).$fragment(`
fragment NameAndEmail on User { id email }`
`)
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,
},
})