activerecord 5.2.7 → 6.0.0.beta1
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 +299 -778
- data/MIT-LICENSE +3 -1
- data/README.rdoc +1 -1
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +4 -2
- data/lib/active_record/associations/association.rb +35 -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/belongs_to.rb +14 -50
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
- data/lib/active_record/associations/collection_association.rb +11 -25
- data/lib/active_record/associations/collection_proxy.rb +32 -6
- data/lib/active_record/associations/foreign_association.rb +7 -0
- data/lib/active_record/associations/has_many_association.rb +1 -1
- data/lib/active_record/associations/has_many_through_association.rb +25 -18
- 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/join_association.rb +11 -26
- data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
- data/lib/active_record/associations/join_dependency.rb +15 -20
- data/lib/active_record/associations/preloader/association.rb +1 -2
- data/lib/active_record/associations/preloader.rb +32 -29
- data/lib/active_record/associations/singular_association.rb +2 -16
- data/lib/active_record/associations.rb +16 -12
- data/lib/active_record/attribute_assignment.rb +7 -10
- data/lib/active_record/attribute_methods/dirty.rb +64 -26
- data/lib/active_record/attribute_methods/primary_key.rb +8 -7
- data/lib/active_record/attribute_methods/read.rb +16 -48
- 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 +15 -16
- data/lib/active_record/attribute_methods.rb +34 -56
- data/lib/active_record/autosave_association.rb +7 -21
- data/lib/active_record/base.rb +2 -2
- data/lib/active_record/callbacks.rb +3 -17
- data/lib/active_record/collection_cache_key.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
- data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
- data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
- data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
- data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
- data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
- data/lib/active_record/connection_handling.rb +132 -26
- data/lib/active_record/core.rb +76 -43
- data/lib/active_record/counter_cache.rb +4 -29
- 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 +74 -0
- data/lib/active_record/database_configurations.rb +184 -0
- data/lib/active_record/enum.rb +22 -7
- data/lib/active_record/errors.rb +24 -21
- 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 +12 -2
- data/lib/active_record/integration.rb +56 -16
- data/lib/active_record/internal_metadata.rb +5 -1
- data/lib/active_record/locking/optimistic.rb +2 -2
- data/lib/active_record/locking/pessimistic.rb +3 -3
- data/lib/active_record/log_subscriber.rb +7 -26
- data/lib/active_record/migration/command_recorder.rb +35 -5
- data/lib/active_record/migration/compatibility.rb +34 -16
- data/lib/active_record/migration.rb +38 -37
- 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 +18 -7
- data/lib/active_record/query_cache.rb +11 -4
- data/lib/active_record/querying.rb +19 -11
- data/lib/active_record/railtie.rb +71 -42
- 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 +94 -43
- data/lib/active_record/reflection.rb +60 -44
- data/lib/active_record/relation/batches.rb +13 -10
- data/lib/active_record/relation/calculations.rb +38 -28
- data/lib/active_record/relation/delegation.rb +4 -13
- data/lib/active_record/relation/finder_methods.rb +12 -25
- data/lib/active_record/relation/merger.rb +2 -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/predicate_builder.rb +4 -6
- data/lib/active_record/relation/query_attribute.rb +15 -12
- data/lib/active_record/relation/query_methods.rb +29 -52
- data/lib/active_record/relation/where_clause.rb +4 -0
- data/lib/active_record/relation/where_clause_factory.rb +1 -2
- data/lib/active_record/relation.rb +150 -69
- data/lib/active_record/result.rb +30 -11
- data/lib/active_record/sanitization.rb +2 -39
- data/lib/active_record/schema.rb +1 -10
- data/lib/active_record/schema_dumper.rb +12 -6
- data/lib/active_record/schema_migration.rb +4 -0
- data/lib/active_record/scoping/default.rb +10 -3
- data/lib/active_record/scoping/named.rb +10 -14
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/statement_cache.rb +32 -5
- data/lib/active_record/store.rb +39 -8
- data/lib/active_record/table_metadata.rb +1 -4
- data/lib/active_record/tasks/database_tasks.rb +89 -23
- data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
- 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 +4 -6
- data/lib/active_record/transactions.rb +3 -22
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type.rb +3 -4
- data/lib/active_record/type_caster/connection.rb +1 -6
- data/lib/active_record/type_caster/map.rb +1 -4
- data/lib/active_record/validations/uniqueness.rb +13 -25
- data/lib/active_record.rb +2 -1
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -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/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/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 +63 -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 +44 -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.rb +16 -0
- data/lib/arel/nodes/values_list.rb +24 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +67 -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/depth_first.rb +199 -0
- data/lib/arel/visitors/dot.rb +292 -0
- data/lib/arel/visitors/ibm_db.rb +21 -0
- data/lib/arel/visitors/informix.rb +56 -0
- data/lib/arel/visitors/mssql.rb +143 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +67 -0
- data/lib/arel/visitors/postgresql.rb +116 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +913 -0
- data/lib/arel/visitors/visitor.rb +42 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +44 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
- data/lib/rails/generators/active_record/migration.rb +14 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
- metadata +104 -26
@@ -79,17 +79,12 @@ module ActiveRecord
|
|
79
79
|
# Post.find_by "published_at < ?", 2.weeks.ago
|
80
80
|
def find_by(arg, *args)
|
81
81
|
where(arg, *args).take
|
82
|
-
rescue ::RangeError
|
83
|
-
nil
|
84
82
|
end
|
85
83
|
|
86
84
|
# Like #find_by, except that if no record is found, raises
|
87
85
|
# an ActiveRecord::RecordNotFound error.
|
88
86
|
def find_by!(arg, *args)
|
89
87
|
where(arg, *args).take!
|
90
|
-
rescue ::RangeError
|
91
|
-
raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value",
|
92
|
-
@klass.name, @klass.primary_key)
|
93
88
|
end
|
94
89
|
|
95
90
|
# Gives a record (or N records if a parameter is supplied) without any implied
|
@@ -312,6 +307,8 @@ module ActiveRecord
|
|
312
307
|
|
313
308
|
return false if !conditions || limit_value == 0
|
314
309
|
|
310
|
+
conditions = sanitize_forbidden_attributes(conditions)
|
311
|
+
|
315
312
|
if eager_loading?
|
316
313
|
relation = apply_join_dependency(eager_loading: false)
|
317
314
|
return relation.exists?(conditions)
|
@@ -319,9 +316,7 @@ module ActiveRecord
|
|
319
316
|
|
320
317
|
relation = construct_relation_for_exists(conditions)
|
321
318
|
|
322
|
-
skip_query_cache_if_necessary { connection.
|
323
|
-
rescue ::RangeError
|
324
|
-
false
|
319
|
+
skip_query_cache_if_necessary { connection.select_value(relation.arel, "#{name} Exists") } ? true : false
|
325
320
|
end
|
326
321
|
|
327
322
|
# This method is called whenever no records are found with either a single
|
@@ -338,14 +333,14 @@ module ActiveRecord
|
|
338
333
|
name = @klass.name
|
339
334
|
|
340
335
|
if ids.nil?
|
341
|
-
error = "Couldn't find #{name}"
|
336
|
+
error = +"Couldn't find #{name}"
|
342
337
|
error << " with#{conditions}" if conditions
|
343
338
|
raise RecordNotFound.new(error, name, key)
|
344
339
|
elsif Array(ids).size == 1
|
345
340
|
error = "Couldn't find #{name} with '#{key}'=#{ids}#{conditions}"
|
346
341
|
raise RecordNotFound.new(error, name, key, ids)
|
347
342
|
else
|
348
|
-
error = "Couldn't find all #{name.pluralize} with '#{key}': "
|
343
|
+
error = +"Couldn't find all #{name.pluralize} with '#{key}': "
|
349
344
|
error << "(#{ids.join(", ")})#{conditions} (found #{result_size} results, but was looking for #{expected_size})."
|
350
345
|
error << " Couldn't find #{name.pluralize(not_found_ids.size)} with #{key.to_s.pluralize(not_found_ids.size)} #{not_found_ids.join(', ')}." if not_found_ids
|
351
346
|
raise RecordNotFound.new(error, name, key, ids)
|
@@ -359,11 +354,7 @@ module ActiveRecord
|
|
359
354
|
end
|
360
355
|
|
361
356
|
def construct_relation_for_exists(conditions)
|
362
|
-
|
363
|
-
relation = except(:order).limit!(1)
|
364
|
-
else
|
365
|
-
relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
|
366
|
-
end
|
357
|
+
relation = except(:select, :distinct, :order)._select!(ONE_AS_ONE).limit!(1)
|
367
358
|
|
368
359
|
case conditions
|
369
360
|
when Array, Hash
|
@@ -375,15 +366,14 @@ module ActiveRecord
|
|
375
366
|
relation
|
376
367
|
end
|
377
368
|
|
378
|
-
def construct_join_dependency
|
379
|
-
including = eager_load_values + includes_values
|
369
|
+
def construct_join_dependency(associations)
|
380
370
|
ActiveRecord::Associations::JoinDependency.new(
|
381
|
-
klass, table,
|
371
|
+
klass, table, associations
|
382
372
|
)
|
383
373
|
end
|
384
374
|
|
385
375
|
def apply_join_dependency(eager_loading: group_values.empty?)
|
386
|
-
join_dependency = construct_join_dependency
|
376
|
+
join_dependency = construct_join_dependency(eager_load_values + includes_values)
|
387
377
|
relation = except(:includes, :eager_load, :preload).joins!(join_dependency)
|
388
378
|
|
389
379
|
if eager_loading && !using_limitable_reflections?(join_dependency.reflections)
|
@@ -403,7 +393,7 @@ module ActiveRecord
|
|
403
393
|
|
404
394
|
def limited_ids_for(relation)
|
405
395
|
values = @klass.connection.columns_for_distinct(
|
406
|
-
connection.
|
396
|
+
connection.visitor.compile(arel_attribute(primary_key)),
|
407
397
|
relation.order_values
|
408
398
|
)
|
409
399
|
|
@@ -437,9 +427,6 @@ module ActiveRecord
|
|
437
427
|
else
|
438
428
|
find_some(ids)
|
439
429
|
end
|
440
|
-
rescue ::RangeError
|
441
|
-
error_message = "Couldn't find #{model_name} with an out of range ID"
|
442
|
-
raise RecordNotFound.new(error_message, model_name, primary_key, ids)
|
443
430
|
end
|
444
431
|
|
445
432
|
def find_one(id)
|
@@ -555,8 +542,8 @@ module ActiveRecord
|
|
555
542
|
end
|
556
543
|
|
557
544
|
def ordered_relation
|
558
|
-
if order_values.empty? && primary_key
|
559
|
-
order(arel_attribute(primary_key).asc)
|
545
|
+
if order_values.empty? && (implicit_order_column || primary_key)
|
546
|
+
order(arel_attribute(implicit_order_column || primary_key).asc)
|
560
547
|
else
|
561
548
|
self
|
562
549
|
end
|
@@ -120,9 +120,7 @@ module ActiveRecord
|
|
120
120
|
joins_dependency = other.joins_values.map do |join|
|
121
121
|
case join
|
122
122
|
when Hash, Symbol, Array
|
123
|
-
|
124
|
-
other.klass, other.table, join
|
125
|
-
)
|
123
|
+
other.send(:construct_join_dependency, join)
|
126
124
|
else
|
127
125
|
join
|
128
126
|
end
|
@@ -141,9 +139,7 @@ module ActiveRecord
|
|
141
139
|
joins_dependency = other.left_outer_joins_values.map do |join|
|
142
140
|
case join
|
143
141
|
when Hash, Symbol, Array
|
144
|
-
|
145
|
-
other.klass, other.table, join
|
146
|
-
)
|
142
|
+
other.send(:construct_join_dependency, join)
|
147
143
|
else
|
148
144
|
join
|
149
145
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/array/extract"
|
4
|
+
|
3
5
|
module ActiveRecord
|
4
6
|
class PredicateBuilder
|
5
7
|
class ArrayHandler # :nodoc:
|
@@ -11,8 +13,8 @@ module ActiveRecord
|
|
11
13
|
return attribute.in([]) if value.empty?
|
12
14
|
|
13
15
|
values = value.map { |x| x.is_a?(Base) ? x.id : x }
|
14
|
-
nils
|
15
|
-
ranges
|
16
|
+
nils = values.extract!(&:nil?)
|
17
|
+
ranges = values.extract! { |v| v.is_a?(Range) }
|
16
18
|
|
17
19
|
values_predicate =
|
18
20
|
case values.length
|
@@ -34,8 +36,7 @@ module ActiveRecord
|
|
34
36
|
array_predicates.inject(&:or)
|
35
37
|
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
+
private
|
39
40
|
attr_reader :predicate_builder
|
40
41
|
|
41
42
|
module NullPredicate # :nodoc:
|
@@ -12,12 +12,9 @@ module ActiveRecord
|
|
12
12
|
[associated_table.association_join_foreign_key.to_s => ids]
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
17
|
-
protected
|
15
|
+
private
|
18
16
|
attr_reader :associated_table, :value
|
19
17
|
|
20
|
-
private
|
21
18
|
def ids
|
22
19
|
case value
|
23
20
|
when Relation
|
@@ -17,12 +17,9 @@ module ActiveRecord
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
|
-
# Workaround for Ruby 2.2 "private attribute?" warning.
|
22
|
-
protected
|
20
|
+
private
|
23
21
|
attr_reader :associated_table, :values
|
24
22
|
|
25
|
-
private
|
26
23
|
def type_to_ids_mapping
|
27
24
|
default_hash = Hash.new { |hsh, key| hsh[key] = [] }
|
28
25
|
values.each_with_object(default_hash) do |value, hash|
|
@@ -3,11 +3,7 @@
|
|
3
3
|
module ActiveRecord
|
4
4
|
class PredicateBuilder
|
5
5
|
class RangeHandler # :nodoc:
|
6
|
-
|
7
|
-
def exclude_end?
|
8
|
-
false
|
9
|
-
end
|
10
|
-
end
|
6
|
+
RangeWithBinds = Struct.new(:begin, :end, :exclude_end?)
|
11
7
|
|
12
8
|
def initialize(predicate_builder)
|
13
9
|
@predicate_builder = predicate_builder
|
@@ -16,26 +12,10 @@ module ActiveRecord
|
|
16
12
|
def call(attribute, value)
|
17
13
|
begin_bind = predicate_builder.build_bind_attribute(attribute.name, value.begin)
|
18
14
|
end_bind = predicate_builder.build_bind_attribute(attribute.name, value.end)
|
19
|
-
|
20
|
-
if begin_bind.value.infinity?
|
21
|
-
if end_bind.value.infinity?
|
22
|
-
attribute.not_in([])
|
23
|
-
elsif value.exclude_end?
|
24
|
-
attribute.lt(end_bind)
|
25
|
-
else
|
26
|
-
attribute.lteq(end_bind)
|
27
|
-
end
|
28
|
-
elsif end_bind.value.infinity?
|
29
|
-
attribute.gteq(begin_bind)
|
30
|
-
elsif value.exclude_end?
|
31
|
-
attribute.gteq(begin_bind).and(attribute.lt(end_bind))
|
32
|
-
else
|
33
|
-
attribute.between(RangeWithBinds.new(begin_bind, end_bind))
|
34
|
-
end
|
15
|
+
attribute.between(RangeWithBinds.new(begin_bind, end_bind, value.exclude_end?))
|
35
16
|
end
|
36
17
|
|
37
|
-
|
38
|
-
|
18
|
+
private
|
39
19
|
attr_reader :predicate_builder
|
40
20
|
end
|
41
21
|
end
|
@@ -27,7 +27,7 @@ module ActiveRecord
|
|
27
27
|
key
|
28
28
|
else
|
29
29
|
key = key.to_s
|
30
|
-
key.split("."
|
30
|
+
key.split(".").first if key.include?(".")
|
31
31
|
end
|
32
32
|
end.compact
|
33
33
|
end
|
@@ -62,9 +62,6 @@ module ActiveRecord
|
|
62
62
|
end
|
63
63
|
|
64
64
|
protected
|
65
|
-
|
66
|
-
attr_reader :table
|
67
|
-
|
68
65
|
def expand_from_hash(attributes)
|
69
66
|
return ["1=0"] if attributes.empty?
|
70
67
|
|
@@ -115,6 +112,7 @@ module ActiveRecord
|
|
115
112
|
end
|
116
113
|
|
117
114
|
private
|
115
|
+
attr_reader :table
|
118
116
|
|
119
117
|
def associated_predicate_builder(association_name)
|
120
118
|
self.class.new(table.associated_table(association_name))
|
@@ -122,11 +120,11 @@ module ActiveRecord
|
|
122
120
|
|
123
121
|
def convert_dot_notation_to_hash(attributes)
|
124
122
|
dot_notation = attributes.select do |k, v|
|
125
|
-
k.include?("."
|
123
|
+
k.include?(".") && !v.is_a?(Hash)
|
126
124
|
end
|
127
125
|
|
128
126
|
dot_notation.each_key do |key|
|
129
|
-
table_name, column_name = key.split("."
|
127
|
+
table_name, column_name = key.split(".")
|
130
128
|
value = attributes.delete(key)
|
131
129
|
attributes[table_name] ||= {}
|
132
130
|
|
@@ -18,26 +18,29 @@ module ActiveRecord
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def nil?
|
21
|
-
|
22
|
-
value_before_type_cast.nil? ||
|
23
|
-
|
24
|
-
end
|
21
|
+
!value_before_type_cast.is_a?(StatementCache::Substitute) &&
|
22
|
+
(value_before_type_cast.nil? || value_for_database.nil?)
|
23
|
+
rescue ::RangeError
|
25
24
|
end
|
26
25
|
|
27
|
-
def
|
28
|
-
|
29
|
-
value_for_database unless value_before_type_cast.is_a?(StatementCache::Substitute)
|
30
|
-
@_boundable = true
|
26
|
+
def infinite?
|
27
|
+
infinity?(value_before_type_cast) || infinity?(value_for_database)
|
31
28
|
rescue ::RangeError
|
32
|
-
@_boundable = false
|
33
29
|
end
|
34
30
|
|
35
|
-
def
|
36
|
-
|
31
|
+
def unboundable?
|
32
|
+
if defined?(@_unboundable)
|
33
|
+
@_unboundable
|
34
|
+
else
|
35
|
+
value_for_database
|
36
|
+
@_unboundable = nil
|
37
|
+
end
|
38
|
+
rescue ::RangeError
|
39
|
+
@_unboundable = type.cast(value_before_type_cast) <=> 0
|
37
40
|
end
|
38
41
|
|
39
42
|
private
|
40
|
-
def
|
43
|
+
def infinity?(value)
|
41
44
|
value.respond_to?(:infinite?) && value.infinite?
|
42
45
|
end
|
43
46
|
end
|
@@ -231,7 +231,11 @@ module ActiveRecord
|
|
231
231
|
end
|
232
232
|
|
233
233
|
def _select!(*fields) # :nodoc:
|
234
|
+
fields.reject!(&:blank?)
|
234
235
|
fields.flatten!
|
236
|
+
fields.map! do |field|
|
237
|
+
klass.attribute_alias?(field) ? klass.attribute_alias(field).to_sym : field
|
238
|
+
end
|
235
239
|
self.select_values += fields
|
236
240
|
self
|
237
241
|
end
|
@@ -895,26 +899,28 @@ module ActiveRecord
|
|
895
899
|
self
|
896
900
|
end
|
897
901
|
|
902
|
+
def skip_preloading! # :nodoc:
|
903
|
+
self.skip_preloading_value = true
|
904
|
+
self
|
905
|
+
end
|
906
|
+
|
898
907
|
# Returns the Arel object associated with the relation.
|
899
908
|
def arel(aliases = nil) # :nodoc:
|
900
909
|
@arel ||= build_arel(aliases)
|
901
910
|
end
|
902
911
|
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
protected
|
912
|
+
private
|
913
|
+
# Returns a relation value with a given name
|
914
|
+
def get_value(name)
|
915
|
+
@values.fetch(name, DEFAULT_VALUES[name])
|
916
|
+
end
|
909
917
|
|
910
918
|
# Sets the relation value with the given name
|
911
|
-
def set_value(name, value)
|
919
|
+
def set_value(name, value)
|
912
920
|
assert_mutability!
|
913
921
|
@values[name] = value
|
914
922
|
end
|
915
923
|
|
916
|
-
private
|
917
|
-
|
918
924
|
def assert_mutability!
|
919
925
|
raise ImmutableRelation if @loaded
|
920
926
|
raise ImmutableRelation if defined?(@arel) && @arel
|
@@ -930,7 +936,7 @@ module ActiveRecord
|
|
930
936
|
arel.having(having_clause.ast) unless having_clause.empty?
|
931
937
|
if limit_value
|
932
938
|
limit_attribute = ActiveModel::Attribute.with_cast_value(
|
933
|
-
"LIMIT"
|
939
|
+
"LIMIT",
|
934
940
|
connection.sanitize_limit(limit_value),
|
935
941
|
Type.default_value,
|
936
942
|
)
|
@@ -938,7 +944,7 @@ module ActiveRecord
|
|
938
944
|
end
|
939
945
|
if offset_value
|
940
946
|
offset_attribute = ActiveModel::Attribute.with_cast_value(
|
941
|
-
"OFFSET"
|
947
|
+
"OFFSET",
|
942
948
|
offset_value.to_i,
|
943
949
|
Type.default_value,
|
944
950
|
)
|
@@ -1017,9 +1023,7 @@ module ActiveRecord
|
|
1017
1023
|
join_list = join_nodes + convert_join_strings_to_ast(string_joins)
|
1018
1024
|
alias_tracker = alias_tracker(join_list, aliases)
|
1019
1025
|
|
1020
|
-
join_dependency =
|
1021
|
-
klass, table, association_joins
|
1022
|
-
)
|
1026
|
+
join_dependency = construct_join_dependency(association_joins)
|
1023
1027
|
|
1024
1028
|
joins = join_dependency.join_constraints(stashed_joins, join_type, alias_tracker)
|
1025
1029
|
joins.each { |join| manager.from(join) }
|
@@ -1048,14 +1052,11 @@ module ActiveRecord
|
|
1048
1052
|
|
1049
1053
|
def arel_columns(columns)
|
1050
1054
|
columns.flat_map do |field|
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
when String
|
1057
|
-
arel_column(field, &:itself)
|
1058
|
-
when Proc
|
1055
|
+
if (Symbol === field || String === field) && (klass.has_attribute?(field) || klass.attribute_alias?(field)) && !from_clause.value
|
1056
|
+
arel_attribute(field)
|
1057
|
+
elsif Symbol === field
|
1058
|
+
connection.quote_table_name(field.to_s)
|
1059
|
+
elsif Proc === field
|
1059
1060
|
field.call
|
1060
1061
|
else
|
1061
1062
|
field
|
@@ -1063,21 +1064,6 @@ module ActiveRecord
|
|
1063
1064
|
end
|
1064
1065
|
end
|
1065
1066
|
|
1066
|
-
def arel_column(field)
|
1067
|
-
field = klass.attribute_alias(field) if klass.attribute_alias?(field)
|
1068
|
-
from = from_clause.name || from_clause.value
|
1069
|
-
|
1070
|
-
if klass.columns_hash.key?(field) && (!from || table_name_matches?(from))
|
1071
|
-
arel_attribute(field)
|
1072
|
-
else
|
1073
|
-
yield field
|
1074
|
-
end
|
1075
|
-
end
|
1076
|
-
|
1077
|
-
def table_name_matches?(from)
|
1078
|
-
/(?:\A|(?<!FROM)\s)(?:\b#{table.name}\b|#{connection.quote_table_name(table.name)})(?!\.)/i.match?(from.to_s)
|
1079
|
-
end
|
1080
|
-
|
1081
1067
|
def reverse_sql_order(order_query)
|
1082
1068
|
if order_query.empty?
|
1083
1069
|
return [arel_attribute(primary_key).desc] if primary_key
|
@@ -1144,9 +1130,9 @@ module ActiveRecord
|
|
1144
1130
|
end
|
1145
1131
|
order_args.flatten!
|
1146
1132
|
|
1147
|
-
@klass.
|
1133
|
+
@klass.disallow_raw_sql!(
|
1148
1134
|
order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a },
|
1149
|
-
|
1135
|
+
permit: AttributeMethods::ClassMethods::COLUMN_NAME_WITH_ORDER
|
1150
1136
|
)
|
1151
1137
|
|
1152
1138
|
validate_order_args(order_args)
|
@@ -1159,14 +1145,14 @@ module ActiveRecord
|
|
1159
1145
|
order_args.map! do |arg|
|
1160
1146
|
case arg
|
1161
1147
|
when Symbol
|
1162
|
-
|
1148
|
+
arel_attribute(arg).asc
|
1163
1149
|
when Hash
|
1164
1150
|
arg.map { |field, dir|
|
1165
1151
|
case field
|
1166
1152
|
when Arel::Nodes::SqlLiteral
|
1167
1153
|
field.send(dir.downcase)
|
1168
1154
|
else
|
1169
|
-
|
1155
|
+
arel_attribute(field).send(dir.downcase)
|
1170
1156
|
end
|
1171
1157
|
}
|
1172
1158
|
else
|
@@ -1175,16 +1161,6 @@ module ActiveRecord
|
|
1175
1161
|
end.flatten!
|
1176
1162
|
end
|
1177
1163
|
|
1178
|
-
def order_column(field)
|
1179
|
-
arel_column(field) do |attr_name|
|
1180
|
-
if attr_name == "count" && !group_values.empty?
|
1181
|
-
arel_attribute(attr_name)
|
1182
|
-
else
|
1183
|
-
Arel.sql(connection.quote_table_name(attr_name))
|
1184
|
-
end
|
1185
|
-
end
|
1186
|
-
end
|
1187
|
-
|
1188
1164
|
# Checks to make sure that the arguments are not blank. Note that if some
|
1189
1165
|
# blank-like object were initially passed into the query method, then this
|
1190
1166
|
# method will not raise an error.
|
@@ -1209,8 +1185,9 @@ module ActiveRecord
|
|
1209
1185
|
|
1210
1186
|
STRUCTURAL_OR_METHODS = Relation::VALUE_METHODS - [:extending, :where, :having, :unscope, :references]
|
1211
1187
|
def structurally_incompatible_values_for_or(other)
|
1188
|
+
values = other.values
|
1212
1189
|
STRUCTURAL_OR_METHODS.reject do |method|
|
1213
|
-
get_value(method) ==
|
1190
|
+
get_value(method) == values.fetch(method, DEFAULT_VALUES[method])
|
1214
1191
|
end
|
1215
1192
|
end
|
1216
1193
|
|
@@ -125,6 +125,10 @@ module ActiveRecord
|
|
125
125
|
raise ArgumentError, "Invalid argument for .where.not(), got nil."
|
126
126
|
when Arel::Nodes::In
|
127
127
|
Arel::Nodes::NotIn.new(node.left, node.right)
|
128
|
+
when Arel::Nodes::IsNotDistinctFrom
|
129
|
+
Arel::Nodes::IsDistinctFrom.new(node.left, node.right)
|
130
|
+
when Arel::Nodes::IsDistinctFrom
|
131
|
+
Arel::Nodes::IsNotDistinctFrom.new(node.left, node.right)
|
128
132
|
when Arel::Nodes::Equality
|
129
133
|
Arel::Nodes::NotEqual.new(node.left, node.right)
|
130
134
|
when String
|