Commit Graph

132 Commits

Author SHA1 Message Date
Edouard CHIN
db0469bf6f Fix AR::Relation#where_values_hash with HomogeousIn:
- Calling `Blog.where(title: ['foo', 'bar']).where_values_hash` now
  returns an empty hash.
  This is a regression since 72fd0bae59 .

  `Arel::Node::HomogeousIn` isn't a `EqualityNode`, the `WhereClause`
  didn't had a case for this.

  I decide to not make `HomogeousIn` inherit from `EqualityNode`,
  because there is a comment questioning it for `In` 57d926a78a/activerecord/lib/arel/nodes.rb (L31)
  Intead I just modified the `WhereClause` case and implemented
  `right` on the node which is needed by `where_value_hash` 57d926a78a/activerecord/lib/active_record/relation/where_clause.rb (L59)
2020-05-15 01:39:19 +02:00
Carlos Antonio da Silva
8fdbc2ae22 Use assert_queries since we are only checking for the count 2019-09-30 22:38:00 -03:00
John Hawthorn
a8b16c8a5b Avoid making query when using where(attr: []) 2019-09-30 16:37:07 -07:00
Kir Shatrov
77931f4f52 [ActiveRecord] Deduplicate optimizer hints 2019-07-19 11:52:39 +01:00
Ryuta Kamizono
c81af6ae72 Enable Layout/EmptyLinesAroundAccessModifier cop
We sometimes say "✂️ newline after `private`" in a code review (e.g.
https://github.com/rails/rails/pull/18546#discussion_r23188776,
https://github.com/rails/rails/pull/34832#discussion_r244847195).

Now `Layout/EmptyLinesAroundAccessModifier` cop have new enforced style
`EnforcedStyle: only_before` (https://github.com/rubocop-hq/rubocop/pull/7059).

That cop and enforced style will reduce the our code review cost.
2019-06-13 12:00:45 +09:00
Ryuta Kamizono
2ab3751781 Remove duplicated attribute alias resolution in _select!
This is also resolved in `arel_column`.
2019-04-09 23:11:11 +09:00
Ryuta Kamizono
0856f7c744 There is no need to check null_relation? in empty_scope?
`values[:extending]` includes `NullRelation` if `null_relation?`.
2019-04-06 12:00:17 +09:00
Matt Yoho
f41825809c Add Relation#annotate for SQL commenting
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.
2019-03-21 20:30:56 -07:00
Aidan Haran
50684d15c6 Escape table name so that it can be used in regular expression 2018-10-04 11:56:00 +01:00
bogdanvlviv
09ec075f1e
Remove Rubocop's comments from Rails code base
PR#32381 added Rubocop's comments to some tests files in order to
exclude `Performance/RedundantMerge`.

Turn off `Performance` cops for tests files via `Exclude`
in `.rubocop.yml`.

Context https://github.com/rails/rails/pull/32381#discussion_r205212331
2018-07-26 23:37:31 +03:00
Dillon Welch
d108288c2f
Turn on performance based cops
Use attr_reader/attr_writer instead of methods

method is 12% slower

Use flat_map over map.flatten(1)

flatten is 66% slower

Use hash[]= instead of hash.merge! with single arguments

merge! is 166% slower

See https://github.com/rails/rails/pull/32337 for more conversation
2018-07-23 15:37:06 -07:00
Chalo Fernandez
fd689d9fb1 Child joins should be aliased when merging relations
Rails 5.2 does not alias child joins, causing an error about duplicated table/fields:

Example:

Using some code like:
`Post.joins(:author, :categorizations).merge(Author.select(:id)).merge(Categorization.joins(:author))`

*Before this fix:*
`
SELECT ... FROM "posts" INNER JOIN "authors" ON ... INNER JOIN "authors" ON ...
`

*After this fix:*
`
SELECT ... FROM "posts" INNER JOIN "authors" ON ... INNER JOIN "authors" "authors_categorizations" ON ...
`

Before 5.2, Rails aliased the joins, but wrongfully transformed them into a LEFT OUTER JOIN.
This fix will keep them as INNER JOINS, but make sure child joins are aliased, to avoid errors.
2018-06-06 02:43:46 -05:00
Ryuta Kamizono
1dc17e7b2e Fix CustomCops/AssertNot to allow it to have failure message
Follow up of #32605.
2018-05-13 11:32:47 +09:00
Lachlan Sylvester
115bbdac2b don't check for immutability when setting skip_preloading as it doesn't effect the arel and the arel may already be generated by fresh_when 2018-04-12 10:17:31 +10:00
Daniel Colson
94333a4c31 Use assert_predicate and assert_not_predicate 2018-01-25 23:32:59 -05:00
Daniel Colson
0d50cae996 Use respond_to test helpers 2018-01-25 23:32:58 -05:00
Daniel Colson
6928950def Avoid passing unnecessary arguments to relation
Most of the time the table and predicate_builder
passed to Relation.new are exactly the
arel_table and predicate builder of the
given klass. This uses klass.arel_table
and klass.predicate_builder as the defaults,
so we don't have to pass them in most cases.

This does change the signaure of both Relation and
AssocationRelation. Are we ok with that?
2018-01-24 16:49:35 -05:00
Ryuta Kamizono
7eaae937e6 Partial revert the changing default value of readonly_value
This is a partial revert of #26182. There is no reason to change the
default value.
2018-01-05 00:53:47 +09:00
Ryuta Kamizono
6a8ce7416d Fix scope_for_create to do not lose polymorphic associations
This regression was caused at 213796fb due to polymorphic predicates are
combined by `Arel::Nodes::And`. But I'd like to keep that combined
because it would help inverting polymorphic predicates correctly
(e9ba12f7), and we can collect equality nodes regardless of combined by
`Arel::Nodes::And` (`a AND (b AND c) AND d` == `a AND b AND c AND d`).
This change fixes the regression to collect equality nodes in
`Arel::Nodes::And` as well.

Fixes #31338.
2017-12-08 03:42:04 +09:00
Sean Griffin
68fe6b08ee Properly cast input in update_all
The documentation claims that given values go through "normal AR type
casting and serialization", which to me implies
`serialize(cast(value))`, not just serialization. The docs were changed
to use this wording in #22492. The tests I cited in that PR (which is
the same test modified in this commit), is worded in a way that implies
it should be using `cast` as well.

It's possible that I originally meant "normal type casting" to imply
just the call to `serialize`, but given that `update_all(archived:
params['archived'])` seems to be pretty common, I'm inclined to make
this change as long as no tests are broken from it.
2017-11-13 13:31:46 -07:00
Ryuta Kamizono
4528dd6327 Relation merging should keep joining order
`joins_values.partition` will break joins values order. It should be
kept as user intended order.

Fixes #15488.
2017-11-11 04:02:09 +09:00
Ryuta Kamizono
f27a45af46 Remove unused explicit delegation to klass in relation
It is only used `primary_key` and `connection` in the internal, so it is
not needed to delegate others to `klass` explicitly.
This doesn't change public behavior because `relation` will delegate
missing method to `klass`.
2017-09-14 10:45:28 +09:00
Ryuta Kamizono
45955aed00 Relation::Merger should not fill values with empty values
Currently `Relation#merge` will almost fill `values` with empty values
(e.g. `other.order_values` is always true, it should be
`other.order_values.any?`). This means that `Relation#merge` always
changes `values` even if actually `values` is nothing changed. This
behavior will makes `Relation#empty_scope?` fragile. So `Relation#merge`
should avoid unnecessary changes.
2017-07-25 03:11:56 +09:00
Sean Griffin
213796fb49 Refactor Active Record to let Arel manage bind params
A common source of bugs and code bloat within Active Record has been the
need for us to maintain the list of bind values separately from the AST
they're associated with. This makes any sort of AST manipulation
incredibly difficult, as any time we want to potentially insert or
remove an AST node, we need to traverse the entire tree to find where
the associated bind parameters are.

With this change, the bind parameters now live on the AST directly.
Active Record does not need to know or care about them until the final
AST traversal for SQL construction. Rather than returning just the SQL,
the Arel collector will now return both the SQL and the bind parameters.
At this point the connection adapter will have all the values that it
had before.

A bit of this code is janky and something I'd like to refactor later. In
particular, I don't like how we're handling associations in the
predicate builder, the special casing of `StatementCache::Substitute` in
`QueryAttribute`, or generally how we're handling bind value replacement
in the statement cache when prepared statements are disabled.

This also mostly reverts #26378, as it moved all the code into a
location that I wanted to delete.

/cc @metaskills @yahonda, this change will affect the adapters

Fixes #29766.
Fixes #29804.
Fixes #26541.
Close #28539.
Close #24769.
Close #26468.
Close #26202.

There are probably other issues/PRs that can be closed because of this
commit, but that's all I could find on the first few pages.
2017-07-24 09:07:24 -04:00
Kir Shatrov
831be98f9a Use frozen-string-literal in ActiveRecord 2017-07-19 22:27:07 +03:00
Ryuta Kamizono
d476553d1c Don't cache scope_for_create
I investigated where `scope_for_create` is reused in tests with the
following code:

```diff
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -590,6 +590,10 @@ def where_values_hash(relation_table_name = table_name)
     end

     def scope_for_create
+      if defined?(@scope_for_create) && @scope_for_create
+        puts caller
+        puts "defined"
+      end
       @scope_for_create ||= where_values_hash.merge!(create_with_value.stringify_keys)
     end
```

It was hit only `test_scope_for_create_is_cached`. This means that
`scope_for_create` will not be reused in normal use cases. So we can
remove caching `scope_for_create` to respect changing `where_clause` and
`create_with_value`.
2017-07-16 21:31:08 +09:00
Ryuta Kamizono
01c85097d4 Fix create_with using both string and symbol
This is related with #27680.

Since `where_values_hash` keys constructed by `where` are string, so we
need `stringify_keys` to `create_with_value` before merging it.
2017-07-16 15:38:49 +09:00
Ryuta Kamizono
189b8a06dc Use where(id: 10) rather than where(relation.table[:id].eq(10))
Because Arel is a private API and to describe `where_values_hash` keys
constructed by `where` are string.
2017-07-16 15:23:57 +09:00
Ryuta Kamizono
23300f4440 Extract FakeKlass in relation_test.rb and relation/mutation_test.rb
`FakeKlass` in `relation_test.rb` and `relation/mutation_test.rb` are
almost the same.
2017-07-11 07:43:05 +09:00
Matthew Draper
87b3e226d6 Revert "Merge pull request #29540 from kirs/rubocop-frozen-string"
This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing
changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
2017-07-02 02:15:17 +09:30
Kir Shatrov
cfade1ec7e Enforce frozen string in Rubocop 2017-07-01 02:11:03 +03:00
yuuji.yaginuma
5fac725a4a Remove unused variable
This fixes the following warnings:

```
activerecord/test/cases/relation_test.rb:231: warning: assigned but unused variable - authors_with_commented_posts
```
2017-06-22 09:13:02 +09:00
Maxime Lapointe
249ddd0c39 Keep INNER JOIN when merging relations
Doing `Author.joins(:posts).merge(Post.joins(:comments))` does this
`SELECT ... INNER JOIN posts ON... LEFT OUTER JOIN comments ON...`
instead of doing
`SELECT ... INNER JOIN posts ON... INNER JOIN comments ON...`.

This behavior is unexpected and makes little sense as, basically, doing
`Post.joins(:comments)` means I want posts that have comments. Turning
it to a LEFT JOIN means I want posts and join the comments data, if
any.

We can see this problem directly in the existing tests.
The test_relation_merging_with_merged_joins_as_symbols only does joins
from posts to comments to ratings while the ratings fixture isn't
loaded, but the count is non-zero.
2017-06-20 20:47:22 -04:00
Ryuta Kamizono
86e74a083a Restore fixtures :author_addresses
This change reverted in eac6f369 but it is needed for data integrity.
See #25328.
2017-04-27 15:44:25 +09:00
Rafael Mendonça França
eac6f3690f
Revert "Merge pull request #27636 from mtsmfm/disable-referential-integrity-without-superuser-privilege-take-2"
This reverts commit c1faca6333abe4b938b98fedc8d1f47b88209ecf, reversing
changes made to 8c658a0ecc7f2b5fc015d424baf9edf6f3eb2b0b.

See https://github.com/rails/rails/pull/27636#issuecomment-297534129
2017-04-26 13:39:05 -07:00
Fumiaki MATSUSHIMA
2a129380e8 Use SET CONSTRAINTS for disable_referential_integrity without superuser privileges (take 2)
Re-create https://github.com/rails/rails/pull/21233

eeac6151a5 was reverted (127509c071b4) because it breaks tests.

----------------

ref: 72c1557254

- We must use `authors` fixture with `author_addresses` because of its foreign key constraint.
- Tests require PostgreSQL >= 9.4.2 because it had a bug about `ALTER CONSTRAINTS` and fixed in 9.4.2.
2017-03-26 17:12:13 +09:00
Akira Matsuda
9360b6be63 class Foo < Struct.new(:x) creates an extra unneeded anonymous class
because Struct.new returns a Class, we just can give it a name and use it directly without inheriting from it
2017-01-13 15:13:47 +09:00
Rafael Mendonça França
127509c071
Revert "Merge pull request #21233 from mtsmfm/disable-referential-integrity-without-superuser-privileges"
This reverts commit eeac6151a55cb7d5f799e1ae33aa64a839cbc3aa, reversing
changes made to 5c40239d3104543e70508360d27584a3e4dc5baf.

Reason: Broke the isolated tests.
https://travis-ci.org/rails/rails/builds/188721346
2017-01-03 22:11:16 -05:00
Fumiaki MATSUSHIMA
e75fcdf3fe Use SET CONSTRAINTS for disable_referential_integrity without superuser privileges
ref: 72c1557254

- We must use `authors` fixture with `author_addresses` because of its foreign key constraint.
- Tests require PostgreSQL >= 9.4.2 because it had a bug about `ALTER CONSTRAINTS` and fixed in 9.4.2.
2016-12-03 15:53:22 +09:00
Rafael Mendonça França
fe1f4b2ad5
Add more rubocop rules about whitespaces 2016-10-29 01:17:49 -02:00
Ryuta Kamizono
7c70430ce0 Fix broken heredoc indentation caused by rubocop auto-correct
All indentation was normalized by rubocop auto-correct at 80e66cc4d90bf8c15d1a5f6e3152e90147f00772.
But heredocs was still kept absolute position. This commit aligns
heredocs indentation for consistency.
2016-09-03 13:28:46 +09:00
Rafael França
8c83a449f5 Merge pull request #26182 from bogdan/remove-relation-metaprogramming
Remove over meta programming in AR::Relation
2016-08-23 23:29:20 -03:00
Bogdan Gusiev
5b42628e79 Remove over meta programming in AR::Relation
Introduced low level methods #set_value and #get_value for setting query attributes:

  relation.set_value(:where, {id: 1})
  relation.get_value(:includes)

Used those internally when working with relation's attributes
at the abstract level
2016-08-23 13:11:06 +03:00
Maxime Lapointe
0aae7806c1 Fix count which would sometimes force a DISTINCT
The current behaviour of checking if there is a LEFT OUTER JOIN arel
node to detect if we are doing eager_loading is wrong. This problem
wasn't frequent before as only some pretty specific cases would add
a LEFT OUTER JOIN arel node. However, the recent new feature
left_outer_joins also add this node and made this problem happen
frequently.

Since in the perform_calculation function, we don't have access to
eager_loading information, I had to extract the logic for the distinct
out to the calculate method.

As I was in the file for left_outer_join tests, I fixed a few that had
bugs and I replaced some that were really weak with something that
will catch more issues.

In relation tests, the first test I changed would have failed if it
had validated the hash returned by count instead of just checking how
many pairs were in it. This is because this merge of join currently
transforms the join node into an outer join node, which then made
count do a distinct. So before this change, the return was
{1=>1, 4=>1, 5=>1}.
2016-08-16 09:45:23 -04:00
Rafael Mendonça França
55f9b8129a
Add three new rubocop rules
Style/SpaceBeforeBlockBraces
Style/SpaceInsideBlockBraces
Style/SpaceInsideHashLiteralBraces

Fix all violations in the repository.
2016-08-16 04:30:11 -03:00
Xavier Noria
80e66cc4d9 normalizes indentation and whitespace across the project 2016-08-06 20:16:27 +02:00
Xavier Noria
d22e522179 modernizes hash syntax in activerecord 2016-08-06 19:37:57 +02:00
Xavier Noria
9617db2078 applies new string literal convention in activerecord/test
The current code base is not uniform. After some discussion,
we have chosen to go with double quotes by default.
2016-08-06 18:26:53 +02:00
Tamir Duberstein
0aa5150f9f activerecord: reuse immutable objects 2016-01-04 12:09:37 -05:00
Ryuta Kamizono
48e2faaa11 Remove FIXME comments about the Arel::Nodes::Quoted [ci skip]
The `Arel::Nodes::Quoted` was removed already.
Follow up to f916aa247bddba0c58c50822886bc29e8556df76.
2016-01-03 00:57:23 +09:00