Class: ActiveRecord::InsertAll

Inherits:
Object
  • Object
show all
Defined in:
activerecord/lib/active_record/insert_all.rb

Overview

:nodoc:

Defined Under Namespace

Classes: Builder

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(relation, connection, inserts, on_duplicate:, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil) ⇒ InsertAll

Returns a new instance of InsertAll.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'activerecord/lib/active_record/insert_all.rb', line 18

def initialize(relation, connection, inserts, on_duplicate:, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
  @relation = relation
  @model, @connection, @inserts = relation.model, connection, inserts.map(&:stringify_keys)
  @on_duplicate, @update_only, @returning, @unique_by = on_duplicate, update_only, returning, unique_by
  @record_timestamps = record_timestamps.nil? ? model.record_timestamps : record_timestamps

  disallow_raw_sql!(on_duplicate)
  disallow_raw_sql!(returning)

  if @inserts.empty?
    @keys = []
  else
    resolve_sti
    resolve_attribute_aliases
    @keys = @inserts.first.keys
  end

  @scope_attributes = relation.scope_for_create.except(@model.inheritance_column)
  @keys |= @scope_attributes.keys

  @returning = (connection.supports_insert_returning? ? primary_keys : false) if @returning.nil?
  @returning = false if @returning == []

  @unique_by = find_unique_index_for(@unique_by) if @on_duplicate != :raise

  configure_on_duplicate_update_logic
  ensure_valid_options_for_connection!
end

Instance Attribute Details

#connectionObject (readonly)

Returns the value of attribute connection.



7
8
9
# File 'activerecord/lib/active_record/insert_all.rb', line 7

def connection
  @connection
end

#insertsObject (readonly)

Returns the value of attribute inserts.



7
8
9
# File 'activerecord/lib/active_record/insert_all.rb', line 7

def inserts
  @inserts
end

#keysObject (readonly)

Returns the value of attribute keys.



7
8
9
# File 'activerecord/lib/active_record/insert_all.rb', line 7

def keys
  @keys
end

#modelObject (readonly)

Returns the value of attribute model.



7
8
9
# File 'activerecord/lib/active_record/insert_all.rb', line 7

def model
  @model
end

#on_duplicateObject (readonly)

Returns the value of attribute on_duplicate.



8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def on_duplicate
  @on_duplicate
end

#returningObject (readonly)

Returns the value of attribute returning.



8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def returning
  @returning
end

#unique_byObject (readonly)

Returns the value of attribute unique_by.



8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def unique_by
  @unique_by
end

#update_onlyObject (readonly)

Returns the value of attribute update_only.



8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def update_only
  @update_only
end

#update_sqlObject (readonly)

Returns the value of attribute update_sql.



8
9
10
# File 'activerecord/lib/active_record/insert_all.rb', line 8

def update_sql
  @update_sql
end

Class Method Details

.execute(relation) ⇒ Object



11
12
13
14
15
# File 'activerecord/lib/active_record/insert_all.rb', line 11

def execute(relation, ...)
  relation.model.with_connection do |c|
    new(relation, c, ...).execute
  end.tap { relation.reset }
end

Instance Method Details

#executeObject



47
48
49
50
51
52
53
54
# File 'activerecord/lib/active_record/insert_all.rb', line 47

def execute
  return ActiveRecord::Result.empty if inserts.empty?

  message = +"#{model} "
  message << "Bulk " if inserts.many?
  message << (on_duplicate == :update ? "Upsert" : "Insert")
  connection.exec_insert_all to_sql, message
end

#keys_including_timestampsObject

TODO: Consider renaming this method, as it only conditionally extends keys, not always



95
96
97
98
99
100
101
# File 'activerecord/lib/active_record/insert_all.rb', line 95

def keys_including_timestamps
  @keys_including_timestamps ||= if record_timestamps?
    (keys | model.all_timestamp_attributes_in_model).sort!
  else
    keys.sort!
  end
end

#map_key_with_valueObject



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'activerecord/lib/active_record/insert_all.rb', line 72

def map_key_with_value
  timestamps_to_merge = model.all_timestamp_attributes_in_model if record_timestamps?

  inserts.map do |attributes|
    attributes.merge!(@scope_attributes)

    timestamps_to_merge&.each do |attribute|
      attributes[attribute] = connection.high_precision_current_timestamp if !attributes.key?(attribute)
    end

    verify_attributes(attributes)

    keys_including_timestamps.map do |key|
      yield key, attributes[key]
    end
  end
end

#primary_keysObject



60
61
62
# File 'activerecord/lib/active_record/insert_all.rb', line 60

def primary_keys
  Array(@connection.schema_cache.primary_keys(model.table_name))
end

#record_timestamps?Boolean

Returns:

  • (Boolean)


90
91
92
# File 'activerecord/lib/active_record/insert_all.rb', line 90

def record_timestamps?
  @record_timestamps
end

#skip_duplicates?Boolean

Returns:

  • (Boolean)


64
65
66
# File 'activerecord/lib/active_record/insert_all.rb', line 64

def skip_duplicates?
  on_duplicate == :skip
end

#updatable_columnsObject



56
57
58
# File 'activerecord/lib/active_record/insert_all.rb', line 56

def updatable_columns
  @updatable_columns ||= keys - readonly_columns - unique_by_columns
end

#update_duplicates?Boolean

Returns:

  • (Boolean)


68
69
70
# File 'activerecord/lib/active_record/insert_all.rb', line 68

def update_duplicates?
  on_duplicate == :update
end