| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
| |
Ruby 2.7 introduces beginless ranges (..value and ...value) and as with
endless ranges we can turn these into inequalities, enabling expressions
such as
Order.where(created_at: ..1.year.ago)
User.where(karma: ...0)
|
| |
|
|
|
|
| |
`Arel::Attributes.for` is no longer used since https://github.com/rails/arel/pull/196.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Each `visit o, collector` allocates one extra array due to
receiving args by splat array.
https://github.com/rails/rails/blob/2c3332cc4c0fa77dbe2e13e8a792f80fbd8f4ad3/activerecord/lib/arel/visitors/visitor.rb#L27-L29
Currently 1,000 times `User.where(id: 1).to_sql` allocates 13,000
arrays in `visitor.accept`. This avoids receiving args by splat array,
it makes `visitor.accept` no array allocation.
```ruby
ObjectSpace::AllocationTracer.setup(%i{path line type})
pp ObjectSpace::AllocationTracer.trace {
1_000.times { User.where(id: 1).to_sql }
}.select { |k, _| k[2] == :T_ARRAY && k[0].end_with?("visitor.rb", "to_sql.rb") }
```
Before (2c3332cc4c0fa77dbe2e13e8a792f80fbd8f4ad3):
```
{["~/rails/activerecord/lib/arel/visitors/to_sql.rb",
18,
:T_ARRAY]=>[1000, 0, 0, 0, 0, 0],
["~/rails/activerecord/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb",
11,
:T_ARRAY]=>[1000, 0, 0, 0, 0, 0],
["~/rails/activerecord/lib/arel/visitors/visitor.rb",
12,
:T_ARRAY]=>[1000, 0, 0, 0, 0, 0],
["~/rails/activerecord/lib/arel/visitors/to_sql.rb",
788,
:T_ARRAY]=>[3000, 0, 0, 0, 0, 0],
["~/rails/activerecord/lib/arel/visitors/to_sql.rb",
794,
:T_ARRAY]=>[3000, 0, 0, 0, 0, 0],
["~/rails/activerecord/lib/arel/visitors/to_sql.rb",
156,
:T_ARRAY]=>[1000, 0, 0, 0, 0, 0],
["~/rails/activerecord/lib/arel/visitors/to_sql.rb",
443,
:T_ARRAY]=>[1000, 0, 0, 0, 0, 0],
["~/rails/activerecord/lib/arel/visitors/to_sql.rb",
603,
:T_ARRAY]=>[1000, 0, 0, 0, 0, 0],
["~/rails/activerecord/lib/arel/visitors/to_sql.rb",
611,
:T_ARRAY]=>[1000, 0, 0, 0, 0, 0]}
```
After (this change):
```
{}
```
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
| |
Follow up of #35838.
And also this refactors `in_clause_length` handling is entirely
integrated in Arel visitor.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* To address this error, this commit splits expressions by slices of 1000 elements.
* "Oracle Database Error Messages 18c"
https://docs.oracle.com/en/database/oracle/oracle-database/18/errmg/
```
ORA-01795: maximum number of expressions in a list is 1000
Cause: Number of expressions in the query exceeded than 1000. Note that unused column/expressions are also counted Maximum number of expressions that are allowed are 1000.
```
* This commit addresses this ORA-01795 error
Note: Actually addressing this error raises another "ORA-00913: too many values"
Number of values Oracle database allows is 65535 regardless bind values or literal values.
```ruby
$ ARCONN=oracle bin/test test/cases/bind_parameter_test.rb -n test_too_many_binds
... snip ...
Error:
ActiveRecord::BindParameterTest#test_too_many_binds:
ActiveRecord::StatementInvalid: OCIError: ORA-01795: maximum number of expressions in a list is 1000
stmt.c:267:in oci8lib_260.so
/home/yahonda/.rbenv/versions/2.6.2/lib/ruby/gems/2.6.0/gems/ruby-oci8-2.2.7/lib/oci8/cursor.rb:131:in `exec'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb:142:in `exec'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:41:in `block in exec_query'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:676:in `block (2 levels) in log'
/home/yahonda/.rbenv/versions/2.6.2/lib/ruby/2.6.0/monitor.rb:230:in `mon_synchronize'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:675:in `block in log'
/home/yahonda/git/rails/activesupport/lib/active_support/notifications/instrumenter.rb:24:in `instrument'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:666:in `log'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced/dbms_output.rb:36:in `log'
/home/yahonda/git/oracle-enhanced/lib/active_record/connection_adapters/oracle_enhanced/database_statements.rb:24:in `exec_query'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:484:in `select'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:70:in `select_all'
/home/yahonda/git/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:106:in `select_all'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:299:in `block in execute_simple_calculation'
/home/yahonda/git/rails/activerecord/lib/active_record/relation.rb:755:in `skip_query_cache_if_necessary'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:299:in `execute_simple_calculation'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:251:in `perform_calculation'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:141:in `calculate'
/home/yahonda/git/rails/activerecord/lib/active_record/relation/calculations.rb:49:in `count'
/home/yahonda/git/rails/activerecord/test/cases/bind_parameter_test.rb:113:in `test_too_many_binds'
bin/test test/cases/bind_parameter_test.rb:109
.............................F
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`delete_all`
This partly reverts #35617.
#35617 includes unused code (for `InsertStatement`) and re-using query
annotation for `update_all` and `delete_all`, which has not been
discussed yet.
If a relation has any annotation, I think it is mostly for SELECT query,
so re-using annotation by default is not always desired behavior for me.
We should discuss about desired behavior before publishing the
implementation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|\
| |
| | |
Remove roflscaling
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
roflscaling (using frozen string constants instead of literal
strings) was added in 2012, before frozen string literals were
added in Ruby 2.3. Now that Rails no longer supports Ruby <2.3,
and all of these files use frozen string literals, there is
no reason to keep the roflscaling.
This does not delete or deprecate the related constants. Such
a change can be made in a later commit.
|
|/
|
|
| |
Probably that is useful for any other feature as well.
|
|\
| |
| | |
Get rid of `Arel::Nodes::Values`
|
| |
| |
| |
| |
| |
| | |
That is completely covered by `Arel::Nodes::ValuesList`.
Related https://github.com/rails/arel/pull/484.
|
|/ |
|
|
|
|
| |
https://buildkite.com/rails/rails/builds/59622#924dff9d-85c2-4946-b264-a7e6ce01432c/122-130
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
| |
The `Row` class is no longer used since d956772b3c61d97940ebcccd7c83e2397ca0c36c.
|
|
|
|
| |
Allows aliasing, predications, ordering, and various other functions on `And` and `Case` nodes. This brings them in line with other nodes like `Binary` and `Unary`.
|
|
|
|
| |
When `Arel` was merged into `ActiveRecord` we lost the ability to alias case nodes. This adds it back.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
```
|
|
|
|
| |
This class is no longer used since 9cbfc8a370bf6537a02a2f21e7246dc21ba4cf1f.
|
|
|
|
|
|
| |
And support endless ranges for `not_between` like as `between`.
Follow up #34906.
|
|
|
|
|
|
| |
This commit adds support for endless ranges, e.g. (1..), that were added
in Ruby 2.6. They're functionally equivalent to explicitly specifying
Float::INFINITY as the end of the range.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
* Enable `Lint/UselessAssignment` cop to avoid unused variable warnings
Since we've addressed the warning "assigned but unused variable"
frequently.
370537de05092aeea552146b42042833212a1acc
3040446cece8e7a6d9e29219e636e13f180a1e03
5ed618e192e9788094bd92c51255dda1c4fd0eae
76ebafe594fc23abc3764acc7a3758ca473799e5
And also, I've found the unused args in c1b14ad which raises no warnings
by the cop, it shows the value of the cop.
|
|
|
|
|
| |
This slightly change the code in the Arel to allow +/-INFINITY as open
ended since the Active Record expects that behavior. See 5ecbeda.
|
|
|
|
|
|
|
|
|
| |
* 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]
|
|\
| |
| |
| | |
Fix: Arel now emits a single pair of parens for UNION and UNION ALL
|
|/
|
|
|
|
|
|
| |
mysql has a great implementation to suppress multiple parens for union
sql statements.
This moves that functionality to the generic implementation
This also introduces that functionality for UNION ALL
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Before:
```
Pet Destroy (0.8ms) DELETE FROM `pets` WHERE `pets`.`pet_id` IN (SELECT `pet_id` FROM (SELECT DISTINCT `pets`.`pet_id` FROM `pets` LEFT OUTER JOIN `toys` ON `toys`.`pet_id` = `pets`.`pet_id` WHERE `toys`.`name` = ?) AS __active_record_temp) [["name", "Bone"]]
```
After:
```
Pet Destroy (1.0ms) DELETE `pets` FROM `pets` LEFT OUTER JOIN `toys` ON `toys`.`pet_id` = `pets`.`pet_id` WHERE `toys`.`name` = ? [["name", "Bone"]]
```
|
| |
|
| |
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
MySQL supports DELETE with LIMIT and ORDER BY.
https://dev.mysql.com/doc/refman/8.0/en/delete.html
Before:
```
Post Destroy (1.0ms) DELETE FROM `posts` WHERE `posts`.`id` IN (SELECT `id` FROM (SELECT `posts`.`id` FROM `posts` WHERE `posts`.`author_id` = ? ORDER BY `posts`.`id` ASC LIMIT ?) __active_record_temp) [["author_id", 1], ["LIMIT", 1]]
```
After:
```
Post Destroy (0.4ms) DELETE FROM `posts` WHERE `posts`.`author_id` = ? ORDER BY `posts`.`id` ASC LIMIT ? [["author_id", 1], ["LIMIT", 1]]
```
|
|
|
|
| |
53521a9e39b9d8af4165d7703c36dc905f1f8f67
|
| |
|
|
|
|
|
|
| |
No longer needed workaround for Ruby 2.2 "private attribute?" warning.
Related 6d63b5e49a399fe246afcebad45c3c962de268fa.
|
|
|
|
| |
Follow up ae406cd633dab2cafbc0d1bb5922d1ca40056ea0.
|
|
|
|
| |
This reverts commit a1b72178714fbf0033fe076b7e51f57eff152bdd.
|
|
|
|
| |
Since Ruby 2.4 unified Fixnum and Bignum into Integer.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Before:
```
Topic Update All (0.4ms) UPDATE `topics` SET `topics`.`replies_count` = COALESCE(`topics`.`replies_count`, 0) + 1, `topics`.`updated_at` = '2018-09-27 18:34:05.068774' WHERE `topics`.`id` = ? [["id", 7]]
```
After:
```
Topic Update All (0.4ms) UPDATE `topics` SET `topics`.`replies_count` = COALESCE(`topics`.`replies_count`, 0) + ?, `topics`.`updated_at` = ? WHERE `topics`.`id` = ? [["replies_count", 1], ["updated_at", 2018-09-27 18:55:05 UTC], ["id", 7]]
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Before:
```
Pet Update All (0.8ms) UPDATE `pets` LEFT OUTER JOIN `toys` ON `toys`.`pet_id` = `pets`.`pet_id` SET `pets`.`name` = 'Bob' WHERE `toys`.`name` = ? [["name", "Bone"]]
```
After:
```
Pet Update All (1.1ms) UPDATE `pets` LEFT OUTER JOIN `toys` ON `toys`.`pet_id` = `pets`.`pet_id` SET `pets`.`name` = ? WHERE `toys`.`name` = ? [["name", "Bob"], ["name", "Bone"]]
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Initially, `TOP` was introduced to support `limit` for MSSQL database.
Unlike PostgreSQL/MySQL/SQLite, MSSQL does not have native `LIMIT`/`OFFSET` support.
The commit adding `TOP` is 1a246f71616cf246a75ef6cbdb56032e43d4e643.
However, it figured out that `TOP` implementation was weak and it's not sufficient
to also support `OFFSET`, then `TOP` was substituted with
`ROW_NUMBER()` subquery in be48ed3071fd6524d0145c4ad3faeb4aafe3eda3.
This is a well known trick in MSSQL -
https://stackoverflow.com/questions/2135418/equivalent-of-limit-and-offset-for-sql-server.
So now we don't need this `visit_Arel_Nodes_Top` at all.
It does nothing useful but also adds an extra space after `SELECT` when `LIMIT` is being
used for **any** database.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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
```
|