summaryrefslogtreecommitdiff
path: root/db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb
diff options
context:
space:
mode:
Diffstat (limited to 'db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb')
-rw-r--r--db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb49
1 files changed, 49 insertions, 0 deletions
diff --git a/db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb b/db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb
new file mode 100644
index 00000000000..df38591a333
--- /dev/null
+++ b/db/post_migrate/20161109150329_fix_project_records_with_invalid_visibility.rb
@@ -0,0 +1,49 @@
+class FixProjectRecordsWithInvalidVisibility < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ BATCH_SIZE = 500
+ DOWNTIME = false
+
+ # This migration is idempotent and there's no sense in throwing away the
+ # partial result if it's interrupted
+ disable_ddl_transaction!
+
+ def up
+ projects = Arel::Table.new(:projects)
+ namespaces = Arel::Table.new(:namespaces)
+
+ finder_sql =
+ projects.
+ join(namespaces, Arel::Nodes::InnerJoin).
+ on(projects[:namespace_id].eq(namespaces[:id])).
+ where(projects[:visibility_level].gt(namespaces[:visibility_level])).
+ project(projects[:id], namespaces[:visibility_level]).
+ take(BATCH_SIZE).
+ to_sql
+
+ # Update matching rows in batches. Each batch can cause up to 3 UPDATE
+ # statements, in addition to the SELECT: one per visibility_level
+ loop do
+ to_update = connection.exec_query(finder_sql)
+ break if to_update.rows.count == 0
+
+ # row[0] is projects.id, row[1] is namespaces.visibility_level
+ updates = to_update.rows.each_with_object(Hash.new {|h, k| h[k] = [] }) do |row, obj|
+ obj[row[1]] << row[0]
+ end
+
+ updates.each do |visibility_level, project_ids|
+ updater = Arel::UpdateManager.new(ActiveRecord::Base).
+ table(projects).
+ set(projects[:visibility_level] => visibility_level).
+ where(projects[:id].in(project_ids))
+
+ ActiveRecord::Base.connection.exec_update(updater.to_sql, self.class.name, [])
+ end
+ end
+ end
+
+ def down
+ # no-op
+ end
+end