aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation
Commit message (Collapse)AuthorAgeFilesLines
* Fix `relation.exists?` with giving both `distinct` and `offset`Ryuta Kamizono2019-02-081-4/+8
| | | | | | | | | | | The `distinct` affects (reduces) rows of the result, so it is important part when both `distinct` and `offset` are given. Replacing SELECT clause to `1 AS one` and removing `distinct` and `order` is just optimization for the `exists?`, we should not apply the optimization for that case. Fixes #35191.
* Refactor around scopingRyuta Kamizono2019-02-071-1/+1
| | | | | | Don't use `false` as special value to skip to find inherited scope, we could use `skip_inherited_scope = true`, and move `_scoping` back on Relation.
* Relation no longer respond to Arel methodsRyuta Kamizono2019-02-061-1/+1
| | | | This follows up d97980a16d76ad190042b4d8578109714e9c53d0.
* Chaining named scope is no longer leaking to class level querying methodsRyuta Kamizono2019-02-061-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Active Record uses `scoping` to delegate to named scopes from relations for propagating the chaining source scope. It was needed to restore the source scope in named scopes, but it was caused undesired behavior that pollute all class level querying methods. Example: ```ruby class Topic < ActiveRecord::Base scope :toplevel, -> { where(parent_id: nil) } scope :children, -> { where.not(parent_id: nil) } scope :has_children, -> { where(id: Topic.children.select(:parent_id)) } end # Works as expected. Topic.toplevel.where(id: Topic.children.select(:parent_id)) # Doesn't work due to leaking `toplevel` to `Topic.children`. Topic.toplevel.has_children ``` Since #29301, the receiver in named scopes has changed from the model class to the chaining source scope, so the polluting class level querying methods is no longer required for that purpose. Fixes #14003.
* activerecord: Fix statement cache for strictly cast attributesDylan Thacker-Smith2019-01-231-1/+1
|
* activerecord: Fix where nil condition on composed_of attributeDylan Thacker-Smith2019-01-181-4/+5
|
* All of queries should return correct result even if including large numberRyuta Kamizono2019-01-181-10/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently several queries cannot return correct result due to incorrect `RangeError` handling. First example: ```ruby assert_equal true, Topic.where(id: [1, 9223372036854775808]).exists? assert_equal true, Topic.where.not(id: 9223372036854775808).exists? ``` The first example is obviously to be true, but currently it returns false. Second example: ```ruby assert_equal topics(:first), Topic.where(id: 1..9223372036854775808).find(1) ``` The second example also should return the object, but currently it raises `RecordNotFound`. It can be seen from the examples, the queries including large number assuming empty result is not always correct. Therefore, This change handles `RangeError` to generate executable SQL instead of raising `RangeError` to users to always return correct result. By this change, it is no longer raised `RangeError` to users.
* Use `unboundable?` rather than `boundable?`Ryuta Kamizono2019-01-181-7/+12
| | | | | | | | | | | | | | | | | | The `unboundable?` behaves like the `infinite?`. ```ruby inf = Topic.predicate_builder.build_bind_attribute(:id, Float::INFINITY) inf.infinite? # => 1 oob = Topic.predicate_builder.build_bind_attribute(:id, 9999999999999999999999999999999) oob.unboundable? # => 1 inf = Topic.predicate_builder.build_bind_attribute(:id, -Float::INFINITY) inf.infinite? # => -1 oob = Topic.predicate_builder.build_bind_attribute(:id, -9999999999999999999999999999999) oob.unboundable? # => -1 ```
* Merge pull request #34963 from ↵Rafael França2019-01-171-8/+12
|\ | | | | | | | | dylanahsmith/better-composed-of-single-field-query activerecord: Use a simpler query condition for aggregates with one mapping
| * Use public_send instead since respond_to? doesn't include private/protected ↵Ryuta Kamizono2019-01-171-1/+1
| | | | | | | | | | methods by default Co-Authored-By: dylanahsmith <dylan.smith@shopify.com>
| * Avoid using yield_self to make it easier to backportDylan Thacker-Smith2019-01-171-5/+4
| |
| * activerecord: Use a simpler query condition for aggregates with one mappingDylan Thacker-Smith2019-01-171-8/+13
| |
* | Do not allow passing the column name to `sum` when a block is passedRafael Mendonça França2019-01-171-6/+4
| |
* | Do not allow passing the column name to `count` when a block is passedRafael Mendonça França2019-01-171-6/+4
| |
* | Remove delegation of missing methods in a relation to arelRafael Mendonça França2019-01-171-4/+0
| |
* | Remove delegation of missing methods in a relation to private methods of the ↵Rafael Mendonça França2019-01-171-5/+0
|/ | | | class
* Merge branch 'master' into ac_params_existsAaron Patterson2019-01-112-24/+5
|\
| * Consolidate the duplicated code that building range predicateRyuta Kamizono2019-01-082-24/+5
| | | | | | | | | | This slightly change the code in the Arel to allow +/-INFINITY as open ended since the Active Record expects that behavior. See 5ecbeda.
* | Allow strong params in ActiveRecord::Base#exists?Gannon McGibbon2019-01-071-0/+2
|/ | | | | Allow `ActionController::Params` as argument of `ActiveRecord::Base#exists?`
* Make average compatible accross Ruby versionsAlberto Almagro2019-01-041-1/+1
| | | | | | | Since Ruby 2.6.0 NilClass#to_d is returning `BigDecimal` 0.0, this breaks `average` compatibility with prior Ruby versions. This patch makes `average` return `nil` in all Ruby versions when there are no rows.
* Fix TypeError: no implicit conversion of Arel::Attributes::Attribute into ↵Ryuta Kamizono2019-01-021-1/+1
| | | | | | | | | | | | | String properly This reverts 27c6c07 since `arel_attr.to_s` is not right way to avoid the type error. That to_s returns `"#<struct Arel::Attributes::Attribute ...>"`, there is no reason to match the regex to the inspect form. And also, the regex path is not covered by our test cases. I've tweaked the regex for redundant part and added assertions for the regex path.
* Module#{define_method,alias_method,undef_method,remove_method} become public ↵Ryuta Kamizono2018-12-211-1/+1
| | | | | | since Ruby 2.5 https://bugs.ruby-lang.org/issues/14133
* Fix the scoping with query methods in the scope blockRyuta Kamizono2018-11-301-1/+1
| | | | | | | | | Follow up #33394. #33394 only fixes the case of scoping with klass methods in the scope block which invokes `klass.all`. Query methods in the scope block also need to invoke `klass.all` to be affected by the scoping.
* Make implicit order column configurableTekin Suleyman2018-11-261-2/+2
| | | | | | | | | | | | | | When calling ordered finder methods such as +first+ or +last+ without an explicit order clause, ActiveRecord sorts records by primary key. This can result in unpredictable and surprising behaviour when the primary key is not an auto-incrementing integer, for example when it's a UUID. This change makes it possible to override the column used for implicit ordering such that +first+ and +last+ will return more predictable results. For Example: class Project < ActiveRecord::Base self.implicit_order_column = "created_at" end
* Arel: Implemented DB-aware NULL-safe comparison (#34451)Dmytro Shteflyuk2018-11-151-0/+4
| | | | | | | | | * Arel: Implemented DB-aware NULL-safe comparison * Fixed where clause inversion for NULL-safe comparison * Renaming "null_safe_eq" to "is_not_distinct_from", "null_safe_not_eq" to "is_distinct_from" [Dmytro Shteflyuk + Rafael Mendonça França]
* Ignore empty condition on #construct_relation_for_existsr7kamura2018-10-271-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | At https://github.com/rails/rails/commit/fc0e3354af7e7878bdd905a95ce4c1491113af9a, ```rb relation = relation.where(conditions) ``` was rewritten to: ```rb relation.where!(condition) ``` This change accidentally changed the result of `Topic.exists?({})` from true to false. To fix this regression, first I moved the blank check logic (`opts.blank?`) from `#where` to `#where!`, because I thought `#where!` should be identical to `#where`, except that instead of returning a new relation, it adds the condition to the existing relation. But on second thought after some discussion on https://github.com/rails/rails/pull/34329, I started to think that just fixing `#construct_relation_for_exists` is more preferable than changing `#where` and `#where!`.
* Lazy checking whether or not values in IN clause are boundableRyuta Kamizono2018-10-241-3/+2
| | | | | | | | | | | | | Since #33844, eager loading/preloading with too many and/or too large ids won't be broken by pre-checking whether the value is constructable or not. But the pre-checking caused the type to be evaluated at relation build time instead of at the query execution time, that is breaking an expectation for some apps. I've made the pre-cheking lazy as much as possible, that is no longer happend at relation build time.
* Don't expose internal `get_value`/`set_value` methodsRyuta Kamizono2018-10-181-10/+8
|
* Generate delegation methods to named scope in the definition timeRyuta Kamizono2018-10-091-0/+30
| | | | | | | | | | | | | | | | | | | The delegation methods to named scope are defined when `method_missing` is invoked on the relation. Since #29301, the receiver in the named scope is changed to the relation like others (e.g. `default_scope`, etc) for consistency. Most named scopes would be delegated from relation by `method_missing`, since we don't allow scopes to be defined which conflict with instance methods on `Relation` (#31179). But if a named scope is defined with the same name as any method on the `superclass` (e.g. `Kernel.open`), the `method_missing` on the relation is not invoked. To address the issue, make the delegation methods to named scope is generated in the definition time. Fixes #34098.
* Add `Style/RedundantFreeze` to remove redudant `.freeze`Yasuo Honda2018-09-293-6/+6
| | | | | | | | | | | | | | | | | | | | | Since Rails 6.0 will support Ruby 2.4.1 or higher `# frozen_string_literal: true` magic comment is enough to make string object frozen. This magic comment is enabled by `Style/FrozenStringLiteralComment` cop. * Exclude these files not to auto correct false positive `Regexp#freeze` - 'actionpack/lib/action_dispatch/journey/router/utils.rb' - 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb' It has been fixed by https://github.com/rubocop-hq/rubocop/pull/6333 Once the newer version of RuboCop released and available at Code Climate these exclude entries should be removed. * Replace `String#freeze` with `String#-@` manually if explicit frozen string objects are required - 'actionpack/test/controller/test_case_test.rb' - 'activemodel/test/cases/type/string_test.rb' - 'activesupport/lib/active_support/core_ext/string/strip.rb' - 'activesupport/test/core_ext/string_ext_test.rb' - 'railties/test/generators/actions_test.rb'
* Bugfix ActiveRecord::Relation#merge special case of from clauseBogdan Gusiev2018-09-281-3/+6
| | | | | When one relation is merged into another that has a different base class merging `from_clause` causes invalid SQL to be generated
* Enable `Performance/UnfreezeString` copyuuji.yaginuma2018-09-231-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In Ruby 2.3 or later, `String#+@` is available and `+@` is faster than `dup`. ```ruby # frozen_string_literal: true require "bundler/inline" gemfile(true) do source "https://rubygems.org" gem "benchmark-ips" end Benchmark.ips do |x| x.report('+@') { +"" } x.report('dup') { "".dup } x.compare! end ``` ``` $ ruby -v benchmark.rb ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux] Warming up -------------------------------------- +@ 282.289k i/100ms dup 187.638k i/100ms Calculating ------------------------------------- +@ 6.775M (± 3.6%) i/s - 33.875M in 5.006253s dup 3.320M (± 2.2%) i/s - 16.700M in 5.032125s Comparison: +@: 6775299.3 i/s dup: 3320400.7 i/s - 2.04x slower ```
* Don't return the same object when using find with an empty arrayRafael Mendonça França2018-09-191-1/+1
| | | | | | When you pass an empty array to find we know we shoudl return an empty array but it is surprising that we are returning the original empty array instead of a new one.
* Fallback to unprepared statement only when bind params limit is exceededRyuta Kamizono2018-09-142-7/+3
| | | | | | | | | | | This is a follow up and/or an alternative of #33844. Unlike #33844, this would attempt to construct unprepared statement only when bind params limit (mysql2 65535, pg 65535, sqlite3 249999) is exceeded. I only defined 65535 as the limit, not defined 249999 for sqlite3, since it is an edge case, I'm not excited to add less worth extra code.
* Eager loading/preloading should be worked regardless of large number of recordsRyuta Kamizono2018-09-122-5/+10
| | | | | | | | | | | | | | | | Since 213796f, bind params are used for IN clause if enabled prepared statements. Unfortunately, most adapter modules have a limitation for # of bind params (mysql2 65535, pg 65535, sqlite3 250000). So if eager loading large number of records at once, that query couldn't be sent to the database. Since eager loading/preloading queries are auto-generated by Active Record itself, so it should be worked regardless of large number of records like as before. Fixes #33702.
* Use `visitor.compile` instead of constructing by connection itselfRyuta Kamizono2018-09-091-1/+1
|
* Permit list usage cleanup and clearer documentationKevin Deisz2018-08-272-3/+3
|
* Convert over the rest of the whitelist referencesKevin Deisz2018-08-242-3/+3
|
* Fix merging relation that order including `?`Ryuta Kamizono2018-08-211-2/+2
| | | | | | | | | | | | | | | The `Relation::Merger` has a problem that order values would be merged as nested array. That was caused an issue #33664 since if array value is passed to `order` and first element in the array includes `?`, the array is regarded as a prepared statement and bind variables. https://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html#method-i-sanitize_sql_for_order Just merging that as splat args like other values would fix the issue. Fixes #33664.
* Use `Array#extract!` where possiblebogdanvlviv2018-08-141-2/+4
|
* Revert "Merge pull request #24131 from brchristian/limit_and_primary_key"Ryuta Kamizono2018-08-011-1/+1
| | | | | | | | | | This reverts commit d162188dd662a7d9f62ba8431474f50bc35e3e93, reversing changes made to 3576782888c307e3e192c44e332b957cd1174128. Reason: #24131 conflicts the #5153's default order contract, it means that existing apps would be broken by that change. We don't want to break existing apps without a deprecation cycle.
* Extract `Relation#bind_attribute` for internal useRyuta Kamizono2018-07-301-8/+5
| | | | To make it easier to construct boundable predicate.
* Fix TypeError: no implicit conversion of Arel::Attributes::Attribute into StringBart de Water2018-07-281-1/+1
|
* Enable Start/EndWith and RegexpMatch copsBart de Water2018-07-281-1/+1
| | | | | In cases where the MatchData object is not used, this provides a speed-up: https://github.com/JuanitoFatas/fast-ruby/#stringmatch-vs-stringmatch-vs-stringstart_withstringend_with-code-start-code-end
* don't impose primary key order if limit() is definedBrian Christian2018-07-191-1/+1
|
* Revert "Short circuit the scoping delegation for `relation.all`"Ryuta Kamizono2018-07-191-1/+0
| | | | | | | This reverts commit eb807384c81a6e086b17a576755e992e6c4c685e. If the current scope is affected by the `unscoped` block, `all` won't be the same with `spawn`.
* Use `construct_join_dependency` in all placesRyuta Kamizono2018-07-033-13/+6
|
* Ensure to calculate column aliases after all table aliases are constructedRyuta Kamizono2018-06-193-16/+12
| | | | | | | | | | | | | | | | | Currently, column aliases which is used for eager loading are calculated before constructing all table aliases in FROM clause. `JoinDependency#join_constraints` constructs table aliases for `joins` first, and then always re-constructs table aliases for eager loading. If both `joins` and eager loading are given a same table association, the re-construction would cause the discrepancy between column aliases and table aliases. To avoid the discrepancy, the column aliases should be calculated after all table aliases are constructed. Fixes #30603.
* Fix GROUP BY queries to apply LIMIT/OFFSET after aggregationsRyuta Kamizono2018-06-071-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If `eager_loading` is true, `apply_join_dependency` force applies LIMIT/OFFSET before JOINs by `limited_ids_for` to keep parent records count. But for aggregation queries, LIMIT/OFFSET should be applied after aggregations the same as SQL semantics. And also, we could not replace SELECT list by `limited_ids_for` when a query has a GROUP BY clause. It had never been worked since it will causes generating invalid SQL for MySQL, PostgreSQL, and probably most backends. ``` % ARCONN=postgresql be ruby -w -Itest test/cases/calculations_test.rb -n test_group_by_with_limit Using postgresql Run options: -n test_group_by_with_limit --seed 20925 # Running: E Error: CalculationsTest#test_group_by_with_limit: ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "posts.id" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: SELECT DISTINCT "posts"."id", "posts"."type" AS alias_0 FRO... ^ : SELECT DISTINCT "posts"."id", "posts"."type" AS alias_0 FROM "posts" LEFT OUTER JOIN "comments" ON "comments"."post_id" = "posts"."id" GROUP BY "posts"."type" ORDER BY "posts"."type" ASC LIMIT $1 ``` Fixes #8103. Closes #27249.
* Fix force equality checking not to break the serialized attribute with ArrayRyuta Kamizono2018-06-061-1/+0
| | | | Context: https://github.com/rails/rails/commit/43ef00e5d7a55ad79bc840276d33cb70f1f5dde5#commitcomment-29256140