activerecord 5.2.3 → 6.0.0.rc2
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 +605 -554
- 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/associations.rb +19 -14
- data/lib/active_record/associations/association.rb +52 -19
- 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 +5 -15
- 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 +6 -21
- 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 +18 -25
- 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 +24 -28
- data/lib/active_record/associations/join_dependency/join_association.rb +27 -7
- 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 +15 -5
- 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 +111 -19
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +95 -123
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +20 -11
- 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 +172 -41
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +128 -194
- data/lib/active_record/connection_adapters/column.rb +17 -13
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +73 -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 +24 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +20 -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/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 +160 -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 +118 -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 +127 -143
- data/lib/active_record/connection_handling.rb +149 -27
- data/lib/active_record/core.rb +100 -60
- data/lib/active_record/counter_cache.rb +4 -29
- data/lib/active_record/database_configurations.rb +204 -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 +28 -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 +140 -472
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +13 -3
- data/lib/active_record/insert_all.rb +180 -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 +90 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +87 -76
- 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 +30 -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 +193 -46
- data/lib/active_record/reflection.rb +42 -44
- data/lib/active_record/relation.rb +310 -80
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +58 -49
- data/lib/active_record/relation/delegation.rb +26 -43
- data/lib/active_record/relation/finder_methods.rb +14 -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 +182 -68
- 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 +6 -7
- data/lib/active_record/scoping/named.rb +19 -15
- data/lib/active_record/statement_cache.rb +32 -5
- 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 +159 -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 +38 -0
- data/lib/active_record/test_fixtures.rb +224 -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/uniqueness.rb +15 -27
- data/lib/arel.rb +51 -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 -27
- data/lib/active_record/collection_cache_key.rb +0 -53
@@ -1,22 +1,30 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/deprecation"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
module ConnectionAdapters # :nodoc:
|
5
7
|
module DatabaseLimits
|
8
|
+
def max_identifier_length # :nodoc:
|
9
|
+
64
|
10
|
+
end
|
11
|
+
|
6
12
|
# Returns the maximum length of a table alias.
|
7
13
|
def table_alias_length
|
8
|
-
|
14
|
+
max_identifier_length
|
9
15
|
end
|
10
16
|
|
11
17
|
# Returns the maximum length of a column name.
|
12
18
|
def column_name_length
|
13
|
-
|
19
|
+
max_identifier_length
|
14
20
|
end
|
21
|
+
deprecate :column_name_length
|
15
22
|
|
16
23
|
# Returns the maximum length of a table name.
|
17
24
|
def table_name_length
|
18
|
-
|
25
|
+
max_identifier_length
|
19
26
|
end
|
27
|
+
deprecate :table_name_length
|
20
28
|
|
21
29
|
# Returns the maximum allowed length for an index name. This
|
22
30
|
# limit is enforced by \Rails and is less than or equal to
|
@@ -29,23 +37,26 @@ module ActiveRecord
|
|
29
37
|
|
30
38
|
# Returns the maximum length of an index name.
|
31
39
|
def index_name_length
|
32
|
-
|
40
|
+
max_identifier_length
|
33
41
|
end
|
34
42
|
|
35
43
|
# Returns the maximum number of columns per table.
|
36
44
|
def columns_per_table
|
37
45
|
1024
|
38
46
|
end
|
47
|
+
deprecate :columns_per_table
|
39
48
|
|
40
49
|
# Returns the maximum number of indexes per table.
|
41
50
|
def indexes_per_table
|
42
51
|
16
|
43
52
|
end
|
53
|
+
deprecate :indexes_per_table
|
44
54
|
|
45
55
|
# Returns the maximum number of columns in a multicolumn index.
|
46
56
|
def columns_per_multicolumn_index
|
47
57
|
16
|
48
58
|
end
|
59
|
+
deprecate :columns_per_multicolumn_index
|
49
60
|
|
50
61
|
# Returns the maximum number of elements in an IN (x,y,z) clause.
|
51
62
|
# +nil+ means no limit.
|
@@ -57,11 +68,13 @@ module ActiveRecord
|
|
57
68
|
def sql_query_length
|
58
69
|
1048575
|
59
70
|
end
|
71
|
+
deprecate :sql_query_length
|
60
72
|
|
61
73
|
# Returns maximum number of joins in a single query.
|
62
74
|
def joins_per_query
|
63
75
|
256
|
64
76
|
end
|
77
|
+
deprecate :joins_per_query
|
65
78
|
|
66
79
|
private
|
67
80
|
def bind_params_length
|
@@ -22,7 +22,7 @@ module ActiveRecord
|
|
22
22
|
end
|
23
23
|
|
24
24
|
if prepared_statements
|
25
|
-
sql, binds = visitor.
|
25
|
+
sql, binds = visitor.compile(arel_or_sql_string.ast, collector)
|
26
26
|
|
27
27
|
if binds.length > bind_params_length
|
28
28
|
unprepared_statement do
|
@@ -31,7 +31,7 @@ module ActiveRecord
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
else
|
34
|
-
sql = visitor.
|
34
|
+
sql = visitor.compile(arel_or_sql_string.ast, collector)
|
35
35
|
end
|
36
36
|
[sql.freeze, binds]
|
37
37
|
else
|
@@ -45,11 +45,11 @@ module ActiveRecord
|
|
45
45
|
# can be used to query the database repeatedly.
|
46
46
|
def cacheable_query(klass, arel) # :nodoc:
|
47
47
|
if prepared_statements
|
48
|
-
sql, binds = visitor.
|
48
|
+
sql, binds = visitor.compile(arel.ast, collector)
|
49
49
|
query = klass.query(sql)
|
50
50
|
else
|
51
|
-
collector =
|
52
|
-
parts, binds = visitor.
|
51
|
+
collector = klass.partial_query_collector
|
52
|
+
parts, binds = visitor.compile(arel.ast, collector)
|
53
53
|
query = klass.partial_query(parts)
|
54
54
|
end
|
55
55
|
[query, binds]
|
@@ -106,6 +106,11 @@ module ActiveRecord
|
|
106
106
|
exec_query(sql, name).rows
|
107
107
|
end
|
108
108
|
|
109
|
+
# Determines whether the SQL statement is a write query.
|
110
|
+
def write_query?(sql)
|
111
|
+
raise NotImplementedError
|
112
|
+
end
|
113
|
+
|
109
114
|
# Executes the SQL statement in the context of this connection and returns
|
110
115
|
# the raw result from the connection adapter.
|
111
116
|
# Note: depending on your database connector, the result returned by this
|
@@ -126,7 +131,7 @@ module ActiveRecord
|
|
126
131
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
127
132
|
# the executed +sql+ statement.
|
128
133
|
def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
|
129
|
-
sql, binds = sql_for_insert(sql, pk,
|
134
|
+
sql, binds = sql_for_insert(sql, pk, binds)
|
130
135
|
exec_query(sql, name, binds)
|
131
136
|
end
|
132
137
|
|
@@ -137,11 +142,6 @@ module ActiveRecord
|
|
137
142
|
exec_query(sql, name, binds)
|
138
143
|
end
|
139
144
|
|
140
|
-
# Executes the truncate statement.
|
141
|
-
def truncate(table_name, name = nil)
|
142
|
-
raise NotImplementedError
|
143
|
-
end
|
144
|
-
|
145
145
|
# Executes update +sql+ statement in the context of this connection using
|
146
146
|
# +binds+ as the bind substitutes. +name+ is logged along with
|
147
147
|
# the executed +sql+ statement.
|
@@ -176,12 +176,22 @@ module ActiveRecord
|
|
176
176
|
exec_delete(sql, name, binds)
|
177
177
|
end
|
178
178
|
|
179
|
-
#
|
180
|
-
|
181
|
-
|
182
|
-
|
179
|
+
# Executes the truncate statement.
|
180
|
+
def truncate(table_name, name = nil)
|
181
|
+
execute(build_truncate_statements(table_name), name)
|
182
|
+
end
|
183
|
+
|
184
|
+
def truncate_tables(*table_names) # :nodoc:
|
185
|
+
return if table_names.empty?
|
186
|
+
|
187
|
+
with_multi_statements do
|
188
|
+
disable_referential_integrity do
|
189
|
+
Array(build_truncate_statements(*table_names)).each do |sql|
|
190
|
+
execute_batch(sql, "Truncate Tables")
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
183
194
|
end
|
184
|
-
deprecate :supports_statement_cache?
|
185
195
|
|
186
196
|
# Runs the given block in a database transaction, and returns the result
|
187
197
|
# of the block.
|
@@ -272,7 +282,9 @@ module ActiveRecord
|
|
272
282
|
|
273
283
|
attr_reader :transaction_manager #:nodoc:
|
274
284
|
|
275
|
-
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
285
|
+
delegate :within_new_transaction, :open_transactions, :current_transaction, :begin_transaction,
|
286
|
+
:commit_transaction, :rollback_transaction, :materialize_transactions,
|
287
|
+
:disable_lazy_transactions!, :enable_lazy_transactions!, to: :transaction_manager
|
276
288
|
|
277
289
|
def transaction_open?
|
278
290
|
current_transaction.open?
|
@@ -337,68 +349,30 @@ module ActiveRecord
|
|
337
349
|
|
338
350
|
# Inserts the given fixture into the table. Overridden in adapters that require
|
339
351
|
# something beyond a simple insert (eg. Oracle).
|
340
|
-
# Most of adapters should implement `
|
352
|
+
# Most of adapters should implement `insert_fixtures_set` that leverages bulk SQL insert.
|
341
353
|
# We keep this method to provide fallback
|
342
354
|
# for databases like sqlite that do not support bulk inserts.
|
343
355
|
def insert_fixture(fixture, table_name)
|
344
|
-
fixture
|
345
|
-
|
346
|
-
columns = schema_cache.columns_hash(table_name)
|
347
|
-
binds = fixture.map do |name, value|
|
348
|
-
if column = columns[name]
|
349
|
-
type = lookup_cast_type_from_column(column)
|
350
|
-
Relation::QueryAttribute.new(name, value, type)
|
351
|
-
else
|
352
|
-
raise Fixture::FixtureError, %(table "#{table_name}" has no column named #{name.inspect}.)
|
353
|
-
end
|
354
|
-
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]
|
361
|
-
end
|
362
|
-
|
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")
|
356
|
+
execute(build_fixture_sql(Array.wrap(fixture), table_name), "Fixture Insert")
|
379
357
|
end
|
380
358
|
|
381
359
|
def insert_fixtures_set(fixture_set, tables_to_delete = [])
|
382
|
-
fixture_inserts = fixture_set
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
transaction(requires_new: true) do
|
393
|
-
total_sql.each do |sql|
|
394
|
-
execute sql, "Fixtures Load"
|
395
|
-
yield if block_given?
|
360
|
+
fixture_inserts = build_fixture_statements(fixture_set)
|
361
|
+
table_deletes = tables_to_delete.map { |table| "DELETE FROM #{quote_table_name(table)}" }
|
362
|
+
total_sql = Array(combine_multi_statements(table_deletes + fixture_inserts))
|
363
|
+
|
364
|
+
with_multi_statements do
|
365
|
+
disable_referential_integrity do
|
366
|
+
transaction(requires_new: true) do
|
367
|
+
total_sql.each do |sql|
|
368
|
+
execute_batch(sql, "Fixtures Load")
|
369
|
+
end
|
396
370
|
end
|
397
371
|
end
|
398
372
|
end
|
399
373
|
end
|
400
374
|
|
401
|
-
def empty_insert_statement_value
|
375
|
+
def empty_insert_statement_value(primary_key = nil)
|
402
376
|
"DEFAULT VALUES"
|
403
377
|
end
|
404
378
|
|
@@ -416,25 +390,33 @@ module ActiveRecord
|
|
416
390
|
end
|
417
391
|
end
|
418
392
|
|
419
|
-
#
|
420
|
-
#
|
421
|
-
#
|
422
|
-
def
|
423
|
-
|
424
|
-
|
425
|
-
|
393
|
+
# Fixture value is quoted by Arel, however scalar values
|
394
|
+
# are not quotable. In this case we want to convert
|
395
|
+
# the column value to YAML.
|
396
|
+
def with_yaml_fallback(value) # :nodoc:
|
397
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
398
|
+
YAML.dump(value)
|
399
|
+
else
|
400
|
+
value
|
401
|
+
end
|
426
402
|
end
|
427
|
-
alias join_to_delete join_to_update
|
428
403
|
|
429
404
|
private
|
405
|
+
def execute_batch(sql, name = nil)
|
406
|
+
execute(sql, name)
|
407
|
+
end
|
408
|
+
|
409
|
+
DEFAULT_INSERT_VALUE = Arel.sql("DEFAULT").freeze
|
410
|
+
private_constant :DEFAULT_INSERT_VALUE
|
411
|
+
|
430
412
|
def default_insert_value(column)
|
431
|
-
|
413
|
+
DEFAULT_INSERT_VALUE
|
432
414
|
end
|
433
415
|
|
434
416
|
def build_fixture_sql(fixtures, table_name)
|
435
417
|
columns = schema_cache.columns_hash(table_name)
|
436
418
|
|
437
|
-
|
419
|
+
values_list = fixtures.map do |fixture|
|
438
420
|
fixture = fixture.stringify_keys
|
439
421
|
|
440
422
|
unknown_columns = fixture.keys - columns.keys
|
@@ -445,8 +427,7 @@ module ActiveRecord
|
|
445
427
|
columns.map do |name, column|
|
446
428
|
if fixture.key?(name)
|
447
429
|
type = lookup_cast_type_from_column(column)
|
448
|
-
|
449
|
-
with_yaml_fallback(bind.value_for_database)
|
430
|
+
with_yaml_fallback(type.serialize(fixture[name]))
|
450
431
|
else
|
451
432
|
default_insert_value(column)
|
452
433
|
end
|
@@ -456,21 +437,45 @@ module ActiveRecord
|
|
456
437
|
table = Arel::Table.new(table_name)
|
457
438
|
manager = Arel::InsertManager.new
|
458
439
|
manager.into(table)
|
459
|
-
columns.each_key { |column| manager.columns << table[column] }
|
460
|
-
manager.values = manager.create_values_list(values)
|
461
440
|
|
441
|
+
if values_list.size == 1
|
442
|
+
values = values_list.shift
|
443
|
+
new_values = []
|
444
|
+
columns.each_key.with_index { |column, i|
|
445
|
+
unless values[i].equal?(DEFAULT_INSERT_VALUE)
|
446
|
+
new_values << values[i]
|
447
|
+
manager.columns << table[column]
|
448
|
+
end
|
449
|
+
}
|
450
|
+
values_list << new_values
|
451
|
+
else
|
452
|
+
columns.each_key { |column| manager.columns << table[column] }
|
453
|
+
end
|
454
|
+
|
455
|
+
manager.values = manager.create_values_list(values_list)
|
462
456
|
manager.to_sql
|
463
457
|
end
|
464
458
|
|
465
|
-
def
|
466
|
-
|
459
|
+
def build_fixture_statements(fixture_set)
|
460
|
+
fixture_set.map do |table_name, fixtures|
|
461
|
+
next if fixtures.empty?
|
462
|
+
build_fixture_sql(fixtures, table_name)
|
463
|
+
end.compact
|
464
|
+
end
|
465
|
+
|
466
|
+
def build_truncate_statements(*table_names)
|
467
|
+
truncate_tables = table_names.map do |table_name|
|
468
|
+
"TRUNCATE TABLE #{quote_table_name(table_name)}"
|
469
|
+
end
|
470
|
+
combine_multi_statements(truncate_tables)
|
471
|
+
end
|
472
|
+
|
473
|
+
def with_multi_statements
|
474
|
+
yield
|
467
475
|
end
|
468
476
|
|
469
|
-
|
470
|
-
|
471
|
-
subselect = select.clone
|
472
|
-
subselect.projections = [key]
|
473
|
-
subselect
|
477
|
+
def combine_multi_statements(total_sql)
|
478
|
+
total_sql.join(";\n")
|
474
479
|
end
|
475
480
|
|
476
481
|
# Returns an ActiveRecord::Result instance.
|
@@ -482,7 +487,7 @@ module ActiveRecord
|
|
482
487
|
exec_query(sql, name, binds, prepare: true)
|
483
488
|
end
|
484
489
|
|
485
|
-
def sql_for_insert(sql, pk,
|
490
|
+
def sql_for_insert(sql, pk, binds)
|
486
491
|
[sql, binds]
|
487
492
|
end
|
488
493
|
|
@@ -502,39 +507,6 @@ module ActiveRecord
|
|
502
507
|
relation
|
503
508
|
end
|
504
509
|
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]
|
536
|
-
end
|
537
|
-
end
|
538
510
|
end
|
539
511
|
end
|
540
512
|
end
|
@@ -7,7 +7,8 @@ module ActiveRecord
|
|
7
7
|
module QueryCache
|
8
8
|
class << self
|
9
9
|
def included(base) #:nodoc:
|
10
|
-
dirties_query_cache base, :insert, :update, :delete, :
|
10
|
+
dirties_query_cache base, :insert, :update, :delete, :truncate, :truncate_tables,
|
11
|
+
:rollback_to_savepoint, :rollback_db_transaction
|
11
12
|
|
12
13
|
base.set_callback :checkout, :after, :configure_query_cache!
|
13
14
|
base.set_callback :checkin, :after, :disable_query_cache!
|
@@ -17,7 +18,7 @@ module ActiveRecord
|
|
17
18
|
method_names.each do |method_name|
|
18
19
|
base.class_eval <<-end_code, __FILE__, __LINE__ + 1
|
19
20
|
def #{method_name}(*)
|
20
|
-
|
21
|
+
ActiveRecord::Base.clear_query_caches_for_current_thread if @query_cache_enabled
|
21
22
|
super
|
22
23
|
end
|
23
24
|
end_code
|
@@ -32,17 +33,17 @@ module ActiveRecord
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def enable_query_cache!
|
35
|
-
@query_cache_enabled[connection_cache_key(
|
36
|
+
@query_cache_enabled[connection_cache_key(current_thread)] = true
|
36
37
|
connection.enable_query_cache! if active_connection?
|
37
38
|
end
|
38
39
|
|
39
40
|
def disable_query_cache!
|
40
|
-
@query_cache_enabled.delete connection_cache_key(
|
41
|
+
@query_cache_enabled.delete connection_cache_key(current_thread)
|
41
42
|
connection.disable_query_cache! if active_connection?
|
42
43
|
end
|
43
44
|
|
44
45
|
def query_cache_enabled
|
45
|
-
@query_cache_enabled[connection_cache_key(
|
46
|
+
@query_cache_enabled[connection_cache_key(current_thread)]
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
@@ -115,12 +116,7 @@ module ActiveRecord
|
|
115
116
|
if @query_cache[sql].key?(binds)
|
116
117
|
ActiveSupport::Notifications.instrument(
|
117
118
|
"sql.active_record",
|
118
|
-
sql
|
119
|
-
binds: binds,
|
120
|
-
type_casted_binds: -> { type_casted_binds(binds) },
|
121
|
-
name: name,
|
122
|
-
connection_id: object_id,
|
123
|
-
cached: true,
|
119
|
+
cache_notification_info(sql, name, binds)
|
124
120
|
)
|
125
121
|
@query_cache[sql][binds]
|
126
122
|
else
|
@@ -130,6 +126,19 @@ module ActiveRecord
|
|
130
126
|
end
|
131
127
|
end
|
132
128
|
|
129
|
+
# Database adapters can override this method to
|
130
|
+
# provide custom cache information.
|
131
|
+
def cache_notification_info(sql, name, binds)
|
132
|
+
{
|
133
|
+
sql: sql,
|
134
|
+
binds: binds,
|
135
|
+
type_casted_binds: -> { type_casted_binds(binds) },
|
136
|
+
name: name,
|
137
|
+
connection_id: object_id,
|
138
|
+
cached: true
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
133
142
|
# If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
|
134
143
|
# queries should not be cached.
|
135
144
|
def locked?(arel)
|