diff --git a/server/db-patches/patch-20-21.sql b/server/db-patches/patch-20-21.sql new file mode 100644 index 0000000000..686119d38f --- /dev/null +++ b/server/db-patches/patch-20-21.sql @@ -0,0 +1 @@ +CREATE INDEX images_shotid_idx ON images (shotid); diff --git a/server/db-patches/patch-21-20.sql b/server/db-patches/patch-21-20.sql new file mode 100644 index 0000000000..273ad385de --- /dev/null +++ b/server/db-patches/patch-21-20.sql @@ -0,0 +1 @@ +DROP INDEX images_shotid_idx; diff --git a/server/schema.sql b/server/schema.sql index d2ed02e070..d6b2e9e0c4 100644 --- a/server/schema.sql +++ b/server/schema.sql @@ -72,6 +72,7 @@ ALTER TABLE ONLY states ADD CONSTRAINT states_pkey PRIMARY KEY (state); CREATE INDEX data_deviceid_idx ON data USING btree (deviceid); CREATE INDEX devices_accountid_idx ON devices USING btree (accountid); +CREATE INDEX images_shotid_idx ON images USING btree (shotid); CREATE INDEX searchable_text_idx ON data USING gin (searchable_text); CREATE INDEX states_deviceid_idx ON states USING btree (deviceid); ALTER TABLE ONLY data diff --git a/server/src/dbschema.js b/server/src/dbschema.js index 9d04d2d78f..a6fe24a7ca 100644 --- a/server/src/dbschema.js +++ b/server/src/dbschema.js @@ -6,7 +6,7 @@ const mozlog = require("./logging").mozlog("dbschema"); // When updating the database, please also run ./bin/dumpschema --record // This updates schema.sql with the latest full database schema -const MAX_DB_LEVEL = exports.MAX_DB_LEVEL = 20; +const MAX_DB_LEVEL = exports.MAX_DB_LEVEL = 21; exports.forceDbVersion = function(version) { mozlog.info("forcing-db-version", {db: db.constr, version}); diff --git a/server/src/pages/leave-screenshots/server.js b/server/src/pages/leave-screenshots/server.js index 37c8ab4e93..b8bcb35e83 100644 --- a/server/src/pages/leave-screenshots/server.js +++ b/server/src/pages/leave-screenshots/server.js @@ -23,7 +23,7 @@ app.post("/leave", function(req, res) { if (!req.deviceId) { res.status(403).send(req.getText("leavePageErrorAddonRequired")); } - Shot.deleteEverythingForDevice(req.backend, req.deviceId).then(() => { + Shot.deleteEverythingForDevice(req.backend, req.deviceId, req.accountId).then(() => { res.redirect("/leave-screenshots/?complete"); }).catch((e) => { mozlog.error("delete-account-error", {msg: "An error occurred trying to delete account", error: e}); diff --git a/server/src/servershot.js b/server/src/servershot.js index 7dd2a4c1d5..be323776fa 100644 --- a/server/src/servershot.js +++ b/server/src/servershot.js @@ -620,42 +620,50 @@ Shot.deleteShot = function(backend, shotId, deviceId, accountId) { }) }; -Shot.deleteEverythingForDevice = function(backend, deviceId) { - return db.select( - `SELECT images.id - FROM images JOIN data - ON images.shotid = data.id - WHERE data.deviceid = $1`, - [deviceId] - ).then((rows) => { - rows.forEach((row) => del(row.id)) +Shot.deleteEverythingForDevice = function(backend, deviceId, accountId) { + let deviceIds; + + const getDeviceIds = () => { + if (accountId) { + return db.select( + `SELECT devices.id + FROM devices + WHERE devices.accountid = $1`, + [accountId]); + } + return Promise.resolve([{id: deviceId}]); + }; + + const imageIdsSelect = (deviceIdRows) => { + deviceIds = deviceIdRows.map(row => row.id); + if (!deviceIds.length) { + deviceIds = [deviceId]; } - ).then(() => { return db.select( - `SELECT DISTINCT devices.id - FROM devices, devices AS devices2 - WHERE devices.id = $1 - OR (devices.accountid = devices2.accountid - AND devices2.id = $1) - `, - [deviceId]); - } - ).then((rows) => { - let ids = []; - for (let i = 0; i < rows.length; i++) { - ids.push(rows[i].id); - } - if (!ids.length) { - ids = [deviceId]; - } + `SELECT images.id + FROM images JOIN data + ON images.shotid = data.id + WHERE data.deviceid IN (${db.markersForArgs(1, deviceIds.length)})`, + deviceIds); + }; + + const deleteImageData = (imageIdRows) => { + imageIdRows.forEach(row => del(row.id)); + }; + + const deleteShotRecords = () => { let deleteSql = `DELETE FROM data WHERE - deviceid IN (${db.markersForArgs(1, ids.length)})`; + deviceid IN (${db.markersForArgs(1, deviceIds.length)})`; return db.update( deleteSql, - ids + deviceIds ); + } - }); + return getDeviceIds() + .then(imageIdsSelect) + .then(deleteImageData) + .then(deleteShotRecords); }; ClipRewrites = class ClipRewrites {