1. 10 5月, 2020 1 次提交
  2. 07 5月, 2020 2 次提交
    • R
      Fix the result of aggregations to maintain duplicated "group by" fields · 82b66fe4
      Ryuta Kamizono 提交于
      Actually that result is odd and hard to predictable result to me, but we
      should not change the public behavior without deprecation cycle.
      
      I had not intended to break any apps, so I've restored the behavior.
      
      Fixes #39171.
      82b66fe4
    • R
      Allow `unscope` to be aware of table name qualified values · 5136277f
      Ryuta Kamizono 提交于
      It is possible to unscope only the column in the specified table.
      
      ```ruby
      posts = Post.joins(:comments).group(:"posts.hidden")
      posts = posts.where("posts.hidden": false, "comments.hidden": false)
      
      posts.count
      # => { false => 10 }
      
      # unscope both hidden columns
      posts.unscope(where: :hidden).count
      # => { false => 11, true => 1 }
      
      # unscope only comments.hidden column
      posts.unscope(where: :"comments.hidden").count
      # => { false => 11 }
      ```
      Co-authored-by: NSlava Korolev <korolvs@gmail.com>
      5136277f
  3. 05 5月, 2020 1 次提交
    • R
      Fix `rewhere` to truly overwrite collided where clause by new where clause · 6187b713
      Ryuta Kamizono 提交于
      ```ruby
      steve = Person.find_by(name: "Steve")
      david = Author.find_by(name: "David")
      
      relation = Essay.where(writer: steve)
      
      # Before
      relation.rewhere(writer: david).to_a # => []
      
      # After
      relation.rewhere(writer: david).to_a # => [david]
      ```
      
      For now `rewhere` only works for truly column names, doesn't work for
      alias attributes, nested conditions, associations.
      
      To fix that, need to build new where clause first, and then get
      attribute names from new where clause.
      6187b713
  4. 03 5月, 2020 1 次提交
  5. 23 4月, 2020 1 次提交
    • G
      Fix typos [ci skip] · 1064c516
      Godfrey Chan 提交于
      I wrote this shell script to find words from the Rails repo,
      so I can paste them into https://www.horsepaste.com/ for
      the [codenames game](https://en.m.wikipedia.org/wiki/Codenames_(board_game)).
      
      ```bash
      git grep -Il '' | \
        grep -v -E "CHANGELOG|Gemfile|gemspec|package\.json|yarn\.lock" | \
        xargs cat | \
        sed '/[^ ]\{10,\}/d' | \
        sed 's/\([A-Z]\)/ \1/g' | \
        tr 'A-Z' 'a-z' | \
        tr -c -s 'a-z' '\n' | \
        sed '/^.\{0,3\}$/d' | \
        sort | \
        uniq | \
        tr '\n' ',' | \
        pbcopy
      ```
      
      You can see the result in https://www.horsepaste.com/rails-fixed.
      Click "Next game" to cycle the words.
      
      Found some typos in the codebase from this 😂
      
      This is how I generated the list of possible typos:
      
      ```bash
      git grep -Il '' | \
        grep -v -E "CHANGELOG|Gemfile|gemspec|package\.json|yarn\.lock" | \
        xargs cat | \
        sed '/[^ ]\{10,\}/d' | \
        sed 's/\([A-Z]\)/ \1/g' | \
        tr 'A-Z' 'a-z' | \
        tr -c -s 'a-z' '\n' | \
        sed '/^.\{0,3\}$/d' | \
        sort | \
        uniq | \
        aspell --ignore-case list
      ```
      
      I manually reviewed the list and made the corrections
      in this commit. The rest on the list are either:
      
      * Bugs in my script: it split things like "doesn't" into
        "doesn" and "t", if find things like `#ffffff` and
        extracts "ffffff" as a word, etc
      * British spelling: honour, optimised
      * Foreign words: bonjour, espanol
      * Names: nginx, hanekawa
      * Technical words: mutex, xhtml
      * Portmanteau words: autosave, nodelist
      * Invented words: camelize, coachee
      * Shortened words: attrs, repo
      * Deliberate typos: hllo, hillo (used in code examples, etc)
      * Lorem ipsum words: arcu, euismod
      
      This is the [output](https://gist.github.com/chancancode/eb0b573d667dc31906f33f1fb0b22313)
      of the script *after* fixing the typos included in this
      commit. In theory, someone can run that command again in
      the future and compare the output to catch new typos (i.e.
      using my list to filter out known typos).
      
      Limitations: the aspell dictionary could be wrong, I
      could have miss things, and my script ignores words that
      are less than 3 characters or longer than 10 characters.
      1064c516
  6. 05 3月, 2020 1 次提交
  7. 21 2月, 2020 1 次提交
  8. 20 2月, 2020 1 次提交
  9. 07 2月, 2020 1 次提交
  10. 29 1月, 2020 1 次提交
  11. 14 1月, 2020 2 次提交
  12. 11 1月, 2020 1 次提交
  13. 04 1月, 2020 1 次提交
    • S
      Avoid assigning duplicate values in QueryMethods · aca85f62
      sinsoku 提交于
      The ArgumentError occurs even though structures is compatible.
      Because some query methods keep duplicate values.
      
      For example, the behavior of `joins` method is as following:
      
      ```ruby
      relation = Post.joins(:author).joins(:author)
      relation.joins_values
      #=> [:author, :author]
      relation.or(Post.joins(:author))
      #=> ArgumentError: Relation passed to #or must be structurally compatible. Incompatible values: [:joins]
      ```
      
      This commit changes to not keep duplicate values.
      
      Fixes #38052
      aca85f62
  14. 17 12月, 2019 1 次提交
  15. 13 12月, 2019 1 次提交
    • R
      Generate 45% faster query methods · 58df9a45
      Ryuta Kamizono 提交于
      `DEFAULT_VALUES` access is a bit slower, avoiding that makes about 45%
      faster query methods.
      
      https://gist.github.com/kamipo/e64439f7a206e1c5b5c69d92d982828e
      
      Before (ff299f17):
      
      ```
      Warming up --------------------------------------
              #limit_value   263.800k i/100ms
          #limit_value = 1   241.758k i/100ms
      Calculating -------------------------------------
              #limit_value      7.044M (± 1.5%) i/s -     35.349M in   5.019511s
          #limit_value = 1      6.044M (± 2.3%) i/s -     30.220M in   5.003292s
      ```
      
      After (this change):
      
      ```
      Warming up --------------------------------------
              #limit_value   246.295k i/100ms
          #limit_value = 1   244.398k i/100ms
      Calculating -------------------------------------
              #limit_value     10.303M (± 2.1%) i/s -     51.722M in   5.022568s
          #limit_value = 1      6.021M (± 6.1%) i/s -     30.061M in   5.015545s
      ```
      58df9a45
  16. 31 10月, 2019 2 次提交
  17. 11 10月, 2019 1 次提交
  18. 18 9月, 2019 1 次提交
    • R
      Maintain eager loading joining order as before · 783cafee
      Ryuta Kamizono 提交于
      If a relation has eager_load and string joins only, string joins will be
      regarded as leading joins unlike before, due to #36805.
      
      To maintain that joining order as before, check eager loading join
      first before string joins.
      
      Fixes #37133.
      783cafee
  19. 08 8月, 2019 1 次提交
  20. 02 8月, 2019 1 次提交
    • R
      Deduplicate joins values · e6f953fc
      Ryuta Kamizono 提交于
      #36805 have one possible regression that failing deduplication if
      `joins_values` have complex order (e.g. `joins_values = [join_node_a,
      :comments, :tags, join_node_a]`).
      
      This fixes the deduplication to take it in the first phase before
      grouping.
      e6f953fc
  21. 30 7月, 2019 1 次提交
    • R
      Preserve user supplied joins order as much as possible · b4478ae8
      Ryuta Kamizono 提交于
      Currently, string joins are always applied as last joins part, and Arel
      join nodes are always applied as leading joins part (since #36304), it
      makes people struggled to preserve user supplied joins order.
      
      To mitigate this problem, preserve the order of string joins and Arel
      join nodes either before or after of association joins.
      
      Fixes #36761.
      Fixes #34328.
      Fixes #24281.
      Fixes #12953.
      b4478ae8
  22. 19 7月, 2019 1 次提交
  23. 17 6月, 2019 1 次提交
    • R
      PostgreSQL: Fix GROUP BY with ORDER BY virtual count attribute · cb0299c9
      Ryuta Kamizono 提交于
      GROUP BY with virtual count attribute is invalid for almost all
      databases, but it is valid for PostgreSQL, and it had worked until Rails
      5.2.2, so it is a regression for Rails 5.2.3 (caused by 311f0011).
      
      I can't find perfectly solution for fixing this for now, but I would not
      like to break existing apps, so I decided to allow referencing virtual
      count attribute in ORDER BY clause when GROUP BY aggrigation (it partly
      revert the effect of 311f0011) to fix the regression #36022.
      
      Fixes #36022.
      cb0299c9
  24. 09 6月, 2019 1 次提交
  25. 06 6月, 2019 1 次提交
    • R
      Allow quoted identifier string as safe SQL string · 7696f44f
      Ryuta Kamizono 提交于
      Currently `posts.title` is regarded as a safe SQL string, but
      `"posts"."title"` (it is a result of `quote_table_name("posts.title")`)
      is regarded as an unsafe SQL string even though a result of
      `quote_table_name` should obviously be regarded as a safe SQL string,
      since the column name matcher doesn't respect quotation, it is a little
      annoying.
      
      This changes the column name matcher to allow quoted identifiers as safe
      SQL string, now all results of the `quote_table_name` are regarded as
      safe SQL string.
      7696f44f
  26. 05 6月, 2019 1 次提交
  27. 19 5月, 2019 1 次提交
    • R
      Implicit through table joins should be appeared before user supplied joins · 7412b7f8
      Ryuta Kamizono 提交于
      #36293 was an issue for through association with `joins` for a long
      time, but since #35864 through association with `left_joins` would also
      be affected by the issue.
      
      Implicit through table joins should be appeared before user supplied
      joins, otherwise loading through association with joins will cause a
      statement invalid error.
      
      Fixes #36293.
      
      ```
      % ARCONN=postgresql bundle exec ruby -w -Itest test/cases/associations/has_many_through_associations_test
      .rb -n test_through_association_with_joins
      Using postgresql
      Run options: -n test_through_association_with_joins --seed 7116
      
      # Running:
      
      E
      
      Error:
      HasManyThroughAssociationsTest#test_through_association_with_joins:
      ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  missing FROM-clause entry for table "posts"
      LINE 1: ... "comments_posts" ON "comments_posts"."post_id" = "posts"."i...
                                                                   ^
      : SELECT "comments".* FROM "comments" INNER JOIN "comments" "comments_posts" ON "comments_posts"."post_id" = "posts"."id" INNER JOIN "posts" ON "comments"."post_id" = "posts"."id" WHERE "posts"."author_id" = $1
      
      rails test test/cases/associations/has_many_through_associations_test.rb:61
      
      Finished in 0.388657s, 2.5730 runs/s, 0.0000 assertions/s.
      1 runs, 0 assertions, 0 failures, 1 errors, 0 skips
      ```
      7412b7f8
  28. 27 4月, 2019 1 次提交
    • R
      Fix merging left_joins to maintain its own `join_type` context · 20ede2e2
      Ryuta Kamizono 提交于
      This fixes a regression for #35864.
      
      Usually, stashed joins (mainly eager loading) are performed as LEFT
      JOINs.
      But the case of merging joins/left_joins of different class, that
      (stashed) joins are performed as the same `join_type` as the parent
      context for now.
      Since #35864, both (joins/left_joins) stashed joins might be contained
      in `joins_values`, so each stashed joins should maintain its own
      `join_type` context.
      
      Fixes #36103.
      20ede2e2
  29. 24 4月, 2019 1 次提交
    • R
      Avoid redundant `attribute_alias?` before `attribute_alias` · 5575bd7b
      Ryuta Kamizono 提交于
      If we want to get alias resolved attribute finally, we can use
      `attribute_alias` directly.
      
      For that purpose, avoiding redundant `attribute_alias?` makes alias
      attribute access 40% faster.
      
      https://gist.github.com/kamipo/e427f080a27b46f50bc508fae3612a0e
      
      Before (2c0729d8):
      
      ```
      Warming up --------------------------------------
                user['id']   102.668k i/100ms
            user['new_id']    80.660k i/100ms
              user['name']    99.368k i/100ms
          user['new_name']    81.626k i/100ms
      Calculating -------------------------------------
                user['id']      1.431M (± 4.0%) i/s -      7.187M in   5.031985s
            user['new_id']      1.042M (± 4.2%) i/s -      5.243M in   5.039858s
              user['name']      1.406M (± 5.6%) i/s -      7.055M in   5.036743s
          user['new_name']      1.074M (± 3.6%) i/s -      5.387M in   5.024152s
      ```
      
      After (this change):
      
      ```
      Warming up --------------------------------------
                user['id']   109.775k i/100ms
            user['new_id']   103.303k i/100ms
              user['name']   105.988k i/100ms
          user['new_name']    99.618k i/100ms
      Calculating -------------------------------------
                user['id']      1.520M (± 6.7%) i/s -      7.574M in   5.011496s
            user['new_id']      1.485M (± 6.2%) i/s -      7.438M in   5.036252s
              user['name']      1.538M (± 5.4%) i/s -      7.737M in   5.049765s
          user['new_name']      1.516M (± 4.6%) i/s -      7.571M in   5.007293s
      ```
      5575bd7b
  30. 22 4月, 2019 1 次提交
    • R
      Remove useless `set_value` / `get_value` helper methods · 89b86640
      Ryuta Kamizono 提交于
      Those helper methods makes relation values access 15% slower.
      
      https://gist.github.com/kamipo/e64439f7a206e1c5b5c69d92d982828e
      
      Before (02b5b8cb):
      
      ```
      Warming up --------------------------------------
              #limit_value   237.074k i/100ms
          #limit_value = 1   222.052k i/100ms
      Calculating -------------------------------------
              #limit_value      6.477M (± 2.9%) i/s -     32.479M in   5.019475s
          #limit_value = 1      5.297M (± 4.3%) i/s -     26.424M in   4.999933s
      ```
      
      After (this change):
      
      ```
      Warming up --------------------------------------
              #limit_value   261.109k i/100ms
          #limit_value = 1   239.646k i/100ms
      Calculating -------------------------------------
              #limit_value      7.412M (± 1.6%) i/s -     37.077M in   5.003345s
          #limit_value = 1      6.134M (± 1.0%) i/s -     30.675M in   5.000908s
      ```
      89b86640
  31. 19 4月, 2019 1 次提交
    • R
      Deprecate `where.not` working as NOR and will be changed to NAND in Rails 6.1 · 12a9664f
      Ryuta Kamizono 提交于
      `where.not` with polymorphic association is partly fixed incidentally at
      213796fb (refer #33493, #26207, #17010, #16983, #14161), and I've added
      test case e9ba12f7 to avoid lose that fix accidentally in the future.
      
      In Rails 5.2, `where.not(polymorphic: object)` works as expected as
      NAND, but `where.not(polymorphic_type: object.class.polymorphic_name,
      polymorphic_id: object.id)` still unexpectedly works as NOR.
      
      To will make `where.not` working desiredly as NAND in Rails 6.1, this
      deprecates `where.not` working as NOR. If people want to continue NOR
      conditions, we'd encourage to them to `where.not` each conditions
      manually.
      
      ```ruby
      all = [treasures(:diamond), treasures(:sapphire), cars(:honda), treasures(:sapphire)]
      assert_equal all, PriceEstimate.all.map(&:estimate_of)
      ```
      
      In Rails 6.0:
      
      ```ruby
      sapphire = treasures(:sapphire)
      
      nor = all.reject { |e|
        e.estimate_of_type == sapphire.class.polymorphic_name
      }.reject { |e|
        e.estimate_of_id == sapphire.id
      }
      assert_equal [cars(:honda)], nor
      
      without_sapphire = PriceEstimate.where.not(
        estimate_of_type: sapphire.class.polymorphic_name, estimate_of_id: sapphire.id
      )
      assert_equal nor, without_sapphire.map(&:estimate_of)
      ```
      
      In Rails 6.1:
      
      ```ruby
      sapphire = treasures(:sapphire)
      
      nand = all - [sapphire]
      assert_equal [treasures(:diamond), cars(:honda)], nand
      
      without_sapphire = PriceEstimate.where.not(
        estimate_of_type: sapphire.class.polymorphic_name, estimate_of_id: sapphire.id
      )
      assert_equal nand, without_sapphire.map(&:estimate_of)
      ```
      
      Resolves #31209.
      12a9664f
  32. 09 4月, 2019 1 次提交
  33. 05 4月, 2019 1 次提交
    • R
      Stash `left_joins` into `joins` to deduplicate redundant LEFT JOIN · 8f05035b
      Ryuta Kamizono 提交于
      Originally the `JoinDependency` has the deduplication for eager loading
      (LEFT JOIN). This re-uses that deduplication for `left_joins`.
      
      And also, This makes left join order into part of joins, i.e.:
      
      Before:
      
      ```
      association joins -> stash joins (eager loading, etc) -> string joins -> left joins
      ```
      
      After:
      
      ```
      association joins -> stash joins (eager loading, left joins, etc) -> string joins
      ```
      
      Now string joins are able to refer left joins.
      
      Fixes #34325.
      Fixes #34332.
      Fixes #34536.
      8f05035b
  34. 04 4月, 2019 1 次提交
  35. 30 3月, 2019 1 次提交
  36. 24 3月, 2019 1 次提交
  37. 22 3月, 2019 1 次提交
    • M
      Add Relation#annotate for SQL commenting · f4182580
      Matt Yoho 提交于
      This patch has two main portions:
      
      1. Add SQL comment support to Arel via Arel::Nodes::Comment.
      2. Implement a Relation#annotate method on top of that.
      
      == Adding SQL comment support
      
      Adds a new Arel::Nodes::Comment node that represents an optional SQL
      comment and teachers the relevant visitors how to handle it.
      
      Comment nodes may be added to the basic CRUD statement nodes and set
      through any of the four (Select|Insert|Update|Delete)Manager objects.
      
      For example:
      
          manager = Arel::UpdateManager.new
          manager.table table
          manager.comment("annotation")
          manager.to_sql # UPDATE "users" /* annotation */
      
      This new node type will be used by ActiveRecord::Relation to enable
      query annotation via SQL comments.
      
      == Implementing the Relation#annotate method
      
      Implements `ActiveRecord::Relation#annotate`, which accepts a comment
      string that will be appeneded to any queries generated by the relation.
      
      Some examples:
      
          relation = Post.where(id: 123).annotate("metadata string")
          relation.first
          # SELECT "posts".* FROM "posts" WHERE "posts"."id" = 123
          # LIMIT 1 /* metadata string */
      
          class Tag < ActiveRecord::Base
            scope :foo_annotated, -> { annotate("foo") }
          end
          Tag.foo_annotated.annotate("bar").first
          # SELECT "tags".* FROM "tags" LIMIT 1 /* foo */ /* bar */
      
      Also wires up the plumbing so this works with `#update_all` and
      `#delete_all` as well.
      
      This feature is useful for instrumentation and general analysis of
      queries generated at runtime.
      f4182580