mirror of
https://gitlab.com/gitlab-org/gitlab-foss.git
synced 2025-08-12 23:57:42 +00:00
101 lines
3.2 KiB
Ruby
101 lines
3.2 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module Database
|
|
class AlterCellSequencesRange
|
|
MISSING_LIMIT_MSG = 'minval and maxval are required to alter sequence range'
|
|
|
|
attr_reader :minval, :maxval, :connection, :logger
|
|
|
|
def initialize(minval, maxval, connection, logger: Gitlab::AppLogger)
|
|
raise MISSING_LIMIT_MSG unless minval.present? && maxval.present?
|
|
|
|
@minval = minval
|
|
@maxval = maxval
|
|
@connection = connection
|
|
@logger = logger
|
|
end
|
|
|
|
def execute
|
|
logger.info("Altering existing sequences with minval: #{minval}, maxval: #{maxval}")
|
|
|
|
sequences.each do |sequence|
|
|
with_lock_retries do
|
|
alter_sequence_query = <<~SQL
|
|
ALTER SEQUENCE #{sequence.seq_name}
|
|
START #{minval} RESTART #{minval} MINVALUE #{minval} MAXVALUE #{maxval}
|
|
SQL
|
|
|
|
connection.execute(alter_sequence_query)
|
|
end
|
|
end
|
|
|
|
logger.info("Altered all existing sequences range.")
|
|
|
|
connection.execute(alter_new_sequences_range_function)
|
|
connection.execute(alter_new_sequences_range_trigger)
|
|
end
|
|
|
|
private
|
|
|
|
def sequences
|
|
Gitlab::Database::PostgresSequence.all
|
|
end
|
|
|
|
def with_lock_retries(&)
|
|
Gitlab::Database::WithLockRetries.new(
|
|
connection: connection,
|
|
logger: logger
|
|
).run(raise_on_exhaustion: false, &)
|
|
end
|
|
|
|
def alter_new_sequences_range_function
|
|
<<~SQL
|
|
CREATE OR REPLACE FUNCTION alter_new_sequences_range()
|
|
RETURNS event_trigger
|
|
AS $$
|
|
DECLARE
|
|
command_record RECORD;
|
|
sequence_name text;
|
|
current_minval BIGINT;
|
|
current_maxval BIGINT;
|
|
BEGIN
|
|
FOR command_record IN SELECT * FROM pg_event_trigger_ddl_commands () LOOP
|
|
-- CREATE TABLE, ALTER TABLE will fire ALTER SEQUENCE event when SERIAL, BIGSERIAL IDs are used.
|
|
IF command_record.command_tag IN ('CREATE SEQUENCE', 'ALTER SEQUENCE') THEN
|
|
sequence_name := substring(command_record.object_identity FROM '([^.]+)$');
|
|
|
|
SELECT min_value, max_value INTO current_minval, current_maxval FROM pg_sequences
|
|
WHERE sequencename = sequence_name;
|
|
|
|
IF current_minval != #{minval} OR current_maxval != #{maxval} THEN
|
|
RAISE NOTICE 'Altering sequence "%" with range [%, %]', sequence_name, #{minval}, #{maxval};
|
|
|
|
EXECUTE FORMAT('ALTER SEQUENCE %I START %s RESTART %s MINVALUE %s MAXVALUE %s',
|
|
sequence_name,
|
|
#{minval},
|
|
#{minval},
|
|
#{minval},
|
|
#{maxval}
|
|
);
|
|
END IF;
|
|
END IF;
|
|
END LOOP;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
SQL
|
|
end
|
|
|
|
def alter_new_sequences_range_trigger
|
|
<<~SQL
|
|
DROP EVENT TRIGGER IF EXISTS alter_new_sequences_range;
|
|
|
|
CREATE EVENT TRIGGER alter_new_sequences_range ON ddl_command_end
|
|
WHEN TAG IN ('CREATE TABLE', 'ALTER TABLE', 'CREATE SEQUENCE', 'ALTER SEQUENCE')
|
|
EXECUTE FUNCTION alter_new_sequences_range();
|
|
SQL
|
|
end
|
|
end
|
|
end
|
|
end
|