Prior 7.1 Rails always included `primary_key` in `RETURNING` clause on
record creation. This was changed in 7.1 to include more auto-populated
columns if such columns exist. This change lead to situations where
no columns were requested in `RETURNING` clause, even the `primary_key`.
This change brings back the old behavior of always requesting the
`primary_key` in `RETURNING` clause if no other columns are requested.
MySQL 5.7.5+ supports generated columns, which can be used to create a column that is computed from an expression. This commit fixes the escaping of the default value for such expressions if a single quote is included.
See the following for more: https://dev.mysql.com/blog-archive/generated-columns-in-mysql-5-7-5/
Fix#46363.
Currently calling `reload` re-calculates the association cache based
on the object freshly loaded from the database. The fresh object gets
assigned as `owner` for each association in the association cache.
That object however is not the same as `self` (even though they
both point to the same record). Under some specific circumstances
(using `has_one/has_many through` associations and transactions with
`after_commit` callbacks) this might lead to losing the effects of
assignments done inside the callback.
This commit fixes it by making `reload` point to `self` as `owner`
for each association in the association cache.
The docs already talk about how to set up deferrable constraints, but
then rely on the user crafting custom SQL to actually use the feature.
The helper makes it easier to handle juggling multiple specific
constraints and quoting issues.
Fixes#49502.
This bug was introduced in https://github.com/rails/rails/pull/48241. Since `IDENTITY` columns
in PostgreSQL do not have defaults, they are not auto populated via the changes made in that PR.
Thus we need to consider them separately.
As we (I and @yahonda) talked about the naming in person, naming unique
constraints as unique keys is very confusing to me.
All documents and descriptions says it's unique constraints, but naming
unique keys leads to misunderstanding it's a short-hand of unique
indexes.
Just naming it unique constraints is not misleading.
Implementing the full `supports_insert_returning?` contract means the SQLite3 adapter supports auto-populated columns (#48241) as well as custom primary keys.
This reverts commit 213e8ff95e, reversing
changes made to b5d63b9b16.
It broke a lot of test.
It also changed how lazy loading of model code works.
With this change a simple `belongs_to :owner` is now loading `owner.rb`
when that line is executed, where before it wasn't doing that.
This can have serious impact on boot time in development.
We should make this as lazy as possible.
While working on implementing query constraints in our vitess gem, I
noticed that we were applying query constraints even when we didn't have
them on both sides of the association. We only want to infer query
constraints if both the `klass` and `active_record` have them set.
* If both the `klass` and `active_record` on the association don't have
query constraints set, use the `foreign_key` and don't infer query
constraints.
* Adds an error if the `active_record` and `klass` query constraints
don't match.
* Calling `klass` in `derive_fk_query_constraints` revealed that a bunch
of our tests are missing requires, without these we'll see test failures
that an association can't compute the klass name. Adding the requires
fixes those.
Fix when multiple `belongs_to` maps to the same counter_cache column.
In such situation `inverse_which_updates_counter_cache` may find the
wrong relation which leads into an invalid increment of the
counter_cache.
This is done by releying on the `inverse_of` property of the relation
as well as comparing the models the association points two.
Note however that this second check doesn't work for polymorphic
associations.
Fixes#41250
Co-Authored-By: Jean Boussier <jean.boussier@gmail.com>
Composite primary key records need to conditionally unset multiple
column attributes from the associated record in order to properly
support dependent: nullify.
This commit extends Active Record creation logic to allow for a database
auto-populated attributes to be assigned on object creation.
Given a `Post` model represented by the following schema:
```ruby
create_table :posts, id: false do |t|
t.integer :sequential_number, auto_increment: true
t.string :title, primary_key: true
t.string :ruby_on_rails, default: -> { "concat('R', 'o', 'R')" }
end
```
where `title` is being used as a primary key, the table has an
integer `sequential_number` column populated by a sequence and
`ruby_on_rails` column has a default function - creation of
`Post` records should populate the `sequential_number` and
`ruby_on_rails` attributes:
```ruby
new_post = Post.create(title: 'My first post')
new_post.sequential_number # => 1
new_post.ruby_on_rails # => 'RoR'
```
* At this moment MySQL and SQLite adapters are limited to only one
column being populated and the column must be the `auto_increment`
while PostgreSQL adapter supports any number of auto-populated
columns through `RETURNING` statement.
We had a mysql2_specific_schema.rb file but not one for trilogy that was
causing tests to break. I also removed the prepared statements from
trilogy because it is not supported.
This reverts commit 2815cb9620, reversing
changes made to 11a5e37715.
The change broke application code and if we are going to make this
change we will need to deprecate the prior behavior. See #47864 for more
details.
The [Trilogy database client][trilogy-client] and corresponding
[Active Record adapter][ar-adapter] were both open sourced by GitHub last year.
Shopify has recently taken the plunge and successfully adopted Trilogy in their Rails monolith.
With two major Rails applications running Trilogy successfully, we'd like to propose upstreaming the adapter
to Rails as a MySQL-compatible alternative to Mysql2Adapter.
[trilogy-client]: https://github.com/github/trilogy
[ar-adapter]: https://github.com/github/activerecord-trilogy-adapter
Co-authored-by: Aaron Patterson <tenderlove@github.com>
Co-authored-by: Adam Roben <adam@roben.org>
Co-authored-by: Ali Ibrahim <aibrahim2k2@gmail.com>
Co-authored-by: Aman Gupta <aman@tmm1.net>
Co-authored-by: Arthur Nogueira Neves <github@arthurnn.com>
Co-authored-by: Arthur Schreiber <arthurschreiber@github.com>
Co-authored-by: Ashe Connor <kivikakk@github.com>
Co-authored-by: Brandon Keepers <brandon@opensoul.org>
Co-authored-by: Brian Lopez <seniorlopez@gmail.com>
Co-authored-by: Brooke Kuhlmann <brooke@testdouble.com>
Co-authored-by: Bryana Knight <bryanaknight@github.com>
Co-authored-by: Carl Brasic <brasic@github.com>
Co-authored-by: Chris Bloom <chrisbloom7@github.com>
Co-authored-by: Cliff Pruitt <cliff.pruitt@cliffpruitt.com>
Co-authored-by: Daniel Colson <composerinteralia@github.com>
Co-authored-by: David Calavera <david.calavera@gmail.com>
Co-authored-by: David Celis <davidcelis@github.com>
Co-authored-by: David Ratajczak <david@mockra.com>
Co-authored-by: Dirkjan Bussink <d.bussink@gmail.com>
Co-authored-by: Eileen Uchitelle <eileencodes@gmail.com>
Co-authored-by: Enrique Gonzalez <enriikke@gmail.com>
Co-authored-by: Garrett Bjerkhoel <garrett@github.com>
Co-authored-by: Georgi Knox <georgicodes@github.com>
Co-authored-by: HParker <HParker@github.com>
Co-authored-by: Hailey Somerville <hailey@hailey.lol>
Co-authored-by: James Dennes <jdennes@gmail.com>
Co-authored-by: Jane Sternbach <janester@github.com>
Co-authored-by: Jess Bees <toomanybees@github.com>
Co-authored-by: Jesse Toth <jesse.toth@github.com>
Co-authored-by: Joel Hawksley <joelhawksley@github.com>
Co-authored-by: John Barnette <jbarnette@github.com>
Co-authored-by: John Crepezzi <john.crepezzi@gmail.com>
Co-authored-by: John Hawthorn <john@hawthorn.email>
Co-authored-by: John Nunemaker <nunemaker@gmail.com>
Co-authored-by: Jonathan Hoyt <hoyt@github.com>
Co-authored-by: Katrina Owen <kytrinyx@github.com>
Co-authored-by: Keeran Raj Hawoldar <keeran@gmail.com>
Co-authored-by: Kevin Solorio <soloriok@gmail.com>
Co-authored-by: Leo Correa <lcorr005@gmail.com>
Co-authored-by: Lizz Hale <lizzhale@github.com>
Co-authored-by: Lorin Thwaits <lorint@gmail.com>
Co-authored-by: Matt Jones <al2o3cr@gmail.com>
Co-authored-by: Matthew Draper <matthewd@github.com>
Co-authored-by: Max Veytsman <mveytsman@github.com>
Co-authored-by: Nathan Witmer <nathan@zerowidth.com>
Co-authored-by: Nick Holden <nick.r.holden@gmail.com>
Co-authored-by: Paarth Madan <paarth.madan@shopify.com>
Co-authored-by: Patrick Reynolds <patrick.reynolds@github.com>
Co-authored-by: Rob Sanheim <rsanheim@gmail.com>
Co-authored-by: Rocio Delgado <rocio@github.com>
Co-authored-by: Sam Lambert <sam.lambert@github.com>
Co-authored-by: Shay Frendt <shay@github.com>
Co-authored-by: Shlomi Noach <shlomi-noach@github.com>
Co-authored-by: Sophie Haskins <sophaskins@github.com>
Co-authored-by: Thomas Maurer <tma@github.com>
Co-authored-by: Tim Pease <tim.pease@gmail.com>
Co-authored-by: Yossef Mendelssohn <ymendel@pobox.com>
Co-authored-by: Zack Koppert <zkoppert@github.com>
Co-authored-by: Zhongying Qiao <cryptoque@users.noreply.github.com>
Most of the support here is in implementing how to correctly substitute
multiple values in place of one, for composite caes. In composite cases,
it's not sufficient to hash a label into a single integer value.
Instead, we build an API that accepts a single label, and a list of
columns that we'd like to map to. The algorithm used internally is very
similar to #identify, with an additional bit shift and modulo to cycle
the hash and ensure it doesn't exceed a max.
This fixes `ids_writer` so that it can handle a composite primary key.
Using a CPK model associated with a non-CPK model was working correctly
(which I added a test for). Using a CPK model associated with another
CPK model was not working correctly. It now takes it into account to
write the correct ids.
While working on `ids_reader` I found that `pluck` is not working for
CPK because it's passing an array of attributes and that's not supported
by `disallow_raw_sql!`. I chose to call `flatten` in `pluck` but not
conditionally because this seems like it could be a problem elsewhere as
well. This fixes pluck by CPK overall and fixes a test in the
calculations test file.
Given a model associated with a composite primary key by `id` attribute,
for example:
```ruby
Order.primary_key = [:shop_id, :id]
OrderAgreement.primary_key = :id
Order.has_many :order_agreements, primary_key: :id
```
Accessing the association should perform queries using
the `id` attribute value and not the `id` as Order's composite primary key.
```ruby
order = Order.last # => #<Order id: 1, shop_id: 2>
order.order_agreements.to_a
```
By default, exclude constraints in PostgreSQL are checked after each statement.
This works for most use cases, but becomes a major limitation when replacing
records with overlapping ranges by using multiple statements.
```ruby
exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :immediate
```
Passing `deferrable: :immediate` checks constraint after each statement,
but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED`
within a transaction. This will cause the excludes to be checked after the transaction.
It's also possible to change the default behavior from an immediate check
(after the statement), to a deferred check (after the transaction):
```ruby
exclusion_constraint :users, "daterange(valid_from, valid_to) WITH &&", deferrable: :deferred
```
*Hiroyuki Ishii*
Given a model with a composite primary key:
```ruby
class Order < ActiveRecord::Base
self.primary_key = [:shop_id, :id]
end
```
`ActiveRecord::Base#id` method will return an array of values for every
column of the primary key.
```ruby
order = Order.create!(shop_id: 1, id: 2)
order.id # => [1, 2]
```
The `id` column is accessible through the `read_attribute` method:
```ruby
order.read_attribute(:id) # => 2
```
```ruby
add_unique_key :sections, [:position], deferrable: :deferred, name: "unique_section_position"
remove_unique_key :sections, name: "unique_section_position"
```
See PostgreSQL's [Unique Constraints](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-UNIQUE-CONSTRAINTS) documentation for more on unique constraints.
By default, unique constraints in PostgreSQL are checked after each statement.
This works for most use cases, but becomes a major limitation when replacing
records with unique column by using multiple statements.
An example of swapping unique columns between records.
```ruby
old_item = Item.create!(position: 1)
new_item = Item.create!(position: 2)
Item.transaction do
old_item.update!(position: 2)
new_item.update!(position: 1)
end
```
Using the default behavior, the transaction would fail when executing the
first `UPDATE` statement.
By passing the `:deferrable` option to the `add_unique_key` statement in
migrations, it's possible to defer this check.
```ruby
add_unique_key :items, [:position], deferrable: :immediate
```
Passing `deferrable: :immediate` does not change the behaviour of the previous example,
but allows manually deferring the check using `SET CONSTRAINTS ALL DEFERRED` within a transaction.
This will cause the unique constraints to be checked after the transaction.
It's also possible to adjust the default behavior from an immediate
check (after the statement), to a deferred check (after the transaction):
```ruby
add_unique_key :items, [:position], deferrable: :deferred
```
PostgreSQL allows users to create a unique constraints on top of the unique
index that cannot be deferred. In this case, even if users creates deferrable
unique constraint, the existing unique index does not allow users to violate uniqueness
within the transaction. If you want to change existing unique index to deferrable,
you need execute `remove_index` before creating deferrable unique constraints.
*Hiroyuki Ishii*