# frozen_string_literal: true module Gitlab module BackgroundMigration class ResyncHasVulnerabilities < BatchedMigrationJob operation_name :rsync_has_vulnerabilities feature_category :vulnerability_management class Vulnerability < ::SecApplicationRecord self.table_name = 'vulnerabilities' end class ProjectSetting < ApplicationRecord self.table_name = 'project_settings' end def perform each_sub_batch do |sub_batch| project_ids = sub_batch.pluck(:project_id) bulk_update!(update_values_sql(project_ids)) end end private def update_values_sql(project_ids) project_ids_values = Arel::Nodes::ValuesList.new(project_ids.zip).to_sql results = Vulnerability .select('project_ids.id AS project_id', exists_select) .from("(#{project_ids_values}) AS project_ids (id)") update_values = results.map { |result| [result.project_id, result.has_vulnerabilities] } Arel::Nodes::ValuesList.new(update_values).to_sql end def exists_select <<~SQL EXISTS ( SELECT 1 FROM vulnerabilities WHERE vulnerabilities.project_id = project_ids.id AND vulnerabilities.present_on_default_branch IS TRUE ) AS has_vulnerabilities SQL end def bulk_update!(update_values) sql = <<~SQL UPDATE project_settings SET has_vulnerabilities = update_values.has_vulnerabilities, updated_at = NOW() FROM (#{update_values}) AS update_values (project_id, has_vulnerabilities) WHERE project_settings.project_id = update_values.project_id; SQL ProjectSetting.connection.execute(sql) end end end end