Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

test(schema-engine): allow SQLite migration to be D1-compatible #4808

Merged
merged 3 commits into from May 5, 2024

Conversation

jkomyno
Copy link
Contributor

@jkomyno jkomyno commented Apr 3, 2024

This PR closes https://github.com/prisma/team-orm/issues/1081.

This PR allows the Prisma Schema Engine to emit Cloudflare D1-compatible migration scripts when provider = "sqlite".
In particular, the PRAGMA foreign_key_check statement, which was previously only used at the end of any SQLite migration script, is now replaced with PRAGMA foreign_key_check("$TABLE"), where $TABLE is the name of the table that was altered by the migration.

When multiple tables are involved in a migration, the expected diff for prisma migrate is:

PRAGMA foreign_keys=OFF;

CREATE TABLE "new_Post" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "title" TEXT NOT NULL,
    "content" TEXT,
    "published" BOOLEAN NOT NULL DEFAULT false,
    "authorId" INTEGER NOT NULL,
    FOREIGN KEY ("authorId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
);
INSERT INTO "new_Post" ("authorId", "content", "id", "published", "title") SELECT "authorId", "content", "id", "published", "title" FROM "Post";
DROP TABLE "Post";
ALTER TABLE "new_Post" RENAME TO "Post";

CREATE TABLE "new_User" (
    "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
    "email" TEXT NOT NULL,
    "name" TEXT
);
INSERT INTO "new_User" ("email", "id", "name") SELECT "email", "id", "name" FROM "User";
DROP TABLE "User";
ALTER TABLE "new_User" RENAME TO "User";

CREATE UNIQUE INDEX "User_email_key" ON "User"("email" ASC);

+ PRAGMA foreign_key_check("Post");
+ PRAGMA foreign_key_check("User");
- PRAGMA foreign_key_check;
PRAGMA foreign_keys=ON;

This is necessary because PRAGMA foreign_key_check("$TABLE"); is allowed by Cloudflare D1, whereas PRAGMA foreign_key_check; isn't.

Note: foreign_key_check PRAGMAs must be run immediately before the PRAGMA foreign_keys=ON; at the end of the migration script. Without that, the following tests would fail with a "foreign key mismatch" SQLite database error:

  • migrations::foreign_keys::changing_all_referenced_columns_of_foreign_key_works
  • migrations::relations::adding_mutual_references_on_existing_tables_works

/integration

@jkomyno jkomyno added this to the 5.13.0 milestone Apr 3, 2024
@jkomyno jkomyno self-assigned this Apr 3, 2024
Copy link
Contributor

github-actions bot commented Apr 3, 2024

WASM Query Engine file Size

Engine This PR Base branch Diff
Postgres 2.126MiB 2.126MiB 0.000B
Postgres (gzip) 836.254KiB 836.254KiB 0.000B
Mysql 2.096MiB 2.096MiB 0.000B
Mysql (gzip) 824.265KiB 824.265KiB 0.000B
Sqlite 1.990MiB 1.990MiB 0.000B
Sqlite (gzip) 784.750KiB 784.749KiB 1.000B

Copy link

codspeed-hq bot commented Apr 3, 2024

CodSpeed Performance Report

Merging #4808 will not alter performance

Comparing feat/d1-compatible-sqlite-migration (61ede41) with main (6d35870)

Summary

✅ 11 untouched benchmarks

…ing_all_referenced_columns_of_foreign_key_works" and "migrations::relations::adding_mutual_references_on_existing_tables_works"
Copy link
Contributor

github-actions bot commented Apr 3, 2024

✅ WASM query-engine performance won't change substantially (0.996x)

Full benchmark report
DATABASE_URL="postgresql://postgres:postgres@localhost:5432/bench?schema=imdb_bench&sslmode=disable" \
node --experimental-wasm-modules query-engine/driver-adapters/executor/dist/bench.mjs
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
"
cpu: AMD EPYC 7763 64-Core Processor
runtime: node v18.20.1 (x64-linux)

benchmark                   time (avg)             (min … max)       p75       p99      p999
-------------------------------------------------------------- -----------------------------
• movies.findMany() (all - ~50K)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     367 ms/iter       (363 ms … 370 ms)    369 ms    370 ms    370 ms
Web Assembly: Latest       462 ms/iter       (455 ms … 472 ms)    463 ms    472 ms    472 ms
Web Assembly: Current      459 ms/iter       (453 ms … 467 ms)    463 ms    467 ms    467 ms
Node API: Current          198 ms/iter       (195 ms … 207 ms)    200 ms    207 ms    207 ms

summary for movies.findMany() (all - ~50K)
  Web Assembly: Current
   2.32x slower than Node API: Current
   1.25x slower than Web Assembly: Baseline
   1.01x faster than Web Assembly: Latest

• movies.findMany({ take: 2000 })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline  15'215 µs/iter (14'916 µs … 15'942 µs) 15'240 µs 15'942 µs 15'942 µs
Web Assembly: Latest    18'414 µs/iter (18'205 µs … 19'767 µs) 18'432 µs 19'767 µs 19'767 µs
Web Assembly: Current   18'435 µs/iter (18'238 µs … 19'452 µs) 18'441 µs 19'452 µs 19'452 µs
Node API: Current        8'123 µs/iter   (7'921 µs … 8'833 µs)  8'217 µs  8'833 µs  8'833 µs

summary for movies.findMany({ take: 2000 })
  Web Assembly: Current
   2.27x slower than Node API: Current
   1.21x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movies.findMany({ where: {...}, take: 2000 })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline   2'299 µs/iter   (2'182 µs … 3'731 µs)  2'281 µs  3'144 µs  3'731 µs
Web Assembly: Latest     2'913 µs/iter   (2'787 µs … 4'718 µs)  2'888 µs  3'964 µs  4'718 µs
Web Assembly: Current    2'856 µs/iter   (2'771 µs … 4'523 µs)  2'846 µs  3'411 µs  4'523 µs
Node API: Current        1'415 µs/iter   (1'316 µs … 1'881 µs)  1'422 µs  1'629 µs  1'881 µs

summary for movies.findMany({ where: {...}, take: 2000 })
  Web Assembly: Current
   2.02x slower than Node API: Current
   1.24x slower than Web Assembly: Baseline
   1.02x faster than Web Assembly: Latest

• movies.findMany({ include: { cast: true } take: 2000 }) (m2m)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     565 ms/iter       (559 ms … 583 ms)    568 ms    583 ms    583 ms
Web Assembly: Latest       782 ms/iter       (776 ms … 800 ms)    786 ms    800 ms    800 ms
Web Assembly: Current      787 ms/iter       (780 ms … 803 ms)    801 ms    803 ms    803 ms
Node API: Current          485 ms/iter       (471 ms … 498 ms)    497 ms    498 ms    498 ms

summary for movies.findMany({ include: { cast: true } take: 2000 }) (m2m)
  Web Assembly: Current
   1.62x slower than Node API: Current
   1.39x slower than Web Assembly: Baseline
   1.01x slower than Web Assembly: Latest

• movies.findMany({ where: {...}, include: { cast: true } take: 2000 }) (m2m)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline  78'430 µs/iter (78'072 µs … 78'792 µs) 78'752 µs 78'792 µs 78'792 µs
Web Assembly: Latest       110 ms/iter       (110 ms … 111 ms)    111 ms    111 ms    111 ms
Web Assembly: Current      112 ms/iter       (111 ms … 112 ms)    112 ms    112 ms    112 ms
Node API: Current       64'420 µs/iter (63'242 µs … 66'617 µs) 65'031 µs 66'617 µs 66'617 µs

summary for movies.findMany({ where: {...}, include: { cast: true } take: 2000 }) (m2m)
  Web Assembly: Current
   1.73x slower than Node API: Current
   1.42x slower than Web Assembly: Baseline
   1.01x slower than Web Assembly: Latest

• movies.findMany({ take: 2000, include: { cast: { include: { person: true } } } })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline   1'013 ms/iter   (1'003 ms … 1'025 ms)  1'024 ms  1'025 ms  1'025 ms
Web Assembly: Latest     1'315 ms/iter   (1'305 ms … 1'323 ms)  1'323 ms  1'323 ms  1'323 ms
Web Assembly: Current    1'321 ms/iter   (1'306 ms … 1'362 ms)  1'330 ms  1'362 ms  1'362 ms
Node API: Current          903 ms/iter       (882 ms … 924 ms)    921 ms    924 ms    924 ms

summary for movies.findMany({ take: 2000, include: { cast: { include: { person: true } } } })
  Web Assembly: Current
   1.46x slower than Node API: Current
   1.3x slower than Web Assembly: Baseline
   1x faster than Web Assembly: Latest

• movie.findMany({ where: { ... }, take: 2000, include: { cast: { include: { person: true } } } })
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline     146 ms/iter       (146 ms … 147 ms)    147 ms    147 ms    147 ms
Web Assembly: Latest       187 ms/iter       (186 ms … 188 ms)    188 ms    188 ms    188 ms
Web Assembly: Current      184 ms/iter       (182 ms … 187 ms)    185 ms    187 ms    187 ms
Node API: Current          108 ms/iter       (106 ms … 111 ms)    111 ms    111 ms    111 ms

summary for movie.findMany({ where: { ... }, take: 2000, include: { cast: { include: { person: true } } } })
  Web Assembly: Current
   1.7x slower than Node API: Current
   1.25x slower than Web Assembly: Baseline
   1.02x faster than Web Assembly: Latest

• movie.findMany({ where: { reviews: { author: { ... } }, take: 100 }) (to-many -> to-one)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline   1'024 µs/iter     (969 µs … 1'702 µs)  1'023 µs  1'434 µs  1'702 µs
Web Assembly: Latest     1'381 µs/iter   (1'297 µs … 2'149 µs)  1'375 µs  1'925 µs  2'149 µs
Web Assembly: Current    1'390 µs/iter   (1'297 µs … 2'387 µs)  1'372 µs  2'131 µs  2'387 µs
Node API: Current          797 µs/iter     (703 µs … 1'464 µs)    805 µs  1'172 µs  1'464 µs

summary for movie.findMany({ where: { reviews: { author: { ... } }, take: 100 }) (to-many -> to-one)
  Web Assembly: Current
   1.74x slower than Node API: Current
   1.36x slower than Web Assembly: Baseline
   1.01x slower than Web Assembly: Latest

• movie.findMany({ where: { cast: { person: { ... } }, take: 100 }) (m2m -> to-one)
-------------------------------------------------------------- -----------------------------
Web Assembly: Baseline   1'038 µs/iter     (976 µs … 1'707 µs)  1'028 µs  1'657 µs  1'707 µs
Web Assembly: Latest     1'384 µs/iter   (1'329 µs … 2'004 µs)  1'388 µs  1'766 µs  2'004 µs
Web Assembly: Current    1'376 µs/iter   (1'326 µs … 1'876 µs)  1'384 µs  1'657 µs  1'876 µs
Node API: Current          789 µs/iter     (719 µs … 1'064 µs)    806 µs    942 µs  1'064 µs

summary for movie.findMany({ where: { cast: { person: { ... } }, take: 100 }) (m2m -> to-one)
  Web Assembly: Current
   1.74x slower than Node API: Current
   1.33x slower than Web Assembly: Baseline
   1.01x faster than Web Assembly: Latest

After changes in 61ede41

@jkomyno jkomyno marked this pull request as ready for review April 4, 2024 08:32
@jkomyno jkomyno requested a review from a team as a code owner April 4, 2024 08:32
@jkomyno jkomyno requested review from laplab and removed request for a team April 4, 2024 08:32
@janpio janpio requested a review from Jolg42 April 12, 2024 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants