Module: ActiveRecord::Import::MysqlAdapter
- Includes:
- ImportSupport, OnDuplicateKeyUpdateSupport
- 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.
-
#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, arr) ⇒ Object
:nodoc:.
-
#sql_for_on_duplicate_key_update_as_hash(table_name, 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
73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 73 def add_column_for_on_duplicate_key_update( column, = {} ) # :nodoc: if .include?(:on_duplicate_key_update) 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 elsif ![:ignore] && ![:on_duplicate_key_ignore] [:on_duplicate_key_update] = [column.to_sym] end end |
#duplicate_key_update_error?(exception) ⇒ Boolean
Return true if the statement is a duplicate key record error
120 121 122 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 120 def duplicate_key_update_error?(exception) # :nodoc: exception.is_a?(ActiveRecord::StatementInvalid) && exception.to_s.include?('Duplicate entry') 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.
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 53 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 10 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 [number_of_inserts, []] end |
#max_allowed_packet ⇒ Object
Returns the maximum number of bytes that the server will allow in a single packet
57 58 59 60 61 62 63 64 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 57 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
66 67 68 69 70 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 66 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
.
87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 87 def sql_for_on_duplicate_key_update( table_name, *args ) # :nodoc: sql = ' ON DUPLICATE KEY UPDATE ' arg = args.first if arg.is_a?( Array ) sql << sql_for_on_duplicate_key_update_as_array( table_name, arg ) elsif arg.is_a?( Hash ) sql << sql_for_on_duplicate_key_update_as_hash( table_name, 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, arr) ⇒ Object
:nodoc:
102 103 104 105 106 107 108 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 102 def sql_for_on_duplicate_key_update_as_array( table_name, arr ) # :nodoc: results = arr.map do |column| qc = quote_column_name( column ) "#{table_name}.#{qc}=VALUES(#{qc})" end results.join( ',' ) end |
#sql_for_on_duplicate_key_update_as_hash(table_name, hsh) ⇒ Object
:nodoc:
110 111 112 113 114 115 116 117 |
# File 'lib/activerecord-import/adapters/mysql_adapter.rb', line 110 def sql_for_on_duplicate_key_update_as_hash( table_name, hsh ) # :nodoc: results = hsh.map do |column1, column2| qc1 = quote_column_name( column1 ) qc2 = quote_column_name( column2 ) "#{table_name}.#{qc1}=VALUES( #{qc2} )" end results.join( ',') end |