activerecord 5.0.7.2 → 5.1.0.beta1
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 +389 -2252
- 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.rb +20 -20
- data/lib/active_record/aggregations.rb +244 -244
- data/lib/active_record/association_relation.rb +5 -5
- data/lib/active_record/associations.rb +1579 -1569
- data/lib/active_record/associations/alias_tracker.rb +1 -1
- data/lib/active_record/associations/association.rb +23 -15
- data/lib/active_record/associations/association_scope.rb +83 -81
- data/lib/active_record/associations/belongs_to_association.rb +0 -1
- data/lib/active_record/associations/builder/belongs_to.rb +16 -14
- 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 +74 -241
- data/lib/active_record/associations/collection_proxy.rb +144 -70
- data/lib/active_record/associations/has_many_association.rb +15 -19
- data/lib/active_record/associations/has_many_through_association.rb +12 -5
- data/lib/active_record/associations/has_one_association.rb +22 -28
- data/lib/active_record/associations/has_one_through_association.rb +5 -1
- data/lib/active_record/associations/join_dependency.rb +117 -115
- data/lib/active_record/associations/join_dependency/join_association.rb +16 -13
- 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/preloader.rb +94 -94
- data/lib/active_record/associations/preloader/association.rb +87 -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 +34 -41
- data/lib/active_record/associations/singular_association.rb +8 -25
- data/lib/active_record/associations/through_association.rb +3 -6
- data/lib/active_record/attribute.rb +98 -71
- data/lib/active_record/attribute/user_provided_default.rb +4 -2
- data/lib/active_record/attribute_assignment.rb +61 -61
- data/lib/active_record/attribute_decorators.rb +35 -13
- data/lib/active_record/attribute_methods.rb +56 -65
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
- data/lib/active_record/attribute_methods/dirty.rb +216 -34
- data/lib/active_record/attribute_methods/primary_key.rb +78 -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 +36 -30
- data/lib/active_record/attribute_mutation_tracker.rb +53 -10
- data/lib/active_record/attribute_set.rb +9 -6
- data/lib/active_record/attribute_set/builder.rb +41 -49
- data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
- data/lib/active_record/attributes.rb +21 -21
- data/lib/active_record/autosave_association.rb +13 -13
- data/lib/active_record/base.rb +24 -22
- data/lib/active_record/callbacks.rb +52 -14
- data/lib/active_record/coders/yaml_column.rb +9 -11
- data/lib/active_record/collection_cache_key.rb +6 -17
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +320 -278
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -34
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +31 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +44 -57
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +9 -19
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +78 -79
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +99 -93
- data/lib/active_record/connection_adapters/abstract/transaction.rb +1 -5
- data/lib/active_record/connection_adapters/abstract_adapter.rb +156 -128
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +424 -382
- data/lib/active_record/connection_adapters/column.rb +27 -5
- 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 +45 -43
- 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 +49 -31
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +5 -6
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +24 -26
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +46 -35
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +9 -9
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- 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/enum.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
- 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 +28 -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/quoting.rb +38 -36
- 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 +161 -170
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +179 -152
- 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 -20
- 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_adapter.rb +187 -130
- 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 +110 -93
- data/lib/active_record/counter_cache.rb +62 -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 +58 -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 +3 -3
- 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 +64 -56
- data/lib/active_record/locking/pessimistic.rb +10 -1
- data/lib/active_record/log_subscriber.rb +29 -29
- data/lib/active_record/migration.rb +155 -172
- data/lib/active_record/migration/command_recorder.rb +94 -94
- data/lib/active_record/migration/compatibility.rb +76 -37
- data/lib/active_record/migration/join_table.rb +6 -6
- data/lib/active_record/model_schema.rb +85 -119
- data/lib/active_record/nested_attributes.rb +200 -199
- data/lib/active_record/null_relation.rb +10 -33
- data/lib/active_record/persistence.rb +45 -38
- data/lib/active_record/query_cache.rb +4 -8
- data/lib/active_record/querying.rb +2 -3
- 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 +125 -140
- 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 +79 -96
- data/lib/active_record/relation.rb +72 -115
- data/lib/active_record/relation/batches.rb +87 -58
- data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
- data/lib/active_record/relation/calculations.rb +154 -160
- data/lib/active_record/relation/delegation.rb +30 -29
- data/lib/active_record/relation/finder_methods.rb +195 -226
- data/lib/active_record/relation/merger.rb +58 -62
- data/lib/active_record/relation/predicate_builder.rb +92 -89
- 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/query_attribute.rb +1 -1
- data/lib/active_record/relation/query_methods.rb +247 -295
- 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 +79 -65
- data/lib/active_record/relation/where_clause_factory.rb +47 -8
- data/lib/active_record/result.rb +29 -31
- data/lib/active_record/runtime_registry.rb +3 -3
- data/lib/active_record/sanitization.rb +182 -197
- data/lib/active_record/schema.rb +3 -3
- data/lib/active_record/schema_dumper.rb +14 -37
- data/lib/active_record/schema_migration.rb +3 -3
- data/lib/active_record/scoping.rb +9 -10
- data/lib/active_record/scoping/default.rb +87 -91
- data/lib/active_record/scoping/named.rb +16 -28
- 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 +72 -65
- data/lib/active_record/tasks/mysql_database_tasks.rb +75 -72
- data/lib/active_record/tasks/postgresql_database_tasks.rb +53 -48
- data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +1 -2
- data/lib/active_record/transactions.rb +98 -110
- data/lib/active_record/type.rb +17 -13
- data/lib/active_record/type/adapter_specific_registry.rb +46 -42
- data/lib/active_record/type/decimal_without_scale.rb +9 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
- data/lib/active_record/type/serialized.rb +8 -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_caster.rb +2 -2
- data/lib/active_record/type_caster/connection.rb +8 -6
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +4 -4
- 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/version.rb +1 -1
- data/lib/rails/generators/active_record.rb +4 -4
- data/lib/rails/generators/active_record/migration.rb +2 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
- metadata +22 -13
- data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -13,7 +13,7 @@ module ActiveRecord
|
|
13
13
|
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
14
14
|
# +sql_type_metadata+ is various information about the type of the column
|
15
15
|
# +null+ determines if this column allows +NULL+ values.
|
16
|
-
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil
|
16
|
+
def initialize(name, default, sql_type_metadata = nil, null = true, table_name = nil, default_function = nil, collation = nil, comment: nil)
|
17
17
|
@name = name.freeze
|
18
18
|
@table_name = table_name
|
19
19
|
@sql_type_metadata = sql_type_metadata
|
@@ -29,7 +29,7 @@ module ActiveRecord
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def bigint?
|
32
|
-
/\Abigint\b
|
32
|
+
/\Abigint\b/.match?(sql_type)
|
33
33
|
end
|
34
34
|
|
35
35
|
# Returns the human name of the column name.
|
@@ -40,6 +40,28 @@ module ActiveRecord
|
|
40
40
|
Base.human_attribute_name(@name)
|
41
41
|
end
|
42
42
|
|
43
|
+
def init_with(coder)
|
44
|
+
@name = coder["name"]
|
45
|
+
@table_name = coder["table_name"]
|
46
|
+
@sql_type_metadata = coder["sql_type_metadata"]
|
47
|
+
@null = coder["null"]
|
48
|
+
@default = coder["default"]
|
49
|
+
@default_function = coder["default_function"]
|
50
|
+
@collation = coder["collation"]
|
51
|
+
@comment = coder["comment"]
|
52
|
+
end
|
53
|
+
|
54
|
+
def encode_with(coder)
|
55
|
+
coder["name"] = @name
|
56
|
+
coder["table_name"] = @table_name
|
57
|
+
coder["sql_type_metadata"] = @sql_type_metadata
|
58
|
+
coder["null"] = @null
|
59
|
+
coder["default"] = @default
|
60
|
+
coder["default_function"] = @default_function
|
61
|
+
coder["collation"] = @collation
|
62
|
+
coder["comment"] = @comment
|
63
|
+
end
|
64
|
+
|
43
65
|
def ==(other)
|
44
66
|
other.is_a?(Column) &&
|
45
67
|
attributes_for_hash == other.attributes_for_hash
|
@@ -52,9 +74,9 @@ module ActiveRecord
|
|
52
74
|
|
53
75
|
protected
|
54
76
|
|
55
|
-
|
56
|
-
|
57
|
-
|
77
|
+
def attributes_for_hash
|
78
|
+
[self.class, name, default, sql_type_metadata, null, table_name, default_function, collation]
|
79
|
+
end
|
58
80
|
end
|
59
81
|
|
60
82
|
class NullColumn < Column
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "uri"
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module ConnectionAdapters
|
@@ -13,9 +13,12 @@ module ActiveRecord
|
|
13
13
|
@config = original.config.dup
|
14
14
|
end
|
15
15
|
|
16
|
+
def to_hash
|
17
|
+
@config.merge(name: @name)
|
18
|
+
end
|
19
|
+
|
16
20
|
# Expands a connection string into a hash.
|
17
21
|
class ConnectionUrlResolver # :nodoc:
|
18
|
-
|
19
22
|
# == Example
|
20
23
|
#
|
21
24
|
# url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
|
@@ -33,11 +36,11 @@ module ActiveRecord
|
|
33
36
|
def initialize(url)
|
34
37
|
raise "Database URL cannot be empty" if url.blank?
|
35
38
|
@uri = uri_parser.parse(url)
|
36
|
-
@adapter = @uri.scheme && @uri.scheme.tr(
|
39
|
+
@adapter = @uri.scheme && @uri.scheme.tr("-", "_")
|
37
40
|
@adapter = "postgresql" if @adapter == "postgres"
|
38
41
|
|
39
42
|
if @uri.opaque
|
40
|
-
@uri.opaque, @query = @uri.opaque.split(
|
43
|
+
@uri.opaque, @query = @uri.opaque.split("?", 2)
|
41
44
|
else
|
42
45
|
@query = @uri.query
|
43
46
|
end
|
@@ -45,65 +48,65 @@ module ActiveRecord
|
|
45
48
|
|
46
49
|
# Converts the given URL to a full connection hash.
|
47
50
|
def to_hash
|
48
|
-
config = raw_config.reject { |_,value| value.blank? }
|
49
|
-
config.map { |key,value| config[key] = uri_parser.unescape(value) if value.is_a? String }
|
51
|
+
config = raw_config.reject { |_, value| value.blank? }
|
52
|
+
config.map { |key, value| config[key] = uri_parser.unescape(value) if value.is_a? String }
|
50
53
|
config
|
51
54
|
end
|
52
55
|
|
53
56
|
private
|
54
57
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
+
def uri
|
59
|
+
@uri
|
60
|
+
end
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
+
def uri_parser
|
63
|
+
@uri_parser ||= URI::Parser.new
|
64
|
+
end
|
62
65
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
66
|
+
# Converts the query parameters of the URI into a hash.
|
67
|
+
#
|
68
|
+
# "localhost?pool=5&reaping_frequency=2"
|
69
|
+
# # => { "pool" => "5", "reaping_frequency" => "2" }
|
70
|
+
#
|
71
|
+
# returns empty hash if no query present.
|
72
|
+
#
|
73
|
+
# "localhost"
|
74
|
+
# # => {}
|
75
|
+
def query_hash
|
76
|
+
Hash[(@query || "").split("&").map { |pair| pair.split("=") }]
|
77
|
+
end
|
75
78
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
79
|
+
def raw_config
|
80
|
+
if uri.opaque
|
81
|
+
query_hash.merge(
|
82
|
+
"adapter" => @adapter,
|
83
|
+
"database" => uri.opaque)
|
84
|
+
else
|
85
|
+
query_hash.merge(
|
86
|
+
"adapter" => @adapter,
|
87
|
+
"username" => uri.user,
|
88
|
+
"password" => uri.password,
|
89
|
+
"port" => uri.port,
|
90
|
+
"database" => database_from_path,
|
91
|
+
"host" => uri.hostname)
|
92
|
+
end
|
89
93
|
end
|
90
|
-
end
|
91
94
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
95
|
+
# Returns name of the database.
|
96
|
+
def database_from_path
|
97
|
+
if @adapter == "sqlite3"
|
98
|
+
# 'sqlite3:/foo' is absolute, because that makes sense. The
|
99
|
+
# corresponding relative version, 'sqlite3:foo', is handled
|
100
|
+
# elsewhere, as an "opaque".
|
98
101
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
102
|
+
uri.path
|
103
|
+
else
|
104
|
+
# Only SQLite uses a filename as the "database" name; for
|
105
|
+
# anything else, a leading slash would be silly.
|
103
106
|
|
104
|
-
|
107
|
+
uri.path.sub(%r{^/}, "")
|
108
|
+
end
|
105
109
|
end
|
106
|
-
end
|
107
110
|
end
|
108
111
|
|
109
112
|
##
|
@@ -146,9 +149,18 @@ module ActiveRecord
|
|
146
149
|
# Expands each key in @configurations hash into fully resolved hash
|
147
150
|
def resolve_all
|
148
151
|
config = configurations.dup
|
152
|
+
|
153
|
+
if env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
154
|
+
env_config = config[env] if config[env].is_a?(Hash) && !(config[env].key?("adapter") || config[env].key?("url"))
|
155
|
+
end
|
156
|
+
|
157
|
+
config.reject! { |k, v| v.is_a?(Hash) && !(v.key?("adapter") || v.key?("url")) }
|
158
|
+
config.merge! env_config if env_config
|
159
|
+
|
149
160
|
config.each do |key, value|
|
150
161
|
config[key] = resolve(value) if value
|
151
162
|
end
|
163
|
+
|
152
164
|
config
|
153
165
|
end
|
154
166
|
|
@@ -164,7 +176,7 @@ module ActiveRecord
|
|
164
176
|
# spec.config
|
165
177
|
# # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" }
|
166
178
|
#
|
167
|
-
def spec(config
|
179
|
+
def spec(config)
|
168
180
|
spec = resolve(config).symbolize_keys
|
169
181
|
|
170
182
|
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
|
@@ -180,83 +192,81 @@ module ActiveRecord
|
|
180
192
|
|
181
193
|
adapter_method = "#{spec[:adapter]}_connection"
|
182
194
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
end
|
189
|
-
ConnectionSpecification.new(name, spec, adapter_method)
|
195
|
+
unless ActiveRecord::Base.respond_to?(adapter_method)
|
196
|
+
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
|
197
|
+
end
|
198
|
+
|
199
|
+
ConnectionSpecification.new(spec.delete(:name) || "primary", spec, adapter_method)
|
190
200
|
end
|
191
201
|
|
192
202
|
private
|
193
203
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
204
|
+
# Returns fully resolved connection, accepts hash, string or symbol.
|
205
|
+
# Always returns a hash.
|
206
|
+
#
|
207
|
+
# == Examples
|
208
|
+
#
|
209
|
+
# Symbol representing current environment.
|
210
|
+
#
|
211
|
+
# Resolver.new("production" => {}).resolve_connection(:production)
|
212
|
+
# # => {}
|
213
|
+
#
|
214
|
+
# One layer deep hash of connection values.
|
215
|
+
#
|
216
|
+
# Resolver.new({}).resolve_connection("adapter" => "sqlite3")
|
217
|
+
# # => { "adapter" => "sqlite3" }
|
218
|
+
#
|
219
|
+
# Connection URL.
|
220
|
+
#
|
221
|
+
# Resolver.new({}).resolve_connection("postgresql://localhost/foo")
|
222
|
+
# # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
|
223
|
+
#
|
224
|
+
def resolve_connection(spec)
|
225
|
+
case spec
|
226
|
+
when Symbol
|
227
|
+
resolve_symbol_connection spec
|
228
|
+
when String
|
229
|
+
resolve_url_connection spec
|
230
|
+
when Hash
|
231
|
+
resolve_hash_connection spec
|
232
|
+
end
|
222
233
|
end
|
223
|
-
end
|
224
234
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
235
|
+
# Takes the environment such as +:production+ or +:development+.
|
236
|
+
# This requires that the @configurations was initialized with a key that
|
237
|
+
# matches.
|
238
|
+
#
|
239
|
+
# Resolver.new("production" => {}).resolve_symbol_connection(:production)
|
240
|
+
# # => {}
|
241
|
+
#
|
242
|
+
def resolve_symbol_connection(spec)
|
243
|
+
if config = configurations[spec.to_s]
|
244
|
+
resolve_connection(config).merge("name" => spec.to_s)
|
245
|
+
else
|
246
|
+
raise(AdapterNotSpecified, "'#{spec}' database is not configured. Available: #{configurations.keys.inspect}")
|
247
|
+
end
|
237
248
|
end
|
238
|
-
end
|
239
249
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
250
|
+
# Accepts a hash. Expands the "url" key that contains a
|
251
|
+
# URL database connection to a full connection
|
252
|
+
# hash and merges with the rest of the hash.
|
253
|
+
# Connection details inside of the "url" key win any merge conflicts
|
254
|
+
def resolve_hash_connection(spec)
|
255
|
+
if spec["url"] && spec["url"] !~ /^jdbc:/
|
256
|
+
connection_hash = resolve_url_connection(spec.delete("url"))
|
257
|
+
spec.merge!(connection_hash)
|
258
|
+
end
|
259
|
+
spec
|
248
260
|
end
|
249
|
-
spec
|
250
|
-
end
|
251
261
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
262
|
+
# Takes a connection URL.
|
263
|
+
#
|
264
|
+
# Resolver.new({}).resolve_url_connection("postgresql://localhost/foo")
|
265
|
+
# # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
|
266
|
+
#
|
267
|
+
def resolve_url_connection(url)
|
268
|
+
ConnectionUrlResolver.new(url).to_hash
|
269
|
+
end
|
260
270
|
end
|
261
271
|
end
|
262
272
|
end
|
@@ -2,47 +2,22 @@ module ActiveRecord
|
|
2
2
|
module ConnectionAdapters
|
3
3
|
module MySQL
|
4
4
|
class Column < ConnectionAdapters::Column # :nodoc:
|
5
|
-
delegate :
|
6
|
-
|
7
|
-
def initialize(*)
|
8
|
-
super
|
9
|
-
assert_valid_default
|
10
|
-
extract_default
|
11
|
-
end
|
12
|
-
|
13
|
-
def has_default?
|
14
|
-
return false if blob_or_text_column? # MySQL forbids defaults on blob and text columns
|
15
|
-
super
|
16
|
-
end
|
17
|
-
|
18
|
-
def blob_or_text_column?
|
19
|
-
/\A(?:tiny|medium|long)?blob\b/ === sql_type || type == :text
|
20
|
-
end
|
5
|
+
delegate :extra, to: :sql_type_metadata, allow_nil: true
|
21
6
|
|
22
7
|
def unsigned?
|
23
|
-
/\
|
8
|
+
/\bunsigned(?: zerofill)?\z/.match?(sql_type)
|
24
9
|
end
|
25
10
|
|
26
11
|
def case_sensitive?
|
27
|
-
collation &&
|
12
|
+
collation && !/_ci\z/.match?(collation)
|
28
13
|
end
|
29
14
|
|
30
15
|
def auto_increment?
|
31
|
-
extra ==
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def extract_default
|
37
|
-
if blob_or_text_column?
|
38
|
-
@default = null || strict ? nil : ''
|
39
|
-
end
|
16
|
+
extra == "auto_increment"
|
40
17
|
end
|
41
18
|
|
42
|
-
def
|
43
|
-
|
44
|
-
raise ArgumentError, "#{type} columns cannot have a default value: #{default.inspect}"
|
45
|
-
end
|
19
|
+
def virtual?
|
20
|
+
/\b(?:VIRTUAL|STORED|PERSISTENT)\b/.match?(extra)
|
46
21
|
end
|
47
22
|
end
|
48
23
|
end
|
@@ -3,7 +3,7 @@ module ActiveRecord
|
|
3
3
|
module MySQL
|
4
4
|
module DatabaseStatements
|
5
5
|
# Returns an ActiveRecord::Result instance.
|
6
|
-
def select_all(arel, name = nil, binds = [], preparable: nil)
|
6
|
+
def select_all(arel, name = nil, binds = [], preparable: nil) # :nodoc:
|
7
7
|
result = if ExplainRegistry.collect? && prepared_statements
|
8
8
|
unprepared_statement { super }
|
9
9
|
else
|
@@ -15,8 +15,8 @@ module ActiveRecord
|
|
15
15
|
|
16
16
|
# Returns an array of arrays containing the field values.
|
17
17
|
# Order is the same as that returned by +columns+.
|
18
|
-
def select_rows(
|
19
|
-
select_result(
|
18
|
+
def select_rows(arel, name = nil, binds = []) # :nodoc:
|
19
|
+
select_result(arel, name, binds) do |result|
|
20
20
|
@connection.next_result while @connection.more_results?
|
21
21
|
result.to_a
|
22
22
|
end
|
@@ -31,7 +31,7 @@ module ActiveRecord
|
|
31
31
|
super
|
32
32
|
end
|
33
33
|
|
34
|
-
def exec_query(sql, name =
|
34
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
35
35
|
if without_prepared_statement?(binds)
|
36
36
|
execute_and_free(sql, name) do |result|
|
37
37
|
ActiveRecord::Result.new(result.fields, result.to_a) if result
|
@@ -43,7 +43,7 @@ module ActiveRecord
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
def exec_delete(sql, name, binds)
|
46
|
+
def exec_delete(sql, name = nil, binds = [])
|
47
47
|
if without_prepared_statement?(binds)
|
48
48
|
execute_and_free(sql, name) { @connection.affected_rows }
|
49
49
|
else
|
@@ -52,56 +52,58 @@ module ActiveRecord
|
|
52
52
|
end
|
53
53
|
alias :exec_update :exec_delete
|
54
54
|
|
55
|
-
protected
|
56
|
-
|
57
|
-
def last_inserted_id(result)
|
58
|
-
@connection.last_id
|
59
|
-
end
|
60
|
-
|
61
55
|
private
|
62
56
|
|
63
|
-
|
64
|
-
|
65
|
-
execute_and_free(sql, name) { |result| yield result }
|
66
|
-
else
|
67
|
-
exec_stmt_and_free(sql, name, binds, cache_stmt: true) { |_, result| yield result }
|
57
|
+
def last_inserted_id(result)
|
58
|
+
@connection.last_id
|
68
59
|
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
72
|
-
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
73
|
-
# made since we established the connection
|
74
|
-
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
75
60
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
if
|
80
|
-
|
81
|
-
stmt: @connection.prepare(sql)
|
82
|
-
}
|
83
|
-
stmt = cache[:stmt]
|
61
|
+
def select_result(arel, name, binds)
|
62
|
+
arel, binds = binds_from_relation(arel, binds)
|
63
|
+
sql = to_sql(arel, binds)
|
64
|
+
if without_prepared_statement?(binds)
|
65
|
+
execute_and_free(sql, name) { |result| yield result }
|
84
66
|
else
|
85
|
-
|
67
|
+
exec_stmt_and_free(sql, name, binds, cache_stmt: true) { |_, result| yield result }
|
86
68
|
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
72
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
73
|
+
# made since we established the connection
|
74
|
+
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
87
75
|
|
88
|
-
|
89
|
-
|
90
|
-
|
76
|
+
type_casted_binds = type_casted_binds(binds)
|
77
|
+
|
78
|
+
log(sql, name, binds, type_casted_binds) do
|
91
79
|
if cache_stmt
|
92
|
-
@statements
|
80
|
+
cache = @statements[sql] ||= {
|
81
|
+
stmt: @connection.prepare(sql)
|
82
|
+
}
|
83
|
+
stmt = cache[:stmt]
|
93
84
|
else
|
94
|
-
stmt.
|
85
|
+
stmt = @connection.prepare(sql)
|
95
86
|
end
|
96
|
-
raise e
|
97
|
-
end
|
98
87
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
88
|
+
begin
|
89
|
+
result = ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
90
|
+
stmt.execute(*type_casted_binds)
|
91
|
+
end
|
92
|
+
rescue Mysql2::Error => e
|
93
|
+
if cache_stmt
|
94
|
+
@statements.delete(sql)
|
95
|
+
else
|
96
|
+
stmt.close
|
97
|
+
end
|
98
|
+
raise e
|
99
|
+
end
|
100
|
+
|
101
|
+
ret = yield stmt, result
|
102
|
+
result.free if result
|
103
|
+
stmt.close unless cache_stmt
|
104
|
+
ret
|
105
|
+
end
|
103
106
|
end
|
104
|
-
end
|
105
107
|
end
|
106
108
|
end
|
107
109
|
end
|