diff options
| author | Micaël Bergeron <mbergeron@gitlab.com> | 2018-03-22 09:06:10 -0400 |
|---|---|---|
| committer | Micaël Bergeron <mbergeron@gitlab.com> | 2018-03-22 09:06:10 -0400 |
| commit | 9c6663ea079128bb730ec2a168b43961cd9462ec (patch) | |
| tree | 4f62c2e745c7f3e8571ee8c023abcce316c68275 /db | |
| parent | 6801a93e5e7447199b091e44f33c96d22a1a1960 (diff) | |
| parent | c01697539c3da4e72b1812662ff35d1f709d1dcc (diff) | |
| download | gitlab-ce-9c6663ea079128bb730ec2a168b43961cd9462ec.tar.gz | |
Merge remote-tracking branch 'origin/master' into 40781-os-to-ce
Diffstat (limited to 'db')
12 files changed, 338 insertions, 82 deletions
diff --git a/db/fixtures/development/22_labeled_issues_seed.rb b/db/fixtures/development/22_labeled_issues_seed.rb new file mode 100644 index 00000000000..3730e9c7958 --- /dev/null +++ b/db/fixtures/development/22_labeled_issues_seed.rb @@ -0,0 +1,103 @@ +# Creates a project with labeled issues for an user. +# Run this single seed file using: rake db:seed_fu FILTER=labeled USER_ID=74. +# If an USER_ID is not provided it will use the last created user. +require './spec/support/sidekiq' + +class Gitlab::Seeder::LabeledIssues + include ::Gitlab::Utils + + def initialize(user) + @user = user + end + + def seed! + Sidekiq::Testing.inline! do + group = create_group + + create_projects(group) + create_labels(group) + create_issues(group) + end + + print '.' + end + + private + + def create_group + group_name = "group_of_#{@user.username}_#{SecureRandom.hex(4)}" + + group_params = { + name: group_name, + path: group_name, + description: FFaker::Lorem.sentence + } + + Groups::CreateService.new(@user, group_params).execute + end + + def create_projects(group) + 5.times do + project_name = "project_#{SecureRandom.hex(6)}" + + params = { + namespace_id: group.id, + name: project_name, + description: FFaker::Lorem.sentence, + visibility_level: Gitlab::VisibilityLevel.values.sample + } + + Projects::CreateService.new(@user, params).execute + end + end + + def create_labels(group) + group.projects.each do |project| + 5.times do + label_title = FFaker::Vehicle.model + Labels::CreateService.new(title: label_title, color: "#69D100").execute(project: project) + end + end + + 10.times do + label_title = FFaker::Product.brand + Labels::CreateService.new(title: label_title).execute(group: group) + end + end + + def create_issues(group) + # Get only group labels + group_labels = + LabelsFinder.new(@user, group_id: group.id).execute.where.not(group_id: nil) + + group.projects.each do |project| + label_ids = project.labels.pluck(:id).sample(5) + label_ids.push(*group.labels.sample(4)) + + 20.times do + issue_params = { + title: FFaker::Lorem.sentence(6), + description: FFaker::Lorem.sentence, + state: 'opened', + label_ids: label_ids + + } + + Issues::CreateService.new(project, @user, issue_params).execute if project.project_feature.present? + end + end + end +end + +Gitlab::Seeder.quiet do + user_id = ENV['USER_ID'] + + user = + if user_id.present? + User.find(user_id) + else + User.last + end + + Gitlab::Seeder::LabeledIssues.new(user).seed! +end diff --git a/db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb b/db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb index af6d10b5158..1199073ed3a 100644 --- a/db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb +++ b/db/migrate/20170530130129_project_foreign_keys_with_cascading_deletes.rb @@ -154,7 +154,7 @@ class ProjectForeignKeysWithCascadingDeletes < ActiveRecord::Migration end def add_foreign_key_if_not_exists(source, target, column:) - return if foreign_key_exists?(source, column) + return if foreign_key_exists?(source, target, column: column) add_concurrent_foreign_key(source, target, column: column) end @@ -175,12 +175,6 @@ class ProjectForeignKeysWithCascadingDeletes < ActiveRecord::Migration rescue ArgumentError end - def foreign_key_exists?(table, column) - foreign_keys(table).any? do |key| - key.options[:column] == column.to_s - end - end - def connection # Rails memoizes connection objects, but this causes them to be shared # amongst threads; we don't want that. diff --git a/db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb b/db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb index 68b947583d3..a89d348b127 100644 --- a/db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb +++ b/db/migrate/20170703102400_add_stage_id_foreign_key_to_builds.rb @@ -10,13 +10,13 @@ class AddStageIdForeignKeyToBuilds < ActiveRecord::Migration add_concurrent_index(:ci_builds, :stage_id) end - unless foreign_key_exists?(:ci_builds, :stage_id) + unless foreign_key_exists?(:ci_builds, :ci_stages, column: :stage_id) add_concurrent_foreign_key(:ci_builds, :ci_stages, column: :stage_id, on_delete: :cascade) end end def down - if foreign_key_exists?(:ci_builds, :stage_id) + if foreign_key_exists?(:ci_builds, column: :stage_id) remove_foreign_key(:ci_builds, column: :stage_id) end @@ -24,12 +24,4 @@ class AddStageIdForeignKeyToBuilds < ActiveRecord::Migration remove_concurrent_index(:ci_builds, :stage_id) end end - - private - - def foreign_key_exists?(table, column) - foreign_keys(:ci_builds).any? do |key| - key.options[:column] == column.to_s - end - end end diff --git a/db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb b/db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb index c25d4fd5986..c409915ceed 100644 --- a/db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb +++ b/db/migrate/20170713104829_add_foreign_key_to_merge_requests.rb @@ -23,23 +23,15 @@ class AddForeignKeyToMergeRequests < ActiveRecord::Migration merge_requests.update_all(head_pipeline_id: nil) end - unless foreign_key_exists?(:merge_requests, :head_pipeline_id) + unless foreign_key_exists?(:merge_requests, column: :head_pipeline_id) add_concurrent_foreign_key(:merge_requests, :ci_pipelines, column: :head_pipeline_id, on_delete: :nullify) end end def down - if foreign_key_exists?(:merge_requests, :head_pipeline_id) + if foreign_key_exists?(:merge_requests, column: :head_pipeline_id) remove_foreign_key(:merge_requests, column: :head_pipeline_id) end end - - private - - def foreign_key_exists?(table, column) - foreign_keys(table).any? do |key| - key.options[:column] == column.to_s - end - end end diff --git a/db/migrate/20180223120443_create_user_interacted_projects_table.rb b/db/migrate/20180223120443_create_user_interacted_projects_table.rb index 20749940b1e..8da8cf68088 100644 --- a/db/migrate/20180223120443_create_user_interacted_projects_table.rb +++ b/db/migrate/20180223120443_create_user_interacted_projects_table.rb @@ -3,13 +3,15 @@ class CreateUserInteractedProjectsTable < ActiveRecord::Migration DOWNTIME = false - disable_ddl_transaction! + INDEX_NAME = 'user_interacted_projects_non_unique_index' def up create_table :user_interacted_projects, id: false do |t| t.references :user, null: false t.references :project, null: false end + + add_index :user_interacted_projects, [:project_id, :user_id], name: INDEX_NAME end def down diff --git a/db/migrate/20180305095250_create_internal_ids_table.rb b/db/migrate/20180305095250_create_internal_ids_table.rb new file mode 100644 index 00000000000..432086fe98b --- /dev/null +++ b/db/migrate/20180305095250_create_internal_ids_table.rb @@ -0,0 +1,15 @@ +class CreateInternalIdsTable < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + create_table :internal_ids, id: :bigserial do |t| + t.references :project, null: false, foreign_key: { on_delete: :cascade } + t.integer :usage, null: false + t.integer :last_value, null: false + + t.index [:usage, :project_id], unique: true + end + end +end diff --git a/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb b/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb index 0cf665ac935..b616cc2fd30 100644 --- a/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb +++ b/db/migrate/20180308052825_add_section_name_id_index_on_ci_build_trace_sections.rb @@ -3,20 +3,21 @@ class AddSectionNameIdIndexOnCiBuildTraceSections < ActiveRecord::Migration # Set this constant to true if this migration requires downtime. DOWNTIME = false + INDEX_NAME = 'index_ci_build_trace_sections_on_section_name_id' disable_ddl_transaction! def up # MySQL may already have this as a foreign key - unless index_exists?(:ci_build_trace_sections, :section_name_id) - add_concurrent_index :ci_build_trace_sections, :section_name_id + unless index_exists?(:ci_build_trace_sections, :section_name_id, name: INDEX_NAME) + add_concurrent_index :ci_build_trace_sections, :section_name_id, name: INDEX_NAME end end def down # We cannot remove index for MySQL because it's needed for foreign key if Gitlab::Database.postgresql? - remove_concurrent_index :ci_build_trace_sections, :section_name_id + remove_concurrent_index :ci_build_trace_sections, :section_name_id, name: INDEX_NAME end end end diff --git a/db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb b/db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb new file mode 100644 index 00000000000..990759104b0 --- /dev/null +++ b/db/migrate/20180309121820_reschedule_commits_count_for_merge_request_diff.rb @@ -0,0 +1,30 @@ +class RescheduleCommitsCountForMergeRequestDiff < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + MIGRATION = 'AddMergeRequestDiffCommitsCount'.freeze + BATCH_SIZE = 5000 + DELAY_INTERVAL = 5.minutes.to_i + + class MergeRequestDiff < ActiveRecord::Base + self.table_name = 'merge_request_diffs' + + include ::EachBatch + end + + disable_ddl_transaction! + + def up + say 'Populating the MergeRequestDiff `commits_count` (reschedule)' + + execute("SET statement_timeout TO '60s'") if Gitlab::Database.postgresql? + + MergeRequestDiff.where(commits_count: nil).each_batch(of: BATCH_SIZE) do |relation, index| + start_id, end_id = relation.pluck('MIN(id), MAX(id)').first + delay = index * DELAY_INTERVAL + + BackgroundMigrationWorker.perform_in(delay, MIGRATION, [start_id, end_id]) + end + end +end diff --git a/db/migrate/20180309160427_add_partial_indexes_on_todos.rb b/db/migrate/20180309160427_add_partial_indexes_on_todos.rb new file mode 100644 index 00000000000..18a5c69df1b --- /dev/null +++ b/db/migrate/20180309160427_add_partial_indexes_on_todos.rb @@ -0,0 +1,28 @@ +# See http://doc.gitlab.com/ce/development/migration_style_guide.html +# for more information on how to write migrations for GitLab. + +class AddPartialIndexesOnTodos < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + # Set this constant to true if this migration requires downtime. + DOWNTIME = false + + disable_ddl_transaction! + + INDEX_NAME_PENDING="index_todos_on_user_id_and_id_pending" + INDEX_NAME_DONE="index_todos_on_user_id_and_id_done" + + def up + unless index_exists?(:todos, [:user_id, :id], name: INDEX_NAME_PENDING) + add_concurrent_index(:todos, [:user_id, :id], where: "state='pending'", name: INDEX_NAME_PENDING) + end + unless index_exists?(:todos, [:user_id, :id], name: INDEX_NAME_DONE) + add_concurrent_index(:todos, [:user_id, :id], where: "state='done'", name: INDEX_NAME_DONE) + end + end + + def down + remove_concurrent_index(:todos, [:user_id, :id], where: "state='pending'", name: INDEX_NAME_PENDING) + remove_concurrent_index(:todos, [:user_id, :id], where: "state='done'", name: INDEX_NAME_DONE) + end +end diff --git a/db/migrate/20180320182229_add_indexes_for_user_activity_queries.rb b/db/migrate/20180320182229_add_indexes_for_user_activity_queries.rb new file mode 100644 index 00000000000..824bbb3ac05 --- /dev/null +++ b/db/migrate/20180320182229_add_indexes_for_user_activity_queries.rb @@ -0,0 +1,40 @@ +class AddIndexesForUserActivityQueries < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_concurrent_index :events, [:author_id, :project_id] unless index_exists?(:events, [:author_id, :project_id]) + add_concurrent_index :user_interacted_projects, :user_id unless index_exists?(:user_interacted_projects, :user_id) + end + + def down + remove_concurrent_index :events, [:author_id, :project_id] if index_exists?(:events, [:author_id, :project_id]) + + patch_foreign_keys do + remove_concurrent_index :user_interacted_projects, :user_id if index_exists?(:user_interacted_projects, :user_id) + end + end + + private + + def patch_foreign_keys + return yield if Gitlab::Database.postgresql? + + # MySQL doesn't like to remove the index with a foreign key using it. + remove_foreign_key :user_interacted_projects, :users if fk_exists?(:user_interacted_projects, :user_id) + + yield + + # Let's re-add the foreign key using the existing index on (user_id, project_id) + add_concurrent_foreign_key :user_interacted_projects, :users, column: :user_id unless fk_exists?(:user_interacted_projects, :user_id) + end + + def fk_exists?(table, column) + foreign_keys(table).any? do |key| + key.options[:column] == column.to_s + end + end +end diff --git a/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb b/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb index 5e729b1aa53..9addd36dca6 100644 --- a/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb +++ b/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb @@ -1,9 +1,14 @@ +require_relative '../migrate/20180223120443_create_user_interacted_projects_table.rb' +# rubocop:disable AddIndex +# rubocop:disable AddConcurrentForeignKey class BuildUserInteractedProjectsTable < ActiveRecord::Migration include Gitlab::Database::MigrationHelpers # Set this constant to true if this migration requires downtime. DOWNTIME = false + UNIQUE_INDEX_NAME = 'index_user_interacted_projects_on_project_id_and_user_id' + disable_ddl_transaction! def up @@ -13,55 +18,32 @@ class BuildUserInteractedProjectsTable < ActiveRecord::Migration MysqlStrategy.new end.up - unless index_exists?(:user_interacted_projects, [:project_id, :user_id]) - add_concurrent_index :user_interacted_projects, [:project_id, :user_id], unique: true - end - - unless foreign_key_exists?(:user_interacted_projects, :user_id) - add_concurrent_foreign_key :user_interacted_projects, :users, column: :user_id, on_delete: :cascade - end - - unless foreign_key_exists?(:user_interacted_projects, :project_id) - add_concurrent_foreign_key :user_interacted_projects, :projects, column: :project_id, on_delete: :cascade + if index_exists_by_name?(:user_interacted_projects, CreateUserInteractedProjectsTable::INDEX_NAME) + remove_concurrent_index_by_name :user_interacted_projects, CreateUserInteractedProjectsTable::INDEX_NAME end end def down execute "TRUNCATE user_interacted_projects" - if foreign_key_exists?(:user_interacted_projects, :user_id) + if foreign_key_exists?(:user_interacted_projects, :users) remove_foreign_key :user_interacted_projects, :users end - if foreign_key_exists?(:user_interacted_projects, :project_id) + if foreign_key_exists?(:user_interacted_projects, :projects) remove_foreign_key :user_interacted_projects, :projects end - if index_exists_by_name?(:user_interacted_projects, 'index_user_interacted_projects_on_project_id_and_user_id') - remove_concurrent_index_by_name :user_interacted_projects, 'index_user_interacted_projects_on_project_id_and_user_id' + if index_exists_by_name?(:user_interacted_projects, UNIQUE_INDEX_NAME) + remove_concurrent_index_by_name :user_interacted_projects, UNIQUE_INDEX_NAME end - end - private - - # Rails' index_exists? doesn't work when you only give it a table and index - # name. As such we have to use some extra code to check if an index exists for - # a given name. - def index_exists_by_name?(table, index) - indexes_for_table[table].include?(index) - end - - def indexes_for_table - @indexes_for_table ||= Hash.new do |hash, table_name| - hash[table_name] = indexes(table_name).map(&:name) + unless index_exists_by_name?(:user_interacted_projects, CreateUserInteractedProjectsTable::INDEX_NAME) + add_concurrent_index :user_interacted_projects, [:project_id, :user_id], name: CreateUserInteractedProjectsTable::INDEX_NAME end end - def foreign_key_exists?(table, column) - foreign_keys(table).any? do |key| - key.options[:column] == column.to_s - end - end + private class PostgresStrategy < ActiveRecord::Migration include Gitlab::Database::MigrationHelpers @@ -71,33 +53,86 @@ class BuildUserInteractedProjectsTable < ActiveRecord::Migration def up with_index(:events, [:author_id, :project_id], name: 'events_user_interactions_temp', where: 'project_id IS NOT NULL') do - iteration = 0 - records = 0 - begin - Rails.logger.info "Building user_interacted_projects table, batch ##{iteration}" - result = execute <<~SQL + insert_missing_records + + # Do this once without lock to speed up the second invocation + remove_duplicates + with_table_lock(:user_interacted_projects) do + remove_duplicates + create_unique_index + end + + remove_without_project + with_table_lock(:user_interacted_projects, :projects) do + remove_without_project + create_fk :user_interacted_projects, :projects, :project_id + end + + remove_without_user + with_table_lock(:user_interacted_projects, :users) do + remove_without_user + create_fk :user_interacted_projects, :users, :user_id + end + end + + execute "ANALYZE user_interacted_projects" + end + + private + def insert_missing_records + iteration = 0 + records = 0 + begin + Rails.logger.info "Building user_interacted_projects table, batch ##{iteration}" + result = execute <<~SQL INSERT INTO user_interacted_projects (user_id, project_id) SELECT e.user_id, e.project_id FROM (SELECT DISTINCT author_id AS user_id, project_id FROM events WHERE project_id IS NOT NULL) AS e LEFT JOIN user_interacted_projects ucp USING (user_id, project_id) WHERE ucp.user_id IS NULL LIMIT #{BATCH_SIZE} - SQL - iteration += 1 - records += result.cmd_tuples - Rails.logger.info "Building user_interacted_projects table, batch ##{iteration} complete, created #{records} overall" - Kernel.sleep(SLEEP_TIME) if result.cmd_tuples > 0 - rescue ActiveRecord::InvalidForeignKey => e - Rails.logger.info "Retry on InvalidForeignKey: #{e}" - retry - end while result.cmd_tuples > 0 - end + SQL + iteration += 1 + records += result.cmd_tuples + Rails.logger.info "Building user_interacted_projects table, batch ##{iteration} complete, created #{records} overall" + Kernel.sleep(SLEEP_TIME) if result.cmd_tuples > 0 + end while result.cmd_tuples > 0 + end - execute "ANALYZE user_interacted_projects" + def remove_duplicates + execute <<~SQL + WITH numbered AS (select ctid, ROW_NUMBER() OVER (PARTITION BY (user_id, project_id)) as row_number, user_id, project_id from user_interacted_projects) + DELETE FROM user_interacted_projects WHERE ctid IN (SELECT ctid FROM numbered WHERE row_number > 1); + SQL + end + def remove_without_project + execute "DELETE FROM user_interacted_projects WHERE NOT EXISTS (SELECT 1 FROM projects WHERE id = user_interacted_projects.project_id)" end - private + def remove_without_user + execute "DELETE FROM user_interacted_projects WHERE NOT EXISTS (SELECT 1 FROM users WHERE id = user_interacted_projects.user_id)" + end + + def create_fk(table, target, column) + return if foreign_key_exists?(table, target, column: column) + + add_foreign_key table, target, column: column, on_delete: :cascade + end + + def create_unique_index + return if index_exists_by_name?(:user_interacted_projects, UNIQUE_INDEX_NAME) + + add_index :user_interacted_projects, [:project_id, :user_id], unique: true, name: UNIQUE_INDEX_NAME + end + + # Protect table against concurrent data changes while still allowing reads + def with_table_lock(*tables) + ActiveRecord::Base.connection.transaction do + execute "LOCK TABLE #{tables.join(", ")} IN SHARE MODE" + yield + end + end def with_index(*args) add_concurrent_index(*args) unless index_exists?(*args) @@ -118,7 +153,18 @@ class BuildUserInteractedProjectsTable < ActiveRecord::Migration LEFT JOIN user_interacted_projects ucp USING (user_id, project_id) WHERE ucp.user_id IS NULL SQL + + unless index_exists?(:user_interacted_projects, [:project_id, :user_id]) + add_concurrent_index :user_interacted_projects, [:project_id, :user_id], unique: true, name: UNIQUE_INDEX_NAME + end + + unless foreign_key_exists?(:user_interacted_projects, :users, column: :user_id) + add_concurrent_foreign_key :user_interacted_projects, :users, column: :user_id, on_delete: :cascade + end + + unless foreign_key_exists?(:user_interacted_projects, :projects, column: :project_id) + add_concurrent_foreign_key :user_interacted_projects, :projects, column: :project_id, on_delete: :cascade + end end end - end diff --git a/db/schema.rb b/db/schema.rb index cfe66ab592b..b96508836d2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20180308052825) do +ActiveRecord::Schema.define(version: 20180320182229) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -730,6 +730,7 @@ ActiveRecord::Schema.define(version: 20180308052825) do end add_index "events", ["action"], name: "index_events_on_action", using: :btree + add_index "events", ["author_id", "project_id"], name: "index_events_on_author_id_and_project_id", using: :btree add_index "events", ["author_id"], name: "index_events_on_author_id", using: :btree add_index "events", ["project_id", "id"], name: "index_events_on_project_id_and_id", using: :btree add_index "events", ["target_type", "target_id"], name: "index_events_on_target_type_and_target_id", using: :btree @@ -869,6 +870,14 @@ ActiveRecord::Schema.define(version: 20180308052825) do add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree + create_table "internal_ids", id: :bigserial, force: :cascade do |t| + t.integer "project_id", null: false + t.integer "usage", null: false + t.integer "last_value", null: false + end + + add_index "internal_ids", ["usage", "project_id"], name: "index_internal_ids_on_usage_and_project_id", unique: true, using: :btree + create_table "issue_assignees", id: false, force: :cascade do |t| t.integer "user_id", null: false t.integer "issue_id", null: false @@ -1782,6 +1791,8 @@ ActiveRecord::Schema.define(version: 20180308052825) do add_index "todos", ["note_id"], name: "index_todos_on_note_id", using: :btree add_index "todos", ["project_id"], name: "index_todos_on_project_id", using: :btree add_index "todos", ["target_type", "target_id"], name: "index_todos_on_target_type_and_target_id", using: :btree + add_index "todos", ["user_id", "id"], name: "index_todos_on_user_id_and_id_done", where: "((state)::text = 'done'::text)", using: :btree + add_index "todos", ["user_id", "id"], name: "index_todos_on_user_id_and_id_pending", where: "((state)::text = 'pending'::text)", using: :btree add_index "todos", ["user_id"], name: "index_todos_on_user_id", using: :btree create_table "trending_projects", force: :cascade do |t| @@ -1858,6 +1869,7 @@ ActiveRecord::Schema.define(version: 20180308052825) do end add_index "user_interacted_projects", ["project_id", "user_id"], name: "index_user_interacted_projects_on_project_id_and_user_id", unique: true, using: :btree + add_index "user_interacted_projects", ["user_id"], name: "index_user_interacted_projects_on_user_id", using: :btree create_table "user_synced_attributes_metadata", force: :cascade do |t| t.boolean "name_synced", default: false @@ -2061,6 +2073,7 @@ ActiveRecord::Schema.define(version: 20180308052825) do add_foreign_key "gpg_signatures", "gpg_keys", on_delete: :nullify add_foreign_key "gpg_signatures", "projects", on_delete: :cascade add_foreign_key "group_custom_attributes", "namespaces", column: "group_id", on_delete: :cascade + add_foreign_key "internal_ids", "projects", on_delete: :cascade add_foreign_key "issue_assignees", "issues", name: "fk_b7d881734a", on_delete: :cascade add_foreign_key "issue_assignees", "users", name: "fk_5e0c8d9154", on_delete: :cascade add_foreign_key "issue_metrics", "issues", on_delete: :cascade |
