| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
| |
Follow up of #32605.
|
|
|
|
| |
Since Rails 6 requires Ruby 2.4.1+.
|
|
|
|
|
|
|
| |
Prevent `ActiveRecord::FinderMethods#limited_ids_for` from using correct primary
key values even if `ORDER BY` columns include other table's primary key.
Fixes #28364.
|
|
|
|
|
|
|
|
|
| |
BC dates are supported by both date and datetime types.
https://www.postgresql.org/docs/current/static/datatype-datetime.html
Since #1097, new datetime allows year zero as 1 BC, but new date does
not. It should be allowed even in new date consistently.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The values infinity and -infinity are supported by both date and
timestamp types.
https://www.postgresql.org/docs/current/static/datatype-datetime.html#DATATYPE-DATETIME-SPECIAL-TABLE
And also, it can not be known whether a value is infinity correctly
unless cast a value.
I've added `QueryAttribute#infinity?` to handle that case.
Closes #27585.
|
|
|
|
| |
Closes #31998
|
| |
|
| |
|
| |
|
| |
|
|\
| |
| | |
Build a multi-statement query when inserting fixtures
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
- The `insert_fixtures` method can be optimized by making a single multi statement query for all fixtures having the same connection instead of doing a single query per table
- The previous code was bulk inserting fixtures for a single table, making X query for X fixture files
- This patch builds a single **multi statement query** for every tables. Given a set of 3 fixtures (authors, dogs, computers):
```ruby
# before
%w(authors dogs computers).each do |table|
sql = build_sql(table)
connection.query(sql)
end
# after
sql = build_sql(authors, dogs, computers)
connection.query(sql)
```
- `insert_fixtures` is now deprecated, `insert_fixtures_set` is the new way to go with performance improvement
- My tests were done with an app having more than 700 fixtures, the time it takes to insert all of them was around 15s. Using a single multi statement query, it took on average of 8 seconds
- In order for a multi statement to be executed, mysql needs to be connected with the `MULTI_STATEMENTS` [flag](https://dev.mysql.com/doc/refman/5.7/en/c-api-multiple-queries.html), which is done before inserting the fixtures by reconnecting to da the database with the flag declared. Reconnecting to the database creates some caveats:
1. We loose all open transactions; Inside the original code, when inserting fixtures, a transaction is open. Multple delete statements are [executed](https://github.com/rails/rails/blob/a681eaf22955734c142609961a6d71746cfa0583/activerecord/lib/active_record/fixtures.rb#L566) and finally the fixtures are inserted. The problem with this patch is that we need to open the transaction only after we reconnect to the DB otherwise reconnecting drops the open transaction which doesn't commit all delete statements and inserting fixtures doesn't work since we duplicated them (Primary key duplicate exception)...
- In order to fix this problem, the transaction is now open directly inside the `insert_fixtures` method, right after we reconnect to the db
- As an effect, since the transaction is open inside the `insert_fixtures` method, the DELETE statements need to be executed here since the transaction is open later
2. The same problem happens for the `disable_referential_integrity` since we reconnect, the `FOREIGN_KEY_CHECKS` is reset to the original value
- Same solution as 1. , the disable_referential_integrity can be called after we reconnect to the transaction
3. When the multi statement query is executed, no other queries can be performed until we paginate over the set of results, otherwise mysql throws a "Commands out of sync" [Ref](https://dev.mysql.com/doc/refman/5.7/en/commands-out-of-sync.html)
- Iterating over the set of results until `mysql_client.next_result` is false. [Ref](https://github.com/brianmario/mysql2#multiple-result-sets)
- Removed the `active_record.sql "Fixture delete"` notification, the delete statements are now inside the INSERT's one
- On mysql the `max_allowed_packet` is looked up:
1. Before executing the multi-statements query, we check the packet length of each statements, if the packet is bigger than the max_allowed_packet config, an `ActiveRecordError` is raised
2. Otherwise we concatenate the current sql statement into the previous and so on until the packet is `< max_allowed_packet`
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| | |
An empty string is an invalid value in Ruby's range class.
So need to handle `Float::INFINITY` as it is and cast it in
`encode_range`.
Fixes #31612
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
`BigDecimal.new` has been deprecated in BigDecimal 1.3.3
which will be a default for Ruby 2.5.
Refer https://github.com/ruby/bigdecimal/commit/533737338db915b00dc7168c3602e4b462b23503
```
$ cd rails/activerecord/
$ git grep -l BigDecimal.new | grep \.rb | xargs sed -i -e "s/BigDecimal.new/BigDecimal/g"
```
- Changes made only to Active Record. Will apply the same change to
other module once this commit is merged.
- The following deprecation has not been addressed because it has been
reported at `ActiveRecord::Result.new`. `ActiveRecord::Result.ancestors`
did not show `BigDecimal`.
* Not addressed
```ruby
/path/to/rails/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb:34:
warning: BigDecimal.new is deprecated
```
* database_statements.rb:34
```ruby
ActiveRecord::Result.new(result.fields, result.to_a) if result
```
* ActiveRecord::Result.ancestors
```ruby
[ActiveRecord::Result,
Enumerable,
ActiveSupport::ToJsonWithActiveSupportEncoder,
Object,
Metaclass::ObjectMethods,
Mocha::ObjectMethods,
PP::ObjectMixin,
ActiveSupport::Dependencies::Loadable,
ActiveSupport::Tryable,
JSON::Ext::Generator::GeneratorMethods::Object,
Kernel,
BasicObject]
```
This commit has been tested with these Ruby and BigDecimal versions
- ruby 2.5 and bigdecimal 1.3.3
```
$ ruby -v
ruby 2.5.0dev (2017-12-14 trunk 61217) [x86_64-linux]
$ gem list |grep bigdecimal
bigdecimal (default: 1.3.3, default: 1.3.2)
```
- ruby 2.4 and bigdecimal 1.3.0
```
$ ruby -v
ruby 2.4.2p198 (2017-09-14 revision 59899) [x86_64-linux-gnu]
$ gem list |grep bigdecimal
bigdecimal (default: 1.3.0)
```
- ruby 2.3 and bigdecimal 1.2.8
```
$ ruby -v
ruby 2.3.5p376 (2017-09-14 revision 59905) [x86_64-linux]
$ gem list |grep -i bigdecimal
bigdecimal (1.2.8)
```
- ruby 2.2 and bigdecimal 1.2.6
```
$ ruby -v
ruby 2.2.8p477 (2017-09-14 revision 59906) [x86_64-linux]
$ gem list |grep bigdecimal
bigdecimal (1.2.6)
```
|
|/
|
|
|
|
|
|
|
|
|
|
|
| |
* Ruby 2.4 introduces `report_on_exception` to control if it reports exceptions in thread,
this default value has been `false` in Ruby 2.4.
Refer https://www.ruby-lang.org/en/news/2016/11/09/ruby-2-4-0-preview3-released/
* Ruby 2.5 changes `report_on_exception` default value to `true`
since this commit https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?revision=61183&view=revision
This pull request suppresses expected exceptions by setting `report_on_exception` = `false`
it also supports Ruby 2.3 which does not have`report_on_exception`.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add support for specifying non-default operator classes in PostgreSQL
indexes. An example CREATE INDEX query that becomes possible is:
CREATE INDEX users_name ON users USING gist (name gist_trgm_ops);
Previously it was possible to specify the `gist` index but not the
custom operator class. The `add_index` call for the above query is:
add_index :users, :name, using: :gist, opclasses: {name: :gist_trgm_ops}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
statement due to user request (#31235)
This changes `StatementTimeout` to `QueryCanceled` for PostgreSQL.
In MySQL, errno 1317 (`ER_QUERY_INTERRUPTED`) is only used when the
query is manually cancelled.
But in PostgreSQL, `QUERY_CANCELED` error code (57014) which is used
`StatementTimeout` is also used when the both case. And, we can not tell
which reason happened.
So I decided to introduce new error class `QueryCanceled` closer to the
error code name.
|
|
|
|
|
|
| |
Since #31129, new error class `StatementTimeout` has been added.
`TransactionTimeout` is caused by the timeout shorter than
`StatementTimeout`, but its name is too generic. I think that it should
be a name that understands the difference with `StatementTimeout`.
|
|\
| |
| | |
Do not use `Arel.star` when `ignored_columns`
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
timeout exceeded (#31129)
We are sometimes using The MAX_EXECUTION_TIME hint for MySQL depending
on the situation. It will prevent catastrophic performance down by wrong
performing queries.
The new error class `StatementTimeout` will make to be easier to handle
that case.
https://dev.mysql.com/doc/refman/5.7/en/optimizer-hints.html#optimizer-hints-execution-time
|
| |
| |
| |
| | |
Follow up of #30360.
|
|/ |
|
|
|
|
|
|
|
|
| |
since the minimum version of PostgreSQL currently Rails supports is 9.1,
there is no need to handle if `supports_extensions?`
Refer https://www.postgresql.org/docs/9.1/static/sql-createextension.html
"CREATE EXTENSION"
|
| |
|
|
|
|
|
|
|
|
| |
We already found the longer sequence name, but we could not consider
whether it was the sequence name created by serial type due to missed a
max identifier length limitation. I've addressed the sequence name
consideration to respect the max identifier length.
Fixes #28332.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
PostgreSQL 9.1+ introduced range types, and Rails added support for
using this datatype in ActiveRecord. However, the serialization of
`PostgreSQL::OID::Range` was incomplete, because it did not properly
quote the bounds that make up the range. A clear example of this is a
`tsrange`.
Normally, ActiveRecord quotes Date/Time objects to include the
milliseconds. However, the way `PostgreSQL::OID::Range` serialized its
bounds, the milliseconds were dropped. This meant that the value was
incomplete and not equal to the submitted value.
An example of normal timestamps vs. a `tsrange`. Note how the bounds
for the range do not include their milliseconds (they were present in
the ruby Range):
UPDATE "iterations" SET "updated_at" = $1, "range" = $2 WHERE
"iterations"."id" = $3
[["updated_at", "2017-09-23 17:07:01.304864"],
["range", "[2017-09-23 00:00:00 UTC,2017-09-23 23:59:59 UTC]"],
["id", 1234]]
`PostgreSQL::OID::Range` serialized the range by interpolating a
string for the range, which works for most cases, but does not work
for timestamps:
def serialize(value)
if value.is_a?(::Range)
from = type_cast_single_for_database(value.begin)
to = type_cast_single_for_database(value.end)
"[#{from},#{to}#{value.exclude_end? ? ')' : ']'}"
else
super
end
end
(byebug) from = type_cast_single_for_database(value.begin)
2010-01-01 13:30:00 UTC
(byebug) to = type_cast_single_for_database(value.end)
2011-02-02 19:30:00 UTC
(byebug) "[#{from},#{to}#{value.exclude_end? ? ')' : ']'}"
"[2010-01-01 13:30:00 UTC,2011-02-02 19:30:00 UTC)"
@sgrif (the original implementer for Postgres Range support) provided
some feedback about where the quoting should occur:
Yeah, quoting at all is definitely wrong here. I'm not sure what I
was thinking in 02579b5, but what this is doing is definitely in the
wrong place. It should probably just be returning a range of
subtype.serialize(value.begin) and subtype.serialize(value.end), and
letting the adapter handle the rest.
`Postgres::OID::Range` now returns a `Range` object, and
`ActiveRecord::ConnectionAdapters::PostgreSQL::Quoting` can now encode
and quote a `Range`:
def encode_range(range)
"[#{type_cast(range.first)},#{type_cast(range.last)}#{range.exclude_end? ? ')' : ']'}"
end
...
encode_range(range)
#=> "['2010-01-01 13:30:00.670277','2011-02-02 19:30:00.745125')"
This commit includes tests to make sure the milliseconds are
preserved in `tsrange` and `tstzrange` columns
|
|
|
|
|
|
| |
If collided named sequence already exists, newly created serial column
will generate alternative sequence name. Fix sequence name detection to
allow the alternative names.
|
| |
|
|
|
|
| |
Fixes #30539.
|
|
|
|
|
|
|
|
| |
`SET time zone 'value'` is an alias for `SET timezone TO 'value'`.
https://www.postgresql.org/docs/current/static/sql-set.html
So if `variables["timezone"]` is specified, it is enough to
`SET timezone` once.
|
|
|
|
|
|
|
| |
We already have a test case for `serialize` with a custom coder in
`PostgresqlHstoreTest`.
https://github.com/rails/rails/blob/v5.1.3/activerecord/test/cases/adapters/postgresql/hstore_test.rb#L316-L335
|
|
|
|
| |
Because `JSONSharedTestCases` is also used for `Mysql2JSONTest`.
|
|\
| |
| | |
Do not let use `serialize` on native JSON/array column
|
| | |
|
|\| |
|
| |\
| | |
| | | |
Make `type_map` to private because it is only used in the connection adapter
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
`type_map` is an internal API and it is only used in the connection
adapter. And also, some type map initializer methods requires passed
`type_map`, but those instances already has `type_map` in itself.
So we don't need explicit passing `type_map` to the initializers.
|
| |\ \
| | | |
| | | | |
Use frozen-string-literal in ActiveRecord
|
| | |/ |
|
| |/
| |
| |
| |
| |
| |
| |
| | |
This reverts commit b6ad4052d18e4b29b8a092526c2beef013e2bf4f.
This is not something that the majority of Active Record should be
testing or care about. We should look at having fewer places rely on
these details, not make it easier to rely on them.
|
| |\
| | |
| | | |
Make preload query to preparable
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Currently preload query cannot be prepared statements even if
`prepared_statements: true` due to array handler in predicate builder
doesn't support making bind params. This makes preload query to
preparable by don't passing array value if possible.
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
Abstract boolean serialization has been using 't' and 'f', with MySQL
overriding that to use 1 and 0.
This has the advantage that SQLite natively recognizes 1 and 0 as true
and false, but does not natively recognize 't' and 'f'.
This change in serialization requires a migration of stored boolean data
for SQLite databases, so it's implemented behind a configuration flag
whose default false value is deprecated. The flag itself can be
deprecated in a future version of Rails. While loaded models will give
the correct result for boolean columns without migrating old data,
where() clauses will interact incorrectly with old data.
While working in this area, also change the abstract adapter to use
`"TRUE"` and `"FALSE"` as quoted values and `true` and `false` for
unquoted. These are supported by PostreSQL, and MySQL remains
overriden.
|
|\| | |
|
| |/
| |
| |
| |
| |
| |
| |
| | |
The uuid validation regex was allowing uuids to have a single leading
curly brace or single trailing curly brace. Saving with such a uuid
would cause Postgres to generate an exception even though the record
seemed valid. With this change, the regex requires both a leading *and*
a trailing curly brace or neither to be valid.
|
| |
| |
| |
| |
| | |
This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing
changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
|
| |\
| | |
| | |
| | | |
Enforce frozen string in Rubocop
|