Skip to content

Commit 09bc0d2

Browse files
authored
docs: add auto-generated primary key sample for Prisma (GoogleCloudPlatform#3085)
Add a model that uses an auto-generated primary key to the Prisma sample application.
1 parent c34d047 commit 09bc0d2

5 files changed

Lines changed: 71 additions & 31 deletions

File tree

samples/nodejs/prisma-sample-app/README.md

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ The following limitations are currently known:
121121
| Migrations | Cloud Spanner does not support the full PostgreSQL DDL dialect, and also not all `pg_catalog` tables and functions. PGAdapter contains translations for the most commonly used features that are not supported. It is possible to use Prisma Migrations with PGAdapter, but some migrations are likely to require manual modifications. |
122122
| Shadow Database | Cloud Spanner cannot be used as a shadow database. Instead, you need to set up a real PostgreSQL database and use that as the shadow database. See https://www.prisma.io/docs/concepts/components/prisma-migrate/shadow-database#cloud-hosted-shadow-databases-must-be-created-manually |
123123
| Advisory locks | Advisory locks are not supported. Prisma will try to use this during migrations. These commands will be ignored by PGAdapter. |
124-
| Generated primary keys | Auto-generated primary keys are not supported. Do not add the `@default(autoincrement())` annotation to your model definitions. |
124+
| Generated primary keys | Auto-generated primary keys are supported, but do not generate a monotonically increasing value. The `@default(autoincrement())` annotation in combination with the `serial` data type will generate bit-reversed sequential values that are safe from causing hotspots in your database. |
125125
| Upsert | Upsert is not supported. |
126126

127127
### Migrations
@@ -158,25 +158,22 @@ Cloud Spanner and PGAdapter do not support advisory locks. The advisory lock sta
158158
therefore be ignored and have no effect.
159159

160160
### Generated Primary Keys
161-
Generated primary keys are not supported and should be replaced with primary key definitions that
162-
are manually assigned. See https://cloud.google.com/spanner/docs/schema-design#primary-key-prevent-hotspots
163-
for more information on choosing a good primary key. This sample uses UUIDs that are generated by the
164-
application for primary keys.
161+
Generated primary keys are supported and use values that are not monotonically increasing. This
162+
prevents hotspots in your database. See https://cloud.google.com/spanner/docs/schema-design#primary-key-prevent-hotspots
163+
for more information. The `TicketSale` model in this sample uses an auto-generated primary key. The
164+
primary key is generated by a column with type `serial`, which uses a backing bit-reversed sequence
165+
to generate unique values.
165166

166167
```typescript
167-
model Singer {
168-
id String @id
169-
createdAt DateTime @default(now())
170-
updatedAt DateTime @updatedAt
171-
firstName String
172-
lastName String
173-
/// `fullName` is generated by the database and should not be set.
174-
fullName String?
175-
active Boolean
176-
albums Album[]
177-
Concert Concert[]
178-
179-
@@index(lastName)
168+
model TicketSale {
169+
id Int @id @default(autoincrement())
170+
createdAt DateTime @default(now())
171+
updatedAt DateTime @updatedAt
172+
concert Concert @relation(fields: [concertId], references: [id])
173+
concertId String
174+
customerName String
175+
price Decimal
176+
seats String[]
180177
}
181178
```
182179

@@ -187,4 +184,4 @@ column for the `fullName` property of `Singer`. See [migration.sql](prisma/migra
187184
for an example.
188185

189186
### Upsert
190-
`Upsert` statements are not supported by Cloud Spanner and should not be used.
187+
`Upsert` statements are not supported by Spanner and should not be used.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- CreateTable
2+
CREATE TABLE "TicketSale" (
3+
"id" SERIAL PRIMARY KEY,
4+
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
5+
"updatedAt" TIMESTAMP(3) NOT NULL,
6+
"concertId" TEXT NOT NULL,
7+
"customerName" TEXT NOT NULL,
8+
"price" NUMERIC,
9+
"seats" TEXT[] NOT NULL,
10+
CONSTRAINT "TicketSale_concertId_fkey" FOREIGN KEY ("concertId") REFERENCES "Concert"("id") ON DELETE RESTRICT ON UPDATE CASCADE
11+
);

samples/nodejs/prisma-sample-app/prisma/schema.prisma

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,27 @@ model Venue {
5757
}
5858

5959
model Concert {
60-
id String @id
61-
createdAt DateTime @default(now())
62-
updatedAt DateTime @updatedAt
63-
name String
64-
venue Venue @relation(fields: [venueId], references: [id])
65-
venueId String
66-
singer Singer @relation(fields: [singerId], references: [id])
67-
singerId String
68-
startTime DateTime @db.Timestamptz
69-
endTime DateTime @db.Timestamptz
60+
id String @id
61+
createdAt DateTime @default(now())
62+
updatedAt DateTime @updatedAt
63+
name String
64+
venue Venue @relation(fields: [venueId], references: [id])
65+
venueId String
66+
singer Singer @relation(fields: [singerId], references: [id])
67+
singerId String
68+
startTime DateTime @db.Timestamptz
69+
endTime DateTime @db.Timestamptz
70+
ticketSales TicketSale[]
7071
@@index([startTime(sort: Desc)])
7172
}
73+
74+
model TicketSale {
75+
id Int @id @default(autoincrement())
76+
createdAt DateTime @default(now())
77+
updatedAt DateTime @updatedAt
78+
concert Concert @relation(fields: [concertId], references: [id])
79+
concertId String
80+
customerName String
81+
price Decimal
82+
seats String[]
83+
}

samples/nodejs/prisma-sample-app/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import {
1616
createPrismaClient,
17-
createRandomSingersAndAlbumsAndTracks,
17+
createRandomSingersAndAlbumsAndTracks, createTicketSale,
1818
createVenueAndConcertInTransaction,
1919
deleteExistingData, deployMigrations, printAlbumsReleasedBefore1900,
2020
printSingersAndAlbums, staleRead, updateVenueDescription
@@ -63,6 +63,7 @@ async function runSample() {
6363
await printAlbumsReleasedBefore1900();
6464
await updateVenueDescription();
6565
await staleRead();
66+
await createTicketSale();
6667

6768
// Run 'npx prisma migrate deploy' once more, just to verify that we can run this command multiple
6869
// times on an existing database.

samples/nodejs/prisma-sample-app/src/sample.ts

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,12 @@ export async function deployMigrations() {
5454
}
5555

5656
export async function deleteExistingData() {
57+
console.log("Deleting all existing ticket sales");
58+
let result = await prisma.ticketSale.deleteMany({});
59+
console.log(`Deleted ${result.count} ticket sales`);
60+
5761
console.log("Deleting all existing concerts");
58-
let result = await prisma.concert.deleteMany({});
62+
result = await prisma.concert.deleteMany({});
5963
console.log(`Deleted ${result.count} concerts`);
6064

6165
console.log("Deleting all existing albums and related tracks");
@@ -185,6 +189,21 @@ export async function createVenueAndConcertInTransaction() {
185189
console.log();
186190
}
187191

192+
export async function createTicketSale() {
193+
console.log("Creating a ticket sale. Ticket sale uses an auto-generated primary key");
194+
const concert = await prisma.concert.findFirst({});
195+
const ticketSale = await prisma.ticketSale.create({
196+
data: {
197+
concertId: concert.id,
198+
customerName: "Alice Neeson",
199+
price: 99.50,
200+
seats: ["A11", "A12", "A13"],
201+
}
202+
});
203+
console.log(`Created a ticket sale with id ${ticketSale.id}`);
204+
console.log();
205+
}
206+
188207
export async function printAlbumsReleasedBefore1900() {
189208
console.log("Searching for albums released before 1900");
190209
const albums = await prisma.album.findMany({

0 commit comments

Comments
 (0)