1# frozen_string_literal: true 2 3module LegacyBulkInsert 4 extend ActiveSupport::Concern 5 6 class_methods do 7 # Bulk inserts a number of rows into a table, optionally returning their 8 # IDs. 9 # 10 # This method is deprecated, and you should use the BulkInsertSafe module 11 # instead. 12 # 13 # table - The name of the table to insert the rows into. 14 # rows - An Array of Hash instances, each mapping the columns to their 15 # values. 16 # return_ids - When set to true the return value will be an Array of IDs of 17 # the inserted rows 18 # disable_quote - A key or an Array of keys to exclude from quoting (You 19 # become responsible for protection from SQL injection for 20 # these keys!) 21 # on_conflict - Defines an upsert. Values can be: :disabled (default) or 22 # :do_nothing 23 def legacy_bulk_insert(table, rows, return_ids: false, disable_quote: [], on_conflict: nil) 24 return if rows.empty? 25 26 keys = rows.first.keys 27 columns = keys.map { |key| connection.quote_column_name(key) } 28 29 disable_quote = Array(disable_quote).to_set 30 tuples = rows.map do |row| 31 keys.map do |k| 32 disable_quote.include?(k) ? row[k] : connection.quote(row[k]) 33 end 34 end 35 36 sql = <<-EOF 37 INSERT INTO #{table} (#{columns.join(', ')}) 38 VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')} 39 EOF 40 41 sql = "#{sql} ON CONFLICT DO NOTHING" if on_conflict == :do_nothing 42 43 sql = "#{sql} RETURNING id" if return_ids 44 45 result = connection.execute(sql) 46 47 if return_ids 48 result.values.map { |tuple| tuple[0].to_i } 49 else 50 [] 51 end 52 end 53 end 54end 55