Module: ActiveRecord::Import::MysqlAdapter
- Includes:
- ImportSupport, OnDuplicateKeyUpdateSupport
- 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 OnDuplicateKeyUpdateSupport
#supports_on_duplicate_key_update?
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
75 76 77 78 79 80 81 82 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 75 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
122 123 124 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 122 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
126 127 128 129 130 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 126 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.
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 53 54 55 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 12 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
59 60 61 62 63 64 65 66 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 59 def max_allowed_packet # :nodoc: @max_allowed_packet ||= begin result = execute( "SELECT @@max_allowed_packet" ) # original Mysql gem responds to #fetch_row while Mysql2 responds to #first val = result.respond_to?(:fetch_row) ? result.fetch_row[0] : result.first[0] val.to_i end end |
#pre_sql_statements(options) ⇒ Object
68 69 70 71 72 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 68 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
.
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 86 def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc: sql = ' ON DUPLICATE KEY UPDATE '.dup 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:
102 103 104 105 106 107 108 109 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 102 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:
111 112 113 114 115 116 117 118 119 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 111 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 |