From 6a6597c6571849ae46d5cdec9533d4ac0d8c44f7 Mon Sep 17 00:00:00 2001 From: Vyacheslav Matyukhin Date: Tue, 5 Apr 2022 23:38:40 +0300 Subject: [PATCH] WIP: more prisma migrate --- package-lock.json | 39 ++++++++ package.json | 1 + prisma/schema.prisma | 48 +++++++++- .../{manual => migrate}/noSchemaMigrate.ts | 0 src/backend/migrate/prepareForPrisma.ts | 92 +++++++++++++++++++ 5 files changed, 177 insertions(+), 3 deletions(-) rename src/backend/{manual => migrate}/noSchemaMigrate.ts (100%) create mode 100644 src/backend/migrate/prepareForPrisma.ts diff --git a/package-lock.json b/package-lock.json index a7c11e4..c71052d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "2.0.0", "license": "MIT", "dependencies": { + "@prisma/client": "^3.11.1", "@tailwindcss/forms": "^0.4.0", "@tailwindcss/typography": "^0.5.1", "@types/jsdom": "^16.2.14", @@ -1194,12 +1195,37 @@ "node": ">= 8" } }, + "node_modules/@prisma/client": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.11.1.tgz", + "integrity": "sha512-B3C7zQG4HbjJzUr2Zg9UVkBJutbqq9/uqkl1S138+keZCubJrwizx3RuIvGwI+s+pm3qbsyNqXiZgL3Ir0fSng==", + "hasInstallScript": true, + "dependencies": { + "@prisma/engines-version": "3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9" + }, + "engines": { + "node": ">=12.6" + }, + "peerDependencies": { + "prisma": "*" + }, + "peerDependenciesMeta": { + "prisma": { + "optional": true + } + } + }, "node_modules/@prisma/engines": { "version": "3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9", "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9.tgz", "integrity": "sha512-MILbsGnvmnhCbFGa2/iSnsyGyazU3afzD7ldjCIeLIGKkNBMSZgA2IvpYsAXl+6qFHKGrS3B2otKfV31dwMSQw==", "hasInstallScript": true }, + "node_modules/@prisma/engines-version": { + "version": "3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9.tgz", + "integrity": "sha512-HkcsDniA4iNb/gi0iuyOJNAM7nD/LwQ0uJm15v360O5dee3TM4lWdSQiTYBMK6FF68ACUItmzSur7oYuUZ2zkQ==" + }, "node_modules/@rescript/react": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@rescript%2freact/-/react-0.10.3.tgz", @@ -36242,11 +36268,24 @@ "fastq": "^1.6.0" } }, + "@prisma/client": { + "version": "3.11.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-3.11.1.tgz", + "integrity": "sha512-B3C7zQG4HbjJzUr2Zg9UVkBJutbqq9/uqkl1S138+keZCubJrwizx3RuIvGwI+s+pm3qbsyNqXiZgL3Ir0fSng==", + "requires": { + "@prisma/engines-version": "3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9" + } + }, "@prisma/engines": { "version": "3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9", "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9.tgz", "integrity": "sha512-MILbsGnvmnhCbFGa2/iSnsyGyazU3afzD7ldjCIeLIGKkNBMSZgA2IvpYsAXl+6qFHKGrS3B2otKfV31dwMSQw==" }, + "@prisma/engines-version": { + "version": "3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-3.11.1-1.1a2506facaf1a4727b7c26850735e88ec779dee9.tgz", + "integrity": "sha512-HkcsDniA4iNb/gi0iuyOJNAM7nD/LwQ0uJm15v360O5dee3TM4lWdSQiTYBMK6FF68ACUItmzSur7oYuUZ2zkQ==" + }, "@rescript/react": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@rescript%2freact/-/react-0.10.3.tgz", diff --git a/package.json b/package.json index 65acc65..05ad0ef 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "dbshell": ". .env && psql $DIGITALOCEAN_POSTGRES" }, "dependencies": { + "@prisma/client": "^3.11.1", "@tailwindcss/forms": "^0.4.0", "@tailwindcss/typography": "^0.5.1", "@types/jsdom": "^16.2.14", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3d2f9fd..c69c78f 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,6 +1,3 @@ -// This is your Prisma schema file, -// learn more about it in the docs: https://pris.ly/d/prisma-schema - generator client { provider = "prisma-client-js" } @@ -9,3 +6,48 @@ datasource db { provider = "postgresql" url = env("DIGITALOCEAN_POSTGRES") } + +model dashboards { + id String @id + title String + description String + contents Json + timestamp DateTime @db.Timestamp(6) + creator String + extra Json +} + +model frontpage { + id Int @id @default(autoincrement()) + frontpage_full Json + frontpage_sliced Json +} + +model history { + id String + title String + url String + platform String + description String + options Json + timestamp DateTime @db.Timestamp(6) + stars Int + qualityindicators Json + extra Json + pk Int @id @default(autoincrement()) + + @@index([id]) +} + +model questions { + id String @id + title String + url String + platform String + description String + options Json + timestamp DateTime @db.Timestamp(6) + stars Int + qualityindicators Json + extra Json +} diff --git a/src/backend/manual/noSchemaMigrate.ts b/src/backend/migrate/noSchemaMigrate.ts similarity index 100% rename from src/backend/manual/noSchemaMigrate.ts rename to src/backend/migrate/noSchemaMigrate.ts diff --git a/src/backend/migrate/prepareForPrisma.ts b/src/backend/migrate/prepareForPrisma.ts new file mode 100644 index 0000000..613f9bd --- /dev/null +++ b/src/backend/migrate/prepareForPrisma.ts @@ -0,0 +1,92 @@ +import "dotenv/config"; + +import { readWritePool } from "../database/pg-wrapper"; + +const migrate = async () => { + const client = await readWritePool.connect(); + + const execQuery = async (q: string) => { + console.log(q); + await client.query(q); + }; + + try { + await client.query("BEGIN"); + + const notNullColumn = async (table: string, column: string) => { + await execQuery( + `ALTER TABLE ${table} ALTER COLUMN ${column} SET NOT NULL` + ); + }; + + const jsonbColumn = async (table: string, column: string) => { + await execQuery( + `ALTER TABLE ${table} ALTER COLUMN ${column} SET DATA TYPE jsonb USING ${column}::jsonb` + ); + }; + + const t2c = { + dashboards: [ + "id", + "title", + "description", + "contents", + "timestamp", + "creator", + "extra", + ], + frontpage: ["frontpage_sliced", "frontpage_full"], + history: [ + "id", + "title", + "url", + "platform", + "description", + "options", + "timestamp", + "stars", + "qualityindicators", + "extra", + ], + questions: [ + "id", + "title", + "url", + "platform", + "description", + "options", + "timestamp", + "stars", + "qualityindicators", + "extra", + ], + }; + for (const [table, columns] of Object.entries(t2c)) { + for (const column of columns) { + await notNullColumn(table, column); + } + } + + await execQuery("ALTER TABLE history ADD COLUMN pk SERIAL PRIMARY KEY"); + await execQuery("ALTER TABLE dashboards ADD PRIMARY KEY (id)"); + await execQuery("ALTER TABLE questions ADD PRIMARY KEY (id)"); + + await jsonbColumn("dashboards", "contents"); + await jsonbColumn("dashboards", "extra"); + + for (const table of ["history", "questions"]) { + await jsonbColumn(table, "options"); + await jsonbColumn(table, "qualityindicators"); + await jsonbColumn(table, "extra"); + } + + await client.query("COMMIT"); + } catch (e) { + await client.query("ROLLBACK"); + throw e; + } finally { + client.release(); + } +}; + +migrate();