activerecord 4.2.0 → 5.2.8.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +640 -928
- data/MIT-LICENSE +2 -2
- data/README.rdoc +10 -11
- data/examples/performance.rb +32 -31
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +264 -247
- data/lib/active_record/association_relation.rb +24 -6
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +87 -41
- data/lib/active_record/associations/association_scope.rb +106 -132
- data/lib/active_record/associations/belongs_to_association.rb +55 -36
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +29 -38
- data/lib/active_record/associations/builder/belongs_to.rb +77 -30
- data/lib/active_record/associations/builder/collection_association.rb +14 -23
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +50 -39
- data/lib/active_record/associations/builder/has_many.rb +6 -4
- data/lib/active_record/associations/builder/has_one.rb +13 -6
- data/lib/active_record/associations/builder/singular_association.rb +15 -11
- data/lib/active_record/associations/collection_association.rb +145 -266
- data/lib/active_record/associations/collection_proxy.rb +242 -138
- data/lib/active_record/associations/foreign_association.rb +13 -0
- data/lib/active_record/associations/has_many_association.rb +35 -75
- data/lib/active_record/associations/has_many_through_association.rb +51 -69
- data/lib/active_record/associations/has_one_association.rb +39 -24
- data/lib/active_record/associations/has_one_through_association.rb +18 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +40 -81
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
- data/lib/active_record/associations/join_dependency.rb +134 -154
- data/lib/active_record/associations/preloader/association.rb +85 -116
- data/lib/active_record/associations/preloader/through_association.rb +85 -74
- data/lib/active_record/associations/preloader.rb +83 -93
- data/lib/active_record/associations/singular_association.rb +27 -40
- data/lib/active_record/associations/through_association.rb +48 -23
- data/lib/active_record/associations.rb +1732 -1596
- data/lib/active_record/attribute_assignment.rb +58 -182
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods/before_type_cast.rb +12 -5
- data/lib/active_record/attribute_methods/dirty.rb +94 -125
- data/lib/active_record/attribute_methods/primary_key.rb +86 -71
- data/lib/active_record/attribute_methods/query.rb +4 -2
- data/lib/active_record/attribute_methods/read.rb +45 -63
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +62 -36
- data/lib/active_record/attribute_methods/write.rb +31 -46
- data/lib/active_record/attribute_methods.rb +170 -117
- data/lib/active_record/attributes.rb +201 -74
- data/lib/active_record/autosave_association.rb +118 -45
- data/lib/active_record/base.rb +60 -48
- data/lib/active_record/callbacks.rb +97 -57
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +37 -13
- data/lib/active_record/collection_cache_key.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -284
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +254 -87
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +72 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +119 -52
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +328 -217
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +617 -212
- data/lib/active_record/connection_adapters/abstract/transaction.rb +139 -75
- data/lib/active_record/connection_adapters/abstract_adapter.rb +332 -191
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +567 -563
- data/lib/active_record/connection_adapters/column.rb +50 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +42 -195
- data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -115
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +7 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +65 -51
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +466 -280
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +439 -330
- data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -324
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +40 -27
- data/lib/active_record/core.rb +205 -202
- data/lib/active_record/counter_cache.rb +80 -37
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +136 -90
- data/lib/active_record/errors.rb +180 -52
- data/lib/active_record/explain.rb +23 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +35 -9
- data/lib/active_record/fixtures.rb +193 -135
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +148 -112
- data/lib/active_record/integration.rb +70 -28
- data/lib/active_record/internal_metadata.rb +45 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +92 -98
- data/lib/active_record/locking/pessimistic.rb +15 -3
- data/lib/active_record/log_subscriber.rb +95 -33
- data/lib/active_record/migration/command_recorder.rb +133 -90
- data/lib/active_record/migration/compatibility.rb +217 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/migration.rb +594 -267
- data/lib/active_record/model_schema.rb +292 -111
- data/lib/active_record/nested_attributes.rb +266 -214
- data/lib/active_record/no_touching.rb +8 -2
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +350 -119
- data/lib/active_record/query_cache.rb +13 -24
- data/lib/active_record/querying.rb +19 -17
- data/lib/active_record/railtie.rb +117 -35
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +9 -3
- data/lib/active_record/railties/databases.rake +160 -174
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +447 -288
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +204 -55
- data/lib/active_record/relation/calculations.rb +259 -244
- data/lib/active_record/relation/delegation.rb +67 -60
- data/lib/active_record/relation/finder_methods.rb +290 -253
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +91 -68
- data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -23
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +118 -92
- data/lib/active_record/relation/query_attribute.rb +45 -0
- data/lib/active_record/relation/query_methods.rb +446 -389
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -16
- data/lib/active_record/relation/where_clause.rb +186 -0
- data/lib/active_record/relation/where_clause_factory.rb +34 -0
- data/lib/active_record/relation.rb +287 -339
- data/lib/active_record/result.rb +54 -36
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +155 -124
- data/lib/active_record/schema.rb +30 -24
- data/lib/active_record/schema_dumper.rb +91 -87
- data/lib/active_record/schema_migration.rb +19 -19
- data/lib/active_record/scoping/default.rb +102 -84
- data/lib/active_record/scoping/named.rb +81 -32
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +45 -35
- data/lib/active_record/store.rb +42 -36
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +82 -0
- data/lib/active_record/tasks/database_tasks.rb +136 -95
- data/lib/active_record/tasks/mysql_database_tasks.rb +59 -89
- data/lib/active_record/tasks/postgresql_database_tasks.rb +84 -31
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
- data/lib/active_record/timestamp.rb +70 -38
- data/lib/active_record/touch_later.rb +64 -0
- data/lib/active_record/transactions.rb +208 -123
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +136 -0
- data/lib/active_record/type/date.rb +4 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +13 -5
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +30 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type.rb +79 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +41 -32
- data/lib/active_record/validations.rb +38 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +36 -21
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -6
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -7
- data/lib/rails/generators/active_record/migration.rb +18 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +77 -53
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -149
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,10 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Tasks # :nodoc:
|
3
5
|
class MySQLDatabaseTasks # :nodoc:
|
4
|
-
DEFAULT_CHARSET = ENV['CHARSET'] || 'utf8'
|
5
|
-
DEFAULT_COLLATION = ENV['COLLATION'] || 'utf8_unicode_ci'
|
6
|
-
ACCESS_DENIED_ERROR = 1045
|
7
|
-
|
8
6
|
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
9
7
|
|
10
8
|
def initialize(configuration)
|
@@ -13,38 +11,24 @@ module ActiveRecord
|
|
13
11
|
|
14
12
|
def create
|
15
13
|
establish_connection configuration_without_database
|
16
|
-
connection.create_database configuration[
|
14
|
+
connection.create_database configuration["database"], creation_options
|
17
15
|
establish_connection configuration
|
18
16
|
rescue ActiveRecord::StatementInvalid => error
|
19
|
-
if
|
17
|
+
if error.message.include?("database exists")
|
20
18
|
raise DatabaseAlreadyExists
|
21
19
|
else
|
22
20
|
raise
|
23
21
|
end
|
24
|
-
rescue error_class => error
|
25
|
-
if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
|
26
|
-
$stdout.print error.error
|
27
|
-
establish_connection root_configuration_without_database
|
28
|
-
connection.create_database configuration['database'], creation_options
|
29
|
-
if configuration['username'] != 'root'
|
30
|
-
connection.execute grant_statement.gsub(/\s+/, ' ').strip
|
31
|
-
end
|
32
|
-
establish_connection configuration
|
33
|
-
else
|
34
|
-
$stderr.puts error.inspect
|
35
|
-
$stderr.puts "Couldn't create database for #{configuration.inspect}, #{creation_options.inspect}"
|
36
|
-
$stderr.puts "(If you set the charset manually, make sure you have a matching collation)" if configuration['encoding']
|
37
|
-
end
|
38
22
|
end
|
39
23
|
|
40
24
|
def drop
|
41
25
|
establish_connection configuration
|
42
|
-
connection.drop_database configuration[
|
26
|
+
connection.drop_database configuration["database"]
|
43
27
|
end
|
44
28
|
|
45
29
|
def purge
|
46
30
|
establish_connection configuration
|
47
|
-
connection.recreate_database configuration[
|
31
|
+
connection.recreate_database configuration["database"], creation_options
|
48
32
|
end
|
49
33
|
|
50
34
|
def charset
|
@@ -55,91 +39,77 @@ module ActiveRecord
|
|
55
39
|
connection.collation
|
56
40
|
end
|
57
41
|
|
58
|
-
def structure_dump(filename)
|
59
|
-
args = prepare_command_options
|
42
|
+
def structure_dump(filename, extra_flags)
|
43
|
+
args = prepare_command_options
|
60
44
|
args.concat(["--result-file", "#{filename}"])
|
61
45
|
args.concat(["--no-data"])
|
62
|
-
args.concat(["
|
63
|
-
|
64
|
-
$stderr.puts "Could not dump the database structure. "\
|
65
|
-
"Make sure `mysqldump` is in your PATH and check the command output for warnings."
|
66
|
-
end
|
67
|
-
end
|
46
|
+
args.concat(["--routines"])
|
47
|
+
args.concat(["--skip-comments"])
|
68
48
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
Kernel.system(*args)
|
74
|
-
end
|
49
|
+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
50
|
+
if ignore_tables.any?
|
51
|
+
args += ignore_tables.map { |table| "--ignore-table=#{configuration['database']}.#{table}" }
|
52
|
+
end
|
75
53
|
|
76
|
-
|
54
|
+
args.concat(["#{configuration['database']}"])
|
55
|
+
args.unshift(*extra_flags) if extra_flags
|
77
56
|
|
78
|
-
|
79
|
-
@configuration
|
57
|
+
run_cmd("mysqldump", args, "dumping")
|
80
58
|
end
|
81
59
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
60
|
+
def structure_load(filename, extra_flags)
|
61
|
+
args = prepare_command_options
|
62
|
+
args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
|
63
|
+
args.concat(["--database", "#{configuration['database']}"])
|
64
|
+
args.unshift(*extra_flags) if extra_flags
|
85
65
|
|
86
|
-
|
87
|
-
|
88
|
-
options[:charset] = configuration['encoding'] if configuration.include? 'encoding'
|
89
|
-
options[:collation] = configuration['collation'] if configuration.include? 'collation'
|
66
|
+
run_cmd("mysql", args, "loading")
|
67
|
+
end
|
90
68
|
|
91
|
-
|
92
|
-
options[:charset] ||= DEFAULT_CHARSET unless options[:collation]
|
69
|
+
private
|
93
70
|
|
94
|
-
|
95
|
-
|
71
|
+
def configuration
|
72
|
+
@configuration
|
96
73
|
end
|
97
|
-
end
|
98
74
|
|
99
|
-
|
100
|
-
|
101
|
-
require 'active_record/railties/jdbcmysql_error'
|
102
|
-
ArJdbcMySQL::Error
|
103
|
-
elsif defined?(Mysql2)
|
104
|
-
Mysql2::Error
|
105
|
-
elsif defined?(Mysql)
|
106
|
-
Mysql::Error
|
107
|
-
else
|
108
|
-
StandardError
|
75
|
+
def configuration_without_database
|
76
|
+
configuration.merge("database" => nil)
|
109
77
|
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def grant_statement
|
113
|
-
<<-SQL
|
114
|
-
GRANT ALL PRIVILEGES ON #{configuration['database']}.*
|
115
|
-
TO '#{configuration['username']}'@'localhost'
|
116
|
-
IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
117
|
-
SQL
|
118
|
-
end
|
119
78
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
79
|
+
def creation_options
|
80
|
+
Hash.new.tap do |options|
|
81
|
+
options[:charset] = configuration["encoding"] if configuration.include? "encoding"
|
82
|
+
options[:collation] = configuration["collation"] if configuration.include? "collation"
|
83
|
+
end
|
84
|
+
end
|
126
85
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
86
|
+
def prepare_command_options
|
87
|
+
args = {
|
88
|
+
"host" => "--host",
|
89
|
+
"port" => "--port",
|
90
|
+
"socket" => "--socket",
|
91
|
+
"username" => "--user",
|
92
|
+
"password" => "--password",
|
93
|
+
"encoding" => "--default-character-set",
|
94
|
+
"sslca" => "--ssl-ca",
|
95
|
+
"sslcert" => "--ssl-cert",
|
96
|
+
"sslcapath" => "--ssl-capath",
|
97
|
+
"sslcipher" => "--ssl-cipher",
|
98
|
+
"sslkey" => "--ssl-key"
|
99
|
+
}.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
|
100
|
+
|
101
|
+
args
|
102
|
+
end
|
131
103
|
|
132
|
-
|
133
|
-
|
134
|
-
args.concat(['--user', configuration['username']]) if configuration['username']
|
135
|
-
args << "--password=#{configuration['password']}" if configuration['password']
|
136
|
-
args.concat(['--default-character-set', configuration['encoding']]) if configuration['encoding']
|
137
|
-
configuration.slice('host', 'port', 'socket').each do |k, v|
|
138
|
-
args.concat([ "--#{k}", v.to_s ]) if v
|
104
|
+
def run_cmd(cmd, args, action)
|
105
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
139
106
|
end
|
140
107
|
|
141
|
-
args
|
142
|
-
|
108
|
+
def run_cmd_error(cmd, args, action)
|
109
|
+
msg = "failed to execute: `#{cmd}`\n".dup
|
110
|
+
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"
|
111
|
+
msg
|
112
|
+
end
|
143
113
|
end
|
144
114
|
end
|
145
115
|
end
|
@@ -1,9 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "tempfile"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module Tasks # :nodoc:
|
5
7
|
class PostgreSQLDatabaseTasks # :nodoc:
|
6
|
-
DEFAULT_ENCODING = ENV[
|
8
|
+
DEFAULT_ENCODING = ENV["CHARSET"] || "utf8"
|
9
|
+
ON_ERROR_STOP_1 = "ON_ERROR_STOP=1".freeze
|
10
|
+
SQL_COMMENT_BEGIN = "--".freeze
|
7
11
|
|
8
12
|
delegate :connection, :establish_connection, :clear_active_connections!,
|
9
13
|
to: ActiveRecord::Base
|
@@ -14,11 +18,11 @@ module ActiveRecord
|
|
14
18
|
|
15
19
|
def create(master_established = false)
|
16
20
|
establish_master_connection unless master_established
|
17
|
-
connection.create_database configuration[
|
18
|
-
configuration.merge(
|
21
|
+
connection.create_database configuration["database"],
|
22
|
+
configuration.merge("encoding" => encoding)
|
19
23
|
establish_connection configuration
|
20
24
|
rescue ActiveRecord::StatementInvalid => error
|
21
|
-
if
|
25
|
+
if error.cause.is_a?(PG::DuplicateDatabase)
|
22
26
|
raise DatabaseAlreadyExists
|
23
27
|
else
|
24
28
|
raise
|
@@ -27,7 +31,7 @@ module ActiveRecord
|
|
27
31
|
|
28
32
|
def drop
|
29
33
|
establish_master_connection
|
30
|
-
connection.drop_database configuration[
|
34
|
+
connection.drop_database configuration["database"]
|
31
35
|
end
|
32
36
|
|
33
37
|
def charset
|
@@ -44,47 +48,96 @@ module ActiveRecord
|
|
44
48
|
create true
|
45
49
|
end
|
46
50
|
|
47
|
-
def structure_dump(filename)
|
51
|
+
def structure_dump(filename, extra_flags)
|
48
52
|
set_psql_env
|
49
|
-
|
53
|
+
|
54
|
+
search_path = \
|
55
|
+
case ActiveRecord::Base.dump_schemas
|
56
|
+
when :schema_search_path
|
57
|
+
configuration["schema_search_path"]
|
58
|
+
when :all
|
59
|
+
nil
|
60
|
+
when String
|
61
|
+
ActiveRecord::Base.dump_schemas
|
62
|
+
end
|
63
|
+
|
64
|
+
args = ["-s", "-x", "-O", "-f", filename]
|
65
|
+
args.concat(Array(extra_flags)) if extra_flags
|
50
66
|
unless search_path.blank?
|
51
|
-
|
67
|
+
args += search_path.split(",").map do |part|
|
68
|
+
"--schema=#{part.strip}"
|
69
|
+
end
|
52
70
|
end
|
53
71
|
|
54
|
-
|
55
|
-
|
72
|
+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
73
|
+
if ignore_tables.any?
|
74
|
+
args += ignore_tables.flat_map { |table| ["-T", table] }
|
75
|
+
end
|
56
76
|
|
77
|
+
args << configuration["database"]
|
78
|
+
run_cmd("pg_dump", args, "dumping")
|
79
|
+
remove_sql_header_comments(filename)
|
57
80
|
File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
|
58
81
|
end
|
59
82
|
|
60
|
-
def structure_load(filename)
|
83
|
+
def structure_load(filename, extra_flags)
|
61
84
|
set_psql_env
|
62
|
-
|
85
|
+
args = ["-v", ON_ERROR_STOP_1, "-q", "-f", filename]
|
86
|
+
args.concat(Array(extra_flags)) if extra_flags
|
87
|
+
args << configuration["database"]
|
88
|
+
run_cmd("psql", args, "loading")
|
63
89
|
end
|
64
90
|
|
65
91
|
private
|
66
92
|
|
67
|
-
|
68
|
-
|
69
|
-
|
93
|
+
def configuration
|
94
|
+
@configuration
|
95
|
+
end
|
70
96
|
|
71
|
-
|
72
|
-
|
73
|
-
|
97
|
+
def encoding
|
98
|
+
configuration["encoding"] || DEFAULT_ENCODING
|
99
|
+
end
|
74
100
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
101
|
+
def establish_master_connection
|
102
|
+
establish_connection configuration.merge(
|
103
|
+
"database" => "postgres",
|
104
|
+
"schema_search_path" => "public"
|
105
|
+
)
|
106
|
+
end
|
81
107
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
108
|
+
def set_psql_env
|
109
|
+
ENV["PGHOST"] = configuration["host"] if configuration["host"]
|
110
|
+
ENV["PGPORT"] = configuration["port"].to_s if configuration["port"]
|
111
|
+
ENV["PGPASSWORD"] = configuration["password"].to_s if configuration["password"]
|
112
|
+
ENV["PGUSER"] = configuration["username"].to_s if configuration["username"]
|
113
|
+
end
|
114
|
+
|
115
|
+
def run_cmd(cmd, args, action)
|
116
|
+
fail run_cmd_error(cmd, args, action) unless Kernel.system(cmd, *args)
|
117
|
+
end
|
118
|
+
|
119
|
+
def run_cmd_error(cmd, args, action)
|
120
|
+
msg = "failed to execute:\n".dup
|
121
|
+
msg << "#{cmd} #{args.join(' ')}\n\n"
|
122
|
+
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"
|
123
|
+
msg
|
124
|
+
end
|
125
|
+
|
126
|
+
def remove_sql_header_comments(filename)
|
127
|
+
removing_comments = true
|
128
|
+
tempfile = Tempfile.open("uncommented_structure.sql")
|
129
|
+
begin
|
130
|
+
File.foreach(filename) do |line|
|
131
|
+
unless removing_comments && (line.start_with?(SQL_COMMENT_BEGIN) || line.blank?)
|
132
|
+
tempfile << line
|
133
|
+
removing_comments = false
|
134
|
+
end
|
135
|
+
end
|
136
|
+
ensure
|
137
|
+
tempfile.close
|
138
|
+
end
|
139
|
+
FileUtils.cp(tempfile.path, filename)
|
140
|
+
end
|
88
141
|
end
|
89
142
|
end
|
90
143
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Tasks # :nodoc:
|
3
5
|
class SQLiteDatabaseTasks # :nodoc:
|
@@ -8,22 +10,26 @@ module ActiveRecord
|
|
8
10
|
end
|
9
11
|
|
10
12
|
def create
|
11
|
-
raise DatabaseAlreadyExists if File.exist?(configuration[
|
13
|
+
raise DatabaseAlreadyExists if File.exist?(configuration["database"])
|
12
14
|
|
13
15
|
establish_connection configuration
|
14
16
|
connection
|
15
17
|
end
|
16
18
|
|
17
19
|
def drop
|
18
|
-
require
|
19
|
-
path = Pathname.new configuration[
|
20
|
+
require "pathname"
|
21
|
+
path = Pathname.new configuration["database"]
|
20
22
|
file = path.absolute? ? path.to_s : File.join(root, path)
|
21
23
|
|
22
|
-
FileUtils.rm(file)
|
24
|
+
FileUtils.rm(file)
|
25
|
+
rescue Errno::ENOENT => error
|
26
|
+
raise NoDatabaseError.new(error.message)
|
23
27
|
end
|
24
28
|
|
25
29
|
def purge
|
26
30
|
drop
|
31
|
+
rescue NoDatabaseError
|
32
|
+
ensure
|
27
33
|
create
|
28
34
|
end
|
29
35
|
|
@@ -31,25 +37,47 @@ module ActiveRecord
|
|
31
37
|
connection.encoding
|
32
38
|
end
|
33
39
|
|
34
|
-
def structure_dump(filename)
|
35
|
-
|
36
|
-
|
40
|
+
def structure_dump(filename, extra_flags)
|
41
|
+
args = []
|
42
|
+
args.concat(Array(extra_flags)) if extra_flags
|
43
|
+
args << configuration["database"]
|
44
|
+
|
45
|
+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
|
46
|
+
if ignore_tables.any?
|
47
|
+
condition = ignore_tables.map { |table| connection.quote(table) }.join(", ")
|
48
|
+
args << "SELECT sql FROM sqlite_master WHERE tbl_name NOT IN (#{condition}) ORDER BY tbl_name, type DESC, name"
|
49
|
+
else
|
50
|
+
args << ".schema"
|
51
|
+
end
|
52
|
+
run_cmd("sqlite3", args, filename)
|
37
53
|
end
|
38
54
|
|
39
|
-
def structure_load(filename)
|
40
|
-
dbfile = configuration[
|
41
|
-
|
55
|
+
def structure_load(filename, extra_flags)
|
56
|
+
dbfile = configuration["database"]
|
57
|
+
flags = extra_flags.join(" ") if extra_flags
|
58
|
+
`sqlite3 #{flags} #{dbfile} < "#{filename}"`
|
42
59
|
end
|
43
60
|
|
44
61
|
private
|
45
62
|
|
46
|
-
|
47
|
-
|
48
|
-
|
63
|
+
def configuration
|
64
|
+
@configuration
|
65
|
+
end
|
49
66
|
|
50
|
-
|
51
|
-
|
52
|
-
|
67
|
+
def root
|
68
|
+
@root
|
69
|
+
end
|
70
|
+
|
71
|
+
def run_cmd(cmd, args, out)
|
72
|
+
fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
|
73
|
+
end
|
74
|
+
|
75
|
+
def run_cmd_error(cmd, args)
|
76
|
+
msg = "failed to execute:\n".dup
|
77
|
+
msg << "#{cmd} #{args.join(' ')}\n\n"
|
78
|
+
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"
|
79
|
+
msg
|
80
|
+
end
|
53
81
|
end
|
54
82
|
end
|
55
83
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
|
-
# = Active Record Timestamp
|
4
|
+
# = Active Record \Timestamp
|
3
5
|
#
|
4
6
|
# Active Record automatically timestamps create and update operations if the
|
5
7
|
# table has fields named <tt>created_at/created_on</tt> or
|
@@ -15,14 +17,25 @@ module ActiveRecord
|
|
15
17
|
#
|
16
18
|
# == Time Zone aware attributes
|
17
19
|
#
|
18
|
-
#
|
20
|
+
# Active Record keeps all the <tt>datetime</tt> and <tt>time</tt> columns
|
21
|
+
# timezone aware. By default, these values are stored in the database as UTC
|
22
|
+
# and converted back to the current <tt>Time.zone</tt> when pulled from the database.
|
23
|
+
#
|
24
|
+
# This feature can be turned off completely by setting:
|
25
|
+
#
|
26
|
+
# config.active_record.time_zone_aware_attributes = false
|
27
|
+
#
|
28
|
+
# You can also specify that only <tt>datetime</tt> columns should be time-zone
|
29
|
+
# aware (while <tt>time</tt> should not) by setting:
|
19
30
|
#
|
20
|
-
#
|
31
|
+
# ActiveRecord::Base.time_zone_aware_types = [:datetime]
|
21
32
|
#
|
22
|
-
#
|
33
|
+
# You can also add database specific timezone aware types. For example, for PostgreSQL:
|
23
34
|
#
|
24
|
-
#
|
25
|
-
#
|
35
|
+
# ActiveRecord::Base.time_zone_aware_types += [:tsrange, :tstzrange]
|
36
|
+
#
|
37
|
+
# Finally, you can indicate specific attributes of a model for which time zone
|
38
|
+
# conversion should not applied, for instance by setting:
|
26
39
|
#
|
27
40
|
# class Topic < ActiveRecord::Base
|
28
41
|
# self.skip_time_zone_conversion_for_attributes = [:written_on]
|
@@ -31,8 +44,7 @@ module ActiveRecord
|
|
31
44
|
extend ActiveSupport::Concern
|
32
45
|
|
33
46
|
included do
|
34
|
-
class_attribute :record_timestamps
|
35
|
-
self.record_timestamps = true
|
47
|
+
class_attribute :record_timestamps, default: true
|
36
48
|
end
|
37
49
|
|
38
50
|
def initialize_dup(other) # :nodoc:
|
@@ -40,16 +52,49 @@ module ActiveRecord
|
|
40
52
|
clear_timestamp_attributes
|
41
53
|
end
|
42
54
|
|
55
|
+
module ClassMethods # :nodoc:
|
56
|
+
def touch_attributes_with_time(*names, time: nil)
|
57
|
+
attribute_names = timestamp_attributes_for_update_in_model
|
58
|
+
attribute_names |= names.map(&:to_s)
|
59
|
+
time ||= current_time_from_proper_timezone
|
60
|
+
attribute_names.each_with_object({}) { |attr_name, result| result[attr_name] = time }
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def timestamp_attributes_for_create_in_model
|
65
|
+
timestamp_attributes_for_create.select { |c| column_names.include?(c) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def timestamp_attributes_for_update_in_model
|
69
|
+
timestamp_attributes_for_update.select { |c| column_names.include?(c) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def all_timestamp_attributes_in_model
|
73
|
+
timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model
|
74
|
+
end
|
75
|
+
|
76
|
+
def timestamp_attributes_for_create
|
77
|
+
["created_at", "created_on"]
|
78
|
+
end
|
79
|
+
|
80
|
+
def timestamp_attributes_for_update
|
81
|
+
["updated_at", "updated_on"]
|
82
|
+
end
|
83
|
+
|
84
|
+
def current_time_from_proper_timezone
|
85
|
+
default_timezone == :utc ? Time.now.utc : Time.now
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
43
89
|
private
|
44
90
|
|
45
91
|
def _create_record
|
46
|
-
if
|
92
|
+
if record_timestamps
|
47
93
|
current_time = current_time_from_proper_timezone
|
48
94
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
write_attribute(column, current_time)
|
95
|
+
all_timestamp_attributes_in_model.each do |column|
|
96
|
+
if !attribute_present?(column)
|
97
|
+
_write_attribute(column, current_time)
|
53
98
|
end
|
54
99
|
end
|
55
100
|
end
|
@@ -57,48 +102,39 @@ module ActiveRecord
|
|
57
102
|
super
|
58
103
|
end
|
59
104
|
|
60
|
-
def _update_record(*args)
|
61
|
-
if should_record_timestamps?
|
105
|
+
def _update_record(*args, touch: true, **options)
|
106
|
+
if touch && should_record_timestamps?
|
62
107
|
current_time = current_time_from_proper_timezone
|
63
108
|
|
64
109
|
timestamp_attributes_for_update_in_model.each do |column|
|
65
|
-
|
66
|
-
|
67
|
-
write_attribute(column, current_time)
|
110
|
+
next if will_save_change_to_attribute?(column)
|
111
|
+
_write_attribute(column, current_time)
|
68
112
|
end
|
69
113
|
end
|
70
|
-
super
|
114
|
+
super(*args)
|
71
115
|
end
|
72
116
|
|
73
117
|
def should_record_timestamps?
|
74
|
-
|
118
|
+
record_timestamps && (!partial_writes? || has_changes_to_save?)
|
75
119
|
end
|
76
120
|
|
77
121
|
def timestamp_attributes_for_create_in_model
|
78
|
-
|
122
|
+
self.class.send(:timestamp_attributes_for_create_in_model)
|
79
123
|
end
|
80
124
|
|
81
125
|
def timestamp_attributes_for_update_in_model
|
82
|
-
|
126
|
+
self.class.send(:timestamp_attributes_for_update_in_model)
|
83
127
|
end
|
84
128
|
|
85
129
|
def all_timestamp_attributes_in_model
|
86
|
-
|
87
|
-
end
|
88
|
-
|
89
|
-
def timestamp_attributes_for_update
|
90
|
-
[:updated_at, :updated_on]
|
91
|
-
end
|
92
|
-
|
93
|
-
def timestamp_attributes_for_create
|
94
|
-
[:created_at, :created_on]
|
130
|
+
self.class.send(:all_timestamp_attributes_in_model)
|
95
131
|
end
|
96
132
|
|
97
|
-
def
|
98
|
-
|
133
|
+
def current_time_from_proper_timezone
|
134
|
+
self.class.send(:current_time_from_proper_timezone)
|
99
135
|
end
|
100
136
|
|
101
|
-
def max_updated_column_timestamp(timestamp_names =
|
137
|
+
def max_updated_column_timestamp(timestamp_names = timestamp_attributes_for_update_in_model)
|
102
138
|
timestamp_names
|
103
139
|
.map { |attr| self[attr] }
|
104
140
|
.compact
|
@@ -106,10 +142,6 @@ module ActiveRecord
|
|
106
142
|
.max
|
107
143
|
end
|
108
144
|
|
109
|
-
def current_time_from_proper_timezone
|
110
|
-
self.class.default_timezone == :utc ? Time.now.utc : Time.now
|
111
|
-
end
|
112
|
-
|
113
145
|
# Clear attributes and changed_attributes
|
114
146
|
def clear_timestamp_attributes
|
115
147
|
all_timestamp_attributes_in_model.each do |attribute_name|
|