activerecord 5.2.4.2 → 6.0.2.2
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 +4 -4
- data/CHANGELOG.md +715 -566
- data/MIT-LICENSE +3 -1
- data/README.rdoc +4 -2
- data/examples/performance.rb +1 -1
- data/lib/active_record.rb +9 -2
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/association_relation.rb +15 -6
- data/lib/active_record/associations.rb +20 -15
- data/lib/active_record/associations/association.rb +61 -20
- data/lib/active_record/associations/association_scope.rb +4 -6
- data/lib/active_record/associations/belongs_to_association.rb +36 -42
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
- data/lib/active_record/associations/builder/association.rb +14 -18
- data/lib/active_record/associations/builder/belongs_to.rb +19 -52
- data/lib/active_record/associations/builder/collection_association.rb +3 -13
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +35 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +12 -23
- data/lib/active_record/associations/collection_proxy.rb +12 -15
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +2 -10
- data/lib/active_record/associations/has_many_through_association.rb +14 -14
- data/lib/active_record/associations/has_one_association.rb +28 -30
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +28 -28
- data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/preloader.rb +39 -31
- data/lib/active_record/associations/preloader/association.rb +38 -36
- data/lib/active_record/associations/preloader/through_association.rb +48 -39
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods.rb +28 -100
- data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
- data/lib/active_record/attribute_methods/dirty.rb +111 -40
- data/lib/active_record/attribute_methods/primary_key.rb +15 -22
- data/lib/active_record/attribute_methods/query.rb +2 -3
- data/lib/active_record/attribute_methods/read.rb +15 -53
- data/lib/active_record/attribute_methods/serialization.rb +1 -1
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
- data/lib/active_record/attribute_methods/write.rb +17 -24
- data/lib/active_record/attributes.rb +13 -0
- data/lib/active_record/autosave_association.rb +2 -2
- data/lib/active_record/base.rb +2 -3
- data/lib/active_record/callbacks.rb +5 -19
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +104 -16
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +99 -123
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -8
- data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +19 -12
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +76 -48
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +132 -53
- data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -56
- data/lib/active_record/connection_adapters/abstract_adapter.rb +187 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +138 -195
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +53 -43
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +75 -13
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +129 -13
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +55 -53
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +164 -74
- data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +120 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -6
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +42 -11
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +129 -141
- data/lib/active_record/connection_handling.rb +155 -26
- data/lib/active_record/core.rb +103 -59
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/enum.rb +37 -7
- data/lib/active_record/errors.rb +15 -7
- data/lib/active_record/explain.rb +1 -1
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +145 -472
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +13 -3
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +68 -16
- data/lib/active_record/internal_metadata.rb +10 -2
- data/lib/active_record/locking/optimistic.rb +5 -6
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +88 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +100 -81
- data/lib/active_record/migration/command_recorder.rb +50 -6
- data/lib/active_record/migration/compatibility.rb +76 -49
- data/lib/active_record/model_schema.rb +33 -9
- data/lib/active_record/nested_attributes.rb +2 -2
- data/lib/active_record/no_touching.rb +7 -0
- data/lib/active_record/persistence.rb +228 -24
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +32 -20
- data/lib/active_record/railtie.rb +80 -43
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +199 -46
- data/lib/active_record/reflection.rb +32 -30
- data/lib/active_record/relation.rb +311 -80
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +53 -47
- data/lib/active_record/relation/delegation.rb +26 -43
- data/lib/active_record/relation/finder_methods.rb +23 -27
- data/lib/active_record/relation/merger.rb +11 -20
- data/lib/active_record/relation/predicate_builder.rb +4 -6
- data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +213 -64
- data/lib/active_record/relation/spawn_methods.rb +1 -1
- data/lib/active_record/relation/where_clause.rb +14 -10
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +32 -40
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +22 -7
- data/lib/active_record/schema_migration.rb +5 -1
- data/lib/active_record/scoping.rb +8 -8
- data/lib/active_record/scoping/default.rb +4 -5
- data/lib/active_record/scoping/named.rb +20 -15
- data/lib/active_record/statement_cache.rb +30 -3
- data/lib/active_record/store.rb +87 -8
- data/lib/active_record/table_metadata.rb +10 -17
- data/lib/active_record/tasks/database_tasks.rb +194 -25
- data/lib/active_record/tasks/mysql_database_tasks.rb +5 -5
- data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
- data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +225 -0
- data/lib/active_record/timestamp.rb +39 -25
- data/lib/active_record/touch_later.rb +4 -2
- data/lib/active_record/transactions.rb +56 -65
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type_caster/connection.rb +15 -14
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations.rb +1 -0
- data/lib/active_record/validations/uniqueness.rb +15 -27
- data/lib/arel.rb +58 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +109 -24
- data/lib/active_record/collection_cache_key.rb +0 -53
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
module ConnectionAdapters
|
6
6
|
# An abstract definition of a column in a table.
|
7
7
|
class Column
|
8
|
-
attr_reader :name, :default, :sql_type_metadata, :null, :
|
8
|
+
attr_reader :name, :default, :sql_type_metadata, :null, :default_function, :collation, :comment
|
9
9
|
|
10
10
|
delegate :precision, :scale, :limit, :type, :sql_type, to: :sql_type_metadata, allow_nil: true
|
11
11
|
|
@@ -15,9 +15,8 @@ module ActiveRecord
|
|
15
15
|
# +default+ is the type-casted default value, such as +new+ in <tt>sales_stage varchar(20) default 'new'</tt>.
|
16
16
|
# +sql_type_metadata+ is various information about the type of the column
|
17
17
|
# +null+ determines if this column allows +NULL+ values.
|
18
|
-
def initialize(name, default, sql_type_metadata = nil, null = true,
|
18
|
+
def initialize(name, default, sql_type_metadata = nil, null = true, default_function = nil, collation: nil, comment: nil, **)
|
19
19
|
@name = name.freeze
|
20
|
-
@table_name = table_name
|
21
20
|
@sql_type_metadata = sql_type_metadata
|
22
21
|
@null = null
|
23
22
|
@default = default
|
@@ -44,7 +43,6 @@ module ActiveRecord
|
|
44
43
|
|
45
44
|
def init_with(coder)
|
46
45
|
@name = coder["name"]
|
47
|
-
@table_name = coder["table_name"]
|
48
46
|
@sql_type_metadata = coder["sql_type_metadata"]
|
49
47
|
@null = coder["null"]
|
50
48
|
@default = coder["default"]
|
@@ -55,7 +53,6 @@ module ActiveRecord
|
|
55
53
|
|
56
54
|
def encode_with(coder)
|
57
55
|
coder["name"] = @name
|
58
|
-
coder["table_name"] = @table_name
|
59
56
|
coder["sql_type_metadata"] = @sql_type_metadata
|
60
57
|
coder["null"] = @null
|
61
58
|
coder["default"] = @default
|
@@ -66,19 +63,26 @@ module ActiveRecord
|
|
66
63
|
|
67
64
|
def ==(other)
|
68
65
|
other.is_a?(Column) &&
|
69
|
-
|
66
|
+
name == other.name &&
|
67
|
+
default == other.default &&
|
68
|
+
sql_type_metadata == other.sql_type_metadata &&
|
69
|
+
null == other.null &&
|
70
|
+
default_function == other.default_function &&
|
71
|
+
collation == other.collation &&
|
72
|
+
comment == other.comment
|
70
73
|
end
|
71
74
|
alias :eql? :==
|
72
75
|
|
73
76
|
def hash
|
74
|
-
|
77
|
+
Column.hash ^
|
78
|
+
name.hash ^
|
79
|
+
default.hash ^
|
80
|
+
sql_type_metadata.hash ^
|
81
|
+
null.hash ^
|
82
|
+
default_function.hash ^
|
83
|
+
collation.hash ^
|
84
|
+
comment.hash
|
75
85
|
end
|
76
|
-
|
77
|
-
protected
|
78
|
-
|
79
|
-
def attributes_for_hash
|
80
|
-
[self.class, name, default, sql_type_metadata, null, table_name, default_function, collation]
|
81
|
-
end
|
82
86
|
end
|
83
87
|
|
84
88
|
class NullColumn < Column
|
@@ -57,9 +57,7 @@ module ActiveRecord
|
|
57
57
|
|
58
58
|
private
|
59
59
|
|
60
|
-
|
61
|
-
@uri
|
62
|
-
end
|
60
|
+
attr_reader :uri
|
63
61
|
|
64
62
|
def uri_parser
|
65
63
|
@uri_parser ||= URI::Parser.new
|
@@ -116,8 +114,7 @@ module ActiveRecord
|
|
116
114
|
class Resolver # :nodoc:
|
117
115
|
attr_reader :configurations
|
118
116
|
|
119
|
-
# Accepts a
|
120
|
-
# environments such as "production". Keys must be strings.
|
117
|
+
# Accepts a list of db config objects.
|
121
118
|
def initialize(configurations)
|
122
119
|
@configurations = configurations
|
123
120
|
end
|
@@ -138,34 +135,14 @@ module ActiveRecord
|
|
138
135
|
# Resolver.new(configurations).resolve(:production)
|
139
136
|
# # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
|
140
137
|
#
|
141
|
-
def resolve(
|
142
|
-
if
|
143
|
-
resolve_connection
|
144
|
-
elsif env = ActiveRecord::ConnectionHandling::RAILS_ENV.call
|
145
|
-
resolve_symbol_connection env.to_sym
|
138
|
+
def resolve(config_or_env, pool_name = nil)
|
139
|
+
if config_or_env
|
140
|
+
resolve_connection config_or_env, pool_name
|
146
141
|
else
|
147
142
|
raise AdapterNotSpecified
|
148
143
|
end
|
149
144
|
end
|
150
145
|
|
151
|
-
# Expands each key in @configurations hash into fully resolved hash
|
152
|
-
def resolve_all
|
153
|
-
config = configurations.dup
|
154
|
-
|
155
|
-
if env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
156
|
-
env_config = config[env] if config[env].is_a?(Hash) && !(config[env].key?("adapter") || config[env].key?("url"))
|
157
|
-
end
|
158
|
-
|
159
|
-
config.reject! { |k, v| v.is_a?(Hash) && !(v.key?("adapter") || v.key?("url")) }
|
160
|
-
config.merge! env_config if env_config
|
161
|
-
|
162
|
-
config.each do |key, value|
|
163
|
-
config[key] = resolve(value) if value
|
164
|
-
end
|
165
|
-
|
166
|
-
config
|
167
|
-
end
|
168
|
-
|
169
146
|
# Returns an instance of ConnectionSpecification for a given adapter.
|
170
147
|
# Accepts a hash one layer deep that contains all connection information.
|
171
148
|
#
|
@@ -179,7 +156,9 @@ module ActiveRecord
|
|
179
156
|
# # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" }
|
180
157
|
#
|
181
158
|
def spec(config)
|
182
|
-
|
159
|
+
pool_name = config if config.is_a?(Symbol)
|
160
|
+
|
161
|
+
spec = resolve(config, pool_name).symbolize_keys
|
183
162
|
|
184
163
|
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
|
185
164
|
|
@@ -207,14 +186,13 @@ module ActiveRecord
|
|
207
186
|
adapter_method = "#{spec[:adapter]}_connection"
|
208
187
|
|
209
188
|
unless ActiveRecord::Base.respond_to?(adapter_method)
|
210
|
-
raise AdapterNotFound, "database configuration specifies nonexistent #{spec
|
189
|
+
raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter"
|
211
190
|
end
|
212
191
|
|
213
192
|
ConnectionSpecification.new(spec.delete(:name) || "primary", spec, adapter_method)
|
214
193
|
end
|
215
194
|
|
216
195
|
private
|
217
|
-
|
218
196
|
# Returns fully resolved connection, accepts hash, string or symbol.
|
219
197
|
# Always returns a hash.
|
220
198
|
#
|
@@ -235,32 +213,64 @@ module ActiveRecord
|
|
235
213
|
# Resolver.new({}).resolve_connection("postgresql://localhost/foo")
|
236
214
|
# # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" }
|
237
215
|
#
|
238
|
-
def resolve_connection(
|
239
|
-
case
|
216
|
+
def resolve_connection(config_or_env, pool_name = nil)
|
217
|
+
case config_or_env
|
240
218
|
when Symbol
|
241
|
-
resolve_symbol_connection
|
219
|
+
resolve_symbol_connection config_or_env, pool_name
|
242
220
|
when String
|
243
|
-
resolve_url_connection
|
221
|
+
resolve_url_connection config_or_env
|
244
222
|
when Hash
|
245
|
-
resolve_hash_connection
|
223
|
+
resolve_hash_connection config_or_env
|
224
|
+
else
|
225
|
+
raise TypeError, "Invalid type for configuration. Expected Symbol, String, or Hash. Got #{config_or_env.inspect}"
|
246
226
|
end
|
247
227
|
end
|
248
228
|
|
249
|
-
# Takes the environment such as +:production+ or +:development
|
229
|
+
# Takes the environment such as +:production+ or +:development+ and a
|
230
|
+
# pool name the corresponds to the name given by the connection pool
|
231
|
+
# to the connection. That pool name is merged into the hash with the
|
232
|
+
# name key.
|
233
|
+
#
|
250
234
|
# This requires that the @configurations was initialized with a key that
|
251
235
|
# matches.
|
252
236
|
#
|
253
|
-
#
|
254
|
-
#
|
237
|
+
# configurations = #<ActiveRecord::DatabaseConfigurations:0x00007fd9fdace3e0
|
238
|
+
# @configurations=[
|
239
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd9fdace250
|
240
|
+
# @env_name="production", @spec_name="primary", @config={"database"=>"my_db"}>
|
241
|
+
# ]>
|
255
242
|
#
|
256
|
-
|
257
|
-
|
258
|
-
|
243
|
+
# Resolver.new(configurations).resolve_symbol_connection(:production, "primary")
|
244
|
+
# # => { "database" => "my_db" }
|
245
|
+
def resolve_symbol_connection(env_name, pool_name)
|
246
|
+
db_config = configurations.find_db_config(env_name)
|
247
|
+
|
248
|
+
if db_config
|
249
|
+
resolve_connection(db_config.config).merge("name" => pool_name.to_s)
|
259
250
|
else
|
260
|
-
raise
|
251
|
+
raise AdapterNotSpecified, <<~MSG
|
252
|
+
The `#{env_name}` database is not configured for the `#{ActiveRecord::ConnectionHandling::DEFAULT_ENV.call}` environment.
|
253
|
+
|
254
|
+
Available databases configurations are:
|
255
|
+
|
256
|
+
#{build_configuration_sentence}
|
257
|
+
MSG
|
261
258
|
end
|
262
259
|
end
|
263
260
|
|
261
|
+
def build_configuration_sentence # :nodoc:
|
262
|
+
configs = configurations.configs_for(include_replicas: true)
|
263
|
+
|
264
|
+
configs.group_by(&:env_name).map do |env, config|
|
265
|
+
namespaces = config.map(&:spec_name)
|
266
|
+
if namespaces.size > 1
|
267
|
+
"#{env}: #{namespaces.join(", ")}"
|
268
|
+
else
|
269
|
+
env
|
270
|
+
end
|
271
|
+
end.join("\n")
|
272
|
+
end
|
273
|
+
|
264
274
|
# Accepts a hash. Expands the "url" key that contains a
|
265
275
|
# URL database connection to a full connection
|
266
276
|
# hash and merges with the rest of the hash.
|
@@ -5,26 +5,22 @@ module ActiveRecord
|
|
5
5
|
module DetermineIfPreparableVisitor
|
6
6
|
attr_accessor :preparable
|
7
7
|
|
8
|
-
def accept(
|
8
|
+
def accept(object, collector)
|
9
9
|
@preparable = true
|
10
10
|
super
|
11
11
|
end
|
12
12
|
|
13
13
|
def visit_Arel_Nodes_In(o, collector)
|
14
14
|
@preparable = false
|
15
|
+
super
|
16
|
+
end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
if Arel::Nodes::BindParam === bind && Relation::QueryAttribute === bind.value
|
19
|
-
!bind.value.boundable?
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
18
|
+
def visit_Arel_Nodes_NotIn(o, collector)
|
19
|
+
@preparable = false
|
24
20
|
super
|
25
21
|
end
|
26
22
|
|
27
|
-
def visit_Arel_Nodes_SqlLiteral(
|
23
|
+
def visit_Arel_Nodes_SqlLiteral(o, collector)
|
28
24
|
@preparable = false
|
29
25
|
super
|
30
26
|
end
|
@@ -11,7 +11,7 @@ module ActiveRecord
|
|
11
11
|
else
|
12
12
|
super
|
13
13
|
end
|
14
|
-
|
14
|
+
@connection.abandon_results!
|
15
15
|
result
|
16
16
|
end
|
17
17
|
|
@@ -19,8 +19,21 @@ module ActiveRecord
|
|
19
19
|
execute(sql, name).to_a
|
20
20
|
end
|
21
21
|
|
22
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
23
|
+
:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :describe, :desc, :with
|
24
|
+
) # :nodoc:
|
25
|
+
private_constant :READ_QUERY
|
26
|
+
|
27
|
+
def write_query?(sql) # :nodoc:
|
28
|
+
!READ_QUERY.match?(sql)
|
29
|
+
end
|
30
|
+
|
22
31
|
# Executes the SQL statement in the context of this connection.
|
23
32
|
def execute(sql, name = nil)
|
33
|
+
if preventing_writes? && write_query?(sql)
|
34
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
35
|
+
end
|
36
|
+
|
24
37
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
25
38
|
# made since we established the connection
|
26
39
|
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
@@ -31,18 +44,28 @@ module ActiveRecord
|
|
31
44
|
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
32
45
|
if without_prepared_statement?(binds)
|
33
46
|
execute_and_free(sql, name) do |result|
|
34
|
-
|
47
|
+
if result
|
48
|
+
ActiveRecord::Result.new(result.fields, result.to_a)
|
49
|
+
else
|
50
|
+
ActiveRecord::Result.new([], [])
|
51
|
+
end
|
35
52
|
end
|
36
53
|
else
|
37
54
|
exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
|
38
|
-
|
55
|
+
if result
|
56
|
+
ActiveRecord::Result.new(result.fields, result.to_a)
|
57
|
+
else
|
58
|
+
ActiveRecord::Result.new([], [])
|
59
|
+
end
|
39
60
|
end
|
40
61
|
end
|
41
62
|
end
|
42
63
|
|
43
64
|
def exec_delete(sql, name = nil, binds = [])
|
44
65
|
if without_prepared_statement?(binds)
|
45
|
-
|
66
|
+
@lock.synchronize do
|
67
|
+
execute_and_free(sql, name) { @connection.affected_rows }
|
68
|
+
end
|
46
69
|
else
|
47
70
|
exec_stmt_and_free(sql, name, binds) { |stmt| stmt.affected_rows }
|
48
71
|
end
|
@@ -50,22 +73,31 @@ module ActiveRecord
|
|
50
73
|
alias :exec_update :exec_delete
|
51
74
|
|
52
75
|
private
|
76
|
+
def execute_batch(sql, name = nil)
|
77
|
+
super
|
78
|
+
@connection.abandon_results!
|
79
|
+
end
|
80
|
+
|
53
81
|
def default_insert_value(column)
|
54
|
-
|
82
|
+
super unless column.auto_increment?
|
55
83
|
end
|
56
84
|
|
57
85
|
def last_inserted_id(result)
|
58
86
|
@connection.last_id
|
59
87
|
end
|
60
88
|
|
61
|
-
def discard_remaining_results
|
62
|
-
@connection.next_result while @connection.more_results?
|
63
|
-
end
|
64
|
-
|
65
89
|
def supports_set_server_option?
|
66
90
|
@connection.respond_to?(:set_server_option)
|
67
91
|
end
|
68
92
|
|
93
|
+
def build_truncate_statements(*table_names)
|
94
|
+
if table_names.size == 1
|
95
|
+
super.first
|
96
|
+
else
|
97
|
+
super
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
69
101
|
def multi_statements_enabled?(flags)
|
70
102
|
if flags.is_a?(Array)
|
71
103
|
flags.include?("MULTI_STATEMENTS")
|
@@ -98,7 +130,40 @@ module ActiveRecord
|
|
98
130
|
end
|
99
131
|
end
|
100
132
|
|
133
|
+
def combine_multi_statements(total_sql)
|
134
|
+
total_sql.each_with_object([]) do |sql, total_sql_chunks|
|
135
|
+
previous_packet = total_sql_chunks.last
|
136
|
+
if max_allowed_packet_reached?(sql, previous_packet)
|
137
|
+
total_sql_chunks << +sql
|
138
|
+
else
|
139
|
+
previous_packet << ";\n"
|
140
|
+
previous_packet << sql
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def max_allowed_packet_reached?(current_packet, previous_packet)
|
146
|
+
if current_packet.bytesize > max_allowed_packet
|
147
|
+
raise ActiveRecordError,
|
148
|
+
"Fixtures set is too large #{current_packet.bytesize}. Consider increasing the max_allowed_packet variable."
|
149
|
+
elsif previous_packet.nil?
|
150
|
+
true
|
151
|
+
else
|
152
|
+
(current_packet.bytesize + previous_packet.bytesize + 2) > max_allowed_packet
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def max_allowed_packet
|
157
|
+
@max_allowed_packet ||= show_variable("max_allowed_packet")
|
158
|
+
end
|
159
|
+
|
101
160
|
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
161
|
+
if preventing_writes? && write_query?(sql)
|
162
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
163
|
+
end
|
164
|
+
|
165
|
+
materialize_transactions
|
166
|
+
|
102
167
|
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
103
168
|
# made since we established the connection
|
104
169
|
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
@@ -107,10 +172,7 @@ module ActiveRecord
|
|
107
172
|
|
108
173
|
log(sql, name, binds, type_casted_binds) do
|
109
174
|
if cache_stmt
|
110
|
-
|
111
|
-
stmt: @connection.prepare(sql)
|
112
|
-
}
|
113
|
-
stmt = cache[:stmt]
|
175
|
+
stmt = @statements[sql] ||= @connection.prepare(sql)
|
114
176
|
else
|
115
177
|
stmt = @connection.prepare(sql)
|
116
178
|
end
|
@@ -5,11 +5,11 @@ module ActiveRecord
|
|
5
5
|
module MySQL
|
6
6
|
module Quoting # :nodoc:
|
7
7
|
def quote_column_name(name)
|
8
|
-
|
8
|
+
self.class.quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
|
9
9
|
end
|
10
10
|
|
11
11
|
def quote_table_name(name)
|
12
|
-
|
12
|
+
self.class.quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
|
13
13
|
end
|
14
14
|
|
15
15
|
def unquoted_true
|
@@ -32,12 +32,49 @@ module ActiveRecord
|
|
32
32
|
"x'#{value.hex}'"
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
def column_name_matcher
|
36
|
+
COLUMN_NAME
|
37
|
+
end
|
38
|
+
|
39
|
+
def column_name_with_order_matcher
|
40
|
+
COLUMN_NAME_WITH_ORDER
|
40
41
|
end
|
42
|
+
|
43
|
+
COLUMN_NAME = /
|
44
|
+
\A
|
45
|
+
(
|
46
|
+
(?:
|
47
|
+
# `table_name`.`column_name` | function(one or no argument)
|
48
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
49
|
+
)
|
50
|
+
(?:\s+AS\s+(?:\w+|`\w+`))?
|
51
|
+
)
|
52
|
+
(?:\s*,\s*\g<1>)*
|
53
|
+
\z
|
54
|
+
/ix
|
55
|
+
|
56
|
+
COLUMN_NAME_WITH_ORDER = /
|
57
|
+
\A
|
58
|
+
(
|
59
|
+
(?:
|
60
|
+
# `table_name`.`column_name` | function(one or no argument)
|
61
|
+
((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\)
|
62
|
+
)
|
63
|
+
(?:\s+ASC|\s+DESC)?
|
64
|
+
)
|
65
|
+
(?:\s*,\s*\g<1>)*
|
66
|
+
\z
|
67
|
+
/ix
|
68
|
+
|
69
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
70
|
+
|
71
|
+
private
|
72
|
+
def _type_cast(value)
|
73
|
+
case value
|
74
|
+
when Date, Time then value
|
75
|
+
else super
|
76
|
+
end
|
77
|
+
end
|
41
78
|
end
|
42
79
|
end
|
43
80
|
end
|