Module: ActiveRecord::Import::MysqlAdapter
- Includes:
- ImportSupport
- Included in:
- ConnectionAdapters::MysqlAdapter, ConnectionAdapters::SeamlessDatabasePoolAdapter, EMMysql2Adapter, Mysql2Adapter
- Defined in:
- lib/activerecord-import/adapters/mysql_adapter.rb
Constant Summary collapse
- NO_MAX_PACKET =
0
- QUERY_OVERHEAD =
This was shown to be true for MySQL, but it’s not clear where the overhead is from.
8
Instance Method Summary collapse
-
#add_column_for_on_duplicate_key_update(column, options = {}) ⇒ Object
Add a column to be updated on duplicate key update.
-
#duplicate_key_update_error?(exception) ⇒ Boolean
Return true if the statement is a duplicate key record error.
- #increment_locking_column!(table_name, results, locking_column) ⇒ Object
-
#insert_many(sql, values, options = {}, *args) ⇒ Object
sql
can be a single string or an array. -
#max_allowed_packet ⇒ Object
Returns the maximum number of bytes that the server will allow in a single packet.
- #pre_sql_statements(options) ⇒ Object
-
#sql_for_on_duplicate_key_update(table_name, *args) ⇒ Object
Returns a generated ON DUPLICATE KEY UPDATE statement given the passed in
args
. -
#sql_for_on_duplicate_key_update_as_array(table_name, locking_column, arr) ⇒ Object
:nodoc:.
-
#sql_for_on_duplicate_key_update_as_hash(table_name, locking_column, hsh) ⇒ Object
:nodoc:.
Methods included from ImportSupport
Instance Method Details
#add_column_for_on_duplicate_key_update(column, options = {}) ⇒ Object
Add a column to be updated on duplicate key update
72 73 74 75 76 77 78 79 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 72 def add_column_for_on_duplicate_key_update( column, = {} ) # :nodoc: if (columns = [:on_duplicate_key_update]) case columns when Array then columns << column.to_sym unless columns.include?(column.to_sym) when Hash then columns[column.to_sym] = column.to_sym end end end |
#duplicate_key_update_error?(exception) ⇒ Boolean
Return true if the statement is a duplicate key record error
119 120 121 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 119 def duplicate_key_update_error?(exception) # :nodoc: exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('Duplicate entry') end |
#increment_locking_column!(table_name, results, locking_column) ⇒ Object
123 124 125 126 127 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 123 def increment_locking_column!(table_name, results, locking_column) if locking_column.present? results << "`#{locking_column}`=#{table_name}.`#{locking_column}`+1" end end |
#insert_many(sql, values, options = {}, *args) ⇒ Object
sql
can be a single string or an array. If it is an array all elements that are in position >= 1 will be appended to the final SQL.
9 10 11 12 13 14 15 16 17 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 46 47 48 49 50 51 52 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 9 def insert_many( sql, values, = {}, *args ) # :nodoc: # the number of inserts default number_of_inserts = 0 base_sql, post_sql = if sql.is_a?( String ) [sql, ''] elsif sql.is_a?( Array ) [sql.shift, sql.join( ' ' )] end sql_size = QUERY_OVERHEAD + base_sql.size + post_sql.size # the number of bytes the requested insert statement values will take up values_in_bytes = values.sum(&:bytesize) # the number of bytes (commas) it will take to comma separate our values comma_separated_bytes = values.size - 1 # the total number of bytes required if this statement is one statement total_bytes = sql_size + values_in_bytes + comma_separated_bytes max = max_allowed_packet # if we can insert it all as one statement if NO_MAX_PACKET == max || total_bytes <= max || [:force_single_insert] number_of_inserts += 1 sql2insert = base_sql + values.join( ',' ) + post_sql insert( sql2insert, *args ) else value_sets = ::ActiveRecord::Import::ValueSetsBytesParser.parse(values, reserved_bytes: sql_size, max_bytes: max) transaction(requires_new: true) do value_sets.each do |value_set| number_of_inserts += 1 sql2insert = base_sql + value_set.join( ',' ) + post_sql insert( sql2insert, *args ) end end end ActiveRecord::Import::Result.new([], number_of_inserts, [], []) end |
#max_allowed_packet ⇒ Object
Returns the maximum number of bytes that the server will allow in a single packet
56 57 58 59 60 61 62 63 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 56 def max_allowed_packet # :nodoc: @max_allowed_packet ||= begin result = execute( "SHOW VARIABLES like 'max_allowed_packet'" ) # original Mysql gem responds to #fetch_row while Mysql2 responds to #first val = result.respond_to?(:fetch_row) ? result.fetch_row[1] : result.first[1] val.to_i end end |
#pre_sql_statements(options) ⇒ Object
65 66 67 68 69 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 65 def pre_sql_statements( ) sql = [] sql << "IGNORE" if [:ignore] || [:on_duplicate_key_ignore] sql + super end |
#sql_for_on_duplicate_key_update(table_name, *args) ⇒ Object
Returns a generated ON DUPLICATE KEY UPDATE statement given the passed in args
.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 83 def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc: sql = ' ON DUPLICATE KEY UPDATE ' arg = args.first locking_column = args.last if arg.is_a?( Array ) sql << sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arg ) elsif arg.is_a?( Hash ) sql << sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, arg ) elsif arg.is_a?( String ) sql << arg else raise ArgumentError, "Expected Array or Hash" end sql end |
#sql_for_on_duplicate_key_update_as_array(table_name, locking_column, arr) ⇒ Object
:nodoc:
99 100 101 102 103 104 105 106 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 99 def sql_for_on_duplicate_key_update_as_array( table_name, locking_column, arr ) # :nodoc: results = arr.map do |column| qc = quote_column_name( column ) "#{table_name}.#{qc}=VALUES(#{qc})" end increment_locking_column!(table_name, results, locking_column) results.join( ',' ) end |
#sql_for_on_duplicate_key_update_as_hash(table_name, locking_column, hsh) ⇒ Object
:nodoc:
108 109 110 111 112 113 114 115 116 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 108 def sql_for_on_duplicate_key_update_as_hash( table_name, locking_column, hsh ) # :nodoc: results = hsh.map do |column1, column2| qc1 = quote_column_name( column1 ) qc2 = quote_column_name( column2 ) "#{table_name}.#{qc1}=VALUES( #{qc2} )" end increment_locking_column!(table_name, results, locking_column) results.join( ',') end |