activerecord 5.1.7 → 5.2.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +556 -685
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations.rb +40 -63
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +41 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +27 -8
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +12 -4
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +59 -47
- data/lib/active_record/associations/collection_proxy.rb +20 -49
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +12 -1
- data/lib/active_record/associations/has_many_through_association.rb +36 -30
- data/lib/active_record/associations/has_one_association.rb +12 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency.rb +48 -93
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/preloader.rb +18 -38
- data/lib/active_record/associations/preloader/association.rb +45 -61
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +30 -214
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +9 -3
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attributes.rb +6 -5
- data/lib/active_record/autosave_association.rb +35 -19
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -6
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +2 -0
- data/lib/active_record/collection_cache_key.rb +12 -8
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +139 -41
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -31
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +92 -165
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +233 -111
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +57 -73
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +81 -94
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +41 -61
- data/lib/active_record/counter_cache.rb +10 -3
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +42 -3
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +67 -60
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +49 -19
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +14 -17
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +43 -0
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +47 -9
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/model_schema.rb +16 -21
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +167 -16
- data/lib/active_record/query_cache.rb +6 -8
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +62 -6
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +46 -36
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +108 -194
- data/lib/active_record/relation.rb +120 -214
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/calculations.rb +45 -19
- data/lib/active_record/relation/delegation.rb +45 -27
- data/lib/active_record/relation/finder_methods.rb +75 -76
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder.rb +60 -79
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +128 -99
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -68
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/scoping/default.rb +8 -9
- data/lib/active_record/scoping/named.rb +23 -7
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +23 -13
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +25 -14
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +6 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +33 -28
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +2 -0
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +35 -5
- data/lib/active_record/version.rb +2 -0
- data/lib/rails/generators/active_record.rb +3 -1
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- metadata +23 -36
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute_mutation_tracker.rb +0 -122
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/attribute_set/builder.rb +0 -126
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters # :nodoc:
|
3
5
|
module DatabaseLimits
|
@@ -60,6 +62,11 @@ module ActiveRecord
|
|
60
62
|
def joins_per_query
|
61
63
|
256
|
62
64
|
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def bind_params_length
|
68
|
+
65535
|
69
|
+
end
|
63
70
|
end
|
64
71
|
end
|
65
72
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module ConnectionAdapters # :nodoc:
|
3
5
|
module DatabaseStatements
|
@@ -7,35 +9,61 @@ module ActiveRecord
|
|
7
9
|
end
|
8
10
|
|
9
11
|
# Converts an arel AST to SQL
|
10
|
-
def to_sql(
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def to_sql(arel_or_sql_string, binds = [])
|
13
|
+
sql, _ = to_sql_and_binds(arel_or_sql_string, binds)
|
14
|
+
sql
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_sql_and_binds(arel_or_sql_string, binds = []) # :nodoc:
|
18
|
+
if arel_or_sql_string.respond_to?(:ast)
|
19
|
+
unless binds.empty?
|
20
|
+
raise "Passing bind parameters with an arel AST is forbidden. " \
|
21
|
+
"The values must be stored on the AST directly"
|
22
|
+
end
|
23
|
+
|
24
|
+
if prepared_statements
|
25
|
+
sql, binds = visitor.accept(arel_or_sql_string.ast, collector).value
|
26
|
+
|
27
|
+
if binds.length > bind_params_length
|
28
|
+
unprepared_statement do
|
29
|
+
sql, binds = to_sql_and_binds(arel_or_sql_string)
|
30
|
+
visitor.preparable = false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
else
|
34
|
+
sql = visitor.accept(arel_or_sql_string.ast, collector).value
|
35
|
+
end
|
36
|
+
[sql.freeze, binds]
|
14
37
|
else
|
15
|
-
|
38
|
+
visitor.preparable = false if prepared_statements
|
39
|
+
[arel_or_sql_string.dup.freeze, binds]
|
16
40
|
end
|
17
41
|
end
|
42
|
+
private :to_sql_and_binds
|
18
43
|
|
19
44
|
# This is used in the StatementCache object. It returns an object that
|
20
45
|
# can be used to query the database repeatedly.
|
21
46
|
def cacheable_query(klass, arel) # :nodoc:
|
22
|
-
collected = visitor.accept(arel.ast, collector)
|
23
47
|
if prepared_statements
|
24
|
-
|
48
|
+
sql, binds = visitor.accept(arel.ast, collector).value
|
49
|
+
query = klass.query(sql)
|
25
50
|
else
|
26
|
-
|
51
|
+
collector = PartialQueryCollector.new
|
52
|
+
parts, binds = visitor.accept(arel.ast, collector).value
|
53
|
+
query = klass.partial_query(parts)
|
27
54
|
end
|
55
|
+
[query, binds]
|
28
56
|
end
|
29
57
|
|
30
58
|
# Returns an ActiveRecord::Result instance.
|
31
59
|
def select_all(arel, name = nil, binds = [], preparable: nil)
|
32
|
-
arel
|
33
|
-
sql =
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
preparable = visitor.preparable
|
60
|
+
arel = arel_from_relation(arel)
|
61
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
62
|
+
|
63
|
+
if preparable.nil?
|
64
|
+
preparable = prepared_statements ? visitor.preparable : false
|
38
65
|
end
|
66
|
+
|
39
67
|
if prepared_statements && preparable
|
40
68
|
select_prepared(sql, name, binds)
|
41
69
|
else
|
@@ -130,26 +158,30 @@ module ActiveRecord
|
|
130
158
|
# If the next id was calculated in advance (as in Oracle), it should be
|
131
159
|
# passed in as +id_value+.
|
132
160
|
def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
|
133
|
-
|
161
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
162
|
+
value = exec_insert(sql, name, binds, pk, sequence_name)
|
134
163
|
id_value || last_inserted_id(value)
|
135
164
|
end
|
136
165
|
alias create insert
|
137
166
|
|
138
167
|
# Executes the update statement and returns the number of rows affected.
|
139
168
|
def update(arel, name = nil, binds = [])
|
140
|
-
|
169
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
170
|
+
exec_update(sql, name, binds)
|
141
171
|
end
|
142
172
|
|
143
173
|
# Executes the delete statement and returns the number of rows affected.
|
144
174
|
def delete(arel, name = nil, binds = [])
|
145
|
-
|
175
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
176
|
+
exec_delete(sql, name, binds)
|
146
177
|
end
|
147
178
|
|
148
179
|
# Returns +true+ when the connection adapter supports prepared statement
|
149
180
|
# caching, otherwise returns +false+
|
150
|
-
def supports_statement_cache?
|
151
|
-
|
181
|
+
def supports_statement_cache? # :nodoc:
|
182
|
+
true
|
152
183
|
end
|
184
|
+
deprecate :supports_statement_cache?
|
153
185
|
|
154
186
|
# Runs the given block in a database transaction, and returns the result
|
155
187
|
# of the block.
|
@@ -162,7 +194,7 @@ module ActiveRecord
|
|
162
194
|
#
|
163
195
|
# In order to get around this problem, #transaction will emulate the effect
|
164
196
|
# of nested transactions, by using savepoints:
|
165
|
-
#
|
197
|
+
# https://dev.mysql.com/doc/refman/5.7/en/savepoint.html
|
166
198
|
# Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8'
|
167
199
|
# supports savepoints.
|
168
200
|
#
|
@@ -214,7 +246,7 @@ module ActiveRecord
|
|
214
246
|
# You should consult the documentation for your database to understand the
|
215
247
|
# semantics of these different levels:
|
216
248
|
#
|
217
|
-
# *
|
249
|
+
# * https://www.postgresql.org/docs/current/static/transaction-iso.html
|
218
250
|
# * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
|
219
251
|
#
|
220
252
|
# An ActiveRecord::TransactionIsolationError will be raised if:
|
@@ -305,6 +337,9 @@ module ActiveRecord
|
|
305
337
|
|
306
338
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
307
339
|
# something beyond a simple insert (eg. Oracle).
|
340
|
+
# Most of adapters should implement `insert_fixtures` that leverages bulk SQL insert.
|
341
|
+
# We keep this method to provide fallback
|
342
|
+
# for databases like sqlite that do not support bulk inserts.
|
308
343
|
def insert_fixture(fixture, table_name)
|
309
344
|
fixture = fixture.stringify_keys
|
310
345
|
|
@@ -317,16 +352,50 @@ module ActiveRecord
|
|
317
352
|
raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
|
318
353
|
end
|
319
354
|
end
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
end
|
355
|
+
|
356
|
+
table = Arel::Table.new(table_name)
|
357
|
+
|
358
|
+
values = binds.map do |bind|
|
359
|
+
value = with_yaml_fallback(bind.value_for_database)
|
360
|
+
[table[bind.name], value]
|
327
361
|
end
|
328
362
|
|
329
|
-
|
363
|
+
manager = Arel::InsertManager.new
|
364
|
+
manager.into(table)
|
365
|
+
manager.insert(values)
|
366
|
+
execute manager.to_sql, "Fixture Insert"
|
367
|
+
end
|
368
|
+
|
369
|
+
# Inserts a set of fixtures into the table. Overridden in adapters that require
|
370
|
+
# something beyond a simple insert (eg. Oracle).
|
371
|
+
def insert_fixtures(fixtures, table_name)
|
372
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
373
|
+
`insert_fixtures` is deprecated and will be removed in the next version of Rails.
|
374
|
+
Consider using `insert_fixtures_set` for performance improvement.
|
375
|
+
MSG
|
376
|
+
return if fixtures.empty?
|
377
|
+
|
378
|
+
execute(build_fixture_sql(fixtures, table_name), "Fixtures Insert")
|
379
|
+
end
|
380
|
+
|
381
|
+
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
382
|
+
fixture_inserts = fixture_set.map do |table_name, fixtures|
|
383
|
+
next if fixtures.empty?
|
384
|
+
|
385
|
+
build_fixture_sql(fixtures, table_name)
|
386
|
+
end.compact
|
387
|
+
|
388
|
+
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name table}".dup }
|
389
|
+
total_sql = Array.wrap(combine_multi_statements(table_deletes + fixture_inserts))
|
390
|
+
|
391
|
+
disable_referential_integrity do
|
392
|
+
transaction(requires_new: true) do
|
393
|
+
total_sql.each do |sql|
|
394
|
+
execute sql, "Fixtures Load"
|
395
|
+
yield if block_given?
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
330
399
|
end
|
331
400
|
|
332
401
|
def empty_insert_statement_value
|
@@ -358,6 +427,44 @@ module ActiveRecord
|
|
358
427
|
alias join_to_delete join_to_update
|
359
428
|
|
360
429
|
private
|
430
|
+
def default_insert_value(column)
|
431
|
+
Arel.sql("DEFAULT")
|
432
|
+
end
|
433
|
+
|
434
|
+
def build_fixture_sql(fixtures, table_name)
|
435
|
+
columns = schema_cache.columns_hash(table_name)
|
436
|
+
|
437
|
+
values = fixtures.map do |fixture|
|
438
|
+
fixture = fixture.stringify_keys
|
439
|
+
|
440
|
+
unknown_columns = fixture.keys - columns.keys
|
441
|
+
if unknown_columns.any?
|
442
|
+
raise Fixture::FixtureError, %(table "#{table_name}" has no columns named #{unknown_columns.map(&:inspect).join(', ')}.)
|
443
|
+
end
|
444
|
+
|
445
|
+
columns.map do |name, column|
|
446
|
+
if fixture.key?(name)
|
447
|
+
type = lookup_cast_type_from_column(column)
|
448
|
+
bind = Relation::QueryAttribute.new(name, fixture[name], type)
|
449
|
+
with_yaml_fallback(bind.value_for_database)
|
450
|
+
else
|
451
|
+
default_insert_value(column)
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
table = Arel::Table.new(table_name)
|
457
|
+
manager = Arel::InsertManager.new
|
458
|
+
manager.into(table)
|
459
|
+
columns.each_key { |column| manager.columns << table[column] }
|
460
|
+
manager.values = manager.create_values_list(values)
|
461
|
+
|
462
|
+
manager.to_sql
|
463
|
+
end
|
464
|
+
|
465
|
+
def combine_multi_statements(total_sql)
|
466
|
+
total_sql.join(";\n")
|
467
|
+
end
|
361
468
|
|
362
469
|
# Returns a subquery for the given key using the join information.
|
363
470
|
def subquery_for(key, select)
|
@@ -388,11 +495,45 @@ module ActiveRecord
|
|
388
495
|
row && row.first
|
389
496
|
end
|
390
497
|
|
391
|
-
def
|
392
|
-
if relation.is_a?(Relation)
|
393
|
-
relation
|
498
|
+
def arel_from_relation(relation)
|
499
|
+
if relation.is_a?(Relation)
|
500
|
+
relation.arel
|
501
|
+
else
|
502
|
+
relation
|
503
|
+
end
|
504
|
+
end
|
505
|
+
|
506
|
+
# Fixture value is quoted by Arel, however scalar values
|
507
|
+
# are not quotable. In this case we want to convert
|
508
|
+
# the column value to YAML.
|
509
|
+
def with_yaml_fallback(value)
|
510
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
511
|
+
YAML.dump(value)
|
512
|
+
else
|
513
|
+
value
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
class PartialQueryCollector
|
518
|
+
def initialize
|
519
|
+
@parts = []
|
520
|
+
@binds = []
|
521
|
+
end
|
522
|
+
|
523
|
+
def <<(str)
|
524
|
+
@parts << str
|
525
|
+
self
|
526
|
+
end
|
527
|
+
|
528
|
+
def add_bind(obj)
|
529
|
+
@binds << obj
|
530
|
+
@parts << Arel::Nodes::BindParam.new(1)
|
531
|
+
self
|
532
|
+
end
|
533
|
+
|
534
|
+
def value
|
535
|
+
[@parts, @binds]
|
394
536
|
end
|
395
|
-
[relation, binds]
|
396
537
|
end
|
397
538
|
end
|
398
539
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "concurrent/map"
|
4
|
+
|
1
5
|
module ActiveRecord
|
2
6
|
module ConnectionAdapters # :nodoc:
|
3
7
|
module QueryCache
|
@@ -28,17 +32,17 @@ module ActiveRecord
|
|
28
32
|
end
|
29
33
|
|
30
34
|
def enable_query_cache!
|
31
|
-
@query_cache_enabled[connection_cache_key(
|
35
|
+
@query_cache_enabled[connection_cache_key(current_thread)] = true
|
32
36
|
connection.enable_query_cache! if active_connection?
|
33
37
|
end
|
34
38
|
|
35
39
|
def disable_query_cache!
|
36
|
-
@query_cache_enabled.delete connection_cache_key(
|
40
|
+
@query_cache_enabled.delete connection_cache_key(current_thread)
|
37
41
|
connection.disable_query_cache! if active_connection?
|
38
42
|
end
|
39
43
|
|
40
44
|
def query_cache_enabled
|
41
|
-
@query_cache_enabled[connection_cache_key(
|
45
|
+
@query_cache_enabled[connection_cache_key(current_thread)]
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
@@ -90,8 +94,13 @@ module ActiveRecord
|
|
90
94
|
|
91
95
|
def select_all(arel, name = nil, binds = [], preparable: nil)
|
92
96
|
if @query_cache_enabled && !locked?(arel)
|
93
|
-
arel
|
94
|
-
sql =
|
97
|
+
arel = arel_from_relation(arel)
|
98
|
+
sql, binds = to_sql_and_binds(arel, binds)
|
99
|
+
|
100
|
+
if preparable.nil?
|
101
|
+
preparable = prepared_statements ? visitor.preparable : false
|
102
|
+
end
|
103
|
+
|
95
104
|
cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
|
96
105
|
else
|
97
106
|
super
|
@@ -124,6 +133,7 @@ module ActiveRecord
|
|
124
133
|
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
|
125
134
|
# queries should not be cached.
|
126
135
|
def locked?(arel)
|
136
|
+
arel = arel.arel if arel.is_a?(Relation)
|
127
137
|
arel.respond_to?(:locked) && arel.locked
|
128
138
|
end
|
129
139
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/big_decimal/conversions"
|
2
4
|
require "active_support/multibyte/chars"
|
3
5
|
|
@@ -5,21 +7,12 @@ module ActiveRecord
|
|
5
7
|
module ConnectionAdapters # :nodoc:
|
6
8
|
module Quoting
|
7
9
|
# Quotes the column value to help prevent
|
8
|
-
# {SQL injection attacks}[
|
10
|
+
# {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection].
|
9
11
|
def quote(value)
|
10
12
|
value = id_value_for_database(value) if value.is_a?(Base)
|
11
13
|
|
12
|
-
if value.respond_to?(:
|
13
|
-
|
14
|
-
at &&= " at %s:%d" % at
|
15
|
-
|
16
|
-
owner = value.method(:quoted_id).owner.to_s
|
17
|
-
klass = value.class.to_s
|
18
|
-
klass += "(#{owner})" unless owner == klass
|
19
|
-
|
20
|
-
ActiveSupport::Deprecation.warn \
|
21
|
-
"Defining #quoted_id is deprecated and will be ignored in Rails 5.2. (defined on #{klass}#{at})"
|
22
|
-
return value.quoted_id
|
14
|
+
if value.respond_to?(:value_for_database)
|
15
|
+
value = value.value_for_database
|
23
16
|
end
|
24
17
|
|
25
18
|
_quote(value)
|
@@ -31,10 +24,6 @@ module ActiveRecord
|
|
31
24
|
def type_cast(value, column = nil)
|
32
25
|
value = id_value_for_database(value) if value.is_a?(Base)
|
33
26
|
|
34
|
-
if value.respond_to?(:quoted_id) && value.respond_to?(:id)
|
35
|
-
return value.id
|
36
|
-
end
|
37
|
-
|
38
27
|
if column
|
39
28
|
value = type_cast_from_column(column, value)
|
40
29
|
end
|
@@ -68,17 +57,6 @@ module ActiveRecord
|
|
68
57
|
lookup_cast_type(column.sql_type)
|
69
58
|
end
|
70
59
|
|
71
|
-
def fetch_type_metadata(sql_type)
|
72
|
-
cast_type = lookup_cast_type(sql_type)
|
73
|
-
SqlTypeMetadata.new(
|
74
|
-
sql_type: sql_type,
|
75
|
-
type: cast_type.type,
|
76
|
-
limit: cast_type.limit,
|
77
|
-
precision: cast_type.precision,
|
78
|
-
scale: cast_type.scale,
|
79
|
-
)
|
80
|
-
end
|
81
|
-
|
82
60
|
# Quotes a string, escaping any ' (single quote) and \ (backslash)
|
83
61
|
# characters.
|
84
62
|
def quote_string(s)
|
@@ -117,19 +95,19 @@ module ActiveRecord
|
|
117
95
|
end
|
118
96
|
|
119
97
|
def quoted_true
|
120
|
-
"
|
98
|
+
"TRUE".freeze
|
121
99
|
end
|
122
100
|
|
123
101
|
def unquoted_true
|
124
|
-
|
102
|
+
true
|
125
103
|
end
|
126
104
|
|
127
105
|
def quoted_false
|
128
|
-
"
|
106
|
+
"FALSE".freeze
|
129
107
|
end
|
130
108
|
|
131
109
|
def unquoted_false
|
132
|
-
|
110
|
+
false
|
133
111
|
end
|
134
112
|
|
135
113
|
# Quote date/time values for use in SQL input. Includes microseconds
|
@@ -169,6 +147,10 @@ module ActiveRecord
|
|
169
147
|
end
|
170
148
|
|
171
149
|
private
|
150
|
+
def lookup_cast_type(sql_type)
|
151
|
+
type_map.lookup(sql_type)
|
152
|
+
end
|
153
|
+
|
172
154
|
def id_value_for_database(value)
|
173
155
|
if primary_key = value.class.primary_key
|
174
156
|
value.instance_variable_get(:@attributes)[primary_key].value_for_database
|