Commit Graph

17379 Commits

Author SHA1 Message Date
Daniel Colson
211adb47e7 Change refute to assert_not 2018-01-25 23:32:58 -05:00
Daniel Colson
0d50cae996 Use respond_to test helpers 2018-01-25 23:32:58 -05:00
Ryuta Kamizono
8baca31dbe
Bring back ability to insert zero value on primary key for fixtures (#31795)
Since #29504, mysql2 adapter lost ability to insert zero value on
primary key due to enforce `NO_AUTO_VALUE_ON_ZERO` disabled.
That is for using `DEFAULT` on auto increment column, but we can use
`NULL` instead in that case.
2018-01-26 12:42:28 +09:00
Eugene Kenny
92b0c49cb9 Update note on MySQL index order support [ci skip]
MySQL supports descending indexes from 8.0.1 onwards:
https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-1.html
2018-01-26 00:33:01 +00:00
Ryuta Kamizono
8c42d1b6e5 Add test case for deprecated insert_fixtures
Since #31422, `insert_fixtures` is deprecated.
2018-01-26 05:50:05 +09:00
Ryuta Kamizono
a4df58a828 Remove unused test/fixtures/teapots.yml
It was unused since 9e4c41c903e8e58721f2c41776a8c60ddba7a0a9.
2018-01-25 18:22:04 +09:00
Ryuta Kamizono
057ba1280b Remove internal typecasted_attribute_value method
It is useless since 90c8be76a7d00475be5ff4db2eeedde5cc936c2d.
2018-01-25 14:42:11 +09:00
Ryuta Kamizono
ebc09ed9ad Fix count(:all) with eager loading and having an order other than the driving table
This is a regression caused by 6beb4de.

In PostgreSQL, ORDER BY expressions must appear in SELECT list when
using DISTINCT.

When using `count(:all)` with eager loading, Active Record enforces
DISTINCT to count the driving table records only. 6beb4de was caused the
regression because `count(:all)` with DISTINCT path no longer removes
ORDER BY.

We need to ignore ORDER BY when DISTINCT is enforced, otherwise not
always generated valid SQL for PostgreSQL.

Fixes #31783.
2018-01-25 14:12:58 +09:00
Ryuta Kamizono
8223408c8d Expand AR to Active Record [ci skip] 2018-01-25 12:52:19 +09:00
Yuriy Ustushenko
226116a440 Clear the transaction state when AR object is duped 2018-01-25 10:09:16 +07:00
Rafael França
e981adef44
Merge pull request #31784 from composerinteralia/relation-signature
Avoid passing unnecessary arguments to relation
2018-01-24 18:04:34 -05:00
Rafael Mendonça França
a5e6f44ef6 Skip test that use fork in the memory store db 2018-01-24 18:04:10 -05:00
Rafael França
554dcc4c6e
Merge pull request #31690 from olivierlacan/no-verbose-query-logs-in-console
Only enable verbose_query_logs in Rails server
2018-01-24 17:04:31 -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
Matthew Draper
1280ad6d19 Make discard safe when it follows a manual disconnect
It doesn't have to do anything, but it shouldn't fail.

Fixes #31766.
2018-01-25 01:01:51 +10:30
Matthew Draper
ee1fda121e
Merge pull request #31773 from dinahshi/postgresql_bulk_patch
Postgresql bulk_change_table should flatten procs array
2018-01-24 21:53:01 +10:30
Matthew Draper
bc26f30370
Merge pull request #31422 from Edouard-chin/multistatement-fixtures
Build a multi-statement query when inserting fixtures
2018-01-24 21:47:15 +10:30
Dinah Shi
1d8266fc68 Use concat to join procs arrays in bulk_change_table 2018-01-23 22:25:22 -05:00
Edouard CHIN
1d04baafa6 Allow a 2 bytes margin:
- mysql will add a 2 bytes margin to the statement, so given a `max_allowed_packet` set to 1024 bytes, a 1024 bytes fixtures will no be inserted (mysql will throw an error)
- Preventing this by decreasing the max_allowed_packet by 2 bytes when doing the comparison with the actual statement size
2018-01-23 14:21:58 -05:00
Olivier Lacan
1044e8b355 Disable verbose_query_logs in Rails Console
Should fix #31688 unless someone can point me to a better way to achieve
this goal. Essentially David's point was that verbose query logging when
enabled in Rails console tends to make things very noisy.

That's especially true if we display absolute paths to callsites which
sadly is still the case when we detect a caller that isn't part of the
Rails application — think gems.

Discussed this with both @matthewd and @rafaelfranca and went back and
forth between enabling if defined?(Rails::Server) or this implementation
and this one makes more sense for now.

Long term I think it'll make sense to let people override this default
disabling in Rails Console because they might want to use the feature
but for now it feels like the correct default behavior.
2018-01-23 16:21:13 +01:00
Ryuta Kamizono
742c9ba92a
Merge pull request #31549 from fatkodima/foreign_tables
Support for PostgreSQL foreign tables
2018-01-23 05:44:16 +09:00
Ryuta Kamizono
7ca3ab415d Fix building has_one through record
Fixes #31762.
2018-01-23 05:23:32 +09:00
fatkodima
3ad2f9921a Support for PostgreSQL foreign tables 2018-01-22 21:41:38 +02:00
Edouard CHIN
9a5b1fad63 Combine delete and insert statements in the same query 2018-01-22 13:03:16 -05:00
Edouard CHIN
22a26d249f 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](a681eaf229/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`
2018-01-22 13:02:56 -05:00
Leonel Galan
3562331669 Ignores a default subclass when becomes(Parent)
Fixes issue described in #30399: A default value on the
inheritance column prevented `child.becomes(Parent)` to return
an instance of `Parent` as expected, instead it returns an instance
of the default subclass.

The change was introduced by #17169 and it was meant to affect
initialization, alone. Where `Parent.new` is expected to return
an instance of the default subclass.
2018-01-22 10:04:47 -05:00
Matthew Draper
7bb0b397ea
Merge pull request #24964 from vipulnsward/true-false
Don't perform unnecessary check with false, just use true/false values
2018-01-23 00:47:11 +10:30
Ryuta Kamizono
109505843f
Merge pull request #31710 from eugeneius/indestructible_through_record
Don't update counter cache when through record was not destroyed
2018-01-22 16:12:24 +09:00
Ryuta Kamizono
a19e91f0fa
PERF: Recover changes_applied performance (#31698)
#30985 caused `object.save` performance regression since calling
`changes` in `changes_applied` is very slow.
We don't need to call the expensive method in `changes_applied` as long
as `@attributes` is tracked by mutation tracker.

https://gist.github.com/kamipo/1a9f4f3891803b914fc72ede98268aa2

Before:

```
Warming up --------------------------------------
create_string_columns
                        73.000  i/100ms
Calculating -------------------------------------
create_string_columns
                        722.256  (± 5.8%) i/s -      3.650k in   5.073031s
```

After:

```
Warming up --------------------------------------
create_string_columns
                        96.000  i/100ms
Calculating -------------------------------------
create_string_columns
                        950.224  (± 7.7%) i/s -      4.800k in   5.084837s
```
2018-01-22 10:46:36 +09:00
Matthew Draper
acbcef6094
Merge pull request #31732 from koic/enable_autocorrect_for_lint_end_alignment_cop
Enable autocorrect for `Lint/EndAlignment` cop
2018-01-19 17:49:21 +10:30
Ryuta Kamizono
6559577d1d Remove unused connection argument from MigrationContext#current_version 2018-01-19 15:06:05 +09:00
Ryuta Kamizono
fa17fcc32f Remove unused migration_context in DatabaseTasks
This was added in #31727, but it is unused.
2018-01-19 14:56:04 +09:00
Ryuta Kamizono
f5c4b7cf13 Restore test_migrations_status_with_schema_define_in_subdirectories
This test case which was added in #28287 checks that
`ActiveRecord::Schema.define` loads migration versions in
subdirectories. It should be kept it as it was.
2018-01-19 11:51:07 +09:00
Rafael França
fd04c8cbb6
Merge pull request #31663 from Edouard-chin/remove-without-sql-mode
Added a test around `NO_AUTO_VALUE_ON_ZERO`:
2018-01-18 15:24:30 -05:00
oz
4d4db4c861 Use selected_migrations if block_given?
This slipped in as part of a2827ec9811b5012e8e366011fd44c8eb53fc714.
2018-01-18 13:04:57 -05:00
eileencodes
a2827ec981 Refactor migration to move migrations paths to connection
Rails has some support for multiple databases but it can be hard to
handle migrations with those. The easiest way to implement multiple
databases is to contain migrations into their own folder ("db/migrate"
for the primary db and "db/seconddb_migrate" for the second db). Without
this you would need to write code that allowed you to switch connections
in migrations. I can tell you from experience that is not a fun way to
implement multiple databases.

This refactoring is a pre-requisite for implementing other features
related to parallel testing and improved handling for multiple
databases.

The refactoring here moves the class methods from the `Migrator` class
into it's own new class `MigrationContext`. The goal was to move the
`migrations_paths` method off of the `Migrator` class and onto the
connection. This allows users to do the following in their
`database.yml`:

```
development:
  adapter: mysql2
  username: root
  password:

development_seconddb:
  adapter: mysql2
  username: root
  password:
  migrations_paths: "db/second_db_migrate"
```

Migrations for the `seconddb` can now be store in the
`db/second_db_migrate` directory. Migrations for the primary database
are stored in `db/migrate`".

The refactoring here drastically reduces the internal API for migrations
since we don't need to pass `migrations_paths` around to every single
method. Additionally this change does not require any Rails applications
to make changes unless they want to use the new public API. All of the
class methods from the `Migrator` class were `nodoc`'d except for the
`migrations_paths` and `migrations_path` getter/setters respectively.
2018-01-18 08:55:03 -05:00
Koichi ITO
5ac6ec54a6 Enable autocorrect for Lint/EndAlignment cop
### Summary

This PR changes .rubocop.yml.

Regarding the code using `if ... else ... end`, I think the coding style
that Rails expects is as follows.

```ruby
var = if cond
  a
else
  b
end
```

However, the current .rubocop.yml setting does not offense for the
following code.

```ruby
var = if cond
        a
      else
        b
      end
```

I think that the above code expects offense to be warned.
Moreover, the layout by autocorrect is unnatural.

```ruby
var = if cond
  a
      else
        b
      end
```

This PR adds a setting to .rubocop.yml to make an offense warning and
autocorrect as expected by the coding style.
And this change also fixes `case ... when ... end` together.

Also this PR itself is an example that arranges the layout using
`rubocop -a`.

### Other Information

Autocorrect of `Lint/EndAlignment` cop is `false` by default.
https://github.com/bbatsov/rubocop/blob/v0.51.0/config/default.yml#L1443

This PR changes this value to `true`.

Also this PR has changed it together as it is necessary to enable
`Layout/ElseAlignment` cop to make this behavior.
2018-01-18 17:19:13 +09:00
Edouard CHIN
84206ad387 Added a test around NO_AUTO_VALUE_ON_ZERO:
- The mysql `NO_AUTO_VALUE_ON_ZERO` mode should be disabled when inserting fixtures in bulk, this PR adds a test to make sure we don't remove it by mistake
- If we live this mode enabled, a statement like this wouldn't work and a `Duplicate entry '0' for key 'PRIMARY'` error will be raised. That's because `DEFAULT` on auto_increment will return 0

```sql
INSERT INTO `aircraft` (`id`, `name`, `wheels_count`) VALUES (DEFAULT, 'first', 2), (DEFAULT, 'second', 3)
```
2018-01-17 15:03:22 -05:00
Mehmet Emin INAC
899a801413
Fix relation merger issue with left_outer_joins 2018-01-15 16:06:00 +01:00
Eugene Kenny
3e71bc4b04 Don't update counter cache when through record was not destroyed
When removing a record from a has many through association, the counter
cache was being updated even if the through record halted the callback
chain and prevented itself from being destroyed.
2018-01-14 20:46:19 +00:00
Ryuta Kamizono
562dd0494a Don't allow destroyed object mutation after save or save! is called
Currently `object.save` will unfreeze the object, due to
`changes_applied` replaces frozen `@attributes` to new `@attributes`.

Since originally destroyed objects are not allowed to be mutated, `save`
and `save!` should not return success in that case.

Fixes #28563.
2018-01-15 04:52:01 +09:00
Ryuta Kamizono
f1af27fd9d create_database should not add default charset when collation is given
If `collation` is given without `charset`, it may generate invalid SQL.
For example `create_database(:matt_aimonetti, collation: "utf8mb4_bin")`:

```
> CREATE DATABASE `matt_aimonetti` DEFAULT CHARACTER SET `utf8` COLLATE `utf8mb4_bin`;
ERROR 1253 (42000): COLLATION 'utf8mb4_bin' is not valid for CHARACTER SET 'utf8'
```

In MySQL, charset is used to find the default collation. If `collation`
is given explicitly, it is not necessary to give extra charset.
2018-01-15 03:42:11 +09:00
Ryuta Kamizono
282668cc81 Merge pull request #28313 from sandrew/master
Allow unscoping of left_outer_joins
2018-01-15 03:19:54 +09:00
Ryuta Kamizono
192e74fc60 Don't need to pass manager to convert_join_strings_to_ast
Because `Relation` already have Arel `table`.
2018-01-14 07:31:38 +09:00
Ryuta Kamizono
e9c16536d4 Don't pass garbage args to alias tracker
This is a complete fix to #30995.

Originally alias tracker will only track table aliases on
`Arel::Nodes::Join`, other args are ignored.

Since c5ab6e5, parent aliases hash will be passed then it caused the
regression #30995.

It is enough to pass list of `Arel::Nodes::Join` simply, not need to
pass garbage args which will be ignored.
2018-01-14 06:50:25 +09:00
Rafael Mendonça França
181836d894 Merge pull request #31671 from larskanis/pg-1.0
PostgreSQL: Allow pg-1.0 gem to be used with ActiveRecord
2018-01-11 14:31:37 -05:00
Ryuta Kamizono
ae48c65e41 Merge pull request #23146 from piotrj/issue_18424
When deleting through records, take into account association conditions
2018-01-11 07:31:05 +09:00
Ryuta Kamizono
f30f20ccec Remove the deprecated :conditions option in INVALID_AUTOMATIC_INVERSE_OPTIONS
This option was moved into active_record_deprecated_finders in ac4d101.
2018-01-11 05:59:59 +09:00
Lars Kanis
f820dc2dea PostgreSQL: Allow pg-1.0 gem to be used with ActiveRecord
pg-1.0.0 is just released and most Gemfiles don't restrict
it's version. But the version is checked when connecting to
the database, which leads to the following error:

Gem::LoadError: can't activate pg (~> 0.18), already activated pg-1.0.0

See also this pg issue:
https://bitbucket.org/ged/ruby-pg/issues/270/pg-100-x64-mingw32-rails-server-not-start

Preparation for pg-1.0 was done in commit f28a331023fab,
but the pg version constraint was not yet relaxed.
2018-01-10 21:55:43 +01:00
Ryuta Kamizono
412db710df Use apply_join_dependency instead of meaningless named find_with_associations
`find_with_associations` is meaningless name in this point since it just
contain `construct_join_dependency` and `apply_join_dependency`, does
not contain finding anything.
If `apply_join_dependency` returns `relation` and `join_dependency` then
`find_with_associations` is no longer needed.
2018-01-11 04:28:28 +09:00