Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-11-09 15:10:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-11-09 15:10:06 +0300
commit963e09aecfb3cdd57babdd9b37c15e34601fdb42 (patch)
tree2c3067224f4ed5197d9bfc34a1ff63e7003e05dc /lib/gitlab
parent529d3153bc5823c8326f04649f8362f1a32d8c61 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'lib/gitlab')
-rw-r--r--lib/gitlab/database/migration_helpers/convert_to_bigint.rb88
1 files changed, 82 insertions, 6 deletions
diff --git a/lib/gitlab/database/migration_helpers/convert_to_bigint.rb b/lib/gitlab/database/migration_helpers/convert_to_bigint.rb
index 11f1e62e8b9..d1edb739b85 100644
--- a/lib/gitlab/database/migration_helpers/convert_to_bigint.rb
+++ b/lib/gitlab/database/migration_helpers/convert_to_bigint.rb
@@ -4,12 +4,16 @@ module Gitlab
module Database
module MigrationHelpers
module ConvertToBigint
- # This helper is extracted for the purpose of
- # https://gitlab.com/gitlab-org/gitlab/-/issues/392815
- # so that we can test all combinations just once,
- # and simplify migration tests.
- #
- # Once we are done with the PK conversions we can remove this.
+ INDEX_OPTIONS_MAP = {
+ unique: :unique,
+ order: :orders,
+ opclass: :opclasses,
+ where: :where,
+ type: :type,
+ using: :using,
+ comment: :comment
+ }.freeze
+
def com_or_dev_or_test_but_not_jh?
return true if Gitlab.dev_or_test_env?
@@ -29,6 +33,78 @@ module Gitlab
column.sql_type == 'bigint' && temp_column.sql_type == 'integer'
end
+
+ def add_bigint_column_indexes(table_name, int_column_name)
+ bigint_column_name = convert_to_bigint_column(int_column_name)
+
+ unless column_exists?(table_name.to_s, bigint_column_name)
+ raise "Bigint column '#{bigint_column_name}' does not exist on #{table_name}"
+ end
+
+ indexes(table_name).each do |i|
+ next unless Array(i.columns).join(' ').match?(/\b#{int_column_name}\b/)
+
+ create_bigint_index(table_name, i, int_column_name, bigint_column_name)
+ end
+ end
+
+ # default 'index_name' method is not used because this method can be reused while swapping/dropping the indexes
+ def bigint_index_name(int_column_index_name)
+ # First 20 digits of the hash is chosen to make sure it fits the 63 chars limit
+ digest = Digest::SHA256.hexdigest(int_column_index_name).first(20)
+ "bigint_idx_#{digest}"
+ end
+
+ private
+
+ def create_bigint_index(table_name, index_definition, int_column_name, bigint_column_name)
+ index_attributes = index_definition.as_json
+ index_options = INDEX_OPTIONS_MAP
+ .transform_values { |key| index_attributes[key.to_s] }
+ .select { |_, v| v.present? }
+
+ bigint_index_options = create_bigint_options(
+ index_options,
+ index_definition.name,
+ int_column_name,
+ bigint_column_name
+ )
+
+ add_concurrent_index(
+ table_name,
+ bigint_index_columns(int_column_name, bigint_column_name, index_definition.columns),
+ name: bigint_index_options.delete(:name),
+ ** bigint_index_options
+ )
+ end
+
+ def bigint_index_columns(int_column_name, bigint_column_name, int_index_columns)
+ if int_index_columns.is_a?(String)
+ int_index_columns.gsub(/\b#{int_column_name}\b/, bigint_column_name)
+ else
+ int_index_columns.map do |column|
+ column == int_column_name.to_s ? bigint_column_name : column
+ end
+ end
+ end
+
+ def create_bigint_options(index_options, int_index_name, int_column_name, bigint_column_name)
+ index_options[:name] = bigint_index_name(int_index_name)
+ index_options[:where]&.gsub!(/\b#{int_column_name}\b/, bigint_column_name)
+
+ # ordering on multiple columns will return a Hash instead of string
+ index_options[:order] =
+ if index_options[:order].is_a?(Hash)
+ index_options[:order].to_h do |column, order|
+ column = bigint_column_name if column == int_column_name
+ [column, order]
+ end
+ else
+ index_options[:order]&.gsub(/\b#{int_column_name}\b/, bigint_column_name)
+ end
+
+ index_options.select { |_, v| v.present? }
+ end
end
end
end