OurBigBook logoOurBigBook Docs OurBigBook logoOurBigBook.comSite Source code
web/migrations/21000101000035-issue-comment-add-list-column.js
const { sequelizeCreateTriggerUpdateCount } = require('ourbigbook/nodejs_webpack_safe')

const issueListIndices = [
  ['list', 'createdAt'],
  ['list', 'updatedAt'],
  ['list', 'score'],
  ['list', 'followerCount'],
  ['list', 'commentCount'],
  ['authorId', 'list', 'createdAt'],
  ['authorId', 'list', 'updatedAt'],
  ['authorId', 'list', 'score'],
  ['authorId', 'list', 'followerCount'],
  ['authorId', 'list', 'commentCount'],
]

const commentListIndices = [
  ['list', 'createdAt'],
  ['list', 'updatedAt'],
  ['authorId', 'list', 'createdAt'],
  ['authorId', 'list', 'updatedAt'],
]

const triggerSpecs = [
  ['Issue', 'discussionCount', 'user_discussion_count'],
  ['Comment', 'commentCount', 'user_comment_count'],
]

async function createUserCountTriggers(queryInterface, conditional, transaction) {
  const sequelize = queryInterface.sequelize
  for (const [childTable, countField, nameExtra] of triggerSpecs) {
    await sequelizeCreateTriggerUpdateCount(
      sequelize,
      { tableName: 'User' },
      { tableName: childTable },
      countField,
      'authorId',
      {
        countBooleanField: conditional ? 'list' : undefined,
        nameExtra,
        transaction,
      },
    )
  }
}

async function updateUserCounts(queryInterface, conditional, transaction) {
  for (const [childTable, countField] of triggerSpecs) {
    await queryInterface.sequelize.query(`
UPDATE "User"
SET "${countField}" = (
  SELECT CAST(COUNT(*) AS INTEGER)
  FROM "${childTable}"
  WHERE "${childTable}"."authorId" = "User"."id"${conditional ? ` AND "${childTable}"."list" = ${queryInterface.sequelize.options.dialect === 'postgres' ? 'TRUE' : '1'}` : ''}
)
`, { transaction })
  }
}

module.exports = {
  up: async (queryInterface, Sequelize) => queryInterface.sequelize.transaction(async transaction => {
    const column = () => ({
      type: Sequelize.DataTypes.BOOLEAN,
      allowNull: false,
      defaultValue: true,
    })
    await queryInterface.addColumn('Issue', 'list', column(), { transaction })
    await queryInterface.addColumn('Comment', 'list', column(), { transaction })
    for (const index of issueListIndices) {
      await queryInterface.addIndex('Issue', index, { transaction })
    }
    for (const index of commentListIndices) {
      await queryInterface.addIndex('Comment', index, { transaction })
    }
    await createUserCountTriggers(queryInterface, true, transaction)
    await updateUserCounts(queryInterface, true, transaction)
  }),
  down: async (queryInterface, Sequelize) => queryInterface.sequelize.transaction(async transaction => {
    await createUserCountTriggers(queryInterface, false, transaction)
    await updateUserCounts(queryInterface, false, transaction)
    await queryInterface.removeColumn('Comment', 'list', { transaction })
    await queryInterface.removeColumn('Issue', 'list', { transaction })
    await createUserCountTriggers(queryInterface, false, transaction)
  }),
}