OurBigBook logoOurBigBook Docs OurBigBook logoOurBigBook.comSite Source code
web/migrations/21000101000038-user-add-file-size-column.js
const { createFileSizeTriggers, fileOwnerWhere } = require('../models/upload')

const indices = [
  ['fileSize', 'createdAt'],
  ['verified', 'locked', 'fileSize', 'createdAt'],
]

module.exports = {
  up: async (queryInterface, Sequelize) => queryInterface.sequelize.transaction(async transaction => {
    await queryInterface.addColumn('User', 'fileSize', {
      type: Sequelize.DataTypes.BIGINT,
      allowNull: false,
      defaultValue: 0,
    }, { transaction })
    for (const index of indices) {
      await queryInterface.addIndex('User', index, { transaction })
    }
    await createFileSizeTriggers(queryInterface.sequelize, transaction)
    await queryInterface.sequelize.query(`
UPDATE "User" SET "fileSize" = (
  SELECT COALESCE(SUM(CAST("Upload"."size" AS BIGINT)), 0) FROM "Upload"
  WHERE ${fileOwnerWhere('"Upload"."path"')}
)
`, { transaction })
  }),
  down: async (queryInterface) => {
    const sequelize = queryInterface.sequelize
    const sqlite = sequelize.options.dialect === 'sqlite'
    // Older SQLite rebuilds the table to remove a column. Preserve references,
    // indices and triggers while doing so.
    if (sqlite) await sequelize.query('PRAGMA foreign_keys = OFF')
    try {
      await sequelize.transaction(async transaction => {
        for (const operation of ['insert', 'delete', 'update']) {
          const name = `Upload_${operation}_user_file_size`
          if (sqlite) {
            await sequelize.query(`DROP TRIGGER IF EXISTS "${name}"`, { transaction })
          } else {
            await sequelize.query(`DROP TRIGGER IF EXISTS ${name} ON "Upload"`, { transaction })
            await sequelize.query(`DROP FUNCTION IF EXISTS "${name}_fn"()`, { transaction })
          }
        }
        for (const index of indices) {
          await queryInterface.removeIndex('User', index, { transaction })
        }
        const [schema] = sqlite ? await sequelize.query(
          `SELECT sql FROM sqlite_master WHERE tbl_name = 'User' AND type IN ('index', 'trigger') AND sql IS NOT NULL`,
          { transaction },
        ) : [[]]
        await queryInterface.removeColumn('User', 'fileSize', { transaction })
        for (const { sql } of schema) await sequelize.query(sql, { transaction })
      })
    } finally {
      if (sqlite) await sequelize.query('PRAGMA foreign_keys = ON')
    }
  },
}