From 30033717521e251c44ac8c38c08cfc6218124fa4 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 17 Aug 2022 17:35:52 -0700 Subject: [PATCH 1/7] remove cascading delete --- .../04_remove_casade_delete/migration.sql | 35 +++++++++++++++++++ db/postgresql/schema.prisma | 12 +++---- queries/admin/account/deleteAccount.js | 33 ++++++++++++++--- queries/admin/website/deleteWebsite.js | 28 ++++++++++++--- 4 files changed, 92 insertions(+), 16 deletions(-) create mode 100644 db/postgresql/migrations/04_remove_casade_delete/migration.sql diff --git a/db/postgresql/migrations/04_remove_casade_delete/migration.sql b/db/postgresql/migrations/04_remove_casade_delete/migration.sql new file mode 100644 index 00000000..d0995938 --- /dev/null +++ b/db/postgresql/migrations/04_remove_casade_delete/migration.sql @@ -0,0 +1,35 @@ +-- DropForeignKey +ALTER TABLE "event" DROP CONSTRAINT IF EXISTS "event_session_id_fkey"; + +-- DropForeignKey +ALTER TABLE "event" DROP CONSTRAINT IF EXISTS "event_website_id_fkey"; + +-- DropForeignKey +ALTER TABLE "pageview" DROP CONSTRAINT IF EXISTS "pageview_session_id_fkey"; + +-- DropForeignKey +ALTER TABLE "pageview" DROP CONSTRAINT IF EXISTS "pageview_website_id_fkey"; + +-- DropForeignKey +ALTER TABLE "session" DROP CONSTRAINT IF EXISTS "session_website_id_fkey"; + +-- DropForeignKey +ALTER TABLE "website" DROP CONSTRAINT IF EXISTS "website_user_id_fkey"; + +-- AddForeignKey +ALTER TABLE "event" ADD CONSTRAINT EXISTS "event_session_id_fkey" FOREIGN KEY ("session_id") REFERENCES "session"("session_id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "event" ADD CONSTRAINT "event_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "website"("website_id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "pageview" ADD CONSTRAINT "pageview_session_id_fkey" FOREIGN KEY ("session_id") REFERENCES "session"("session_id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "pageview" ADD CONSTRAINT "pageview_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "website"("website_id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "session" ADD CONSTRAINT "session_website_id_fkey" FOREIGN KEY ("website_id") REFERENCES "website"("website_id") ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "website" ADD CONSTRAINT "website_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "account"("user_id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/db/postgresql/schema.prisma b/db/postgresql/schema.prisma index 19d206d8..1608d32c 100644 --- a/db/postgresql/schema.prisma +++ b/db/postgresql/schema.prisma @@ -24,8 +24,8 @@ model event { created_at DateTime? @default(now()) @db.Timestamptz(6) url String @db.VarChar(500) event_name String @db.VarChar(50) - session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade) - website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade) + session session @relation(fields: [session_id], references: [session_id]) + website website @relation(fields: [website_id], references: [website_id]) event_data event_data? @@index([created_at]) @@ -47,8 +47,8 @@ model pageview { created_at DateTime? @default(now()) @db.Timestamptz(6) url String @db.VarChar(500) referrer String? @db.VarChar(500) - session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade) - website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade) + session session @relation(fields: [session_id], references: [session_id]) + website website @relation(fields: [website_id], references: [website_id]) @@index([created_at]) @@index([session_id]) @@ -69,7 +69,7 @@ model session { screen String? @db.VarChar(11) language String? @db.VarChar(35) country String? @db.Char(2) - website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade) + website website @relation(fields: [website_id], references: [website_id]) pageview pageview[] event event[] @@ -85,7 +85,7 @@ model website { domain String? @db.VarChar(500) share_id String? @unique @db.VarChar(64) created_at DateTime? @default(now()) @db.Timestamptz(6) - account account @relation(fields: [user_id], references: [user_id], onDelete: Cascade) + account account @relation(fields: [user_id], references: [user_id]) pageview pageview[] session session[] event event[] diff --git a/queries/admin/account/deleteAccount.js b/queries/admin/account/deleteAccount.js index 402b4111..7d5c39bf 100644 --- a/queries/admin/account/deleteAccount.js +++ b/queries/admin/account/deleteAccount.js @@ -2,10 +2,33 @@ import { prisma, runQuery } from 'lib/db'; export async function deleteAccount(user_id) { return runQuery( - prisma.account.delete({ - where: { - user_id, - }, - }), + prisma.$transaction([ + prisma.pageview.deleteMany({ + where: { session: { website: { user_id } } }, + }), + prisma.event_data.deleteMany({ + where: { event: { session: { website: { user_id } } } }, + }), + prisma.event.deleteMany({ + where: { session: { website: { user_id } } }, + }), + prisma.event.deleteMany({ + where: { session: { website: { user_id } } }, + }), + prisma.event.deleteMany({ + where: { session: { website: { user_id } } }, + }), + prisma.session.deleteMany({ + where: { website: { user_id } }, + }), + prisma.website.deleteMany({ + where: { user_id }, + }), + prisma.account.delete({ + where: { + user_id, + }, + }), + ]), ); } diff --git a/queries/admin/website/deleteWebsite.js b/queries/admin/website/deleteWebsite.js index 81cef845..1cfc3895 100644 --- a/queries/admin/website/deleteWebsite.js +++ b/queries/admin/website/deleteWebsite.js @@ -2,10 +2,28 @@ import { prisma, runQuery } from 'lib/db'; export async function deleteWebsite(website_id) { return runQuery( - prisma.website.delete({ - where: { - website_id, - }, - }), + prisma.$transaction([ + prisma.pageview.deleteMany({ + where: { session: { website: { website_id } } }, + }), + prisma.event_data.deleteMany({ + where: { event: { session: { website: { website_id } } } }, + }), + prisma.event.deleteMany({ + where: { session: { website: { website_id } } }, + }), + prisma.event.deleteMany({ + where: { session: { website: { website_id } } }, + }), + prisma.event.deleteMany({ + where: { session: { website: { website_id } } }, + }), + prisma.session.deleteMany({ + where: { website: { website_id } }, + }), + prisma.website.delete({ + where: { website_id }, + }), + ]), ); } From 207c1224ed410d6cfc064fa81923b1b8ae08f244 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Thu, 18 Aug 2022 17:10:45 -0700 Subject: [PATCH 2/7] checkpoint --- scripts/check-db.js | 3 ++ scripts/update-db.js | 101 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 scripts/update-db.js diff --git a/scripts/check-db.js b/scripts/check-db.js index 821e7f74..1ac5a5f0 100644 --- a/scripts/check-db.js +++ b/scripts/check-db.js @@ -65,6 +65,9 @@ async function checkMigrations() { console.log(output); + var x = await prisma.$queryRaw`select * from _prisma_migrations`; + console.log(x); + const missingMigrations = output.includes('have not yet been applied'); const missingInitialMigration = output.includes('01_init') && !output.includes('The last common migration is: 01_init'); diff --git a/scripts/update-db.js b/scripts/update-db.js new file mode 100644 index 00000000..821e7f74 --- /dev/null +++ b/scripts/update-db.js @@ -0,0 +1,101 @@ +require('dotenv').config(); +const { PrismaClient } = require('@prisma/client'); +const chalk = require('chalk'); +const spawn = require('cross-spawn'); +const { execSync } = require('child_process'); + +const prisma = new PrismaClient(); + +function success(msg) { + console.log(chalk.greenBright(`✓ ${msg}`)); +} + +function error(msg) { + console.log(chalk.redBright(`✗ ${msg}`)); +} + +async function checkEnv() { + if (!process.env.DATABASE_URL) { + throw new Error('DATABASE_URL is not defined.'); + } else { + success('DATABASE_URL is defined.'); + } +} + +async function checkConnection() { + try { + await prisma.$connect(); + + success('Database connection successful.'); + } catch (e) { + throw new Error('Unable to connect to the database.'); + } +} + +async function checkTables() { + try { + await prisma.account.findFirst(); + + success('Database tables found.'); + } catch (e) { + error('Database tables not found.'); + console.log('Adding tables...'); + + console.log(execSync('prisma migrate deploy').toString()); + } +} + +async function run(cmd, args) { + const buffer = []; + const proc = spawn(cmd, args); + + return new Promise((resolve, reject) => { + proc.stdout.on('data', data => buffer.push(data)); + + proc.on('error', () => { + reject(new Error('Failed to run Prisma.')); + }); + + proc.on('exit', () => resolve(buffer.join(''))); + }); +} + +async function checkMigrations() { + const output = await run('prisma', ['migrate', 'status']); + + console.log(output); + + const missingMigrations = output.includes('have not yet been applied'); + const missingInitialMigration = + output.includes('01_init') && !output.includes('The last common migration is: 01_init'); + const notManaged = output.includes('The current database is not managed'); + + if (notManaged || missingMigrations) { + console.log('Running update...'); + + if (missingInitialMigration) { + console.log(execSync('prisma migrate resolve --applied "01_init"').toString()); + } + + console.log(execSync('prisma migrate deploy').toString()); + } + + success('Database is up to date.'); +} + +(async () => { + let err = false; + for (let fn of [checkEnv, checkConnection, checkTables, checkMigrations]) { + try { + await fn(); + } catch (e) { + console.log(chalk.red(`✗ ${e.message}`)); + err = true; + } finally { + await prisma.$disconnect(); + if (err) { + process.exit(1); + } + } + } +})(); From 0066e8dbcbbbd79d1d06ff7cf4eee5bc4b41e71c Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Sun, 21 Aug 2022 23:47:11 -0700 Subject: [PATCH 3/7] roll back check/update --- scripts/check-db.js | 3 -- scripts/update-db.js | 101 ------------------------------------------- 2 files changed, 104 deletions(-) delete mode 100644 scripts/update-db.js diff --git a/scripts/check-db.js b/scripts/check-db.js index 1ac5a5f0..821e7f74 100644 --- a/scripts/check-db.js +++ b/scripts/check-db.js @@ -65,9 +65,6 @@ async function checkMigrations() { console.log(output); - var x = await prisma.$queryRaw`select * from _prisma_migrations`; - console.log(x); - const missingMigrations = output.includes('have not yet been applied'); const missingInitialMigration = output.includes('01_init') && !output.includes('The last common migration is: 01_init'); diff --git a/scripts/update-db.js b/scripts/update-db.js deleted file mode 100644 index 821e7f74..00000000 --- a/scripts/update-db.js +++ /dev/null @@ -1,101 +0,0 @@ -require('dotenv').config(); -const { PrismaClient } = require('@prisma/client'); -const chalk = require('chalk'); -const spawn = require('cross-spawn'); -const { execSync } = require('child_process'); - -const prisma = new PrismaClient(); - -function success(msg) { - console.log(chalk.greenBright(`✓ ${msg}`)); -} - -function error(msg) { - console.log(chalk.redBright(`✗ ${msg}`)); -} - -async function checkEnv() { - if (!process.env.DATABASE_URL) { - throw new Error('DATABASE_URL is not defined.'); - } else { - success('DATABASE_URL is defined.'); - } -} - -async function checkConnection() { - try { - await prisma.$connect(); - - success('Database connection successful.'); - } catch (e) { - throw new Error('Unable to connect to the database.'); - } -} - -async function checkTables() { - try { - await prisma.account.findFirst(); - - success('Database tables found.'); - } catch (e) { - error('Database tables not found.'); - console.log('Adding tables...'); - - console.log(execSync('prisma migrate deploy').toString()); - } -} - -async function run(cmd, args) { - const buffer = []; - const proc = spawn(cmd, args); - - return new Promise((resolve, reject) => { - proc.stdout.on('data', data => buffer.push(data)); - - proc.on('error', () => { - reject(new Error('Failed to run Prisma.')); - }); - - proc.on('exit', () => resolve(buffer.join(''))); - }); -} - -async function checkMigrations() { - const output = await run('prisma', ['migrate', 'status']); - - console.log(output); - - const missingMigrations = output.includes('have not yet been applied'); - const missingInitialMigration = - output.includes('01_init') && !output.includes('The last common migration is: 01_init'); - const notManaged = output.includes('The current database is not managed'); - - if (notManaged || missingMigrations) { - console.log('Running update...'); - - if (missingInitialMigration) { - console.log(execSync('prisma migrate resolve --applied "01_init"').toString()); - } - - console.log(execSync('prisma migrate deploy').toString()); - } - - success('Database is up to date.'); -} - -(async () => { - let err = false; - for (let fn of [checkEnv, checkConnection, checkTables, checkMigrations]) { - try { - await fn(); - } catch (e) { - console.log(chalk.red(`✗ ${e.message}`)); - err = true; - } finally { - await prisma.$disconnect(); - if (err) { - process.exit(1); - } - } - } -})(); From 4924a616f94f1f35acaeeaac659e1bfcdc1bf0bd Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Mon, 22 Aug 2022 16:00:26 -0700 Subject: [PATCH 4/7] cascading deletes mysql --- .../04_remove_cascade_delete/migration.sql | 35 +++++++++++++++++++ db/mysql/schema.prisma | 12 +++---- 2 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 db/mysql/migrations/04_remove_cascade_delete/migration.sql diff --git a/db/mysql/migrations/04_remove_cascade_delete/migration.sql b/db/mysql/migrations/04_remove_cascade_delete/migration.sql new file mode 100644 index 00000000..542784a9 --- /dev/null +++ b/db/mysql/migrations/04_remove_cascade_delete/migration.sql @@ -0,0 +1,35 @@ +-- DropForeignKey +ALTER TABLE `event` DROP FOREIGN KEY `event_ibfk_2`; + +-- DropForeignKey +ALTER TABLE `event` DROP FOREIGN KEY `event_ibfk_1`; + +-- DropForeignKey +ALTER TABLE `pageview` DROP FOREIGN KEY `pageview_ibfk_2`; + +-- DropForeignKey +ALTER TABLE `pageview` DROP FOREIGN KEY `pageview_ibfk_1`; + +-- DropForeignKey +ALTER TABLE `session` DROP FOREIGN KEY `session_ibfk_1`; + +-- DropForeignKey +ALTER TABLE `website` DROP FOREIGN KEY `website_ibfk_1`; + +-- AddForeignKey +ALTER TABLE `event` ADD CONSTRAINT `event_session_id_fkey` FOREIGN KEY (`session_id`) REFERENCES `session`(`session_id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `event` ADD CONSTRAINT `event_website_id_fkey` FOREIGN KEY (`website_id`) REFERENCES `website`(`website_id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `pageview` ADD CONSTRAINT `pageview_session_id_fkey` FOREIGN KEY (`session_id`) REFERENCES `session`(`session_id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `pageview` ADD CONSTRAINT `pageview_website_id_fkey` FOREIGN KEY (`website_id`) REFERENCES `website`(`website_id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `session` ADD CONSTRAINT `session_website_id_fkey` FOREIGN KEY (`website_id`) REFERENCES `website`(`website_id`) ON DELETE RESTRICT ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE `website` ADD CONSTRAINT `website_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `account`(`user_id`) ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/db/mysql/schema.prisma b/db/mysql/schema.prisma index 6ac27e04..3e0093ab 100644 --- a/db/mysql/schema.prisma +++ b/db/mysql/schema.prisma @@ -24,8 +24,8 @@ model event { created_at DateTime? @default(now()) @db.Timestamp(0) url String @db.VarChar(500) event_name String @db.VarChar(50) - session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade, onUpdate: NoAction, map: "event_ibfk_2") - website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade, onUpdate: NoAction, map: "event_ibfk_1") + session session @relation(fields: [session_id], references: [session_id]) + website website @relation(fields: [website_id], references: [website_id]) event_data event_data? @@index([created_at]) @@ -47,8 +47,8 @@ model pageview { created_at DateTime? @default(now()) @db.Timestamp(0) url String @db.VarChar(500) referrer String? @db.VarChar(500) - session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade, onUpdate: NoAction, map: "pageview_ibfk_2") - website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade, onUpdate: NoAction, map: "pageview_ibfk_1") + session session @relation(fields: [session_id], references: [session_id]) + website website @relation(fields: [website_id], references: [website_id]) @@index([created_at]) @@index([session_id]) @@ -69,7 +69,7 @@ model session { screen String? @db.VarChar(11) language String? @db.VarChar(35) country String? @db.Char(2) - website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade, onUpdate: NoAction, map: "session_ibfk_1") + website website @relation(fields: [website_id], references: [website_id]) event event[] pageview pageview[] @@ -85,7 +85,7 @@ model website { domain String? @db.VarChar(500) share_id String? @unique() @db.VarChar(64) created_at DateTime? @default(now()) @db.Timestamp(0) - account account @relation(fields: [user_id], references: [user_id], onDelete: Cascade, onUpdate: NoAction, map: "website_ibfk_1") + account account @relation(fields: [user_id], references: [user_id]) event event[] pageview pageview[] session session[] From e418f86f35c86eab72908f8ba2e5dbb56e9c15d1 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Mon, 22 Aug 2022 22:44:48 -0700 Subject: [PATCH 5/7] logging --- scripts/copy-db-files.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/copy-db-files.js b/scripts/copy-db-files.js index a7897fca..84ae5473 100644 --- a/scripts/copy-db-files.js +++ b/scripts/copy-db-files.js @@ -18,6 +18,7 @@ function getDatabaseType() { const databaseType = getDatabaseType(); if (!databaseType || !['mysql', 'postgresql'].includes(databaseType)) { + console.log(databaseType); throw new Error('Missing or invalid database'); } From 724ca6dc243fdca43e641cfef3dd5f43ead9a3bb Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Mon, 22 Aug 2022 22:45:35 -0700 Subject: [PATCH 6/7] remove logging --- scripts/copy-db-files.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/copy-db-files.js b/scripts/copy-db-files.js index 84ae5473..a7897fca 100644 --- a/scripts/copy-db-files.js +++ b/scripts/copy-db-files.js @@ -18,7 +18,6 @@ function getDatabaseType() { const databaseType = getDatabaseType(); if (!databaseType || !['mysql', 'postgresql'].includes(databaseType)) { - console.log(databaseType); throw new Error('Missing or invalid database'); } From 18b7fc8626fe4e1d20e6ae9281af9475a7f638fa Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Mon, 22 Aug 2022 23:18:48 -0700 Subject: [PATCH 7/7] fix dupes --- queries/admin/account/deleteAccount.js | 6 ------ queries/admin/website/deleteWebsite.js | 6 ------ 2 files changed, 12 deletions(-) diff --git a/queries/admin/account/deleteAccount.js b/queries/admin/account/deleteAccount.js index 7d5c39bf..8c4e2c0c 100644 --- a/queries/admin/account/deleteAccount.js +++ b/queries/admin/account/deleteAccount.js @@ -12,12 +12,6 @@ export async function deleteAccount(user_id) { prisma.event.deleteMany({ where: { session: { website: { user_id } } }, }), - prisma.event.deleteMany({ - where: { session: { website: { user_id } } }, - }), - prisma.event.deleteMany({ - where: { session: { website: { user_id } } }, - }), prisma.session.deleteMany({ where: { website: { user_id } }, }), diff --git a/queries/admin/website/deleteWebsite.js b/queries/admin/website/deleteWebsite.js index 1cfc3895..129351ea 100644 --- a/queries/admin/website/deleteWebsite.js +++ b/queries/admin/website/deleteWebsite.js @@ -12,12 +12,6 @@ export async function deleteWebsite(website_id) { prisma.event.deleteMany({ where: { session: { website: { website_id } } }, }), - prisma.event.deleteMany({ - where: { session: { website: { website_id } } }, - }), - prisma.event.deleteMany({ - where: { session: { website: { website_id } } }, - }), prisma.session.deleteMany({ where: { website: { website_id } }, }),