43 lines
1.2 KiB
Ruby
43 lines
1.2 KiB
Ruby
|
# frozen_string_literal: true
|
||
|
|
||
|
module Gitlab
|
||
|
module Database
|
||
|
module PartitioningMigrationHelpers
|
||
|
# Helper class to copy data between two tables via upserts
|
||
|
class BulkCopy
|
||
|
DELIMITER = ', '
|
||
|
|
||
|
attr_reader :source_table, :destination_table, :source_column, :connection
|
||
|
|
||
|
def initialize(source_table, destination_table, source_column, connection:)
|
||
|
@source_table = source_table
|
||
|
@destination_table = destination_table
|
||
|
@source_column = source_column
|
||
|
@connection = connection
|
||
|
end
|
||
|
|
||
|
def copy_between(start_id, stop_id)
|
||
|
connection.execute(<<~SQL)
|
||
|
INSERT INTO #{destination_table} (#{column_listing})
|
||
|
SELECT #{column_listing}
|
||
|
FROM #{source_table}
|
||
|
WHERE #{source_column} BETWEEN #{start_id} AND #{stop_id}
|
||
|
FOR UPDATE
|
||
|
ON CONFLICT (#{conflict_targets}) DO NOTHING
|
||
|
SQL
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def column_listing
|
||
|
@column_listing ||= connection.columns(source_table).map(&:name).join(DELIMITER)
|
||
|
end
|
||
|
|
||
|
def conflict_targets
|
||
|
connection.primary_keys(destination_table).join(DELIMITER)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|