diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-19 12:06:28 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-19 12:06:28 +0000 |
commit | 26804e91d92ce76b741103de6fd0012f9e26d18c (patch) | |
tree | 2e05d1688e0372e25953fe99576e60437e0b4f83 | |
parent | 6cd5b7dbfaa4ff630ecbbfe351a1faac5fc71a8d (diff) | |
download | gitlab-ce-26804e91d92ce76b741103de6fd0012f9e26d18c.tar.gz |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | changelogs/unreleased/issue_26823_sync_state_id.yml | 5 | ||||
-rw-r--r-- | db/post_migrate/20190911251732_sync_issuables_state_id.rb | 79 | ||||
-rw-r--r-- | spec/migrations/sync_issuables_state_id_spec.rb | 37 |
3 files changed, 121 insertions, 0 deletions
diff --git a/changelogs/unreleased/issue_26823_sync_state_id.yml b/changelogs/unreleased/issue_26823_sync_state_id.yml new file mode 100644 index 00000000000..fd3993d3b65 --- /dev/null +++ b/changelogs/unreleased/issue_26823_sync_state_id.yml @@ -0,0 +1,5 @@ +--- +title: Sync issuables state_id with null values +merge_request: 16480 +author: +type: other diff --git a/db/post_migrate/20190911251732_sync_issuables_state_id.rb b/db/post_migrate/20190911251732_sync_issuables_state_id.rb new file mode 100644 index 00000000000..56e764a1ae2 --- /dev/null +++ b/db/post_migrate/20190911251732_sync_issuables_state_id.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +# Sync remaining records for issues/merge_requests tables where state_id +# is still null. +# For more information check: https://gitlab.com/gitlab-org/gitlab-ee/issues/26823 +# It creates a temporary index before performing the UPDATES to sync values. +# +# In 09-11-2019 we have the following numbers for records with state_id == nil: +# +# 1348 issues - default batch size for each update 67 +# 10247 merge requests - default batch size for each update 511 + +class SyncIssuablesStateId < ActiveRecord::Migration[5.2] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + %i(issues merge_requests).each do |table| + temp_index_name = index_name_for(table) + + add_concurrent_index( + table, + 'id', + name: temp_index_name, + where: 'state_id IS NULL' + ) + + update_value = update_condition_for(table) + + update_column_in_batches(table, :state_id, update_value) do |table, query| + query.where(table[:state_id].eq(nil)) + end + ensure + remove_concurrent_index_by_name(table, temp_index_name) + end + end + + def down + # NO OP + end + + def update_condition_for(table) + value_expresson = + if table == :issues + issues_state_id_condition + else + merge_requests_state_id_condition + end + + Arel.sql(value_expresson) + end + + def index_name_for(table) + "idx_tmp_on_#{table}_where_state_id_is_null" + end + + def issues_state_id_condition + <<~SQL + CASE state + WHEN 'opened' THEN 1 + WHEN 'closed' THEN 2 + END + SQL + end + + def merge_requests_state_id_condition + <<~SQL + CASE state + WHEN 'opened' THEN 1 + WHEN 'closed' THEN 2 + WHEN 'merged' THEN 3 + WHEN 'locked' THEN 4 + END + SQL + end +end diff --git a/spec/migrations/sync_issuables_state_id_spec.rb b/spec/migrations/sync_issuables_state_id_spec.rb new file mode 100644 index 00000000000..8d1f8a36ac3 --- /dev/null +++ b/spec/migrations/sync_issuables_state_id_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'post_migrate', '20190911251732_sync_issuables_state_id') + +describe SyncIssuablesStateId, :migration, :sidekiq do + let(:migration) { described_class.new } + + describe '#up' do + let(:issues) { table(:issues) } + let(:namespaces) { table(:namespaces) } + let(:projects) { table(:projects) } + let(:merge_requests) { table(:merge_requests) } + let(:group) { namespaces.create!(name: 'gitlab', path: 'gitlab') } + let(:project) { projects.create!(namespace_id: group.id) } + # These state_ids should be the same defined on Issue/MergeRequest models + let(:state_ids) { { opened: 1, closed: 2, merged: 3, locked: 4 } } + + it 'migrates state column to state_id as integer' do + opened_issue = issues.create!(description: 'first', state: 'opened') + closed_issue = issues.create!(description: 'second', state: 'closed') + opened_merge_request = merge_requests.create!(state: 'opened', target_project_id: project.id, target_branch: 'feature1', source_branch: 'master') + closed_merge_request = merge_requests.create!(state: 'closed', target_project_id: project.id, target_branch: 'feature2', source_branch: 'master') + merged_merge_request = merge_requests.create!(state: 'merged', target_project_id: project.id, target_branch: 'feature3', source_branch: 'master') + locked_merge_request = merge_requests.create!(state: 'locked', target_project_id: project.id, target_branch: 'feature4', source_branch: 'master') + + migrate! + + expect(opened_issue.reload.state_id).to eq(state_ids[:opened]) + expect(closed_issue.reload.state_id).to eq(state_ids[:closed]) + expect(opened_merge_request.reload.state_id).to eq(state_ids[:opened]) + expect(closed_merge_request.reload.state_id).to eq(state_ids[:closed]) + expect(merged_merge_request.reload.state_id).to eq(state_ids[:merged]) + expect(locked_merge_request.reload.state_id).to eq(state_ids[:locked]) + end + end +end |