summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-09-19 12:06:28 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-09-19 12:06:28 +0000
commit26804e91d92ce76b741103de6fd0012f9e26d18c (patch)
tree2e05d1688e0372e25953fe99576e60437e0b4f83
parent6cd5b7dbfaa4ff630ecbbfe351a1faac5fc71a8d (diff)
downloadgitlab-ce-26804e91d92ce76b741103de6fd0012f9e26d18c.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--changelogs/unreleased/issue_26823_sync_state_id.yml5
-rw-r--r--db/post_migrate/20190911251732_sync_issuables_state_id.rb79
-rw-r--r--spec/migrations/sync_issuables_state_id_spec.rb37
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