1. 24 8月, 2020 2 次提交
  2. 07 8月, 2020 1 次提交
  3. 25 7月, 2020 3 次提交
  4. 23 7月, 2020 1 次提交
  5. 19 7月, 2020 1 次提交
    • R
      Move Arel attribute normalization into `arel_table` · 1ac40f16
      Ryuta Kamizono 提交于
      In Active Record internal, `arel_table` is not directly used but
      `arel_attribute` is used, since `arel_table` doesn't normalize an
      attribute name as a string, and doesn't resolve attribute aliases.
      
      For the above reason, `arel_attribute` should be used rather than
      `arel_table`, but most people directly use `arel_table`, both
      `arel_table` and `arel_attribute` are private API though.
      
      Although I'd not recommend using private API, `arel_table` is actually
      widely used, and it is also problematic for unscopeable queries and
      hash-like relation merging friendly, as I explained at #39863.
      
      To resolve the issue, this change moves Arel attribute normalization
      (attribute name as a string, and attribute alias resolution) into
      `arel_table`.
      1ac40f16
  6. 17 7月, 2020 1 次提交
  7. 14 7月, 2020 1 次提交
  8. 06 7月, 2020 2 次提交
    • R
      Consolidate stringify keys in `PredicateBuilder` · 8714b359
      Ryuta Kamizono 提交于
      `PredicateBuilder.references` and `PredicateBuilder#build_from_hash`
      does similar processing and both requires stringify keys for passed hash
      argument. This consolidates stringify keys to avoid extra string
      allocation in `PredicateBuilder`.
      8714b359
    • R
      Support `where` with comparison operators (`>`, `>=`, `<`, and `<=`) · 6d6ec6f9
      Ryuta Kamizono 提交于
      ```ruby
      posts = Post.order(:id)
      
      posts.where("id >": 9).pluck(:id)  # => [10, 11]
      posts.where("id >=": 9).pluck(:id) # => [9, 10, 11]
      posts.where("id <": 3).pluck(:id)  # => [1, 2]
      posts.where("id <=": 3).pluck(:id) # => [1, 2, 3]
      ```
      
      From type casting and table/column name resolution's point of view,
      `where("create_at >=": time)` is better alternative than `where("create_at >= ?", time)`.
      
      ```ruby
      class Post < ActiveRecord::Base
        attribute :created_at, :datetime, precision: 3
      end
      
      time = Time.now.utc # => 2020-06-24 10:11:12.123456 UTC
      
      Post.create!(created_at: time) # => #<Post id: 1, created_at: "2020-06-24 10:11:12.123000">
      
      # SELECT `posts`.* FROM `posts` WHERE (created_at >= '2020-06-24 10:11:12.123456')
      Post.where("created_at >= ?", time) # => []
      
      # SELECT `posts`.* FROM `posts` WHERE `posts`.`created_at` >= '2020-06-24 10:11:12.123000'
      Post.where("created_at >=": time) # => [#<Post id: 1, created_at: "2020-06-24 10:11:12.123000">]
      ```
      6d6ec6f9
  9. 21 6月, 2020 1 次提交
  10. 20 6月, 2020 1 次提交
  11. 17 6月, 2020 1 次提交
    • R
      Make `where_sql` more few code · b1646a48
      Ryuta Kamizono 提交于
      To be honest, it is hardly worth having a dedicated method for
      `where_sql`, since it is a reduced version of `to_sql`.
      
      I've left it for now, but just made it more few code (used `to_sql`).
      b1646a48
  12. 15 6月, 2020 1 次提交
    • R
      Allow difference for `and`/`or` unless other values are set explicitly · 0ea798a4
      Ryuta Kamizono 提交于
      I often hit the inconvenience (recently in #39558).
      
      `and`/`or` are focused to combine where-like clauses, so we often use
      one-time relation which has only where clause. But if the receiver has
      values other than where clause (e.g. `order`, `select`, `includes`,
      etc), `and`/`or` will raise structurally incompatible error.
      
      Since it is harder to predict the receiver has which values other than
      where clause before doing `and`/`or`, that restriction is a little
      annoying to me.
      
      So I'd like to relax that restriction, at least unless other values are
      set explicitly for multiple values.
      0ea798a4
  13. 14 6月, 2020 2 次提交
  14. 13 6月, 2020 1 次提交
    • R
      Backward compatibility to work `Marshal.load(legacy_relation.dump)` · 34d0836f
      Ryuta Kamizono 提交于
      A relation has a predicate builder, so if a predicate handler which is
      referenced by a legacy predicate builder is removed in the new code,
      `Marshal.load(legacy_relation.dump)` will fail due to referencing
      undefined constant.
      
      I've restored no-op `BaseHandler` constant alias to make cache rotation
      easier during Rails 6.1.
      
      Fixes #39601.
      34d0836f
  15. 08 6月, 2020 1 次提交
  16. 07 6月, 2020 3 次提交
    • R
      Support `relation.and` for intersection as Set theory · 7219eb2c
      Ryuta Kamizono 提交于
      As described at #39328, `relation.merge` behaves inspired as Hash-like
      merge for where clause. In other words, currently there is no official
      way to intersect the result by both relation conditions (i.e. there is
      no official way to maintain both relation conditions).
      
      To resolve that issue, I'd like to support a way to intersect relations
      as `relation.and`.
      
      ```ruby
      david_and_mary = Author.where(id: [david, mary])
      mary_and_bob   = Author.where(id: [mary, bob]) # => [bob]
      
      david_and_mary.merge(mary_and_bob) # => [mary, bob]
      
      david_and_mary.and(mary_and_bob) # => [mary]
      david_and_mary.or(mary_and_bob)  # => [david, mary, bob]
      ```
      
      Fixes #39232.
      7219eb2c
    • R
      Make predicate builder about 2x faster · a1d236e9
      Ryuta Kamizono 提交于
      Extra predicate handler for just one line preprocess is too expensive.
      
      ```ruby
      ActiveRecord::Schema.define do
        create_table :users, force: true do |t|
        end
      end
      
      class User < ActiveRecord::Base
      end
      
      predicate_builder = User.predicate_builder
      
      attr = User.arel_attribute(:id)
      user = User.create!
      user_id = user.id
      
      Benchmark.ips do |x|
        x.report("build:user") { predicate_builder.build(attr, user) }
        x.report("build:user_id") { predicate_builder.build(attr, user_id) }
      end
      ```
      
      Before:
      
      ```
      Warming up --------------------------------------
                build:user    11.626k i/100ms
             build:user_id    23.314k i/100ms
      Calculating -------------------------------------
                build:user    114.151k (± 2.0%) i/s -    581.300k in   5.094468s
             build:user_id    226.420k (± 2.3%) i/s -      1.142M in   5.048205s
      ```
      
      After:
      
      ```
      Warming up --------------------------------------
                build:user    21.484k i/100ms
             build:user_id    24.307k i/100ms
      Calculating -------------------------------------
                build:user    210.207k (± 1.8%) i/s -      1.053M in   5.009623s
             build:user_id    238.276k (± 2.1%) i/s -      1.215M in   5.102951s
      ```
      a1d236e9
    • R
      Deprecate inconsistent behavior that merging conditions on the same column · 930bfb93
      Ryuta Kamizono 提交于
      Related to #39250 and #39236.
      
      The purpose of the change here is to unify inconsistent behavior on the
      merging.
      
      For now, mergee side condition is replaced by merger side condition only
      if both arel nodes are Equality or In clauses.
      
      In other words, if mergee side condition is not Equality or In clauses
      (e.g. `between`, `or`, `gt`, `lt`, etc), those conditions will be kept
      even on the same column.
      
      This behavior is harder to predict unless people are familiar with the
      merging behavior.
      
      Originally I suppose this behavior is just an implementation issue
      rather than an intended one, since `unscope` and `rewhere`, which were
      introduced later than `merge`, works more consistently.
      
      Since most of the conditions are usually Equality and In clauses, I
      don't suppose most people have encountered this merging issue, but I'd
      like to deprecate the inconsistent behavior and will completely unify
      that to improve a future UX.
      
      ```ruby
      # Rails 6.1 (IN clause is replaced by merger side equality condition)
      Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
      
      # Rails 6.1 (both conflict conditions exists, deprecated)
      Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => []
      
      # Rails 6.1 with rewhere to migrate to Rails 6.2's behavior
      Author.where(id: david.id..mary.id).merge(Author.where(id: bob), rewhere: true) # => [bob]
      
      # Rails 6.2 (same behavior with IN clause, mergee side condition is consistently replaced)
      Author.where(id: [david.id, mary.id]).merge(Author.where(id: bob)) # => [bob]
      Author.where(id: david.id..mary.id).merge(Author.where(id: bob)) # => [bob]
      ```
      930bfb93
  17. 03 6月, 2020 1 次提交
    • R
      Ensure column names on reflection as a string · c0750fe2
      Ryuta Kamizono 提交于
      If association column names are defined as a symbol, association access
      will cause `Symbol#to_s` each time since attributes and columns hash
      keys are a string.
      
      To avoid that extra `Symbol#to_s` allocation, ensure column names on
      reflection as a string.
      c0750fe2
  18. 29 5月, 2020 4 次提交
  19. 28 5月, 2020 1 次提交
  20. 27 5月, 2020 1 次提交
  21. 25 5月, 2020 1 次提交
  22. 24 5月, 2020 5 次提交
  23. 22 5月, 2020 1 次提交
  24. 20 5月, 2020 2 次提交
  25. 19 5月, 2020 1 次提交