activerecord 5.1.7 → 5.2.0
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 +372 -765
- 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 +16 -27
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +20 -10
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +4 -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 +43 -35
- 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 +7 -18
- data/lib/active_record/associations/has_one_association.rb +4 -1
- data/lib/active_record/associations/has_one_through_association.rb +8 -7
- data/lib/active_record/associations/join_dependency/join_association.rb +17 -56
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
- data/lib/active_record/associations/join_dependency.rb +23 -43
- 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 -10
- data/lib/active_record/associations/through_association.rb +25 -10
- data/lib/active_record/associations.rb +31 -54
- 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 +8 -2
- 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 +6 -5
- data/lib/active_record/autosave_association.rb +8 -11
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +8 -10
- 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 +111 -38
- 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 +13 -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 +57 -2
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -78
- data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +111 -183
- 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 +11 -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 +3 -11
- 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 -6
- 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 +246 -110
- 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 +58 -82
- 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 +18 -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 +71 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +80 -90
- 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 +15 -12
- 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 +54 -21
- 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 +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/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 +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 +166 -16
- data/lib/active_record/query_cache.rb +11 -6
- 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 +30 -8
- data/lib/active_record/relation/delegation.rb +15 -27
- data/lib/active_record/relation/finder_methods.rb +75 -78
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +51 -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 +53 -78
- data/lib/active_record/relation/query_attribute.rb +26 -2
- data/lib/active_record/relation/query_methods.rb +89 -88
- 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 +95 -208
- 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 +26 -15
- 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 +5 -12
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -7
- 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 +2 -4
- 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 +35 -5
- 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 +24 -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 -122
- 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/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,27 @@ module ActiveRecord
|
|
913
893
|
self
|
914
894
|
end
|
915
895
|
|
916
|
-
|
917
|
-
|
918
|
-
|
896
|
+
def skip_query_cache! # :nodoc:
|
897
|
+
self.skip_query_cache_value = true
|
898
|
+
self
|
919
899
|
end
|
920
900
|
|
921
|
-
# Returns
|
922
|
-
def
|
923
|
-
@
|
901
|
+
# Returns the Arel object associated with the relation.
|
902
|
+
def arel(aliases = nil) # :nodoc:
|
903
|
+
@arel ||= build_arel(aliases)
|
924
904
|
end
|
925
905
|
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
906
|
+
protected
|
907
|
+
# Returns a relation value with a given name
|
908
|
+
def get_value(name) # :nodoc:
|
909
|
+
@values.fetch(name, DEFAULT_VALUES[name])
|
910
|
+
end
|
911
|
+
|
912
|
+
# Sets the relation value with the given name
|
913
|
+
def set_value(name, value) # :nodoc:
|
914
|
+
assert_mutability!
|
915
|
+
@values[name] = value
|
916
|
+
end
|
931
917
|
|
932
918
|
private
|
933
919
|
|
@@ -936,16 +922,30 @@ module ActiveRecord
|
|
936
922
|
raise ImmutableRelation if defined?(@arel) && @arel
|
937
923
|
end
|
938
924
|
|
939
|
-
def build_arel
|
925
|
+
def build_arel(aliases)
|
940
926
|
arel = Arel::SelectManager.new(table)
|
941
927
|
|
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?
|
928
|
+
aliases = build_joins(arel, joins_values.flatten, aliases) unless joins_values.empty?
|
929
|
+
build_left_outer_joins(arel, left_outer_joins_values.flatten, aliases) unless left_outer_joins_values.empty?
|
944
930
|
|
945
931
|
arel.where(where_clause.ast) unless where_clause.empty?
|
946
932
|
arel.having(having_clause.ast) unless having_clause.empty?
|
947
|
-
|
948
|
-
|
933
|
+
if limit_value
|
934
|
+
limit_attribute = ActiveModel::Attribute.with_cast_value(
|
935
|
+
"LIMIT".freeze,
|
936
|
+
connection.sanitize_limit(limit_value),
|
937
|
+
Type.default_value,
|
938
|
+
)
|
939
|
+
arel.take(Arel::Nodes::BindParam.new(limit_attribute))
|
940
|
+
end
|
941
|
+
if offset_value
|
942
|
+
offset_attribute = ActiveModel::Attribute.with_cast_value(
|
943
|
+
"OFFSET".freeze,
|
944
|
+
offset_value.to_i,
|
945
|
+
Type.default_value,
|
946
|
+
)
|
947
|
+
arel.skip(Arel::Nodes::BindParam.new(offset_attribute))
|
948
|
+
end
|
949
949
|
arel.group(*arel_columns(group_values.uniq.reject(&:blank?))) unless group_values.empty?
|
950
950
|
|
951
951
|
build_order(arel)
|
@@ -964,6 +964,9 @@ module ActiveRecord
|
|
964
964
|
name = from_clause.name
|
965
965
|
case opts
|
966
966
|
when Relation
|
967
|
+
if opts.eager_loading?
|
968
|
+
opts = opts.send(:apply_join_dependency)
|
969
|
+
end
|
967
970
|
name ||= "subquery"
|
968
971
|
opts.arel.as(name.to_s)
|
969
972
|
else
|
@@ -971,20 +974,22 @@ module ActiveRecord
|
|
971
974
|
end
|
972
975
|
end
|
973
976
|
|
974
|
-
def build_left_outer_joins(manager, outer_joins)
|
977
|
+
def build_left_outer_joins(manager, outer_joins, aliases)
|
975
978
|
buckets = outer_joins.group_by do |join|
|
976
979
|
case join
|
977
980
|
when Hash, Symbol, Array
|
978
981
|
:association_join
|
982
|
+
when ActiveRecord::Associations::JoinDependency
|
983
|
+
:stashed_join
|
979
984
|
else
|
980
985
|
raise ArgumentError, "only Hash, Symbol and Array are allowed"
|
981
986
|
end
|
982
987
|
end
|
983
988
|
|
984
|
-
build_join_query(manager, buckets, Arel::Nodes::OuterJoin)
|
989
|
+
build_join_query(manager, buckets, Arel::Nodes::OuterJoin, aliases)
|
985
990
|
end
|
986
991
|
|
987
|
-
def build_joins(manager, joins)
|
992
|
+
def build_joins(manager, joins, aliases)
|
988
993
|
buckets = joins.group_by do |join|
|
989
994
|
case join
|
990
995
|
when String
|
@@ -1000,10 +1005,10 @@ module ActiveRecord
|
|
1000
1005
|
end
|
1001
1006
|
end
|
1002
1007
|
|
1003
|
-
build_join_query(manager, buckets, Arel::Nodes::InnerJoin)
|
1008
|
+
build_join_query(manager, buckets, Arel::Nodes::InnerJoin, aliases)
|
1004
1009
|
end
|
1005
1010
|
|
1006
|
-
def build_join_query(manager, buckets, join_type)
|
1011
|
+
def build_join_query(manager, buckets, join_type, aliases)
|
1007
1012
|
buckets.default = []
|
1008
1013
|
|
1009
1014
|
association_joins = buckets[:association_join]
|
@@ -1011,27 +1016,22 @@ module ActiveRecord
|
|
1011
1016
|
join_nodes = buckets[:join_node].uniq
|
1012
1017
|
string_joins = buckets[:string_join].map(&:strip).uniq
|
1013
1018
|
|
1014
|
-
join_list = join_nodes + convert_join_strings_to_ast(
|
1019
|
+
join_list = join_nodes + convert_join_strings_to_ast(string_joins)
|
1020
|
+
alias_tracker = alias_tracker(join_list, aliases)
|
1015
1021
|
|
1016
1022
|
join_dependency = ActiveRecord::Associations::JoinDependency.new(
|
1017
|
-
|
1018
|
-
association_joins,
|
1019
|
-
join_list
|
1023
|
+
klass, table, association_joins, alias_tracker
|
1020
1024
|
)
|
1021
1025
|
|
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
|
1026
|
+
joins = join_dependency.join_constraints(stashed_association_joins, join_type)
|
1027
|
+
joins.each { |join| manager.from(join) }
|
1028
1028
|
|
1029
1029
|
manager.join_sources.concat(join_list)
|
1030
1030
|
|
1031
|
-
|
1031
|
+
alias_tracker.aliases
|
1032
1032
|
end
|
1033
1033
|
|
1034
|
-
def convert_join_strings_to_ast(
|
1034
|
+
def convert_join_strings_to_ast(joins)
|
1035
1035
|
joins
|
1036
1036
|
.flatten
|
1037
1037
|
.reject(&:blank?)
|
@@ -1044,7 +1044,7 @@ module ActiveRecord
|
|
1044
1044
|
elsif klass.ignored_columns.any?
|
1045
1045
|
arel.project(*klass.column_names.map { |field| arel_attribute(field) })
|
1046
1046
|
else
|
1047
|
-
arel.project(
|
1047
|
+
arel.project(table[Arel.star])
|
1048
1048
|
end
|
1049
1049
|
end
|
1050
1050
|
|
@@ -1088,6 +1088,10 @@ module ActiveRecord
|
|
1088
1088
|
end
|
1089
1089
|
|
1090
1090
|
def does_not_support_reverse?(order)
|
1091
|
+
# Account for String subclasses like Arel::Nodes::SqlLiteral that
|
1092
|
+
# override methods like #count.
|
1093
|
+
order = String.new(order) unless order.instance_of?(String)
|
1094
|
+
|
1091
1095
|
# Uses SQL function with multiple arguments.
|
1092
1096
|
(order.include?(",") && order.split(",").find { |section| section.count("(") != section.count(")") }) ||
|
1093
1097
|
# Uses "nulls first" like construction.
|
@@ -1102,27 +1106,35 @@ module ActiveRecord
|
|
1102
1106
|
end
|
1103
1107
|
|
1104
1108
|
VALID_DIRECTIONS = [:asc, :desc, :ASC, :DESC,
|
1105
|
-
"asc", "desc", "ASC", "DESC"] # :nodoc:
|
1109
|
+
"asc", "desc", "ASC", "DESC"].to_set # :nodoc:
|
1106
1110
|
|
1107
1111
|
def validate_order_args(args)
|
1108
1112
|
args.each do |arg|
|
1109
1113
|
next unless arg.is_a?(Hash)
|
1110
1114
|
arg.each do |_key, value|
|
1111
|
-
|
1112
|
-
|
1115
|
+
unless VALID_DIRECTIONS.include?(value)
|
1116
|
+
raise ArgumentError,
|
1117
|
+
"Direction \"#{value}\" is invalid. Valid directions are: #{VALID_DIRECTIONS.to_a.inspect}"
|
1118
|
+
end
|
1113
1119
|
end
|
1114
1120
|
end
|
1115
1121
|
end
|
1116
1122
|
|
1117
1123
|
def preprocess_order_args(order_args)
|
1118
1124
|
order_args.map! do |arg|
|
1119
|
-
klass.
|
1125
|
+
klass.sanitize_sql_for_order(arg)
|
1120
1126
|
end
|
1121
1127
|
order_args.flatten!
|
1128
|
+
|
1129
|
+
@klass.enforce_raw_sql_whitelist(
|
1130
|
+
order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a },
|
1131
|
+
whitelist: AttributeMethods::ClassMethods::COLUMN_NAME_ORDER_WHITELIST
|
1132
|
+
)
|
1133
|
+
|
1122
1134
|
validate_order_args(order_args)
|
1123
1135
|
|
1124
1136
|
references = order_args.grep(String)
|
1125
|
-
references.map! { |arg| arg =~
|
1137
|
+
references.map! { |arg| arg =~ /^\W?(\w+)\W?\./ && $1 }.compact!
|
1126
1138
|
references!(references) if references.any?
|
1127
1139
|
|
1128
1140
|
# if a symbol is given we prepend the quoted table name
|
@@ -1167,7 +1179,7 @@ module ActiveRecord
|
|
1167
1179
|
end
|
1168
1180
|
end
|
1169
1181
|
|
1170
|
-
STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having]
|
1182
|
+
STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references]
|
1171
1183
|
def structurally_incompatible_values_for_or(other)
|
1172
1184
|
STRUCTURAL_OR_METHODS.reject do |method|
|
1173
1185
|
get_value(method) == other.get_value(method)
|
@@ -1181,7 +1193,6 @@ module ActiveRecord
|
|
1181
1193
|
|
1182
1194
|
DEFAULT_VALUES = {
|
1183
1195
|
create_with: FROZEN_EMPTY_HASH,
|
1184
|
-
readonly: false,
|
1185
1196
|
where: Relation::WhereClause.empty,
|
1186
1197
|
having: Relation::WhereClause.empty,
|
1187
1198
|
from: Relation::FromClause.empty
|
@@ -1190,15 +1201,5 @@ module ActiveRecord
|
|
1190
1201
|
Relation::MULTI_VALUE_METHODS.each do |value|
|
1191
1202
|
DEFAULT_VALUES[value] ||= FROZEN_EMPTY_ARRAY
|
1192
1203
|
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
1204
|
end
|
1204
1205
|
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
|