activerecord 5.0.7 → 5.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +657 -2080
- data/MIT-LICENSE +1 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +28 -28
- data/examples/simple.rb +3 -3
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations/alias_tracker.rb +10 -11
- data/lib/active_record/associations/association.rb +23 -5
- data/lib/active_record/associations/association_scope.rb +95 -81
- data/lib/active_record/associations/belongs_to_association.rb +7 -4
- data/lib/active_record/associations/builder/belongs_to.rb +30 -16
- data/lib/active_record/associations/builder/collection_association.rb +1 -2
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
- data/lib/active_record/associations/collection_association.rb +36 -205
- data/lib/active_record/associations/collection_proxy.rb +132 -63
- data/lib/active_record/associations/has_many_association.rb +10 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -4
- data/lib/active_record/associations/has_one_association.rb +24 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
- data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +121 -118
- data/lib/active_record/associations/preloader/association.rb +64 -64
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
- data/lib/active_record/associations/preloader/collection_association.rb +6 -6
- data/lib/active_record/associations/preloader/has_many.rb +0 -2
- data/lib/active_record/associations/preloader/singular_association.rb +6 -8
- data/lib/active_record/associations/preloader/through_association.rb +41 -41
- data/lib/active_record/associations/preloader.rb +94 -94
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +2 -5
- data/lib/active_record/associations.rb +1591 -1562
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +229 -46
- data/lib/active_record/attribute_methods/primary_key.rb +74 -73
- data/lib/active_record/attribute_methods/read.rb +39 -35
- data/lib/active_record/attribute_methods/serialization.rb +7 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
- data/lib/active_record/attribute_methods/write.rb +30 -33
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_mutation_tracker.rb +63 -11
- data/lib/active_record/attribute_set/builder.rb +27 -33
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attributes.rb +22 -22
- data/lib/active_record/autosave_association.rb +18 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +56 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +3 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
- data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
- data/lib/active_record/connection_adapters/column.rb +26 -4
- data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
- data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
- data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
- data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
- data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
- data/lib/active_record/connection_handling.rb +14 -26
- data/lib/active_record/core.rb +109 -93
- data/lib/active_record/counter_cache.rb +60 -13
- data/lib/active_record/define_callbacks.rb +20 -0
- data/lib/active_record/dynamic_matchers.rb +80 -79
- data/lib/active_record/enum.rb +8 -6
- data/lib/active_record/errors.rb +64 -15
- data/lib/active_record/explain.rb +1 -2
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +7 -4
- data/lib/active_record/fixture_set/file.rb +11 -8
- data/lib/active_record/fixtures.rb +66 -53
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/inheritance.rb +93 -79
- data/lib/active_record/integration.rb +7 -7
- data/lib/active_record/internal_metadata.rb +3 -16
- data/lib/active_record/legacy_yaml_adapter.rb +1 -1
- data/lib/active_record/locking/optimistic.rb +69 -74
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +23 -28
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +100 -47
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/migration.rb +153 -155
- data/lib/active_record/model_schema.rb +94 -107
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +11 -34
- data/lib/active_record/persistence.rb +65 -50
- data/lib/active_record/query_cache.rb +2 -6
- data/lib/active_record/querying.rb +3 -4
- data/lib/active_record/railtie.rb +16 -17
- data/lib/active_record/railties/controller_runtime.rb +6 -2
- data/lib/active_record/railties/databases.rake +105 -133
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +2 -2
- data/lib/active_record/reflection.rb +154 -108
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/batches.rb +80 -51
- data/lib/active_record/relation/calculations.rb +169 -162
- data/lib/active_record/relation/delegation.rb +32 -31
- data/lib/active_record/relation/finder_methods.rb +197 -231
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
- data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- data/lib/active_record/relation/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +255 -293
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +4 -5
- data/lib/active_record/relation/where_clause.rb +80 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/relation.rb +93 -119
- data/lib/active_record/result.rb +41 -32
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +176 -192
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +15 -38
- data/lib/active_record/schema_migration.rb +8 -4
- data/lib/active_record/scoping/default.rb +90 -90
- data/lib/active_record/scoping/named.rb +11 -11
- data/lib/active_record/scoping.rb +6 -6
- data/lib/active_record/secure_token.rb +2 -2
- data/lib/active_record/statement_cache.rb +13 -15
- data/lib/active_record/store.rb +31 -32
- data/lib/active_record/suppressor.rb +2 -1
- data/lib/active_record/table_metadata.rb +9 -5
- data/lib/active_record/tasks/database_tasks.rb +65 -55
- data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
- data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +46 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +97 -109
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +13 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/internal/abstract_json.rb +4 -0
- data/lib/active_record/type/serialized.rb +14 -8
- data/lib/active_record/type/text.rb +9 -0
- data/lib/active_record/type/time.rb +0 -1
- data/lib/active_record/type/type_map.rb +11 -15
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -2
- data/lib/active_record/validations/associated.rb +1 -1
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +8 -39
- data/lib/active_record/validations.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +20 -20
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/migration.rb +1 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- data/lib/rails/generators/active_record.rb +4 -4
- metadata +24 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/string/filters'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
module Tasks # :nodoc:
|
5
3
|
class DatabaseAlreadyExists < StandardError; end # :nodoc:
|
@@ -35,15 +33,25 @@ module ActiveRecord
|
|
35
33
|
#
|
36
34
|
# DatabaseTasks.create_current('production')
|
37
35
|
module DatabaseTasks
|
36
|
+
##
|
37
|
+
# :singleton-method:
|
38
|
+
# Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
|
39
|
+
mattr_accessor :structure_dump_flags, instance_accessor: false
|
40
|
+
|
41
|
+
##
|
42
|
+
# :singleton-method:
|
43
|
+
# Extra flags passed to database CLI tool when calling db:structure:load
|
44
|
+
mattr_accessor :structure_load_flags, instance_accessor: false
|
45
|
+
|
38
46
|
extend self
|
39
47
|
|
40
48
|
attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
|
41
49
|
attr_accessor :database_configuration
|
42
50
|
|
43
|
-
LOCAL_HOSTS
|
51
|
+
LOCAL_HOSTS = ["127.0.0.1", "localhost"]
|
44
52
|
|
45
53
|
def check_protected_environments!
|
46
|
-
unless ENV[
|
54
|
+
unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
|
47
55
|
current = ActiveRecord::Migrator.current_environment
|
48
56
|
stored = ActiveRecord::Migrator.last_stored_environment
|
49
57
|
|
@@ -72,15 +80,15 @@ module ActiveRecord
|
|
72
80
|
end
|
73
81
|
|
74
82
|
def migrations_paths
|
75
|
-
@migrations_paths ||= Rails.application.paths[
|
83
|
+
@migrations_paths ||= Rails.application.paths["db/migrate"].to_a
|
76
84
|
end
|
77
85
|
|
78
86
|
def fixtures_path
|
79
|
-
@fixtures_path ||= if ENV[
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
87
|
+
@fixtures_path ||= if ENV["FIXTURES_PATH"]
|
88
|
+
File.join(root, ENV["FIXTURES_PATH"])
|
89
|
+
else
|
90
|
+
File.join(root, "test", "fixtures")
|
91
|
+
end
|
84
92
|
end
|
85
93
|
|
86
94
|
def root
|
@@ -96,7 +104,7 @@ module ActiveRecord
|
|
96
104
|
end
|
97
105
|
|
98
106
|
def current_config(options = {})
|
99
|
-
options.reverse_merge! :
|
107
|
+
options.reverse_merge! env: env
|
100
108
|
if options.has_key?(:config)
|
101
109
|
@current_config = options[:config]
|
102
110
|
else
|
@@ -106,13 +114,13 @@ module ActiveRecord
|
|
106
114
|
|
107
115
|
def create(*arguments)
|
108
116
|
configuration = arguments.first
|
109
|
-
class_for_adapter(configuration[
|
117
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).create
|
110
118
|
$stdout.puts "Created database '#{configuration['database']}'"
|
111
119
|
rescue DatabaseAlreadyExists
|
112
120
|
$stderr.puts "Database '#{configuration['database']}' already exists"
|
113
121
|
rescue Exception => error
|
114
122
|
$stderr.puts error
|
115
|
-
$stderr.puts "Couldn't create database
|
123
|
+
$stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
|
116
124
|
raise
|
117
125
|
end
|
118
126
|
|
@@ -120,7 +128,7 @@ module ActiveRecord
|
|
120
128
|
old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
|
121
129
|
each_local_configuration { |configuration| create configuration }
|
122
130
|
if old_pool
|
123
|
-
ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec)
|
131
|
+
ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
|
124
132
|
end
|
125
133
|
end
|
126
134
|
|
@@ -133,7 +141,7 @@ module ActiveRecord
|
|
133
141
|
|
134
142
|
def drop(*arguments)
|
135
143
|
configuration = arguments.first
|
136
|
-
class_for_adapter(configuration[
|
144
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).drop
|
137
145
|
$stdout.puts "Dropped database '#{configuration['database']}'"
|
138
146
|
rescue ActiveRecord::NoDatabaseError
|
139
147
|
$stderr.puts "Database '#{configuration['database']}' does not exist"
|
@@ -158,7 +166,7 @@ module ActiveRecord
|
|
158
166
|
|
159
167
|
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
160
168
|
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
161
|
-
scope
|
169
|
+
scope = ENV["SCOPE"]
|
162
170
|
verbose_was, Migration.verbose = Migration.verbose, verbose
|
163
171
|
Migrator.migrate(migrations_paths, version) do |migration|
|
164
172
|
scope.blank? || scope == migration.scope
|
@@ -174,7 +182,7 @@ module ActiveRecord
|
|
174
182
|
|
175
183
|
def charset(*arguments)
|
176
184
|
configuration = arguments.first
|
177
|
-
class_for_adapter(configuration[
|
185
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).charset
|
178
186
|
end
|
179
187
|
|
180
188
|
def collation_current(environment = env)
|
@@ -183,11 +191,11 @@ module ActiveRecord
|
|
183
191
|
|
184
192
|
def collation(*arguments)
|
185
193
|
configuration = arguments.first
|
186
|
-
class_for_adapter(configuration[
|
194
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).collation
|
187
195
|
end
|
188
196
|
|
189
197
|
def purge(configuration)
|
190
|
-
class_for_adapter(configuration[
|
198
|
+
class_for_adapter(configuration["adapter"]).new(configuration).purge
|
191
199
|
end
|
192
200
|
|
193
201
|
def purge_all
|
@@ -206,13 +214,13 @@ module ActiveRecord
|
|
206
214
|
def structure_dump(*arguments)
|
207
215
|
configuration = arguments.first
|
208
216
|
filename = arguments.delete_at 1
|
209
|
-
class_for_adapter(configuration[
|
217
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
|
210
218
|
end
|
211
219
|
|
212
220
|
def structure_load(*arguments)
|
213
221
|
configuration = arguments.first
|
214
222
|
filename = arguments.delete_at 1
|
215
|
-
class_for_adapter(configuration[
|
223
|
+
class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
|
216
224
|
end
|
217
225
|
|
218
226
|
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env) # :nodoc:
|
@@ -233,14 +241,6 @@ module ActiveRecord
|
|
233
241
|
ActiveRecord::InternalMetadata[:environment] = environment
|
234
242
|
end
|
235
243
|
|
236
|
-
def load_schema_for(*args)
|
237
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
238
|
-
This method was renamed to `#load_schema` and will be removed in the future.
|
239
|
-
Use `#load_schema` instead.
|
240
|
-
MSG
|
241
|
-
load_schema(*args)
|
242
|
-
end
|
243
|
-
|
244
244
|
def schema_file(format = ActiveRecord::Base.schema_format)
|
245
245
|
case format
|
246
246
|
when :ruby
|
@@ -269,48 +269,58 @@ module ActiveRecord
|
|
269
269
|
if seed_loader
|
270
270
|
seed_loader.load_seed
|
271
271
|
else
|
272
|
-
raise "You tried to load seed data, but no seed loader is specified. Please specify seed "
|
273
|
-
"loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n"
|
272
|
+
raise "You tried to load seed data, but no seed loader is specified. Please specify seed " \
|
273
|
+
"loader with ActiveRecord::Tasks::DatabaseTasks.seed_loader = your_seed_loader\n" \
|
274
274
|
"Seed loader should respond to load_seed method"
|
275
275
|
end
|
276
276
|
end
|
277
277
|
|
278
|
+
# Dumps the schema cache in YAML format for the connection into the file
|
279
|
+
#
|
280
|
+
# ==== Examples:
|
281
|
+
# ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
|
282
|
+
def dump_schema_cache(conn, filename)
|
283
|
+
conn.schema_cache.clear!
|
284
|
+
conn.data_sources.each { |table| conn.schema_cache.add(table) }
|
285
|
+
open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
|
286
|
+
end
|
287
|
+
|
278
288
|
private
|
279
289
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
290
|
+
def class_for_adapter(adapter)
|
291
|
+
key = @tasks.keys.detect { |pattern| adapter[pattern] }
|
292
|
+
unless key
|
293
|
+
raise DatabaseNotSupported, "Rake tasks not supported by '#{adapter}' adapter"
|
294
|
+
end
|
295
|
+
@tasks[key]
|
284
296
|
end
|
285
|
-
@tasks[key]
|
286
|
-
end
|
287
297
|
|
288
|
-
|
289
|
-
|
290
|
-
|
298
|
+
def each_current_configuration(environment)
|
299
|
+
environments = [environment]
|
300
|
+
environments << "test" if environment == "development"
|
291
301
|
|
292
|
-
|
293
|
-
|
302
|
+
ActiveRecord::Base.configurations.slice(*environments).each do |configuration_environment, configuration|
|
303
|
+
next unless configuration["database"]
|
294
304
|
|
295
|
-
|
305
|
+
yield configuration, configuration_environment
|
306
|
+
end
|
296
307
|
end
|
297
|
-
end
|
298
308
|
|
299
|
-
|
300
|
-
|
301
|
-
|
309
|
+
def each_local_configuration
|
310
|
+
ActiveRecord::Base.configurations.each_value do |configuration|
|
311
|
+
next unless configuration["database"]
|
302
312
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
313
|
+
if local_database?(configuration)
|
314
|
+
yield configuration
|
315
|
+
else
|
316
|
+
$stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
|
317
|
+
end
|
307
318
|
end
|
308
319
|
end
|
309
|
-
end
|
310
320
|
|
311
|
-
|
312
|
-
|
313
|
-
|
321
|
+
def local_database?(configuration)
|
322
|
+
configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
|
323
|
+
end
|
314
324
|
end
|
315
325
|
end
|
316
326
|
end
|
@@ -11,10 +11,10 @@ module ActiveRecord
|
|
11
11
|
|
12
12
|
def create
|
13
13
|
establish_connection configuration_without_database
|
14
|
-
connection.create_database configuration[
|
14
|
+
connection.create_database configuration["database"], creation_options
|
15
15
|
establish_connection configuration
|
16
16
|
rescue ActiveRecord::StatementInvalid => error
|
17
|
-
if
|
17
|
+
if error.message.include?("database exists")
|
18
18
|
raise DatabaseAlreadyExists
|
19
19
|
else
|
20
20
|
raise
|
@@ -23,26 +23,26 @@ module ActiveRecord
|
|
23
23
|
if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
|
24
24
|
$stdout.print error.message
|
25
25
|
establish_connection root_configuration_without_database
|
26
|
-
connection.create_database configuration[
|
27
|
-
if configuration[
|
28
|
-
connection.execute grant_statement.gsub(/\s+/,
|
26
|
+
connection.create_database configuration["database"], creation_options
|
27
|
+
if configuration["username"] != "root"
|
28
|
+
connection.execute grant_statement.gsub(/\s+/, " ").strip
|
29
29
|
end
|
30
30
|
establish_connection configuration
|
31
31
|
else
|
32
32
|
$stderr.puts error.inspect
|
33
33
|
$stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}"
|
34
|
-
$stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration[
|
34
|
+
$stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration["encoding"]
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
38
|
def drop
|
39
39
|
establish_connection configuration
|
40
|
-
connection.drop_database configuration[
|
40
|
+
connection.drop_database configuration["database"]
|
41
41
|
end
|
42
42
|
|
43
43
|
def purge
|
44
44
|
establish_connection configuration
|
45
|
-
connection.recreate_database configuration[
|
45
|
+
connection.recreate_database configuration["database"], creation_options
|
46
46
|
end
|
47
47
|
|
48
48
|
def charset
|
@@ -53,99 +53,102 @@ module ActiveRecord
|
|
53
53
|
connection.collation
|
54
54
|
end
|
55
55
|
|
56
|
-
def structure_dump(filename)
|
56
|
+
def structure_dump(filename, extra_flags)
|
57
57
|
args = prepare_command_options
|
58
58
|
args.concat(["--result-file", "#{filename}"])
|
59
59
|
args.concat(["--no-data"])
|
60
60
|
args.concat(["--routines"])
|
61
|
+
args.concat(["--skip-comments"])
|
61
62
|
args.concat(["#{configuration['database']}"])
|
63
|
+
args.unshift(*extra_flags) if extra_flags
|
62
64
|
|
63
|
-
run_cmd(
|
65
|
+
run_cmd("mysqldump", args, "dumping")
|
64
66
|
end
|
65
67
|
|
66
|
-
def structure_load(filename)
|
68
|
+
def structure_load(filename, extra_flags)
|
67
69
|
args = prepare_command_options
|
68
|
-
args.concat([
|
70
|
+
args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
|
69
71
|
args.concat(["--database", "#{configuration['database']}"])
|
72
|
+
args.unshift(*extra_flags) if extra_flags
|
70
73
|
|
71
|
-
run_cmd(
|
74
|
+
run_cmd("mysql", args, "loading")
|
72
75
|
end
|
73
76
|
|
74
77
|
private
|
75
78
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
+
def configuration
|
80
|
+
@configuration
|
81
|
+
end
|
79
82
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
+
def configuration_without_database
|
84
|
+
configuration.merge("database" => nil)
|
85
|
+
end
|
83
86
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
87
|
+
def creation_options
|
88
|
+
Hash.new.tap do |options|
|
89
|
+
options[:charset] = configuration["encoding"] if configuration.include? "encoding"
|
90
|
+
options[:collation] = configuration["collation"] if configuration.include? "collation"
|
91
|
+
end
|
88
92
|
end
|
89
|
-
end
|
90
93
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
94
|
+
def error_class
|
95
|
+
if configuration["adapter"].include?("jdbc")
|
96
|
+
require "active_record/railties/jdbcmysql_error"
|
97
|
+
ArJdbcMySQL::Error
|
98
|
+
elsif defined?(Mysql2)
|
99
|
+
Mysql2::Error
|
100
|
+
else
|
101
|
+
StandardError
|
102
|
+
end
|
99
103
|
end
|
100
|
-
end
|
101
104
|
|
102
|
-
|
103
|
-
|
104
|
-
GRANT ALL PRIVILEGES ON
|
105
|
+
def grant_statement
|
106
|
+
<<-SQL
|
107
|
+
GRANT ALL PRIVILEGES ON `#{configuration['database']}`.*
|
105
108
|
TO '#{configuration['username']}'@'localhost'
|
106
109
|
IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
107
|
-
|
108
|
-
|
110
|
+
SQL
|
111
|
+
end
|
109
112
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
113
|
+
def root_configuration_without_database
|
114
|
+
configuration_without_database.merge(
|
115
|
+
"username" => "root",
|
116
|
+
"password" => root_password
|
117
|
+
)
|
118
|
+
end
|
116
119
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
120
|
+
def root_password
|
121
|
+
$stdout.print "Please provide the root password for your MySQL installation\n>"
|
122
|
+
$stdin.gets.strip
|
123
|
+
end
|
121
124
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
125
|
+
def prepare_command_options
|
126
|
+
args = {
|
127
|
+
"host" => "--host",
|
128
|
+
"port" => "--port",
|
129
|
+
"socket" => "--socket",
|
130
|
+
"username" => "--user",
|
131
|
+
"password" => "--password",
|
132
|
+
"encoding" => "--default-character-set",
|
133
|
+
"sslca" => "--ssl-ca",
|
134
|
+
"sslcert" => "--ssl-cert",
|
135
|
+
"sslcapath" => "--ssl-capath",
|
136
|
+
"sslcipher" => "--ssl-cipher",
|
137
|
+
"sslkey" => "--ssl-key"
|
138
|
+
}.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
|
139
|
+
|
140
|
+
args
|
141
|
+
end
|
139
142
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
+
def run_cmd(cmd, args, action)
|
144
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
145
|
+
end
|
143
146
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
147
|
+
def run_cmd_error(cmd, args, action)
|
148
|
+
msg = "failed to execute: `#{cmd}`\n"
|
149
|
+
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
150
|
+
msg
|
151
|
+
end
|
149
152
|
end
|
150
153
|
end
|
151
154
|
end
|
@@ -1,7 +1,11 @@
|
|
1
|
+
require "tempfile"
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Tasks # :nodoc:
|
3
5
|
class PostgreSQLDatabaseTasks # :nodoc:
|
4
|
-
DEFAULT_ENCODING = ENV[
|
6
|
+
DEFAULT_ENCODING = ENV["CHARSET"] || "utf8"
|
7
|
+
ON_ERROR_STOP_1 = "ON_ERROR_STOP=1".freeze
|
8
|
+
SQL_COMMENT_BEGIN = "--".freeze
|
5
9
|
|
6
10
|
delegate :connection, :establish_connection, :clear_active_connections!,
|
7
11
|
to: ActiveRecord::Base
|
@@ -12,8 +16,8 @@ module ActiveRecord
|
|
12
16
|
|
13
17
|
def create(master_established = false)
|
14
18
|
establish_master_connection unless master_established
|
15
|
-
connection.create_database configuration[
|
16
|
-
configuration.merge(
|
19
|
+
connection.create_database configuration["database"],
|
20
|
+
configuration.merge("encoding" => encoding)
|
17
21
|
establish_connection configuration
|
18
22
|
rescue ActiveRecord::StatementInvalid => error
|
19
23
|
if error.cause.is_a?(PG::DuplicateDatabase)
|
@@ -25,7 +29,7 @@ module ActiveRecord
|
|
25
29
|
|
26
30
|
def drop
|
27
31
|
establish_master_connection
|
28
|
-
connection.drop_database configuration[
|
32
|
+
connection.drop_database configuration["database"]
|
29
33
|
end
|
30
34
|
|
31
35
|
def charset
|
@@ -42,69 +46,90 @@ module ActiveRecord
|
|
42
46
|
create true
|
43
47
|
end
|
44
48
|
|
45
|
-
def structure_dump(filename)
|
49
|
+
def structure_dump(filename, extra_flags)
|
46
50
|
set_psql_env
|
47
51
|
|
48
|
-
search_path =
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
search_path = \
|
53
|
+
case ActiveRecord::Base.dump_schemas
|
54
|
+
when :schema_search_path
|
55
|
+
configuration["schema_search_path"]
|
56
|
+
when :all
|
57
|
+
nil
|
58
|
+
when String
|
59
|
+
ActiveRecord::Base.dump_schemas
|
60
|
+
end
|
56
61
|
|
57
|
-
args = [
|
62
|
+
args = ["-s", "-x", "-O", "-f", filename]
|
63
|
+
args.concat(Array(extra_flags)) if extra_flags
|
58
64
|
unless search_path.blank?
|
59
|
-
args += search_path.split(
|
65
|
+
args += search_path.split(",").map do |part|
|
60
66
|
"--schema=#{part.strip}"
|
61
67
|
end
|
62
68
|
end
|
63
|
-
args << configuration[
|
64
|
-
run_cmd(
|
69
|
+
args << configuration["database"]
|
70
|
+
run_cmd("pg_dump", args, "dumping")
|
71
|
+
remove_sql_header_comments(filename)
|
65
72
|
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
|
66
73
|
end
|
67
74
|
|
68
|
-
def structure_load(filename)
|
75
|
+
def structure_load(filename, extra_flags)
|
69
76
|
set_psql_env
|
70
|
-
args = [
|
71
|
-
|
77
|
+
args = ["-v", ON_ERROR_STOP_1, "-q", "-f", filename]
|
78
|
+
args.concat(Array(extra_flags)) if extra_flags
|
79
|
+
args << configuration["database"]
|
80
|
+
run_cmd("psql", args, "loading")
|
72
81
|
end
|
73
82
|
|
74
83
|
private
|
75
84
|
|
76
|
-
|
77
|
-
|
78
|
-
|
85
|
+
def configuration
|
86
|
+
@configuration
|
87
|
+
end
|
79
88
|
|
80
|
-
|
81
|
-
|
82
|
-
|
89
|
+
def encoding
|
90
|
+
configuration["encoding"] || DEFAULT_ENCODING
|
91
|
+
end
|
83
92
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
93
|
+
def establish_master_connection
|
94
|
+
establish_connection configuration.merge(
|
95
|
+
"database" => "postgres",
|
96
|
+
"schema_search_path" => "public"
|
97
|
+
)
|
98
|
+
end
|
90
99
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
100
|
+
def set_psql_env
|
101
|
+
ENV["PGHOST"] = configuration["host"] if configuration["host"]
|
102
|
+
ENV["PGPORT"] = configuration["port"].to_s if configuration["port"]
|
103
|
+
ENV["PGPASSWORD"] = configuration["password"].to_s if configuration["password"]
|
104
|
+
ENV["PGUSER"] = configuration["username"].to_s if configuration["username"]
|
105
|
+
end
|
97
106
|
|
98
|
-
|
99
|
-
|
100
|
-
|
107
|
+
def run_cmd(cmd, args, action)
|
108
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
109
|
+
end
|
101
110
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
111
|
+
def run_cmd_error(cmd, args, action)
|
112
|
+
msg = "failed to execute:\n"
|
113
|
+
msg << "#{cmd} #{args.join(' ')}\n\n"
|
114
|
+
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
115
|
+
msg
|
116
|
+
end
|
117
|
+
|
118
|
+
def remove_sql_header_comments(filename)
|
119
|
+
removing_comments = true
|
120
|
+
tempfile = Tempfile.open("uncommented_structure.sql")
|
121
|
+
begin
|
122
|
+
File.foreach(filename) do |line|
|
123
|
+
unless removing_comments && (line.start_with?(SQL_COMMENT_BEGIN) || line.blank?)
|
124
|
+
tempfile << line
|
125
|
+
removing_comments = false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
ensure
|
129
|
+
tempfile.close
|
130
|
+
end
|
131
|
+
FileUtils.mv(tempfile.path, filename)
|
132
|
+
end
|
108
133
|
end
|
109
134
|
end
|
110
135
|
end
|