activerecord 5.1.5 → 5.2.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +450 -699
- 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/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +4 -2
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +33 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- 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 +14 -5
- data/lib/active_record/associations/builder/collection_association.rb +1 -1
- 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 +52 -41
- data/lib/active_record/associations/collection_proxy.rb +12 -15
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +3 -1
- data/lib/active_record/associations/has_many_through_association.rb +8 -19
- 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/join_association.rb +22 -67
- 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/join_dependency.rb +48 -93
- 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/preloader.rb +17 -37
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/associations.rb +40 -63
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +25 -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/attribute_methods.rb +65 -24
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +16 -14
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +12 -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 +11 -7
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +157 -29
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -32
- 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 +149 -78
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
- 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 +2 -0
- 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/array.rb +6 -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 +3 -1
- 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 +8 -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/oid.rb +3 -1
- 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 +14 -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 +248 -112
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
- 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 +20 -1
- 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 +79 -92
- 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 +39 -60
- data/lib/active_record/counter_cache.rb +20 -15
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +17 -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 +4 -2
- 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 +30 -42
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +43 -0
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +40 -2
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/model_schema.rb +19 -24
- 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 +196 -48
- data/lib/active_record/query_cache.rb +12 -14
- data/lib/active_record/querying.rb +3 -1
- data/lib/active_record/railtie.rb +61 -3
- 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 +110 -192
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/calculations.rb +31 -9
- data/lib/active_record/relation/delegation.rb +15 -27
- data/lib/active_record/relation/finder_methods.rb +71 -76
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +47 -20
- 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/predicate_builder.rb +55 -79
- data/lib/active_record/relation/query_attribute.rb +26 -2
- data/lib/active_record/relation/query_methods.rb +95 -91
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -1
- 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/relation.rb +106 -219
- 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/default.rb +6 -7
- data/lib/active_record/scoping/named.rb +21 -7
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +22 -12
- 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 +13 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +32 -27
- data/lib/active_record/translation.rb +2 -0
- 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 +6 -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.rb +4 -1
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.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 +36 -6
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/version.rb +2 -0
- data/lib/active_record.rb +11 -4
- 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/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/migration.rb +2 -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
- data/lib/rails/generators/active_record.rb +3 -1
- 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/user_provided_default.rb +0 -30
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute_mutation_tracker.rb +0 -114
- data/lib/active_record/attribute_set/builder.rb +0 -124
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/attribute_set.rb +0 -113
- 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
|
require "active_record/relation/from_clause"
|
2
4
|
require "active_record/relation/query_attribute"
|
3
5
|
require "active_record/relation/where_clause"
|
@@ -74,31 +76,6 @@ module ActiveRecord
|
|
74
76
|
CODE
|
75
77
|
end
|
76
78
|
|
77
|
-
def bound_attributes
|
78
|
-
if limit_value
|
79
|
-
limit_bind = Attribute.with_cast_value(
|
80
|
-
"LIMIT".freeze,
|
81
|
-
connection.sanitize_limit(limit_value),
|
82
|
-
Type.default_value,
|
83
|
-
)
|
84
|
-
end
|
85
|
-
if offset_value
|
86
|
-
offset_bind = Attribute.with_cast_value(
|
87
|
-
"OFFSET".freeze,
|
88
|
-
offset_value.to_i,
|
89
|
-
Type.default_value,
|
90
|
-
)
|
91
|
-
end
|
92
|
-
connection.combine_bind_parameters(
|
93
|
-
from_clause: from_clause.binds,
|
94
|
-
join_clause: arel.bind_values,
|
95
|
-
where_clause: where_clause.binds,
|
96
|
-
having_clause: having_clause.binds,
|
97
|
-
limit: limit_bind,
|
98
|
-
offset: offset_bind,
|
99
|
-
)
|
100
|
-
end
|
101
|
-
|
102
79
|
alias extensions extending_values
|
103
80
|
|
104
81
|
# Specify relationships to be included in the result set. For
|
@@ -202,12 +179,13 @@ module ActiveRecord
|
|
202
179
|
|
203
180
|
# Works in two unique ways.
|
204
181
|
#
|
205
|
-
# First: takes a block so it can be used just like
|
182
|
+
# First: takes a block so it can be used just like <tt>Array#select</tt>.
|
206
183
|
#
|
207
184
|
# Model.all.select { |m| m.field == value }
|
208
185
|
#
|
209
186
|
# This will build an array of objects from the database for the scope,
|
210
|
-
# converting them into an array and iterating through them using
|
187
|
+
# converting them into an array and iterating through them using
|
188
|
+
# <tt>Array#select</tt>.
|
211
189
|
#
|
212
190
|
# Second: Modifies the SELECT statement for the query so that only certain
|
213
191
|
# fields are retrieved:
|
@@ -248,7 +226,7 @@ module ActiveRecord
|
|
248
226
|
return super()
|
249
227
|
end
|
250
228
|
|
251
|
-
raise ArgumentError, "Call
|
229
|
+
raise ArgumentError, "Call `select' with at least one field" if fields.empty?
|
252
230
|
spawn._select!(*fields)
|
253
231
|
end
|
254
232
|
|
@@ -317,6 +295,7 @@ module ActiveRecord
|
|
317
295
|
spawn.order!(*args)
|
318
296
|
end
|
319
297
|
|
298
|
+
# Same as #order but operates on relation in-place instead of copying.
|
320
299
|
def order!(*args) # :nodoc:
|
321
300
|
preprocess_order_args(args)
|
322
301
|
|
@@ -338,6 +317,7 @@ module ActiveRecord
|
|
338
317
|
spawn.reorder!(*args)
|
339
318
|
end
|
340
319
|
|
320
|
+
# Same as #reorder but operates on relation in-place instead of copying.
|
341
321
|
def reorder!(*args) # :nodoc:
|
342
322
|
preprocess_order_args(args)
|
343
323
|
|
@@ -347,8 +327,8 @@ module ActiveRecord
|
|
347
327
|
end
|
348
328
|
|
349
329
|
VALID_UNSCOPING_VALUES = Set.new([:where, :select, :group, :order, :lock,
|
350
|
-
:limit, :offset, :joins, :
|
351
|
-
:readonly, :having])
|
330
|
+
:limit, :offset, :joins, :left_outer_joins,
|
331
|
+
:includes, :from, :readonly, :having])
|
352
332
|
|
353
333
|
# Removes an unwanted relation that is already defined on a chain of relations.
|
354
334
|
# This is useful when passing around chains of relations and would like to
|
@@ -395,10 +375,11 @@ module ActiveRecord
|
|
395
375
|
args.each do |scope|
|
396
376
|
case scope
|
397
377
|
when Symbol
|
378
|
+
scope = :left_outer_joins if scope == :left_joins
|
398
379
|
if !VALID_UNSCOPING_VALUES.include?(scope)
|
399
380
|
raise ArgumentError, "Called unscope() with invalid unscoping argument ':#{scope}'. Valid arguments are :#{VALID_UNSCOPING_VALUES.to_a.join(", :")}."
|
400
381
|
end
|
401
|
-
set_value(scope,
|
382
|
+
set_value(scope, DEFAULT_VALUES[scope])
|
402
383
|
when Hash
|
403
384
|
scope.each do |key, target_value|
|
404
385
|
if key != :where
|
@@ -463,16 +444,14 @@ module ActiveRecord
|
|
463
444
|
# => SELECT "users".* FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"
|
464
445
|
#
|
465
446
|
def left_outer_joins(*args)
|
466
|
-
check_if_method_has_arguments!(
|
467
|
-
|
468
|
-
args.compact!
|
469
|
-
args.flatten!
|
470
|
-
|
447
|
+
check_if_method_has_arguments!(__callee__, args)
|
471
448
|
spawn.left_outer_joins!(*args)
|
472
449
|
end
|
473
450
|
alias :left_joins :left_outer_joins
|
474
451
|
|
475
452
|
def left_outer_joins!(*args) # :nodoc:
|
453
|
+
args.compact!
|
454
|
+
args.flatten!
|
476
455
|
self.left_outer_joins_values += args
|
477
456
|
self
|
478
457
|
end
|
@@ -657,6 +636,7 @@ module ActiveRecord
|
|
657
636
|
|
658
637
|
self.where_clause = self.where_clause.or(other.where_clause)
|
659
638
|
self.having_clause = having_clause.or(other.having_clause)
|
639
|
+
self.references_values += other.references_values
|
660
640
|
|
661
641
|
self
|
662
642
|
end
|
@@ -797,7 +777,7 @@ module ActiveRecord
|
|
797
777
|
value = sanitize_forbidden_attributes(value)
|
798
778
|
self.create_with_value = create_with_value.merge(value)
|
799
779
|
else
|
800
|
-
self.create_with_value =
|
780
|
+
self.create_with_value = FROZEN_EMPTY_HASH
|
801
781
|
end
|
802
782
|
|
803
783
|
self
|
@@ -913,21 +893,28 @@ module ActiveRecord
|
|
913
893
|
self
|
914
894
|
end
|
915
895
|
|
896
|
+
def skip_query_cache!(value = true) # :nodoc:
|
897
|
+
self.skip_query_cache_value = value
|
898
|
+
self
|
899
|
+
end
|
900
|
+
|
916
901
|
# Returns the Arel object associated with the relation.
|
917
|
-
def arel # :nodoc:
|
918
|
-
@arel ||= build_arel
|
902
|
+
def arel(aliases = nil) # :nodoc:
|
903
|
+
@arel ||= build_arel(aliases)
|
919
904
|
end
|
920
905
|
|
921
906
|
# Returns a relation value with a given name
|
922
907
|
def get_value(name) # :nodoc:
|
923
|
-
@values[name]
|
908
|
+
@values.fetch(name, DEFAULT_VALUES[name])
|
924
909
|
end
|
925
910
|
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
911
|
+
protected
|
912
|
+
|
913
|
+
# Sets the relation value with the given name
|
914
|
+
def set_value(name, value) # :nodoc:
|
915
|
+
assert_mutability!
|
916
|
+
@values[name] = value
|
917
|
+
end
|
931
918
|
|
932
919
|
private
|
933
920
|
|
@@ -936,16 +923,30 @@ module ActiveRecord
|
|
936
923
|
raise ImmutableRelation if defined?(@arel) && @arel
|
937
924
|
end
|
938
925
|
|
939
|
-
def build_arel
|
926
|
+
def build_arel(aliases)
|
940
927
|
arel = Arel::SelectManager.new(table)
|
941
928
|
|
942
|
-
build_joins(arel, joins_values.flatten) unless joins_values.empty?
|
943
|
-
build_left_outer_joins(arel, left_outer_joins_values.flatten) unless left_outer_joins_values.empty?
|
929
|
+
aliases = build_joins(arel, joins_values.flatten, aliases) unless joins_values.empty?
|
930
|
+
build_left_outer_joins(arel, left_outer_joins_values.flatten, aliases) unless left_outer_joins_values.empty?
|
944
931
|
|
945
932
|
arel.where(where_clause.ast) unless where_clause.empty?
|
946
933
|
arel.having(having_clause.ast) unless having_clause.empty?
|
947
|
-
|
948
|
-
|
934
|
+
if limit_value
|
935
|
+
limit_attribute = ActiveModel::Attribute.with_cast_value(
|
936
|
+
"LIMIT".freeze,
|
937
|
+
connection.sanitize_limit(limit_value),
|
938
|
+
Type.default_value,
|
939
|
+
)
|
940
|
+
arel.take(Arel::Nodes::BindParam.new(limit_attribute))
|
941
|
+
end
|
942
|
+
if offset_value
|
943
|
+
offset_attribute = ActiveModel::Attribute.with_cast_value(
|
944
|
+
"OFFSET".freeze,
|
945
|
+
offset_value.to_i,
|
946
|
+
Type.default_value,
|
947
|
+
)
|
948
|
+
arel.skip(Arel::Nodes::BindParam.new(offset_attribute))
|
949
|
+
end
|
949
950
|
arel.group(*arel_columns(group_values.uniq.reject(&:blank?))) unless group_values.empty?
|
950
951
|
|
951
952
|
build_order(arel)
|
@@ -964,6 +965,9 @@ module ActiveRecord
|
|
964
965
|
name = from_clause.name
|
965
966
|
case opts
|
966
967
|
when Relation
|
968
|
+
if opts.eager_loading?
|
969
|
+
opts = opts.send(:apply_join_dependency)
|
970
|
+
end
|
967
971
|
name ||= "subquery"
|
968
972
|
opts.arel.as(name.to_s)
|
969
973
|
else
|
@@ -971,20 +975,22 @@ module ActiveRecord
|
|
971
975
|
end
|
972
976
|
end
|
973
977
|
|
974
|
-
def build_left_outer_joins(manager, outer_joins)
|
978
|
+
def build_left_outer_joins(manager, outer_joins, aliases)
|
975
979
|
buckets = outer_joins.group_by do |join|
|
976
980
|
case join
|
977
981
|
when Hash, Symbol, Array
|
978
982
|
:association_join
|
983
|
+
when ActiveRecord::Associations::JoinDependency
|
984
|
+
:stashed_join
|
979
985
|
else
|
980
986
|
raise ArgumentError, "only Hash, Symbol and Array are allowed"
|
981
987
|
end
|
982
988
|
end
|
983
989
|
|
984
|
-
build_join_query(manager, buckets, Arel::Nodes::OuterJoin)
|
990
|
+
build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases)
|
985
991
|
end
|
986
992
|
|
987
|
-
def build_joins(manager, joins)
|
993
|
+
def build_joins(manager, joins, aliases)
|
988
994
|
buckets = joins.group_by do |join|
|
989
995
|
case join
|
990
996
|
when String
|
@@ -1000,38 +1006,33 @@ module ActiveRecord
|
|
1000
1006
|
end
|
1001
1007
|
end
|
1002
1008
|
|
1003
|
-
build_join_query(manager, buckets, Arel::Nodes::InnerJoin)
|
1009
|
+
build_join_query(manager, buckets, Arel::Nodes::InnerJoin, aliases)
|
1004
1010
|
end
|
1005
1011
|
|
1006
|
-
def build_join_query(manager, buckets, join_type)
|
1012
|
+
def build_join_query(manager, buckets, join_type, aliases)
|
1007
1013
|
buckets.default = []
|
1008
1014
|
|
1009
|
-
association_joins
|
1010
|
-
|
1011
|
-
join_nodes
|
1012
|
-
string_joins
|
1015
|
+
association_joins = buckets[:association_join]
|
1016
|
+
stashed_joins = buckets[:stashed_join]
|
1017
|
+
join_nodes = buckets[:join_node].uniq
|
1018
|
+
string_joins = buckets[:string_join].map(&:strip).uniq
|
1013
1019
|
|
1014
|
-
join_list = join_nodes + convert_join_strings_to_ast(
|
1020
|
+
join_list = join_nodes + convert_join_strings_to_ast(string_joins)
|
1021
|
+
alias_tracker = alias_tracker(join_list, aliases)
|
1015
1022
|
|
1016
1023
|
join_dependency = ActiveRecord::Associations::JoinDependency.new(
|
1017
|
-
|
1018
|
-
association_joins,
|
1019
|
-
join_list
|
1024
|
+
klass, table, association_joins
|
1020
1025
|
)
|
1021
1026
|
|
1022
|
-
|
1023
|
-
|
1024
|
-
join_infos.each do |info|
|
1025
|
-
info.joins.each { |join| manager.from(join) }
|
1026
|
-
manager.bind_values.concat info.binds
|
1027
|
-
end
|
1027
|
+
joins = join_dependency.join_constraints(stashed_joins, join_type, alias_tracker)
|
1028
|
+
joins.each { |join| manager.from(join) }
|
1028
1029
|
|
1029
1030
|
manager.join_sources.concat(join_list)
|
1030
1031
|
|
1031
|
-
|
1032
|
+
alias_tracker.aliases
|
1032
1033
|
end
|
1033
1034
|
|
1034
|
-
def convert_join_strings_to_ast(
|
1035
|
+
def convert_join_strings_to_ast(joins)
|
1035
1036
|
joins
|
1036
1037
|
.flatten
|
1037
1038
|
.reject(&:blank?)
|
@@ -1044,16 +1045,18 @@ module ActiveRecord
|
|
1044
1045
|
elsif klass.ignored_columns.any?
|
1045
1046
|
arel.project(*klass.column_names.map { |field| arel_attribute(field) })
|
1046
1047
|
else
|
1047
|
-
arel.project(
|
1048
|
+
arel.project(table[Arel.star])
|
1048
1049
|
end
|
1049
1050
|
end
|
1050
1051
|
|
1051
1052
|
def arel_columns(columns)
|
1052
|
-
columns.
|
1053
|
+
columns.flat_map do |field|
|
1053
1054
|
if (Symbol === field || String === field) && (klass.has_attribute?(field) || klass.attribute_alias?(field)) && !from_clause.value
|
1054
1055
|
arel_attribute(field)
|
1055
1056
|
elsif Symbol === field
|
1056
1057
|
connection.quote_table_name(field.to_s)
|
1058
|
+
elsif Proc === field
|
1059
|
+
field.call
|
1057
1060
|
else
|
1058
1061
|
field
|
1059
1062
|
end
|
@@ -1079,7 +1082,7 @@ module ActiveRecord
|
|
1079
1082
|
end
|
1080
1083
|
o.split(",").map! do |s|
|
1081
1084
|
s.strip!
|
1082
|
-
s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || s
|
1085
|
+
s.gsub!(/\sasc\Z/i, " DESC") || s.gsub!(/\sdesc\Z/i, " ASC") || (s << " DESC")
|
1083
1086
|
end
|
1084
1087
|
else
|
1085
1088
|
o
|
@@ -1088,6 +1091,10 @@ module ActiveRecord
|
|
1088
1091
|
end
|
1089
1092
|
|
1090
1093
|
def does_not_support_reverse?(order)
|
1094
|
+
# Account for String subclasses like Arel::Nodes::SqlLiteral that
|
1095
|
+
# override methods like #count.
|
1096
|
+
order = String.new(order) unless order.instance_of?(String)
|
1097
|
+
|
1091
1098
|
# Uses SQL function with multiple arguments.
|
1092
1099
|
(order.include?(",") && order.split(",").find { |section| section.count("(") != section.count(")") }) ||
|
1093
1100
|
# Uses "nulls first" like construction.
|
@@ -1102,27 +1109,35 @@ module ActiveRecord
|
|
1102
1109
|
end
|
1103
1110
|
|
1104
1111
|
VALID_DIRECTIONS = [:asc, :desc, :ASC, :DESC,
|
1105
|
-
"asc", "desc", "ASC", "DESC"] # :nodoc:
|
1112
|
+
"asc", "desc", "ASC", "DESC"].to_set # :nodoc:
|
1106
1113
|
|
1107
1114
|
def validate_order_args(args)
|
1108
1115
|
args.each do |arg|
|
1109
1116
|
next unless arg.is_a?(Hash)
|
1110
1117
|
arg.each do |_key, value|
|
1111
|
-
|
1112
|
-
|
1118
|
+
unless VALID_DIRECTIONS.include?(value)
|
1119
|
+
raise ArgumentError,
|
1120
|
+
"Direction \"#{value}\" is invalid. Valid directions are: #{VALID_DIRECTIONS.to_a.inspect}"
|
1121
|
+
end
|
1113
1122
|
end
|
1114
1123
|
end
|
1115
1124
|
end
|
1116
1125
|
|
1117
1126
|
def preprocess_order_args(order_args)
|
1118
1127
|
order_args.map! do |arg|
|
1119
|
-
klass.
|
1128
|
+
klass.sanitize_sql_for_order(arg)
|
1120
1129
|
end
|
1121
1130
|
order_args.flatten!
|
1131
|
+
|
1132
|
+
@klass.enforce_raw_sql_whitelist(
|
1133
|
+
order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a },
|
1134
|
+
whitelist: AttributeMethods::ClassMethods::COLUMN_NAME_ORDER_WHITELIST
|
1135
|
+
)
|
1136
|
+
|
1122
1137
|
validate_order_args(order_args)
|
1123
1138
|
|
1124
1139
|
references = order_args.grep(String)
|
1125
|
-
references.map! { |arg| arg =~
|
1140
|
+
references.map! { |arg| arg =~ /^\W?(\w+)\W?\./ && $1 }.compact!
|
1126
1141
|
references!(references) if references.any?
|
1127
1142
|
|
1128
1143
|
# if a symbol is given we prepend the quoted table name
|
@@ -1167,7 +1182,7 @@ module ActiveRecord
|
|
1167
1182
|
end
|
1168
1183
|
end
|
1169
1184
|
|
1170
|
-
STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having]
|
1185
|
+
STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references]
|
1171
1186
|
def structurally_incompatible_values_for_or(other)
|
1172
1187
|
STRUCTURAL_OR_METHODS.reject do |method|
|
1173
1188
|
get_value(method) == other.get_value(method)
|
@@ -1181,7 +1196,6 @@ module ActiveRecord
|
|
1181
1196
|
|
1182
1197
|
DEFAULT_VALUES = {
|
1183
1198
|
create_with: FROZEN_EMPTY_HASH,
|
1184
|
-
readonly: false,
|
1185
1199
|
where: Relation::WhereClause.empty,
|
1186
1200
|
having: Relation::WhereClause.empty,
|
1187
1201
|
from: Relation::FromClause.empty
|
@@ -1190,15 +1204,5 @@ module ActiveRecord
|
|
1190
1204
|
Relation::MULTI_VALUE_METHODS.each do |value|
|
1191
1205
|
DEFAULT_VALUES[value] ||= FROZEN_EMPTY_ARRAY
|
1192
1206
|
end
|
1193
|
-
|
1194
|
-
Relation::SINGLE_VALUE_METHODS.each do |value|
|
1195
|
-
DEFAULT_VALUES[value] = nil if DEFAULT_VALUES[value].nil?
|
1196
|
-
end
|
1197
|
-
|
1198
|
-
def default_value_for(name)
|
1199
|
-
DEFAULT_VALUES.fetch(name) do
|
1200
|
-
raise ArgumentError, "unknown relation value #{name.inspect}"
|
1201
|
-
end
|
1202
|
-
end
|
1203
1207
|
end
|
1204
1208
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_support/core_ext/hash/except"
|
2
4
|
require "active_support/core_ext/hash/slice"
|
3
5
|
require "active_record/relation/merger"
|
@@ -67,7 +69,7 @@ module ActiveRecord
|
|
67
69
|
private
|
68
70
|
|
69
71
|
def relation_with(values)
|
70
|
-
result = Relation.create(klass,
|
72
|
+
result = Relation.create(klass, values: values)
|
71
73
|
result.extend(*extending_values) if extending_values.any?
|
72
74
|
result
|
73
75
|
end
|
@@ -1,65 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
class Relation
|
3
5
|
class WhereClause # :nodoc:
|
4
|
-
attr_reader :binds
|
5
|
-
|
6
6
|
delegate :any?, :empty?, to: :predicates
|
7
7
|
|
8
|
-
def initialize(predicates
|
8
|
+
def initialize(predicates)
|
9
9
|
@predicates = predicates
|
10
|
-
@binds = binds
|
11
10
|
end
|
12
11
|
|
13
12
|
def +(other)
|
14
13
|
WhereClause.new(
|
15
14
|
predicates + other.predicates,
|
16
|
-
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def -(other)
|
19
|
+
WhereClause.new(
|
20
|
+
predicates - other.predicates,
|
17
21
|
)
|
18
22
|
end
|
19
23
|
|
20
24
|
def merge(other)
|
21
25
|
WhereClause.new(
|
22
26
|
predicates_unreferenced_by(other) + other.predicates,
|
23
|
-
non_conflicting_binds(other) + other.binds,
|
24
27
|
)
|
25
28
|
end
|
26
29
|
|
27
30
|
def except(*columns)
|
28
|
-
WhereClause.new(
|
31
|
+
WhereClause.new(except_predicates(columns))
|
29
32
|
end
|
30
33
|
|
31
34
|
def or(other)
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
left = self - other
|
36
|
+
common = self - left
|
37
|
+
right = other - common
|
38
|
+
|
39
|
+
if left.empty? || right.empty?
|
40
|
+
common
|
36
41
|
else
|
37
|
-
WhereClause.new(
|
38
|
-
[ast.or(
|
39
|
-
binds + other.binds
|
42
|
+
or_clause = WhereClause.new(
|
43
|
+
[left.ast.or(right.ast)],
|
40
44
|
)
|
45
|
+
common + or_clause
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
44
49
|
def to_h(table_name = nil)
|
45
|
-
equalities = predicates
|
50
|
+
equalities = equalities(predicates)
|
46
51
|
if table_name
|
47
52
|
equalities = equalities.select do |node|
|
48
53
|
node.left.relation.name == table_name
|
49
54
|
end
|
50
55
|
end
|
51
56
|
|
52
|
-
binds = self.binds.map { |attr| [attr.name, attr.value] }.to_h
|
53
|
-
|
54
57
|
equalities.map { |node|
|
55
|
-
name = node.left.name
|
56
|
-
|
57
|
-
|
58
|
-
when Array then node.right.map(&:val)
|
59
|
-
when Arel::Nodes::Casted, Arel::Nodes::Quoted
|
60
|
-
node.right.val
|
61
|
-
end
|
62
|
-
}]
|
58
|
+
name = node.left.name.to_s
|
59
|
+
value = extract_node_value(node.right)
|
60
|
+
[name, value]
|
63
61
|
}.to_h
|
64
62
|
end
|
65
63
|
|
@@ -69,20 +67,17 @@ module ActiveRecord
|
|
69
67
|
|
70
68
|
def ==(other)
|
71
69
|
other.is_a?(WhereClause) &&
|
72
|
-
predicates == other.predicates
|
73
|
-
binds == other.binds
|
70
|
+
predicates == other.predicates
|
74
71
|
end
|
75
72
|
|
76
73
|
def invert
|
77
|
-
WhereClause.new(inverted_predicates
|
74
|
+
WhereClause.new(inverted_predicates)
|
78
75
|
end
|
79
76
|
|
80
77
|
def self.empty
|
81
|
-
@empty ||= new([]
|
78
|
+
@empty ||= new([])
|
82
79
|
end
|
83
80
|
|
84
|
-
# TODO Change this to private once we've dropped Ruby 2.2 support.
|
85
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
86
81
|
protected
|
87
82
|
|
88
83
|
attr_reader :predicates
|
@@ -95,6 +90,20 @@ module ActiveRecord
|
|
95
90
|
end
|
96
91
|
|
97
92
|
private
|
93
|
+
def equalities(predicates)
|
94
|
+
equalities = []
|
95
|
+
|
96
|
+
predicates.each do |node|
|
97
|
+
case node
|
98
|
+
when Arel::Nodes::Equality
|
99
|
+
equalities << node
|
100
|
+
when Arel::Nodes::And
|
101
|
+
equalities.concat equalities(node.children)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
equalities
|
106
|
+
end
|
98
107
|
|
99
108
|
def predicates_unreferenced_by(other)
|
100
109
|
predicates.reject do |n|
|
@@ -106,12 +115,6 @@ module ActiveRecord
|
|
106
115
|
node.respond_to?(:operator) && node.operator == :==
|
107
116
|
end
|
108
117
|
|
109
|
-
def non_conflicting_binds(other)
|
110
|
-
conflicts = referenced_columns & other.referenced_columns
|
111
|
-
conflicts.map! { |node| node.name.to_s }
|
112
|
-
binds.reject { |attr| conflicts.include?(attr.name) }
|
113
|
-
end
|
114
|
-
|
115
118
|
def inverted_predicates
|
116
119
|
predicates.map { |node| invert_predicate(node) }
|
117
120
|
end
|
@@ -131,44 +134,22 @@ module ActiveRecord
|
|
131
134
|
end
|
132
135
|
end
|
133
136
|
|
134
|
-
def
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
except = \
|
142
|
-
case node
|
143
|
-
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
|
144
|
-
subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
|
145
|
-
columns.include?(subrelation.name.to_s)
|
146
|
-
end
|
147
|
-
|
148
|
-
if except && binds_contains > 0
|
149
|
-
(binds_index...(binds_index + binds_contains)).each do |i|
|
150
|
-
except_binds[i] = true
|
151
|
-
end
|
137
|
+
def except_predicates(columns)
|
138
|
+
predicates.reject do |node|
|
139
|
+
case node
|
140
|
+
when Arel::Nodes::Between, Arel::Nodes::In, Arel::Nodes::NotIn, Arel::Nodes::Equality, Arel::Nodes::NotEqual, Arel::Nodes::LessThan, Arel::Nodes::LessThanOrEqual, Arel::Nodes::GreaterThan, Arel::Nodes::GreaterThanOrEqual
|
141
|
+
subrelation = (node.left.kind_of?(Arel::Attributes::Attribute) ? node.left : node.right)
|
142
|
+
columns.include?(subrelation.name.to_s)
|
152
143
|
end
|
153
|
-
|
154
|
-
binds_index += binds_contains if binds_contains
|
155
|
-
|
156
|
-
except
|
157
|
-
end
|
158
|
-
|
159
|
-
binds = self.binds.reject.with_index do |_, i|
|
160
|
-
except_binds[i]
|
161
144
|
end
|
162
|
-
|
163
|
-
[predicates, binds]
|
164
145
|
end
|
165
146
|
|
166
147
|
def predicates_with_wrapped_sql_literals
|
167
148
|
non_empty_predicates.map do |node|
|
168
|
-
|
169
|
-
|
170
|
-
else
|
149
|
+
case node
|
150
|
+
when Arel::Nodes::SqlLiteral, ::String
|
171
151
|
wrap_sql_literal(node)
|
152
|
+
else node
|
172
153
|
end
|
173
154
|
end
|
174
155
|
end
|
@@ -184,6 +165,22 @@ module ActiveRecord
|
|
184
165
|
end
|
185
166
|
Arel::Nodes::Grouping.new(node)
|
186
167
|
end
|
168
|
+
|
169
|
+
def extract_node_value(node)
|
170
|
+
case node
|
171
|
+
when Array
|
172
|
+
node.map { |v| extract_node_value(v) }
|
173
|
+
when Arel::Nodes::Casted, Arel::Nodes::Quoted
|
174
|
+
node.val
|
175
|
+
when Arel::Nodes::BindParam
|
176
|
+
value = node.value
|
177
|
+
if value.respond_to?(:value_before_type_cast)
|
178
|
+
value.value_before_type_cast
|
179
|
+
else
|
180
|
+
value
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
187
184
|
end
|
188
185
|
end
|
189
186
|
end
|