From 6c52b9ab115ae0135dbc689cc4465eacc54a7f48 Mon Sep 17 00:00:00 2001 From: Nikolas Burk Date: Tue, 24 Mar 2020 07:04:53 +0100 Subject: [PATCH 1/6] continue docs --- .../08-renaming-tables-and-columns/index.mdx | 2 +- content/05-more/02-style-guide.mdx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/content/04-guides/01-database-workflows/08-renaming-tables-and-columns/index.mdx b/content/04-guides/01-database-workflows/08-renaming-tables-and-columns/index.mdx index f0d25c081a..37743e4710 100644 --- a/content/04-guides/01-database-workflows/08-renaming-tables-and-columns/index.mdx +++ b/content/04-guides/01-database-workflows/08-renaming-tables-and-columns/index.mdx @@ -1,4 +1,4 @@ --- -title: "Data validation" +title: "Renaming tables and columns" metaTitle: "" --- diff --git a/content/05-more/02-style-guide.mdx b/content/05-more/02-style-guide.mdx index 7742c7406c..a7f0b25e74 100644 --- a/content/05-more/02-style-guide.mdx +++ b/content/05-more/02-style-guide.mdx @@ -30,7 +30,7 @@ When you need to refer to one or more people in third-person, be sure to use inc ### Avoid emojis, slang, and metaphors -Avoid using emojis or emoticons in the docs and idiomatic expressions / slang, or metaphors. Gatsby has a global community, and the cultural meaning of an emoji, emoticon, or slang may be different around the world. Use your best judgment! Also, emojis can render differently on different systems. +Avoid using emojis or emoticons in the docs and idiomatic expressions / slang, or metaphors. Prisma has a global community, and the cultural meaning of an emoji, emoticon, or slang may be different around the world. Use your best judgment! Also, emojis can render differently on different systems. ### Define jargon @@ -57,9 +57,9 @@ Hyperlinks should contain the clearest words to indicate where the link will lea ```md -[Prisma's docs](https://www.prisma.io/docs/) +Read more in the [Prisma docs](https://www.prisma.io/docs/) -[here](https://www.gatsbyjs.org/docs/ "Gatsby's docs") +Read more in the Prisma docs [here](https://www.prisma.io/docs/) ``` ### Indicate when something is optional From f70bb6d99084de9944d5c8993438b09e16d807b1 Mon Sep 17 00:00:00 2001 From: Nikolas Burk Date: Tue, 24 Mar 2020 07:18:33 +0100 Subject: [PATCH 2/6] continue docs --- .../02-prisma-client/01-generating-prisma-client.mdx | 6 +++--- .../01-tools-and-interfaces/04-introspection.mdx | 7 ++++++- .../01-database-workflows/07-data-validation/index.mdx | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/content/03-reference/01-tools-and-interfaces/02-prisma-client/01-generating-prisma-client.mdx b/content/03-reference/01-tools-and-interfaces/02-prisma-client/01-generating-prisma-client.mdx index 9b6492c834..0cf91fcb66 100644 --- a/content/03-reference/01-tools-and-interfaces/02-prisma-client/01-generating-prisma-client.mdx +++ b/content/03-reference/01-tools-and-interfaces/02-prisma-client/01-generating-prisma-client.mdx @@ -29,7 +29,7 @@ Generating Prisma Client requires three steps: Here is a graphical illustration of the typicaly workflow for the Prisma Client generation: -![](https://imgur.com/fZ5rtVg.png) +![](https://i.imgur.com/aRJmVFY.png) Note also that `prisma generate` is _automatically_ invoked when you're installing the `@prisma/client` npm module. So, when you're initially setting up Prisma Client, you can typically save the third step from the list above. @@ -63,9 +63,9 @@ The `@prisma/client` node module is different. It is a "facade package" (basical While you do need to install it _once_ with `npm install @prisma/client`, it is likely that the code inside the `node_modules/@prisma/client` directory changes more often as you're evolving your application. This is because the directory contains code that is _generated_ based on your Prisma schema. When your Prisma schema changes (e.g. because you perform a [schema migration]()), you need to re-execute `prisma generate` which takes care of updating the code in `node_modules/@prisma/client` so that it reflects the schema changes. -Because the `node_modules/@prisma/client` directory contains some code that is _specific_ to _your_ project, it is sometimes called a "smart node module". +Because the `node_modules/@prisma/client` directory contains some code that is _specific_ to _your_ project, it is sometimes called a "smart node module": -![](https://imgur.com/5HuBN2G.png) +![](https://i.imgur.com/83djlkl.png) ### Why is the "facade package" needed if Prisma Client is generated? diff --git a/content/03-reference/01-tools-and-interfaces/04-introspection.mdx b/content/03-reference/01-tools-and-interfaces/04-introspection.mdx index 7a523aee2e..7575bb41c9 100644 --- a/content/03-reference/01-tools-and-interfaces/04-introspection.mdx +++ b/content/03-reference/01-tools-and-interfaces/04-introspection.mdx @@ -4,4 +4,9 @@ metaTitle: '' metaDescription: '' --- -Coming 🔜 +## Overview + +You can introspect your database using the Prisma CLI in order to generate the [data model]() in your [Prisma schema](). The data model is needed to [generate Prisma Client](). + + + diff --git a/content/04-guides/01-database-workflows/07-data-validation/index.mdx b/content/04-guides/01-database-workflows/07-data-validation/index.mdx index e9a6ec135a..d532994bde 100644 --- a/content/04-guides/01-database-workflows/07-data-validation/index.mdx +++ b/content/04-guides/01-database-workflows/07-data-validation/index.mdx @@ -1,4 +1,4 @@ --- -title: 'Renaming tables and columns' +title: 'Data validation' metaTitle: '' --- From 6f3f1cb02012efc9fcb27c7224a4166a16015a4c Mon Sep 17 00:00:00 2001 From: Nikolas Burk Date: Tue, 24 Mar 2020 07:48:26 +0100 Subject: [PATCH 3/6] continue docs --- .../02-understand-prisma/05-data-modeling.mdx | 6 ++-- .../04-introspection.mdx | 33 +++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/content/02-understand-prisma/05-data-modeling.mdx b/content/02-understand-prisma/05-data-modeling.mdx index b7f93b8845..b1d1d7dd44 100644 --- a/content/02-understand-prisma/05-data-modeling.mdx +++ b/content/02-understand-prisma/05-data-modeling.mdx @@ -58,12 +58,12 @@ It has the following columns: - `user_id`: An integer that increments with every new record in the `users` table. It also represents the [primary key](https://en.wikipedia.org/wiki/Primary_key) for each record. - `name`: A string with at most 255 characters. -- `email`: A string with at most 255 characters. Additionaly, the added constraints express that no two records can have duplicate values for the `email` column, and that _every_ record needs to have a value for it. +- `email`: A string with at most 255 characters. Additionally, the added constraints express that no two records can have duplicate values for the `email` column, and that _every_ record needs to have a value for it. - `isAdmin`: A boolean that indicates whether the user has admin rights. ### Data modeling on the application level -Additionally to creating the tables that represent the entities from your application domain, you also need to create application models in your programming language. In object-oriented languages, this is often done by creating _classes_ to represent your models. Depending on the programming language, this might also be done with _interfaces_ or _structs_. +In addition to creating the tables that represent the entities from your application domain, you also need to create application models in your programming language. In object-oriented languages, this is often done by creating _classes_ to represent your models. Depending on the programming language, this might also be done with _interfaces_ or _structs_. There often is a strong correlation between the tables in your database and the models you define in your code. For example, to represent records from the aforementioned `users` table in your application, you might define a JavaScript (ES6) class looking similar to this: @@ -185,7 +185,7 @@ export declare type User = { }; ``` -Addtionally to the generated types, Prisma Client also provides a data access API that you can use once you've installed the `@prisma/client` package: +In addition to the generated types, Prisma Client also provides a data access API that you can use once you've installed the `@prisma/client` package: ```js import { PrismaClient } from '@prisma/client' diff --git a/content/03-reference/01-tools-and-interfaces/04-introspection.mdx b/content/03-reference/01-tools-and-interfaces/04-introspection.mdx index 7575bb41c9..a1e1eb77bc 100644 --- a/content/03-reference/01-tools-and-interfaces/04-introspection.mdx +++ b/content/03-reference/01-tools-and-interfaces/04-introspection.mdx @@ -8,5 +8,38 @@ metaDescription: '' You can introspect your database using the Prisma CLI in order to generate the [data model]() in your [Prisma schema](). The data model is needed to [generate Prisma Client](). +Introspection is often used to generate an _initial_ version of the data model when [adding Prisma to an existing project](). However, it can also be used _repeatedly_ in an application. This is most commonly the case when you're _not_ using [Prisma Migrate]() but perform schema migrations using plain SQL or another migration tool. In that case, you also need to re-introspect your database and subsequently re-generate Prisma Client to reflect the schema changes in your [Prisma Client API](). +## What does introspection do? +Introspection has one main goal: Populate your Prisma schema with a data model that reflects the current database schema. + +![](https://imgur.com/EYC3RIK.png) + +Here's an overview of its main functions: + +- Map _tables_ in the database to [Prisma models]() +- Map _columns_ in the database to the [fields]() of Prisma models +- Map _indexes_ in the database to [indexes]() in the Prisma schema +- Map _database_ constraints to corresponding [attributes]() in the Prisma schema + + +## The `prisma introspect` command + +You can introspect your database using the `prisma introspect` command of the [Prisma CLI](). + + +> **Warning**: The `prisma introspect` command overwrites the current version of your Prisma schema! If you made any manual adjustments to the Prisma schema (e.g. by adding [comments](), [making a 1-1-relation required on both sides]() or [configuring your Prisma Client API]()), be sure to back up your schema before running the command! + + +Here's a high-level overview of the steps that `prisma introspect` performs internally: + +1. Read the [connection URL]() from the `datasource` configuration in the Prisma schema +1. Open database connection +1. Introspect database schema (i.e. read tables, columns and other structures ...) +1. Transform database schema into Prisma data model +1. Write data model into Prisma schema + +## Introspection workflows + +![](https://imgur.com/8Tp9jRL.png) From e8ea0774e0c0b8d6aa5babf39212e11db8e962cf Mon Sep 17 00:00:00 2001 From: Nikolas Burk Date: Tue, 24 Mar 2020 09:11:23 +0100 Subject: [PATCH 4/6] continue docs --- content/02-understand-prisma/02-features.mdx | 9 +------- .../01-prisma-schema/02-data-sources.mdx | 2 +- .../01-prisma-schema/05-models.mdx | 5 ++-- .../01-prisma-schema/06-relations.mdx | 6 ++--- .../04-introspection.mdx | 23 +++++++++++++++---- 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/content/02-understand-prisma/02-features.mdx b/content/02-understand-prisma/02-features.mdx index 15a5140979..a19329fef5 100644 --- a/content/02-understand-prisma/02-features.mdx +++ b/content/02-understand-prisma/02-features.mdx @@ -99,17 +99,10 @@ Lock option (MySQL): | `autoincrement()` | Yes (via the `SERIAL` type) | Yes (via the `AUTO_INCREMENT` keyword) | Yes (via the `AUTOINCREMENT` keyword) | | `now()` | Yes | Yes | -## Type mappings between Prisma and database - -TBD for different scenarios: - -- Introspection -- Migrations -- Raw SQL ## Queries (Prisma Client API) -- eager and lazy loading +- CRUD - field selection - raw database access - advanced filter api on relations diff --git a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/02-data-sources.mdx b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/02-data-sources.mdx index c485b17a47..c854b185e6 100644 --- a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/02-data-sources.mdx +++ b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/02-data-sources.mdx @@ -1,5 +1,5 @@ --- -title: 'Connectors' +title: 'Data sources' metaTitle: '' metaDescription: '' --- diff --git a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/05-models.mdx b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/05-models.mdx index 2aaff84114..ca94c59079 100644 --- a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/05-models.mdx +++ b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/05-models.mdx @@ -37,7 +37,7 @@ Models are typically spelled in [PascalCase](http://wiki.c2.com/?PascalCase) and Technically, a model can be named anything that adheres to this regular expression: ``` -[A-Za-z_][A-Za-z0-9_]* +[A-Za-z][A-Za-z0-9_]* ``` Note that naming conventions in databases wildly differ. A common approach for naming tables in databases is to use plural form and [snake_case](https://en.wikipedia.org/wiki/Snake_case) notation, e.g. `users`. When introspecting a database where a table is called `users`, you'll end up with a model looking similar to this: @@ -161,9 +161,10 @@ When annotated with the `[]` type modifier, a field becomes a list. This means i #### Optional vs required + When **not** annotating a field with the `?` type modifier, the field will be _required_ on every record of the model. This has effects on two levels: -- **Database**: Required fields are represented via `NOT NULL` constraintß in the underlying database. +- **Database**: Required fields are represented via `NOT NULL` constraints in the underlying database. - **Prisma Client**: Prisma Client's generated [TypeScript types](#type-definitions) that represent the models in your application code will also define these fields as required to ensure they always carry values at runtime. ### Model attributes diff --git a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/06-relations.mdx b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/06-relations.mdx index 42b967fc27..a5f0c174f5 100644 --- a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/06-relations.mdx +++ b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/06-relations.mdx @@ -195,9 +195,9 @@ For **1-1 and 1-n relations**, pne side of the relation represents a foreign key ![](https://imgur.com/kOO4eh2.png) -For **implicit m-n-relations**, both relation fields are virtual since neither of them directly maps to a foreign key: +For **implicit m-n-relations**, both relation fields are virtual since neither of them _directly_ maps to a foreign key: -![](https://imgur.com/01pxhWM.png) +![](https://imgur.com/DxuOs88.png) Prisma always requires both sides of a relation to be present, this means that one virtual relation field always needs to be added per relation. When [formatting the Prisma schema](), the formatter automatically inserts any missing virtual relation fields for you to save some typing work. @@ -436,7 +436,7 @@ To summarize, these are the rules for determining which side of a 1-1-relation h Here's the summary in the form of a table assuming the two relation fields of the models from before `Profile.user` and `User.profile`: -| `Prrofile.user` | `User.profile` | Foreign key on | `@relation` attribute | +| `Profile.user` | `User.profile` | Foreign key on | `@relation` attribute | | :------------------------ | :------------------------ | ------------------------------------------------------------ | ------------------------------------------------- | | Required | Optional | `Profile` (because the relation field on `User` is virtual) | Can't be used to determine the foreign key | | Optional | Required | `User` (because the relation field on `Profile` is virtual) | Can't be used to determine the foreign key | diff --git a/content/03-reference/01-tools-and-interfaces/04-introspection.mdx b/content/03-reference/01-tools-and-interfaces/04-introspection.mdx index a1e1eb77bc..7c4cfb1e2e 100644 --- a/content/03-reference/01-tools-and-interfaces/04-introspection.mdx +++ b/content/03-reference/01-tools-and-interfaces/04-introspection.mdx @@ -8,7 +8,7 @@ metaDescription: '' You can introspect your database using the Prisma CLI in order to generate the [data model]() in your [Prisma schema](). The data model is needed to [generate Prisma Client](). -Introspection is often used to generate an _initial_ version of the data model when [adding Prisma to an existing project](). However, it can also be used _repeatedly_ in an application. This is most commonly the case when you're _not_ using [Prisma Migrate]() but perform schema migrations using plain SQL or another migration tool. In that case, you also need to re-introspect your database and subsequently re-generate Prisma Client to reflect the schema changes in your [Prisma Client API](). +Introspection is often used to generate an _initial_ version of the data model when [adding Prisma to an existing project](). However, it can also be used _repeatedly_ in an application. This is most commonly the case when you're _not_ using [Prisma Migrate]() but perform schema migrations using plain SQL or another migration tool. In that case, you also need to re-introspect your database and subsequently re-generate Prisma Client to reflect the schema changes in your [Prisma Client API](). ## What does introspection do? @@ -23,15 +23,12 @@ Here's an overview of its main functions: - Map _indexes_ in the database to [indexes]() in the Prisma schema - Map _database_ constraints to corresponding [attributes]() in the Prisma schema - ## The `prisma introspect` command -You can introspect your database using the `prisma introspect` command of the [Prisma CLI](). - +You can introspect your database using the `prisma introspect` command of the [Prisma CLI](). Note that using this command requires your [connection URL]() to be set in your Prisma schema! > **Warning**: The `prisma introspect` command overwrites the current version of your Prisma schema! If you made any manual adjustments to the Prisma schema (e.g. by adding [comments](), [making a 1-1-relation required on both sides]() or [configuring your Prisma Client API]()), be sure to back up your schema before running the command! - Here's a high-level overview of the steps that `prisma introspect` performs internally: 1. Read the [connection URL]() from the `datasource` configuration in the Prisma schema @@ -40,6 +37,22 @@ Here's a high-level overview of the steps that `prisma introspect` performs inte 1. Transform database schema into Prisma data model 1. Write data model into Prisma schema +## Rules and conventions + +Prisma employs a number of conventions for translating a database schema into a Prisma data model: + +- Field, model and enum names (identifiers) must start with a letter and generally must only contain underscores, letters and digits. +- If invalid characters appear before a letter in an identifier, they get dropped. If they appear after the initial letter, they are replaced by an underscorce. Additionally, the transformed name is mapped to the database using `@map` or `@@map` to retain the original name. +- If sanitization results in duplicate identifiers, no immediate error handling is in place. You get the error later and can manually fix it. +- Relation names for a relation between models `A` and `B` are generated as `AToB` (the model that comes first in alphabetical order also appears first in the generated relation name). If relation names turn out to be ambiguous because there is more than one relation between models `A` and `B`, the field name of the column that holds the foreign key is appended to the model name after an underscore to disambiguate, e.g.: `A_FieldWithFKToB`. +- The name of the virtual relation field is based on the opposing model. It gets camel cases by defauld and pluralized (unless the column with the foreign key also has a unique constraint). If back-relation fields are ambiguous, the relation name is appended to disambiguate. + +## Introspecting only a subset of your database schema + +Introspecting only a subset of your database schema is [not yet officially supported](https://github.com/prisma/prisma2/issues/807) by Prisma. + +However, you can achieve this by creating a new database user that only has access to the tables which you'd like to see represented in your Prisma schema, and then perform the introspection using that user. The introspection will then only include the tables the new user has access to. + ## Introspection workflows ![](https://imgur.com/8Tp9jRL.png) From f4ffe0b2e0df54c255de38203310f10c8ba3b3ef Mon Sep 17 00:00:00 2001 From: Nikolas Burk Date: Tue, 24 Mar 2020 11:16:49 +0100 Subject: [PATCH 5/6] continue docs --- .../01-prisma-schema/04-data-model.mdx | 11 + .../01-prisma-schema/05-models.mdx | 6 +- .../02-configuring-the-prisma-client-api.mdx | 59 ++++- .../04-introspection.mdx | 241 +++++++++++++++++- 4 files changed, 301 insertions(+), 16 deletions(-) diff --git a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/04-data-model.mdx b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/04-data-model.mdx index cd896dbc64..cb8d9115df 100644 --- a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/04-data-model.mdx +++ b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/04-data-model.mdx @@ -149,6 +149,17 @@ Enums are considered [scalar](#scalar-types) types in the Prisma data model. The Enums are defined via the `enum` block. + +## Naming enums + +Enum names must start with a letter. They are are typically spelled in [PascalCase](http://wiki.c2.com/?PascalCase) and use the singular form (e.g. `Role` instead of `role`, `roles` or `Roles`). + +Technically, an enum can be named anything that adheres to this regular expression: + +``` +[A-Za-z][A-Za-z0-9_]* +``` + ### Examples **Specify an `enum` with two possible values** diff --git a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/05-models.mdx b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/05-models.mdx index ca94c59079..8f7bc97061 100644 --- a/content/03-reference/01-tools-and-interfaces/01-prisma-schema/05-models.mdx +++ b/content/03-reference/01-tools-and-interfaces/01-prisma-schema/05-models.mdx @@ -32,7 +32,7 @@ On a technical level, a model maps to the underlying structures of the data sour ## Naming models -Models are typically spelled in [PascalCase](http://wiki.c2.com/?PascalCase) and use the singular form (e.g. `User` instead of `user`, `users` or `Users`). +Model names must start with a letter. They are are typically spelled in [PascalCase](http://wiki.c2.com/?PascalCase) and use the singular form (e.g. `User` instead of `user`, `users` or `Users`). Technically, a model can be named anything that adheres to this regular expression: @@ -99,12 +99,12 @@ Here's an overview of these for the fields from the `User` model [above](#exampl ### Naming fields -Field names are typically spelled in [camelCase](http://wiki.c2.com/?CamelCase). +Field names _must_ start with a letter and are typically spelled in [camelCase](http://wiki.c2.com/?CamelCase). Technically, a field can be named anything that adheres to this regular expression: ``` -[A-Za-z_][A-Za-z0-9_]* +[A-Za-z][A-Za-z0-9_]* ``` > **Note**: There's currently a [bug](https://github.com/prisma/prisma2/issues/259) that doesn't allow for field names prepended with an underscore. The current regular expression for valid field names therefore is: `[A-Za-z][A-Za-z0-9_]*` diff --git a/content/03-reference/01-tools-and-interfaces/02-prisma-client/02-configuring-the-prisma-client-api.mdx b/content/03-reference/01-tools-and-interfaces/02-prisma-client/02-configuring-the-prisma-client-api.mdx index af7006ed8f..efbb9ac6f6 100644 --- a/content/03-reference/01-tools-and-interfaces/02-prisma-client/02-configuring-the-prisma-client-api.mdx +++ b/content/03-reference/01-tools-and-interfaces/02-prisma-client/02-configuring-the-prisma-client-api.mdx @@ -107,9 +107,9 @@ model User { } ``` -**Naming of relation fields** +**Naming of foreign key relation fields** -Foreign keys are represented as _relation fields_ in the Prisma schema. Here's how all the relations from the SQL schema are represented: +Foreign keys are represented as [relation fields]() in the Prisma schema. Here's how all the relations from the SQL schema are represented: ```prisma model categories { @@ -240,4 +240,57 @@ const userByProfile = await prisma.profile .user(); ``` -> **Warning**: `@map` and `@@map` attributes are removed when you run `prisma introspect` again. You might want to back up your Prisma schema with these attributes in order to not having to annotate everything from scratch again after a re-introspection. +> **Warning**: `@map` and `@@map` attributes are removed when you run `prisma introspect` again. You therefore might want to back up your Prisma schema with these attributes in order to not having to annotate everything from scratch again after a re-introspection. + +## Renaming virtual relation fields + +[Virtual relation fields]() only exist in the Prisma schema, but are not actually manifested in the underlying database. You can therefore name these fields whatever you want. + +Consider the following example of an ambiguous relation in a SQL database: + +```sql +CREATE TABLE "User" ( + id SERIAL PRIMARY KEY +); +CREATE TABLE "Post" ( + id SERIAL PRIMARY KEY, + "author" integer NOT NULL, + "favoritedBy" INTEGER, + FOREIGN KEY ("author") REFERENCES "User"(id), + FOREIGN KEY ("favoritedBy") REFERENCES "User"(id) +); +``` + +Prism's introspection will result in the following Prisma schema: + +```prisma +model Post { + id Int @default(autoincrement()) @id + author User @relation("Post_authorToUser", references: [id]) + favoritedBy User? @relation("Post_favoritedByToUser", references: [id]) +} + +model User { + id Int @default(autoincrement()) @id + Post_Post_authorToUser Post[] @relation("Post_authorToUser") + Post_Post_favoritedByToUser Post[] @relation("Post_favoritedByToUser") +} +``` + +Since the names of the virtual relation fields `Post_Post_authorToUser` and `Post_Post_favoritedByToUser` are based on the generated relation names, they don't look very friendly in the Prisma Client API. In that case, you can rename the relation fields to anything you like, e.g.: + +```prisma +model Post { + id Int @default(autoincrement()) @id + author User @relation("Post_authorToUser", references: [id]) + favoritedBy User? @relation("Post_favoritedByToUser", references: [id]) +} + +model User { + id Int @default(autoincrement()) @id + writtenPost Post[] @relation("Post_authorToUser") + favoritedPosts Post[] @relation("Post_favoritedByToUser") +} +``` + +> **Warning**: Virtual relation fields that were renamed in the Prisma schema will be reset when you run `prisma introspect` again. You therefore might want to back up your Prisma schema with these attributes in order to not having to annotate everything from scratch again after a re-introspection. \ No newline at end of file diff --git a/content/03-reference/01-tools-and-interfaces/04-introspection.mdx b/content/03-reference/01-tools-and-interfaces/04-introspection.mdx index 7c4cfb1e2e..2e79c65f79 100644 --- a/content/03-reference/01-tools-and-interfaces/04-introspection.mdx +++ b/content/03-reference/01-tools-and-interfaces/04-introspection.mdx @@ -8,7 +8,9 @@ metaDescription: '' You can introspect your database using the Prisma CLI in order to generate the [data model]() in your [Prisma schema](). The data model is needed to [generate Prisma Client](). -Introspection is often used to generate an _initial_ version of the data model when [adding Prisma to an existing project](). However, it can also be used _repeatedly_ in an application. This is most commonly the case when you're _not_ using [Prisma Migrate]() but perform schema migrations using plain SQL or another migration tool. In that case, you also need to re-introspect your database and subsequently re-generate Prisma Client to reflect the schema changes in your [Prisma Client API](). +Introspection is often used to generate an _initial_ version of the data model when [adding Prisma to an existing project](). + +However, it can also be used _repeatedly_ in an application. This is most commonly the case when you're _not_ using [Prisma Migrate]() but perform schema migrations using plain SQL or another migration tool. In that case, you also need to re-introspect your database and subsequently re-generate Prisma Client to reflect the schema changes in your [Prisma Client API](). ## What does introspection do? @@ -21,7 +23,13 @@ Here's an overview of its main functions: - Map _tables_ in the database to [Prisma models]() - Map _columns_ in the database to the [fields]() of Prisma models - Map _indexes_ in the database to [indexes]() in the Prisma schema -- Map _database_ constraints to corresponding [attributes]() in the Prisma schema +- Map _database_ constraints to [attributes]() or [type modifiers]() in the Prisma schema + +You can learn more about how Prisma maps types from the database to the types available in the Prisma schema on the respective docs page for the data source connector: + +- [PostgreSQL]() +- [MySQL]() +- [SQLite]() ## The `prisma introspect` command @@ -37,15 +45,231 @@ Here's a high-level overview of the steps that `prisma introspect` performs inte 1. Transform database schema into Prisma data model 1. Write data model into Prisma schema +## Introspection workflow + +The typical workflow for projects that are not using Prisma Migrate, but instead use plain SQL or another migration tool looks as follows: + +1. Change the database schema (e.g. using plain SQL) +1. Run `prisma introspect` to update the Prisma schema +1. Run `prisma generate` to update Prisma Client +1. Use the updated Prisma Client in your application + +Note that as you evolve the application, this process can be repeated for an indefinite number of times. + +![](https://imgur.com/8Tp9jRL.png) + + ## Rules and conventions Prisma employs a number of conventions for translating a database schema into a Prisma data model: -- Field, model and enum names (identifiers) must start with a letter and generally must only contain underscores, letters and digits. -- If invalid characters appear before a letter in an identifier, they get dropped. If they appear after the initial letter, they are replaced by an underscorce. Additionally, the transformed name is mapped to the database using `@map` or `@@map` to retain the original name. -- If sanitization results in duplicate identifiers, no immediate error handling is in place. You get the error later and can manually fix it. -- Relation names for a relation between models `A` and `B` are generated as `AToB` (the model that comes first in alphabetical order also appears first in the generated relation name). If relation names turn out to be ambiguous because there is more than one relation between models `A` and `B`, the field name of the column that holds the foreign key is appended to the model name after an underscore to disambiguate, e.g.: `A_FieldWithFKToB`. -- The name of the virtual relation field is based on the opposing model. It gets camel cases by defauld and pluralized (unless the column with the foreign key also has a unique constraint). If back-relation fields are ambiguous, the relation name is appended to disambiguate. +### Model, field and enum names + +Field, model and enum names (identifiers) must start with a letter and generally must only contain underscores, letters and digits. You can find the naming rules and conventions for each of these identifiers on the respective docs page: + +- [Naming models]() +- [Naming fields]() +- [Naming enums]() + +The general rule for identifiers is that they need to adhere to this regular expression: + +``` +[A-Za-z][A-Za-z0-9_]* +``` + +**Invalid characters** are being sanitized during introspection: + +- If they appear _before_ a letter in an identifier, they get dropped. +- If they appear _after_ the first letter, they get replaced by an underscorce. + +Additionally, the transformed name is mapped to the database using `@map` or `@@map` to retain the original name. + +Consider the following table as an example: + +```sql +CREATE TABLE "42User" ( + _id SERIAL PRIMARY KEY, + _name VARCHAR(255), + two$two INTEGER +); +``` + +Because the leading `5` in the table name as well as the leading underscores and the `$` on the columns are forbidden in Prisma, introspection adds the `@map` and `@@map` attributes so that these names adhere to Prisma's naming conventions: + +```prisma +model User { + id Int @default(autoincrement()) @id @map("_id") + name String? @map("_name") + two_two Int? @map("two$two") + + @@map("42User") +} +``` + +If sanitization results in duplicate identifiers, no immediate error handling is in place. You get the error later and can manually fix it. Consider the case of the following two tables: + +```sql +CREATE TABLE "42User" ( + _id SERIAL PRIMARY KEY +); + +CREATE TABLE "24User" ( + _id SERIAL PRIMARY KEY +); +``` + +This would result in the following introspection result: + +```prisma +model User { + id Int @default(autoincrement()) @id @map("_id") + + @@map("42User") +} + +model User { + id Int @default(autoincrement()) @id @map("_id") + + @@map("24User") +} +``` + +In this case, you must manually change the name of one of the two generated `User` models because duplicate model names are not allowed in the Prisma schema. + +### Relations + +Prisma translates foreign keys that are defined on your database tables into [relations](). + +#### One-to-one relations + +Prisma adds a [one-to-one]() relation to your data model when the foreign key on a table has a `UNIQUE` constraint, e.g.: + +```sql +CREATE TABLE "User" ( + id SERIAL PRIMARY KEY +); +CREATE TABLE "Profile" ( + id SERIAL PRIMARY KEY, + "user" integer NOT NULL UNIQUE, + FOREIGN KEY ("user") REFERENCES "User"(id) +); +``` + +Prisma translates this into the following data model: + +```prisma +model User { + id Int @id @default(autoincrement()) + profile Profile? +} + +model Profile { + id Int @id @default(autoincrement()) + user User +} +``` + +Note that you can still [make both sides of the relation required]() by manually removing the `?` on `User.profile`: + +```prisma +model User { + id Int @id @default(autoincrement()) + profile Profile +} + +model Profile { + id Int @id @default(autoincrement()) + user User +} +``` + +The required constraint will be enforced by Prisma Client. + +#### One-to-many relations + +By default, Prisma adds a [one-to-many]() relation to your data model for a foreign key it finds in your database schema: + +```sql +CREATE TABLE "User" ( + id SERIAL PRIMARY KEY +); +CREATE TABLE "Post" ( + id SERIAL PRIMARY KEY, + "author" integer NOT NULL, + FOREIGN KEY ("author") REFERENCES "User"(id) +); +``` + +These tables are transformed into the following models: + +```prisma +model Post { + id Int @default(autoincrement()) @id + author User @relation(references: [id]) +} + +model User { + id Int @default(autoincrement()) @id + Post Post[] +} +``` + +#### Many-to-many relations + +Many-to-many relations are commonly represented as [relation tables]() in relational databases. + +Prisma supports two ways for defining many-to-many relations in the Prisma schema: + +- [Implicit many-to-many relations]() (Prisma manages the relation table under the hood) +- [Explicit many-to-many relations]() (the relation table is present as a [model]()) + +_Implicit_ many-to-many relations are recognized if they adhere to Prisma's [conventions for relation tables](). Otherwise the relation table is rendered in the Prisma schema as a model (therefore making it an _explicit_ many-to-many relation). + +This topic is covered extensivelty on the docs page about [relations](). + +#### Disambiguating relations + +Prisma generally omits the `name` argument on the [`@relation`]() attribute if it's not needed. Consider the `User` ↔ `Post` example from the previous section. The `@relation` attribute only has the `references` argument, `name` is omitted because it's not needed in this case: + +```prisma +model Post { + id Int @default(autoincrement()) @id + author User @relation(references: [id]) +} +``` + +It would be needed if there were _two_ foreign keys defined on the `Post` table: + +```sql +CREATE TABLE "User" ( + id SERIAL PRIMARY KEY +); +CREATE TABLE "Post" ( + id SERIAL PRIMARY KEY, + "author" integer NOT NULL, + "favoritedBy" INTEGER, + FOREIGN KEY ("author") REFERENCES "User"(id), + FOREIGN KEY ("favoritedBy") REFERENCES "User"(id) +); +``` + +In this case, Prisma needs to [disambiguate the relation]() using a dedicated relation name: + +```prisma +model Post { + id Int @default(autoincrement()) @id + author User @relation("Post_authorToUser", references: [id]) + favoritedBy User? @relation("Post_favoritedByToUser", references: [id]) +} + +model User { + id Int @default(autoincrement()) @id + Post_Post_authorToUser Post[] @relation("Post_authorToUser") + Post_Post_favoritedByToUser Post[] @relation("Post_favoritedByToUser") +} +``` + +Note that you can [rename the virtual relation field]() to anything you like so that it looks friendlier in the generated Prisma Client API. ## Introspecting only a subset of your database schema @@ -53,6 +277,3 @@ Introspecting only a subset of your database schema is [not yet officially suppo However, you can achieve this by creating a new database user that only has access to the tables which you'd like to see represented in your Prisma schema, and then perform the introspection using that user. The introspection will then only include the tables the new user has access to. -## Introspection workflows - -![](https://imgur.com/8Tp9jRL.png) From 5917a6dcde511309467cabc2aa1af709904352d1 Mon Sep 17 00:00:00 2001 From: Nikolas Burk Date: Tue, 24 Mar 2020 13:50:51 +0100 Subject: [PATCH 6/6] continue docs --- content/03-reference/03-more/01-editor-setup.mdx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/content/03-reference/03-more/01-editor-setup.mdx b/content/03-reference/03-more/01-editor-setup.mdx index f19c0a7250..b8f2801cac 100644 --- a/content/03-reference/03-more/01-editor-setup.mdx +++ b/content/03-reference/03-more/01-editor-setup.mdx @@ -4,4 +4,12 @@ metaTitle: '' metaDescription: '' --- -Coming 🔜 +## Overview + +This page describes how you can configure your editor for an optimal developer experience when using Prisma. + +If you don't see you editor here, please [open a feature request]() and ask for dedicated support for your editor (e.g. for syntax highlighting and auto-formatting). + +## VS Code + +You can install the [Prisma VS Code extension](). \ No newline at end of file