Created
March 3, 2023 09:26
-
-
Save NoTimeForHero/ca1711a158e559743c08b5abafaa31d9 to your computer and use it in GitHub Desktop.
Реализация Bulk Insert для PostgreSQL в Rails 5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ApplicationRecord < ActiveRecord::Base | |
self.abstract_class = true | |
def self.bulk_insert(data) | |
# @type [PG::Connection] conn | |
conn = self.connection.raw_connection | |
raise NotImplementedError.new 'Database Driver not supported!' unless conn.class.to_s == 'PG::Connection' | |
raise ArgumentError "Data not an Array of Hashes!" unless data.is_a?(Array) && data.all? {|rec| rec.is_a? Hash } | |
return nil unless data.count > 0 | |
fields = data[0].keys | |
values = data.map { |item| item.values } | |
# Создаём Prepared Statement | |
prepared_name = 'bulk_insert' | |
begin | |
conn.exec("DEALLOCATE #{prepared_name}") | |
rescue PG::InvalidSqlStatementName | |
# Ignored | |
end | |
raw_fields = fields.map { |key| conn.escape_string(key)}.join(', ') | |
raw_values = fields.each_with_index.map { |x,index| "$#{index+1}" }.join(', ') | |
conn.prepare(prepared_name, "INSERT INTO #{self.table_name} (#{raw_fields}) VALUES(#{raw_values})") | |
# Запускаем в транзации insert для каждой записи | |
conn.exec("START TRANSACTION") | |
values.each { |record| conn.exec_prepared(prepared_name, record) } | |
conn.exec("COMMIT") | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment