SQLite3: Make fixture loading to bulk statements
This commit is contained in:
parent
c852eda542
commit
d8d6bd5e63
|
@ -353,39 +353,12 @@ module ActiveRecord
|
||||||
# We keep this method to provide fallback
|
# We keep this method to provide fallback
|
||||||
# for databases like sqlite that do not support bulk inserts.
|
# for databases like sqlite that do not support bulk inserts.
|
||||||
def insert_fixture(fixture, table_name)
|
def insert_fixture(fixture, table_name)
|
||||||
fixture = fixture.stringify_keys
|
execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
|
||||||
|
|
||||||
columns = schema_cache.columns_hash(table_name)
|
|
||||||
binds = fixture.map do |name, value|
|
|
||||||
if column = columns[name]
|
|
||||||
type = lookup_cast_type_from_column(column)
|
|
||||||
Relation::QueryAttribute.new(name, value, type)
|
|
||||||
else
|
|
||||||
raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table = Arel::Table.new(table_name)
|
|
||||||
|
|
||||||
values = binds.map do |bind|
|
|
||||||
value = with_yaml_fallback(bind.value_for_database)
|
|
||||||
[table[bind.name], value]
|
|
||||||
end
|
|
||||||
|
|
||||||
manager = Arel::InsertManager.new
|
|
||||||
manager.into(table)
|
|
||||||
manager.insert(values)
|
|
||||||
execute manager.to_sql, "Fixture Insert"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
||||||
fixture_inserts = fixture_set.map do |table_name, fixtures|
|
fixture_inserts = build_fixture_statements(fixture_set)
|
||||||
next if fixtures.empty?
|
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
|
||||||
|
|
||||||
build_fixture_sql(fixtures, table_name)
|
|
||||||
end.compact
|
|
||||||
|
|
||||||
table_deletes = tables_to_delete.map { |table| +"DELETE FROM #{quote_table_name table}" }
|
|
||||||
total_sql = Array(combine_multi_statements(table_deletes + fixture_inserts))
|
total_sql = Array(combine_multi_statements(table_deletes + fixture_inserts))
|
||||||
|
|
||||||
with_multi_statements do
|
with_multi_statements do
|
||||||
|
@ -433,14 +406,17 @@ module ActiveRecord
|
||||||
execute(sql, name)
|
execute(sql, name)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
|
||||||
|
private_constant :DEFAULT_INSERT_VALUE
|
||||||
|
|
||||||
def default_insert_value(column)
|
def default_insert_value(column)
|
||||||
Arel.sql("DEFAULT")
|
DEFAULT_INSERT_VALUE
|
||||||
end
|
end
|
||||||
|
|
||||||
def build_fixture_sql(fixtures, table_name)
|
def build_fixture_sql(fixtures, table_name)
|
||||||
columns = schema_cache.columns_hash(table_name)
|
columns = schema_cache.columns_hash(table_name)
|
||||||
|
|
||||||
values = fixtures.map do |fixture|
|
values_list = fixtures.map do |fixture|
|
||||||
fixture = fixture.stringify_keys
|
fixture = fixture.stringify_keys
|
||||||
|
|
||||||
unknown_columns = fixture.keys - columns.keys
|
unknown_columns = fixture.keys - columns.keys
|
||||||
|
@ -462,12 +438,32 @@ module ActiveRecord
|
||||||
table = Arel::Table.new(table_name)
|
table = Arel::Table.new(table_name)
|
||||||
manager = Arel::InsertManager.new
|
manager = Arel::InsertManager.new
|
||||||
manager.into(table)
|
manager.into(table)
|
||||||
columns.each_key { |column| manager.columns << table[column] }
|
|
||||||
manager.values = manager.create_values_list(values)
|
|
||||||
|
|
||||||
|
if values_list.size == 1
|
||||||
|
values = values_list.shift
|
||||||
|
new_values = []
|
||||||
|
columns.each_key.with_index { |column, i|
|
||||||
|
unless values[i].equal?(DEFAULT_INSERT_VALUE)
|
||||||
|
new_values << values[i]
|
||||||
|
manager.columns << table[column]
|
||||||
|
end
|
||||||
|
}
|
||||||
|
values_list << new_values
|
||||||
|
else
|
||||||
|
columns.each_key { |column| manager.columns << table[column] }
|
||||||
|
end
|
||||||
|
|
||||||
|
manager.values = manager.create_values_list(values_list)
|
||||||
manager.to_sql
|
manager.to_sql
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_fixture_statements(fixture_set)
|
||||||
|
fixture_set.map do |table_name, fixtures|
|
||||||
|
next if fixtures.empty?
|
||||||
|
build_fixture_sql(fixtures, table_name)
|
||||||
|
end.compact
|
||||||
|
end
|
||||||
|
|
||||||
def build_truncate_statements(*table_names)
|
def build_truncate_statements(*table_names)
|
||||||
truncate_tables = table_names.map do |table_name|
|
truncate_tables = table_names.map do |table_name|
|
||||||
"TRUNCATE TABLE #{quote_table_name(table_name)}"
|
"TRUNCATE TABLE #{quote_table_name(table_name)}"
|
||||||
|
|
|
@ -75,7 +75,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_insert_value(column)
|
def default_insert_value(column)
|
||||||
Arel.sql("DEFAULT") unless column.auto_increment?
|
super unless column.auto_increment?
|
||||||
end
|
end
|
||||||
|
|
||||||
def last_inserted_id(result)
|
def last_inserted_id(result)
|
||||||
|
|
|
@ -19,6 +19,13 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def build_fixture_statements(fixture_set)
|
||||||
|
fixture_set.flat_map do |table_name, fixtures|
|
||||||
|
next if fixtures.empty?
|
||||||
|
fixtures.map { |fixture| build_fixture_sql([fixture], table_name) }
|
||||||
|
end.compact
|
||||||
|
end
|
||||||
|
|
||||||
def build_truncate_statements(*table_names)
|
def build_truncate_statements(*table_names)
|
||||||
truncate_tables = table_names.map do |table_name|
|
truncate_tables = table_names.map do |table_name|
|
||||||
"DELETE FROM #{quote_table_name(table_name)}"
|
"DELETE FROM #{quote_table_name(table_name)}"
|
||||||
|
|
|
@ -384,18 +384,6 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
|
||||||
disable_referential_integrity do
|
|
||||||
transaction(requires_new: true) do
|
|
||||||
tables_to_delete.each { |table| delete "DELETE FROM #{quote_table_name(table)}", "Fixture Delete" }
|
|
||||||
|
|
||||||
fixture_set.each do |table_name, rows|
|
|
||||||
rows.each { |row| insert_fixture(row, table_name) }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def build_insert_sql(insert) # :nodoc:
|
def build_insert_sql(insert) # :nodoc:
|
||||||
sql = +"INSERT #{insert.into} #{insert.values_list}"
|
sql = +"INSERT #{insert.into} #{insert.values_list}"
|
||||||
|
|
||||||
|
|
|
@ -209,7 +209,7 @@ class FixturesTest < ActiveRecord::TestCase
|
||||||
conn = ActiveRecord::Base.connection
|
conn = ActiveRecord::Base.connection
|
||||||
mysql_margin = 2
|
mysql_margin = 2
|
||||||
packet_size = 1024
|
packet_size = 1024
|
||||||
bytes_needed_to_have_a_1024_bytes_fixture = 860
|
bytes_needed_to_have_a_1024_bytes_fixture = 906
|
||||||
fixtures = {
|
fixtures = {
|
||||||
"traffic_lights" => [
|
"traffic_lights" => [
|
||||||
{ "location" => "US", "state" => ["NY"], "long_state" => ["a" * bytes_needed_to_have_a_1024_bytes_fixture] },
|
{ "location" => "US", "state" => ["NY"], "long_state" => ["a" * bytes_needed_to_have_a_1024_bytes_fixture] },
|
||||||
|
@ -496,12 +496,8 @@ class FixturesTest < ActiveRecord::TestCase
|
||||||
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT + "/naked/yml", "parrots")
|
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT + "/naked/yml", "parrots")
|
||||||
end
|
end
|
||||||
|
|
||||||
if current_adapter?(:SQLite3Adapter)
|
|
||||||
assert_equal(%(table "parrots" has no column named "arrr".), e.message)
|
|
||||||
else
|
|
||||||
assert_equal(%(table "parrots" has no columns named "arrr", "foobar".), e.message)
|
assert_equal(%(table "parrots" has no columns named "arrr", "foobar".), e.message)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def test_yaml_file_with_symbol_columns
|
def test_yaml_file_with_symbol_columns
|
||||||
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT + "/naked/yml", "trees")
|
ActiveRecord::FixtureSet.create_fixtures(FIXTURES_ROOT + "/naked/yml", "trees")
|
||||||
|
|
Loading…
Reference in New Issue