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:
Diffstat (limited to 'lib/gitlab/database/migration_helpers.rb')
-rw-r--r--lib/gitlab/database/migration_helpers.rb75
1 files changed, 45 insertions, 30 deletions
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 9968096b1f6..7dce4fa0ce2 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -10,8 +10,6 @@ module Gitlab
# https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS
MAX_IDENTIFIER_NAME_LENGTH = 63
-
- PERMITTED_TIMESTAMP_COLUMNS = %i[created_at updated_at deleted_at].to_set.freeze
DEFAULT_TIMESTAMP_COLUMNS = %i[created_at updated_at].freeze
# Adds `created_at` and `updated_at` columns with timezone information.
@@ -28,33 +26,23 @@ module Gitlab
# :default - The default value for the column.
# :null - When set to `true` the column will allow NULL values.
# The default is to not allow NULL values.
- # :columns - the column names to create. Must be one
- # of `Gitlab::Database::MigrationHelpers::PERMITTED_TIMESTAMP_COLUMNS`.
+ # :columns - the column names to create. Must end with `_at`.
# Default value: `DEFAULT_TIMESTAMP_COLUMNS`
#
# All options are optional.
def add_timestamps_with_timezone(table_name, options = {})
- options[:null] = false if options[:null].nil?
columns = options.fetch(:columns, DEFAULT_TIMESTAMP_COLUMNS)
- default_value = options[:default]
-
- validate_not_in_transaction!(:add_timestamps_with_timezone, 'with default value') if default_value
columns.each do |column_name|
validate_timestamp_column_name!(column_name)
- # If default value is presented, use `add_column_with_default` method instead.
- if default_value
- add_column_with_default(
- table_name,
- column_name,
- :datetime_with_timezone,
- default: default_value,
- allow_null: options[:null]
- )
- else
- add_column(table_name, column_name, :datetime_with_timezone, **options)
- end
+ add_column(
+ table_name,
+ column_name,
+ :datetime_with_timezone,
+ default: options[:default],
+ null: options[:null] || false
+ )
end
end
@@ -147,8 +135,18 @@ module Gitlab
options = options.merge({ algorithm: :concurrently })
if index_exists?(table_name, column_name, **options)
- Gitlab::AppLogger.warn "Index not created because it already exists (this may be due to an aborted migration or similar): table_name: #{table_name}, column_name: #{column_name}"
- return
+ name = options[:name] || index_name(table_name, column_name)
+ _, schema = table_name.to_s.split('.').reverse
+
+ if index_invalid?(name, schema: schema)
+ say "Index being recreated because the existing version was INVALID: table_name: #{table_name}, column_name: #{column_name}"
+
+ remove_concurrent_index_by_name(table_name, name)
+ else
+ say "Index not created because it already exists (this may be due to an aborted migration or similar): table_name: #{table_name}, column_name: #{column_name}"
+
+ return
+ end
end
disable_statement_timeout do
@@ -159,6 +157,23 @@ module Gitlab
unprepare_async_index(table_name, column_name, **options)
end
+ def index_invalid?(index_name, schema: nil)
+ index_name = connection.quote(index_name)
+ schema = connection.quote(schema) if schema
+ schema ||= 'current_schema()'
+
+ connection.select_value(<<~SQL)
+ select not i.indisvalid
+ from pg_class c
+ inner join pg_index i
+ on c.oid = i.indexrelid
+ inner join pg_namespace n
+ on n.oid = c.relnamespace
+ where n.nspname = #{schema}
+ and c.relname = #{index_name}
+ SQL
+ end
+
# Removes an existed index, concurrently
#
# Example:
@@ -1245,8 +1260,8 @@ module Gitlab
def check_trigger_permissions!(table)
unless Grant.create_and_execute_trigger?(table)
- dbname = Database.main.database_name
- user = Database.main.username
+ dbname = ApplicationRecord.database.database_name
+ user = ApplicationRecord.database.username
raise <<-EOF
Your database user is not allowed to create, drop, or execute triggers on the
@@ -1568,8 +1583,8 @@ into similar problems in the future (e.g. when new tables are created).
def create_extension(extension)
execute('CREATE EXTENSION IF NOT EXISTS %s' % extension)
rescue ActiveRecord::StatementInvalid => e
- dbname = Database.main.database_name
- user = Database.main.username
+ dbname = ApplicationRecord.database.database_name
+ user = ApplicationRecord.database.username
warn(<<~MSG) if e.to_s =~ /permission denied/
GitLab requires the PostgreSQL extension '#{extension}' installed in database '#{dbname}', but
@@ -1596,8 +1611,8 @@ into similar problems in the future (e.g. when new tables are created).
def drop_extension(extension)
execute('DROP EXTENSION IF EXISTS %s' % extension)
rescue ActiveRecord::StatementInvalid => e
- dbname = Database.main.database_name
- user = Database.main.username
+ dbname = ApplicationRecord.database.database_name
+ user = ApplicationRecord.database.username
warn(<<~MSG) if e.to_s =~ /permission denied/
This migration attempts to drop the PostgreSQL extension '#{extension}'
@@ -1791,11 +1806,11 @@ into similar problems in the future (e.g. when new tables are created).
end
def validate_timestamp_column_name!(column_name)
- return if PERMITTED_TIMESTAMP_COLUMNS.member?(column_name)
+ return if column_name.to_s.end_with?('_at')
raise <<~MESSAGE
Illegal timestamp column name! Got #{column_name}.
- Must be one of: #{PERMITTED_TIMESTAMP_COLUMNS.to_a}
+ Must end with `_at`}
MESSAGE
end