Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
cb934f93
Commit
cb934f93
authored
Oct 30, 2018
by
Kamil Trzciński
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Validate foreign keys being indexed
parent
0724350f
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
139 additions
and
6 deletions
+139
-6
changelogs/unreleased/validate-foreign-keys-being-indexed.yml
...gelogs/unreleased/validate-foreign-keys-being-indexed.yml
+5
-0
changelogs/unreleased/validate-that-foreign-keys-are-created.yml
...ogs/unreleased/validate-that-foreign-keys-are-created.yml
+5
-0
db/migrate/20181030154446_add_missing_indexes_for_foreign_keys.rb
...te/20181030154446_add_missing_indexes_for_foreign_keys.rb
+38
-0
doc/development/migration_style_guide.md
doc/development/migration_style_guide.md
+1
-6
spec/db/schema_spec.rb
spec/db/schema_spec.rb
+90
-0
No files found.
changelogs/unreleased/validate-foreign-keys-being-indexed.yml
0 → 100644
View file @
cb934f93
---
title
:
Validate foreign keys being indexed
merge_request
:
author
:
type
:
performance
changelogs/unreleased/validate-that-foreign-keys-are-created.yml
0 → 100644
View file @
cb934f93
---
title
:
Validate that FK is created for column with _id
merge_request
:
author
:
type
:
performance
db/migrate/20181030154446_add_missing_indexes_for_foreign_keys.rb
0 → 100644
View file @
cb934f93
# frozen_string_literal: true
class
AddMissingIndexesForForeignKeys
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
def
up
add_concurrent_index
(
:application_settings
,
:usage_stats_set_by_user_id
)
add_concurrent_index
(
:ci_pipeline_schedules
,
:owner_id
)
add_concurrent_index
(
:ci_trigger_requests
,
:trigger_id
)
add_concurrent_index
(
:ci_triggers
,
:owner_id
)
add_concurrent_index
(
:clusters_applications_helm
,
:cluster_id
,
unique:
true
)
add_concurrent_index
(
:clusters_applications_ingress
,
:cluster_id
,
unique:
true
)
add_concurrent_index
(
:clusters_applications_jupyter
,
:cluster_id
,
unique:
true
)
add_concurrent_index
(
:clusters_applications_jupyter
,
:oauth_application_id
)
add_concurrent_index
(
:clusters_applications_prometheus
,
:cluster_id
,
unique:
true
)
add_concurrent_index
(
:fork_network_members
,
:forked_from_project_id
)
add_concurrent_index
(
:internal_ids
,
:namespace_id
)
add_concurrent_index
(
:internal_ids
,
:project_id
)
add_concurrent_index
(
:issues
,
:closed_by_id
)
add_concurrent_index
(
:label_priorities
,
:label_id
)
add_concurrent_index
(
:merge_request_metrics
,
:merged_by_id
)
add_concurrent_index
(
:merge_request_metrics
,
:latest_closed_by_id
)
add_concurrent_index
(
:oauth_openid_requests
,
:access_grant_id
)
add_concurrent_index
(
:project_deploy_tokens
,
:deploy_token_id
)
add_concurrent_index
(
:protected_tag_create_access_levels
,
:group_id
)
add_concurrent_index
(
:subscriptions
,
:project_id
)
add_concurrent_index
(
:user_statuses
,
:user_id
)
add_concurrent_index
(
:users
,
:accepted_term_id
)
end
def
down
# no-op
end
end
doc/development/migration_style_guide.md
View file @
cb934f93
...
...
@@ -187,12 +187,7 @@ end
When adding a foreign-key constraint to either an existing or new
column remember to also add a index on the column.
This is _required_ if the foreign-key constraint specifies
`ON DELETE CASCADE`
or
`ON DELETE SET NULL`
behavior. On a cascading
delete, the
[
corresponding record needs to be retrieved using an
index
](
https://www.cybertec-postgresql.com/en/postgresql-indexes-and-foreign-keys/
)
(otherwise, we'd need to scan the whole table) for subsequent update or
deletion.
This is _required_ for all foreign-keys.
Here's an example where we add a new column with a foreign key
constraint. Note it includes
`index: true`
to create an index for it.
...
...
spec/db/schema_spec.rb
0 → 100644
View file @
cb934f93
# frozen_string_literal: true
require
'spec_helper'
describe
'Database schema'
do
let
(
:connection
)
{
ActiveRecord
::
Base
.
connection
}
let
(
:tables
)
{
connection
.
tables
}
# Use if you are certain that this column should not have a foreign key
IGNORED_FK_COLUMNS
=
{
abuse_reports:
%w[reporter_id user_id]
,
application_settings:
%w[performance_bar_allowed_group_id]
,
audit_events:
%w[author_id entity_id]
,
award_emoji:
%w[awardable_id user_id]
,
chat_names:
%w[chat_id service_id team_id user_id]
,
chat_teams:
%w[team_id]
,
ci_builds:
%w[erased_by_id runner_id trigger_request_id user_id]
,
ci_pipelines:
%w[user_id]
,
ci_runner_projects:
%w[runner_id]
,
ci_trigger_requests:
%w[commit_id]
,
cluster_providers_gcp:
%w[gcp_project_id operation_id]
,
deploy_keys_projects:
%w[deploy_key_id]
,
deployments:
%w[deployable_id environment_id user_id]
,
emails:
%w[user_id]
,
events:
%w[target_id]
,
forked_project_links:
%w[forked_from_project_id]
,
identities:
%w[user_id]
,
issues:
%w[last_edited_by_id]
,
keys:
%w[user_id]
,
label_links:
%w[target_id]
,
lfs_objects_projects:
%w[lfs_object_id project_id]
,
members:
%w[source_id created_by_id]
,
merge_requests:
%w[last_edited_by_id]
,
namespaces:
%w[owner_id parent_id]
,
notes:
%w[author_id commit_id noteable_id updated_by_id resolved_by_id discussion_id]
,
notification_settings:
%w[source_id]
,
oauth_access_grants:
%w[resource_owner_id application_id]
,
oauth_access_tokens:
%w[resource_owner_id application_id]
,
oauth_applications:
%w[owner_id]
,
project_group_links:
%w[group_id]
,
project_statistics:
%w[namespace_id]
,
projects:
%w[creator_id namespace_id ci_id]
,
redirect_routes:
%w[source_id]
,
repository_languages:
%w[programming_language_id]
,
routes:
%w[source_id]
,
sent_notifications:
%w[project_id noteable_id recipient_id commit_id in_reply_to_discussion_id]
,
snippets:
%w[author_id]
,
spam_logs:
%w[user_id]
,
subscriptions:
%w[user_id subscribable_id]
,
taggings:
%w[tag_id taggable_id tagger_id]
,
timelogs:
%w[user_id]
,
todos:
%w[target_id commit_id]
,
uploads:
%w[model_id]
,
user_agent_details:
%w[subject_id]
,
users:
%w[color_scheme_id created_by_id theme_id]
,
users_star_projects:
%w[user_id]
,
web_hooks:
%w[service_id]
}.
with_indifferent_access
.
freeze
context
'for table'
do
ActiveRecord
::
Base
.
connection
.
tables
.
sort
.
each
do
|
table
|
describe
table
do
let
(
:indexes
)
{
connection
.
indexes
(
table
)
}
let
(
:columns
)
{
connection
.
columns
(
table
)
}
let
(
:foreign_keys
)
{
connection
.
foreign_keys
(
table
)
}
context
'all foreign keys'
do
# for index to be effective, the FK constraint has to be at first place
it
'are indexed'
do
first_indexed_column
=
indexes
.
map
(
&
:columns
).
map
(
&
:first
)
foreign_keys_columns
=
foreign_keys
.
map
(
&
:column
)
expect
(
first_indexed_column
.
uniq
).
to
include
(
*
foreign_keys_columns
)
end
end
context
'columns ending with _id'
do
let
(
:column_names
)
{
columns
.
map
(
&
:name
)
}
let
(
:column_names_with_id
)
{
column_names
.
select
{
|
column_name
|
column_name
.
ends_with?
(
'_id'
)
}
}
let
(
:foreign_keys_columns
)
{
foreign_keys
.
map
(
&
:column
)
}
let
(
:ignored_columns
)
{
IGNORED_FK_COLUMNS
[
table
]
||
[]
}
it
'do have the foreign keys'
do
expect
(
column_names_with_id
-
ignored_columns
).
to
contain_exactly
(
*
foreign_keys_columns
)
end
end
end
end
end
end
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment