aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/query_methods.rb
Commit message (Collapse)AuthorAgeFilesLines
* Refactor `disallow_raw_sql!` to avoid `split(/\s*,\s*/)` to order argsRyuta Kamizono2019-06-091-0/+1
| | | | | `split(/\s*,\s*/)` to order args and then `permit.match?` one by one is much slower than `permit.match?` once.
* Allow quoted identifier string as safe SQL stringRyuta Kamizono2019-06-061-1/+1
| | | | | | | | | | | | | 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.
* Implicit through table joins should be appeared before user supplied joinsRyuta Kamizono2019-05-191-17/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | #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 ```
* Fix merging left_joins to maintain its own `join_type` contextRyuta Kamizono2019-04-271-5/+5
| | | | | | | | | | | | | | | 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.
* Avoid redundant `attribute_alias?` before `attribute_alias`Ryuta Kamizono2019-04-241-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 ```
* Merge pull request #36029 from kamipo/deprecate_where_notRyuta Kamizono2019-04-231-4/+17
|\ | | | | Deprecate `where.not` working as NOR and will be changed to NAND in Rails 6.1
| * Deprecate `where.not` working as NOR and will be changed to NAND in Rails 6.1Ryuta Kamizono2019-04-191-4/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `where.not` with polymorphic association is partly fixed incidentally at 213796f (refer #33493, #26207, #17010, #16983, #14161), and I've added test case e9ba12f 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.
* | Remove useless `set_value` / `get_value` helper methodsRyuta Kamizono2019-04-221-15/+8
|/ | | | | | | | | | | | | | | | | | | | | | | | | | | | 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 ```
* Remove duplicated attribute alias resolution in `_select!`Ryuta Kamizono2019-04-091-6/+3
| | | | This is also resolved in `arel_column`.
* Stash `left_joins` into `joins` to deduplicate redundant LEFT JOINRyuta Kamizono2019-04-051-8/+23
| | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Optimizer hints should be applied on Top level query as much as possibleRyuta Kamizono2019-04-041-0/+9
| | | | | I've experienced this issue in our app, some hints only works on Top level query (e.g. `MAX_EXECUTION_TIME`).
* Merge pull request #35727 from zinosama/zzz/update-doc-for-includesRyuta Kamizono2019-04-011-1/+7
|\ | | | | | | | | | | Update API doc for #includes on unnecessary #references [ci skip]
| * [ci skip] Update doc for unnecessary #referenceszino2019-03-231-1/+7
| | | | | | | | Update doc for #includes to clarify that #references is unnecessary when conditions are passed into #includes as a hash.
* | Add `ActiveRecord::Relation#extract_associated` for extracting associated ↵David Heinemeier Hansson2019-03-291-0/+13
|/ | | | | record (#35784) * Add `ActiveRecord::Relation#extract_associated` for extracting associated records from a relation
* Add Relation#annotate for SQL commentingMatt Yoho2019-03-211-1/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Add test case for unscoping `:optimizer_hints`Ryuta Kamizono2019-03-181-1/+1
|
* Support Optimizer HintsRyuta Kamizono2019-03-161-0/+24
| | | | | | | | | | | | | | | | | | We as Arm Treasure Data are using Optimizer Hints with a monkey patch (https://gist.github.com/kamipo/4c8539f0ce4acf85075cf5a6b0d9712e), especially in order to use `MAX_EXECUTION_TIME` (refer #31129). Example: ```ruby class Job < ApplicationRecord default_scope { optimizer_hints("MAX_EXECUTION_TIME(50000) NO_INDEX_MERGE(jobs)") } end ``` Optimizer Hints is supported not only for MySQL but also for most databases (PostgreSQL on RDS, Oracle, SQL Server, etc), it is really helpful to turn heavy queries for large scale applications.
* Merge pull request #35503 from samjohn/cannot-grammar-correctionXavier Noria2019-03-071-1/+1
|\ | | | | Replace “can not” with “cannot”.
| * Replace “can not” with “cannot”.Samantha John2019-03-061-1/+1
| |
* | Fix incorrect identifier quoting [ci skip]Ryuta Kamizono2019-03-071-2/+2
|/
* Relax table name detection in `from` to allow any extension like INDEX hintRyuta Kamizono2019-03-011-2/+5
| | | | | | | | | | #35360 allows table name qualified if `from` has original table name. But that is still too strict. We have a valid use case that `from` with INDEX hint (e.g. `from("comments USE INDEX (PRIMARY)")`). So I've relaxed the table name detection in `from` to allow any extension like INDEX hint. Fixes #35359.
* Merge pull request #33611 from willianveiga/feature/reselect-methodAndrew White2019-03-011-0/+21
|\ | | | | Add reselect method
| * Avoid creating an extra relation instanceWillian Gustavo Veiga2018-10-241-2/+9
| |
| * Merge branch 'master' into feature/reselect-methodWillian Gustavo Veiga2018-10-221-10/+8
| |\
| * \ Merge branch 'master' into feature/reselect-methodWillian Gustavo Veiga2018-10-021-4/+4
| |\ \
| * | | Add reselect methodWillian Gustavo Veiga2018-08-131-0/+14
| | | |
* | | | Fix `pluck` and `select` with `from` if `from` has original table nameRyuta Kamizono2019-02-221-1/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This is caused by 0ee96d1. Since #18744, `select` columns doesn't be qualified by table name if using `from`. 0ee96d1 follows that for `pluck` as well. But people depends that `pluck` columns are qualified even if using `from`. So I've fixed that to be qualified if `from` has the original table name to keep the behavior as much as before. Fixes #35359.
* | | | Fix lint `ShadowingOuterLocalVariable`soartec-lab2019-02-211-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Revert "Fix lint `ShadowingOuterLocalVariable`" This reverts commit 38bd45a48992b500478a82d56d31468a322937a8. Change of variable name Fix lint `ShadowingOuterLocalVariable`
* | | | Merge pull request #35274 from AlexBrodianoi/fix_does_not_support_reverseRyuta Kamizono2019-02-171-1/+1
|\ \ \ \ | | | | | | | | | | Raise ActiveRecord::IrreversibleOrderError if nulls first/last is not a single ordering argument.
| * | | | Raise ActiveRecord::IrreversibleOrderError if nulls first/last is not a ↵Finn Young2019-02-171-1/+1
| | | | | | | | | | | | | | | | | | | | single ordering argument.
* | | | | Fix `order` with custom attributesRyuta Kamizono2019-02-171-2/+8
|/ / / / | | | | | | | | | | | | This follows up 0ee96d13de29680e148ccb8e5b68025f29fd091c.
* | | / Fix `pluck` and `select` with custom attributesRyuta Kamizono2019-02-131-5/+17
| |_|/ |/| | | | | | | | | | | | | | | | | | | | | | | Currently custom attributes are always qualified by the table name in the generated SQL wrongly even if the table doesn't have the named column, it would cause an invalid SQL error. Custom attributes should only be qualified if the table has the same named column.
* | | Don't expose internal `get_value`/`set_value` methodsRyuta Kamizono2018-10-181-10/+8
| |/ |/|
* | Add `Style/RedundantFreeze` to remove redudant `.freeze`Yasuo Honda2018-09-291-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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'
* | Permit list usage cleanup and clearer documentationKevin Deisz2018-08-271-2/+2
| |
* | Convert over the rest of the whitelist referencesKevin Deisz2018-08-241-2/+2
|/
* Use `construct_join_dependency` in all placesRyuta Kamizono2018-07-031-3/+1
|
* Ensure to calculate column aliases after all table aliases are constructedRyuta Kamizono2018-06-191-7/+9
| | | | | | | | | | | | | | | | | 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.
* `get_value` needs to be a public methodGraham Turner2018-04-251-4/+5
| | | | | | Adds test case for failing issue Moves set_value back to protected
* Fix relation merging with skip_query_cache!James Williams2018-04-191-2/+2
|
* Only preload misses on multifetch cacheLachlan Sylvester2018-03-061-0/+5
|
* Merge pull request #31133 from ↵Matthew Draper2018-02-111-0/+1
|\ | | | | | | | | mohsen-alizadeh/sanitize_empty_and_nil_parameters_passed_to_select sanitize empty and nil parameters to select #31059
| * sanitize empty and nil parameters to selectMohsen Alizadeh2017-11-121-0/+1
| |
* | Fix relation merger issue with `left_outer_joins`Mehmet Emin INAC2018-01-151-0/+2
| |
* | Merge pull request #28313 from sandrew/masterRyuta Kamizono2018-01-151-2/+3
|\ \ | | | | | | | | | Allow unscoping of left_outer_joins
| * | Allow unscoping of left_outer_joinsAndrei Shaidurov2017-03-061-1/+1
| | |
* | | Don't need to pass `manager` to `convert_join_strings_to_ast`Ryuta Kamizono2018-01-141-2/+2
| | | | | | | | | | | | Because `Relation` already have Arel `table`.
* | | Partial revert the changing default value of `readonly_value`Ryuta Kamizono2018-01-051-13/+2
| | | | | | | | | | | | | | | This is a partial revert of #26182. There is no reason to change the default value.
* | | Place args normalization from `left_outer_joins` to `left_outer_joins!`Ryuta Kamizono2017-12-201-4/+2
| | | | | | | | | | | | Like other query bang methods.
* | | Using table name qualified column names unless having SELECT list explicitlyRyuta Kamizono2017-12-181-2/+2
| | | | | | | | | | | | | | | | | | Previously table name qualified `*` is used in that case. If it is not qualified with a table name, an ambiguous column name error will occur when using JOINs.